refuse_visibility_changes (false), externally_visible (false),
no_reorder (false), force_output (false), forced_by_abi (false),
ref_by_asm (false),
+ must_remain_in_tu_name (false), must_remain_in_tu_body (false),
unique_name (false), implicit_section (false), body_removed (false),
semantic_interposition (flag_semantic_interposition),
used_from_other_partition (false), in_other_partition (false),
Static symbol may be renamed. Global symbol should not be renamed.
Unlike force_output, can be on declarations. */
unsigned ref_by_asm : 1;
+ /* Set when asm_name must remain in TU partition.
+ Used to guarantee not renaming of static ref_by_asm symbols. */
+ unsigned must_remain_in_tu_name : 1;
+ /* Set when body (or any references) must remain in TU partition.
+ Used on symbols referring/calling must_remain_in_tu_name. */
+ unsigned must_remain_in_tu_body : 1;
/* True when the name is known to be unique and thus it does not need mangling. */
unsigned unique_name : 1;
/* Specify whether the section was set by user or by
new_node->unit_id = unit_id;
new_node->merged_comdat = merged_comdat;
new_node->merged_extern_inline = merged_extern_inline;
+ new_node->must_remain_in_tu_body = must_remain_in_tu_body;
clone_info *info = clone_info::get (this);
if (param_adjustments)
N_("function has external linkage when the user requests only"
" inlining static for live patching"))
+/* We can't inline because callee must remain in translation unit
+ and caller is in another. */
+DEFCIFCODE(MUST_REMAIN_IN_TU, CIF_FINAL_ERROR,
+ N_("callee must remain in translation unit"))
+
/* We proved that the call is unreachable. */
DEFCIFCODE(UNREACHABLE, CIF_FINAL_ERROR,
N_("unreachable"))
m_compared_func = static_cast<sem_function *> (item);
+ if (cnode->must_remain_in_tu_name || cnode2->must_remain_in_tu_name
+ || cnode->must_remain_in_tu_body || cnode2->must_remain_in_tu_body)
+ return return_false_with_msg ("must remain in TU");
+
if (cnode->thunk != cnode2->thunk)
return return_false_with_msg ("thunk mismatch");
if (cnode->former_thunk_p () != cnode2->former_thunk_p ())
{
gcc_assert (item->type == VAR);
+ if (node->must_remain_in_tu_name || item->node->must_remain_in_tu_name
+ || node->must_remain_in_tu_body || item->node->must_remain_in_tu_body)
+ return return_false_with_msg ("must remain in TU");
+
if (node->num_references () != item->node->num_references ())
return return_false_with_msg ("different number of references");
}
}
+ if (callee->must_remain_in_tu_body)
+ {
+ gcc_assert (callee->lto_file_data == to->lto_file_data);
+ to->must_remain_in_tu_body = true;
+ }
+
clone_inlined_nodes (e, true, keep_offline_copy,
update_original, overall_size);
e->inline_failed = CIF_UNSPECIFIED;
inlinable = false;
}
+ if (inlinable && callee->must_remain_in_tu_body
+ && caller->lto_file_data != callee->lto_file_data)
+ {
+ e->inline_failed = CIF_MUST_REMAIN_IN_TU;
+ inlinable = false;
+ }
if (!inlinable && report)
report_inline_failed_reason (e);
return inlinable;
bp_pack_value (&bp, node->force_output, 1);
bp_pack_value (&bp, node->forced_by_abi, 1);
bp_pack_value (&bp, node->ref_by_asm, 1);
+ bp_pack_value (&bp, node->must_remain_in_tu_name, 1);
+ bp_pack_value (&bp, node->must_remain_in_tu_body, 1);
bp_pack_value (&bp, node->unique_name, 1);
bp_pack_value (&bp, node->body_removed, 1);
bp_pack_value (&bp, node->semantic_interposition, 1);
bp_pack_value (&bp, node->force_output, 1);
bp_pack_value (&bp, node->forced_by_abi, 1);
bp_pack_value (&bp, node->ref_by_asm, 1);
+ bp_pack_value (&bp, node->must_remain_in_tu_name, 1);
+ bp_pack_value (&bp, node->must_remain_in_tu_body, 1);
bp_pack_value (&bp, node->unique_name, 1);
bp_pack_value (&bp,
node->body_removed
node->force_output = bp_unpack_value (bp, 1);
node->forced_by_abi = bp_unpack_value (bp, 1);
node->ref_by_asm = bp_unpack_value (bp, 1);
+ node->must_remain_in_tu_name = bp_unpack_value (bp, 1);
+ node->must_remain_in_tu_body = bp_unpack_value (bp, 1);
node->unique_name = bp_unpack_value (bp, 1);
node->body_removed = bp_unpack_value (bp, 1);
node->semantic_interposition = bp_unpack_value (bp, 1);
node->force_output = bp_unpack_value (&bp, 1);
node->forced_by_abi = bp_unpack_value (&bp, 1);
node->ref_by_asm = bp_unpack_value (&bp, 1);
+ node->must_remain_in_tu_name = bp_unpack_value (&bp, 1);
+ node->must_remain_in_tu_body = bp_unpack_value (&bp, 1);
node->unique_name = bp_unpack_value (&bp, 1);
node->body_removed = bp_unpack_value (&bp, 1);
node->semantic_interposition = bp_unpack_value (&bp, 1);
if (node->forced_by_abi)
prevailing_node->forced_by_abi = true;
prevailing_node->ref_by_asm |= node->ref_by_asm;
+ prevailing_node->must_remain_in_tu_name |= node->must_remain_in_tu_name;
+ prevailing_node->must_remain_in_tu_body |= node->must_remain_in_tu_body;
if (node->address_taken)
{
if (vnode->forced_by_abi)
prevailing_node->forced_by_abi = true;
prevailing_node->ref_by_asm |= vnode->ref_by_asm;
+ prevailing_node->must_remain_in_tu_name |= vnode->must_remain_in_tu_name;
+ prevailing_node->must_remain_in_tu_body |= vnode->must_remain_in_tu_body;
/* Be sure we can garbage collect the initializer. */
if (DECL_INITIAL (vnode->decl)
/* The conditions below are slightly less strict than the one in
staticp. */
+ symtab_node* node;
switch (TREE_CODE (op))
{
case LABEL_DECL:
- case FUNCTION_DECL:
case STRING_CST:
return true;
+ case FUNCTION_DECL:
+ /* Disable const propagation of symbols defined in assembly. */
+ node = symtab_node::get (op);
+ return !node || !node->must_remain_in_tu_name;
+
case VAR_DECL:
+ if (TREE_STATIC (op) || DECL_EXTERNAL (op))
+ {
+ /* Disable const propagation of symbols defined in assembly. */
+ node = symtab_node::get (op);
+ if (node && node->must_remain_in_tu_name)
+ return false;
+ }
if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
&& !DECL_DLLIMPORT_P (op))
|| DECL_THREAD_LOCAL_P (op))
&& !real_node->lto_file_data)
return false;
+ /* Folding may cross TU boundaries. */
+ if (must_remain_in_tu_body)
+ return false;
+
/* Vtables are defined by their types and must match no matter of interposition
rules. */
if (DECL_VIRTUAL_P (decl))