OSDN Git Service

make ObjC do LTO.
authoriains <iains@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 10 Jul 2010 00:22:35 +0000 (00:22 +0000)
committeriains <iains@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 10 Jul 2010 00:22:35 +0000 (00:22 +0000)
gcc/
PR objc/44140
* config/darwin.c (output_objc_section_asm_op): Save and restore
section when outputting ObjC section list.

testsuite/

PR objc/44140
* objc.dg/lto/trivial-1_0.m: New.
* objc.dg/lto/lto.exp: New.
* obj-c++.dg/lto/trivial-1_0.mm: New.
* obj-c++.dg/lto/lto.exp: New.
* objc.dg/symtab-1.m: Adjust sizes.
* objc.dg/image-info.m: Do not run for gnu-runtime.

gcc/objc/

PR objc/44140
* objc-act.c: build_objc_string_decl() remove declaration.
(finish_var_decl): Remove forcing of var output and marking
as "Used".
(init_def_list): Use integer_zero_node.
(init_objc_symtab): Use integer_zero_node, make the short
integer type specific on relevant nodes.
(generate_objc_symtab_decl): Remove call to
forward_declare_categories().  Use null_pointer_node where
appropriate.
(build_module_descriptor): Comment and mark this item as
DECL_PRESERVE_P.
(generate_static_references): Use gcc_unreachable instead of
abort ().
(diagnose_missing_method): New.
(build_next_selector_translation_table): New.
(build_gnu_selector_translation_table): New.
(add_objc_string): Merge code from build_objc_string_decl...
... and delete build_objc_string_decl().
(generate_dispatch_table): Make integer types explicit.
(generate_category): Pass implent and arrange for the data
to be extracted within the routine.  Do not start new vars,
but finish the ones collcted during parsing.
(generate_shared_structures): Likewise.
(finish_objc):  Reorder code so that we finish variables before
referencing them.  Save the global data before calling meta-data
creation routines, and pass the current reference to the two
main routines.  Only call generate_objc_image_info () for the
NeXT runtime.
(generate_classref_translation_entry): Comment on and make this
item DECL_PRESERVE_P.
(handle_class_ref): Use varpool interfaces, comment on and make
this item DECL_PRESERVE_P.
(handle_impent): Likewise.
(generate_objc_image_info): Only generate when the content is
non-zero.  Make integer types explict.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@162030 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/darwin.c
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/lto/lto.exp [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/image-info.m
gcc/testsuite/objc.dg/lto/lto.exp [new file with mode: 0644]
gcc/testsuite/objc.dg/lto/trivial-1_0.m [new file with mode: 0644]
gcc/testsuite/objc.dg/symtab-1.m

index d860d2e..45f780a 100644 (file)
@@ -1,3 +1,9 @@
+2010-07-10  Iain Sandoe  <iains@gcc.gnu.org>
+
+       PR objc/44140
+       * config/darwin.c (output_objc_section_asm_op): Save and restore
+       section when outputting ObjC section list.
+
 2010-07-09  Jan Hubicka  <jh@suse.cz>
 
        * lto-streamer-out.c (produce_symtab): Do not write alias cgraph/varpool
index 876b433..952539f 100644 (file)
@@ -99,6 +99,7 @@ output_objc_section_asm_op (const void *directive)
      section is requested.  */
   if (! been_here)
     {
+      section *saved_in_section = in_section;
       static const enum darwin_section_enum tomark[] =
        {
          /* written, cold -> hot */
@@ -129,6 +130,7 @@ output_objc_section_asm_op (const void *directive)
       been_here = true;
       for (i = 0; i < ARRAY_SIZE (tomark); i++)
        switch_to_section (darwin_sections[tomark[i]]);
+      switch_to_section (saved_in_section);
     }
   output_section_asm_op (directive);
 }
index 9505d7e..17b116f 100644 (file)
@@ -1,3 +1,42 @@
+2010-07-10  Iain Sandoe  <iains@gcc.gnu.org>
+
+       PR objc/44140
+       * objc-act.c: build_objc_string_decl() remove declaration.
+       (finish_var_decl): Remove forcing of var output and marking
+       as "Used". 
+       (init_def_list): Use integer_zero_node. 
+       (init_objc_symtab): Use integer_zero_node, make the short
+       integer type specific on relevant nodes.
+       (generate_objc_symtab_decl): Remove call to 
+       forward_declare_categories().  Use null_pointer_node where
+       appropriate.  
+       (build_module_descriptor): Comment and mark this item as 
+       DECL_PRESERVE_P. 
+       (generate_static_references): Use gcc_unreachable instead of
+       abort (). 
+       (diagnose_missing_method): New.
+       (build_next_selector_translation_table): New.
+       (build_gnu_selector_translation_table): New.
+       (add_objc_string): Merge code from build_objc_string_decl...
+       ... and delete build_objc_string_decl().
+       (generate_dispatch_table): Make integer types explicit.
+       (generate_category): Pass implent and arrange for the data
+       to be extracted within the routine.  Do not start new vars, 
+       but finish the ones collcted during parsing.
+       (generate_shared_structures): Likewise.
+       (finish_objc):  Reorder code so that we finish variables before
+       referencing them.  Save the global data before calling meta-data
+       creation routines, and pass the current reference to the two 
+       main routines.  Only call generate_objc_image_info () for the 
+       NeXT runtime.
+       (generate_classref_translation_entry): Comment on and make this
+       item DECL_PRESERVE_P.
+       (handle_class_ref): Use varpool interfaces, comment on and make
+       this item DECL_PRESERVE_P.
+       (handle_impent): Likewise.
+       (generate_objc_image_info): Only generate when the content is 
+       non-zero.  Make integer types explict.
+
 2010-07-03  Nathan Froyd  <froydnj@codesourcery.com>
 
        PR objc/24867
index af4aa8e..a0f3690 100644 (file)
@@ -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.  */
@@ -1541,14 +1540,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
@@ -2188,7 +2179,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);
     }
@@ -2211,7 +2202,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,
@@ -2224,11 +2217,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, ...}, ... } */
 
@@ -2289,10 +2284,7 @@ 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");
   finish_var_decl (UOBJC_SYMBOLS_decl,
@@ -2328,7 +2320,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 = null_pointer_node;
   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
 
   return objc_build_constructor (type, v);
@@ -2367,6 +2359,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)));
 
@@ -2490,7 +2485,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++)
@@ -2574,54 +2569,78 @@ 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 chain;
-  int offset = 0;
-  tree decl = NULL_TREE;
-  VEC(constructor_elt,gc) *inits = NULL;
+  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;
   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
     {
       tree expr;
-
+      tree decl = TREE_PURPOSE (chain);
       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));
-         }
-      }
+       {
+         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));
-      /* add one for the '\0' character */
-      offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
 
-      if (flag_next_runtime)
+      if (decl)
        {
-         decl = TREE_PURPOSE (chain);
+         /* Entries of this form are used for references to methods.
+         The runtime re-writes these on start-up, but the compiler can't see 
+         that and optimizes it away unless we force it.  */
+         DECL_PRESERVE_P (decl) = 1;
          finish_var_decl (decl, expr);
        }
-      else
+    }
+}
+
+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))
+    {
+      tree expr;
+
+      if (warn_selector && objc_implementation_context)
+       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;*/
+
        {
          if (flag_typed_selectors)
            {
@@ -2634,9 +2653,8 @@ build_selector_translation_table (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.  */
@@ -2645,12 +2663,12 @@ build_selector_translation_table (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),
@@ -2854,19 +2872,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;
-
+  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)
     {
@@ -2878,12 +2911,11 @@ add_objc_string (tree ident, enum string_section section)
       chain = &TREE_CHAIN (*chain);
     }
 
-  decl = build_objc_string_decl (section);
-
   type = build_sized_array_type (char_type_node, IDENTIFIER_LENGTH (ident) + 1);
-  decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
+  decl = start_var_decl (type, buf);
   string_expr = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
                                 IDENTIFIER_POINTER (ident));
+  TREE_CONSTANT (decl) = 1;
   finish_var_decl (decl, string_expr);
 
   *chain = tree_cons (decl, ident, NULL_TREE);
@@ -2892,44 +2924,6 @@ add_objc_string (tree ident, enum string_section section)
                                                    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)
 {
@@ -5334,8 +5328,8 @@ generate_dispatch_table (tree type, const char *name, int size, tree list)
   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, build_int_cst (NULL_TREE, size));
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, size));
   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, list);
 
   finish_var_decl (decl,
@@ -5658,11 +5652,15 @@ lookup_category (tree klass, tree cat_name)
 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
 
 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);
@@ -5680,30 +5678,32 @@ generate_category (tree cat)
   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)
     {
@@ -5734,13 +5734,12 @@ generate_shared_structures (int cls_flags)
 
   /* 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,
-                                cast_type, super_expr); /* cast! */
-    }
+    super_expr = add_objc_string (my_super_id, class_names);
   else
-    super_expr = build_int_cst (NULL_TREE, 0);
+    super_expr = integer_zero_node;
+    
+  super_expr = build_c_cast (input_location,
+                                cast_type, super_expr); /* cast! */
 
   root_expr = add_objc_string (my_root_id, class_names);
   root_expr = build_c_cast (input_location, cast_type, root_expr); /* cast! */
@@ -5756,13 +5755,9 @@ generate_shared_structures (int cls_flags)
 
   /* 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*/,
@@ -5770,17 +5765,13 @@ generate_shared_structures (int cls_flags)
        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,
@@ -5791,7 +5782,7 @@ generate_shared_structures (int cls_flags)
        UOBJC_INSTANCE_VARIABLES_decl,
        protocol_decl);
 
-  finish_var_decl (decl, initlist);
+  finish_var_decl (UOBJC_CLASS_decl, initlist);
 }
 
 
@@ -9176,15 +9167,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;
 
@@ -9202,28 +9195,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)
@@ -9282,8 +9282,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;
 }
@@ -9309,12 +9310,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",
@@ -9322,15 +9322,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
@@ -9381,17 +9383,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) ;
     }
 }
 \f
@@ -9406,16 +9412,24 @@ generate_objc_image_info (void)
 {
   tree decl;
   int flags
-    = ((flag_replace_objc_classes && imp_list ? 1 : 0)
+    = ((flag_replace_objc_classes && imp_count ? 1 : 0)
        | (flag_objc_gc ? 2 : 0));
   VEC(constructor_elt,gc) *v = NULL;
-  tree array_type = build_sized_array_type (integer_type_node, 2);
+  tree array_type;
+  
+   if (!flags)
+    return; /* No need for an image_info entry.  */
+  
+  array_type  = build_sized_array_type (integer_type_node, 2);
 
   decl = start_var_decl (array_type, "_OBJC_IMAGE_INFO");
 
-  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
-  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags));
-
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, flags));
+  /* If we need this (determined above) it is because the runtime wants to
+     refer to it in a manner hidden from the compiler.  So we must force the 
+     output.  */
+  DECL_PRESERVE_P (decl) = 1;
   finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v));
 }
 
index 77e4d9d..6d0de14 100644 (file)
@@ -1,3 +1,13 @@
+2010-07-10  Iain Sandoe  <iains@gcc.gnu.org>
+
+       PR objc/44140
+       * objc.dg/lto/trivial-1_0.m: New.
+       * objc.dg/lto/lto.exp: New.
+       * obj-c++.dg/lto/trivial-1_0.mm: New.
+       * obj-c++.dg/lto/lto.exp: New.
+       * objc.dg/symtab-1.m: Adjust sizes.
+       * objc.dg/image-info.m: Do not run for gnu-runtime.
+
 2010-07-09  Bernd Schmidt  <bernds@codesourcery.com>
 
        * gcc.dg/pr32370.c: Allow another kind of error message.
diff --git a/gcc/testsuite/obj-c++.dg/lto/lto.exp b/gcc/testsuite/obj-c++.dg/lto/lto.exp
new file mode 100644 (file)
index 0000000..291895f
--- /dev/null
@@ -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
+# <http://www.gnu.org/licenses/>.
+#
+# 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
diff --git a/gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm b/gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm
new file mode 100644 (file)
index 0000000..45b6e70
--- /dev/null
@@ -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 0a740fa..e9e9de6 100644 (file)
@@ -4,6 +4,7 @@
 /* Contributed by Ziemowit Laski <zlaski@apple.com>.  */
 
 /* { dg-do compile { target { *-*-darwin* } } } */
+/* { dg-skip-if "NeXT-only" { *-*-* } { "-fgnu-runtime" } { "" } } */
 /* { dg-options "-freplace-objc-classes" } */
 
 #include "../objc-obj-c++-shared/Object1.h"
diff --git a/gcc/testsuite/objc.dg/lto/lto.exp b/gcc/testsuite/objc.dg/lto/lto.exp
new file mode 100644 (file)
index 0000000..4ea89cc
--- /dev/null
@@ -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
+# <http://www.gnu.org/licenses/>.
+#
+# 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
diff --git a/gcc/testsuite/objc.dg/lto/trivial-1_0.m b/gcc/testsuite/objc.dg/lto/trivial-1_0.m
new file mode 100644 (file)
index 0000000..076f230
--- /dev/null
@@ -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 90a7969..100b245 100644 (file)
@@ -22,6 +22,7 @@
 -(void)checkValues { }
 @end
 
-/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.long\t0\n\t.long\t0\n\t.word\t2\n\t.word\t0\n\t.long\tL_OBJC_CLASS_Derived.*\n\t.long\tL_OBJC_CLASS_Base.*\n" { target { i?86-*-darwin* && { ! lp64 } } } } } */
-/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.long\t0\n\t.long\t0\n\t.short\t2\n\t.short\t0\n\t.long\tL_OBJC_CLASS_Derived.*\n\t.long\tL_OBJC_CLASS_Base.*\n" { target { powerpc-*-darwin* && { ! lp64 } } } } } */
-/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.quad\t0\n\t.long\t0\n\t.space 4\n\t.word\t2\n\t.word\t0\n\t.space 4\n\t.quad\tL_OBJC_CLASS_Derived.*\n\t.quad\tL_OBJC_CLASS_Base.*\n" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.long\t0\n\t.long\t0\n\t.word\t2\n\t.word\t0\n\t.long\tL_OBJC_CLASS_Derived.*\n\t.long\tL_OBJC_CLASS_Base.*\n" { target { *86*-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.long\t0\n\t.long\t0\n\t.short\t2\n\t.short\t0\n\t.long\tL_OBJC_CLASS_Derived.*\n\t.long\tL_OBJC_CLASS_Base.*\n" { target { powerpc*-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.quad\t0\n\t.quad\t0\n\t.word\t2\n\t.word\t0\n\t.space 4\n\t.quad\tL_OBJC_CLASS_Derived.*\n\t.quad\tL_OBJC_CLASS_Base.*\n" { target { *86*-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.quad\t0\n\t.quad\t0\n\t.short\t2\n\t.short\t0\n\t.space 4\n\t.quad\tL_OBJC_CLASS_Derived.*\n\t.quad\tL_OBJC_CLASS_Base.*\n" { target { powerpc*-*-darwin* && { lp64 } } } } } */