diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index 5e33b9d606fa5..9cff8a84db3d9 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -7,6 +7,7 @@ use rustc_ast::expand::allocator::{ }; use rustc_codegen_ssa::base::allocator_kind_for_codegen; use rustc_session::config::OomStrategy; +use rustc_symbol_mangling::mangle_internal_symbol; use crate::prelude::*; @@ -14,6 +15,7 @@ use crate::prelude::*; pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool { let Some(kind) = allocator_kind_for_codegen(tcx) else { return false }; codegen_inner( + tcx, module, kind, tcx.alloc_error_handler_kind(()).unwrap(), @@ -23,6 +25,7 @@ pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool { } fn codegen_inner( + tcx: TyCtxt<'_>, module: &mut dyn Module, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind, @@ -62,8 +65,8 @@ fn codegen_inner( crate::common::create_wrapper_function( module, sig, - &global_fn_name(method.name), - &default_fn_name(method.name), + &mangle_internal_symbol(tcx, &global_fn_name(method.name)), + &mangle_internal_symbol(tcx, &default_fn_name(method.name)), ); } } @@ -76,19 +79,32 @@ fn codegen_inner( crate::common::create_wrapper_function( module, sig, - "__rust_alloc_error_handler", - &alloc_error_handler_name(alloc_error_handler_kind), + &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), + &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)), ); - let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap(); + let data_id = module + .declare_data( + &mangle_internal_symbol(tcx, OomStrategy::SYMBOL), + Linkage::Export, + false, + false, + ) + .unwrap(); let mut data = DataDescription::new(); data.set_align(1); let val = oom_strategy.should_panic(); data.define(Box::new([val])); module.define_data(data_id, &data).unwrap(); - let data_id = - module.declare_data(NO_ALLOC_SHIM_IS_UNSTABLE, Linkage::Export, false, false).unwrap(); + let data_id = module + .declare_data( + &mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), + Linkage::Export, + false, + false, + ) + .unwrap(); let mut data = DataDescription::new(); data.set_align(1); data.define(Box::new([0])); diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index a3f4374487578..2a4698f3a9dc1 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -26,6 +26,7 @@ extern crate rustc_index; extern crate rustc_metadata; extern crate rustc_session; extern crate rustc_span; +extern crate rustc_symbol_mangling; extern crate rustc_target; #[macro_use] extern crate tracing; diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index 416f3231a13c4..f4ebd42ee2dc0 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -8,6 +8,7 @@ use rustc_ast::expand::allocator::{ use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::config::OomStrategy; +use rustc_symbol_mangling::mangle_internal_symbol; use crate::GccContext; #[cfg(feature = "master")] @@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen( panic!("invalid allocator output") } }; - let from_name = global_fn_name(method.name); - let to_name = default_fn_name(method.name); + let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name)); + let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name)); create_wrapper_function(tcx, context, &from_name, &to_name, &types, output); } @@ -64,13 +65,13 @@ pub(crate) unsafe fn codegen( create_wrapper_function( tcx, context, - "__rust_alloc_error_handler", - alloc_error_handler_name(alloc_error_handler_kind), + &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), + &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)), &[usize, usize], None, ); - let name = OomStrategy::SYMBOL.to_string(); + let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL); let global = context.new_global(None, GlobalKind::Exported, i8, name); #[cfg(feature = "master")] global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc( @@ -80,7 +81,7 @@ pub(crate) unsafe fn codegen( let value = context.new_rvalue_from_int(i8, value as i32); global.global_set_initializer_rvalue(value); - let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string(); + let name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE); let global = context.new_global(None, GlobalKind::Exported, i8, name); #[cfg(feature = "master")] global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc( diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 6455bcec6851b..e963935b3e11e 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -52,6 +52,7 @@ extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; +extern crate rustc_symbol_mangling; extern crate rustc_target; // This prevents duplicating functions and statics that are already part of the host rustc process. diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 66723cbf88206..43ad432343e37 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -6,6 +6,7 @@ use rustc_ast::expand::allocator::{ use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::config::{DebugInfo, OomStrategy}; +use rustc_symbol_mangling::mangle_internal_symbol; use crate::common::AsCCharPtr; use crate::llvm::{self, Context, False, Module, True, Type}; @@ -55,8 +56,8 @@ pub(crate) unsafe fn codegen( } }; - let from_name = global_fn_name(method.name); - let to_name = default_fn_name(method.name); + let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name)); + let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name)); create_wrapper_function(tcx, llcx, llmod, &from_name, &to_name, &args, output, false); } @@ -67,8 +68,8 @@ pub(crate) unsafe fn codegen( tcx, llcx, llmod, - "__rust_alloc_error_handler", - alloc_error_handler_name(alloc_error_handler_kind), + &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), + &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)), &[usize, usize], // size, align None, true, @@ -76,14 +77,14 @@ pub(crate) unsafe fn codegen( unsafe { // __rust_alloc_error_handler_should_panic - let name = OomStrategy::SYMBOL; + let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL); let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8); llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility())); let val = tcx.sess.opts.unstable_opts.oom.should_panic(); let llval = llvm::LLVMConstInt(i8, val as u64, False); llvm::set_initializer(ll_g, llval); - let name = NO_ALLOC_SHIM_IS_UNSTABLE; + let name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE); let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8); llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility())); let llval = llvm::LLVMConstInt(i8, 0, False); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index e7952bc95e7f9..fb7a983519546 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -27,6 +27,7 @@ use rustc_session::config::{ }; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel}; use smallvec::SmallVec; @@ -1181,7 +1182,7 @@ impl<'ll> CodegenCx<'ll, '_> { Some(def_id) => self.get_static(def_id), _ => { let ty = self.type_struct(&[self.type_ptr(), self.type_ptr()], false); - self.declare_global("rust_eh_catch_typeinfo", ty) + self.declare_global(&mangle_internal_symbol(self.tcx, "rust_eh_catch_typeinfo"), ty) } }; self.eh_catch_typeinfo.set(Some(eh_catch_typeinfo)); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 56fae135e5527..245fc246cc1fe 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -14,6 +14,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, GenericArgsRef, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::callconv::{FnAbi, PassMode}; use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use tracing::debug; @@ -812,7 +813,10 @@ fn codegen_msvc_try<'ll>( let type_name = bx.const_bytes(b"rust_panic\0"); let type_info = bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_ptr()), type_name], false); - let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info)); + let tydesc = bx.declare_global( + &mangle_internal_symbol(bx.tcx, "__rust_panic_type_info"), + bx.val_ty(type_info), + ); llvm::set_linkage(tydesc, llvm::Linkage::LinkOnceODRLinkage); if bx.cx.tcx.sess.target.supports_comdat() { diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 459f4329d6e92..5c9e72ae0f19b 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -1,6 +1,6 @@ use std::collections::hash_map::Entry::*; -use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE}; +use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name}; use rustc_data_structures::unord::UnordMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId}; @@ -13,6 +13,7 @@ use rustc_middle::query::LocalCrate; use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, Ty, TyCtxt}; use rustc_middle::util::Providers; use rustc_session::config::{CrateType, OomStrategy}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::callconv::Conv; use rustc_target::spec::{SanitizerSet, TlsModel}; use tracing::debug; @@ -219,8 +220,11 @@ fn exported_symbols_provider_local( if allocator_kind_for_codegen(tcx).is_some() { for symbol_name in ALLOCATOR_METHODS .iter() - .map(|method| format!("__rust_{}", method.name)) - .chain(["__rust_alloc_error_handler".to_string(), OomStrategy::SYMBOL.to_string()]) + .map(|method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str())) + .chain([ + mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), + mangle_internal_symbol(tcx, OomStrategy::SYMBOL), + ]) { let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); @@ -234,8 +238,10 @@ fn exported_symbols_provider_local( )); } - let exported_symbol = - ExportedSymbol::NoDefId(SymbolName::new(tcx, NO_ALLOC_SHIM_IS_UNSTABLE)); + let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new( + tcx, + &mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), + )); symbols.push(( exported_symbol, SymbolExportInfo { diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 73a97d32c2d64..322a95a0ecaaa 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -28,6 +28,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_session::config::{self, CrateType, EntryFnType, OutputType}; use rustc_span::{DUMMY_SP, Symbol, sym}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt}; use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; use tracing::{debug, info}; @@ -989,7 +990,12 @@ impl CrateInfo { .for_each(|(_, linked_symbols)| { let mut symbols = missing_weak_lang_items .iter() - .map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text)) + .map(|item| { + ( + format!("{prefix}{}", mangle_internal_symbol(tcx, item.as_str())), + SymbolExportKind::Text, + ) + }) .collect::>(); symbols.sort_unstable_by(|a, b| a.0.cmp(&b.0)); linked_symbols.extend(symbols); @@ -1002,7 +1008,13 @@ impl CrateInfo { // errors. linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| { ( - format!("{prefix}{}", global_fn_name(method.name).as_str()), + format!( + "{prefix}{}", + mangle_internal_symbol( + tcx, + global_fn_name(method.name).as_str() + ) + ), SymbolExportKind::Text, ) })); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 673740b4aab9f..adae62791592f 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -659,25 +659,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // strippable by the linker. // // Additionally weak lang items have predetermined symbol names. - if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; - } if let Some((name, _)) = lang_items::extract(attrs) && let Some(lang_item) = LangItem::from_name(name) - && let Some(link_name) = lang_item.link_name() { - codegen_fn_attrs.export_name = Some(link_name); - codegen_fn_attrs.link_name = Some(link_name); + if WEAK_LANG_ITEMS.iter().any(|&l| l == lang_item) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; + } + if let Some(link_name) = lang_item.link_name() { + codegen_fn_attrs.export_name = Some(link_name); + codegen_fn_attrs.link_name = Some(link_name); + } } check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span); - // Internal symbols to the standard library all have no_mangle semantics in - // that they have defined symbol names present in the function name. This - // also applies to weak symbols where they all have known symbol names. - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; - } - // Any linkage to LLVM intrinsics for now forcibly marks them all as never // unwinds since LLVM sometimes can't handle codegen which `invoke`s // intrinsic functions. diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 311bc60c3cd39..65a0bfd99c42f 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -174,6 +174,7 @@ impl CodegenFnAttrs { /// * `#[linkage]` is present pub fn contains_extern_indicator(&self) -> bool { self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) + || self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) || self.export_name.is_some() || match self.linkage { // These are private, so make sure we don't try to consider diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9be868122872d..d405d3a1832db 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2198,7 +2198,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::Fn | Target::Static => {} + Target::Fn | Target::Static | Target::ForeignFn | Target::ForeignStatic => {} _ => { self.tcx .dcx() diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index fd465717bf766..a78c707516ef4 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -184,9 +184,7 @@ impl<'tcx> ReachableContext<'tcx> { CodegenFnAttrs::EMPTY }; let is_extern = codegen_attrs.contains_extern_indicator(); - let std_internal = - codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL); - if is_extern || std_internal { + if is_extern { self.reachable_symbols.insert(search_item); } } else { @@ -426,7 +424,6 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { } let codegen_attrs = tcx.codegen_fn_attrs(def_id); codegen_attrs.contains_extern_indicator() - || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) // FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by // `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their // `SymbolExportLevel::Rust` export level but may end up being exported in dylibs. diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 4312c82815c16..202fa152a75e4 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -112,6 +112,8 @@ mod v0; pub mod errors; pub mod test; +pub use v0::mangle_internal_symbol; + /// This function computes the symbol name for the given `instance` and the /// given instantiating crate. That is, if you know that instance X is /// instantiated in crate Y, this is the symbol name this instance would have. @@ -183,6 +185,39 @@ fn compute_symbol_name<'tcx>( CodegenFnAttrs::EMPTY }; + if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { + // Items marked as #[rustc_std_internal_symbol] need to have a fixed + // symbol name because it is used to import items from another crate + // without a direct dependency. As such it is not possible to look up + // the mangled name for the `Instance` from the crate metadata of the + // defining crate. + // Weak lang items automatically get #[rustc_std_internal_symbol] + // applied by the code computing the CodegenFnAttrs. + // We are mangling all #[rustc_std_internal_symbol] items that don't + // also have #[no_mangle] as a combination of the rustc version and the + // unmangled linkage name. This is to ensure that if we link against a + // staticlib compiled by a different rustc version, we don't get symbol + // conflicts or even UB due to a different implementation/ABI. Rust + // staticlibs currently export all symbols, including those that are + // hidden in cdylibs. + // We are using the v0 symbol mangling scheme here as we need to be + // consistent across all crates and in some contexts the legacy symbol + // mangling scheme can't be used. For example both the GCC backend and + // Rust-for-Linux don't support some of the characters used by the + // legacy symbol mangling scheme. + let name = if tcx.is_foreign_item(def_id) { + if let Some(name) = attrs.link_name { name } else { tcx.item_name(def_id) } + } else { + if let Some(name) = attrs.export_name { name } else { tcx.item_name(def_id) } + }; + + if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { + return name.to_string(); + } else { + return v0::mangle_internal_symbol(tcx, name.as_str()); + } + } + // Foreign items by default use no mangling for their symbol name. There's a // few exceptions to this rule though: // @@ -198,6 +233,8 @@ fn compute_symbol_name<'tcx>( // is present we mangle everything on wasm because the demangled form will // show up in the `wasm-import-name` custom attribute in LLVM IR. // + // * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way + // both for exports and imports through foreign items. This is handled above. // [1]: https://bugs.llvm.org/show_bug.cgi?id=44316 if tcx.is_foreign_item(def_id) && (!tcx.sess.target.is_like_wasm diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 4fafd1ac3509a..0edf5bfb7379e 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -1,4 +1,5 @@ use std::fmt::Write; +use std::hash::Hasher; use std::iter; use std::ops::Range; @@ -6,6 +7,8 @@ use rustc_abi::{ExternAbi, Integer}; use rustc_data_structures::base_n::ToBaseN; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::intern::Interned; +use rustc_data_structures::stable_hasher::StableHasher; +use rustc_hashes::Hash64; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{CrateNum, DefId}; @@ -70,6 +73,54 @@ pub(super) fn mangle<'tcx>( std::mem::take(&mut cx.out) } +pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> String { + if item_name == "rust_eh_personality" { + // rust_eh_personality must not be renamed as LLVM hard-codes the name + return "rust_eh_personality".to_owned(); + } else if item_name == "__rust_no_alloc_shim_is_unstable" { + // Temporary back compat hack to give people the chance to migrate to + // include #[rustc_std_internal_symbol]. + return "__rust_no_alloc_shim_is_unstable".to_owned(); + } + + let prefix = "_R"; + let mut cx: SymbolMangler<'_> = SymbolMangler { + tcx, + start_offset: prefix.len(), + paths: FxHashMap::default(), + types: FxHashMap::default(), + consts: FxHashMap::default(), + binders: vec![], + out: String::from(prefix), + }; + + cx.path_append_ns( + |cx| { + cx.push("C"); + cx.push_disambiguator({ + let mut hasher = StableHasher::new(); + // Incorporate the rustc version to ensure #[rustc_std_internal_symbol] functions + // get a different symbol name depending on the rustc version. + // + // RUSTC_FORCE_RUSTC_VERSION is ignored here as otherwise different we would get an + // abi incompatibility with the standard library. + hasher.write(tcx.sess.cfg_version.as_bytes()); + + let hash: Hash64 = hasher.finish(); + hash.as_u64() + }); + cx.push_ident("__rustc"); + Ok(()) + }, + 'v', + 0, + item_name, + ) + .unwrap(); + + std::mem::take(&mut cx.out) +} + pub(super) fn mangle_typeid_for_trait_ref<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::ExistentialTraitRef<'tcx>, diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index e686a02f29b0c..e4d4ad9fc3b19 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -12,25 +12,28 @@ use core::ptr::{self, NonNull}; unsafe extern "Rust" { // These are the magic symbols to call the global allocator. rustc generates - // them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute + // them to call the global allocator if there is a `#[global_allocator]` attribute // (the code expanding that attribute macro generates those functions), or to call // the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`) // otherwise. - // The rustc fork of LLVM 14 and earlier also special-cases these function names to be able to optimize them - // like `malloc`, `realloc`, and `free`, respectively. #[rustc_allocator] #[rustc_nounwind] + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_alloc(size: usize, align: usize) -> *mut u8; #[rustc_deallocator] #[rustc_nounwind] + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); #[rustc_reallocator] #[rustc_nounwind] + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8; #[rustc_allocator_zeroed] #[rustc_nounwind] + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] static __rust_no_alloc_shim_is_unstable: u8; } @@ -359,6 +362,7 @@ unsafe extern "Rust" { // This is the magic symbol to call the global alloc error handler. rustc generates // it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the // default implementations below (`__rdl_oom`) otherwise. + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_alloc_error_handler(size: usize, align: usize) -> !; } @@ -429,6 +433,7 @@ pub mod __alloc_error_handler { unsafe extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] static __rust_alloc_error_handler_should_panic: u8; } diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index a284633ea2fc7..e5c1d6bdb3b06 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -79,9 +79,11 @@ cfg_if::cfg_if! { unsafe extern "C" { /// Handler in std called when a panic object is dropped outside of /// `catch_unwind`. + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_drop_panic() -> !; /// Handler in std called when a foreign exception is caught. + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_foreign_exception() -> !; } diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 99d105a2454a5..5d2a304b41c5a 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -348,6 +348,7 @@ fn default_alloc_error_hook(layout: Layout) { unsafe extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] static __rust_alloc_error_handler_should_panic: u8; } diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index b47b41d4bc5b7..b35549c92ada7 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -55,12 +55,14 @@ pub static EMPTY_PANIC: fn(&'static str) -> ! = // hook up these functions, but it is not this day! #[allow(improper_ctypes)] unsafe extern "C" { + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); } unsafe extern "Rust" { /// `PanicPayload` lazily performs allocation only when needed (this avoids /// allocations when using the "abort" panic runtime). + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32; } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 9ac19a2a5f2b4..116414f69c228 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -70,6 +70,7 @@ extern crate rustc_index; extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; +extern crate rustc_symbol_mangling; extern crate rustc_target; // Linking `rustc_driver` pulls in the required object code as the rest of the rustc crates are // shipped only as rmeta files. diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs index 20dd3c8db2a3e..2feed5a835228 100644 --- a/src/tools/miri/src/shims/extern_static.rs +++ b/src/tools/miri/src/shims/extern_static.rs @@ -1,5 +1,7 @@ //! Provides the `extern static` that this platform expects. +use rustc_symbol_mangling::mangle_internal_symbol; + use crate::*; impl<'tcx> MiriMachine<'tcx> { @@ -50,7 +52,11 @@ impl<'tcx> MiriMachine<'tcx> { // "__rust_alloc_error_handler_should_panic" let val = ecx.tcx.sess.opts.unstable_opts.oom.should_panic(); let val = ImmTy::from_int(val, ecx.machine.layouts.u8); - Self::alloc_extern_static(ecx, "__rust_alloc_error_handler_should_panic", val)?; + Self::alloc_extern_static( + ecx, + &mangle_internal_symbol(*ecx.tcx, "__rust_alloc_error_handler_should_panic"), + val, + )?; if ecx.target_os_is_unix() { // "environ" is mandated by POSIX. diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index bedc1ebdc9509..9e254f5884e2c 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -12,6 +12,7 @@ use rustc_middle::mir::interpret::AllocInit; use rustc_middle::ty::Ty; use rustc_middle::{mir, ty}; use rustc_span::Symbol; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::callconv::{Conv, FnAbi}; use self::helpers::{ToHost, ToSoft}; @@ -51,7 +52,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Some shims forward to other MIR bodies. match link_name.as_str() { - "__rust_alloc_error_handler" => { + name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_error_handler") => { // Forward to the right symbol that implements this function. let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else { // in real code, this symbol does not exist without an allocator @@ -59,9 +60,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" ); }; - let name = alloc_error_handler_name(handler_kind); + let name = + mangle_internal_symbol(*this.tcx, alloc_error_handler_name(handler_kind)); let handler = this - .lookup_exported_symbol(Symbol::intern(name))? + .lookup_exported_symbol(Symbol::intern(&name))? .expect("missing alloc error handler symbol"); return interp_ok(Some(handler)); } @@ -136,15 +138,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Find it if it was not cached. let mut instance_and_crate: Option<(ty::Instance<'_>, CrateNum)> = None; helpers::iter_exported_symbols(tcx, |cnum, def_id| { + if tcx.is_foreign_item(def_id) { + // Skip over imports of items + return interp_ok(()); + } + let attrs = tcx.codegen_fn_attrs(def_id); + // FIXME use tcx.symbol_name(instance) instead let symbol_name = if let Some(export_name) = attrs.export_name { export_name - } else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { + } else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) + || attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) + { tcx.item_name(def_id) } else { // Skip over items without an explicitly defined symbol name. return interp_ok(()); }; + let symbol_name = + if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { + Symbol::intern(&mangle_internal_symbol(tcx, symbol_name.as_str())) + } else { + symbol_name + }; if symbol_name == link_name { if let Some((original_instance, original_cnum)) = instance_and_crate { // Make sure we are consistent wrt what is 'first' and 'second'. @@ -489,7 +505,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Rust allocation - "__rust_alloc" | "miri_alloc" => { + name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc") + || name == "miri_alloc" => + { let default = |ecx: &mut MiriInterpCx<'tcx>| { // Only call `check_shim` when `#[global_allocator]` isn't used. When that // macro is used, we act like no shim exists, so that the exported function can run. @@ -500,9 +518,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { ecx.check_rustc_alloc_request(size, align)?; let memory_kind = match link_name.as_str() { - "__rust_alloc" => MiriMemoryKind::Rust, "miri_alloc" => MiriMemoryKind::Miri, - _ => unreachable!(), + _ => MiriMemoryKind::Rust, }; let ptr = ecx.allocate_ptr( @@ -516,15 +533,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { }; match link_name.as_str() { - "__rust_alloc" => return this.emulate_allocator(default), "miri_alloc" => { default(this)?; return interp_ok(EmulateItemResult::NeedsReturn); } - _ => unreachable!(), + _ => return this.emulate_allocator(default), } } - "__rust_alloc_zeroed" => { + name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_zeroed") => { return this.emulate_allocator(|this| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. @@ -543,7 +559,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_pointer(ptr, dest) }); } - "__rust_dealloc" | "miri_dealloc" => { + name if name == mangle_internal_symbol(*this.tcx, "__rust_dealloc") + || name == "miri_dealloc" => + { let default = |ecx: &mut MiriInterpCx<'tcx>| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. @@ -554,9 +572,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let align = ecx.read_target_usize(align)?; let memory_kind = match link_name.as_str() { - "__rust_dealloc" => MiriMemoryKind::Rust, "miri_dealloc" => MiriMemoryKind::Miri, - _ => unreachable!(), + _ => MiriMemoryKind::Rust, }; // No need to check old_size/align; we anyway check that they match the allocation. @@ -568,17 +585,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { }; match link_name.as_str() { - "__rust_dealloc" => { - return this.emulate_allocator(default); - } "miri_dealloc" => { default(this)?; return interp_ok(EmulateItemResult::NeedsReturn); } - _ => unreachable!(), + _ => return this.emulate_allocator(default), } } - "__rust_realloc" => { + name if name == mangle_internal_symbol(*this.tcx, "__rust_realloc") => { return this.emulate_allocator(|this| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. diff --git a/src/tools/miri/tests/fail/alloc/too_large.rs b/src/tools/miri/tests/fail/alloc/too_large.rs index 4e28d2401d79f..c53318855aba0 100644 --- a/src/tools/miri/tests/fail/alloc/too_large.rs +++ b/src/tools/miri/tests/fail/alloc/too_large.rs @@ -1,4 +1,7 @@ +#![feature(rustc_attrs)] + extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_alloc(size: usize, align: usize) -> *mut u8; } diff --git a/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs b/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs index 08d84c461bfaa..34c6a6ce55012 100644 --- a/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs +++ b/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs @@ -2,7 +2,10 @@ // because rustc does not support alignments that large. // https://github.com/rust-lang/miri/issues/3687 +#![feature(rustc_attrs)] + extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_alloc(size: usize, align: usize) -> *mut u8; } diff --git a/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs b/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs index a4ab8094bf4e1..ce8861937f873 100644 --- a/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs +++ b/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs @@ -1,5 +1,9 @@ // Test non-power-of-two alignment. + +#![feature(rustc_attrs)] + extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_alloc(size: usize, align: usize) -> *mut u8; } diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs index f174909e9d56b..d0a2848205410 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs @@ -3,6 +3,8 @@ // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 +#![feature(rustc_attrs)] + use std::thread::spawn; #[derive(Copy, Clone)] @@ -12,6 +14,7 @@ unsafe impl Send for EvilSend {} unsafe impl Sync for EvilSend {} extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); } diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs index 1edfbf5e61c0d..f56c44cabc234 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs @@ -3,6 +3,8 @@ // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 +#![feature(rustc_attrs)] + use std::thread::spawn; #[derive(Copy, Clone)] @@ -12,6 +14,7 @@ unsafe impl Send for EvilSend {} unsafe impl Sync for EvilSend {} extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); } diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs index 7605f1911db77..a16ea25e11ce8 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs @@ -3,6 +3,8 @@ // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 +#![feature(rustc_attrs)] + use std::thread::spawn; #[derive(Copy, Clone)] @@ -12,6 +14,7 @@ unsafe impl Send for EvilSend {} unsafe impl Sync for EvilSend {} extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); } pub fn main() { diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs index 4f3819bd636b2..f3855e33c98d9 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs @@ -3,6 +3,8 @@ // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 +#![feature(rustc_attrs)] + use std::thread::spawn; #[derive(Copy, Clone)] @@ -12,6 +14,7 @@ unsafe impl Send for EvilSend {} unsafe impl Sync for EvilSend {} extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); } pub fn main() { diff --git a/src/tools/miri/tests/pass/function_calls/exported_symbol.rs b/src/tools/miri/tests/pass/function_calls/exported_symbol.rs index 27aee9c883588..d804f3642b1d2 100644 --- a/src/tools/miri/tests/pass/function_calls/exported_symbol.rs +++ b/src/tools/miri/tests/pass/function_calls/exported_symbol.rs @@ -40,6 +40,7 @@ fn main() { extern "Rust" { fn bar() -> i32; + #[rustc_std_internal_symbol] fn baz() -> i32; fn qux() -> i32; } @@ -63,6 +64,7 @@ fn main() { extern "C" { fn bar() -> i32; + #[rustc_std_internal_symbol] fn baz() -> i32; fn qux() -> i32; } diff --git a/tests/codegen/alloc-optimisation.rs b/tests/codegen/alloc-optimisation.rs index 8abeecf8550be..19f14647c1d7d 100644 --- a/tests/codegen/alloc-optimisation.rs +++ b/tests/codegen/alloc-optimisation.rs @@ -5,7 +5,7 @@ pub fn alloc_test(data: u32) { // CHECK-LABEL: @alloc_test // CHECK-NEXT: start: - // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1 + // CHECK-NEXT: {{.*}} load volatile i8, ptr @{{.*}}__rust_no_alloc_shim_is_unstable, align 1 // CHECK-NEXT: ret void let x = Box::new(data); drop(x); diff --git a/tests/codegen/box-uninit-bytes.rs b/tests/codegen/box-uninit-bytes.rs index 3b83ef3e250c4..0cc011485951c 100644 --- a/tests/codegen/box-uninit-bytes.rs +++ b/tests/codegen/box-uninit-bytes.rs @@ -41,6 +41,6 @@ pub fn box_lotsa_padding() -> Box { // Hide the `allocalign` attribute in the declaration of __rust_alloc // from the CHECK-NOT above, and also verify the attributes got set reasonably. -// CHECK: declare {{(dso_local )?}}noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]] +// CHECK: declare {{(dso_local )?}}noalias noundef ptr @{{.*}}__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]] // CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) {{(uwtable )?}}"alloc-family"="__rust_alloc" {{.*}} } diff --git a/tests/codegen/dealloc-no-unwind.rs b/tests/codegen/dealloc-no-unwind.rs index c560d7a993209..68597817d6f34 100644 --- a/tests/codegen/dealloc-no-unwind.rs +++ b/tests/codegen/dealloc-no-unwind.rs @@ -18,7 +18,7 @@ impl Drop for A { #[no_mangle] pub fn a(a: Box) { // CHECK-LABEL: define{{.*}}void @a - // CHECK: call void @__rust_dealloc + // CHECK: call void @{{.*}}__rust_dealloc // CHECK-NEXT: call void @foo let _a = A; drop(a); diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs index 4dab499a8a5cb..3bb942d11d534 100644 --- a/tests/codegen/iter-repeat-n-trivial-drop.rs +++ b/tests/codegen/iter-repeat-n-trivial-drop.rs @@ -47,7 +47,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN) -> Option Vec { - // CHECK: %[[ADDR:.+]] = tail call {{(noalias )?}}noundef dereferenceable_or_null(1234) ptr @__rust_alloc(i64 noundef {{(range\(i64 1, 0\) )?}}1234, i64 noundef {{(range\(i64 1, -9223372036854775807\) )?}}1) + // CHECK: %[[ADDR:.+]] = tail call {{(noalias )?}}noundef dereferenceable_or_null(1234) ptr @{{.*}}__rust_alloc(i64 noundef {{(range\(i64 1, 0\) )?}}1234, i64 noundef {{(range\(i64 1, -9223372036854775807\) )?}}1) // CHECK: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %[[ADDR]], i8 42, i64 1234, let n = 1234_usize; diff --git a/tests/codegen/vec-calloc.rs b/tests/codegen/vec-calloc.rs index 2e2769ce1301a..d1c320ead012e 100644 --- a/tests/codegen/vec-calloc.rs +++ b/tests/codegen/vec-calloc.rs @@ -177,6 +177,6 @@ pub fn vec_option_i32(n: usize) -> Vec> { } // Ensure that __rust_alloc_zeroed gets the right attributes for LLVM to optimize it away. -// CHECK: declare noalias noundef ptr @__rust_alloc_zeroed(i64 noundef, i64 allocalign noundef) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]] +// CHECK: declare noalias noundef ptr @{{.*}}__rust_alloc_zeroed(i64 noundef, i64 allocalign noundef) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]] // CHECK-DAG: attributes [[RUST_ALLOC_ZEROED_ATTRS]] = { {{.*}} allockind("alloc,zeroed,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} } diff --git a/tests/codegen/vec-optimizes-away.rs b/tests/codegen/vec-optimizes-away.rs index 39d5c1614c82a..f6ed2898bdaaa 100644 --- a/tests/codegen/vec-optimizes-away.rs +++ b/tests/codegen/vec-optimizes-away.rs @@ -5,7 +5,7 @@ pub fn sum_me() -> i32 { // CHECK-LABEL: @sum_me // CHECK-NEXT: {{^.*:$}} - // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1 + // CHECK-NEXT: {{.*}} load volatile i8, ptr @{{.*}}__rust_no_alloc_shim_is_unstable, align 1 // CHECK-NEXT: ret i32 6 vec![1, 2, 3].iter().sum::() } diff --git a/tests/run-make/symbols-all-mangled/a_lib.rs b/tests/run-make/symbols-all-mangled/a_lib.rs new file mode 100644 index 0000000000000..716dd3263c5b7 --- /dev/null +++ b/tests/run-make/symbols-all-mangled/a_lib.rs @@ -0,0 +1 @@ +pub fn public_rust_function() {} diff --git a/tests/run-make/symbols-all-mangled/an_executable.rs b/tests/run-make/symbols-all-mangled/an_executable.rs new file mode 100644 index 0000000000000..db8df13b9a753 --- /dev/null +++ b/tests/run-make/symbols-all-mangled/an_executable.rs @@ -0,0 +1,3 @@ +pub fn public_rust_function_from_exe() {} + +fn main() {} diff --git a/tests/run-make/symbols-all-mangled/rmake.rs b/tests/run-make/symbols-all-mangled/rmake.rs new file mode 100644 index 0000000000000..a4c656722a7ac --- /dev/null +++ b/tests/run-make/symbols-all-mangled/rmake.rs @@ -0,0 +1,84 @@ +// Check that all symbols in cdylibs, staticlibs and bins are mangled + +use run_make_support::object::read::{Object, ObjectSymbol}; +use run_make_support::{bin_name, dynamic_lib_name, object, rfs, rustc, static_lib_name}; + +fn main() { + let staticlib_name = static_lib_name("a_lib"); + let cdylib_name = dynamic_lib_name("a_lib"); + let exe_name = bin_name("an_executable"); + rustc().crate_type("cdylib").input("a_lib.rs").run(); + rustc().crate_type("staticlib").input("a_lib.rs").run(); + rustc().crate_type("bin").input("an_executable.rs").run(); + + symbols_check_archive(&staticlib_name); + symbols_check(&cdylib_name); + symbols_check(&exe_name); +} + +fn symbols_check_archive(path: &str) { + let binary_data = rfs::read(path); + let file = object::read::archive::ArchiveFile::parse(&*binary_data).unwrap(); + for symbol in file.symbols().unwrap().unwrap() { + let symbol = symbol.unwrap(); + let name = strip_underscore_if_apple(std::str::from_utf8(symbol.name()).unwrap()); + if name.starts_with("_ZN") || name.starts_with("_R") { + continue; // Correctly mangled + } + + let member_name = + std::str::from_utf8(file.member(symbol.offset()).unwrap().name()).unwrap(); + if !member_name.ends_with(".rcgu.o") || member_name.contains("compiler_builtins") { + continue; // All compiler-builtins symbols must remain unmangled + } + + if name == "__rust_no_alloc_shim_is_unstable" { + continue; // FIXME remove exception once we mangle this symbol + } + + if name.contains("rust_eh_personality") { + continue; // Unfortunately LLVM doesn't allow us to mangle this symbol + } + + panic!("Unmangled symbol found: {name}"); + } +} + +fn symbols_check(path: &str) { + let binary_data = rfs::read(path); + let file = object::File::parse(&*binary_data).unwrap(); + for symbol in file.symbols() { + if !symbol.is_definition() || !symbol.is_global() { + continue; + } + if symbol.is_weak() { + continue; // Likely an intrinsic from compiler-builtins + } + let name = strip_underscore_if_apple(symbol.name().unwrap()); + if name.starts_with("_ZN") || name.starts_with("_R") { + continue; // Correctly mangled + } + + if name == "__rust_no_alloc_shim_is_unstable" { + continue; // FIXME remove exception once we mangle this symbol + } + + if name.contains("rust_eh_personality") { + continue; // Unfortunately LLVM doesn't allow us to mangle this symbol + } + + if ["_start", "__dso_handle", "_init", "_fini", "__TMC_END__"].contains(&name) { + continue; // Part of the libc crt object + } + + if name == "main" { + continue; // The main symbol has to be unmangled for the crt object to find it + } + + panic!("Unmangled symbol found: {name}"); + } +} + +fn strip_underscore_if_apple(symbol: &str) -> &str { + if cfg!(target_vendor = "apple") { symbol.strip_prefix("_").unwrap() } else { symbol } +}