* lto-symtab.c (lto_symtab_merge_cgraph_nodes_1): Rename to ...
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 1 Jun 2013 13:08:53 +0000 (13:08 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 1 Jun 2013 13:08:53 +0000 (13:08 +0000)
(lto_symtab_merge_symbols_1): ... this one.
(lto_symtab_merge_cgraph_nodes): Rename to ...
(lto_symtab_merge_symbols): ... this one; simplify.
* cgraph.c (same_body_aliases_done): Rename to ...
(cpp_implicit_aliases_done): ... this one.
(cgraph_create_function_alias): Update.
(cgraph_same_body_alias): Update.
(dump_cgraph_node): Remove alias dumping; simplify
thunk dumping.
(verify_edge_corresponds_to_fndecl): Simplify.
* cgraph.h (symtab_node_base): Add cpp_implicit_alias,
alias_target.
(cgraph_node): Remove same_body_alias.
(varpool_node): Remove alias_of and extra_name_alias.
(same_body_aliases_done): Rename to ..
(cpp_implicit_aliases_done): ... this one.
(symtab_alias_ultimate_target): Add default parameter.
(symtab_resolve_alias): New function.
(fixup_same_cpp_alias_visibility): Declare.
(cgraph_function_node): Add default parameter.
(cgraph_node_asm_name): Likewise.
(cgraph_function_or_thunk_node): Add default parameter; do
not ICE when it is NULL.
(varpool_variable_node): Likewise.
* tree-emutls.c (create_emultls_var): Update.
(ipa_lower_emutls): Update.
* cgraphunit.c (cgraph_decide_is_function_needed): Update.
(cgraph_reset_node): Reset alias info.
(cgraph_finalize_function): Update.
(fixup_same_cpp_alias_visibility): Move to symtab.c.
(analyze_function): Simplify.
(cgraph_process_same_body_aliases): Simplify.
(analyze_functions): Fixup same body aliases.
(handle_alias_pairs): Simplify.
(assemble_thunk): Update.
(assemble_thunks_and_aliases): Update.
(output_weakrefs): Rewrite.
* lto-cgraph.c (lto_output_node): Rewrite alias handling.
(lto_output_varpool_node): Likewise.
(compute_ltrans_boundary): Remve assert.
(get_alias_symbol): New functoin.
(input_node): Rewrite alias handling.
(input_varpool_node): Likewise.
* ipa-pure-const.c (propagate_pure_const): Fix formating.
* ipa.c (process_references): Handle weakrefs correctly.
(symtab_remove_unreachable_nodes): Likewise.
* trans-mem.c (get_cg_data): Update.
(ipa_tm_create_version_alias): Update.
(ipa_tm_execute): Update.
* symtab.c (dump_symtab_base): Dump aliases.
(verify_symtab_base): Verify aliases.
(symtab_node_availability): New function.
(symtab_alias_ultimate_target): Simplify.
(fixup_same_cpp_alias_visibility): Move here from cgraphunit.c;
handle all the fixup cases.
(symtab_resolve_alias): New function.
* passes.c (ipa_write_summaries): Handle weakrefs.
* varpool.c (varpool_analyze_node): Simplify.
(assemble_aliases): Update.
(varpool_create_variable_alias): Simplify.
(varpool_extra_name_alias): Simplify.
* lto-streamer.h (lto_symtab_merge_cgraph_nodes): Rename to...
(lto_symtab_merge_symbols): ... this one.

* decl2.c (cp_write_global_declarations): Replace same_body_alias
by symbol.cpp_implicit_alias.

* lto.c (read_cgraph_and_symbols): Simplify dumping; Replace
lto_symtab_merge_cgraph_nodes by lto_symtab_merge_symbols.
(do_whole_program_analysis): Update dumping.

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

18 files changed:
gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/ipa-pure-const.c
gcc/ipa.c
gcc/lto-cgraph.c
gcc/lto-streamer.h
gcc/lto-symtab.c
gcc/lto/ChangeLog
gcc/lto/lto.c
gcc/passes.c
gcc/symtab.c
gcc/trans-mem.c
gcc/tree-emutls.c
gcc/varpool.c

index 1da3462..c6a7d7d 100644 (file)
@@ -1,3 +1,70 @@
+2013-06-01  Jan Hubicka  <jh@suse.cz>
+
+       * lto-symtab.c (lto_symtab_merge_cgraph_nodes_1): Rename to ...
+       (lto_symtab_merge_symbols_1): ... this one.
+       (lto_symtab_merge_cgraph_nodes): Rename to ...
+       (lto_symtab_merge_symbols): ... this one; simplify.
+       * cgraph.c (same_body_aliases_done): Rename to ...
+       (cpp_implicit_aliases_done): ... this one.
+       (cgraph_create_function_alias): Update.
+       (cgraph_same_body_alias): Update.
+       (dump_cgraph_node): Remove alias dumping; simplify
+       thunk dumping.
+       (verify_edge_corresponds_to_fndecl): Simplify.
+       * cgraph.h (symtab_node_base): Add cpp_implicit_alias,
+       alias_target.
+       (cgraph_node): Remove same_body_alias.
+       (varpool_node): Remove alias_of and extra_name_alias.
+       (same_body_aliases_done): Rename to ..
+       (cpp_implicit_aliases_done): ... this one.
+       (symtab_alias_ultimate_target): Add default parameter.
+       (symtab_resolve_alias): New function.
+       (fixup_same_cpp_alias_visibility): Declare.
+       (cgraph_function_node): Add default parameter.
+       (cgraph_node_asm_name): Likewise.
+       (cgraph_function_or_thunk_node): Add default parameter; do
+       not ICE when it is NULL.
+       (varpool_variable_node): Likewise.
+       * tree-emutls.c (create_emultls_var): Update.
+       (ipa_lower_emutls): Update.
+       * cgraphunit.c (cgraph_decide_is_function_needed): Update.
+       (cgraph_reset_node): Reset alias info.
+       (cgraph_finalize_function): Update.
+       (fixup_same_cpp_alias_visibility): Move to symtab.c.
+       (analyze_function): Simplify.
+       (cgraph_process_same_body_aliases): Simplify.
+       (analyze_functions): Fixup same body aliases.
+       (handle_alias_pairs): Simplify.
+       (assemble_thunk): Update.
+       (assemble_thunks_and_aliases): Update.
+       (output_weakrefs): Rewrite.
+       * lto-cgraph.c (lto_output_node): Rewrite alias handling.
+       (lto_output_varpool_node): Likewise.
+       (compute_ltrans_boundary): Remve assert.
+       (get_alias_symbol): New functoin.
+       (input_node): Rewrite alias handling.
+       (input_varpool_node): Likewise.
+       * ipa-pure-const.c (propagate_pure_const): Fix formating.
+       * ipa.c (process_references): Handle weakrefs correctly.
+       (symtab_remove_unreachable_nodes): Likewise.
+       * trans-mem.c (get_cg_data): Update.
+       (ipa_tm_create_version_alias): Update.
+       (ipa_tm_execute): Update.
+       * symtab.c (dump_symtab_base): Dump aliases.
+       (verify_symtab_base): Verify aliases.
+       (symtab_node_availability): New function.
+       (symtab_alias_ultimate_target): Simplify.
+       (fixup_same_cpp_alias_visibility): Move here from cgraphunit.c;
+       handle all the fixup cases.
+       (symtab_resolve_alias): New function.
+       * passes.c (ipa_write_summaries): Handle weakrefs.
+       * varpool.c (varpool_analyze_node): Simplify.
+       (assemble_aliases): Update.
+       (varpool_create_variable_alias): Simplify.
+       (varpool_extra_name_alias): Simplify.
+       * lto-streamer.h (lto_symtab_merge_cgraph_nodes): Rename to...
+       (lto_symtab_merge_symbols): ... this one.
+
 2013-06-01  Dinar Temirbulatov  <dinar@kugelworks.com>
 
        Revert
index 735f48a..445282a 100644 (file)
@@ -129,7 +129,7 @@ static GTY(()) struct cgraph_node *free_nodes;
 static GTY(()) struct cgraph_edge *free_edges;
 
 /* Did procss_same_body_aliases run?  */
-bool same_body_aliases_done;
+bool cpp_implicit_aliases_done;
 
 /* Map a cgraph_node to cgraph_function_version_info using this htab.
    The cgraph_function_version_info has a THIS_NODE field that is the
@@ -556,15 +556,16 @@ cgraph_get_create_node (tree decl)
    the function body is associated with (not necessarily cgraph_node (DECL).  */
 
 struct cgraph_node *
-cgraph_create_function_alias (tree alias, tree decl)
+cgraph_create_function_alias (tree alias, tree target)
 {
   struct cgraph_node *alias_node;
 
-  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+  gcc_assert (TREE_CODE (target) == FUNCTION_DECL
+             || TREE_CODE (target) == IDENTIFIER_NODE);
   gcc_assert (TREE_CODE (alias) == FUNCTION_DECL);
   alias_node = cgraph_get_create_node (alias);
   gcc_assert (!alias_node->symbol.definition);
-  alias_node->thunk.alias = decl;
+  alias_node->symbol.alias_target = target;
   alias_node->symbol.definition = true;
   alias_node->symbol.alias = true;
   return alias_node;
@@ -589,10 +590,10 @@ cgraph_same_body_alias (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, tree ali
     return NULL;
 
   n = cgraph_create_function_alias (alias, decl);
-  n->same_body_alias = true;
-  if (same_body_aliases_done)
-    ipa_record_reference ((symtab_node)n, (symtab_node)cgraph_get_node (decl),
-                         IPA_REF_ALIAS, NULL);
+  n->symbol.cpp_implicit_alias = true;
+  if (cpp_implicit_aliases_done)
+    symtab_resolve_alias ((symtab_node)n,
+                         (symtab_node)cgraph_get_node (decl));
   return n;
 }
 
@@ -1545,10 +1546,13 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
 
   if (node->thunk.thunk_p)
     {
-      fprintf (f, "  Thunk of %s (asm: %s) fixed offset %i virtual value %i has "
+      fprintf (f, "  Thunk");
+      if (node->thunk.alias)
+        fprintf (f, "  of %s (asm: %s)",
+                lang_hooks.decl_printable_name (node->thunk.alias, 2),
+                IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->thunk.alias)));
+      fprintf (f, " fixed offset %i virtual value %i has "
               "virtual offset %i)\n",
-              lang_hooks.decl_printable_name (node->thunk.alias, 2),
-              IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->thunk.alias)),
               (int)node->thunk.fixed_offset,
               (int)node->thunk.virtual_value,
               (int)node->thunk.virtual_offset_p);
@@ -2288,17 +2292,11 @@ verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl)
     return false;
   node = cgraph_function_or_thunk_node (node, NULL);
 
-  if ((e->callee->former_clone_of != node->symbol.decl
-       && (!node->same_body_alias
-          || e->callee->former_clone_of != node->thunk.alias))
+  if (e->callee->former_clone_of != node->symbol.decl
       /* IPA-CP sometimes redirect edge to clone and then back to the former
         function.  This ping-pong has to go, eventually.  */
       && (node != cgraph_function_or_thunk_node (e->callee, NULL))
-      && !clone_of_p (node, e->callee)
-      /* If decl is a same body alias of some other decl, allow e->callee to be
-        a clone of a clone of that other decl too.  */
-      && (!node->same_body_alias
-         || !clone_of_p (cgraph_get_node (node->thunk.alias), e->callee)))
+      && !clone_of_p (cgraph_function_or_thunk_node (node, NULL), e->callee))
     return true;
   else
     return false;
index 0dcc1a6..276e568 100644 (file)
@@ -56,6 +56,13 @@ struct GTY(()) symtab_node_base
   /* True when symbol is an alias.  
      Set by assemble_alias.  */
   unsigned alias : 1;
+  /* C++ frontend produce same body aliases and extra name aliases for
+     virutal functions and vtables that are obviously equivalent.
+     Those aliases are bit special, especially because C++ frontend
+     visibility code is so ugly it can not get them right at first time
+     and their visibility needs to be copied from their "masters" at
+     the end of parsing.  */
+  unsigned cpp_implicit_alias : 1;
   /* Set once the definition was analyzed.  The list of references and
      other properties are built during analysis.  */
   unsigned analyzed : 1;
@@ -119,6 +126,11 @@ struct GTY(()) symtab_node_base
   /* Vectors of referring and referenced entities.  */
   struct ipa_ref_list ref_list;
 
+  /* Alias target. May be either DECL pointer or ASSEMBLER_NAME pointer
+     depending to what was known to frontend on the creation time.
+     Once alias is resolved, this pointer become NULL.  */
+  tree alias_target;
+
   /* File stream where this node is being written to.  */
   struct lto_file_decl_data * lto_file_data;
 
@@ -291,8 +303,6 @@ struct GTY(()) cgraph_node {
   /* Set once the function has been instantiated and its callee
      lists created.  */
   unsigned process : 1;
-  /* Set for aliases created as C++ same body aliases.  */
-  unsigned same_body_alias : 1;
   /* How commonly executed the node is.  Initialized during branch
      probabilities pass.  */
   ENUM_BITFIELD (node_frequency) frequency : 2;
@@ -478,12 +488,9 @@ typedef struct cgraph_edge *cgraph_edge_p;
 
 struct GTY(()) varpool_node {
   struct symtab_node_base symbol;
-  /* For aliases points to declaration DECL is alias of.  */
-  tree alias_of;
 
   /* Set when variable is scheduled to be assembled.  */
   unsigned output : 1;
-  unsigned extra_name_alias : 1;
 };
 
 /* Every top level asm statement is put into a asm_node.  */
@@ -553,7 +560,7 @@ extern cgraph_node_set cgraph_new_nodes;
 
 extern GTY(()) struct asm_node *asm_nodes;
 extern GTY(()) int symtab_order;
-extern bool same_body_aliases_done;
+extern bool cpp_implicit_aliases_done;
 
 /* In symtab.c  */
 void symtab_register_node (symtab_node);
@@ -576,7 +583,10 @@ void verify_symtab_node (symtab_node);
 bool verify_symtab_base (symtab_node);
 bool symtab_used_from_object_file_p (symtab_node);
 void symtab_make_decl_local (tree);
-symtab_node symtab_alias_ultimate_target (symtab_node, enum availability *);
+symtab_node symtab_alias_ultimate_target (symtab_node,
+                                         enum availability *avail = NULL);
+bool symtab_resolve_alias (symtab_node node, symtab_node target);
+void fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target);
 
 /* In cgraph.c  */
 void dump_cgraph (FILE *);
@@ -672,7 +682,8 @@ struct cgraph_2node_hook_list *cgraph_add_node_duplication_hook (cgraph_2node_ho
 void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *);
 gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *);
 bool cgraph_propagate_frequency (struct cgraph_node *node);
-struct cgraph_node * cgraph_function_node (struct cgraph_node *, enum availability *);
+struct cgraph_node * cgraph_function_node (struct cgraph_node *,
+                                          enum availability *avail = NULL);
 
 /* In cgraphunit.c  */
 struct asm_node *add_asm_node (tree);
@@ -822,7 +833,7 @@ varpool_get_node (const_tree decl)
 
 /* Return asm name of cgraph node.  */
 static inline const char *
-cgraph_node_asm_name(struct cgraph_node *node)
+cgraph_node_asm_name (struct cgraph_node *node)
 {
   return symtab_node_asm_name ((symtab_node)node);
 }
@@ -1258,12 +1269,14 @@ varpool_alias_target (struct varpool_node *n)
    When AVAILABILITY is non-NULL, get minimal availability in the chain.  */
 
 static inline struct cgraph_node *
-cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *availability)
+cgraph_function_or_thunk_node (struct cgraph_node *node,
+                              enum availability *availability = NULL)
 {
   struct cgraph_node *n;
 
-  n = dyn_cast <cgraph_node> (symtab_alias_ultimate_target ((symtab_node)node, availability));
-  if (!n)
+  n = dyn_cast <cgraph_node> (symtab_alias_ultimate_target ((symtab_node)node,
+                                                           availability));
+  if (!n && availability)
     *availability = AVAIL_NOT_AVAILABLE;
   return n;
 }
@@ -1272,12 +1285,14 @@ cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *avai
    When AVAILABILITY is non-NULL, get minimal availability in the chain.  */
 
 static inline struct varpool_node *
-varpool_variable_node (struct varpool_node *node, enum availability *availability)
+varpool_variable_node (struct varpool_node *node,
+                      enum availability *availability = NULL)
 {
   struct varpool_node *n;
 
-  n = dyn_cast <varpool_node> (symtab_alias_ultimate_target ((symtab_node)node, availability));
-  if (!n)
+  n = dyn_cast <varpool_node> (symtab_alias_ultimate_target ((symtab_node)node,
+                                                            availability));
+  if (!n && availability)
     *availability = AVAIL_NOT_AVAILABLE;
   return n;
 }
index ca314a6..76ef876 100644 (file)
@@ -231,8 +231,7 @@ cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
   /* Double check that no one output the function into assembly file
      early.  */
   gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
-                      || (node->thunk.thunk_p || node->same_body_alias)
-                      ||  !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
+                      || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
 
 
   /* Keep constructors, destructors and virtual functions.  */
@@ -370,6 +369,8 @@ cgraph_reset_node (struct cgraph_node *node)
   memset (&node->rtl, 0, sizeof (node->rtl));
   node->symbol.analyzed = false;
   node->symbol.definition = false;
+  node->symbol.alias = false;
+  node->symbol.cpp_implicit_alias = false;
 
   cgraph_node_remove_callees (node);
   ipa_remove_all_references (&node->symbol.ref_list);
@@ -426,7 +427,7 @@ cgraph_finalize_function (tree decl, bool nested)
      in the original implementation and it is unclear whether we want
      to change the behavior here.  */
   if ((!optimize
-       && !node->same_body_alias
+       && !node->symbol.cpp_implicit_alias
        && !DECL_DISREGARD_INLINE_LIMITS (decl)
        && !DECL_DECLARED_INLINE_P (decl)
        && !(DECL_CONTEXT (decl)
@@ -573,22 +574,6 @@ output_asm_statements (void)
   asm_nodes = NULL;
 }
 
-/* C++ FE sometimes change linkage flags after producing same body aliases.  */
-void
-fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target, tree alias)
-{
-  DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (alias);
-  if (TREE_PUBLIC (node->symbol.decl))
-    {
-      DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (alias);
-      DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (alias);
-      DECL_COMDAT_GROUP (node->symbol.decl) = DECL_COMDAT_GROUP (alias);
-      if (DECL_ONE_ONLY (alias)
-         && !node->symbol.same_comdat_group)
-       symtab_add_to_same_comdat_group ((symtab_node)node, (symtab_node)target);
-    }
-}
-
 /* Analyze the function scheduled to be output.  */
 static void
 analyze_function (struct cgraph_node *node)
@@ -597,39 +582,14 @@ analyze_function (struct cgraph_node *node)
   location_t saved_loc = input_location;
   input_location = DECL_SOURCE_LOCATION (decl);
 
-  if (node->symbol.alias && node->thunk.alias)
-    {
-      struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
-      struct cgraph_node *n;
-
-      for (n = tgt; n && n->symbol.alias;
-          n = n->symbol.analyzed ? cgraph_alias_target (n) : NULL)
-       if (n == node)
-         {
-           error ("function %q+D part of alias cycle", node->symbol.decl);
-           node->symbol.alias = false;
-           input_location = saved_loc;
-           return;
-         }
-      if (!vec_safe_length (node->symbol.ref_list.references))
-        ipa_record_reference ((symtab_node)node, (symtab_node)tgt,
-                             IPA_REF_ALIAS, NULL);
-      if (node->same_body_alias)
-       { 
-         DECL_DECLARED_INLINE_P (node->symbol.decl)
-            = DECL_DECLARED_INLINE_P (node->thunk.alias);
-         DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl)
-            = DECL_DISREGARD_INLINE_LIMITS (node->thunk.alias);
-         fixup_same_cpp_alias_visibility ((symtab_node) node, (symtab_node) tgt, node->thunk.alias);
-       }
-
-      if (node->symbol.address_taken)
-       cgraph_mark_address_taken_node (cgraph_alias_target (node));
-    }
+  if (node->symbol.alias)
+    symtab_resolve_alias
+       ((symtab_node) node, (symtab_node) cgraph_get_node (node->symbol.alias_target));
   else if (node->thunk.thunk_p)
     {
       cgraph_create_edge (node, cgraph_get_node (node->thunk.alias),
                          NULL, 0, CGRAPH_FREQ_BASE);
+      node->thunk.alias = NULL;
     }
   else if (node->dispatcher_function)
     {
@@ -693,16 +653,12 @@ analyze_function (struct cgraph_node *node)
 void
 cgraph_process_same_body_aliases (void)
 {
-  struct cgraph_node *node;
-  FOR_EACH_FUNCTION (node)
-    if (node->same_body_alias
-       && !vec_safe_length (node->symbol.ref_list.references))
-      {
-        struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
-        ipa_record_reference ((symtab_node)node, (symtab_node)tgt,
-                             IPA_REF_ALIAS, NULL);
-      }
-  same_body_aliases_done = true;
+  symtab_node node;
+  FOR_EACH_SYMBOL (node)
+    if (node->symbol.cpp_implicit_alias && !node->symbol.analyzed)
+      symtab_resolve_alias (node,
+                           symtab_get_node (node->symbol.alias_target));
+  cpp_implicit_aliases_done = true;
 }
 
 /* Process attributes common for vars and functions.  */
@@ -890,6 +846,13 @@ analyze_functions (void)
   bitmap_obstack_initialize (NULL);
   cgraph_state = CGRAPH_STATE_CONSTRUCTION;
 
+  /* Ugly, but the fixup can not happen at a time same body alias is created;
+     C++ FE is confused about the COMDAT groups being right.  */
+  if (cpp_implicit_aliases_done)
+    FOR_EACH_SYMBOL (node)
+      if (node->symbol.cpp_implicit_alias)
+         fixup_same_cpp_alias_visibility (node, symtab_alias_target (node));
+
   /* Analysis adds static variables that in turn adds references to new functions.
      So we need to iterate the process until it stabilize.  */
   while (changed)
@@ -940,7 +903,7 @@ analyze_functions (void)
              and later using weak alias attribute to kill its body.
              See gcc.c-torture/compile/20011119-1.c  */
              if (!DECL_STRUCT_FUNCTION (decl)
-                 && (!cnode->symbol.alias || !cnode->thunk.alias)
+                 && !cnode->symbol.alias
                  && !cnode->thunk.thunk_p
                  && !cnode->dispatcher_function)
                {
@@ -970,7 +933,7 @@ analyze_functions (void)
          else
            {
              varpool_node *vnode = dyn_cast <varpool_node> (node);
-             if (vnode && vnode->symbol.definition)
+             if (vnode && vnode->symbol.definition && !vnode->symbol.analyzed)
                varpool_analyze_node (vnode);
            }
 
@@ -1016,7 +979,7 @@ analyze_functions (void)
          tree decl = node->symbol.decl;
 
          if (cnode->symbol.definition && !gimple_has_body_p (decl)
-             && (!cnode->symbol.alias || !cnode->thunk.alias)
+             && !cnode->symbol.alias
              && !cnode->thunk.thunk_p)
            cgraph_reset_node (cnode);
 
@@ -1057,17 +1020,11 @@ handle_alias_pairs (void)
         to later output the weakref pseudo op into asm file.  */
       if (!target_node && lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL)
        {
-         if (TREE_CODE (p->decl) == FUNCTION_DECL)
-           {
-             struct cgraph_node *anode = cgraph_get_create_node (p->decl);
-             anode->symbol.alias = true;
-             anode->thunk.alias = p->target;
-           }
-         else
+         symtab_node node = symtab_get_node (p->decl);
+         if (node)
            {
-             struct varpool_node *anode = varpool_get_node (p->decl);
-             anode->symbol.alias = true;
-             anode->alias_of = p->target;
+             node->symbol.alias_target = p->target;
+             node->symbol.alias = true;
            }
          DECL_EXTERNAL (p->decl) = 1;
          alias_pairs->unordered_remove (i);
@@ -1380,7 +1337,7 @@ assemble_thunk (struct cgraph_node *node)
   HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset;
   HOST_WIDE_INT virtual_value = node->thunk.virtual_value;
   tree virtual_offset = NULL;
-  tree alias = node->thunk.alias;
+  tree alias = node->callees->callee->symbol.decl;
   tree thunk_fndecl = node->symbol.decl;
   tree a = DECL_ARGUMENTS (thunk_fndecl);
 
@@ -1581,15 +1538,15 @@ assemble_thunks_and_aliases (struct cgraph_node *node)
     if (ref->use == IPA_REF_ALIAS)
       {
        struct cgraph_node *alias = ipa_ref_referring_node (ref);
-        bool saved_written = TREE_ASM_WRITTEN (alias->thunk.alias);
+        bool saved_written = TREE_ASM_WRITTEN (node->symbol.decl);
 
        /* Force assemble_alias to really output the alias this time instead
           of buffering it in same alias pairs.  */
-       TREE_ASM_WRITTEN (alias->thunk.alias) = 1;
+       TREE_ASM_WRITTEN (node->symbol.decl) = 1;
        do_assemble_alias (alias->symbol.decl,
-                          DECL_ASSEMBLER_NAME (alias->thunk.alias));
+                          DECL_ASSEMBLER_NAME (node->symbol.decl));
        assemble_thunks_and_aliases (alias);
-       TREE_ASM_WRITTEN (alias->thunk.alias) = saved_written;
+       TREE_ASM_WRITTEN (node->symbol.decl) = saved_written;
       }
 }
 
@@ -1929,22 +1886,32 @@ get_alias_symbol (tree decl)
 static void
 output_weakrefs (void)
 {
-  struct cgraph_node *node;
-  struct varpool_node *vnode;
-  FOR_EACH_FUNCTION (node)
+  symtab_node node;
+  FOR_EACH_SYMBOL (node)
     if (node->symbol.alias && DECL_EXTERNAL (node->symbol.decl)
         && !TREE_ASM_WRITTEN (node->symbol.decl)
        && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
-      do_assemble_alias (node->symbol.decl,
-                        node->thunk.alias && DECL_P (node->thunk.alias) ? DECL_ASSEMBLER_NAME (node->thunk.alias)
-                        : get_alias_symbol (node->symbol.decl));
-  FOR_EACH_VARIABLE (vnode)
-    if (vnode->symbol.alias && DECL_EXTERNAL (vnode->symbol.decl)
-        && !TREE_ASM_WRITTEN (vnode->symbol.decl)
-       && lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl)))
-      do_assemble_alias (vnode->symbol.decl,
-                        vnode->alias_of && DECL_P (vnode->alias_of) ? DECL_ASSEMBLER_NAME (vnode->alias_of)
-                        : get_alias_symbol (vnode->symbol.decl));
+      {
+       tree target;
+
+       /* Weakrefs are special by not requiring target definition in current
+          compilation unit.  It is thus bit hard to work out what we want to
+          alias.
+          When alias target is defined, we need to fetch it from symtab reference,
+          otherwise it is pointed to by alias_target.  */
+       if (node->symbol.alias_target)
+         target = (DECL_P (node->symbol.alias_target)
+                   ? DECL_ASSEMBLER_NAME (node->symbol.alias_target)
+                   : node->symbol.alias_target);
+       else if (node->symbol.analyzed)
+         target = DECL_ASSEMBLER_NAME (symtab_alias_target (node)->symbol.decl);
+       else
+         {
+           gcc_unreachable ();
+           target = get_alias_symbol (node->symbol.decl);
+         }
+        do_assemble_alias (node->symbol.decl, target);
+      }
 }
 
 /* Initialize callgraph dump file.  */
index ae2c174..8dc30f9 100644 (file)
@@ -1,3 +1,8 @@
+2013-06-01  Jan Hubicka  <jh@suse.cz>
+
+       * decl2.c (cp_write_global_declarations): Replace same_body_alias
+       by symbol.cpp_implicit_alias.
+
 2013-05-30  Jason Merrill  <jason@redhat.com>
 
        PR c++/57404
index 409a743..3fe234e 100644 (file)
@@ -4201,7 +4201,7 @@ cp_write_global_declarations (void)
              struct cgraph_node *node, *next;
 
              node = cgraph_get_node (decl);
-             if (node->same_body_alias)
+             if (node->symbol.cpp_implicit_alias)
                node = cgraph_alias_target (node);
 
              cgraph_for_node_and_aliases (node, clear_decl_external,
index c6c41c6..9705db1 100644 (file)
@@ -1110,7 +1110,7 @@ propagate_pure_const (void)
   if (dump_file)
     {
       dump_cgraph (dump_file);
-      ipa_print_order(dump_file, "reduced", order, order_pos);
+      ipa_print_order (dump_file, "reduced", order, order_pos);
     }
 
   /* Propagate the local information through the call graph to produce
index 254c09f..5382b7a 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -139,8 +139,7 @@ process_references (struct ipa_ref_list *list,
       symtab_node node = ref->referred;
 
       if (node->symbol.definition
-         && (!DECL_EXTERNAL (node->symbol.decl)
-             || node->symbol.alias
+         && ((!DECL_EXTERNAL (node->symbol.decl) || node->symbol.alias)
              || (before_inlining_p
                  /* We use variable constructors during late complation for
                     constant folding.  Keep references alive so partitioning
@@ -297,7 +296,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
                  if (e->callee->symbol.definition
                      && (!e->inline_failed
                          || !DECL_EXTERNAL (e->callee->symbol.decl)
-                         || cnode->symbol.alias
+                         || e->callee->symbol.alias
                          || before_inlining_p))
                    pointer_set_insert (reachable, e->callee);
                  enqueue_node ((symtab_node) e->callee, &first, reachable);
index 2268f24..6699b8a 100644 (file)
@@ -377,6 +377,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   struct cgraph_node *clone_of;
   struct ipa_opt_pass_d *pass;
   int i;
+  bool alias_p;
 
   boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node);
 
@@ -485,7 +486,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
      defined in other unit, we may use the info on aliases to resolve 
      symbol1 != symbol2 type tests that we can do only for locally defined objects
      otherwise.  */
-  bp_pack_value (&bp, node->symbol.alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl)), 1);
+  alias_p = node->symbol.alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl));
+  bp_pack_value (&bp, alias_p, 1);
   bp_pack_value (&bp, node->frequency, 2);
   bp_pack_value (&bp, node->only_called_at_startup, 1);
   bp_pack_value (&bp, node->only_called_at_exit, 1);
@@ -504,15 +506,6 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
       streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset);
       streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value);
     }
-  if ((node->symbol.alias || node->thunk.thunk_p)
-      && (!boundary_p || (node->symbol.alias && DECL_EXTERNAL (node->symbol.decl))))
-    {
-      streamer_write_hwi_in_range (ob->main_stream, 0, 1,
-                                       node->thunk.alias != NULL);
-      if (node->thunk.alias != NULL)
-        lto_output_fn_decl_index (ob->decl_state, ob->main_stream,
-                                 node->thunk.alias);
-    }
 }
 
 /* Output the varpool NODE to OB. 
@@ -522,10 +515,10 @@ static void
 lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
                         lto_symtab_encoder_t encoder)
 {
-  bool boundary_p = (node->symbol.definition
-                    && !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node));
+  bool boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node);
   struct bitpack_d bp;
   int ref;
+  bool alias_p;
 
   streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
                       LTO_symtab_variable);
@@ -536,8 +529,9 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
   bp_pack_value (&bp, node->symbol.force_output, 1);
   bp_pack_value (&bp, node->symbol.unique_name, 1);
   bp_pack_value (&bp, node->symbol.definition, 1);
-  bp_pack_value (&bp, node->symbol.alias, 1);
-  bp_pack_value (&bp, node->alias_of != NULL, 1);
+  alias_p = node->symbol.alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl));
+  bp_pack_value (&bp, alias_p, 1);
+  bp_pack_value (&bp, node->symbol.analyzed && !boundary_p, 1);
   gcc_assert (node->symbol.definition || !node->symbol.analyzed);
   /* Constant pool initializers can be de-unified into individual ltrans units.
      FIXME: Alternatively at -Os we may want to avoid generating for them the local
@@ -554,12 +548,11 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
       bp_pack_value (&bp, node->symbol.definition
                     && referenced_from_other_partition_p (&node->symbol.ref_list,
                                                           encoder), 1);
-      bp_pack_value (&bp, boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1);
+      bp_pack_value (&bp, node->symbol.analyzed
+                    && boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1);
          /* in_other_partition.  */
     }
   streamer_write_bitpack (&bp);
-  if (node->alias_of)
-    lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->alias_of);
   if (node->symbol.same_comdat_group && !boundary_p)
     {
       ref = lto_symtab_encoder_lookup (encoder,
@@ -756,7 +749,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
        !lsei_end_p (lsei); lsei_next_variable_in_partition (&lsei))
     {
       struct varpool_node *vnode = lsei_varpool_node (lsei);
-      gcc_assert (!vnode->symbol.alias || vnode->alias_of);
+
       lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
       lto_set_symtab_encoder_encode_initializer (encoder, vnode);
       add_references (encoder, &vnode->symbol.ref_list);
@@ -919,6 +912,17 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
                                     LDPR_NUM_KNOWN);
 }
 
+/* Return string alias is alias of.  */
+
+static tree
+get_alias_symbol (tree decl)
+{
+  tree alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
+  gcc_assert (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)));
+  return get_identifier (TREE_STRING_POINTER
+                         (TREE_VALUE (TREE_VALUE (alias))));
+}
+
 /* Read a node from input_block IB.  TAG is the node's tag just read.
    Return the node read or overwriten.  */
 
@@ -1004,15 +1008,8 @@ input_node (struct lto_file_decl_data *file_data,
       node->thunk.virtual_value = virtual_value;
       node->thunk.virtual_offset_p = (type & 4);
     }
-  if (node->thunk.thunk_p || node->symbol.alias)
-    {
-      if (streamer_read_hwi_in_range (ib, "alias nonzero flag", 0, 1))
-       {
-          decl_index = streamer_read_uhwi (ib);
-          node->thunk.alias = lto_file_decl_data_get_fn_decl (file_data,
-                                                             decl_index);
-       }
-    }
+  if (node->symbol.alias && !node->symbol.analyzed)
+    node->symbol.alias_target = get_alias_symbol (node->symbol.decl);
   return node;
 }
 
@@ -1028,7 +1025,6 @@ input_varpool_node (struct lto_file_decl_data *file_data,
   struct varpool_node *node;
   struct bitpack_d bp;
   int ref = LCC_NOT_FOUND;
-  bool non_null_aliasof;
   int order;
 
   order = streamer_read_hwi (ib) + order_base;
@@ -1046,20 +1042,16 @@ input_varpool_node (struct lto_file_decl_data *file_data,
   node->symbol.unique_name = bp_unpack_value (&bp, 1);
   node->symbol.definition = bp_unpack_value (&bp, 1);
   node->symbol.alias = bp_unpack_value (&bp, 1);
-  non_null_aliasof = bp_unpack_value (&bp, 1);
+  node->symbol.analyzed = bp_unpack_value (&bp, 1);
   node->symbol.used_from_other_partition = bp_unpack_value (&bp, 1);
   node->symbol.in_other_partition = bp_unpack_value (&bp, 1);
-  node->symbol.analyzed = (node->symbol.definition && (!node->symbol.alias || !node->symbol.in_other_partition)); 
   if (node->symbol.in_other_partition)
     {
       DECL_EXTERNAL (node->symbol.decl) = 1;
       TREE_STATIC (node->symbol.decl) = 0;
     }
-  if (non_null_aliasof)
-    {
-      decl_index = streamer_read_uhwi (ib);
-      node->alias_of = lto_file_decl_data_get_var_decl (file_data, decl_index);
-    }
+  if (node->symbol.alias && !node->symbol.analyzed)
+    node->symbol.alias_target = get_alias_symbol (node->symbol.decl);
   ref = streamer_read_hwi (ib);
   /* Store a reference for now, and fix up later to be a pointer.  */
   node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref;
index e0db8b1..0f05d18 100644 (file)
@@ -898,7 +898,7 @@ lto_symtab_encoder_t compute_ltrans_boundary (lto_symtab_encoder_t encoder);
 
 /* In lto-symtab.c.  */
 extern void lto_symtab_merge_decls (void);
-extern void lto_symtab_merge_cgraph_nodes (void);
+extern void lto_symtab_merge_symbols (void);
 extern tree lto_symtab_prevailing_decl (tree decl);
 extern GTY(()) vec<tree, va_gc> *lto_global_var_decls;
 
index 6c433f4..2b41933 100644 (file)
@@ -542,7 +542,7 @@ lto_symtab_merge_decls (void)
 /* Helper to process the decl chain for the symbol table entry *SLOT.  */
 
 static void
-lto_symtab_merge_cgraph_nodes_1 (symtab_node prevailing)
+lto_symtab_merge_symbols_1 (symtab_node prevailing)
 {
   symtab_node e, next;
 
@@ -568,88 +568,32 @@ lto_symtab_merge_cgraph_nodes_1 (symtab_node prevailing)
    lto_symtab_merge_decls.  */
 
 void
-lto_symtab_merge_cgraph_nodes (void)
+lto_symtab_merge_symbols (void)
 {
-  struct cgraph_node *cnode;
-  struct varpool_node *vnode;
   symtab_node node;
 
-  /* Populate assembler name hash.   */
-  symtab_initialize_asm_name_hash ();
-
   if (!flag_ltrans)
-    FOR_EACH_SYMBOL (node)
-      if (lto_symtab_symbol_p (node)
-         && node->symbol.next_sharing_asm_name
-         && !node->symbol.previous_sharing_asm_name)
-        lto_symtab_merge_cgraph_nodes_1 (node);
-
-  FOR_EACH_FUNCTION (cnode)
-    {
-      /* Resolve weakrefs to symbol defined in other unit.  */
-      if (!cnode->symbol.analyzed && cnode->thunk.alias && !DECL_P (cnode->thunk.alias))
-       {
-         symtab_node node = symtab_node_for_asm (cnode->thunk.alias);
-         if (node && is_a <cgraph_node> (node))
-           {
-             struct cgraph_node *n;
-
-             for (n = cgraph (node); n && n->symbol.alias;
-                  n = n->symbol.analyzed ? cgraph_alias_target (n) : NULL)
-               if (n == cnode)
-                 {
-                   error ("function %q+D part of alias cycle", cnode->symbol.decl);
-                   cnode->symbol.alias = false;
-                   break;
-                 }
-             if (cnode->symbol.alias)
-               {
-                 cgraph_create_function_alias (cnode->symbol.decl, node->symbol.decl);
-                 ipa_record_reference ((symtab_node)cnode, (symtab_node)node,
-                                       IPA_REF_ALIAS, NULL);
-                 cnode->symbol.analyzed = true;
-               }
-           }
-         else if (node)
-           error ("%q+D alias in between function and variable is not supported", cnode->symbol.decl);
-       }
-      if ((cnode->thunk.thunk_p || cnode->symbol.alias)
-         && cnode->thunk.alias && DECL_P (cnode->thunk.alias))
-        cnode->thunk.alias = lto_symtab_prevailing_decl (cnode->thunk.alias);
-      cnode->symbol.aux = NULL;
-    }
-  FOR_EACH_VARIABLE (vnode)
     {
-      /* Resolve weakrefs to symbol defined in other unit.  */
-      if (!vnode->symbol.analyzed && vnode->alias_of && !DECL_P (vnode->alias_of))
+      symtab_initialize_asm_name_hash ();
+
+      /* Do the actual merging.  */
+      FOR_EACH_SYMBOL (node)
+       if (lto_symtab_symbol_p (node)
+           && node->symbol.next_sharing_asm_name
+           && !node->symbol.previous_sharing_asm_name)
+         lto_symtab_merge_symbols_1 (node);
+
+      /* Resolve weakref aliases whose target are now in the compilation unit.  */
+      FOR_EACH_SYMBOL (node)
        {
-         symtab_node node = symtab_node_for_asm (vnode->alias_of);
-         if (node && is_a <cgraph_node> (node))
+         if (!node->symbol.analyzed && node->symbol.alias_target)
            {
-             struct varpool_node *n;
-
-             for (n = varpool (node); n && n->symbol.alias;
-                  n = n->symbol.analyzed ? varpool_alias_target (n) : NULL)
-               if (n == vnode)
-                 {
-                   error ("function %q+D part of alias cycle", vnode->symbol.decl);
-                   vnode->symbol.alias = false;
-                   break;
-                 }
-             if (vnode->symbol.alias)
-               {
-                 varpool_create_variable_alias (vnode->symbol.decl, node->symbol.decl);
-                 ipa_record_reference ((symtab_node)vnode, (symtab_node)node,
-                                       IPA_REF_ALIAS, NULL);
-                 vnode->symbol.analyzed = true;
-               }
+             symtab_node tgt = symtab_node_for_asm (node->symbol.alias_target);
+             if (tgt)
+               symtab_resolve_alias (node, tgt);
            }
-         else if (node)
-           error ("%q+D alias in between function and variable is not supported", vnode->symbol.decl);
+         node->symbol.aux = NULL;
        }
-      if (vnode->symbol.alias && DECL_P (vnode->alias_of))
-        vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
-      vnode->symbol.aux = NULL;
     }
 }
 
index ded1056..0a01c1b 100644 (file)
@@ -1,3 +1,9 @@
+2013-06-01  Jan Hubicka  <jh@suse.cz>
+
+       * lto.c (read_cgraph_and_symbols): Simplify dumping; Replace
+       lto_symtab_merge_cgraph_nodes by lto_symtab_merge_symbols.
+       (do_whole_program_analysis): Update dumping.
+
 2013-05-29  Jan Hubicka  <jh@suse.cz>
 
        * lto.c (has_analyzed_clone_p, lto_materialize_function): Update for new symtab
index f2a59d3..05867e1 100644 (file)
@@ -3033,10 +3033,9 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
   if (cgraph_dump_file)
     {
       fprintf (cgraph_dump_file, "Before merging:\n");
-      dump_cgraph (cgraph_dump_file);
-      dump_varpool (cgraph_dump_file);
+      dump_symtab (cgraph_dump_file);
     }
-  lto_symtab_merge_cgraph_nodes ();
+  lto_symtab_merge_symbols ();
   ggc_collect ();
 
   /* FIXME: ipa_transforms_to_apply holds list of passes that have optimization
@@ -3169,10 +3168,7 @@ do_whole_program_analysis (void)
   cgraph_function_flags_ready = true;
 
   if (cgraph_dump_file)
-    {
-      dump_cgraph (cgraph_dump_file);
-      dump_varpool (cgraph_dump_file);
-    }
+    dump_symtab (cgraph_dump_file);
   bitmap_obstack_initialize (NULL);
   cgraph_state = CGRAPH_STATE_IPA_SSA;
 
@@ -3182,8 +3178,7 @@ do_whole_program_analysis (void)
   if (cgraph_dump_file)
     {
       fprintf (cgraph_dump_file, "Optimized ");
-      dump_cgraph (cgraph_dump_file);
-      dump_varpool (cgraph_dump_file);
+      dump_symtab (cgraph_dump_file);
     }
 #ifdef ENABLE_CHECKING
   verify_cgraph ();
index feaf322..2a29d9f 100644 (file)
@@ -2461,6 +2461,7 @@ ipa_write_summaries (void)
   lto_symtab_encoder_t encoder;
   int i, order_pos;
   struct varpool_node *vnode;
+  struct cgraph_node *node;
   struct cgraph_node **order;
 
   if (!flag_generate_lto || seen_error ())
@@ -2496,9 +2497,11 @@ ipa_write_summaries (void)
         lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
     }
 
+  FOR_EACH_DEFINED_FUNCTION (node)
+    if (node->symbol.alias)
+      lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
   FOR_EACH_DEFINED_VARIABLE (vnode)
-    if ((!vnode->symbol.alias || vnode->alias_of))
-      lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
+    lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
 
   ipa_write_summaries_1 (compute_ltrans_boundary (encoder));
 
index 1a7f826..af8e70b 100644 (file)
@@ -481,6 +481,14 @@ dump_symtab_base (FILE *f, symtab_node node)
     fprintf (f, " analyzed");
   if (node->symbol.alias)
     fprintf (f, " alias");
+  if (node->symbol.cpp_implicit_alias)
+    fprintf (f, " cpp_implicit_alias");
+  if (node->symbol.alias_target)
+    fprintf (f, " target:%s",
+            DECL_P (node->symbol.alias_target) 
+            ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME
+                                    (node->symbol.alias_target))
+            : IDENTIFIER_POINTER (node->symbol.alias_target));
   fprintf (f, "\n  Visibility:");
   if (node->symbol.in_other_partition)
     fprintf (f, " in_other_partition");
@@ -666,6 +674,17 @@ verify_symtab_base (symtab_node node)
       error ("node is analyzed byt it is not a definition");
       error_found = true;
     }
+  if (node->symbol.cpp_implicit_alias && !node->symbol.alias)
+    {
+      error ("node is alias but not implicit alias");
+      error_found = true;
+    }
+  if (node->symbol.alias && !node->symbol.definition
+      && !lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
+    {
+      error ("node is alias but not definition");
+      error_found = true;
+    }
   if (node->symbol.same_comdat_group)
     {
       symtab_node n = node->symbol.same_comdat_group;
@@ -757,6 +776,7 @@ symtab_used_from_object_file_p (symtab_node node)
 
 /* Make DECL local.  FIXME: We shouldn't need to mess with rtl this early,
    but other code such as notice_global_symbol generates rtl.  */
+
 void
 symtab_make_decl_local (tree decl)
 {
@@ -796,6 +816,17 @@ symtab_make_decl_local (tree decl)
   SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl);
 }
 
+/* Return availability of NODE.  */
+
+enum availability
+symtab_node_availability (symtab_node node)
+{
+  if (is_a <cgraph_node> (node))
+    return cgraph_function_body_availability (cgraph (node));
+  else
+    return cgraph_variable_initializer_availability (varpool (node));
+}
+
 /* Given NODE, walk the alias chain to return the symbol NODE is alias of.
    If NODE is not an alias, return NODE.
    When AVAILABILITY is non-NULL, get minimal availability in the chain.  */
@@ -804,12 +835,7 @@ symtab_node
 symtab_alias_ultimate_target (symtab_node node, enum availability *availability)
 {
   if (availability)
-    {
-      if (is_a <cgraph_node> (node))
-        *availability = cgraph_function_body_availability (cgraph (node));
-      else
-        *availability = cgraph_variable_initializer_availability (varpool (node));
-    }
+    *availability = symtab_node_availability (node);
   while (node)
     {
       if (node->symbol.alias && node->symbol.analyzed)
@@ -818,11 +844,7 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability)
        return node;
       if (node && availability)
        {
-         enum availability a;
-         if (is_a <cgraph_node> (node))
-           a = cgraph_function_body_availability (cgraph (node));
-         else
-           a = cgraph_variable_initializer_availability (varpool (node));
+         enum availability a = symtab_node_availability (node);
          if (a < *availability)
            *availability = a;
        }
@@ -831,4 +853,93 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability)
     *availability = AVAIL_NOT_AVAILABLE;
   return NULL;
 }
+
+/* C++ FE sometimes change linkage flags after producing same body aliases.
+
+   FIXME: C++ produce implicit aliases for virtual functions and vtables that
+   are obviously equivalent.  The way it is doing so is however somewhat
+   kludgy and interferes with the visibility code. As a result we need to
+   copy the visibility from the target to get things right.  */
+
+void
+fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target)
+{
+  if (is_a <cgraph_node> (node))
+    {
+      DECL_DECLARED_INLINE_P (node->symbol.decl)
+        = DECL_DECLARED_INLINE_P (target->symbol.decl);
+      DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl)
+        = DECL_DISREGARD_INLINE_LIMITS (target->symbol.decl);
+    }
+  /* FIXME: It is not really clear why those flags should not be copied for
+     functions, too.  */
+  else
+    {
+      DECL_WEAK (node->symbol.decl) = DECL_WEAK (target->symbol.decl);
+      DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (target->symbol.decl);
+      DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (target->symbol.decl);
+    }
+  DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (target->symbol.decl);
+  if (TREE_PUBLIC (node->symbol.decl))
+    {
+      DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (target->symbol.decl);
+      DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (target->symbol.decl);
+      DECL_COMDAT_GROUP (node->symbol.decl)
+        = DECL_COMDAT_GROUP (target->symbol.decl);
+      if (DECL_ONE_ONLY (target->symbol.decl)
+         && !node->symbol.same_comdat_group)
+       symtab_add_to_same_comdat_group ((symtab_node)node, (symtab_node)target);
+    }
+  node->symbol.externally_visible = target->symbol.externally_visible;
+}
+
+/* Add reference recording that NODE is alias of TARGET.
+   The function can fail in the case of aliasing cycles; in this case
+   it returns false.  */
+
+bool
+symtab_resolve_alias (symtab_node node, symtab_node target)
+{
+  symtab_node n;
+
+  gcc_assert (!node->symbol.analyzed
+             && !vec_safe_length (node->symbol.ref_list.references));
+
+  /* Never let cycles to creep into the symbol table alias references;
+     those will make alias walkers to be infinite.  */
+  for (n = target; n && n->symbol.alias;
+       n = n->symbol.analyzed ? symtab_alias_target (n) : NULL)
+    if (n == node)
+       {
+        if (is_a <cgraph_node> (node))
+           error ("function %q+D part of alias cycle", node->symbol.decl);
+         else if (is_a <varpool_node> (node))
+           error ("variable %q+D part of alias cycle", node->symbol.decl);
+        else
+          gcc_unreachable ();
+        node->symbol.alias = false;
+        return false;
+       }
+
+  /* "analyze" the node - i.e. mark the reference.  */
+  node->symbol.definition = true;
+  node->symbol.alias = true;
+  node->symbol.analyzed = true;
+  ipa_record_reference (node, target, IPA_REF_ALIAS, NULL);
+
+  /* Alias targets become reudndant after alias is resolved into an reference.
+     We do not want to keep it around or we would have to mind updating them
+     when renaming symbols.  */
+  node->symbol.alias_target = NULL;
+  DECL_ATTRIBUTES (node->symbol.decl)
+     = remove_attribute ("alias", DECL_ATTRIBUTES (node->symbol.decl));
+
+  if (node->symbol.cpp_implicit_alias && cgraph_state >= CGRAPH_STATE_CONSTRUCTION)
+    fixup_same_cpp_alias_visibility (node, target);
+
+  /* If alias has address taken, so does the target.  */
+  if (node->symbol.address_taken)
+    symtab_alias_ultimate_target (target, NULL)->symbol.address_taken = true;
+  return true;
+}
 #include "gt-symtab.h"
index d7e5a40..03aba75 100644 (file)
@@ -3933,7 +3933,7 @@ get_cg_data (struct cgraph_node **node, bool traverse_aliases)
   struct tm_ipa_cg_data *d;
 
   if (traverse_aliases && (*node)->symbol.alias)
-    *node = cgraph_get_node ((*node)->thunk.alias);
+    *node = cgraph_alias_target (*node);
 
   d = (struct tm_ipa_cg_data *) (*node)->symbol.aux;
 
@@ -4699,7 +4699,7 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data)
   tree old_decl, new_decl, tm_name;
   struct cgraph_node *new_node;
 
-  if (!node->same_body_alias)
+  if (!node->symbol.cpp_implicit_alias)
     return false;
 
   old_decl = node->symbol.decl;
@@ -5369,7 +5369,7 @@ ipa_tm_execute (void)
       bool doit = false;
 
       node = tm_callees[i];
-      if (node->same_body_alias)
+      if (node->symbol.cpp_implicit_alias)
        continue;
 
       a = cgraph_function_body_availability (node);
index 9fecb6c..6329fdd 100644 (file)
@@ -699,7 +699,9 @@ create_emultls_var (struct varpool_node *var, void *data)
   tree cdecl;
   struct varpool_node *cvar;
 
-  cdecl = new_emutls_decl (var->symbol.decl, var->alias_of);
+  cdecl = new_emutls_decl (var->symbol.decl,
+                          var->symbol.alias && var->symbol.analyzed
+                          ? varpool_alias_target (var)->symbol.decl : NULL);
 
   cvar = varpool_get_node (cdecl);
   control_vars.quick_push (cvar);
@@ -711,7 +713,7 @@ create_emultls_var (struct varpool_node *var, void *data)
         need to do this once for the main variable.  */
       emutls_common_1 (var->symbol.decl, cdecl, (tree *)data);
     }
-  if (var->symbol.alias && !var->alias_of)
+  if (var->symbol.alias && !var->symbol.analyzed)
     cvar->symbol.alias = true;
 
   /* Indicate that the value of the TLS variable may be found elsewhere,
@@ -767,7 +769,7 @@ ipa_lower_emutls (void)
     {
       var = tls_vars->nodes[i];
 
-      if (var->symbol.alias && !var->alias_of)
+      if (var->symbol.alias && !var->symbol.analyzed)
        any_aliases = true;
       else if (!var->symbol.alias)
        varpool_for_node_and_aliases (var, create_emultls_var, &ctor_body, true);
index 1916b76..7915a95 100644 (file)
@@ -240,30 +240,9 @@ varpool_analyze_node (struct varpool_node *node)
         already informed about increased alignment.  */
       align_variable (decl, 0);
     }
-  if (node->symbol.alias && node->alias_of)
-    {
-      struct varpool_node *tgt = varpool_node_for_decl (node->alias_of);
-      struct varpool_node *n;
-
-      for (n = tgt; n && n->symbol.alias;
-          n = n->symbol.analyzed ? varpool_alias_target (n) : NULL)
-       if (n == node)
-         {
-           error ("variable %q+D part of alias cycle", node->symbol.decl);
-           node->symbol.alias = false;
-           continue;
-         }
-      if (!vec_safe_length (node->symbol.ref_list.references))
-       ipa_record_reference ((symtab_node)node, (symtab_node)tgt, IPA_REF_ALIAS, NULL);
-      if (node->extra_name_alias)
-       {
-         DECL_WEAK (node->symbol.decl) = DECL_WEAK (node->alias_of);
-         DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (node->alias_of);
-         DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (node->alias_of);
-         fixup_same_cpp_alias_visibility ((symtab_node) node,
-                                          (symtab_node) tgt, node->alias_of);
-       }
-    }
+  if (node->symbol.alias)
+    symtab_resolve_alias
+       ((symtab_node) node, (symtab_node) varpool_get_node (node->symbol.alias_target));
   else if (DECL_INITIAL (decl))
     record_references_in_initializer (decl, node->symbol.analyzed);
   node->symbol.analyzed = true;
@@ -281,7 +260,7 @@ assemble_aliases (struct varpool_node *node)
       {
        struct varpool_node *alias = ipa_ref_referring_varpool_node (ref);
        do_assemble_alias (alias->symbol.decl,
-                       DECL_ASSEMBLER_NAME (alias->alias_of));
+                          DECL_ASSEMBLER_NAME (node->symbol.decl));
        assemble_aliases (alias);
       }
 }
@@ -494,18 +473,7 @@ varpool_create_variable_alias (tree alias, tree decl)
   alias_node = varpool_node_for_decl (alias);
   alias_node->symbol.alias = true;
   alias_node->symbol.definition = true;
-  alias_node->alias_of = decl;
-
-  /* Extra name alias mechanizm creates aliases really late
-     via DECL_ASSEMBLER_NAME mechanizm.
-     This is unfortunate because they are not going through the
-     standard channels.  Ensure they get output.  */
-  if (cgraph_state >= CGRAPH_STATE_IPA)
-    {
-      varpool_analyze_node (alias_node);
-      if (TREE_PUBLIC (alias))
-       alias_node->symbol.externally_visible = true;
-    }
+  alias_node->symbol.alias_target = decl;
   return alias_node;
 }
 
@@ -522,7 +490,15 @@ varpool_extra_name_alias (tree alias, tree decl)
   return NULL;
 #endif
   alias_node = varpool_create_variable_alias (alias, decl);
-  alias_node->extra_name_alias = true;
+  alias_node->symbol.cpp_implicit_alias = true;
+
+  /* Extra name alias mechanizm creates aliases really late
+     via DECL_ASSEMBLER_NAME mechanizm.
+     This is unfortunate because they are not going through the
+     standard channels.  Ensure they get output.  */
+  if (cpp_implicit_aliases_done)
+    symtab_resolve_alias ((symtab_node)alias_node,
+                         (symtab_node)varpool_node_for_decl (decl));
   return alias_node;
 }