Example #1
0
static bool
lto_symtab_symbol_p (symtab_node e)
{
  if (!TREE_PUBLIC (e->symbol.decl) && !DECL_EXTERNAL (e->symbol.decl))
    return false;
  return symtab_real_symbol_p (e);
}
Example #2
0
void
build_type_inheritance_graph (void)
{
  struct cgraph_node *n;
  FILE *inheritance_dump_file;
  int flags;

  if (odr_hash.is_created ())
    return;
  timevar_push (TV_IPA_INHERITANCE);
  inheritance_dump_file = dump_begin (TDI_inheritance, &flags);
  odr_hash.create (23);

  /* We reconstruct the graph starting of types of all methods seen in the
     the unit.  */
  FOR_EACH_FUNCTION (n)
    if (DECL_VIRTUAL_P (n->decl)
	&& symtab_real_symbol_p (n))
      get_odr_type (method_class_type (TREE_TYPE (n->decl)), true);
  if (inheritance_dump_file)
    {
      dump_type_inheritance_graph (inheritance_dump_file);
      dump_end (TDI_inheritance, inheritance_dump_file);
    }
  timevar_pop (TV_IPA_INHERITANCE);
}
Example #3
0
static void
maybe_record_node (vec <cgraph_node *> &nodes,
		   tree target, pointer_set_t *inserted,
		   bool *completep)
{
  struct cgraph_node *target_node;
  enum built_in_function fcode;

  if (!target
      /* Those are used to mark impossible scenarios.  */
      || (fcode = DECL_FUNCTION_CODE (target))
	  == BUILT_IN_UNREACHABLE
      || fcode == BUILT_IN_TRAP)
    return;

  target_node = cgraph_get_node (target);

  if (target_node != NULL
      && (TREE_PUBLIC (target)
	  || target_node->definition)
      && symtab_real_symbol_p (target_node))
    {
      gcc_assert (!target_node->global.inlined_to);
      gcc_assert (symtab_real_symbol_p (target_node));
      if (!pointer_set_insert (inserted, target))
	{
	  pointer_set_insert (cached_polymorphic_call_targets,
			      target_node);
	  nodes.safe_push (target_node);
	}
    }
  else if (completep
	   && !type_in_anonymous_namespace_p
		 (method_class_type (TREE_TYPE (target))))
    *completep = true;
}
Example #4
0
static void
maybe_record_node (vec <cgraph_node *> &nodes,
		   tree target, pointer_set_t *inserted)
{
  struct cgraph_node *target_node;
  enum built_in_function fcode;

  if (target
      /* Those are used to mark impossible scenarios.  */
      && (fcode = DECL_FUNCTION_CODE (target))
	  != BUILT_IN_UNREACHABLE
      && fcode != BUILT_IN_TRAP
      && !pointer_set_insert (inserted, target)
      && (target_node = cgraph_get_node (target)) != NULL
      && (TREE_PUBLIC (target)
	  || target_node->symbol.definition)
      && symtab_real_symbol_p ((symtab_node)target_node))
    {
      pointer_set_insert (cached_polymorphic_call_targets,
			  target_node);
      nodes.safe_push (target_node);
    }
}
Example #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;
}