From patchwork Fri Oct 22 10:37:42 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Sandoe X-Patchwork-Id: 68832 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 71A73B6F11 for ; Fri, 22 Oct 2010 21:38:20 +1100 (EST) Received: (qmail 5108 invoked by alias); 22 Oct 2010 10:38:18 -0000 Received: (qmail 5086 invoked by uid 22791); 22 Oct 2010 10:38:14 -0000 X-SWARE-Spam-Status: No, hits=-1.1 required=5.0 tests=AWL, BAYES_00, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, TW_BJ, TW_TR X-Spam-Check-By: sourceware.org Received: from c2beaomr08.btconnect.com (HELO mail.btconnect.com) (213.123.26.186) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 22 Oct 2010 10:38:01 +0000 Received: from host81-138-1-83.in-addr.btopenworld.com (EHLO thor.office) ([81.138.1.83]) by c2beaomr08.btconnect.com with ESMTP id AJG73058; Fri, 22 Oct 2010 11:37:57 +0100 (BST) Cc: Mike Stump , Richard Guenther , Paolo Bonzini , Nicola Pero , Mike Stump Message-Id: From: IainS To: GCC Patches In-Reply-To: Mime-Version: 1.0 (Apple Message framework v936) Subject: Re: re-jigged for lang independence, Re: [Patch, Darwin, c*, ObjC* 1/2] Implement Darwin CFStrings. Date: Fri, 22 Oct 2010 11:37:42 +0100 References: <6C7293F5-4069-43D4-9980-182F81914800@sandoe-acoustics.co.uk> <857065FB-21E8-4C1C-B7F6-66515F515BFD@sandoe-acoustics.co.uk> X-Mirapoint-IP-Reputation: reputation=Fair-1, source=Queried, refid=tid=0001.0A0B0302.4CC1697E.0068, actions=tag X-Junkmail-Signature-Raw: score=unknown, refid=str=0001.0A0B0203.4CC16986.0232, ss=1, fgs=0, ip=0.0.0.0, so=2010-07-22 22:03:31, dmn=2009-09-10 00:05:08, mode=single engine X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org On 20 Oct 2010, at 09:48, Richard Guenther wrote: > On Tue, Oct 19, 2010 at 7:14 PM, IainS > 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 Index: gcc/ChangeLog =================================================================== --- gcc/ChangeLog (revision 165817) +++ gcc/ChangeLog (working copy) @@ -1,3 +1,37 @@ +2010-10-21 Iain Sandoe + + 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 * 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 + + 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 * 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 + + 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 * 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 ; . +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