Esempio n. 1
0
static void
lto_symtab_merge_symbols_1 (symtab_node prevailing)
{
  symtab_node e, next;

  /* Replace the cgraph node of each entry with the prevailing one.  */
  for (e = prevailing->symbol.next_sharing_asm_name; e;
       e = next)
    {
      next = e->symbol.next_sharing_asm_name;

      if (!lto_symtab_symbol_p (e))
	continue;
      cgraph_node *ce = dyn_cast <cgraph_node> (e);
      if (ce && !DECL_BUILT_IN (e->symbol.decl))
	lto_cgraph_replace_node (ce, cgraph (prevailing));
      if (varpool_node *ve = dyn_cast <varpool_node> (e))
	lto_varpool_replace_node (ve, varpool (prevailing));
    }

  return;
}
Esempio n. 2
0
void
lto_symtab_merge_symbols (void)
{
  symtab_node *node;

  if (!flag_ltrans)
    {
      symtab->symtab_initialize_asm_name_hash ();

      /* Do the actual merging.  
         At this point we invalidate hash translating decls into symtab nodes
	 because after removing one of duplicate decls the hash is not correcly
	 updated to the ohter dupliate.  */
      FOR_EACH_SYMBOL (node)
	if (lto_symtab_symbol_p (node)
	    && node->next_sharing_asm_name
	    && !node->previous_sharing_asm_name)
	  lto_symtab_merge_symbols_1 (node);

      /* Resolve weakref aliases whose target are now in the compilation unit.  
	 also re-populate the hash translating decls into symtab nodes*/
      FOR_EACH_SYMBOL (node)
	{
	  cgraph_node *cnode, *cnode2;
	  varpool_node *vnode;
	  symtab_node *node2;

	  if (!node->analyzed && node->alias_target)
	    {
	      symtab_node *tgt = symtab_node::get_for_asmname (node->alias_target);
	      gcc_assert (node->weakref);
	      if (tgt)
		node->resolve_alias (tgt, true);
	    }
	  /* If the symbol was preempted outside IR, see if we want to get rid
	     of the definition.  */
	  if (node->analyzed
	      && !DECL_EXTERNAL (node->decl)
	      && (node->resolution == LDPR_PREEMPTED_REG
		  || node->resolution == LDPR_RESOLVED_IR
		  || node->resolution == LDPR_RESOLVED_EXEC
		  || node->resolution == LDPR_RESOLVED_DYN))
	    {
	      DECL_EXTERNAL (node->decl) = 1;
	      /* If alias to local symbol was preempted by external definition,
		 we know it is not pointing to the local symbol.  Remove it.  */
	      if (node->alias
		  && !node->weakref
		  && !node->transparent_alias
		  && node->get_alias_target ()->binds_to_current_def_p ())
		{
		  node->alias = false;
		  node->remove_all_references ();
		  node->definition = false;
		  node->analyzed = false;
		  node->cpp_implicit_alias = false;
		}
	      else if (!node->alias
		       && node->definition
		       && node->get_availability () <= AVAIL_INTERPOSABLE)
		{
		  if ((cnode = dyn_cast <cgraph_node *> (node)) != NULL)
		    cnode->reset ();
		  else
		    {
		      node->analyzed = node->definition = false;
		      node->remove_all_references ();
		    }
		}
	    }

	  if (!(cnode = dyn_cast <cgraph_node *> (node))
	      || !cnode->clone_of
	      || cnode->clone_of->decl != cnode->decl)
	    {
	      /* Builtins are not merged via decl merging.  It is however
		 possible that tree merging unified the declaration.  We
		 do not want duplicate entries in symbol table.  */
	      if (cnode && DECL_BUILT_IN (node->decl)
		  && (cnode2 = cgraph_node::get (node->decl))
		  && cnode2 != cnode)
		lto_cgraph_replace_node (cnode2, cnode);

	      /* The user defined assembler variables are also not unified by their
		 symbol name (since it is irrelevant), but we need to unify symbol
		 nodes if tree merging occurred.  */
	      if ((vnode = dyn_cast <varpool_node *> (node))
		  && DECL_HARD_REGISTER (vnode->decl)
		  && (node2 = symtab_node::get (vnode->decl))
		  && node2 != node)
		lto_varpool_replace_node (dyn_cast <varpool_node *> (node2),
					  vnode);
	  

	      /* Abstract functions may have duplicated cgraph nodes attached;
		 remove them.  */
	      else if (cnode && DECL_ABSTRACT_P (cnode->decl)
		       && (cnode2 = cgraph_node::get (node->decl))
		       && cnode2 != cnode)
		cnode2->remove ();

	      node->decl->decl_with_vis.symtab_node = node;
	    }
	}
    }
Esempio n. 3
0
static void
lto_symtab_merge_symbols_1 (symtab_node *prevailing)
{
  symtab_node *e;
  symtab_node *next;

  prevailing->decl->decl_with_vis.symtab_node = prevailing;

  /* Replace the cgraph node of each entry with the prevailing one.  */
  for (e = prevailing->next_sharing_asm_name; e;
       e = next)
    {
      next = e->next_sharing_asm_name;

      if (!lto_symtab_symbol_p (e))
	continue;
      cgraph_node *ce = dyn_cast <cgraph_node *> (e);
      symtab_node *to = symtab_node::get (lto_symtab_prevailing_decl (e->decl));

      /* No matter how we are going to deal with resolution, we will ultimately
	 use prevailing definition.  */
      if (ce)
          ipa_merge_profiles (dyn_cast<cgraph_node *> (prevailing),
			      dyn_cast<cgraph_node *> (e));

      /* If we decided to replace the node by TO, do it.  */
      if (e != to)
	{
	  if (ce)
	    lto_cgraph_replace_node (ce, dyn_cast<cgraph_node *> (to));
	  else if (varpool_node *ve = dyn_cast <varpool_node *> (e))
	    lto_varpool_replace_node (ve, dyn_cast<varpool_node *> (to));
	}
      /* Watch out for duplicated symbols for a given declaration.  */
      else if (!e->transparent_alias
	       || !e->definition || e->get_alias_target () != to)
	{
	  /* We got a new declaration we do not want to merge.  In this case
	     get rid of the existing definition and create a transparent
	     alias.  */
	  if (ce)
	    {
	      lto_free_function_in_decl_state_for_node (ce);
	      if (!ce->weakref)
	        ce->release_body ();
	      ce->reset ();
	      symtab->call_cgraph_removal_hooks (ce);
	    }
	  else
	    {
	      DECL_INITIAL (e->decl) = error_mark_node;
	      if (e->lto_file_data)
		{
		  lto_free_function_in_decl_state_for_node (e);
		  e->lto_file_data = NULL;
		}
	      symtab->call_varpool_removal_hooks (dyn_cast<varpool_node *> (e));
	    }
	  e->remove_all_references ();
	  e->analyzed = e->body_removed = false;
	  e->resolve_alias (prevailing, true);
	  gcc_assert (e != prevailing);
	}
    }

  return;
}