use our own alternative to STD_INTERNAL_SYMBOL and make sure we mangle EIIs properly
This commit is contained in:
parent
13de732df5
commit
5768b234de
15 changed files with 91 additions and 14 deletions
|
|
@ -699,3 +699,12 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcPassIndirectlyInNonRusticAbisPa
|
|||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassIndirectlyInNonRusticAbis;
|
||||
}
|
||||
|
||||
pub(crate) struct EiiExternItemParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for EiiExternItemParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_eii_extern_item];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::EiiExternItem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ use crate::attributes::allow_unstable::{
|
|||
};
|
||||
use crate::attributes::body::CoroutineParser;
|
||||
use crate::attributes::codegen_attrs::{
|
||||
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
|
||||
NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
|
||||
ColdParser, CoverageParser, EiiExternItemParser, ExportNameParser, ForceTargetFeatureParser,
|
||||
NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
|
||||
RustcPassIndirectlyInNonRusticAbisParser, SanitizeParser, TargetFeatureParser,
|
||||
TrackCallerParser, UsedParser,
|
||||
};
|
||||
|
|
@ -227,6 +227,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<CoroutineParser>>,
|
||||
Single<WithoutArgs<DenyExplicitImplParser>>,
|
||||
Single<WithoutArgs<DoNotImplementViaObjectParser>>,
|
||||
Single<WithoutArgs<EiiExternItemParser>>,
|
||||
Single<WithoutArgs<ExportStableParser>>,
|
||||
Single<WithoutArgs<FfiConstParser>>,
|
||||
Single<WithoutArgs<FfiPureParser>>,
|
||||
|
|
|
|||
|
|
@ -209,6 +209,24 @@ fn eii_(
|
|||
}
|
||||
|
||||
// extern "…" { safe fn item(); }
|
||||
let mut extern_item_attrs = attrs.clone();
|
||||
extern_item_attrs.push(ast::Attribute {
|
||||
kind: ast::AttrKind::Normal(Box::new(ast::NormalAttr {
|
||||
item: ast::AttrItem {
|
||||
unsafety: ast::Safety::Default,
|
||||
// Add the rustc_eii_extern_item on the foreign item. Usually, foreign items are mangled.
|
||||
// This attribute makes sure that we later know that this foreign item's symbol should not be.
|
||||
path: ast::Path::from_ident(Ident::new(sym::rustc_eii_extern_item, span)),
|
||||
args: ast::AttrArgs::Empty,
|
||||
tokens: None,
|
||||
},
|
||||
tokens: None,
|
||||
})),
|
||||
id: ecx.sess.psess.attr_id_generator.mk_attr_id(),
|
||||
style: ast::AttrStyle::Outer,
|
||||
span,
|
||||
});
|
||||
|
||||
let extern_block = Box::new(ast::Item {
|
||||
attrs: ast::AttrVec::default(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
|
|
@ -219,7 +237,7 @@ fn eii_(
|
|||
safety: ast::Safety::Unsafe(span),
|
||||
abi,
|
||||
items: From::from([Box::new(ast::ForeignItem {
|
||||
attrs: attrs.clone(),
|
||||
attrs: extern_item_attrs,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: item_span,
|
||||
vis,
|
||||
|
|
|
|||
|
|
@ -127,7 +127,10 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
|||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER),
|
||||
rustc_std_internal_symbol: codegen_attrs
|
||||
.flags
|
||||
.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL),
|
||||
.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
|
||||
|| codegen_attrs
|
||||
.flags
|
||||
.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM),
|
||||
};
|
||||
(def_id.to_def_id(), info)
|
||||
})
|
||||
|
|
@ -519,10 +522,12 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
|
|||
let is_extern = codegen_fn_attrs.contains_extern_indicator();
|
||||
let std_internal =
|
||||
codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
|
||||
let eii = codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM);
|
||||
|
||||
if is_extern && !std_internal {
|
||||
if is_extern && !std_internal && !eii {
|
||||
let target = &tcx.sess.target.llvm_target;
|
||||
// WebAssembly cannot export data symbols, so reduce their export level
|
||||
// FIXME(jdonszelmann) don't do a substring match here.
|
||||
if target.contains("emscripten") {
|
||||
if let DefKind::Static { .. } = tcx.def_kind(sym_def_id) {
|
||||
return SymbolExportLevel::Rust;
|
||||
|
|
|
|||
|
|
@ -313,6 +313,9 @@ fn process_builtin_attrs(
|
|||
AttributeKind::ObjcSelector { methname, .. } => {
|
||||
codegen_fn_attrs.objc_selector = Some(*methname);
|
||||
}
|
||||
AttributeKind::EiiExternItem => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM;
|
||||
}
|
||||
AttributeKind::EiiImpls(impls) => {
|
||||
for i in impls {
|
||||
let extern_item = find_attr!(
|
||||
|
|
@ -344,7 +347,7 @@ fn process_builtin_attrs(
|
|||
if i.is_default { Linkage::LinkOnceAny } else { Linkage::External },
|
||||
Visibility::Default,
|
||||
));
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -448,6 +451,12 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
|
|||
// * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
|
||||
// both for exports and imports through foreign items. This is handled further,
|
||||
// during symbol mangling logic.
|
||||
} else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM)
|
||||
{
|
||||
// * externally implementable items keep their mangled symbol name.
|
||||
// multiple EIIs can have the same name, so not mangling them would be a bug.
|
||||
// Implementing an EII does the appropriate name resolution to make sure the implementations
|
||||
// get the same symbol name as the *mangled* foreign item they refer to so that's all good.
|
||||
} else if codegen_fn_attrs.symbol_name.is_some() {
|
||||
// * This can be overridden with the `#[link_name]` attribute
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -961,6 +961,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
|
||||
EncodeCrossCrate::No, "allow_internal_unsafe side-steps the unsafe_code lint",
|
||||
),
|
||||
gated!(
|
||||
rustc_eii_extern_item, Normal, template!(Word),
|
||||
ErrorFollowing, EncodeCrossCrate::Yes, eii_internals,
|
||||
"used internally to mark types with a `transparent` representation when it is guaranteed by the documentation",
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_allowed_through_unstable_modules, Normal, template!(NameValueStr: "deprecation message"),
|
||||
WarnFollowing, EncodeCrossCrate::No,
|
||||
|
|
|
|||
|
|
@ -709,6 +709,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_dummy]`.
|
||||
Dummy,
|
||||
|
||||
/// Implementation detail of `#[eii]`
|
||||
EiiExternItem,
|
||||
|
||||
/// Implementation detail of `#[eii]`
|
||||
EiiExternTarget(EiiDecl),
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ impl AttributeKind {
|
|||
Doc(_) => Yes,
|
||||
DocComment { .. } => Yes,
|
||||
Dummy => No,
|
||||
EiiExternItem => No,
|
||||
EiiExternTarget(_) => Yes,
|
||||
EiiImpls(..) => No,
|
||||
ExportName { .. } => Yes,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
attrs.to_mut().flags.remove(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
|
||||
}
|
||||
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM) {
|
||||
attrs.to_mut().flags.remove(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM);
|
||||
}
|
||||
|
||||
if attrs.symbol_name.is_some() {
|
||||
attrs.to_mut().symbol_name = None;
|
||||
}
|
||||
|
|
@ -199,6 +203,12 @@ bitflags::bitflags! {
|
|||
const FOREIGN_ITEM = 1 << 16;
|
||||
/// `#[rustc_offload_kernel]`: indicates that this is an offload kernel, an extra ptr arg will be added.
|
||||
const OFFLOAD_KERNEL = 1 << 17;
|
||||
/// Externally implementable item symbols act a little like `RUSTC_STD_INTERNAL_SYMBOL`.
|
||||
/// When a crate declares an EII and dependencies expect the symbol to exist,
|
||||
/// they will refer to this symbol name before a definition is given.
|
||||
/// As such, we must make sure these symbols really do exist in the final binary/library.
|
||||
/// This flag is put on both the implementations of EIIs and the foreign item they implement.
|
||||
const EXTERNALLY_IMPLEMENTABLE_ITEM = 1 << 18;
|
||||
}
|
||||
}
|
||||
rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags }
|
||||
|
|
@ -242,6 +252,9 @@ impl CodegenFnAttrs {
|
|||
|
||||
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
|
||||
|| self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
|
||||
// note: for these we do also set a symbol name so technically also handled by the
|
||||
// condition below. However, I think that regardless these should be treated as extern.
|
||||
|| self.flags.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM)
|
||||
|| self.symbol_name.is_some()
|
||||
|| match self.linkage {
|
||||
// These are private, so make sure we don't try to consider
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ pub struct SymbolExportInfo {
|
|||
/// Was the symbol marked as `#[used(compiler)]` or `#[used(linker)]`?
|
||||
pub used: bool,
|
||||
/// Was the symbol marked as `#[rustc_std_internal_symbol]`?
|
||||
/// We also use this for externally implementable items.
|
||||
pub rustc_std_internal_symbol: bool,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1643,11 +1643,13 @@ impl<'v> RootCollector<'_, 'v> {
|
|||
MonoItemCollectionStrategy::Lazy => {
|
||||
self.entry_fn.and_then(|(id, _)| id.as_local()) == Some(def_id)
|
||||
|| self.tcx.is_reachable_non_generic(def_id)
|
||||
|| self
|
||||
.tcx
|
||||
.codegen_fn_attrs(def_id)
|
||||
.flags
|
||||
.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
|
||||
|| {
|
||||
let flags = self.tcx.codegen_fn_attrs(def_id).flags;
|
||||
flags.intersects(
|
||||
CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
|
||||
| CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -872,7 +872,7 @@ fn mono_item_visibility<'tcx>(
|
|||
// visibility. In some situations though we'll want to prevent this
|
||||
// symbol from being internalized.
|
||||
//
|
||||
// There's two categories of items here:
|
||||
// There's three categories of items here:
|
||||
//
|
||||
// * First is weak lang items. These are basically mechanisms for
|
||||
// libcore to forward-reference symbols defined later in crates like
|
||||
|
|
@ -902,8 +902,16 @@ fn mono_item_visibility<'tcx>(
|
|||
// visibility below. Like the weak lang items, though, we can't let
|
||||
// LLVM internalize them as this decision is left up to the linker to
|
||||
// omit them, so prevent them from being internalized.
|
||||
//
|
||||
// * Externally implementable items. They work (in this case) pretty much the same as
|
||||
// RUSTC_STD_INTERNAL_SYMBOL in that their implementation is also chosen later in
|
||||
// the compilation process and we can't let them be internalized and they can't
|
||||
// show up as an external interface.
|
||||
let attrs = tcx.codegen_fn_attrs(def_id);
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
|
||||
if attrs.flags.intersects(
|
||||
CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
|
||||
| CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM,
|
||||
) {
|
||||
*can_be_internalized = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -217,6 +217,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
},
|
||||
Attribute::Parsed(
|
||||
AttributeKind::EiiExternTarget { .. }
|
||||
| AttributeKind::EiiExternItem
|
||||
| AttributeKind::BodyStability { .. }
|
||||
| AttributeKind::ConstStabilityIndirect
|
||||
| AttributeKind::MacroTransparency(_)
|
||||
|
|
|
|||
|
|
@ -1944,6 +1944,7 @@ symbols! {
|
|||
rustc_dump_user_args,
|
||||
rustc_dump_vtable,
|
||||
rustc_effective_visibility,
|
||||
rustc_eii_extern_item,
|
||||
rustc_evaluate_where_clauses,
|
||||
rustc_expected_cgu_reuse,
|
||||
rustc_force_inline,
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
foo1
|
||||
foo1
|
||||
foo2
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue