Hi, The PR is a(nother) bad interaction between [Darwin/NeXT] ObjC meta-data and LTO.
(for the NeXT runtime) the compiler emits a small block of meta-data "ImageInfo" that conveys to the run-time whether the User had enabled fix-and-continue or objc-gc. Since these data are anonymous (the run time finds these data by examining the sections) when we have multiple files, and LTO, we end up with multiple copies of the metadata - which get concatenated. This is correct behaviour - LTO-wise, but wrong behaviour run-time wise; when presented with multiple objects, the linker normally processes the input copies and produces just one output. It now complains that that specific meta-data section is too large (we've always been emitting the wrong data, but only picked up on this when the system linker became more picky). We can't make the section merge-able, or comdat - the first won't work if multiple inputs have differing flags, and the second isn't correct section flags for the runtime. --- Fortunately, the content of the particular meta-data section only depends on command line switches; Further, these should be the switches in force when the back end runs - and thus should be the switches on the LTO command line. So the fix proposed does this: (i) removes the generation of this meta-data from the ObjC FE. (ii) make LTO recognise the relevant c/l switches. (iii) detect the presence of ObjC/ObjC++ [classes or other metadata] during code-gen. (iv) When objc is detected emit the ImageInfo section from the backend. I did think that there should perhaps be some consideration of keeping the flags and merging them in LTO. However, I don't think we need to do this with the current code-gen. There is also evidence that this capability is "going away" in modern Darwin/OSX versions. In any event, this is an incremental improvement, fixing the cases we see at present; preserving and checking flags in LTO would be an enhancement that could be provided if it proves necessary. OK for trunk, and open branches? (wrong code). Iain gcc/c-family: * c.opt (fgnu-runtime, fnext-runtime, fobjc-abi-version, fobjc-gc, freplace-objc-classes): Accept for LTO. gcc: * config/darwin.c (darwin_objc2_section): Note if ObjC Metadata is seen. (darwin_objc1_section): Likewise. (darwin_file_end): Emit Image Info section when required. gcc/objc: * objc-next-runtime-abi-01.c (generate_objc_image_info): Remove. (objc_generate_v1_next_metadata): Remove generation of ImageInfo. * objc-next-runtime-abi-02.c (generate_v2_objc_image_info): Remove. (objc_generate_v2_next_metadata): Remove generation of ImageInfo.
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 9690a08..b2c5c03 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -941,7 +941,7 @@ C++ ObjC++ Var(flag_no_gnu_keywords, 0) Recognize GNU-defined keywords fgnu-runtime -ObjC ObjC++ Report RejectNegative Var(flag_next_runtime,0) Init(NEXT_OBJC_RUNTIME) +ObjC ObjC++ LTO Report RejectNegative Var(flag_next_runtime,0) Init(NEXT_OBJC_RUNTIME) Generate code for GNU runtime environment fgnu89-inline @@ -1015,7 +1015,7 @@ fnew-abi C++ ObjC++ Ignore Warn(switch %qs is no longer supported) fnext-runtime -ObjC ObjC++ Report RejectNegative Var(flag_next_runtime) +ObjC ObjC++ LTO Report RejectNegative Var(flag_next_runtime) Generate code for NeXT (Apple Mac OS X) runtime environment fnil-receivers @@ -1033,7 +1033,7 @@ C++ ObjC++ Optimization Var(flag_nothrow_opt) Treat a throw() exception specification as noexcept to improve code size fobjc-abi-version= -ObjC ObjC++ Joined Report RejectNegative UInteger Var(flag_objc_abi) +ObjC ObjC++ LTO Joined Report RejectNegative UInteger Var(flag_objc_abi) Specify which ABI to use for Objective-C family code and meta-data generation. ; Generate special '- .cxx_construct' and '- .cxx_destruct' methods @@ -1053,7 +1053,7 @@ ObjC ObjC++ Var(flag_objc_exceptions) Enable Objective-C exception and synchronization syntax fobjc-gc -ObjC ObjC++ Var(flag_objc_gc) +ObjC ObjC++ LTO Var(flag_objc_gc) Enable garbage collection (GC) in Objective-C/Objective-C++ programs fobjc-nilcheck @@ -1113,7 +1113,7 @@ C++ ObjC++ Var(flag_pretty_templates) Init(1) -fno-pretty-templates Do not pretty-print template specializations as the template signature followed by the arguments freplace-objc-classes -ObjC ObjC++ Var(flag_replace_objc_classes) +ObjC ObjC++ LTO Var(flag_replace_objc_classes) Used in Fix-and-Continue mode to indicate that object files may be swapped in at runtime frepo diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index e07fa4c..d470003 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -1329,6 +1329,9 @@ is_objc_metadata (tree decl) return NULL_TREE; } +static int classes_seen; +static int objc_metadata_seen; + /* Return the section required for Objective C ABI 2 metadata. */ static section * darwin_objc2_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base) @@ -1338,12 +1341,9 @@ darwin_objc2_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base) gcc_assert (TREE_CODE (ident) == IDENTIFIER_NODE); p = IDENTIFIER_POINTER (ident); - /* If we are in LTO, then we don't know the state of flag_next_runtime - or flag_objc_abi when the code was generated. We set these from the - meta-data - which is needed to deal with const string constructors. */ + gcc_checking_assert (flag_next_runtime == 1 && flag_objc_abi == 2); - flag_next_runtime = 1; - flag_objc_abi = 2; + objc_metadata_seen = 1; if (base == data_section) base = darwin_sections[objc2_metadata_section]; @@ -1366,7 +1366,10 @@ darwin_objc2_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base) else if (!strncmp (p, "V2_NLCL", 7)) return darwin_sections[objc2_nonlazy_class_section]; else if (!strncmp (p, "V2_CLAB", 7)) - return darwin_sections[objc2_classlist_section]; + { + classes_seen = 1; + return darwin_sections[objc2_classlist_section]; + } else if (!strncmp (p, "V2_SRFS", 7)) return darwin_sections[objc2_selector_refs_section]; else if (!strncmp (p, "V2_NLCA", 7)) @@ -1401,12 +1404,9 @@ darwin_objc1_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base) gcc_assert (TREE_CODE (ident) == IDENTIFIER_NODE); p = IDENTIFIER_POINTER (ident); - /* If we are in LTO, then we don't know the state of flag_next_runtime - or flag_objc_abi when the code was generated. We set these from the - meta-data - which is needed to deal with const string constructors. */ - flag_next_runtime = 1; - if (!global_options_set.x_flag_objc_abi) - flag_objc_abi = 1; + gcc_checking_assert (flag_next_runtime == 1 && flag_objc_abi < 2); + + objc_metadata_seen = 1; /* String sections first, cos there are lots of strings. */ if (!strncmp (p, "V1_STRG", 7)) @@ -1419,7 +1419,10 @@ darwin_objc1_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base) return darwin_sections[objc_meth_var_types_section]; else if (!strncmp (p, "V1_CLAS", 7)) - return darwin_sections[objc_class_section]; + { + classes_seen = 1; + return darwin_sections[objc_class_section]; + } else if (!strncmp (p, "V1_META", 7)) return darwin_sections[objc_meta_class_section]; else if (!strncmp (p, "V1_CATG", 7)) @@ -1603,8 +1606,6 @@ machopic_select_section (tree decl, if (TREE_CODE (name) == TYPE_DECL) name = DECL_NAME (name); - /* FIXME: This is unsatisfactory for LTO, since it relies on other - metadata determining the source FE. */ if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_ObjCString")) { if (flag_next_runtime) @@ -2845,6 +2846,33 @@ darwin_file_end (void) finalize_ctors (); if (!vec_safe_is_empty (dtors)) finalize_dtors (); + + /* If we are expecting to output NeXT ObjC meta-data, (and we actually see + some) then we output the fix-and-continue marker (Image Info). + This applies to Objective C, Objective C++ and LTO with either language + as part of the input. */ + if (flag_next_runtime && objc_metadata_seen) + { + unsigned int flags = 0; + if (flag_objc_abi >= 2) + { + flags = 16; + output_section_asm_op + (darwin_sections[objc2_image_info_section]->unnamed.data); + } + else + output_section_asm_op + (darwin_sections[objc_image_info_section]->unnamed.data); + + ASM_OUTPUT_ALIGN (asm_out_file, 2); + fputs ("L_OBJC_ImageInfo:\n", asm_out_file); + + flags |= (flag_replace_objc_classes && classes_seen) ? 1 : 0; + flags |= flag_objc_gc ? 2 : 0; + + fprintf (asm_out_file, "\t.long\t0\n\t.long\t%u\n", flags); + } + machopic_finish (asm_out_file); if (strcmp (lang_hooks.name, "GNU C++") == 0) { diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c index 27ba615..000256d 100644 --- a/gcc/objc/objc-next-runtime-abi-01.c +++ b/gcc/objc/objc-next-runtime-abi-01.c @@ -2332,36 +2332,6 @@ generate_classref_translation_entry (tree chain) return; } - -/* The Fix-and-Continue functionality available in Mac OS X 10.3 and - later requires that ObjC translation units participating in F&C be - specially marked. The following routine accomplishes this. */ - -/* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */ - -static void -generate_objc_image_info (void) -{ - tree decl; - int flags - = ((flag_replace_objc_classes && imp_count ? 1 : 0) - | (flag_objc_gc ? 2 : 0)); - vec<constructor_elt, va_gc> *v = NULL; - tree array_type; - - array_type = build_sized_array_type (integer_type_node, 2); - - decl = start_var_decl (array_type, "_OBJC_ImageInfo"); - - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node); - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, flags)); - /* The runtime wants this and refers to it in a manner hidden from the compiler. - So we must force the output. */ - DECL_PRESERVE_P (decl) = 1; - OBJCMETA (decl, objc_meta, meta_info); - finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v)); -} - static void objc_generate_v1_next_metadata (void) { @@ -2412,9 +2382,6 @@ objc_generate_v1_next_metadata (void) attr = build_tree_list (objc_meta, meta_modules); build_module_descriptor (vers, attr); - /* This conveys information on GC usage and zero-link. */ - generate_objc_image_info (); - /* Dump the class references. This forces the appropriate classes to be linked into the executable image, preserving unix archive semantics. */ diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c index 4bb02c7..0960006 100644 --- a/gcc/objc/objc-next-runtime-abi-02.c +++ b/gcc/objc/objc-next-runtime-abi-02.c @@ -3331,31 +3331,6 @@ build_v2_ivar_offset_ref_table (void) finish_var_decl (ref->decl, ref->offset); } -/* static int _OBJC_IMAGE_INFO[2] = { 0, 16 | flags }; */ - -static void -generate_v2_objc_image_info (void) -{ - tree decl, array_type; - vec<constructor_elt, va_gc> *v = NULL; - int flags = - ((flag_replace_objc_classes && imp_count ? 1 : 0) - | (flag_objc_gc ? 2 : 0)); - - flags |= 16; - - array_type = build_sized_array_type (integer_type_node, 2); - - decl = start_var_decl (array_type, "_OBJC_ImageInfo"); - - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node); - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, flags)); - /* The Runtime wants this. */ - DECL_PRESERVE_P (decl) = 1; - OBJCMETA (decl, objc_meta, meta_info); - finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v)); -} - static void objc_generate_v2_next_metadata (void) { @@ -3407,9 +3382,6 @@ objc_generate_v2_next_metadata (void) build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$", meta_label_nonlazy_categorylist); - /* This conveys information on GC usage and zero-link. */ - generate_v2_objc_image_info (); - /* Generate catch objects for eh, if any are needed. */ build_v2_eh_catch_objects ();