From patchwork Fri Jul 2 19:19:03 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Sandoe X-Patchwork-Id: 57754 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 DFD6A1007D2 for ; Sat, 3 Jul 2010 05:19:46 +1000 (EST) Received: (qmail 24095 invoked by alias); 2 Jul 2010 19:19:43 -0000 Received: (qmail 24062 invoked by uid 22791); 2 Jul 2010 19:19:39 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, TW_BJ X-Spam-Check-By: sourceware.org Received: from c2beaomr03.btconnect.com (HELO c2beaomr03.btconnect.com) (213.123.26.181) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 02 Jul 2010 19:19:30 +0000 Received: from thor.office (host81-138-1-83.in-addr.btopenworld.com [81.138.1.83]) by c2beaomr03.btconnect.com with ESMTP id MDU46591; Fri, 2 Jul 2010 20:19:04 +0100 (BST) X-Mirapoint-IP-Reputation: reputation=Fair-1, source=Queried, refid=0001.0A0B0302.4C2E3BA8.0045, actions=tag Message-Id: <076D2894-5E9C-4021-92A1-1987D2B7E04A@sandoe-acoustics.co.uk> From: IainS To: GCC Patches Mime-Version: 1.0 (Apple Message framework v936) Subject: [Patch, objc] maintenance, make Obj{C,C++} LTO-friendly. Date: Fri, 2 Jul 2010 20:19:03 +0100 Cc: mrs@gcc.gnu.org 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 This patch is intended to maintain the 'status-quo' in the presence of LTO. In fact, it is a general step forward in that I have identified the reason that 'blanket' application of DECL_PRESERVE_P was required and got rid of that. There are places that I intended to round things out a bit more before posting - but we are going to have major patch collisions with Nathan's work and with resources being so limited, it seems better to move forward in smaller steps - rather than spend all the time counteracting bit-rot. It's best viewed as general maintenance - with the side-effect that LTO now works - so there's one fewer barriers to enabling that by default on Darwin. This has been tested on: powerpc*-apple-darwin{8,9} i686-apple-darwin9, x86_64-apple- darwin10, ?86*-unknown-linux-gnu, cris-elf (sim), s390x (compile only), mipsisa64-elf(sim), armel-linux-eabi(compile-only). OK for trunk? Iain objc/ChangeLog: PR objc/44140 * objc-act.c: build_objc_string_decl() remove declaration. (finish_var_decl): Remove forcing of var output and indiscriminate ,marking as "Used". (init_objc_symtab): Use integer_zero_node. Use short_integer_type_node for the counts. (generate_objc_symtab_decl): Remove call to forward_declare_categories(). Attatch the correct section designation to the symtab. (init_module_descriptor): Make the filename "N/A" instead of "". Use integer_zero_node instead of building each time. DECL_PRESERVE_P this item. (diagnose_missing_method): New. (build_next_selector_translation_table): New. (build_gnu_selector_translation_table): New. (add_objc_string): Incorporate the code from build_objc_string_decl. (build_objc_string_decl): Remove. (objc_declare_alias): Use integer_zero_node. (generate_category): Pass in the current class/category entry. Ensure that we finish the variables we originally started, and keep them so that they are emitted. (generate_shared_structures): Pass in the current class/ category entry. Ensure that we finish the variables we originally started so that they are output. (finish_objc): Reorder code so that we finish variables before referencing them. Save the global data before calling meta-daat creation routines, and pass the current reference to the two main routines. (generate_classref_translation_entry): DECL_PRESERVE_P this item it is needed by the runtime. (handle_class_ref): Use finish_var() mark items as DECL_PRESERVE_P where they are needed by the runtime. (handle_impent): Use finish_var() mark items as DECL_PRESERVE_P where they are needed by the runtime. (generate_objc_image_info): Use integer_zero_node, attatch the correct section info. DECL_PRESERVE_P, this is needed by the runtime. testsuite/Changelog: PR objc/44140 objc.dg/lto: New. objc.dg/lto/trivial-1_0.m: New. objc.dg/lto/lto.exp: New. obj-c++.dg/lto: New. obj-c++.dg/lto/trivial-1_0.mm: New. obj-c++.dg/lto/lto.exp: New. Index: gcc/objc/objc-act.c =================================================================== --- gcc/objc/objc-act.c (revision 161726) +++ gcc/objc/objc-act.c (working copy) @@ -214,7 +214,6 @@ enum string_section }; static tree add_objc_string (tree, enum string_section); -static tree build_objc_string_decl (enum string_section); static void build_selector_table_decl (void); /* Protocol additions. */ @@ -1525,14 +1524,6 @@ static void finish_var_decl (tree var, tree initializer) { finish_decl (var, input_location, initializer, NULL_TREE, NULL_TREE); - /* Ensure that the variable actually gets output. */ - mark_decl_referenced (var); - /* Mark the decl to avoid "defined but not used" warning. */ - TREE_USED (var) = 1; - DECL_READ_P (var) = 1; - /* We reserve the right for the runtime to use/modify these variables - in ways that are opaque to us. */ - DECL_PRESERVE_P (var) = 1; } /* Find the decl for the constant string class reference. This is only @@ -2183,7 +2174,7 @@ init_def_list (tree type) expr = build_unary_op (input_location, ADDR_EXPR, static_instances_decl, 0); else - expr = build_int_cst (NULL_TREE, 0); + expr = integer_zero_node; CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); } @@ -2206,7 +2197,9 @@ init_objc_symtab (tree type) /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */ if (flag_next_runtime || ! sel_ref_chain) - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert ( + build_pointer_type (objc_selector_type), + integer_zero_node)); else { tree expr = build_unary_op (input_location, ADDR_EXPR, @@ -2219,11 +2212,13 @@ init_objc_symtab (tree type) /* cls_def_cnt = { ..., 5, ... } */ - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, imp_count)); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, + build_int_cst (short_integer_type_node, imp_count)); /* cat_def_cnt = { ..., 5, ... } */ - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, cat_count)); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, + build_int_cst (short_integer_type_node, cat_count)); /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */ @@ -2284,12 +2279,15 @@ forward_declare_categories (void) static void generate_objc_symtab_decl (void) { - /* forward declare categories */ - if (cat_count) - forward_declare_categories (); - + build_objc_symtab_template (); UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS"); + TREE_CONSTANT (UOBJC_SYMBOLS_decl) = 1; + if (flag_next_runtime) + { + tree sect = my_build_string (16, "__OBJC,__symbols"); + DECL_SECTION_NAME (UOBJC_SYMBOLS_decl) = sect; + } finish_var_decl (UOBJC_SYMBOLS_decl, init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl))); } @@ -2314,7 +2312,7 @@ init_module_descriptor (tree type) /* Don't provide any file name for security reasons. */ /* name = { ..., "", ... } */ - expr = add_objc_string (get_identifier (""), class_names); + expr = add_objc_string (get_identifier ("N/A"), class_names); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); /* symtab = { ..., _OBJC_SYMBOLS, ... } */ @@ -2323,7 +2321,7 @@ init_module_descriptor (tree type) expr = build_unary_op (input_location, ADDR_EXPR, UOBJC_SYMBOLS_decl, 0); else - expr = build_int_cst (NULL_TREE, 0); + expr = integer_zero_node; CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); return objc_build_constructor (type, v); @@ -2368,6 +2366,9 @@ build_module_descriptor (void) /* Create an instance of "_objc_module". */ UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_MODULES"); + /* This is the root of the metadata for defined classes and categories, it + is referenced by the runtime and, therefore, needed. */ + DECL_PRESERVE_P (UOBJC_MODULES_decl) = 1; finish_var_decl (UOBJC_MODULES_decl, init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl))); @@ -2491,7 +2492,7 @@ generate_static_references (void) VEC(constructor_elt,gc) *decls = NULL; if (flag_next_runtime) - abort (); + gcc_unreachable (); for (cl_chain = objc_static_instances, num_class = 0; cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++) @@ -2575,12 +2576,65 @@ build_selector (tree ident) add_objc_string (ident, meth_var_names)); } +/* Used only by build_*_selector_translation_table (). */ static void -build_selector_translation_table (void) +diagnose_missing_method (tree meth, location_t here) { + tree method_chain; + bool found = false; + for (method_chain = meth_var_names_chain; + method_chain; + method_chain = TREE_CHAIN (method_chain)) + { + if (TREE_VALUE (method_chain) == meth) + { + found = true; + break; + } + } + + if (!found) + warning_at (here, 0, "creating selector for nonexistent method %qE", + meth); +} + +static void +build_next_selector_translation_table (void) +{ tree chain; - int offset = 0; - tree decl = NULL_TREE; + for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain)) + { + tree expr; + tree decl = TREE_PURPOSE (chain); + if (warn_selector && objc_implementation_context) + { + location_t loc; + if (decl) + loc = DECL_SOURCE_LOCATION (decl); + else + loc = input_location; + diagnose_missing_method (TREE_VALUE (chain), loc); + } + + expr = build_selector (TREE_VALUE (chain)); + + if (decl) + { + /* Entries of this form are used for references to methods. + The runtime re-writes these one start-up but the FE can't see + that and optimizes it away unless we force it. */ + DECL_PRESERVE_P (decl) = 1; + finish_var_decl (decl, expr); + } + } +} + +static void +build_gnu_selector_translation_table (void) +{ + tree chain; +/* int offset = 0; + tree decl = NULL_TREE;*/ VEC(constructor_elt,gc) *inits = NULL; for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain)) @@ -2588,42 +2642,13 @@ static void tree expr; if (warn_selector && objc_implementation_context) - { - tree method_chain; - bool found = false; - for (method_chain = meth_var_names_chain; - method_chain; - method_chain = TREE_CHAIN (method_chain)) - { - if (TREE_VALUE (method_chain) == TREE_VALUE (chain)) - { - found = true; - break; - } - } - if (!found) - { - location_t loc; - if (flag_next_runtime && TREE_PURPOSE (chain)) - loc = DECL_SOURCE_LOCATION (TREE_PURPOSE (chain)); - else - loc = input_location; - warning_at (loc, 0, "creating selector for nonexistent method %qE", - TREE_VALUE (chain)); - } - } + diagnose_missing_method (TREE_VALUE (chain), input_location); expr = build_selector (TREE_VALUE (chain)); - /* add one for the '\0' character */ - offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1; + /* add one for the '\0' character + offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;*/ - if (flag_next_runtime) { - decl = TREE_PURPOSE (chain); - finish_var_decl (decl, expr); - } - else - { if (flag_typed_selectors) { VEC(constructor_elt,gc) *v = NULL; @@ -2635,9 +2660,8 @@ static void CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); } - } + } /* each element in the chain */ - if (! flag_next_runtime) { /* Cause the selector table (previously forward-declared) to be actually output. */ @@ -2646,12 +2670,12 @@ static void if (flag_typed_selectors) { VEC(constructor_elt,gc) *v = NULL; - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node); expr = objc_build_constructor (objc_selector_template, v); } else - expr = build_int_cst (NULL_TREE, 0); + expr = integer_zero_node; CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); expr = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl), @@ -2855,19 +2879,34 @@ objc_get_class_reference (tree ident) /* For each string section we have a chain which maps identifier nodes to decls for the strings. */ +static GTY(()) int class_names_idx; +static GTY(()) int meth_var_names_idx; +static GTY(()) int meth_var_types_idx; + static tree add_objc_string (tree ident, enum string_section section) { - tree *chain, decl, type, string_expr; - + tree *chain, decl, type, string_expr, namefromsect; + char buf[256]; + + buf[0] = 0; if (section == class_names) - chain = &class_names_chain; + { + chain = &class_names_chain; + sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++); + } else if (section == meth_var_names) - chain = &meth_var_names_chain; + { + chain = &meth_var_names_chain; + sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++); + } else if (section == meth_var_types) - chain = &meth_var_types_chain; + { + chain = &meth_var_types_chain; + sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++); + } else - abort (); + gcc_unreachable (); while (*chain) { @@ -2879,14 +2918,15 @@ add_objc_string (tree ident, enum string_section s chain = &TREE_CHAIN (*chain); } - decl = build_objc_string_decl (section); + namefromsect = get_identifier (buf); type = build_array_type (char_type_node, build_index_type (build_int_cst (NULL_TREE, IDENTIFIER_LENGTH (ident)))); - decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl))); + decl = start_var_decl (type, IDENTIFIER_POINTER (namefromsect)); + TREE_CONSTANT (decl) = 1; string_expr = my_build_string (IDENTIFIER_LENGTH (ident) + 1, IDENTIFIER_POINTER (ident)); finish_var_decl (decl, string_expr); @@ -2897,44 +2937,6 @@ add_objc_string (tree ident, enum string_section s ADDR_EXPR, decl, 1)); } -static GTY(()) int class_names_idx; -static GTY(()) int meth_var_names_idx; -static GTY(()) int meth_var_types_idx; - -static tree -build_objc_string_decl (enum string_section section) -{ - tree decl, ident; - char buf[256]; - - if (section == class_names) - sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++); - else if (section == meth_var_names) - sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++); - else if (section == meth_var_types) - sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++); - - ident = get_identifier (buf); - - decl = build_decl (input_location, - VAR_DECL, ident, build_array_type (char_type_node, 0)); - DECL_EXTERNAL (decl) = 1; - TREE_PUBLIC (decl) = 0; - TREE_USED (decl) = 1; - TREE_CONSTANT (decl) = 1; - DECL_CONTEXT (decl) = 0; - DECL_ARTIFICIAL (decl) = 1; -#ifdef OBJCPLUS - DECL_THIS_STATIC (decl) = 1; /* squash redeclaration errors */ -#endif - - make_decl_rtl (decl); - pushdecl_top_level (decl); - - return decl; -} - - void objc_declare_alias (tree alias_ident, tree class_ident) { @@ -5418,7 +5420,7 @@ generate_dispatch_table (tree type, const char *na decl = start_var_decl (type, synth_id_with_class_suffix (name, objc_implementation_context)); - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size)); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, list); @@ -5744,12 +5746,16 @@ lookup_category (tree klass, tree cat_name) /* static struct objc_category _OBJC_CATEGORY_ = { ... }; */ static void -generate_category (tree cat) +generate_category (struct imp_entry *impent) { - tree decl; tree initlist, cat_name_expr, class_name_expr; tree protocol_decl, category; + tree cat = impent->imp_context; + implementation_template = impent->imp_template; + UOBJC_CLASS_decl = impent->class_decl; + UOBJC_METACLASS_decl = impent->meta_decl; + add_class_reference (CLASS_NAME (cat)); cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names); @@ -5766,30 +5772,32 @@ static void else protocol_decl = 0; - decl = start_var_decl (objc_category_template, - synth_id_with_class_suffix - ("_OBJC_CATEGORY", objc_implementation_context)); - - initlist = build_category_initializer (TREE_TYPE (decl), + initlist = build_category_initializer (TREE_TYPE (UOBJC_CLASS_decl), cat_name_expr, class_name_expr, UOBJC_INSTANCE_METHODS_decl, UOBJC_CLASS_METHODS_decl, protocol_decl); - - finish_var_decl (decl, initlist); + /* Finish and initialize the forward decl. */ + finish_var_decl (UOBJC_CLASS_decl, initlist); } /* static struct objc_class _OBJC_METACLASS_Foo={ ... }; static struct objc_class _OBJC_CLASS_Foo={ ... }; */ static void -generate_shared_structures (int cls_flags) +generate_shared_structures (struct imp_entry *impent) { - tree decl; tree name_expr, super_expr, root_expr; - tree my_root_id = NULL_TREE, my_super_id = NULL_TREE; + tree my_root_id, my_super_id; tree cast_type, initlist, protocol_decl; - + int cls_flags; + + objc_implementation_context = impent->imp_context; + implementation_template = impent->imp_template; + UOBJC_CLASS_decl = impent->class_decl; + UOBJC_METACLASS_decl = impent->meta_decl; + cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS : 0 ; + my_super_id = CLASS_SUPER_NAME (implementation_template); if (my_super_id) { @@ -5820,13 +5828,12 @@ static void /* Install class `isa' and `super' pointers at runtime. */ if (my_super_id) - { - super_expr = add_objc_string (my_super_id, class_names); - super_expr = build_c_cast (input_location, + super_expr = add_objc_string (my_super_id, class_names); + else + super_expr = integer_zero_node; + + super_expr = build_c_cast (input_location, cast_type, super_expr); /* cast! */ - } - else - super_expr = build_int_cst (NULL_TREE, 0); root_expr = add_objc_string (my_root_id, class_names); root_expr = build_c_cast (input_location, cast_type, root_expr); /* cast! */ @@ -5842,13 +5849,9 @@ static void /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */ - decl = start_var_decl (objc_class_template, - IDENTIFIER_POINTER - (DECL_NAME (UOBJC_METACLASS_decl))); - initlist = build_shared_structure_initializer - (TREE_TYPE (decl), + (TREE_TYPE (UOBJC_METACLASS_decl), root_expr, super_expr, name_expr, convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)), 2 /*CLS_META*/, @@ -5856,17 +5859,13 @@ static void UOBJC_CLASS_VARIABLES_decl, protocol_decl); - finish_var_decl (decl, initlist); + finish_var_decl (UOBJC_METACLASS_decl, initlist); /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */ - decl = start_var_decl (objc_class_template, - IDENTIFIER_POINTER - (DECL_NAME (UOBJC_CLASS_decl))); - initlist = build_shared_structure_initializer - (TREE_TYPE (decl), + (TREE_TYPE (UOBJC_CLASS_decl), build_unary_op (input_location, ADDR_EXPR, UOBJC_METACLASS_decl, 0), super_expr, name_expr, convert (integer_type_node, @@ -5877,7 +5876,7 @@ static void UOBJC_INSTANCE_VARIABLES_decl, protocol_decl); - finish_var_decl (decl, initlist); + finish_var_decl (UOBJC_CLASS_decl, initlist); } @@ -9262,15 +9261,17 @@ finish_objc (void) if (objc_static_instances) generate_static_references (); - if (imp_list || class_names_chain - || meth_var_names_chain || meth_var_types_chain || sel_ref_chain) - generate_objc_symtab_decl (); + /* forward declare categories */ + if (cat_count) + forward_declare_categories (); for (impent = imp_list; impent; impent = impent->next) { objc_implementation_context = impent->imp_context; implementation_template = impent->imp_template; + /* FIXME: This needs reworking to be more obvious. */ + UOBJC_CLASS_decl = impent->class_decl; UOBJC_METACLASS_decl = impent->meta_decl; @@ -9288,28 +9289,35 @@ finish_objc (void) /* all of the following reference the string pool... */ generate_ivar_lists (); generate_dispatch_tables (); - generate_shared_structures (impent->has_cxx_cdtors - ? CLS_HAS_CXX_STRUCTORS - : 0); + generate_shared_structures (impent); } else { generate_dispatch_tables (); - generate_category (objc_implementation_context); + generate_category (impent); } + + impent->class_decl = UOBJC_CLASS_decl; + impent->meta_decl = UOBJC_METACLASS_decl; } /* If we are using an array of selectors, we must always finish up the array decl even if no selectors were used. */ - if (! flag_next_runtime || sel_ref_chain) - build_selector_translation_table (); + if (flag_next_runtime) + build_next_selector_translation_table (); + else + build_gnu_selector_translation_table (); if (protocol_chain) generate_protocols (); - if ((flag_replace_objc_classes && imp_list) || flag_objc_gc) + if (flag_next_runtime) generate_objc_image_info (); + if (imp_list || class_names_chain + || meth_var_names_chain || meth_var_types_chain || sel_ref_chain) + generate_objc_symtab_decl (); + /* Arrange for ObjC data structures to be initialized at run time. */ if (objc_implementation_context || class_names_chain || objc_static_instances || meth_var_names_chain || meth_var_types_chain || sel_ref_chain) @@ -9368,8 +9376,9 @@ generate_classref_translation_entry (tree chain) expr = add_objc_string (TREE_VALUE (chain), class_names); expr = convert (type, expr); /* cast! */ - /* The decl that is the one that we - forward declared in build_class_reference. */ + /* This is a class reference. It is re-written by the runtime, + but will be optimized away unless we force it. */ + DECL_PRESERVE_P (decl) = 1; finish_var_decl (decl, expr); return; } @@ -9395,12 +9404,11 @@ handle_class_ref (tree chain) /* Make a decl for this name, so we can use its address in a tree. */ decl = build_decl (input_location, - VAR_DECL, get_identifier (string), char_type_node); + VAR_DECL, get_identifier (string), TREE_TYPE (integer_zero_node)); DECL_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; - pushdecl (decl); - rest_of_decl_compilation (decl, 0, 0); + finish_var_decl (decl, 0); /* Make a decl for the address. */ sprintf (string, "%sobjc_class_ref_%s", @@ -9408,15 +9416,17 @@ handle_class_ref (tree chain) exp = build1 (ADDR_EXPR, string_type_node, decl); decl = build_decl (input_location, VAR_DECL, get_identifier (string), string_type_node); - DECL_INITIAL (decl) = exp; TREE_STATIC (decl) = 1; TREE_USED (decl) = 1; DECL_READ_P (decl) = 1; - /* Force the output of the decl as this forces the reference of the class. */ - mark_decl_referenced (decl); + DECL_ARTIFICIAL (decl) = 1; + DECL_INITIAL (decl) = error_mark_node; + + /* We must force the reference. */ + DECL_PRESERVE_P (decl) = 1; pushdecl (decl); - rest_of_decl_compilation (decl, 0, 0); + finish_var_decl (decl, exp); } static void @@ -9467,17 +9477,21 @@ handle_impent (struct imp_entry *impent) { tree decl, init; - init = build_int_cst (c_common_type_for_size (BITS_PER_WORD, 1), 0); + init = integer_zero_node; decl = build_decl (input_location, VAR_DECL, get_identifier (string), TREE_TYPE (init)); TREE_PUBLIC (decl) = 1; TREE_READONLY (decl) = 1; TREE_USED (decl) = 1; TREE_CONSTANT (decl) = 1; - DECL_CONTEXT (decl) = 0; + DECL_CONTEXT (decl) = NULL_TREE; DECL_ARTIFICIAL (decl) = 1; - DECL_INITIAL (decl) = init; - assemble_variable (decl, 1, 0, 0); + TREE_STATIC (decl) = 1; + DECL_INITIAL (decl) = error_mark_node; /* A real initializer is coming... */ + /* We must force the reference. */ + DECL_PRESERVE_P (decl) = 1; + + finish_var_decl(decl, init) ; } } @@ -9501,9 +9515,16 @@ generate_objc_image_info (void) build_index_type (build_int_cst (NULL_TREE, 2 - 1))), "_OBJC_IMAGE_INFO"); - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags)); + if (flag_next_runtime) + { + tree sect = my_build_string (44, + "__OBJC,__image_info,regular,no_dead_strip"); + DECL_SECTION_NAME (decl) = sect; + } + DECL_PRESERVE_P (decl) = 1; finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v)); } Index: gcc/testsuite/objc.dg/lto/trivial-1_0.m =================================================================== --- gcc/testsuite/objc.dg/lto/trivial-1_0.m (revision 0) +++ gcc/testsuite/objc.dg/lto/trivial-1_0.m (revision 0) @@ -0,0 +1,37 @@ +/* { dg-lto-do run } */ +/* { dg-skip-if "" { "*-*-darwin*" && lp64 } { "*" } { "" } } */ +extern int printf (char *,...) ; + +typedef struct objc_class *Class; + +struct objc_class { + Class isa; + /* other stuff... */ +} ; + +@interface myRootObject { +@public + Class isa; +} ++initialize; ++(Class)class; + +@end + +@implementation myRootObject ++initialize { + return self; +} + ++(Class)class { + return (Class)self; +} + +@end + +int main(void) +{ + [myRootObject class]; + printf("trivial OK\n"); + return 0; +} Index: gcc/testsuite/objc.dg/lto/lto.exp =================================================================== --- gcc/testsuite/objc.dg/lto/lto.exp (revision 0) +++ gcc/testsuite/objc.dg/lto/lto.exp (revision 0) @@ -0,0 +1,84 @@ +# Copyright (C) 2010 Free Software Foundation, Inc. + +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 +# . +# +# Based on gcc/testsuite/gcc.dg/lto/lto.exp. + +# Test link-time optimization across multiple files. +# +# Programs are broken into multiple files. Each one is compiled +# separately with LTO information. The final executable is generated +# by collecting all the generated object files using regular LTO or WHOPR. + +if $tracelevel then { + strace $tracelevel +} + +# Load procedures from common libraries. +load_lib standard.exp +load_lib objc-dg.exp + +# Load the language-independent compabibility support procedures. +load_lib lto.exp + +# If LTO has not been enabled, bail. +if { ![check_effective_target_lto] } { + return +} + +global LTO_OPTIONS + +set LTO_OPTIONS [list \ + {-O0 -fwhopr -fgnu-runtime} \ + {-O2 -fwhopr -fgnu-runtime} \ + {-O0 -flto -fgnu-runtime} \ + {-O2 -flto -fgnu-runtime} \ +] + +objc_init +lto_init no-mathlib + +# Define an identifier for use with this suite to avoid name conflicts +# with other lto tests running at the same time. +set sid "objc_lto" +set tests [lsort [glob -nocomplain $srcdir/$subdir/*_0.m]] + +# Main loop. +foreach src $tests { + # If we're only testing specific files and this isn't one of them, skip it. + if ![runtest_file_p $runtests $src] then { + continue + } + lto-execute $src $sid +} + +# darwin targets can also run code with the NeXT runtime. +if [istarget "*-*-darwin*" ] { +set LTO_OPTIONS [list \ + {-O0 -fwhopr -fnext-runtime} \ + {-O2 -fwhopr -fnext-runtime} \ + {-O0 -flto -fnext-runtime} \ + {-O2 -flto -fnext-runtime} \ +] + foreach src $tests { + # If we're only testing specific files and this isn't one of them, skip it. + if ![runtest_file_p $runtests $src] then { + continue + } + lto-execute $src $sid + } +} + +lto_finish Index: gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm =================================================================== --- gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm (revision 0) +++ gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm (revision 0) @@ -0,0 +1,43 @@ +/* { dg-lto-do run } */ +/* { dg-skip-if "Needs OBJC2 ABI" { "*-*-darwin*" && lp64 } { "*" } { "" } } */ +extern "C" { +extern int printf (char *,...) ; +extern void abort (void) ; +} + +typedef struct objc_class *Class; + +struct objc_class { + Class isa; + /* other stuff... */ +} ; + +@interface myRootObject { +@public + Class isa; +} ++initialize; ++(Class)class; + +@end + +@implementation myRootObject ++initialize { + return self; +} + ++(Class)class { + return (Class)self; +} + +@end + +int main(void) +{ + Class cl = [myRootObject class]; + if (cl != (Class)0) { + printf((char *)"trivial OK\n"); + return 0; + } + abort () ; +} Index: gcc/testsuite/obj-c++.dg/lto/lto.exp =================================================================== --- gcc/testsuite/obj-c++.dg/lto/lto.exp (revision 0) +++ gcc/testsuite/obj-c++.dg/lto/lto.exp (revision 0) @@ -0,0 +1,84 @@ +# Copyright (C) 2010 Free Software Foundation, Inc. + +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 +# . +# +# Based on gcc/testsuite/gcc.dg/lto/lto.exp. + +# Test link-time optimization across multiple files. +# +# Programs are broken into multiple files. Each one is compiled +# separately with LTO information. The final executable is generated +# by collecting all the generated object files using regular LTO or WHOPR. + +if $tracelevel then { + strace $tracelevel +} + +# Load procedures from common libraries. +load_lib standard.exp +load_lib obj-c++-dg.exp + +# Load the language-independent compabibility support procedures. +load_lib lto.exp + +# If LTO has not been enabled, bail. +if { ![check_effective_target_lto] } { + return +} + +global LTO_OPTIONS + +set LTO_OPTIONS [list \ + {-O0 -fwhopr -fgnu-runtime} \ + {-O2 -fwhopr -fgnu-runtime} \ + {-O0 -flto -fgnu-runtime} \ + {-O2 -flto -fgnu-runtime} \ +] + +obj-c++_init +lto_init no-mathlib + +# Define an identifier for use with this suite to avoid name conflicts +# with other lto tests running at the same time. +set sid "obj_cpp_lto" +set tests [lsort [glob -nocomplain $srcdir/$subdir/*_0.mm]] + +# Main loop. +foreach src $tests { + # If we're only testing specific files and this isn't one of them, skip it. + if ![runtest_file_p $runtests $src] then { + continue + } + lto-execute $src $sid +} + +# darwin targets can also run code with the NeXT runtime. +if [istarget "*-*-darwin*" ] { +set LTO_OPTIONS [list \ + {-O0 -fwhopr -fnext-runtime} \ + {-O2 -fwhopr -fnext-runtime} \ + {-O0 -flto -fnext-runtime} \ + {-O2 -flto -fnext-runtime} \ +] + foreach src $tests { + # If we're only testing specific files and this isn't one of them, skip it. + if ![runtest_file_p $runtests $src] then { + continue + } + lto-execute $src $sid + } +} + +lto_finish