Skip to content

Commit 0f116f7

Browse files
committed
make no_mangle explicit on foreign items
1 parent ec7c026 commit 0f116f7

File tree

13 files changed

+99
-85
lines changed

13 files changed

+99
-85
lines changed

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
586586
// core/std/allocators/etc. For example symbols used to hook up allocation
587587
// are not considered for export
588588
let codegen_fn_attrs = tcx.codegen_fn_attrs(sym_def_id);
589-
let is_extern = codegen_fn_attrs.contains_extern_indicator();
589+
let is_extern = codegen_fn_attrs.contains_extern_indicator(tcx, sym_def_id);
590590
let std_internal =
591591
codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
592592

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

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

448477
fn check_result(

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::borrow::Cow;
33
use rustc_abi::Align;
44
use rustc_ast::expand::autodiff_attrs::AutoDiffAttrs;
55
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr};
6+
use rustc_hir::def_id::DefId;
67
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
78
use rustc_span::Symbol;
89
use rustc_target::spec::SanitizerSet;
@@ -193,7 +194,11 @@ impl CodegenFnAttrs {
193194
/// * `#[linkage]` is present
194195
///
195196
/// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
196-
pub fn contains_extern_indicator(&self) -> bool {
197+
pub fn contains_extern_indicator(&self, tcx: TyCtxt<'_>, did: DefId) -> bool {
198+
if tcx.is_foreign_item(did) {
199+
return false;
200+
}
201+
197202
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
198203
|| self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
199204
|| self.export_name.is_some()

compiler/rustc_middle/src/mir/mono.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ impl<'tcx> MonoItem<'tcx> {
151151
// instantiation:
152152
// We emit an unused_attributes lint for this case, which should be kept in sync if possible.
153153
let codegen_fn_attrs = tcx.codegen_instance_attrs(instance.def);
154-
if codegen_fn_attrs.contains_extern_indicator()
154+
if codegen_fn_attrs.contains_extern_indicator(tcx, instance.def.def_id())
155155
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
156156
{
157157
return InstantiationMode::GloballyShared { may_conflict: false };

compiler/rustc_mir_transform/src/cross_crate_inline.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
1818
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
1919
// If this has an extern indicator, then this function is globally shared and thus will not
2020
// generate cgu-internal copies which would make it cross-crate inlinable.
21-
if codegen_fn_attrs.contains_extern_indicator() {
21+
if codegen_fn_attrs.contains_extern_indicator(tcx, def_id.into()) {
2222
return false;
2323
}
2424

compiler/rustc_passes/src/check_attr.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,24 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
562562
match target {
563563
Target::Fn
564564
| Target::Closure
565-
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {}
565+
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {
566+
// `#[inline]` is ignored if the symbol must be codegened upstream because it's exported.
567+
if let Some(did) = hir_id.as_owner()
568+
&& self.tcx.def_kind(did).has_codegen_attrs()
569+
&& kind != &InlineAttr::Never
570+
{
571+
let attrs = self.tcx.codegen_fn_attrs(did);
572+
// Not checking naked as `#[inline]` is forbidden for naked functions anyways.
573+
if attrs.contains_extern_indicator(self.tcx, did.into()) {
574+
self.tcx.emit_node_span_lint(
575+
UNUSED_ATTRIBUTES,
576+
hir_id,
577+
attr_span,
578+
errors::InlineIgnoredForExported {},
579+
);
580+
}
581+
}
582+
}
566583
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
567584
self.tcx.emit_node_span_lint(
568585
UNUSED_ATTRIBUTES,
@@ -589,23 +606,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
589606
self.dcx().emit_err(errors::InlineNotFnOrClosure { attr_span, defn_span });
590607
}
591608
}
592-
593-
// `#[inline]` is ignored if the symbol must be codegened upstream because it's exported.
594-
if let Some(did) = hir_id.as_owner()
595-
&& self.tcx.def_kind(did).has_codegen_attrs()
596-
&& kind != &InlineAttr::Never
597-
{
598-
let attrs = self.tcx.codegen_fn_attrs(did);
599-
// Not checking naked as `#[inline]` is forbidden for naked functions anyways.
600-
if attrs.contains_extern_indicator() {
601-
self.tcx.emit_node_span_lint(
602-
UNUSED_ATTRIBUTES,
603-
hir_id,
604-
attr_span,
605-
errors::InlineIgnoredForExported {},
606-
);
607-
}
608-
}
609609
}
610610

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

compiler/rustc_passes/src/dead.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ fn has_allow_dead_code_or_lang_attr(
701701

702702
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
703703
// forcefully, e.g., for placing it in a specific section.
704-
cg_attrs.contains_extern_indicator()
704+
cg_attrs.contains_extern_indicator(tcx, def_id.into())
705705
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
706706
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
707707
}

compiler/rustc_passes/src/reachable.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl<'tcx> ReachableContext<'tcx> {
183183
} else {
184184
CodegenFnAttrs::EMPTY
185185
};
186-
let is_extern = codegen_attrs.contains_extern_indicator();
186+
let is_extern = codegen_attrs.contains_extern_indicator(self.tcx, search_item.into());
187187
if is_extern {
188188
self.reachable_symbols.insert(search_item);
189189
}
@@ -423,8 +423,9 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
423423
if !tcx.def_kind(def_id).has_codegen_attrs() {
424424
return false;
425425
}
426+
426427
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
427-
codegen_attrs.contains_extern_indicator()
428+
codegen_attrs.contains_extern_indicator(tcx, def_id.into())
428429
// FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
429430
// `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
430431
// `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.

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 {

src/tools/clippy/clippy_lints/src/missing_inline.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,5 +191,5 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
191191
/// and a rustc warning would be triggered, see #15301
192192
fn fn_is_externally_exported(cx: &LateContext<'_>, def_id: DefId) -> bool {
193193
let attrs = cx.tcx.codegen_fn_attrs(def_id);
194-
attrs.contains_extern_indicator()
194+
attrs.contains_extern_indicator(cx.tcx, def_id)
195195
}

0 commit comments

Comments
 (0)