Skip to content

Commit e75b93d

Browse files
committed
make no_mangle explicit on foreign items
1 parent cc0a5b7 commit e75b93d

File tree

6 files changed

+72
-54
lines changed

6 files changed

+72
-54
lines changed

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,35 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
445445
if tcx.should_inherit_track_caller(did) {
446446
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
447447
}
448+
449+
// Foreign items by default use no mangling for their symbol name.
450+
if tcx.is_foreign_item(did) {
451+
// There's a few exceptions to this rule though:
452+
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
453+
// * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
454+
// both for exports and imports through foreign items. This is handled further,
455+
// during symbol mangling logic/
456+
} else if codegen_fn_attrs.link_name.is_some() {
457+
// * This can be overridden with the `#[link_name]` attribute
458+
} else if tcx.sess.target.is_like_wasm
459+
&& tcx.wasm_import_module_map(LOCAL_CRATE).contains_key(&did.into())
460+
{
461+
// * On the wasm32 targets there is a bug (or feature) in LLD [1] where the
462+
// same-named symbol when imported from different wasm modules will get
463+
// hooked up incorrectly. As a result foreign symbols, on the wasm target,
464+
// with a wasm import module, get mangled. Additionally our codegen will
465+
// deduplicate symbols based purely on the symbol name, but for wasm this
466+
// isn't quite right because the same-named symbol on wasm can come from
467+
// different modules. For these reasons if `#[link(wasm_import_module)]`
468+
// is present we mangle everything on wasm because the demangled form will
469+
// show up in the `wasm-import-name` custom attribute in LLVM IR.
470+
//
471+
// [1]: https://bugs.llvm.org/show_bug.cgi?id=44316
472+
} else {
473+
// if none of the exceptions apply; apply no_mangle
474+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
475+
}
476+
}
448477
}
449478

450479
fn check_result(

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ impl CodegenFnAttrs {
192192
/// * `#[export_name(...)]` is present
193193
/// * `#[linkage]` is present
194194
///
195+
/// Note that this returns true for foreign items.
196+
/// However, in some places that care about `contains_extern_indicator`, foreign items
197+
/// (in an `extern` block) should explicitly be ignored.
198+
///
195199
/// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
196200
pub fn contains_extern_indicator(&self) -> bool {
197201
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)

compiler/rustc_passes/src/check_attr.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,24 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
565565
match target {
566566
Target::Fn
567567
| Target::Closure
568-
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {}
568+
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {
569+
// `#[inline]` is ignored if the symbol must be codegened upstream because it's exported.
570+
if let Some(did) = hir_id.as_owner()
571+
&& self.tcx.def_kind(did).has_codegen_attrs()
572+
&& kind != &InlineAttr::Never
573+
{
574+
let attrs = self.tcx.codegen_fn_attrs(did);
575+
// Not checking naked as `#[inline]` is forbidden for naked functions anyways.
576+
if attrs.contains_extern_indicator() {
577+
self.tcx.emit_node_span_lint(
578+
UNUSED_ATTRIBUTES,
579+
hir_id,
580+
attr_span,
581+
errors::InlineIgnoredForExported {},
582+
);
583+
}
584+
}
585+
}
569586
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
570587
self.tcx.emit_node_span_lint(
571588
UNUSED_ATTRIBUTES,
@@ -592,23 +609,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
592609
self.dcx().emit_err(errors::InlineNotFnOrClosure { attr_span, defn_span });
593610
}
594611
}
595-
596-
// `#[inline]` is ignored if the symbol must be codegened upstream because it's exported.
597-
if let Some(did) = hir_id.as_owner()
598-
&& self.tcx.def_kind(did).has_codegen_attrs()
599-
&& kind != &InlineAttr::Never
600-
{
601-
let attrs = self.tcx.codegen_fn_attrs(did);
602-
// Not checking naked as `#[inline]` is forbidden for naked functions anyways.
603-
if attrs.contains_extern_indicator() {
604-
self.tcx.emit_node_span_lint(
605-
UNUSED_ATTRIBUTES,
606-
hir_id,
607-
attr_span,
608-
errors::InlineIgnoredForExported {},
609-
);
610-
}
611-
}
612612
}
613613

614614
/// Checks that `#[coverage(..)]` is applied to a function/closure/method,

compiler/rustc_passes/src/dead.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -694,15 +694,17 @@ fn has_allow_dead_code_or_lang_attr(
694694
}
695695

696696
fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
697-
tcx.def_kind(def_id).has_codegen_attrs() && {
698-
let cg_attrs = tcx.codegen_fn_attrs(def_id);
699-
700-
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
701-
// forcefully, e.g., for placing it in a specific section.
702-
cg_attrs.contains_extern_indicator()
703-
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
704-
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
705-
}
697+
tcx.def_kind(def_id).has_codegen_attrs()
698+
&& {
699+
let cg_attrs = tcx.codegen_fn_attrs(def_id);
700+
701+
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
702+
// forcefully, e.g., for placing it in a specific section.
703+
cg_attrs.contains_extern_indicator()
704+
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
705+
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
706+
}
707+
&& !tcx.is_foreign_item(def_id)
706708
}
707709

708710
if has_allow_expect_dead_code(tcx, def_id) {

compiler/rustc_passes/src/reachable.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ impl<'tcx> ReachableContext<'tcx> {
183183
} else {
184184
CodegenFnAttrs::EMPTY
185185
};
186-
let is_extern = codegen_attrs.contains_extern_indicator();
186+
let is_extern =
187+
codegen_attrs.contains_extern_indicator() && !self.tcx.is_foreign_item(search_item);
187188
if is_extern {
188189
self.reachable_symbols.insert(search_item);
189190
}
@@ -423,6 +424,11 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
423424
if !tcx.def_kind(def_id).has_codegen_attrs() {
424425
return false;
425426
}
427+
428+
if tcx.is_foreign_item(def_id) {
429+
return false;
430+
}
431+
426432
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
427433
codegen_attrs.contains_extern_indicator()
428434
// FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by

compiler/rustc_symbol_mangling/src/lib.rs

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -218,32 +218,9 @@ fn compute_symbol_name<'tcx>(
218218
}
219219
}
220220

221-
// Foreign items by default use no mangling for their symbol name. There's a
222-
// few exceptions to this rule though:
223-
//
224-
// * This can be overridden with the `#[link_name]` attribute
225-
//
226-
// * On the wasm32 targets there is a bug (or feature) in LLD [1] where the
227-
// same-named symbol when imported from different wasm modules will get
228-
// hooked up incorrectly. As a result foreign symbols, on the wasm target,
229-
// with a wasm import module, get mangled. Additionally our codegen will
230-
// deduplicate symbols based purely on the symbol name, but for wasm this
231-
// isn't quite right because the same-named symbol on wasm can come from
232-
// different modules. For these reasons if `#[link(wasm_import_module)]`
233-
// is present we mangle everything on wasm because the demangled form will
234-
// show up in the `wasm-import-name` custom attribute in LLVM IR.
235-
//
236-
// * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
237-
// both for exports and imports through foreign items. This is handled above.
238-
// [1]: https://bugs.llvm.org/show_bug.cgi?id=44316
239-
if tcx.is_foreign_item(def_id)
240-
&& (!tcx.sess.target.is_like_wasm
241-
|| !tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id))
242-
{
243-
if let Some(name) = attrs.link_name {
244-
return name.to_string();
245-
}
246-
return tcx.item_name(def_id).to_string();
221+
if let Some(name) = attrs.link_name {
222+
// Use provided name
223+
return name.to_string();
247224
}
248225

249226
if let Some(name) = attrs.export_name {

0 commit comments

Comments
 (0)