diff --git a/src/helpers.rs b/src/helpers.rs index d1429a0be1..29ed94a2e4 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -17,6 +17,7 @@ use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, MaybeResult, TyAndLayout}; use rustc_middle::ty::{self, Binder, FloatTy, FnSig, IntTy, Ty, TyCtxt, UintTy}; use rustc_session::config::CrateType; use rustc_span::{Span, Symbol}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::callconv::{Conv, FnAbi}; use crate::*; @@ -1258,6 +1259,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(array) } + + fn mangle_internal_symbol<'a>(&'a mut self, name: &'static str) -> &'a str + where + 'tcx: 'a, + { + let this = self.eval_context_mut(); + let tcx = *this.tcx; + this.machine + .mangle_internal_symbol_cache + .entry(name) + .or_insert_with(|| mangle_internal_symbol(tcx, name)) + } } impl<'tcx> MiriMachine<'tcx> { diff --git a/src/machine.rs b/src/machine.rs index bd901a4ed1..fb99bdc517 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -611,6 +611,9 @@ pub struct MiriMachine<'tcx> { pub(crate) reject_in_isolation_warned: RefCell>, /// Remembers which int2ptr casts we have already warned about. pub(crate) int2ptr_warned: RefCell>, + + /// Cache for `mangle_internal_symbol`. + pub(crate) mangle_internal_symbol_cache: FxHashMap<&'static str, String>, } impl<'tcx> MiriMachine<'tcx> { @@ -757,6 +760,7 @@ impl<'tcx> MiriMachine<'tcx> { native_call_mem_warned: Cell::new(false), reject_in_isolation_warned: Default::default(), int2ptr_warned: Default::default(), + mangle_internal_symbol_cache: Default::default(), } } @@ -930,6 +934,7 @@ impl VisitProvenance for MiriMachine<'_> { native_call_mem_warned: _, reject_in_isolation_warned: _, int2ptr_warned: _, + mangle_internal_symbol_cache: _, } = self; threads.visit_provenance(visit); diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 03c6081e99..52c16a0c2e 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -9,10 +9,9 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::CrateNum; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::AllocInit; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{Instance, 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}; @@ -52,7 +51,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Some shims forward to other MIR bodies. match link_name.as_str() { - name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_error_handler") => { + name if name == this.mangle_internal_symbol("__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 @@ -60,11 +59,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" ); }; - let name = - mangle_internal_symbol(*this.tcx, alloc_error_handler_name(handler_kind)); - let handler = this - .lookup_exported_symbol(Symbol::intern(&name))? - .expect("missing alloc error handler symbol"); + let name = Symbol::intern( + this.mangle_internal_symbol(alloc_error_handler_name(handler_kind)), + ); + let handler = + this.lookup_exported_symbol(name)?.expect("missing alloc error handler symbol"); return interp_ok(Some(handler)); } _ => {} @@ -138,30 +137,22 @@ 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| { + let attrs = tcx.codegen_fn_attrs(def_id); + // Skip over imports of items. 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) - || attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) + // Skip over items without an explicitly defined symbol name. + if !(attrs.export_name.is_some() + || 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 { + } + + let instance = Instance::mono(tcx, def_id); + let symbol_name = tcx.symbol_name(instance).name; + if symbol_name == link_name.as_str() { if let Some((original_instance, original_cnum)) = instance_and_crate { // Make sure we are consistent wrt what is 'first' and 'second'. let original_span = tcx.def_span(original_instance.def_id()).data(); @@ -505,9 +496,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Rust allocation - name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc") - || name == "miri_alloc" => - { + name if name == this.mangle_internal_symbol("__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. @@ -540,7 +529,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { _ => return this.emulate_allocator(default), } } - name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_zeroed") => { + name if name == this.mangle_internal_symbol("__rust_alloc_zeroed") => { return this.emulate_allocator(|this| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. @@ -559,7 +548,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_pointer(ptr, dest) }); } - name if name == mangle_internal_symbol(*this.tcx, "__rust_dealloc") + name if name == this.mangle_internal_symbol("__rust_dealloc") || name == "miri_dealloc" => { let default = |ecx: &mut MiriInterpCx<'tcx>| { @@ -592,7 +581,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { _ => return this.emulate_allocator(default), } } - name if name == mangle_internal_symbol(*this.tcx, "__rust_realloc") => { + name if name == this.mangle_internal_symbol("__rust_realloc") => { return this.emulate_allocator(|this| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case.