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)); }
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); } }
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); }
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; }
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; }