diff mbox

re-jigged for lang independence, Re: [Patch, Darwin, c*, ObjC* 1/2] Implement Darwin CFStrings.

Message ID A6EF8868-FC68-4837-95D6-F7AEA27315A0@sandoe-acoustics.co.uk
State New
Headers show

Commit Message

Iain Sandoe Oct. 22, 2010, 10:37 a.m. UTC
On 20 Oct 2010, at 09:48, Richard Guenther wrote:

> On Tue, Oct 19, 2010 at 7:14 PM, IainS <developer@sandoe-acoustics.co.uk 
> > wrote:
>> Hi Mike, Paulo
>> I wasn't quite quick enough...
>> .. sorry if I wasted reviewer's time.
>>
>> On 19 Oct 2010, at 18:01, Mike Stump wrote:
>>
>>> 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.
>>
>> here is an update that addresses Paolo's comments.
>>
>> This is a language-independent variant (other than the ObjC  
>> interface).
>>
>> Essentially the same code (less replacing pushdecl_top_level()  with
>> DECL_CONTEXT=NULL_TREE).
>
> toplevel entities should have DECL_CONTEXT of the
> TRANSLATION_UNIT_DECL, not NULL these days.

So noted in the applied patch with a FIXME.
However, as you noted in irc this needs to be done once per TU
.. and currently each FE handles it differently (and none of them  
export the result where a builtin or other parser code can reach).

Would it be a good idea to introduce  
langhooks.decl.current_translation_unit?
(defaulting to NULL_TREE, I guess).
>
> RIchard.
>
>> Bootstrapped (incl.Java)  and checked ObjC* on i686-darwin9.
>>
>> I can't imagine why there would be any difference on a non-darwin  
>> platform -
>> but...
>> ... OK if it passes remaining regtests and on a non-darwin platform?


this took a while because of the testcycle...
... in addition to adding the  comment above two minor adjustments  
were needed:
to deal with different sized decls (use the lang hook instead of sizeof)
to make sure that builtin enum code is after all the machine ones.

applied as r165820
Iain
diff mbox

Patch

Index: gcc/ChangeLog
===================================================================
--- gcc/ChangeLog	(revision 165817)
+++ gcc/ChangeLog	(working copy)
@@ -1,3 +1,37 @@ 
+2010-10-21  Iain Sandoe  <iains@gcc.gnu.org>
+
+	Based on the CFString implementation in FSF apple/trunk branch.
+	
+	* 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: Amend build rules for darwin.o.
+	* config/darwin.opt: Add cfstrings flags.
+	* config/darwin-c.c: Define __CONSTANT_CFSTRINGS__.
+	(darwin_objc_construct_string): New.
+	* 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): Likewise.
+	(darwin_build_constant_cfstring): Likewise.
+	(darwin_objc_construct_string): Likewise.
+	(darwin_cfstring_p): Likewise.
+	(darwin_enter_string_into_cfstring_table): Likewise.
+	* 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.
+	(add_builtin_field_decl): New.
+	(darwin_init_cfstring_builtins): New.
+	(darwin_build_constant_cfstring): New.
+	(darwin_fold_builtin): New.
+	(cfstring_hash): New.
+	(cfstring_eq): New.
+	(darwin_enter_string_into_cfstring_table): New.
+	* config/darwin-sections.def (cfstring_constant_object_section): New.
+	* config/darwin.h (TARGET_FOLD_BUILTIN): Define.
+	(TARGET_OBJC_CONSTRUCT_STRING): Define.
+
 2010-10-21  Nathan Froyd  <froydnj@codesourcery.com>
 
 	* config/alpha/alpha.c (alpha_build_builtin_va_list): Use
Index: gcc/objc/ChangeLog
===================================================================
--- gcc/objc/ChangeLog	(revision 165817)
+++ gcc/objc/ChangeLog	(working copy)
@@ -1,3 +1,9 @@ 
+2010-10-21  Iain Sandoe  <iains@gcc.gnu.org>
+
+	Based on the CFString implementation in FSF apple/trunk branch.
+	
+	* objc/objc-act.c (objc_build_string_object): Handle CFStrings.
+
 2010-10-21  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	* objc-act.c (get_objc_string_decl): Use a switch instead of a
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 165817)
+++ 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 165817)
+++ 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/target.def
===================================================================
--- gcc/target.def	(revision 165817)
+++ gcc/target.def	(working copy)
@@ -2542,4 +2542,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/objc/objc-act.c
===================================================================
--- gcc/objc/objc-act.c	(revision 165817)
+++ gcc/objc/objc-act.c	(working copy)
@@ -2576,7 +2576,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;
@@ -2587,6 +2587,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)
@@ -2626,7 +2637,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;
Index: gcc/objc/ChangeLog
===================================================================
--- gcc/objc/ChangeLog	(revision 165817)
+++ gcc/objc/ChangeLog	(working copy)
@@ -1,3 +1,9 @@ 
+2010-10-21  Iain Sandoe  <iains@gcc.gnu.org>
+
+	Based on the CFString implementation in FSF apple/trunk branch.
+	
+	* objc/objc-act.c (objc_build_string_object): Handle CFStrings.
+
 2010-10-21  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	* objc-act.c (get_objc_string_decl): Use a switch instead of a
Index: gcc/config/t-darwin
===================================================================
--- gcc/config/t-darwin	(revision 165817)
+++ gcc/config/t-darwin	(working copy)
@@ -21,7 +21,7 @@  darwin.o: $(srcdir)/config/darwin.c $(CONFIG_H) $(
   $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(REAL_H) insn-config.h         \
   conditions.h insn-flags.h output.h insn-attr.h flags.h $(TREE_H) expr.h   \
   reload.h function.h $(GGC_H) langhooks.h $(TARGET_H) $(TM_P_H) gt-darwin.h \
-  config/darwin-sections.def
+  c-tree.h c-lang.h config/darwin-sections.def
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 		$(srcdir)/config/darwin.c
 
Index: gcc/config/darwin.opt
===================================================================
--- gcc/config/darwin.opt	(revision 165817)
+++ 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 165817)
+++ 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);
 
@@ -658,3 +661,20 @@  handle_c_option (size_t code,
 #define TARGET_HANDLE_C_OPTION handle_c_option
 
 struct gcc_targetcm targetcm = TARGETCM_INITIALIZER;
+
+/* Allow ObjC* access to CFStrings.  */
+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.  */
+      darwin_enter_string_into_cfstring_table (str);
+      /* Fall back to NSConstantString.  */
+      return NULL_TREE;
+    }
+
+  return darwin_build_constant_cfstring (str);
+}
Index: gcc/config/i386/darwin.h
===================================================================
--- gcc/config/i386/darwin.h	(revision 165817)
+++ 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 ((unsigned) (IX86_BUILTIN_MAX));\
+} while(0)
+
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 165817)
+++ gcc/config/i386/i386.c	(working copy)
@@ -24410,6 +24410,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 165817)
+++ gcc/config/darwin-protos.h	(working copy)
@@ -91,6 +91,14 @@  extern void darwin_asm_declare_constant_name (FILE
 					      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 (unsigned);
+extern tree darwin_fold_builtin (tree, int, tree *, bool);
+extern tree darwin_objc_construct_string (tree);
+extern bool darwin_cfstring_p (tree);
+extern tree darwin_build_constant_cfstring (tree str);
+extern void darwin_enter_string_into_cfstring_table (tree);
+
 extern void darwin_asm_output_anchor (rtx symbol);
 extern bool darwin_kextabi_p (void);
 extern void darwin_override_options (void);
Index: gcc/config/rs6000/darwin.h
===================================================================
--- gcc/config/rs6000/darwin.h	(revision 165817)
+++ 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 ((unsigned) (RS6000_BUILTIN_COUNT));	\
+} while(0)
Index: gcc/config/darwin.c
===================================================================
--- gcc/config/darwin.c	(revision 165817)
+++ gcc/config/darwin.c	(working copy)
@@ -41,6 +41,8 @@  along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "target.h"
 #include "tm_p.h"
+#include "c-tree.h"
+#include "c-lang.h"
 #include "diagnostic-core.h"
 #include "toplev.h"
 #include "hashtab.h"
@@ -85,6 +87,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 +1263,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 +1919,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 +1966,307 @@  darwin_patch_builtins (void)
 #undef PATCH_BUILTIN_VARIADIC
 }
 
+/*  CFStrings implementation.  */
+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;
 
+static enum built_in_function DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING;
+
+/* Store all constructed constant CFStrings in a hash table so that
+   they get uniqued properly.  */
+
+typedef struct GTY (()) cfstring_descriptor {
+  /* The string literal.  */
+  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 (unsigned first_avail)
+{
+  tree cfsfun, fields, pccfstring_ftype_pcchar;
+  tree *chain = NULL;
+
+  DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING = 
+			(enum built_in_function) first_avail;
+  
+  /* 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;
+  /* Make a lang-specific section - dup_lang_specific_decl makes a new node
+     in place of the existing, which may be NULL.  */
+  DECL_LANG_SPECIFIC (cfsfun) = NULL;
+  (*lang_hooks.dup_lang_specific_decl) (cfsfun);
+  DECL_BUILT_IN_CLASS (cfsfun) = BUILT_IN_MD;
+  DECL_FUNCTION_CODE (cfsfun) = 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;
+  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));
+}
+
+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_ARTIFICIAL (var) = 1;
+      TREE_STATIC (var) = 1;
+      DECL_INITIAL (var) = constructor;
+      /* FIXME: This should use a translation_unit_decl to indicate file scope.  */
+      DECL_CONTEXT (var) = NULL_TREE;
+      desc->constructor = var;
+    }
+
+  addr = build1 (ADDR_EXPR, pccfstring_type_node, desc->constructor);
+  TREE_CONSTANT (addr) = 1;
+
+  return addr;
+}
+
+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;
+}
+
+void
+darwin_enter_string_into_cfstring_table (tree str)
+{
+  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;
+    }
+}
+
 #include "gt-darwin.h"
Index: gcc/config/darwin-sections.def
===================================================================
--- gcc/config/darwin-sections.def	(revision 165817)
+++ 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 165817)
+++ gcc/config/darwin.h	(working copy)
@@ -1054,6 +1054,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