Skip to content

Commit 116f4ae

Browse files
committed
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.
1 parent f47c480 commit 116f4ae

File tree

15 files changed

+83
-86
lines changed

15 files changed

+83
-86
lines changed

compiler/rustc_ast/src/expand/allocator.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,7 @@ pub fn default_fn_name(base: Symbol) -> String {
1515
format!("__rdl_{base}")
1616
}
1717

18-
pub fn alloc_error_handler_name(alloc_error_handler_kind: AllocatorKind) -> &'static str {
19-
match alloc_error_handler_kind {
20-
AllocatorKind::Global => "__rg_oom",
21-
AllocatorKind::Default => "__rdl_oom",
22-
}
23-
}
24-
18+
pub const ALLOC_ERROR_HANDLER: Symbol = sym::alloc_error_handler;
2519
pub const NO_ALLOC_SHIM_IS_UNSTABLE: &str = "__rust_no_alloc_shim_is_unstable_v2";
2620

2721
pub enum AllocatorTy {

compiler/rustc_builtin_macros/src/alloc_error_handler.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_ast::expand::allocator::{ALLOC_ERROR_HANDLER, global_fn_name};
12
use rustc_ast::{
23
self as ast, Fn, FnHeader, FnSig, Generics, ItemKind, Safety, Stmt, StmtKind, TyKind,
34
};
@@ -55,7 +56,7 @@ pub(crate) fn expand(
5556
}
5657

5758
// #[rustc_std_internal_symbol]
58-
// unsafe fn __rg_oom(size: usize, align: usize) -> ! {
59+
// unsafe fn __rust_alloc_error_handler(size: usize, align: usize) -> ! {
5960
// handler(core::alloc::Layout::from_size_align_unchecked(size, align))
6061
// }
6162
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
8485
let kind = ItemKind::Fn(Box::new(Fn {
8586
defaultness: ast::Defaultness::Final,
8687
sig,
87-
ident: Ident::from_str_and_span("__rg_oom", span),
88+
ident: Ident::from_str_and_span(&global_fn_name(ALLOC_ERROR_HANDLER), span),
8889
generics: Generics::default(),
8990
contract: None,
9091
body,

compiler/rustc_codegen_cranelift/src/allocator.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
55
use rustc_ast::expand::allocator::{
6-
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
7-
alloc_error_handler_name, default_fn_name, global_fn_name,
6+
ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
7+
default_fn_name, global_fn_name,
88
};
99
use rustc_codegen_ssa::base::allocator_kind_for_codegen;
1010
use rustc_session::config::OomStrategy;
@@ -72,17 +72,19 @@ fn codegen_inner(
7272
}
7373
}
7474

75-
let sig = Signature {
76-
call_conv: module.target_config().default_call_conv,
77-
params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
78-
returns: vec![],
79-
};
80-
crate::common::create_wrapper_function(
81-
module,
82-
sig,
83-
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
84-
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
85-
);
75+
if alloc_error_handler_kind == AllocatorKind::Default {
76+
let sig = Signature {
77+
call_conv: module.target_config().default_call_conv,
78+
params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
79+
returns: vec![],
80+
};
81+
crate::common::create_wrapper_function(
82+
module,
83+
sig,
84+
&mangle_internal_symbol(tcx, &global_fn_name(ALLOC_ERROR_HANDLER)),
85+
&mangle_internal_symbol(tcx, &default_fn_name(ALLOC_ERROR_HANDLER)),
86+
);
87+
}
8688

8789
{
8890
let sig = Signature {

compiler/rustc_codegen_gcc/src/allocator.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
use gccjit::FnAttribute;
33
use gccjit::{Context, FunctionType, RValue, ToRValue, Type};
44
use rustc_ast::expand::allocator::{
5-
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
6-
alloc_error_handler_name, default_fn_name, global_fn_name,
5+
ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
6+
default_fn_name, global_fn_name,
77
};
88
use rustc_middle::bug;
99
use rustc_middle::ty::TyCtxt;
@@ -61,15 +61,17 @@ pub(crate) unsafe fn codegen(
6161
}
6262
}
6363

64-
// FIXME(bjorn3): Add noreturn attribute
65-
create_wrapper_function(
66-
tcx,
67-
context,
68-
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
69-
Some(&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind))),
70-
&[usize, usize],
71-
None,
72-
);
64+
if alloc_error_handler_kind == AllocatorKind::Default {
65+
// FIXME(bjorn3): Add noreturn attribute
66+
create_wrapper_function(
67+
tcx,
68+
context,
69+
&mangle_internal_symbol(tcx, &global_fn_name(ALLOC_ERROR_HANDLER)),
70+
Some(&mangle_internal_symbol(tcx, &default_fn_name(ALLOC_ERROR_HANDLER))),
71+
&[usize, usize],
72+
None,
73+
);
74+
}
7375

7476
create_const_value_function(
7577
tcx,

compiler/rustc_codegen_llvm/src/allocator.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use libc::c_uint;
22
use rustc_ast::expand::allocator::{
3-
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
4-
alloc_error_handler_name, default_fn_name, global_fn_name,
3+
ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
4+
default_fn_name, global_fn_name,
55
};
66
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
77
use rustc_middle::bug;
@@ -83,17 +83,19 @@ pub(crate) unsafe fn codegen(
8383
}
8484
}
8585

86-
// rust alloc error handler
87-
create_wrapper_function(
88-
tcx,
89-
&cx,
90-
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
91-
Some(&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind))),
92-
&[usize, usize], // size, align
93-
None,
94-
true,
95-
&CodegenFnAttrs::new(),
96-
);
86+
if alloc_error_handler_kind == AllocatorKind::Default {
87+
// rust alloc error handler
88+
create_wrapper_function(
89+
tcx,
90+
&cx,
91+
&mangle_internal_symbol(tcx, &global_fn_name(ALLOC_ERROR_HANDLER)),
92+
Some(&mangle_internal_symbol(tcx, &default_fn_name(ALLOC_ERROR_HANDLER))),
93+
&[usize, usize], // size, align
94+
None,
95+
true,
96+
&CodegenFnAttrs::new(),
97+
);
98+
}
9799

98100
// __rust_alloc_error_handler_should_panic_v2
99101
create_const_value_function(

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::collections::hash_map::Entry::*;
22

33
use rustc_abi::{CanonAbi, X86Call};
4-
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name};
4+
use rustc_ast::expand::allocator::{
5+
ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name,
6+
};
57
use rustc_data_structures::unord::UnordMap;
68
use rustc_hir::def::DefKind;
79
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId};
@@ -498,7 +500,7 @@ pub(crate) fn allocator_shim_symbols(
498500
.iter()
499501
.map(move |method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str()))
500502
.chain([
501-
mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
503+
mangle_internal_symbol(tcx, global_fn_name(ALLOC_ERROR_HANDLER).as_str()),
502504
mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
503505
mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
504506
])

compiler/rustc_metadata/src/creader.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::str::FromStr;
66
use std::time::Duration;
77
use std::{cmp, env, iter};
88

9-
use rustc_ast::expand::allocator::{AllocatorKind, alloc_error_handler_name, global_fn_name};
9+
use rustc_ast::expand::allocator::{ALLOC_ERROR_HANDLER, AllocatorKind, global_fn_name};
1010
use rustc_ast::{self as ast, *};
1111
use rustc_data_structures::fx::FxHashSet;
1212
use rustc_data_structures::owned_slice::OwnedSlice;
@@ -1087,17 +1087,17 @@ impl CStore {
10871087
}
10881088
spans => !spans.is_empty(),
10891089
};
1090-
self.has_alloc_error_handler = match &*fn_spans(
1091-
krate,
1092-
Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)),
1093-
) {
1094-
[span1, span2, ..] => {
1095-
tcx.dcx()
1096-
.emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
1097-
true
1098-
}
1099-
spans => !spans.is_empty(),
1100-
};
1090+
self.has_alloc_error_handler =
1091+
match &*fn_spans(krate, Symbol::intern(&global_fn_name(ALLOC_ERROR_HANDLER))) {
1092+
[span1, span2, ..] => {
1093+
tcx.dcx().emit_err(errors::NoMultipleAllocErrorHandler {
1094+
span2: *span2,
1095+
span1: *span1,
1096+
});
1097+
true
1098+
}
1099+
spans => !spans.is_empty(),
1100+
};
11011101

11021102
// Check to see if we actually need an allocator. This desire comes
11031103
// about through the `#![needs_allocator]` attribute and is typically

library/alloc/src/alloc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
361361
unsafe extern "Rust" {
362362
// This is the magic symbol to call the global alloc error handler. rustc generates
363363
// it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the
364-
// default implementations below (`__rdl_oom`) otherwise.
364+
// default implementations below (`__rdl_alloc_error_handler`) otherwise.
365365
#[rustc_std_internal_symbol]
366366
fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
367367
}
@@ -425,7 +425,7 @@ pub mod __alloc_error_handler {
425425
// called via generated `__rust_alloc_error_handler` if there is no
426426
// `#[alloc_error_handler]`.
427427
#[rustc_std_internal_symbol]
428-
pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! {
428+
pub unsafe fn __rdl_alloc_error_handler(size: usize, _align: usize) -> ! {
429429
unsafe extern "Rust" {
430430
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
431431
// Its value depends on the -Zoom={panic,abort} compiler option.

library/std/src/alloc.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,9 +358,10 @@ fn default_alloc_error_hook(layout: Layout) {
358358
// This is the default path taken on OOM, and the only path taken on stable with std.
359359
// Crucially, it does *not* call any user-defined code, and therefore users do not have to
360360
// worry about allocation failure causing reentrancy issues. That makes it different from
361-
// the default `__rdl_oom` defined in alloc (i.e., the default alloc error handler that is
362-
// called when there is no `#[alloc_error_handler]`), which triggers a regular panic and
363-
// thus can invoke a user-defined panic hook, executing arbitrary user-defined code.
361+
// the default `__rdl_alloc_error_handler` defined in alloc (i.e., the default alloc error
362+
// handler that is called when there is no `#[alloc_error_handler]`), which triggers a
363+
// regular panic and thus can invoke a user-defined panic hook, executing arbitrary
364+
// user-defined code.
364365
rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
365366
}
366367
}

src/tools/miri/src/shims/foreign_items.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::io::Write;
33
use std::path::Path;
44

55
use rustc_abi::{Align, AlignFromBytesError, CanonAbi, Size};
6-
use rustc_ast::expand::allocator::alloc_error_handler_name;
6+
use rustc_ast::expand::allocator::AllocatorKind;
77
use rustc_hir::attrs::Linkage;
88
use rustc_hir::def::DefKind;
99
use rustc_hir::def_id::CrateNum;
@@ -51,6 +51,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
5151

5252
// Some shims forward to other MIR bodies.
5353
match link_name.as_str() {
54+
// FIXME should use global_fn_name, but mangle_internal_symbol requires a static str.
5455
name if name == this.mangle_internal_symbol("__rust_alloc_error_handler") => {
5556
// Forward to the right symbol that implements this function.
5657
let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else {
@@ -59,12 +60,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
5960
"`__rust_alloc_error_handler` cannot be called when no alloc error handler is set"
6061
);
6162
};
62-
let name = Symbol::intern(
63-
this.mangle_internal_symbol(alloc_error_handler_name(handler_kind)),
64-
);
65-
let handler =
66-
this.lookup_exported_symbol(name)?.expect("missing alloc error handler symbol");
67-
return interp_ok(Some(handler));
63+
if handler_kind == AllocatorKind::Default {
64+
let name =
65+
Symbol::intern(this.mangle_internal_symbol("__rdl_alloc_error_handler"));
66+
let handler = this
67+
.lookup_exported_symbol(name)?
68+
.expect("missing alloc error handler symbol");
69+
return interp_ok(Some(handler));
70+
}
6871
}
6972
_ => {}
7073
}

0 commit comments

Comments
 (0)