diff mbox

[Darwin,c*,ObjC*,1/2] Implement Darwin CFStrings.

Message ID 6C7293F5-4069-43D4-9980-182F81914800@sandoe-acoustics.co.uk
State New
Headers show

Commit Message

Iain Sandoe Oct. 19, 2010, 8:48 a.m. UTC
Hi,
CFStrings are a c-family target-specific addition on Darwin (they  
might be useful to GNUstep, but we decided to delay that consideration  
for present).
They've been present in the system since the start of Darwin and using  
them has become a requirement if we are to parse system headers on  
Darwin10.

The changes need to be applied as one commit - hence one email.

however to make review easier I've split the patch into files that  
involve build system changes ...
... and the remainder which are under Mike's area (the bulk of the  
text).
Although this patch is based on examination of the apple local 'trunk'  
branch,  I had to make significant modifications (i.e. it is  
technically covered by the merging pre-approval,  but Mike might wish  
to cast a quick eye over it).

checked on {powerpc,i686}-darwin9, x86_64-darwin10, i686-darwin8,  
x86_64-unknown-linux, and a cross to cris-elf
(really mostly relevant to the test-suite changes in part 2).

OK for trunk?
Iain

===  Build system Changes

It turns out that, whilst we have the capability to add files  
selectively for cfamily per target, this does not extend to gt-files  
and therefore, to apply the patch I need approval for the following  
build mechanism change:

gcc:

	* config.gcc (target_cfamily_gtfiles): New var, target_cfamily_gtfiles
	add darwin-cfstrings.c.
	c_target_objs, cxx_target_objs add darwin-cfstrings.o.
	* c-config-lang.in (gtfiles): Add target_cfamily_gtfiles.

gcc/cp:

	* cp/config-lang.in (gtfiles): Add target_cfamily_gtfiles.

gcc/objc:

	* objc/config-lang.in (gtfiles): Add target_cfamily_gtfiles.

gcc/objcp:

	* objcp/config-lang.in (gtfiles): Add target_cfamily_gtfiles.

==== Darwin CFStrings.

gcc:

	Based on the CFStrings implementation in FSF apple/trunk branch.

	* config.gcc (target_cfamily_gtfiles):  c_target_objs,  
cxx_target_objs add
	darwin-cfstrings.o.

	* target.def (objc_construct_string): New Hook.
	* doc/tm.texi (objc_construct_string): Document.
	* doc/tm.texi.in (TARGET_OBJC_CONSTRUCT_STRING): New.
	* config/t-darwin: Build rules for darwin-cfstrings.o.
	* config/darwin.opt: Add cfstrings flags.
	* config/darwin-c.c: Define __CONSTANT_CFSTRINGS__.
	* config/i386/darwin.h (SUBTARGET_INIT_BUILTINS): Define.
	* config/i386/i386.c (ix86_init_builtins): Add SUBTARGET_INIT_BUILTINS.
	* config/darwin-protos.h (darwin_init_cfstring_builtins): New  
prototype.
	(darwin_fold_builtin): New prototype.
	(darwin_objc_construct_string): New prototype.
	(darwin_cfstring_p): New prototype.
	* config/darwin-cfstrings.c: New.
	* config/rs6000/darwin.h (SUBTARGET_INIT_BUILTINS) Update for CFString.
	* config/darwin.c (darwin_running_cxx): New var.
	(machopic_select_section): Return cfstring_constant_object_section.
	(darwin_override_options): Set darwin_running_cxx.
	(darwin_init_cfstring_builtins): New dummy routine.
	(darwin_fold_builtin): Likewise.
	* config/darwin-sections.def (cfstring_constant_object_section): New.
	* config/darwin.h (TARGET_FOLD_BUILTIN): Define.
	(TARGET_OBJC_CONSTRUCT_STRING): Define.

gcc/objc:

	* objc/objc-act.c (objc_build_string_object): Handle CFStrings.
Index: gcc/target.def
===================================================================
--- gcc/target.def	(revision 165662)
+++ gcc/target.def	(working copy)
@@ -2510,4 +2519,10 @@ DEFHOOK
  bool, (size_t code, const char *arg, int value),
  default_handle_c_option)
 
+DEFHOOK
+(objc_construct_string,
+ "Construct a constant string representation for @var{string}",
+ tree, (tree string),
+ NULL)
+
 HOOK_VECTOR_END (C90_EMPTY_HACK)
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 165662)
+++ gcc/doc/tm.texi	(working copy)
@@ -757,6 +757,10 @@ only available in the C (and related language) fro
 should use @code{TARGET_HANDLE_C_OPTION} instead.
 @end deftypefn
 
+@deftypefn {Target Hook} tree TARGET_OBJC_CONSTRUCT_STRING (tree @var{string})
+Construct a constant string representation for @var{string}
+@end deftypefn
+
 @defmac TARGET_VERSION
 This macro is a C statement to print on @code{stderr} a string
 describing the particular machine description choice.  Every machine
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	(revision 165662)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -757,6 +757,8 @@ only available in the C (and related language) fro
 should use @code{TARGET_HANDLE_C_OPTION} instead.
 @end deftypefn
 
+@hook TARGET_OBJC_CONSTRUCT_STRING
+
 @defmac TARGET_VERSION
 This macro is a C statement to print on @code{stderr} a string
 describing the particular machine description choice.  Every machine
Index: gcc/config/t-darwin
===================================================================
--- gcc/config/t-darwin	(revision 165662)
+++ gcc/config/t-darwin	(working copy)
@@ -31,6 +31,12 @@ darwin-c.o: $(srcdir)/config/darwin-c.c $(CONFIG_H
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 		$(srcdir)/config/darwin-c.c $(PREPROCESSOR_DEFINES)
 
+darwin-cfstrings.o: $(srcdir)/config/darwin-cfstrings.c $(CONFIG_H) $(SYSTEM_H) \
+  coretypes.h $(TM_H) $(TREE_H) $(C_COMMON_H) toplev.h $(TM_P_H)  langhooks.h \
+  c-tree.h c-lang.h gt-darwin-cfstrings.h
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/config/darwin-cfstrings.c $(PREPROCESSOR_DEFINES)
+
 darwin-f.o: $(srcdir)/config/darwin-f.c $(CONFIG_H) $(SYSTEM_H) coretypes.h
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 	  $(srcdir)/config/darwin-f.c $(PREPROCESSOR_DEFINES)
Index: gcc/config/darwin.opt
===================================================================
--- gcc/config/darwin.opt	(revision 165662)
+++ gcc/config/darwin.opt	(working copy)
@@ -18,6 +18,14 @@
 ; along with GCC; see the file COPYING3.  If not see
 ; <http://www.gnu.org/licenses/>.
 
+mconstant-cfstrings
+Target Report Var(darwin_constant_cfstrings) Init(1)
+Generate compile-time CFString objects
+
+Wnonportable-cfstrings
+Target Report Var(darwin_warn_nonportable_cfstrings) Init(1) Warning
+Warn if constant CFString objects contain non-portable characters
+
 mfix-and-continue
 Target Report Var(darwin_fix_and_continue)
 Generate code suitable for fast turn around debugging
Index: gcc/config/darwin-c.c
===================================================================
--- gcc/config/darwin-c.c	(revision 165662)
+++ gcc/config/darwin-c.c	(working copy)
@@ -608,6 +608,9 @@ darwin_cpp_builtins (cpp_reader *pfile)
      to be defined and won't work if it isn't.  */
   builtin_define_with_value ("__APPLE_CC__", "1", false);
 
+  if (darwin_constant_cfstrings)
+    builtin_define ("__CONSTANT_CFSTRINGS__");
+
   builtin_define_with_value ("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__",
 			     version_as_macro(), false);
 
Index: gcc/config/i386/darwin.h
===================================================================
--- gcc/config/i386/darwin.h	(revision 165662)
+++ gcc/config/i386/darwin.h	(working copy)
@@ -314,3 +314,10 @@ extern int darwin_emit_branch_islands;
 #define MACHO_SYMBOL_FLAG_VARIABLE ((SYMBOL_FLAG_MACH_DEP) << 3)
 
 #define SUBTARGET32_DEFAULT_CPU "i686"
+
+#undef  SUBTARGET_INIT_BUILTINS
+#define SUBTARGET_INIT_BUILTINS		\
+do {					\
+  darwin_init_cfstring_builtins ();	\
+} while(0)
+
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 165662)
+++ gcc/config/i386/i386.c	(working copy)
@@ -24437,6 +24437,10 @@ ix86_init_builtins (void)
 
   if (TARGET_64BIT)
     ix86_init_builtins_va_builtins_abi ();
+
+#ifdef SUBTARGET_INIT_BUILTINS
+  SUBTARGET_INIT_BUILTINS;
+#endif
 }
 
 /* Return the ix86 builtin for CODE.  */
Index: gcc/config/darwin-protos.h
===================================================================
--- gcc/config/darwin-protos.h	(revision 165662)
+++ gcc/config/darwin-protos.h	(working copy)
@@ -87,10 +87,17 @@ extern void darwin_asm_output_dwarf_delta (FILE *,
 					   const char *);
 extern void darwin_asm_output_dwarf_offset (FILE *, int, const char *,
 					    section *);
+
 extern void darwin_asm_declare_constant_name (FILE *, const char *,
 					      const_tree, HOST_WIDE_INT);
 extern bool darwin_binds_local_p (const_tree);
 extern void darwin_cpp_builtins (struct cpp_reader *);
+
+extern void darwin_init_cfstring_builtins (void);
+extern tree darwin_fold_builtin (tree, int, tree *, bool);
+extern tree darwin_objc_construct_string (tree);
+extern bool darwin_cfstring_p (tree);
+
 extern void darwin_asm_output_anchor (rtx symbol);
 extern bool darwin_kextabi_p (void);
 extern void darwin_override_options (void);
Index: gcc/config/darwin-cfstrings.c
===================================================================
--- gcc/config/darwin-cfstrings.c	(revision 0)
+++ gcc/config/darwin-cfstrings.c	(revision 0)
@@ -0,0 +1,354 @@
+/* Darwin CFString support.
+   Copyright (C) 2010  Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "c-family/c-common.h"
+#include "diagnostic-core.h"
+#include "toplev.h"
+#include "tm_p.h"
+#include "langhooks.h"
+#include "c-tree.h"
+#include "c-lang.h"
+
+/* We have this computed already and, should we wish to extend CFStrings
+   to non-c-family front ends, it will be required.  */
+extern int darwin_running_cxx;
+
+static tree darwin_build_constant_cfstring (tree);
+
+enum darwin_builtins
+{
+  DARWIN_BUILTIN_MIN = (int)END_BUILTINS,
+
+  DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING,
+  DARWIN_BUILTIN_MAX
+};
+
+static GTY(()) tree cfstring_class_reference = NULL_TREE;
+static GTY(()) tree cfstring_type_node = NULL_TREE;
+static GTY(()) tree ccfstring_type_node = NULL_TREE;
+static GTY(()) tree pccfstring_type_node = NULL_TREE;
+static GTY(()) tree pcint_type_node = NULL_TREE;
+static GTY(()) tree pcchar_type_node = NULL_TREE;
+
+/* Store all constructed constant CFStrings in a hash table so that
+   they get uniqued properly.  */
+
+typedef struct GTY (()) cfstring_descriptor {
+  /* The literal argument .  */
+  tree literal;
+  /* The resulting constant CFString.  */
+  tree constructor;
+} cfstring_descriptor;
+
+static GTY ((param_is (struct cfstring_descriptor))) htab_t cfstring_htab;
+
+static hashval_t cfstring_hash (const void *);
+static int cfstring_eq (const void *, const void *);
+
+static tree
+add_builtin_field_decl (tree type, const char *name, tree **chain)
+{
+  tree field = build_decl (BUILTINS_LOCATION, FIELD_DECL, 
+			    get_identifier (name), type);
+
+  if (*chain != NULL)
+    **chain = field;
+  *chain = &DECL_CHAIN (field);
+
+  return field;
+}
+
+void
+darwin_init_cfstring_builtins (void)
+{
+  tree cfsfun, fields, pccfstring_ftype_pcchar;
+  tree *chain = NULL;
+
+  /* struct __builtin_CFString {
+       const int *isa;		(will point at
+       int flags;		 __CFConstantStringClassReference)
+       const char *str;
+       long length;
+     };  */
+
+  pcint_type_node = build_pointer_type 
+		   (build_qualified_type (integer_type_node, TYPE_QUAL_CONST));
+
+  pcchar_type_node = build_pointer_type 
+		   (build_qualified_type (char_type_node, TYPE_QUAL_CONST));
+
+  cfstring_type_node = (*lang_hooks.types.make_type) (RECORD_TYPE);
+
+  /* Have to build backwards for finish struct.  */
+  fields = add_builtin_field_decl (long_integer_type_node, "length", &chain);
+  add_builtin_field_decl (pcchar_type_node, "str", &chain);
+  add_builtin_field_decl (integer_type_node, "flags", &chain);
+  add_builtin_field_decl (pcint_type_node, "isa", &chain);
+  finish_builtin_struct (cfstring_type_node, "__builtin_CFString",
+			 fields, NULL_TREE);
+
+  /* const struct __builtin_CFstring *
+     __builtin___CFStringMakeConstantString (const char *); */
+
+  ccfstring_type_node = build_qualified_type 
+			(cfstring_type_node, TYPE_QUAL_CONST);
+  pccfstring_type_node = build_pointer_type (ccfstring_type_node);
+  pccfstring_ftype_pcchar = build_function_type_list 
+			(pccfstring_type_node, pcchar_type_node, NULL_TREE);
+
+  cfsfun  = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, 
+			get_identifier ("__builtin___CFStringMakeConstantString"),
+			pccfstring_ftype_pcchar);
+
+  TREE_PUBLIC (cfsfun) = 1;
+  DECL_EXTERNAL (cfsfun) = 1;
+  DECL_ARTIFICIAL (cfsfun) = 1;
+  DECL_LANG_SPECIFIC (cfsfun) =  ggc_alloc_cleared_lang_decl (sizeof
+                                                          (struct lang_decl));
+  DECL_BUILT_IN_CLASS (cfsfun) = BUILT_IN_MD;
+  DECL_FUNCTION_CODE (cfsfun) = 
+	    (enum built_in_function) DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING;
+  lang_hooks.builtin_function (cfsfun);
+
+  /* extern int __CFConstantStringClassReference[];  */
+  cfstring_class_reference = build_decl (BUILTINS_LOCATION, VAR_DECL,
+		 get_identifier ("__CFConstantStringClassReference"),
+		 build_array_type (integer_type_node, NULL_TREE));
+
+  TREE_PUBLIC (cfstring_class_reference) = 1;
+  TREE_USED (cfstring_class_reference) = 1;
+  DECL_ARTIFICIAL (cfstring_class_reference) = 1;
+  (*lang_hooks.decls.pushdecl) (cfstring_class_reference);
+  DECL_EXTERNAL (cfstring_class_reference) = 1;
+  rest_of_decl_compilation (cfstring_class_reference, 0, 0);
+  
+  /* Initialize the hash table used to hold the constant CFString objects.  */
+  cfstring_htab = htab_create_ggc (31, cfstring_hash, cfstring_eq, NULL);
+}
+
+tree
+darwin_fold_builtin (tree fndecl, int n_args, tree *argp, 
+		     bool ARG_UNUSED (ignore))
+{
+  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+
+  if (fcode == DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING)
+    {
+      if (!darwin_constant_cfstrings)
+	{
+	  error ("built-in function %qD requires the" 
+		 " %<-mconstant-cfstrings%> flag", fndecl);
+	  return error_mark_node;
+	}
+
+      if (n_args != 1)
+	{
+	  error ("built-in function %qD takes one argument only", fndecl);
+	  return error_mark_node;
+	}
+
+      return darwin_build_constant_cfstring (*argp);
+    }
+
+  return NULL_TREE;
+}
+
+static hashval_t
+cfstring_hash (const void *ptr)
+{
+  tree str = ((const struct cfstring_descriptor *)ptr)->literal;
+  const unsigned char *p = (const unsigned char *) TREE_STRING_POINTER (str);
+  int i, len = TREE_STRING_LENGTH (str);
+  hashval_t h = len;
+
+  for (i = 0; i < len; i++)
+    h = ((h * 613) + p[i]);
+
+  return h;
+}
+
+static int
+cfstring_eq (const void *ptr1, const void *ptr2)
+{
+  tree str1 = ((const struct cfstring_descriptor *)ptr1)->literal;
+  tree str2 = ((const struct cfstring_descriptor *)ptr2)->literal;
+  int len1 = TREE_STRING_LENGTH (str1);
+
+  return (len1 == TREE_STRING_LENGTH (str2)
+	  && !memcmp (TREE_STRING_POINTER (str1), TREE_STRING_POINTER (str2),
+		      len1));
+}
+
+static tree
+darwin_build_constant_cfstring (tree str)
+{
+  struct cfstring_descriptor *desc, key;
+  void **loc;
+  tree addr;
+
+  if (!str)
+    {
+      error ("CFString literal is missing");
+      return error_mark_node;
+    }
+
+  STRIP_NOPS (str);
+
+  if (TREE_CODE (str) == ADDR_EXPR)
+    str = TREE_OPERAND (str, 0);
+
+  if (TREE_CODE (str) != STRING_CST)
+    {
+      error ("CFString literal expression is not a string constant");
+      return error_mark_node;
+    }
+
+  /* Perhaps we already constructed a constant CFString just like this one? */
+  key.literal = str;
+  loc = htab_find_slot (cfstring_htab, &key, INSERT);
+  desc = (struct cfstring_descriptor *) *loc;
+
+  if (!desc)
+    {
+      tree var, constructor, field ;
+      VEC(constructor_elt,gc) *v = NULL;
+      int length = TREE_STRING_LENGTH (str) - 1;
+
+      if (darwin_warn_nonportable_cfstrings)
+	{
+	  const char *s = TREE_STRING_POINTER (str);
+	  int l = 0;
+
+	  for (l = 0; l < length; l++)
+	    if (!s[l] || !isascii (s[l]))
+	      {
+		warning (darwin_warn_nonportable_cfstrings, "%s in CFString literal",
+			 s[l] ? "non-ASCII character" : "embedded NUL");
+		break;
+	      }
+	}
+
+      *loc = desc = ggc_alloc_cleared_cfstring_descriptor ();
+      desc->literal = str;
+
+      /* isa *. */
+      field = TYPE_FIELDS (ccfstring_type_node);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE, 
+			     build1 (ADDR_EXPR,  TREE_TYPE (field),  
+				     cfstring_class_reference));
+      /* flags */
+      field = DECL_CHAIN (field);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE, 
+			     build_int_cst (TREE_TYPE (field), 0x000007c8));
+      /* string *. */
+      field = DECL_CHAIN (field);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE,
+			     build1 (ADDR_EXPR, TREE_TYPE (field), str));
+      /* length */
+      field = DECL_CHAIN (field);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE,
+			     build_int_cst (TREE_TYPE (field), length));
+
+      constructor = build_constructor (ccfstring_type_node, v);
+      TREE_READONLY (constructor) = 1;
+      TREE_CONSTANT (constructor) = 1;
+      TREE_STATIC (constructor) = 1;
+
+      /* Fromage: The C++ flavor of 'build_unary_op' expects constructor nodes
+	 to have the TREE_HAS_CONSTRUCTOR (...) bit set.  However, this file is
+	 being built without any knowledge of C++ tree accessors; hence, we shall
+	 use the generic accessor that TREE_HAS_CONSTRUCTOR actually maps to!  */
+      if (darwin_running_cxx)
+	TREE_LANG_FLAG_4 (constructor) = 1;  /* TREE_HAS_CONSTRUCTOR  */
+
+      /* Create an anonymous global variable for this CFString.  */
+      var = build_decl (input_location, CONST_DECL, 
+			NULL, TREE_TYPE (constructor));
+      DECL_INITIAL (var) = constructor;
+      TREE_STATIC (var) = 1;
+      pushdecl_top_level (var);
+      desc->constructor = var;
+    }
+
+  addr = build1 (ADDR_EXPR, pccfstring_type_node, desc->constructor);
+  TREE_CONSTANT (addr) = 1;
+
+  return addr;
+}
+
+/* Give ObjC* visibility of the cfstrings innards so that we may share 
+   resources.  */
+tree
+darwin_objc_construct_string (tree str)
+{
+  if (!darwin_constant_cfstrings)
+    {
+      /* Even though we are not using CFStrings, place our literal
+	 into the cfstring_htab hash table, so that the
+	 darwin_constant_cfstring_p() function will see it.  */
+      struct cfstring_descriptor key;
+      void **loc;
+
+      key.literal = str;
+      loc = htab_find_slot (cfstring_htab, &key, INSERT);
+
+      if (!*loc)
+	{
+	  *loc = ggc_alloc_cleared_cfstring_descriptor ();
+	  ((struct cfstring_descriptor *)*loc)->literal = str;
+	}
+
+      return NULL_TREE;  /* Fall back to NSConstantString.  */
+    }
+
+  return darwin_build_constant_cfstring (str);
+}
+
+bool
+darwin_cfstring_p (tree str)
+{
+  struct cfstring_descriptor key;
+  void **loc;
+
+  if (!str)
+    return false;
+
+  STRIP_NOPS (str);
+
+  if (TREE_CODE (str) == ADDR_EXPR)
+    str = TREE_OPERAND (str, 0);
+
+  if (TREE_CODE (str) != STRING_CST)
+    return false;
+
+  key.literal = str;
+  loc = htab_find_slot (cfstring_htab, &key, NO_INSERT);
+  
+  if (loc)
+    return true;
+
+  return false;
+}
+
+#include "gt-darwin-cfstrings.h"
Index: gcc/config/rs6000/darwin.h
===================================================================
--- gcc/config/rs6000/darwin.h	(revision 165662)
+++ gcc/config/rs6000/darwin.h	(working copy)
@@ -436,5 +436,10 @@ extern int darwin_emit_branch_islands;
    default, as kernel code doesn't save/restore those registers.  */
 #define OS_MISSING_ALTIVEC (flag_mkernel || flag_apple_kext)
 
-/* Darwin has to rename some of the long double builtins.  */
-#define SUBTARGET_INIT_BUILTINS darwin_patch_builtins ()
+/* PPC Darwin has to rename some of the long double builtins.  */
+#undef  SUBTARGET_INIT_BUILTINS
+#define SUBTARGET_INIT_BUILTINS		\
+do {					\
+  darwin_patch_builtins ();		\
+  darwin_init_cfstring_builtins ();	\
+} while(0)
Index: gcc/config/darwin.c
===================================================================
--- gcc/config/darwin.c	(revision 165662)
+++ gcc/config/darwin.c	(working copy)
@@ -85,6 +85,11 @@ along with GCC; see the file COPYING3.  If not see
    kernel) the stubs might still be required, and this will be set true.  */
 int darwin_emit_branch_islands = false;
 
+/* A flag to determine whether we are running c++ or obj-c++.  This has to be
+   settable from non-c-family contexts too (i.e. we can't use the c_dialect_
+   functions).  */
+int darwin_running_cxx;
+
 /* Section names.  */
 section * darwin_sections[NUM_DARWIN_SECTIONS];
 
@@ -1256,6 +1261,8 @@ machopic_select_section (tree decl,
           else
             return darwin_sections[objc_string_object_section];
         }
+      else if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_CFString"))
+	return darwin_sections[cfstring_constant_object_section];
       else
         return base_section;
     }
@@ -1910,6 +1904,9 @@ darwin_override_options (void)
   if (darwin_macosx_version_min
       && strverscmp (darwin_macosx_version_min, "10.5") < 0)
     darwin_emit_branch_islands = true;
+
+  /* The c_dialect...() macros are not available to us here.  */
+  darwin_running_cxx = (strstr (lang_hooks.name, "C++") != 0);
 }
 
 /* Add $LDBL128 suffix to long double builtins.  */
@@ -1954,5 +1951,21 @@ darwin_patch_builtins (void)
 #undef PATCH_BUILTIN_VARIADIC
 }
 
+/* ==========================================================   */
+/* Dummy routines to satisfy linkage on fortran, java and lto.  */
 
+__attribute__((weak)) void
+darwin_init_cfstring_builtins (void)
+{
+}
+
+__attribute__((weak)) tree
+darwin_fold_builtin (tree ARG_UNUSED (fndecl),
+		     int ARG_UNUSED (n_args), 
+		     tree ARG_UNUSED (*argp), 
+		     bool ARG_UNUSED (ignore))
+{
+  return NULL_TREE;
+}
+
 #include "gt-darwin.h"
Index: gcc/config/darwin-sections.def
===================================================================
--- gcc/config/darwin-sections.def	(revision 165662)
+++ gcc/config/darwin-sections.def	(working copy)
@@ -33,6 +33,9 @@ DEF_SECTION (cstring_section, SECTION_MERGE | SECT
 DEF_SECTION (literal4_section, SECTION_MERGE, ".literal4", 0)
 DEF_SECTION (literal8_section, SECTION_MERGE, ".literal8", 0)
 DEF_SECTION (literal16_section, SECTION_MERGE, ".literal16", 0)
+/* Unlike constant NSStrings, constant CFStrings do not live  in the __OBJC segment
+  since they may also occur in pure C  or C++ programs.  */
+DEF_SECTION (cfstring_constant_object_section, 0, ".section __DATA, __cfstring", 0)
 DEF_SECTION (constructor_section, 0, ".constructor", 0)
 DEF_SECTION (mod_init_section, 0, ".mod_init_func", 0)
 DEF_SECTION (mod_term_section, 0, ".mod_term_func", 0)
Index: gcc/config/darwin.h
===================================================================
--- gcc/config/darwin.h	(revision 165662)
+++ gcc/config/darwin.h	(working copy)
@@ -1054,6 +1060,12 @@ __enable_execute_stack (void *addr)
 #define TARGET_CXX_CDTOR_RETURNS_THIS (darwin_kextabi_p)
 #define TARGET_KEXTABI flag_apple_kext
 
+/* We have target-specific builtins.  */
+#define TARGET_FOLD_BUILTIN darwin_fold_builtin
+
+#define TARGET_OBJC_CONSTRUCT_STRING \
+  darwin_objc_construct_string
+
 #define TARGET_HAS_TARGETCM 1
 
 #ifndef CROSS_DIRECTORY_STRUCTURE
Index: gcc/objc/objc-act.c
===================================================================
--- gcc/objc/objc-act.c	(revision 165662)
+++ gcc/objc/objc-act.c	(working copy)
@@ -2577,7 +2577,7 @@ string_eq (const void *ptr1, const void *ptr2)
 tree
 objc_build_string_object (tree string)
 {
-  tree constructor = NULL_TREE, constant_string_class;
+  tree constant_string_class;
   int length;
   tree fields, addr;
   struct string_descriptor *desc, key;
@@ -2588,6 +2588,17 @@ objc_build_string_object (tree string)
   TREE_SET_CODE (string, STRING_CST);
   length = TREE_STRING_LENGTH (string) - 1;
 
+  /* The target may have different ideas on how to construct an ObjC string 
+     literal.  On Darwin (Mac OS X), for example, we may wish to obtain a 
+     constant CFString reference instead.
+     At present, this is only supported for the NeXT runtime.  */
+  if (flag_next_runtime && targetcm.objc_construct_string)
+    {
+      tree constructor = (*targetcm.objc_construct_string) (string);
+      if (constructor)
+	return build1 (NOP_EXPR, objc_object_type, constructor);
+    }
+
   /* Check whether the string class being used actually exists and has the
      correct ivar layout.  */
   if (!string_layout_checked)
@@ -2627,7 +2638,7 @@ objc_build_string_object (tree string)
 
   if (!desc)
     {
-      tree var;
+      tree var, constructor;
       VEC(constructor_elt,gc) *v = NULL;
       *loc = desc = ggc_alloc_string_descriptor ();
       desc->literal = string;

Comments

Paolo Bonzini Oct. 19, 2010, 9:06 a.m. UTC | #1
On 10/19/2010 10:48 AM, IainS wrote:
> Hi,
> CFStrings are a c-family target-specific addition on Darwin (they might
> be useful to GNUstep, but we decided to delay that consideration for
> present).
> They've been present in the system since the start of Darwin and using
> them has become a requirement if we are to parse system headers on
> Darwin10.
>
> The changes need to be applied as one commit - hence one email.
>
> however to make review easier I've split the patch into files that
> involve build system changes ...
> ... and the remainder which are under Mike's area (the bulk of the text).
> Although this patch is based on examination of the apple local 'trunk'
> branch, I had to make significant modifications (i.e. it is technically
> covered by the merging pre-approval, but Mike might wish to cast a quick
> eye over it).
>
> checked on {powerpc,i686}-darwin9, x86_64-darwin10, i686-darwin8,
> x86_64-unknown-linux, and a cross to cris-elf
> (really mostly relevant to the test-suite changes in part 2).
>
> OK for trunk?
> Iain
>
> === Build system Changes
>
> It turns out that, whilst we have the capability to add files
> selectively for cfamily per target, this does not extend to gt-files and
> therefore, to apply the patch I need approval for the following build
> mechanism change:
>
> gcc:
>
> * config.gcc (target_cfamily_gtfiles): New var, target_cfamily_gtfiles
> add darwin-cfstrings.c.
> c_target_objs, cxx_target_objs add darwin-cfstrings.o.
> * c-config-lang.in (gtfiles): Add target_cfamily_gtfiles.
>
> gcc/cp:
>
> * cp/config-lang.in (gtfiles): Add target_cfamily_gtfiles.
>
> gcc/objc:
>
> * objc/config-lang.in (gtfiles): Add target_cfamily_gtfiles.
>
> gcc/objcp:
>
> * objcp/config-lang.in (gtfiles): Add target_cfamily_gtfiles.

That's okay.  However I think it's better to make most of the 
implementation language-independent, since it already is.  This is 
especially important for LTO, and also removes the need for the weak 
symbol hack.  What remains is then small enough that it can be put in 
darwin-c.c.

It's also hackish to have darwin_fold_builtin as TARGET_FOLD_BUILTIN; it 
only works because neither x86 and PPC have such a hook.  I don't have 
any big problem with that, though.

Paolo
Iain Sandoe Oct. 19, 2010, 9:27 a.m. UTC | #2
Hi Paolo,

On 19 Oct 2010, at 10:06, Paolo Bonzini wrote:

> On 10/19/2010 10:48 AM, IainS wrote:
>> Hi,
>> CFStrings are a c-family target-specific addition on Darwin (they  
>> might
>> be useful to GNUstep, but we decided to delay that consideration for
>> present).
>> They've been present in the system since the start of Darwin and  
>> using
>> them has become a requirement if we are to parse system headers on
>> Darwin10.
>>
>> The changes need to be applied as one commit - hence one email.
>>
>> however to make review easier I've split the patch into files that
>> involve build system changes ...
>> ... and the remainder which are under Mike's area (the bulk of the  
>> text).
>> Although this patch is based on examination of the apple local  
>> 'trunk'
>> branch, I had to make significant modifications (i.e. it is  
>> technically
>> covered by the merging pre-approval, but Mike might wish to cast a  
>> quick
>> eye over it).
>>
>> checked on {powerpc,i686}-darwin9, x86_64-darwin10, i686-darwin8,
>> x86_64-unknown-linux, and a cross to cris-elf
>> (really mostly relevant to the test-suite changes in part 2).
>>
>> OK for trunk?
>> Iain
>>
>> === Build system Changes
>>
>> It turns out that, whilst we have the capability to add files
>> selectively for cfamily per target, this does not extend to gt- 
>> files and
>> therefore, to apply the patch I need approval for the following build
>> mechanism change:
>>
>> gcc:
>>
>> * config.gcc (target_cfamily_gtfiles): New var,  
>> target_cfamily_gtfiles
>> add darwin-cfstrings.c.
>> c_target_objs, cxx_target_objs add darwin-cfstrings.o.
>> * c-config-lang.in (gtfiles): Add target_cfamily_gtfiles.
>>
>> gcc/cp:
>>
>> * cp/config-lang.in (gtfiles): Add target_cfamily_gtfiles.
>>
>> gcc/objc:
>>
>> * objc/config-lang.in (gtfiles): Add target_cfamily_gtfiles.
>>
>> gcc/objcp:
>>
>> * objcp/config-lang.in (gtfiles): Add target_cfamily_gtfiles.

thanks for the quick review.

> That's okay.  However I think it's better to make most of the  
> implementation language-independent, since it already is.

Hm.  I thought about this, but could not see any real way in which  
this could be made use of in Fortran as things stand... (this might  
change when fortran gets objects)
.. I guess it's easier to see how it might apply to Java.

> This is especially important for LTO, and also removes the need for  
> the weak symbol hack.  What remains is then small enough that it can  
> be put in darwin-c.c.

The test-suite changes incorporate cfstring ObjC torture tests, which  
include basic lto and whopr checks (which pass for darwin).  I haven't  
done multi-file versions yet.

FWIW, there is currently no target-specific additions file defined for  
Java (although there is one for Fortran).

If Mike is also OK with this as it is, I'd prefer to leave as is for  
now - in the absence of any mechanism to test it on Fortran & Java.

cheers,
Iain
Iain Sandoe Oct. 19, 2010, 9:47 a.m. UTC | #3
On 19 Oct 2010, at 10:06, Paolo Bonzini wrote:
>
> It's also hackish to have darwin_fold_builtin as  
> TARGET_FOLD_BUILTIN; it only works because neither x86 and PPC have  
> such a hook.  I don't have any big problem with that, though.

If the consensus is that we should have a  
"TARGET_SUBTARGET_FOLD_BUILTIN" and "TARGET_SUBTARGET_INIT_BUILTINS" ...
... I'll happily add them - not hard to do.

cheers
Iain
Paolo Bonzini Oct. 19, 2010, 10:18 a.m. UTC | #4
On 10/19/2010 11:27 AM, IainS wrote:
> FWIW, there is currently no target-specific additions file defined for
> Java (although there is one for Fortran).

That wouldn't be needed, no? I don't recall anything language-dependent 
in the patch other than the ObjC hook.

Paolo
Iain Sandoe Oct. 19, 2010, 10:28 a.m. UTC | #5
On 19 Oct 2010, at 11:18, Paolo Bonzini wrote:

> On 10/19/2010 11:27 AM, IainS wrote:
>> FWIW, there is currently no target-specific additions file defined  
>> for
>> Java (although there is one for Fortran).
>
> That wouldn't be needed, no? I don't recall anything language- 
> dependent in the patch other than the ObjC hook.

IIRC Fortran and C have different ideas about 'push_top_level()'   
would take some investigation, I don't know about Java ..  I hadn't  
looked.

(BTW, passing the builtin to lto is  dealt with by the streamer, I  
just confirmed w/Richi on IRC).

cheers
Iain
Paolo Bonzini Oct. 19, 2010, 12:49 p.m. UTC | #6
On 10/19/2010 12:28 PM, IainS wrote:
>
> On 19 Oct 2010, at 11:18, Paolo Bonzini wrote:
>
>> On 10/19/2010 11:27 AM, IainS wrote:
>>> FWIW, there is currently no target-specific additions file defined for
>>> Java (although there is one for Fortran).
>>
>> That wouldn't be needed, no? I don't recall anything
>> language-dependent in the patch other than the ObjC hook.
>
> IIRC Fortran and C have different ideas about 'push_top_level()' would
> take some investigation, I don't know about Java

My point is that I see absolutely _nothing_ here that should be 
language-dependent except the C++ TREE_HAS_CONSTRUCTOR bit and the ObjC 
hook.  There are some thing like pushdecl_top_level that in theory 
should be done through varpool, but I guess if Mike is okay it's 
pointless to argue.

Paolo
Iain Sandoe Oct. 19, 2010, 1:04 p.m. UTC | #7
On 19 Oct 2010, at 13:49, Paolo Bonzini wrote:

> On 10/19/2010 12:28 PM, IainS wrote:
>>
>> On 19 Oct 2010, at 11:18, Paolo Bonzini wrote:
>>
>>> On 10/19/2010 11:27 AM, IainS wrote:
>>>> FWIW, there is currently no target-specific additions file  
>>>> defined for
>>>> Java (although there is one for Fortran).
>>>
>>> That wouldn't be needed, no? I don't recall anything
>>> language-dependent in the patch other than the ObjC hook.
>>
>> IIRC Fortran and C have different ideas about 'push_top_level()'  
>> would
>> take some investigation, I don't know about Java
>
> My point is that I see absolutely _nothing_ here that should be  
> language-dependent except the C++ TREE_HAS_CONSTRUCTOR bit

that's already, handled in a language-independent manner in darwin.c
(so that darwin_running_cxx is available generally, without needing  
the c_dialect() macros).

So, I could move the main body code to darwin.c (all languages)

> and the ObjC hook.

... that could probably be moved to darwin-c.c (c-family) ...
(there's no reason to have to export a dummy for that to Fortran &  
Java).

> There are some thing like pushdecl_top_level that in theory should  
> be done through varpool,

hm. maybe that's a thing I've missed...
.... perhaps I should be using finish_var_decl and setting the context  
instead.
(that was part of the merged code I didn't modify).

> but I guess if Mike is okay it's pointless to argue.

Well, not arguing here ;-) ...

... if there's a Better Way, would rather do it now than modify it  
later....

cheers,
Iain
Mike Stump Oct. 19, 2010, 5:01 p.m. UTC | #8
On Oct 19, 2010, at 1:48 AM, IainS wrote:
> The changes need to be applied as one commit - hence one email.

> OK for trunk?

Ok.

If someone has a suggestion and direction for this part:

+      if (darwin_running_cxx)
+	TREE_LANG_FLAG_4 (constructor) = 1;  /* TREE_HAS_CONSTRUCTOR  */

I'd pre-approve a better direction.  I've not thought about it much yet.  I'm wondering if it makes sense to include the header that defines TREE_HAS_CONSTRUCTOR and then use that directly, or, if that should be pushed into the language independent parts of the compiler.... or something else entirely.
diff mbox

Patch

Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 165662)
+++ gcc/config.gcc	(working copy)
@@ -147,6 +147,10 @@ 
 #
 #  target_gtfiles       List of extra source files with type information.
 #
+#  target_cfamily_gtfiles
+#			List of extra source files with type information
+#			to be used for c family only.
+#
 #  xm_defines		List of macros to define when compiling for the
 #			target machine.
 #
@@ -217,6 +221,7 @@  gnu_ld="$gnu_ld_flag"
 default_use_cxa_atexit=no
 default_gnu_indirect_function=no
 target_gtfiles=
+target_cfamily_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
 # Selects the object file format reader/writer used by LTO.
@@ -464,9 +469,10 @@  case ${target} in
   tm_file="${tm_file} ${cpu_type}/darwin.h"
   tm_p_file="${tm_p_file} darwin-protos.h"
   target_gtfiles="\$(srcdir)/config/darwin.c"
+  target_cfamily_gtfiles="\$(srcdir)/config/darwin-cfstrings.c"
   extra_options="${extra_options} darwin.opt"
-  c_target_objs="${c_target_objs} darwin-c.o"
-  cxx_target_objs="${cxx_target_objs} darwin-c.o"
+  c_target_objs="${c_target_objs} darwin-c.o darwin-cfstrings.o"
+  cxx_target_objs="${cxx_target_objs} darwin-c.o darwin-cfstrings.o"
   fortran_target_objs="darwin-f.o"
   extra_objs="darwin.o"
   extra_gcc_objs="darwin-driver.o"
Index: gcc/c-config-lang.in
===================================================================
--- gcc/c-config-lang.in	(revision 165662)
+++ gcc/c-config-lang.in	(working copy)
@@ -1,5 +1,6 @@ 
 # Top level configure fragment for GNU C - C language.
-# Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005, 2007 Free Software Foundation, Inc.
+#   Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005, 2007, 2010
+#   Free Software Foundation, Inc.
 
 #This file is part of GCC.
 
@@ -23,3 +24,4 @@ 
 # which therefore need to be scanned by gengtype.c.
 
 gtfiles="\$(srcdir)/c-lang.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-parser.c \$(srcdir)/c-lang.h"
+gtfiles="${gtfiles} ${target_cfamily_gtfiles}"
Index: gcc/cp/config-lang.in
===================================================================
--- gcc/cp/config-lang.in	(revision 165662)
+++ gcc/cp/config-lang.in	(working copy)
@@ -1,5 +1,5 @@ 
 # Top level configure fragment for GNU C++.
-#   Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2007
+#   Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2007, 2010
 #   Free Software Foundation, Inc.
 
 #This file is part of GCC.
@@ -31,3 +31,4 @@  compilers="cc1plus\$(exeext)"
 target_libs="target-libstdc++-v3"
 
 gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c"
+gtfiles="${gtfiles} ${target_cfamily_gtfiles}"
Index: gcc/objc/config-lang.in
===================================================================
--- gcc/objc/config-lang.in	(revision 165662)
+++ gcc/objc/config-lang.in	(working copy)
@@ -1,5 +1,5 @@ 
 # Top level configure fragment for GNU Objective-C
-#   Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+#   Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2010
 #   Free Software Foundation, Inc.
 
 #This file is part of GCC.
@@ -34,3 +34,4 @@  target_libs=target-libobjc
 lang_requires="c"
 
 gtfiles="\$(srcdir)/objc/objc-act.h \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/objc/objc-act.c"
+gtfiles="${gtfiles} ${target_cfamily_gtfiles}"
Index: gcc/objcp/config-lang.in
===================================================================
--- gcc/objcp/config-lang.in	(revision 165662)
+++ gcc/objcp/config-lang.in	(working copy)
@@ -1,5 +1,5 @@ 
 # Top level configure fragment for GNU Objective-C++.
-#   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+#   Copyright (C) 2005, 2007, 2010 Free Software Foundation, Inc.
 #   Contributed by Ziemowit Laski <zlaski@apple.com>
 
 #This file is part of GCC.
@@ -38,3 +38,4 @@  lang_requires="objc c++"
 subdir_requires="objc cp"
 
 gtfiles="\$(srcdir)/objcp/objcp-decl.c \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-act.h \$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/cp-objcp-common.c"
+gtfiles="${gtfiles} ${target_cfamily_gtfiles}"