Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d5915d9

Browse files
committedJan 17, 2025
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 <strike>macOS and</strike> 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-zzz-job: x86_64-msvc try-job: x86_64-apple-1 try-job: x86_64-apple-2
2 parents 73c0ae6 + 7952352 commit d5915d9

File tree

24 files changed

+232
-513
lines changed

24 files changed

+232
-513
lines changed
 

‎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 {

‎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
}

‎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);
+4-129
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,17 @@
1-
use gccjit::{Context, FunctionType, GlobalKind, ToRValue, Type};
1+
use gccjit::GlobalKind;
22
#[cfg(feature = "master")]
3-
use gccjit::{FnAttribute, VarAttribute};
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;
3+
use gccjit::VarAttribute;
4+
use rustc_ast::expand::allocator::NO_ALLOC_SHIM_IS_UNSTABLE;
95
use rustc_middle::ty::TyCtxt;
106
use rustc_session::config::OomStrategy;
117

128
use crate::GccContext;
139
#[cfg(feature = "master")]
1410
use crate::base::symbol_visibility_to_gcc;
1511

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

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

‎compiler/rustc_codegen_gcc/src/lib.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ use back::lto::{ThinBuffer, ThinData};
9393
use gccjit::{CType, Context, OptimizationLevel};
9494
#[cfg(feature = "master")]
9595
use gccjit::{TargetInfo, Version};
96-
use rustc_ast::expand::allocator::AllocatorKind;
9796
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
9897
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
9998
use rustc_codegen_ssa::back::write::{
@@ -286,13 +285,7 @@ fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
286285
}
287286

288287
impl ExtraBackendMethods for GccCodegenBackend {
289-
fn codegen_allocator(
290-
&self,
291-
tcx: TyCtxt<'_>,
292-
module_name: &str,
293-
kind: AllocatorKind,
294-
alloc_error_handler_kind: AllocatorKind,
295-
) -> Self::Module {
288+
fn codegen_allocator(&self, tcx: TyCtxt<'_>, module_name: &str) -> Self::Module {
296289
let mut mods = GccContext {
297290
context: Arc::new(SyncContext::new(new_context(tcx))),
298291
relocation_model: tcx.sess.relocation_model(),
@@ -301,7 +294,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
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
}
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.