Skip to content

Commit 2faf66d

Browse files
authored
Rollup merge of #143387 - dpaoliello:shouldpanicfn, r=bjorn3
Make __rust_alloc_error_handler_should_panic a function Fixes #143253 `__rust_alloc_error_handler_should_panic` is a static but was being exported as a function. For most targets this doesn't matter, but Arm64EC Windows uses different decorations for exported variables vs functions, hence it fails to link when `-Z oom=abort` is enabled. We've had issues in the past with statics like this (see #141061) but the tldr; is that Arm64EC needs symbols correctly exported as either a function or data, and data MUST and MUST ONLY be marked `dllimport` when the symbol is being imported from another binary, which is non-trivial to calculate for these compiler-generated statics. So, instead, the easiest thing to do is to make `__rust_alloc_error_handler_should_panic` a function instead. Since `__rust_alloc_error_handler_should_panic` isn't involved in any linking shenanigans, I've marked it as `AlwaysInline` with the hopes that the various backends will see that it is just returning a constant and perform the same optimizations as the previous implementation. r? `@bjorn3`
2 parents 18b374d + 2b22d0f commit 2faf66d

File tree

9 files changed

+111
-50
lines changed

9 files changed

+111
-50
lines changed

compiler/rustc_codegen_cranelift/src/allocator.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,34 @@ fn codegen_inner(
8484
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
8585
);
8686

87-
let data_id = module
88-
.declare_data(
89-
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
90-
Linkage::Export,
91-
false,
92-
false,
93-
)
94-
.unwrap();
95-
let mut data = DataDescription::new();
96-
data.set_align(1);
97-
let val = oom_strategy.should_panic();
98-
data.define(Box::new([val]));
99-
module.define_data(data_id, &data).unwrap();
87+
{
88+
let sig = Signature {
89+
call_conv: module.target_config().default_call_conv,
90+
params: vec![],
91+
returns: vec![AbiParam::new(types::I8)],
92+
};
93+
let func_id = module
94+
.declare_function(
95+
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
96+
Linkage::Export,
97+
&sig,
98+
)
99+
.unwrap();
100+
let mut ctx = Context::new();
101+
ctx.func.signature = sig;
102+
{
103+
let mut func_ctx = FunctionBuilderContext::new();
104+
let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
105+
106+
let block = bcx.create_block();
107+
bcx.switch_to_block(block);
108+
let value = bcx.ins().iconst(types::I8, oom_strategy.should_panic() as i64);
109+
bcx.ins().return_(&[value]);
110+
bcx.seal_all_blocks();
111+
bcx.finalize();
112+
}
113+
module.define_function(func_id, &mut ctx).unwrap();
114+
}
100115

101116
{
102117
let sig = Signature {

compiler/rustc_codegen_gcc/src/allocator.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use gccjit::{Context, FunctionType, GlobalKind, ToRValue, Type};
21
#[cfg(feature = "master")]
3-
use gccjit::{FnAttribute, VarAttribute};
2+
use gccjit::FnAttribute;
3+
use gccjit::{Context, FunctionType, RValue, ToRValue, Type};
44
use rustc_ast::expand::allocator::{
55
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
66
alloc_error_handler_name, default_fn_name, global_fn_name,
@@ -71,15 +71,13 @@ pub(crate) unsafe fn codegen(
7171
None,
7272
);
7373

74-
let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
75-
let global = context.new_global(None, GlobalKind::Exported, i8, name);
76-
#[cfg(feature = "master")]
77-
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
78-
tcx.sess.default_visibility(),
79-
)));
80-
let value = tcx.sess.opts.unstable_opts.oom.should_panic();
81-
let value = context.new_rvalue_from_int(i8, value as i32);
82-
global.global_set_initializer_rvalue(value);
74+
create_const_value_function(
75+
tcx,
76+
context,
77+
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
78+
i8,
79+
context.new_rvalue_from_int(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as i32),
80+
);
8381

8482
create_wrapper_function(
8583
tcx,
@@ -91,6 +89,30 @@ pub(crate) unsafe fn codegen(
9189
);
9290
}
9391

92+
fn create_const_value_function(
93+
tcx: TyCtxt<'_>,
94+
context: &Context<'_>,
95+
name: &str,
96+
output: Type<'_>,
97+
value: RValue<'_>,
98+
) {
99+
let func = context.new_function(None, FunctionType::Exported, output, &[], name, false);
100+
101+
#[cfg(feature = "master")]
102+
func.add_attribute(FnAttribute::Visibility(symbol_visibility_to_gcc(
103+
tcx.sess.default_visibility(),
104+
)));
105+
106+
func.add_attribute(FnAttribute::AlwaysInline);
107+
108+
if tcx.sess.must_emit_unwind_tables() {
109+
// TODO(antoyo): emit unwind tables.
110+
}
111+
112+
let block = func.new_block("entry");
113+
block.end_with_return(None, value);
114+
}
115+
94116
fn create_wrapper_function(
95117
tcx: TyCtxt<'_>,
96118
context: &Context<'_>,

compiler/rustc_codegen_llvm/src/allocator.rs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_symbol_mangling::mangle_internal_symbol;
1111

1212
use crate::builder::SBuilder;
1313
use crate::declare::declare_simple_fn;
14-
use crate::llvm::{self, False, True, Type};
14+
use crate::llvm::{self, False, True, Type, Value};
1515
use crate::{SimpleCx, attributes, debuginfo};
1616

1717
pub(crate) unsafe fn codegen(
@@ -73,13 +73,14 @@ pub(crate) unsafe fn codegen(
7373
);
7474

7575
unsafe {
76-
// __rust_alloc_error_handler_should_panic
77-
let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
78-
let ll_g = cx.declare_global(&name, i8);
79-
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
80-
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
81-
let llval = llvm::LLVMConstInt(i8, val as u64, False);
82-
llvm::set_initializer(ll_g, llval);
76+
// __rust_alloc_error_handler_should_panic_v2
77+
create_const_value_function(
78+
tcx,
79+
&cx,
80+
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
81+
&i8,
82+
&llvm::LLVMConstInt(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as u64, False),
83+
);
8384

8485
// __rust_no_alloc_shim_is_unstable_v2
8586
create_wrapper_function(
@@ -100,6 +101,34 @@ pub(crate) unsafe fn codegen(
100101
}
101102
}
102103

104+
fn create_const_value_function(
105+
tcx: TyCtxt<'_>,
106+
cx: &SimpleCx<'_>,
107+
name: &str,
108+
output: &Type,
109+
value: &Value,
110+
) {
111+
let ty = cx.type_func(&[], output);
112+
let llfn = declare_simple_fn(
113+
&cx,
114+
name,
115+
llvm::CallConv::CCallConv,
116+
llvm::UnnamedAddr::Global,
117+
llvm::Visibility::from_generic(tcx.sess.default_visibility()),
118+
ty,
119+
);
120+
121+
attributes::apply_to_llfn(
122+
llfn,
123+
llvm::AttributePlace::Function,
124+
&[llvm::AttributeKind::AlwaysInline.create_attr(cx.llcx)],
125+
);
126+
127+
let llbb = unsafe { llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, c"entry".as_ptr()) };
128+
let mut bx = SBuilder::build(&cx, llbb);
129+
bx.ret(value);
130+
}
131+
103132
fn create_wrapper_function(
104133
tcx: TyCtxt<'_>,
105134
cx: &SimpleCx<'_>,

compiler/rustc_session/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3340,7 +3340,7 @@ pub enum OomStrategy {
33403340
}
33413341

33423342
impl OomStrategy {
3343-
pub const SYMBOL: &'static str = "__rust_alloc_error_handler_should_panic";
3343+
pub const SYMBOL: &'static str = "__rust_alloc_error_handler_should_panic_v2";
33443344

33453345
pub fn should_panic(self) -> u8 {
33463346
match self {

library/alloc/src/alloc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,10 +429,10 @@ pub mod __alloc_error_handler {
429429
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
430430
// Its value depends on the -Zoom={panic,abort} compiler option.
431431
#[rustc_std_internal_symbol]
432-
static __rust_alloc_error_handler_should_panic: u8;
432+
fn __rust_alloc_error_handler_should_panic_v2() -> u8;
433433
}
434434

435-
if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
435+
if unsafe { __rust_alloc_error_handler_should_panic_v2() != 0 } {
436436
panic!("memory allocation of {size} bytes failed")
437437
} else {
438438
core::panicking::panic_nounwind_fmt(

library/std/src/alloc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,10 +349,10 @@ fn default_alloc_error_hook(layout: Layout) {
349349
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
350350
// Its value depends on the -Zoom={panic,abort} compiler option.
351351
#[rustc_std_internal_symbol]
352-
static __rust_alloc_error_handler_should_panic: u8;
352+
fn __rust_alloc_error_handler_should_panic_v2() -> u8;
353353
}
354354

355-
if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
355+
if unsafe { __rust_alloc_error_handler_should_panic_v2() != 0 } {
356356
panic!("memory allocation of {} bytes failed", layout.size());
357357
} else {
358358
// This is the default path taken on OOM, and the only path taken on stable with std.

src/tools/miri/src/shims/extern_static.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
//! Provides the `extern static` that this platform expects.
22
3-
use rustc_symbol_mangling::mangle_internal_symbol;
4-
53
use crate::*;
64

75
impl<'tcx> MiriMachine<'tcx> {
@@ -45,15 +43,6 @@ impl<'tcx> MiriMachine<'tcx> {
4543

4644
/// Sets up the "extern statics" for this machine.
4745
pub fn init_extern_statics(ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx> {
48-
// "__rust_alloc_error_handler_should_panic"
49-
let val = ecx.tcx.sess.opts.unstable_opts.oom.should_panic();
50-
let val = ImmTy::from_int(val, ecx.machine.layouts.u8);
51-
Self::alloc_extern_static(
52-
ecx,
53-
&mangle_internal_symbol(*ecx.tcx, "__rust_alloc_error_handler_should_panic"),
54-
val,
55-
)?;
56-
5746
if ecx.target_os_is_unix() {
5847
// "environ" is mandated by POSIX.
5948
let environ = ecx.machine.env_vars.unix().environ();

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
615615
// This is a no-op shim that only exists to prevent making the allocator shims instantly stable.
616616
let [] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
617617
}
618+
name if name == this.mangle_internal_symbol("__rust_alloc_error_handler_should_panic_v2") => {
619+
// Gets the value of the `oom` option.
620+
let [] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
621+
let val = this.tcx.sess.opts.unstable_opts.oom.should_panic();
622+
this.write_int(val, dest)?;
623+
}
618624

619625
// C memory handling functions
620626
"memcmp" => {

src/tools/miri/tests/pass/alloc-access-tracking.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![no_std]
22
#![no_main]
3-
//@compile-flags: -Zmiri-track-alloc-id=19 -Zmiri-track-alloc-accesses -Cpanic=abort
4-
//@normalize-stderr-test: "id 19" -> "id $$ALLOC"
3+
//@compile-flags: -Zmiri-track-alloc-id=18 -Zmiri-track-alloc-accesses -Cpanic=abort
4+
//@normalize-stderr-test: "id 18" -> "id $$ALLOC"
55
//@only-target: linux # alloc IDs differ between OSes (due to extern static allocations)
66

77
extern "Rust" {

0 commit comments

Comments
 (0)