Esempio n. 1
0
bool
symtab_semantically_equivalent_p (symtab_node *a,
				  symtab_node *b)
{
  enum availability avail;
  symtab_node *ba;
  symtab_node *bb;

  /* Equivalent functions are equivalent.  */
  if (a->decl == b->decl)
    return true;

  /* If symbol is not overwritable by different implementation,
     walk to the base object it defines.  */
  ba = symtab_alias_ultimate_target (a, &avail);
  if (avail >= AVAIL_AVAILABLE)
    {
      if (ba == b)
	return true;
    }
  else
    ba = a;
  bb = symtab_alias_ultimate_target (b, &avail);
  if (avail >= AVAIL_AVAILABLE)
    {
      if (a == bb)
	return true;
    }
  else
    bb = b;
  return bb == ba;
}
Esempio n. 2
0
symtab_node *
symtab_nonoverwritable_alias (symtab_node *node)
{
  tree new_decl;
  symtab_node *new_node = NULL;

  /* First try to look up existing alias or base object
     (if that is already non-overwritable).  */
  node = symtab_alias_ultimate_target (node, NULL);
  gcc_assert (!node->alias && !node->weakref);
  symtab_for_node_and_aliases (node, symtab_nonoverwritable_alias_1,
		               (void *)&new_node, true);
  if (new_node)
    return new_node;
#ifndef ASM_OUTPUT_DEF
  /* If aliases aren't supported by the assembler, fail.  */
  return NULL;
#endif

  /* Otherwise create a new one.  */
  new_decl = copy_node (node->decl);
  DECL_DLLIMPORT_P (new_decl) = 0;
  DECL_NAME (new_decl) = clone_function_name (node->decl, "localalias");
  if (TREE_CODE (new_decl) == FUNCTION_DECL)
    DECL_STRUCT_FUNCTION (new_decl) = NULL;
  DECL_INITIAL (new_decl) = NULL;
  SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
  SET_DECL_RTL (new_decl, NULL);

  /* Update the properties.  */
  DECL_EXTERNAL (new_decl) = 0;
  if (DECL_ONE_ONLY (node->decl))
    DECL_SECTION_NAME (new_decl) = NULL;
  DECL_COMDAT_GROUP (new_decl) = 0;
  TREE_PUBLIC (new_decl) = 0;
  DECL_COMDAT (new_decl) = 0;
  DECL_WEAK (new_decl) = 0;
  DECL_VIRTUAL_P (new_decl) = 0;
  if (TREE_CODE (new_decl) == FUNCTION_DECL)
    {
      DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
      DECL_STATIC_DESTRUCTOR (new_decl) = 0;
      new_node = cgraph_create_function_alias
				 (new_decl, node->decl);
    }
  else
    new_node = varpool_create_variable_alias (new_decl,
							    node->decl);
  symtab_resolve_alias (new_node, node);  
  gcc_assert (decl_binds_to_current_def_p (new_decl));
  return new_node;
}
Esempio n. 3
0
void
enqueue_references (symtab_node **first,
		    symtab_node *symbol)
{
  int i;
  struct ipa_ref *ref;

  for (i = 0; ipa_ref_list_reference_iterate (&symbol->ref_list, i, ref); i++)
    {
      symtab_node *node = symtab_alias_ultimate_target (ref->referred, NULL);
      if (!node->aux && node->definition)
	{
	   node->aux = *first;
	   *first = node;
	}
    }

  if (cgraph_node *cnode = dyn_cast <cgraph_node *> (symbol))
    {
      struct cgraph_edge *edge;

      for (edge = cnode->callees; edge; edge = edge->next_callee)
	if (!edge->inline_failed)
	  enqueue_references (first, edge->callee);
	else
	  {
	    symtab_node *node = symtab_alias_ultimate_target (edge->callee,
							      NULL);
	    if (!node->aux && node->definition)
	      {
		 node->aux = *first;
		 *first = node;
	      }
	  }
    }
}
Esempio n. 4
0
File: symtab.c Progetto: Roffi/gcc
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;

  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;
}
Esempio n. 5
0
static unsigned int
ipa_comdats (void)
{
  pointer_map<tree> map;
  pointer_map<symtab_node *> comdat_head_map;
  symtab_node *symbol;
  bool comdat_group_seen = false;
  symtab_node *first = (symtab_node *) (void *) 1;
  tree group;

  /* Start the dataflow by assigning comdat group to symbols that are in comdat
     groups already.  All other externally visible symbols must stay, we use
     ERROR_MARK_NODE as bottom for the propagation.  */

  FOR_EACH_DEFINED_SYMBOL (symbol)
    if (!symtab_real_symbol_p (symbol))
      ;
    else if ((group = symbol->get_comdat_group ()) != NULL)
      {
        *map.insert (symbol) = group;
        *comdat_head_map.insert (group) = symbol;
	comdat_group_seen = true;

	/* Mark the symbol so we won't waste time visiting it for dataflow.  */
	symbol->aux = (symtab_node *) (void *) 1;
      }
    /* See symbols that can not be privatized to comdats; that is externally
       visible symbols or otherwise used ones.  We also do not want to mangle
       user section names.  */
    else if (symbol->externally_visible
	     || symbol->force_output
	     || symbol->used_from_other_partition
	     || TREE_THIS_VOLATILE (symbol->decl)
	     || symbol->get_section ()
	     || (TREE_CODE (symbol->decl) == FUNCTION_DECL
		 && (DECL_STATIC_CONSTRUCTOR (symbol->decl)
		     || DECL_STATIC_DESTRUCTOR (symbol->decl))))
      {
	*map.insert (symtab_alias_ultimate_target (symbol, NULL)) = error_mark_node;

	/* Mark the symbol so we won't waste time visiting it for dataflow.  */
	symbol->aux = (symtab_node *) (void *) 1;
      }
    else
      {
	/* Enqueue symbol for dataflow.  */
        symbol->aux = first;
	first = symbol;
      }

  if (!comdat_group_seen)
    {
      FOR_EACH_DEFINED_SYMBOL (symbol)
        symbol->aux = NULL;
      return 0;
    }

  /* The actual dataflow.  */

  while (first != (void *) 1)
    {
      tree group = NULL;
      tree newgroup, *val;

      symbol = first;
      first = (symtab_node *)first->aux;

      /* Get current lattice value of SYMBOL.  */
      val = map.contains (symbol);
      if (val)
	group = *val;

      /* If it is bottom, there is nothing to do; do not clear AUX
	 so we won't re-queue the symbol.  */
      if (group == error_mark_node)
	continue;

      newgroup = propagate_comdat_group (symbol, group, map);

      /* If nothing changed, proceed to next symbol.  */
      if (newgroup == group)
	{
	  symbol->aux = NULL;
	  continue;
	}

      /* Update lattice value and enqueue all references for re-visiting.  */
      gcc_assert (newgroup);
      if (val)
	*val = newgroup;
      else
	*map.insert (symbol) = newgroup;
      enqueue_references (&first, symbol);

      /* We may need to revisit the symbol unless it is BOTTOM.  */
      if (newgroup != error_mark_node)
        symbol->aux = NULL;
    }

  /* Finally assign symbols to the sections.  */

  FOR_EACH_DEFINED_SYMBOL (symbol)
    {
      symbol->aux = NULL; 
      if (!symbol->get_comdat_group ()
	  && !symbol->alias
	  && symtab_real_symbol_p (symbol))
	{
	  tree group = *map.contains (symbol);

	  if (group == error_mark_node)
	    continue;
	  if (dump_file)
	    {
	      fprintf (dump_file, "Localizing symbol\n");
	      dump_symtab_node (dump_file, symbol);
	      fprintf (dump_file, "To group: %s\n", IDENTIFIER_POINTER (group));
	    }
	  symtab_for_node_and_aliases (symbol, set_comdat_group,
				       *comdat_head_map.contains (group), true);
	}
    }
  return 0;
}