Skip to content

Commit 25f4036

Browse files
committed
Auto merge of rust-lang#134522 - bjorn3:weak_linkage_allocator, r=<try>
[WIP] Use weak linkage instead of compiler generated shims rust-lang#86844 (unstably) made it possible to avoid the allocator shim when using `#[global_allocator]`. This PR makes it possible to also avoid the allocator shim when using the default allocator in libstd by making use of weak linkage. Eventual stabilization of avoiding the allocator shim may be blocked on it working with the default allocator too. This is still keeping the `__rust_no_alloc_shim_is_unstable` symbol for now until rust-lang#123015 gets stabilized. TODO: Update comments everywhere, test on macOS and Windows and write a better PR description why we want this. Also prevent codegen of weak symbols when there is a non-weak definition of the same symbol in the same codegen unit. try-job: x86_64-msvc try-job: x86_64-apple-1 try-job: x86_64-apple-2
2 parents 8a1f803 + abd406c commit 25f4036

File tree

22 files changed

+190
-566
lines changed

22 files changed

+190
-566
lines changed

Diff for: compiler/rustc_ast/src/expand/allocator.rs

-11
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,6 @@ pub fn global_fn_name(base: Symbol) -> String {
1111
format!("__rust_{base}")
1212
}
1313

14-
pub fn default_fn_name(base: Symbol) -> String {
15-
format!("__rdl_{base}")
16-
}
17-
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-
2514
pub const NO_ALLOC_SHIM_IS_UNSTABLE: &str = "__rust_no_alloc_shim_is_unstable";
2615

2716
pub enum AllocatorTy {

Diff for: compiler/rustc_builtin_macros/src/alloc_error_handler.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub(crate) fn expand(
5656
}
5757

5858
// #[rustc_std_internal_symbol]
59-
// unsafe fn __rg_oom(size: usize, align: usize) -> ! {
59+
// unsafe fn __rust_alloc_error_handler(size: usize, align: usize) -> ! {
6060
// handler(core::alloc::Layout::from_size_align_unchecked(size, align))
6161
// }
6262
fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span) -> Stmt {
@@ -90,6 +90,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
9090

9191
let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];
9292

93-
let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind);
93+
let item =
94+
cx.item(span, Ident::from_str_and_span("__rust_alloc_error_handler", span), attrs, kind);
9495
cx.stmt_item(sig_span, item)
9596
}

Diff for: compiler/rustc_codegen_cranelift/src/allocator.rs

+9-71
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,23 @@
11
//! Allocator shim
22
// Adapted from rustc
33

4-
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,
7-
};
8-
use rustc_codegen_ssa::base::allocator_kind_for_codegen;
4+
use rustc_ast::expand::allocator::NO_ALLOC_SHIM_IS_UNSTABLE;
5+
use rustc_codegen_ssa::base::needs_allocator_shim;
96
use rustc_session::config::OomStrategy;
107

118
use crate::prelude::*;
129

1310
/// Returns whether an allocator shim was created
1411
pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
15-
let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
16-
codegen_inner(
17-
module,
18-
kind,
19-
tcx.alloc_error_handler_kind(()).unwrap(),
20-
tcx.sess.opts.unstable_opts.oom,
21-
);
22-
true
23-
}
24-
25-
fn codegen_inner(
26-
module: &mut dyn Module,
27-
kind: AllocatorKind,
28-
alloc_error_handler_kind: AllocatorKind,
29-
oom_strategy: OomStrategy,
30-
) {
31-
let usize_ty = module.target_config().pointer_type();
32-
33-
if kind == AllocatorKind::Default {
34-
for method in ALLOCATOR_METHODS {
35-
let mut arg_tys = Vec::with_capacity(method.inputs.len());
36-
for input in method.inputs.iter() {
37-
match input.ty {
38-
AllocatorTy::Layout => {
39-
arg_tys.push(usize_ty); // size
40-
arg_tys.push(usize_ty); // align
41-
}
42-
AllocatorTy::Ptr => arg_tys.push(usize_ty),
43-
AllocatorTy::Usize => arg_tys.push(usize_ty),
44-
45-
AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
46-
}
47-
}
48-
let output = match method.output {
49-
AllocatorTy::ResultPtr => Some(usize_ty),
50-
AllocatorTy::Unit => None,
51-
52-
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
53-
panic!("invalid allocator output")
54-
}
55-
};
56-
57-
let sig = Signature {
58-
call_conv: module.target_config().default_call_conv,
59-
params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
60-
returns: output.into_iter().map(AbiParam::new).collect(),
61-
};
62-
crate::common::create_wrapper_function(
63-
module,
64-
sig,
65-
&global_fn_name(method.name),
66-
&default_fn_name(method.name),
67-
);
68-
}
12+
if needs_allocator_shim(tcx) {
13+
codegen_inner(module, tcx.sess.opts.unstable_opts.oom);
14+
true
15+
} else {
16+
false
6917
}
18+
}
7019

71-
let sig = Signature {
72-
call_conv: module.target_config().default_call_conv,
73-
params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
74-
returns: vec![],
75-
};
76-
crate::common::create_wrapper_function(
77-
module,
78-
sig,
79-
"__rust_alloc_error_handler",
80-
&alloc_error_handler_name(alloc_error_handler_kind),
81-
);
82-
20+
fn codegen_inner(module: &mut dyn Module, oom_strategy: OomStrategy) {
8321
let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap();
8422
let mut data = DataDescription::new();
8523
data.set_align(1);

Diff for: compiler/rustc_codegen_gcc/src/allocator.rs

+3-136
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,13 @@
1-
#[cfg(feature = "master")]
2-
use gccjit::FnAttribute;
3-
use gccjit::{Context, FunctionType, GlobalKind, ToRValue, Type};
4-
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,
7-
};
8-
use rustc_middle::bug;
1+
use gccjit::GlobalKind;
2+
use rustc_ast::expand::allocator::NO_ALLOC_SHIM_IS_UNSTABLE;
93
use rustc_middle::ty::TyCtxt;
104
use rustc_session::config::OomStrategy;
115

126
use crate::GccContext;
137

14-
pub(crate) unsafe fn codegen(
15-
tcx: TyCtxt<'_>,
16-
mods: &mut GccContext,
17-
_module_name: &str,
18-
kind: AllocatorKind,
19-
alloc_error_handler_kind: AllocatorKind,
20-
) {
8+
pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str) {
219
let context = &mods.context;
22-
let usize = match tcx.sess.target.pointer_width {
23-
16 => context.new_type::<u16>(),
24-
32 => context.new_type::<u32>(),
25-
64 => context.new_type::<u64>(),
26-
tws => bug!("Unsupported target word size for int: {}", tws),
27-
};
2810
let i8 = context.new_type::<i8>();
29-
let i8p = i8.make_pointer();
30-
31-
if kind == AllocatorKind::Default {
32-
for method in ALLOCATOR_METHODS {
33-
let mut types = Vec::with_capacity(method.inputs.len());
34-
for input in method.inputs.iter() {
35-
match input.ty {
36-
AllocatorTy::Layout => {
37-
types.push(usize);
38-
types.push(usize);
39-
}
40-
AllocatorTy::Ptr => types.push(i8p),
41-
AllocatorTy::Usize => types.push(usize),
42-
43-
AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
44-
}
45-
}
46-
let output = match method.output {
47-
AllocatorTy::ResultPtr => Some(i8p),
48-
AllocatorTy::Unit => None,
49-
50-
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
51-
panic!("invalid allocator output")
52-
}
53-
};
54-
let from_name = global_fn_name(method.name);
55-
let to_name = default_fn_name(method.name);
56-
57-
create_wrapper_function(tcx, context, &from_name, &to_name, &types, output);
58-
}
59-
}
60-
61-
// FIXME(bjorn3): Add noreturn attribute
62-
create_wrapper_function(
63-
tcx,
64-
context,
65-
"__rust_alloc_error_handler",
66-
alloc_error_handler_name(alloc_error_handler_kind),
67-
&[usize, usize],
68-
None,
69-
);
7011

7112
let name = OomStrategy::SYMBOL.to_string();
7213
let global = context.new_global(None, GlobalKind::Exported, i8, name);
@@ -79,77 +20,3 @@ pub(crate) unsafe fn codegen(
7920
let value = context.new_rvalue_from_int(i8, 0);
8021
global.global_set_initializer_rvalue(value);
8122
}
82-
83-
fn create_wrapper_function(
84-
tcx: TyCtxt<'_>,
85-
context: &Context<'_>,
86-
from_name: &str,
87-
to_name: &str,
88-
types: &[Type<'_>],
89-
output: Option<Type<'_>>,
90-
) {
91-
let void = context.new_type::<()>();
92-
93-
let args: Vec<_> = types
94-
.iter()
95-
.enumerate()
96-
.map(|(index, typ)| context.new_parameter(None, *typ, format!("param{}", index)))
97-
.collect();
98-
let func = context.new_function(
99-
None,
100-
FunctionType::Exported,
101-
output.unwrap_or(void),
102-
&args,
103-
from_name,
104-
false,
105-
);
106-
107-
#[cfg(feature = "master")]
108-
match tcx.sess.default_visibility() {
109-
rustc_target::spec::SymbolVisibility::Hidden => {
110-
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden))
111-
}
112-
rustc_target::spec::SymbolVisibility::Protected => {
113-
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Protected))
114-
}
115-
rustc_target::spec::SymbolVisibility::Interposable => {}
116-
}
117-
118-
if tcx.sess.must_emit_unwind_tables() {
119-
// TODO(antoyo): emit unwind tables.
120-
}
121-
122-
let args: Vec<_> = types
123-
.iter()
124-
.enumerate()
125-
.map(|(index, typ)| context.new_parameter(None, *typ, format!("param{}", index)))
126-
.collect();
127-
let callee = context.new_function(
128-
None,
129-
FunctionType::Extern,
130-
output.unwrap_or(void),
131-
&args,
132-
to_name,
133-
false,
134-
);
135-
#[cfg(feature = "master")]
136-
callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
137-
138-
let block = func.new_block("entry");
139-
140-
let args = args
141-
.iter()
142-
.enumerate()
143-
.map(|(i, _)| func.get_param(i as i32).to_rvalue())
144-
.collect::<Vec<_>>();
145-
let ret = context.new_call(None, callee, &args);
146-
//llvm::LLVMSetTailCall(ret, True);
147-
if output.is_some() {
148-
block.end_with_return(None, ret);
149-
} else {
150-
block.end_with_void_return(None);
151-
}
152-
153-
// TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances
154-
// as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643
155-
}

Diff for: compiler/rustc_codegen_gcc/src/lib.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ use errors::LTONotSupported;
9292
use gccjit::{CType, Context, OptimizationLevel};
9393
#[cfg(feature = "master")]
9494
use gccjit::{TargetInfo, Version};
95-
use rustc_ast::expand::allocator::AllocatorKind;
9695
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
9796
use rustc_codegen_ssa::back::write::{
9897
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn,
@@ -287,21 +286,15 @@ fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
287286
}
288287

289288
impl ExtraBackendMethods for GccCodegenBackend {
290-
fn codegen_allocator(
291-
&self,
292-
tcx: TyCtxt<'_>,
293-
module_name: &str,
294-
kind: AllocatorKind,
295-
alloc_error_handler_kind: AllocatorKind,
296-
) -> Self::Module {
289+
fn codegen_allocator(&self, tcx: TyCtxt<'_>, module_name: &str) -> Self::Module {
297290
let mut mods = GccContext {
298291
context: Arc::new(SyncContext::new(new_context(tcx))),
299292
should_combine_object_files: false,
300293
temp_dir: None,
301294
};
302295

303296
unsafe {
304-
allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind);
297+
allocator::codegen(tcx, &mut mods, module_name);
305298
}
306299
mods
307300
}

0 commit comments

Comments
 (0)