Skip to content

Commit 4a211b3

Browse files
committed
use our own alternative to STD_INTERNAL_SYMBOL and make sure we mangle EIIs properly
1 parent 13de732 commit 4a211b3

File tree

14 files changed

+86
-14
lines changed

14 files changed

+86
-14
lines changed

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,3 +699,12 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcPassIndirectlyInNonRusticAbisPa
699699
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
700700
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassIndirectlyInNonRusticAbis;
701701
}
702+
703+
pub(crate) struct EiiExternItemParser;
704+
705+
impl<S: Stage> NoArgsAttributeParser<S> for EiiExternItemParser {
706+
const PATH: &[Symbol] = &[sym::rustc_eii_extern_item];
707+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
708+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);
709+
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::EiiExternItem;
710+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use crate::attributes::allow_unstable::{
2020
};
2121
use crate::attributes::body::CoroutineParser;
2222
use crate::attributes::codegen_attrs::{
23-
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
24-
NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
23+
ColdParser, CoverageParser, EiiExternItemParser, ExportNameParser, ForceTargetFeatureParser,
24+
NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
2525
RustcPassIndirectlyInNonRusticAbisParser, SanitizeParser, TargetFeatureParser,
2626
TrackCallerParser, UsedParser,
2727
};
@@ -227,6 +227,7 @@ attribute_parsers!(
227227
Single<WithoutArgs<CoroutineParser>>,
228228
Single<WithoutArgs<DenyExplicitImplParser>>,
229229
Single<WithoutArgs<DoNotImplementViaObjectParser>>,
230+
Single<WithoutArgs<EiiExternItemParser>>,
230231
Single<WithoutArgs<ExportStableParser>>,
231232
Single<WithoutArgs<FfiConstParser>>,
232233
Single<WithoutArgs<FfiPureParser>>,

compiler/rustc_builtin_macros/src/eii.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,24 @@ fn eii_(
209209
}
210210

211211
// extern "…" { safe fn item(); }
212+
let mut extern_item_attrs = attrs.clone();
213+
extern_item_attrs.push(ast::Attribute {
214+
kind: ast::AttrKind::Normal(Box::new(ast::NormalAttr {
215+
item: ast::AttrItem {
216+
unsafety: ast::Safety::Default,
217+
// Add the rustc_eii_extern_item on the foreign item. Usually, foreign items are mangled.
218+
// This attribute makes sure that we later know that this foreign item's symbol should not be.
219+
path: ast::Path::from_ident(Ident::new(sym::rustc_eii_extern_item, span)),
220+
args: ast::AttrArgs::Empty,
221+
tokens: None,
222+
},
223+
tokens: None,
224+
})),
225+
id: ecx.sess.psess.attr_id_generator.mk_attr_id(),
226+
style: ast::AttrStyle::Outer,
227+
span,
228+
});
229+
212230
let extern_block = Box::new(ast::Item {
213231
attrs: ast::AttrVec::default(),
214232
id: ast::DUMMY_NODE_ID,
@@ -219,7 +237,7 @@ fn eii_(
219237
safety: ast::Safety::Unsafe(span),
220238
abi,
221239
items: From::from([Box::new(ast::ForeignItem {
222-
attrs: attrs.clone(),
240+
attrs: extern_item_attrs,
223241
id: ast::DUMMY_NODE_ID,
224242
span: item_span,
225243
vis,

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,10 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
127127
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER),
128128
rustc_std_internal_symbol: codegen_attrs
129129
.flags
130-
.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL),
130+
.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
131+
|| codegen_attrs
132+
.flags
133+
.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM),
131134
};
132135
(def_id.to_def_id(), info)
133136
})
@@ -519,8 +522,9 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
519522
let is_extern = codegen_fn_attrs.contains_extern_indicator();
520523
let std_internal =
521524
codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
525+
let eii = codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM);
522526

523-
if is_extern && !std_internal {
527+
if is_extern && !std_internal && !eii {
524528
let target = &tcx.sess.target.llvm_target;
525529
// WebAssembly cannot export data symbols, so reduce their export level
526530
if target.contains("emscripten") {

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ fn process_builtin_attrs(
313313
AttributeKind::ObjcSelector { methname, .. } => {
314314
codegen_fn_attrs.objc_selector = Some(*methname);
315315
}
316+
AttributeKind::EiiExternItem => {
317+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM;
318+
}
316319
AttributeKind::EiiImpls(impls) => {
317320
for i in impls {
318321
let extern_item = find_attr!(
@@ -344,7 +347,7 @@ fn process_builtin_attrs(
344347
if i.is_default { Linkage::LinkOnceAny } else { Linkage::External },
345348
Visibility::Default,
346349
));
347-
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
350+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM;
348351
}
349352
}
350353
_ => {}
@@ -448,6 +451,12 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
448451
// * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
449452
// both for exports and imports through foreign items. This is handled further,
450453
// during symbol mangling logic.
454+
} else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM)
455+
{
456+
// * externally implementable items keep their mangled symbol name.
457+
// multiple EIIs can have the same name, so not mangling them would be a bug.
458+
// Implementing an EII does the appropriate name resolution to make sure the implementations
459+
// get the same symbol name as the *mangled* foreign item they refer to so that's all good.
451460
} else if codegen_fn_attrs.symbol_name.is_some() {
452461
// * This can be overridden with the `#[link_name]` attribute
453462
} else {

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
961961
allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
962962
EncodeCrossCrate::No, "allow_internal_unsafe side-steps the unsafe_code lint",
963963
),
964+
gated!(
965+
rustc_eii_extern_item, Normal, template!(Word),
966+
ErrorFollowing, EncodeCrossCrate::Yes, eii_internals,
967+
"used internally to mark types with a `transparent` representation when it is guaranteed by the documentation",
968+
),
964969
rustc_attr!(
965970
rustc_allowed_through_unstable_modules, Normal, template!(NameValueStr: "deprecation message"),
966971
WarnFollowing, EncodeCrossCrate::No,

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,9 @@ pub enum AttributeKind {
709709
/// Represents `#[rustc_dummy]`.
710710
Dummy,
711711

712+
/// Implementation detail of `#[eii]`
713+
EiiExternItem,
714+
712715
/// Implementation detail of `#[eii]`
713716
EiiExternTarget(EiiDecl),
714717

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ impl AttributeKind {
4343
Doc(_) => Yes,
4444
DocComment { .. } => Yes,
4545
Dummy => No,
46+
EiiExternItem => No,
4647
EiiExternTarget(_) => Yes,
4748
EiiImpls(..) => No,
4849
ExportName { .. } => Yes,

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ impl<'tcx> TyCtxt<'tcx> {
4343
attrs.to_mut().flags.remove(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
4444
}
4545

46+
if attrs.flags.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM) {
47+
attrs.to_mut().flags.remove(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM);
48+
}
49+
4650
if attrs.symbol_name.is_some() {
4751
attrs.to_mut().symbol_name = None;
4852
}
@@ -199,6 +203,12 @@ bitflags::bitflags! {
199203
const FOREIGN_ITEM = 1 << 16;
200204
/// `#[rustc_offload_kernel]`: indicates that this is an offload kernel, an extra ptr arg will be added.
201205
const OFFLOAD_KERNEL = 1 << 17;
206+
/// Externally implementable item symbols act a little like `RUSTC_STD_INTERNAL_SYMBOL`.
207+
/// When a crate declares an EII and dependencies expect the symbol to exist,
208+
/// they will refer to this symbol name before a definition is given.
209+
/// As such, we must make sure these symbols really do exist in the final binary/library.
210+
/// This flag is put on both the implementations of EIIs and the foreign item they implement.
211+
const EXTERNALLY_IMPLEMENTABLE_ITEM = 1 << 18;
202212
}
203213
}
204214
rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags }
@@ -242,6 +252,9 @@ impl CodegenFnAttrs {
242252

243253
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
244254
|| self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
255+
// note: for these we do also set a symbol name so technically also handled by the
256+
// condition below. However, I think that regardless these should be treated as extern.
257+
|| self.flags.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM)
245258
|| self.symbol_name.is_some()
246259
|| match self.linkage {
247260
// These are private, so make sure we don't try to consider

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,11 +1643,11 @@ impl<'v> RootCollector<'_, 'v> {
16431643
MonoItemCollectionStrategy::Lazy => {
16441644
self.entry_fn.and_then(|(id, _)| id.as_local()) == Some(def_id)
16451645
|| self.tcx.is_reachable_non_generic(def_id)
1646-
|| self
1647-
.tcx
1648-
.codegen_fn_attrs(def_id)
1649-
.flags
1650-
.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
1646+
|| {
1647+
let flags = self.tcx.codegen_fn_attrs(def_id).flags;
1648+
flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
1649+
|| flags.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM)
1650+
}
16511651
}
16521652
}
16531653
}

0 commit comments

Comments
 (0)