From f47c48048d6ba9d96dd4138803595284443d7708 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 9 Oct 2025 12:35:14 +0000 Subject: [PATCH 1/6] Reduce scope of unsafe block in cg_llvm allocator codegen --- compiler/rustc_codegen_llvm/src/allocator.rs | 42 ++++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 824aa501036d4..486ee817a1c79 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -95,28 +95,28 @@ pub(crate) unsafe fn codegen( &CodegenFnAttrs::new(), ); - unsafe { - // __rust_alloc_error_handler_should_panic_v2 - create_const_value_function( - tcx, - &cx, - &mangle_internal_symbol(tcx, OomStrategy::SYMBOL), - &i8, - &llvm::LLVMConstInt(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as u64, FALSE), - ); + // __rust_alloc_error_handler_should_panic_v2 + create_const_value_function( + tcx, + &cx, + &mangle_internal_symbol(tcx, OomStrategy::SYMBOL), + &i8, + unsafe { + llvm::LLVMConstInt(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as u64, FALSE) + }, + ); - // __rust_no_alloc_shim_is_unstable_v2 - create_wrapper_function( - tcx, - &cx, - &mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), - None, - &[], - None, - false, - &CodegenFnAttrs::new(), - ); - } + // __rust_no_alloc_shim_is_unstable_v2 + create_wrapper_function( + tcx, + &cx, + &mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), + None, + &[], + None, + false, + &CodegenFnAttrs::new(), + ); if tcx.sess.opts.debuginfo != DebugInfo::None { let dbg_cx = debuginfo::CodegenUnitDebugContext::new(cx.llmod); From 116f4ae171e292423304ee6842a11c48a4fff5ba Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 26 Jun 2025 13:44:01 +0000 Subject: [PATCH 2/6] Support #[alloc_error_handler] without the allocator shim Currently it is possible to avoid linking the allocator shim when __rust_no_alloc_shim_is_unstable_v2 is defined when linking rlibs directly as some build systems need. However this requires liballoc to be compiled with --cfg no_global_oom_handling, which places huge restrictions on what functions you can call and makes it impossible to use libstd. Or alternatively you have to define __rust_alloc_error_handler and (when using libstd) __rust_alloc_error_handler_should_panic using #[rustc_std_internal_symbol]. With this commit you can either use libstd and define __rust_alloc_error_handler_should_panic or not use libstd and use #[alloc_error_handler] instead. Both options are still unstable though. Eventually the alloc_error_handler may either be removed entirely (though the PR for that has been stale for years now) or we may start using weak symbols for it instead. For the latter case this commit is a prerequisite anyway. --- compiler/rustc_ast/src/expand/allocator.rs | 8 +----- .../src/alloc_error_handler.rs | 5 ++-- .../rustc_codegen_cranelift/src/allocator.rs | 28 ++++++++++--------- compiler/rustc_codegen_gcc/src/allocator.rs | 24 ++++++++-------- compiler/rustc_codegen_llvm/src/allocator.rs | 28 ++++++++++--------- .../src/back/symbol_export.rs | 6 ++-- compiler/rustc_metadata/src/creader.rs | 24 ++++++++-------- library/alloc/src/alloc.rs | 4 +-- library/std/src/alloc.rs | 7 +++-- src/tools/miri/src/shims/foreign_items.rs | 17 ++++++----- .../fail/alloc/alloc_error_handler.stderr | 2 +- .../alloc/alloc_error_handler_custom.stderr | 2 +- .../alloc/alloc_error_handler_no_std.stderr | 2 +- tests/run-make/bin-emit-no-symbols/rmake.rs | 2 +- tests/ui/sanitizer/dataflow-abilist.txt | 10 ------- 15 files changed, 83 insertions(+), 86 deletions(-) diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index 7dee2ed17b4be..a3f9ddb154f71 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -15,13 +15,7 @@ pub fn default_fn_name(base: Symbol) -> String { format!("__rdl_{base}") } -pub fn alloc_error_handler_name(alloc_error_handler_kind: AllocatorKind) -> &'static str { - match alloc_error_handler_kind { - AllocatorKind::Global => "__rg_oom", - AllocatorKind::Default => "__rdl_oom", - } -} - +pub const ALLOC_ERROR_HANDLER: Symbol = sym::alloc_error_handler; pub const NO_ALLOC_SHIM_IS_UNSTABLE: &str = "__rust_no_alloc_shim_is_unstable_v2"; pub enum AllocatorTy { diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 35ef6be095e9c..40946f3b2791a 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -1,3 +1,4 @@ +use rustc_ast::expand::allocator::{ALLOC_ERROR_HANDLER, global_fn_name}; use rustc_ast::{ self as ast, Fn, FnHeader, FnSig, Generics, ItemKind, Safety, Stmt, StmtKind, TyKind, }; @@ -55,7 +56,7 @@ pub(crate) fn expand( } // #[rustc_std_internal_symbol] -// unsafe fn __rg_oom(size: usize, align: usize) -> ! { +// unsafe fn __rust_alloc_error_handler(size: usize, align: usize) -> ! { // handler(core::alloc::Layout::from_size_align_unchecked(size, align)) // } fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span) -> Stmt { @@ -84,7 +85,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span let kind = ItemKind::Fn(Box::new(Fn { defaultness: ast::Defaultness::Final, sig, - ident: Ident::from_str_and_span("__rg_oom", span), + ident: Ident::from_str_and_span(&global_fn_name(ALLOC_ERROR_HANDLER), span), generics: Generics::default(), contract: None, body, diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index 04f1129d87c1f..9533f870434ab 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -3,8 +3,8 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use rustc_ast::expand::allocator::{ - ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, - alloc_error_handler_name, default_fn_name, global_fn_name, + ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, + default_fn_name, global_fn_name, }; use rustc_codegen_ssa::base::allocator_kind_for_codegen; use rustc_session::config::OomStrategy; @@ -72,17 +72,19 @@ fn codegen_inner( } } - let sig = Signature { - call_conv: module.target_config().default_call_conv, - params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)], - returns: vec![], - }; - crate::common::create_wrapper_function( - module, - sig, - &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), - &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)), - ); + if alloc_error_handler_kind == AllocatorKind::Default { + let sig = Signature { + call_conv: module.target_config().default_call_conv, + params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)], + returns: vec![], + }; + crate::common::create_wrapper_function( + module, + sig, + &mangle_internal_symbol(tcx, &global_fn_name(ALLOC_ERROR_HANDLER)), + &mangle_internal_symbol(tcx, &default_fn_name(ALLOC_ERROR_HANDLER)), + ); + } { let sig = Signature { diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index 2a95a7368aac6..3f99612fcdb02 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -2,8 +2,8 @@ use gccjit::FnAttribute; use gccjit::{Context, FunctionType, RValue, ToRValue, Type}; use rustc_ast::expand::allocator::{ - ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, - alloc_error_handler_name, default_fn_name, global_fn_name, + ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, + default_fn_name, global_fn_name, }; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; @@ -61,15 +61,17 @@ pub(crate) unsafe fn codegen( } } - // FIXME(bjorn3): Add noreturn attribute - create_wrapper_function( - tcx, - context, - &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), - Some(&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind))), - &[usize, usize], - None, - ); + if alloc_error_handler_kind == AllocatorKind::Default { + // FIXME(bjorn3): Add noreturn attribute + create_wrapper_function( + tcx, + context, + &mangle_internal_symbol(tcx, &global_fn_name(ALLOC_ERROR_HANDLER)), + Some(&mangle_internal_symbol(tcx, &default_fn_name(ALLOC_ERROR_HANDLER))), + &[usize, usize], + None, + ); + } create_const_value_function( tcx, diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 486ee817a1c79..b645db3f4a8b8 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -1,7 +1,7 @@ use libc::c_uint; use rustc_ast::expand::allocator::{ - ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, - alloc_error_handler_name, default_fn_name, global_fn_name, + ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, + default_fn_name, global_fn_name, }; use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _; use rustc_middle::bug; @@ -83,17 +83,19 @@ pub(crate) unsafe fn codegen( } } - // rust alloc error handler - create_wrapper_function( - tcx, - &cx, - &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), - Some(&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind))), - &[usize, usize], // size, align - None, - true, - &CodegenFnAttrs::new(), - ); + if alloc_error_handler_kind == AllocatorKind::Default { + // rust alloc error handler + create_wrapper_function( + tcx, + &cx, + &mangle_internal_symbol(tcx, &global_fn_name(ALLOC_ERROR_HANDLER)), + Some(&mangle_internal_symbol(tcx, &default_fn_name(ALLOC_ERROR_HANDLER))), + &[usize, usize], // size, align + None, + true, + &CodegenFnAttrs::new(), + ); + } // __rust_alloc_error_handler_should_panic_v2 create_const_value_function( diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index b49e67217fb01..5bc18e2d7f8bb 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -1,7 +1,9 @@ use std::collections::hash_map::Entry::*; use rustc_abi::{CanonAbi, X86Call}; -use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name}; +use rustc_ast::expand::allocator::{ + ALLOC_ERROR_HANDLER, 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}; @@ -498,7 +500,7 @@ pub(crate) fn allocator_shim_symbols( .iter() .map(move |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, global_fn_name(ALLOC_ERROR_HANDLER).as_str()), mangle_internal_symbol(tcx, OomStrategy::SYMBOL), mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), ]) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 7650acbd292d2..87d64817466d9 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -6,7 +6,7 @@ use std::str::FromStr; use std::time::Duration; use std::{cmp, env, iter}; -use rustc_ast::expand::allocator::{AllocatorKind, alloc_error_handler_name, global_fn_name}; +use rustc_ast::expand::allocator::{ALLOC_ERROR_HANDLER, AllocatorKind, global_fn_name}; use rustc_ast::{self as ast, *}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::owned_slice::OwnedSlice; @@ -1087,17 +1087,17 @@ impl CStore { } spans => !spans.is_empty(), }; - self.has_alloc_error_handler = match &*fn_spans( - krate, - Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)), - ) { - [span1, span2, ..] => { - tcx.dcx() - .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); - true - } - spans => !spans.is_empty(), - }; + self.has_alloc_error_handler = + match &*fn_spans(krate, Symbol::intern(&global_fn_name(ALLOC_ERROR_HANDLER))) { + [span1, span2, ..] => { + tcx.dcx().emit_err(errors::NoMultipleAllocErrorHandler { + span2: *span2, + span1: *span1, + }); + true + } + spans => !spans.is_empty(), + }; // Check to see if we actually need an allocator. This desire comes // about through the `#![needs_allocator]` attribute and is typically diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 65c8206e9d462..39450f69ce30a 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -361,7 +361,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { 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. + // default implementations below (`__rdl_alloc_error_handler`) otherwise. #[rustc_std_internal_symbol] fn __rust_alloc_error_handler(size: usize, align: usize) -> !; } @@ -425,7 +425,7 @@ pub mod __alloc_error_handler { // called via generated `__rust_alloc_error_handler` if there is no // `#[alloc_error_handler]`. #[rustc_std_internal_symbol] - pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! { + pub unsafe fn __rdl_alloc_error_handler(size: usize, _align: usize) -> ! { 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. diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 1d61630269ac3..daa25c5a50dd6 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -358,9 +358,10 @@ fn default_alloc_error_hook(layout: Layout) { // This is the default path taken on OOM, and the only path taken on stable with std. // Crucially, it does *not* call any user-defined code, and therefore users do not have to // worry about allocation failure causing reentrancy issues. That makes it different from - // the default `__rdl_oom` defined in alloc (i.e., the default alloc error handler that is - // called when there is no `#[alloc_error_handler]`), which triggers a regular panic and - // thus can invoke a user-defined panic hook, executing arbitrary user-defined code. + // the default `__rdl_alloc_error_handler` defined in alloc (i.e., the default alloc error + // handler that is called when there is no `#[alloc_error_handler]`), which triggers a + // regular panic and thus can invoke a user-defined panic hook, executing arbitrary + // user-defined code. rtprintpanic!("memory allocation of {} bytes failed\n", layout.size()); } } diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index eca8cccf5efc4..467ac2805fe5e 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -3,7 +3,7 @@ use std::io::Write; use std::path::Path; use rustc_abi::{Align, AlignFromBytesError, CanonAbi, Size}; -use rustc_ast::expand::allocator::alloc_error_handler_name; +use rustc_ast::expand::allocator::AllocatorKind; use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::CrateNum; @@ -51,6 +51,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Some shims forward to other MIR bodies. match link_name.as_str() { + // FIXME should use global_fn_name, but mangle_internal_symbol requires a static str. 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 { @@ -59,12 +60,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" ); }; - 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)); + if handler_kind == AllocatorKind::Default { + let name = + Symbol::intern(this.mangle_internal_symbol("__rdl_alloc_error_handler")); + let handler = this + .lookup_exported_symbol(name)? + .expect("missing alloc error handler symbol"); + return interp_ok(Some(handler)); + } } _ => {} } diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr index bbf5d14a98a1e..7f7fc63ac0ddd 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr @@ -7,7 +7,7 @@ LL | crate::process::abort() | = note: BACKTRACE: = note: inside `std::alloc::rust_oom` at RUSTLIB/std/src/alloc.rs:LL:CC - = note: inside `std::alloc::_::__rg_oom` at RUSTLIB/std/src/alloc.rs:LL:CC + = note: inside `std::alloc::_::__rust_alloc_error_handler` at RUSTLIB/std/src/alloc.rs:LL:CC = note: inside `std::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `std::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr index a2a4be30eca4a..f8a96758aa2d3 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr @@ -7,7 +7,7 @@ LL | core::intrinsics::abort(); | = note: BACKTRACE: = note: inside `alloc_error_handler` at tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC -note: inside `_::__rg_oom` +note: inside `_::__rust_alloc_error_handler` --> tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC | LL | #[alloc_error_handler] diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr index 45ba366acae32..488b1d879e874 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr @@ -9,7 +9,7 @@ LL | core::intrinsics::abort(); | = note: BACKTRACE: = note: inside `panic_handler` at tests/fail/alloc/alloc_error_handler_no_std.rs:LL:CC - = note: inside `alloc::alloc::__alloc_error_handler::__rdl_oom` at RUSTLIB/alloc/src/alloc.rs:LL:CC + = note: inside `alloc::alloc::__alloc_error_handler::__rdl_alloc_error_handler` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `alloc::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `alloc::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC note: inside `miri_start` diff --git a/tests/run-make/bin-emit-no-symbols/rmake.rs b/tests/run-make/bin-emit-no-symbols/rmake.rs index 2faeb20025bb7..0822bd6dfd6a8 100644 --- a/tests/run-make/bin-emit-no-symbols/rmake.rs +++ b/tests/run-make/bin-emit-no-symbols/rmake.rs @@ -14,5 +14,5 @@ fn main() { let out = llvm_readobj().input("app.o").arg("--symbols").run(); out.assert_stdout_contains("rust_begin_unwind"); out.assert_stdout_contains("rust_eh_personality"); - out.assert_stdout_contains("__rg_oom"); + out.assert_stdout_contains("__rust_alloc_error_handler"); } diff --git a/tests/ui/sanitizer/dataflow-abilist.txt b/tests/ui/sanitizer/dataflow-abilist.txt index 3d32397a175d4..b6fdfe3cbf6e7 100644 --- a/tests/ui/sanitizer/dataflow-abilist.txt +++ b/tests/ui/sanitizer/dataflow-abilist.txt @@ -490,16 +490,6 @@ fun:__dfso_*=uninstrumented fun:__dfso_*=discard # Rust functions. -fun:__rdl_alloc=uninstrumented -fun:__rdl_alloc_zeroed=uninstrumented -fun:__rdl_dealloc=uninstrumented -fun:__rdl_realloc=uninstrumented -fun:__rg_oom=uninstrumented -fun:__rust_alloc=uninstrumented -fun:__rust_alloc_error_handler=uninstrumented -fun:__rust_alloc_zeroed=uninstrumented -fun:__rust_dealloc=uninstrumented -fun:__rust_realloc=uninstrumented fun:_ZN4core*=uninstrumented fun:_ZN3std*=uninstrumented fun:rust_eh_personality=uninstrumented From 7e467cd132d0546c26be02d160ca097e00e67522 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 9 Oct 2025 14:08:55 +0000 Subject: [PATCH 3/6] Move computation of allocator shim contents to cg_ssa In the future this should make it easier to use weak symbols for the allocator shim on platforms that properly support weak symbols. And it would allow reusing the allocator shim code for handling default implementations of the upcoming externally implementable items feature on platforms that don't properly support weak symbols. --- compiler/rustc_ast/src/expand/allocator.rs | 3 + .../src/global_allocator.rs | 4 +- .../rustc_codegen_cranelift/src/allocator.rs | 79 +++++-------- compiler/rustc_codegen_gcc/src/allocator.rs | 64 +++++------ compiler/rustc_codegen_gcc/src/lib.rs | 7 +- compiler/rustc_codegen_llvm/src/allocator.rs | 104 ++++++++---------- compiler/rustc_codegen_llvm/src/lib.rs | 7 +- compiler/rustc_codegen_ssa/src/base.rs | 34 ++++-- .../rustc_codegen_ssa/src/traits/backend.rs | 5 +- 9 files changed, 139 insertions(+), 168 deletions(-) diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index a3f9ddb154f71..6392cb77413dd 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -18,14 +18,17 @@ pub fn default_fn_name(base: Symbol) -> String { pub const ALLOC_ERROR_HANDLER: Symbol = sym::alloc_error_handler; pub const NO_ALLOC_SHIM_IS_UNSTABLE: &str = "__rust_no_alloc_shim_is_unstable_v2"; +#[derive(Copy, Clone)] pub enum AllocatorTy { Layout, + Never, Ptr, ResultPtr, Unit, Usize, } +#[derive(Copy, Clone)] pub struct AllocatorMethod { pub name: Symbol, pub inputs: &'static [AllocatorMethodInput], diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 96bece2a368cd..c968353504e15 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -151,7 +151,7 @@ impl AllocFnFactory<'_, '_> { self.cx.expr_ident(self.span, ident) } - AllocatorTy::ResultPtr | AllocatorTy::Unit => { + AllocatorTy::Never | AllocatorTy::ResultPtr | AllocatorTy::Unit => { panic!("can't convert AllocatorTy to an argument") } } @@ -163,7 +163,7 @@ impl AllocFnFactory<'_, '_> { AllocatorTy::Unit => self.cx.ty(self.span, TyKind::Tup(ThinVec::new())), - AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { + AllocatorTy::Layout | AllocatorTy::Never | AllocatorTy::Usize | AllocatorTy::Ptr => { panic!("can't convert `AllocatorTy` to an output") } } diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index 9533f870434ab..67b89114356b5 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -3,10 +3,9 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use rustc_ast::expand::allocator::{ - ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, - default_fn_name, global_fn_name, + AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name, }; -use rustc_codegen_ssa::base::allocator_kind_for_codegen; +use rustc_codegen_ssa::base::{allocator_kind_for_codegen, allocator_shim_contents}; use rustc_session::config::OomStrategy; use rustc_symbol_mangling::mangle_internal_symbol; @@ -15,74 +14,54 @@ use crate::prelude::*; /// Returns whether an allocator shim was created 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(), - tcx.sess.opts.unstable_opts.oom, - ); + let methods = allocator_shim_contents(tcx, kind); + codegen_inner(tcx, module, &methods, tcx.sess.opts.unstable_opts.oom); true } fn codegen_inner( tcx: TyCtxt<'_>, module: &mut dyn Module, - kind: AllocatorKind, - alloc_error_handler_kind: AllocatorKind, + methods: &[AllocatorMethod], oom_strategy: OomStrategy, ) { let usize_ty = module.target_config().pointer_type(); - if kind == AllocatorKind::Default { - for method in ALLOCATOR_METHODS { - let mut arg_tys = Vec::with_capacity(method.inputs.len()); - for input in method.inputs.iter() { - match input.ty { - AllocatorTy::Layout => { - arg_tys.push(usize_ty); // size - arg_tys.push(usize_ty); // align - } - AllocatorTy::Ptr => arg_tys.push(usize_ty), - AllocatorTy::Usize => arg_tys.push(usize_ty), - - AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), + for method in methods { + let mut arg_tys = Vec::with_capacity(method.inputs.len()); + for input in method.inputs.iter() { + match input.ty { + AllocatorTy::Layout => { + arg_tys.push(usize_ty); // size + arg_tys.push(usize_ty); // align } - } - let output = match method.output { - AllocatorTy::ResultPtr => Some(usize_ty), - AllocatorTy::Unit => None, + AllocatorTy::Ptr => arg_tys.push(usize_ty), + AllocatorTy::Usize => arg_tys.push(usize_ty), - AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { - panic!("invalid allocator output") + AllocatorTy::Never | AllocatorTy::ResultPtr | AllocatorTy::Unit => { + panic!("invalid allocator arg") } - }; - - let sig = Signature { - call_conv: module.target_config().default_call_conv, - params: arg_tys.iter().cloned().map(AbiParam::new).collect(), - returns: output.into_iter().map(AbiParam::new).collect(), - }; - crate::common::create_wrapper_function( - module, - sig, - &mangle_internal_symbol(tcx, &global_fn_name(method.name)), - &mangle_internal_symbol(tcx, &default_fn_name(method.name)), - ); + } } - } + let output = match method.output { + AllocatorTy::ResultPtr => Some(usize_ty), + AllocatorTy::Never | AllocatorTy::Unit => None, + + AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { + panic!("invalid allocator output") + } + }; - if alloc_error_handler_kind == AllocatorKind::Default { let sig = Signature { call_conv: module.target_config().default_call_conv, - params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)], - returns: vec![], + params: arg_tys.iter().cloned().map(AbiParam::new).collect(), + returns: output.into_iter().map(AbiParam::new).collect(), }; crate::common::create_wrapper_function( module, sig, - &mangle_internal_symbol(tcx, &global_fn_name(ALLOC_ERROR_HANDLER)), - &mangle_internal_symbol(tcx, &default_fn_name(ALLOC_ERROR_HANDLER)), + &mangle_internal_symbol(tcx, &global_fn_name(method.name)), + &mangle_internal_symbol(tcx, &default_fn_name(method.name)), ); } diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index 3f99612fcdb02..647569694b04d 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -2,8 +2,7 @@ use gccjit::FnAttribute; use gccjit::{Context, FunctionType, RValue, ToRValue, Type}; use rustc_ast::expand::allocator::{ - ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, - default_fn_name, global_fn_name, + AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name, }; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; @@ -18,8 +17,7 @@ pub(crate) unsafe fn codegen( tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, - kind: AllocatorKind, - alloc_error_handler_kind: AllocatorKind, + methods: &[AllocatorMethod], ) { let context = &mods.context; let usize = match tcx.sess.target.pointer_width { @@ -31,46 +29,34 @@ pub(crate) unsafe fn codegen( let i8 = context.new_type::(); let i8p = i8.make_pointer(); - if kind == AllocatorKind::Default { - for method in ALLOCATOR_METHODS { - let mut types = Vec::with_capacity(method.inputs.len()); - for input in method.inputs.iter() { - match input.ty { - AllocatorTy::Layout => { - types.push(usize); - types.push(usize); - } - AllocatorTy::Ptr => types.push(i8p), - AllocatorTy::Usize => types.push(usize), - - AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), + for method in methods { + let mut types = Vec::with_capacity(method.inputs.len()); + for input in method.inputs.iter() { + match input.ty { + AllocatorTy::Layout => { + types.push(usize); + types.push(usize); } - } - let output = match method.output { - AllocatorTy::ResultPtr => Some(i8p), - AllocatorTy::Unit => None, + AllocatorTy::Ptr => types.push(i8p), + AllocatorTy::Usize => types.push(usize), - AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { - panic!("invalid allocator output") + AllocatorTy::Never | AllocatorTy::ResultPtr | AllocatorTy::Unit => { + panic!("invalid allocator arg") } - }; - 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, Some(&to_name), &types, output); + } } - } + let output = match method.output { + AllocatorTy::ResultPtr => Some(i8p), + AllocatorTy::Never | AllocatorTy::Unit => None, - if alloc_error_handler_kind == AllocatorKind::Default { - // FIXME(bjorn3): Add noreturn attribute - create_wrapper_function( - tcx, - context, - &mangle_internal_symbol(tcx, &global_fn_name(ALLOC_ERROR_HANDLER)), - Some(&mangle_internal_symbol(tcx, &default_fn_name(ALLOC_ERROR_HANDLER))), - &[usize, usize], - None, - ); + AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { + panic!("invalid allocator output") + } + }; + 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, Some(&to_name), &types, output); } create_const_value_function( diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index ec7eab8489ab8..c85ed0ebb3390 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -92,7 +92,7 @@ use back::lto::{ThinBuffer, ThinData}; use gccjit::{CType, Context, OptimizationLevel}; #[cfg(feature = "master")] use gccjit::{TargetInfo, Version}; -use rustc_ast::expand::allocator::AllocatorKind; +use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule}; use rustc_codegen_ssa::back::write::{ CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn, @@ -284,8 +284,7 @@ impl ExtraBackendMethods for GccCodegenBackend { &self, tcx: TyCtxt<'_>, module_name: &str, - kind: AllocatorKind, - alloc_error_handler_kind: AllocatorKind, + methods: &[AllocatorMethod], ) -> Self::Module { let mut mods = GccContext { context: Arc::new(SyncContext::new(new_context(tcx))), @@ -295,7 +294,7 @@ impl ExtraBackendMethods for GccCodegenBackend { }; unsafe { - allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); + allocator::codegen(tcx, &mut mods, module_name, methods); } mods } diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index b645db3f4a8b8..a7e83f65151ae 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -1,7 +1,6 @@ use libc::c_uint; use rustc_ast::expand::allocator::{ - ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, - default_fn_name, global_fn_name, + AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name, }; use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _; use rustc_middle::bug; @@ -21,8 +20,7 @@ pub(crate) unsafe fn codegen( tcx: TyCtxt<'_>, cx: SimpleCx<'_>, module_name: &str, - kind: AllocatorKind, - alloc_error_handler_kind: AllocatorKind, + methods: &[AllocatorMethod], ) { let usize = match tcx.sess.target.pointer_width { 16 => cx.type_i16(), @@ -33,67 +31,59 @@ pub(crate) unsafe fn codegen( let i8 = cx.type_i8(); let i8p = cx.type_ptr(); - if kind == AllocatorKind::Default { - for method in ALLOCATOR_METHODS { - let mut args = Vec::with_capacity(method.inputs.len()); - for input in method.inputs.iter() { - match input.ty { - AllocatorTy::Layout => { - args.push(usize); // size - args.push(usize); // align - } - AllocatorTy::Ptr => args.push(i8p), - AllocatorTy::Usize => args.push(usize), - - AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), + for method in methods { + let mut args = Vec::with_capacity(method.inputs.len()); + for input in method.inputs.iter() { + match input.ty { + AllocatorTy::Layout => { + args.push(usize); // size + args.push(usize); // align } - } - let output = match method.output { - AllocatorTy::ResultPtr => Some(i8p), - AllocatorTy::Unit => None, + AllocatorTy::Ptr => args.push(i8p), + AllocatorTy::Usize => args.push(usize), - AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { - panic!("invalid allocator output") + AllocatorTy::Never | AllocatorTy::ResultPtr | AllocatorTy::Unit => { + panic!("invalid allocator arg") } - }; - - let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name)); - let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name)); - - let alloc_attr_flag = match method.name { - sym::alloc => CodegenFnAttrFlags::ALLOCATOR, - sym::dealloc => CodegenFnAttrFlags::DEALLOCATOR, - sym::realloc => CodegenFnAttrFlags::REALLOCATOR, - sym::alloc_zeroed => CodegenFnAttrFlags::ALLOCATOR_ZEROED, - _ => unreachable!("Unknown allocator method!"), - }; - - let mut attrs = CodegenFnAttrs::new(); - attrs.flags |= alloc_attr_flag; - create_wrapper_function( - tcx, - &cx, - &from_name, - Some(&to_name), - &args, - output, - false, - &attrs, - ); + } } - } - if alloc_error_handler_kind == AllocatorKind::Default { - // rust alloc error handler + let mut no_return = false; + let output = match method.output { + AllocatorTy::ResultPtr => Some(i8p), + AllocatorTy::Unit => None, + AllocatorTy::Never => { + no_return = true; + None + } + + AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { + panic!("invalid allocator output") + } + }; + + let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name)); + let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name)); + + let alloc_attr_flag = match method.name { + sym::alloc => CodegenFnAttrFlags::ALLOCATOR, + sym::dealloc => CodegenFnAttrFlags::DEALLOCATOR, + sym::realloc => CodegenFnAttrFlags::REALLOCATOR, + sym::alloc_zeroed => CodegenFnAttrFlags::ALLOCATOR_ZEROED, + _ => CodegenFnAttrFlags::empty(), + }; + + let mut attrs = CodegenFnAttrs::new(); + attrs.flags |= alloc_attr_flag; create_wrapper_function( tcx, &cx, - &mangle_internal_symbol(tcx, &global_fn_name(ALLOC_ERROR_HANDLER)), - Some(&mangle_internal_symbol(tcx, &default_fn_name(ALLOC_ERROR_HANDLER))), - &[usize, usize], // size, align - None, - true, - &CodegenFnAttrs::new(), + &from_name, + Some(&to_name), + &args, + output, + no_return, + &attrs, ); } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 807049f08d367..34fdb4a47c0ff 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -30,7 +30,7 @@ use back::write::{create_informational_target_machine, create_target_machine}; use context::SimpleCx; use errors::ParseTargetMachineConfig; use llvm_util::target_config; -use rustc_ast::expand::allocator::AllocatorKind; +use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule}; use rustc_codegen_ssa::back::write::{ CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn, @@ -107,14 +107,13 @@ impl ExtraBackendMethods for LlvmCodegenBackend { &self, tcx: TyCtxt<'tcx>, module_name: &str, - kind: AllocatorKind, - alloc_error_handler_kind: AllocatorKind, + methods: &[AllocatorMethod], ) -> ModuleLlvm { let module_llvm = ModuleLlvm::new_metadata(tcx, module_name); let cx = SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size()); unsafe { - allocator::codegen(tcx, cx, module_name, kind, alloc_error_handler_kind); + allocator::codegen(tcx, cx, module_name, methods); } module_llvm } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index ac3bcb1ea269f..cd9fb098e531d 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -6,7 +6,9 @@ use std::time::{Duration, Instant}; use itertools::Itertools; use rustc_abi::FIRST_VARIANT; use rustc_ast as ast; -use rustc_ast::expand::allocator::AllocatorKind; +use rustc_ast::expand::allocator::{ + ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorMethod, AllocatorTy, +}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; @@ -655,6 +657,26 @@ pub(crate) fn needs_allocator_shim_for_linking( !any_dynamic_crate } +pub fn allocator_shim_contents(tcx: TyCtxt<'_>, kind: AllocatorKind) -> Vec { + let mut methods = Vec::new(); + + if kind == AllocatorKind::Default { + methods.extend(ALLOCATOR_METHODS.into_iter().copied()); + } + + // If allocator_kind is Some then alloc_error_handler_kind must + // also be Some. + if tcx.alloc_error_handler_kind(()).unwrap() == AllocatorKind::Default { + methods.push(AllocatorMethod { + name: ALLOC_ERROR_HANDLER, + inputs: &[], + output: AllocatorTy::Never, + }); + } + + methods +} + pub fn codegen_crate( backend: B, tcx: TyCtxt<'_>, @@ -699,14 +721,8 @@ pub fn codegen_crate( cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string(); tcx.sess.time("write_allocator_module", || { - let module = backend.codegen_allocator( - tcx, - &llmod_id, - kind, - // If allocator_kind is Some then alloc_error_handler_kind must - // also be Some. - tcx.alloc_error_handler_kind(()).unwrap(), - ); + let module = + backend.codegen_allocator(tcx, &llmod_id, &allocator_shim_contents(tcx, kind)); Some(ModuleCodegen::new_allocator(llmod_id, module)) }) } else { diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 2400160075e2d..ec53d9f53eb83 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -1,7 +1,7 @@ use std::any::Any; use std::hash::Hash; -use rustc_ast::expand::allocator::AllocatorKind; +use rustc_ast::expand::allocator::AllocatorMethod; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_metadata::EncodedMetadata; @@ -116,8 +116,7 @@ pub trait ExtraBackendMethods: &self, tcx: TyCtxt<'tcx>, module_name: &str, - kind: AllocatorKind, - alloc_error_handler_kind: AllocatorKind, + methods: &[AllocatorMethod], ) -> Self::Module; /// This generates the codegen unit and returns it along with From 2e25b5876fe7a9a06bb5a2248a2e54e86937e002 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 10 Oct 2025 12:24:41 +0000 Subject: [PATCH 4/6] Add a couple of comments Co-Authored-By: Ralf Jung --- src/tools/miri/src/shims/foreign_items.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 467ac2805fe5e..39e32322f5b8d 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -51,6 +51,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Some shims forward to other MIR bodies. match link_name.as_str() { + // This allocator function has forwarding shims synthesized during normal codegen + // (see `allocator_shim_contents`); this is where we emulate that behavior. // FIXME should use global_fn_name, but mangle_internal_symbol requires a static str. name if name == this.mangle_internal_symbol("__rust_alloc_error_handler") => { // Forward to the right symbol that implements this function. @@ -68,6 +70,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { .expect("missing alloc error handler symbol"); return interp_ok(Some(handler)); } + // Fall through to the `lookup_exported_symbol` below which should find + // a `__rust_alloc_error_handler`. } _ => {} } From 88e98206836bcf80b33dce9d77298c86c8778e96 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:51:52 +0000 Subject: [PATCH 5/6] Fix review comments --- compiler/rustc_ast/src/expand/allocator.rs | 1 + compiler/rustc_codegen_ssa/src/base.rs | 4 ++-- compiler/rustc_metadata/src/creader.rs | 20 +++++++++----------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index 6392cb77413dd..336126a01f47e 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -18,6 +18,7 @@ pub fn default_fn_name(base: Symbol) -> String { pub const ALLOC_ERROR_HANDLER: Symbol = sym::alloc_error_handler; pub const NO_ALLOC_SHIM_IS_UNSTABLE: &str = "__rust_no_alloc_shim_is_unstable_v2"; +/// Argument or return type for methods in the allocator shim #[derive(Copy, Clone)] pub enum AllocatorTy { Layout, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index cd9fb098e531d..1a79038d1fcd1 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -664,8 +664,8 @@ pub fn allocator_shim_contents(tcx: TyCtxt<'_>, kind: AllocatorKind) -> Vec !spans.is_empty(), }; - self.has_alloc_error_handler = - match &*fn_spans(krate, Symbol::intern(&global_fn_name(ALLOC_ERROR_HANDLER))) { - [span1, span2, ..] => { - tcx.dcx().emit_err(errors::NoMultipleAllocErrorHandler { - span2: *span2, - span1: *span1, - }); - true - } - spans => !spans.is_empty(), - }; + let alloc_error_handler = Symbol::intern(&global_fn_name(ALLOC_ERROR_HANDLER)); + self.has_alloc_error_handler = match &*fn_spans(krate, alloc_error_handler) { + [span1, span2, ..] => { + tcx.dcx() + .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); + true + } + spans => !spans.is_empty(), + }; // Check to see if we actually need an allocator. This desire comes // about through the `#![needs_allocator]` attribute and is typically From cf0256008be86edbeac0af4300e67d1f7bcb7df9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:53:40 +0000 Subject: [PATCH 6/6] Add comment to AllocatorKind and AllocatorMethod --- compiler/rustc_ast/src/expand/allocator.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index 336126a01f47e..c200921e5f807 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -3,7 +3,9 @@ use rustc_span::{Symbol, sym}; #[derive(Clone, Debug, Copy, Eq, PartialEq, HashStable_Generic)] pub enum AllocatorKind { + /// Use `#[global_allocator]` as global allocator. Global, + /// Use the default implementation in libstd as global allocator. Default, } @@ -29,6 +31,7 @@ pub enum AllocatorTy { Usize, } +/// A method that will be codegened in the allocator shim. #[derive(Copy, Clone)] pub struct AllocatorMethod { pub name: Symbol,