Exemplo n.º 1
0
static void
pack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
{
  /* For normal/md builtins we only write the class and code, so they
     should never be handled here.  */
  gcc_assert (!streamer_handle_as_builtin_p (expr));

  bp_pack_enum (bp, built_in_class, BUILT_IN_LAST,
		DECL_BUILT_IN_CLASS (expr));
  bp_pack_value (bp, DECL_STATIC_CONSTRUCTOR (expr), 1);
  bp_pack_value (bp, DECL_STATIC_DESTRUCTOR (expr), 1);
  bp_pack_value (bp, DECL_UNINLINABLE (expr), 1);
  bp_pack_value (bp, DECL_POSSIBLY_INLINED (expr), 1);
  bp_pack_value (bp, DECL_IS_NOVOPS (expr), 1);
  bp_pack_value (bp, DECL_IS_RETURNS_TWICE (expr), 1);
  bp_pack_value (bp, DECL_IS_MALLOC (expr), 1);
  bp_pack_value (bp, DECL_IS_OPERATOR_NEW (expr), 1);
  bp_pack_value (bp, DECL_DECLARED_INLINE_P (expr), 1);
  bp_pack_value (bp, DECL_STATIC_CHAIN (expr), 1);
  bp_pack_value (bp, DECL_NO_INLINE_WARNING_P (expr), 1);
  bp_pack_value (bp, DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (expr), 1);
  bp_pack_value (bp, DECL_NO_LIMIT_STACK (expr), 1);
  bp_pack_value (bp, DECL_DISREGARD_INLINE_LIMITS (expr), 1);
  bp_pack_value (bp, DECL_PURE_P (expr), 1);
  bp_pack_value (bp, DECL_LOOPING_CONST_OR_PURE_P (expr), 1);
  if (DECL_BUILT_IN_CLASS (expr) != NOT_BUILT_IN)
    bp_pack_value (bp, DECL_FUNCTION_CODE (expr), 11);
  if (DECL_STATIC_DESTRUCTOR (expr))
    bp_pack_var_len_unsigned (bp, DECL_FINI_PRIORITY (expr));
}
Exemplo n.º 2
0
static void
unpack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
{
  DECL_BUILT_IN_CLASS (expr) = bp_unpack_enum (bp, built_in_class,
					       BUILT_IN_LAST);
  DECL_STATIC_CONSTRUCTOR (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_STATIC_DESTRUCTOR (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_UNINLINABLE (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_POSSIBLY_INLINED (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_IS_NOVOPS (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_IS_RETURNS_TWICE (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_IS_MALLOC (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_IS_OPERATOR_NEW (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_DECLARED_INLINE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_STATIC_CHAIN (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_NO_INLINE_WARNING_P (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (expr)
    			= (unsigned) bp_unpack_value (bp, 1);
  DECL_NO_LIMIT_STACK (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_DISREGARD_INLINE_LIMITS (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_PURE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
  DECL_LOOPING_CONST_OR_PURE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
  if (DECL_BUILT_IN_CLASS (expr) != NOT_BUILT_IN)
    {
      DECL_FUNCTION_CODE (expr) = (enum built_in_function) bp_unpack_value (bp,
	                                                                    11);
      if (DECL_BUILT_IN_CLASS (expr) == BUILT_IN_NORMAL
	  && DECL_FUNCTION_CODE (expr) >= END_BUILTINS)
	fatal_error ("machine independent builtin code out of range");
      else if (DECL_BUILT_IN_CLASS (expr) == BUILT_IN_MD)
	{
          tree result = targetm.builtin_decl (DECL_FUNCTION_CODE (expr), true);
	  if (!result || result == error_mark_node)
	    fatal_error ("target specific builtin not available");
	}
    }
  if (DECL_STATIC_DESTRUCTOR (expr))
    {
      priority_type p;
      p = (priority_type) bp_unpack_var_len_unsigned (bp);
      SET_DECL_FINI_PRIORITY (expr, p);
    }
}
Exemplo n.º 3
0
static void
pack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
{
  bp_pack_enum (bp, built_in_class, BUILT_IN_LAST,
		DECL_BUILT_IN_CLASS (expr));
  bp_pack_value (bp, DECL_STATIC_CONSTRUCTOR (expr), 1);
  bp_pack_value (bp, DECL_STATIC_DESTRUCTOR (expr), 1);
  bp_pack_value (bp, DECL_UNINLINABLE (expr), 1);
  bp_pack_value (bp, DECL_POSSIBLY_INLINED (expr), 1);
  bp_pack_value (bp, DECL_IS_NOVOPS (expr), 1);
  bp_pack_value (bp, DECL_IS_RETURNS_TWICE (expr), 1);
  bp_pack_value (bp, DECL_IS_MALLOC (expr), 1);
  bp_pack_value (bp, DECL_IS_OPERATOR_NEW (expr), 1);
  bp_pack_value (bp, DECL_DECLARED_INLINE_P (expr), 1);
  bp_pack_value (bp, DECL_STATIC_CHAIN (expr), 1);
  bp_pack_value (bp, DECL_NO_INLINE_WARNING_P (expr), 1);
  bp_pack_value (bp, DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (expr), 1);
  bp_pack_value (bp, DECL_NO_LIMIT_STACK (expr), 1);
  bp_pack_value (bp, DECL_DISREGARD_INLINE_LIMITS (expr), 1);
  bp_pack_value (bp, DECL_PURE_P (expr), 1);
  bp_pack_value (bp, DECL_LOOPING_CONST_OR_PURE_P (expr), 1);
  if (DECL_BUILT_IN_CLASS (expr) != NOT_BUILT_IN)
    bp_pack_value (bp, DECL_FUNCTION_CODE (expr), 12);
}
Exemplo n.º 4
0
bool
inline_call (struct cgraph_edge *e, bool update_original,
	     vec<cgraph_edge_p> *new_edges,
	     int *overall_size, bool update_overall_summary)
{
  int old_size = 0, new_size = 0;
  struct cgraph_node *to = NULL;
  struct cgraph_edge *curr = e;
  struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL);
  bool new_edges_found = false;

#ifdef ENABLE_CHECKING
  int estimated_growth = estimate_edge_growth (e);
  bool predicated = inline_edge_summary (e)->predicate != NULL;
#endif

  /* Don't inline inlined edges.  */
  gcc_assert (e->inline_failed);
  /* Don't even think of inlining inline clone.  */
  gcc_assert (!callee->global.inlined_to);

  e->inline_failed = CIF_OK;
  DECL_POSSIBLY_INLINED (callee->symbol.decl) = true;

  to = e->caller;
  if (to->global.inlined_to)
    to = to->global.inlined_to;

  /* If aliases are involved, redirect edge to the actual destination and
     possibly remove the aliases.  */
  if (e->callee != callee)
    {
      struct cgraph_node *alias = e->callee, *next_alias;
      cgraph_redirect_edge_callee (e, callee);
      while (alias && alias != callee)
	{
	  if (!alias->callers
	      && can_remove_node_now_p (alias, e))
	    {
	      next_alias = cgraph_alias_target (alias);
	      cgraph_remove_node (alias);
	      alias = next_alias;
	    }
	  else
	    break;
	}
    }

  clone_inlined_nodes (e, true, update_original, overall_size);

  gcc_assert (curr->callee->global.inlined_to == to);

  old_size = inline_summary (to)->size;
  inline_merge_summary (e);
  if (optimize)
    new_edges_found = ipa_propagate_indirect_call_infos (curr, new_edges);
  if (update_overall_summary)
   inline_update_overall_summary (to);
  new_size = inline_summary (to)->size;

#ifdef ENABLE_CHECKING
  /* Verify that estimated growth match real growth.  Allow off-by-one
     error due to INLINE_SIZE_SCALE roudoff errors.  */
  gcc_assert (!update_overall_summary || !overall_size || new_edges_found
	      || abs (estimated_growth - (new_size - old_size)) <= 1
	      /* FIXME: a hack.  Edges with false predicate are accounted
		 wrong, we should remove them from callgraph.  */
	      || predicated);
#endif

  /* Account the change of overall unit size; external functions will be
     removed and are thus not accounted.  */
  if (overall_size
      && !DECL_EXTERNAL (to->symbol.decl))
    *overall_size += new_size - old_size;
  ncalls_inlined++;

  /* This must happen after inline_merge_summary that rely on jump
     functions of callee to not be updated.  */
  return new_edges_found;
}
Exemplo n.º 5
0
static bool
lto_symtab_merge (symtab_node *prevailing, symtab_node *entry)
{
  tree prevailing_decl = prevailing->decl;
  tree decl = entry->decl;

  if (prevailing_decl == decl)
    return true;

  /* Merge decl state in both directions, we may still end up using
     the new decl.  */
  TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl);
  TREE_ADDRESSABLE (decl) |= TREE_ADDRESSABLE (prevailing_decl);

  /* The linker may ask us to combine two incompatible symbols.
     Detect this case and notify the caller of required diagnostics.  */

  if (TREE_CODE (decl) == FUNCTION_DECL)
    {
      /* Merge decl state in both directions, we may still end up using
	 the new decl.  */
      DECL_POSSIBLY_INLINED (prevailing_decl) |= DECL_POSSIBLY_INLINED (decl);
      DECL_POSSIBLY_INLINED (decl) |= DECL_POSSIBLY_INLINED (prevailing_decl);

      if (warn_type_compatibility_p (TREE_TYPE (prevailing_decl),
			             TREE_TYPE (decl),
				     DECL_COMMON (decl)
				     || DECL_EXTERNAL (decl)))
	return false;

      return true;
    }

  if (warn_type_compatibility_p (TREE_TYPE (prevailing_decl),
				 TREE_TYPE (decl),
				 DECL_COMMON (decl) || DECL_EXTERNAL (decl)))
    return false;

  /* There is no point in comparing too many details of the decls here.
     The type compatibility checks or the completing of types has properly
     dealt with most issues.  */

  /* The following should all not invoke fatal errors as in non-LTO
     mode the linker wouldn't complain either.  Just emit warnings.  */

  /* Report a warning if user-specified alignments do not match.  */
  if ((DECL_USER_ALIGN (prevailing_decl) && DECL_USER_ALIGN (decl))
      && DECL_ALIGN (prevailing_decl) < DECL_ALIGN (decl))
    return false;

  if (DECL_SIZE (decl) && DECL_SIZE (prevailing_decl)
      && !tree_int_cst_equal (DECL_SIZE (decl), DECL_SIZE (prevailing_decl))
      /* As a special case do not warn about merging
	 int a[];
	 and
	 int a[]={1,2,3};
	 here the first declaration is COMMON
	 and sizeof(a) == sizeof (int).  */
      && ((!DECL_COMMON (decl) && !DECL_EXTERNAL (decl))
	  || TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE
	  || TYPE_SIZE (TREE_TYPE (decl))
	     != TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl)))))
    return false;

  return true;
}