Skip to content

Commit 125284d

Browse files
committed
[WIP] Use weak linkage instead of compiler generated shims
This is still keeping the allocator shim for the oom handler and the __rust_no_alloc_shim_is_unstable symbol for now. TODO: Update comments everywhere and test on macOS and Windows
1 parent 68ac5ab commit 125284d

File tree

15 files changed

+109
-249
lines changed

15 files changed

+109
-249
lines changed

compiler/rustc_ast/src/expand/allocator.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +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-
1814
pub fn alloc_error_handler_name(alloc_error_handler_kind: AllocatorKind) -> &'static str {
1915
match alloc_error_handler_kind {
2016
AllocatorKind::Global => "__rg_oom",

compiler/rustc_codegen_cranelift/src/allocator.rs

Lines changed: 13 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,75 +2,37 @@
22
// Adapted from rustc
33

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+
AllocatorKind, NO_ALLOC_SHIM_IS_UNSTABLE, alloc_error_handler_name,
76
};
8-
use rustc_codegen_ssa::base::allocator_kind_for_codegen;
7+
use rustc_codegen_ssa::base::needs_allocator_shim;
98
use rustc_session::config::OomStrategy;
109
use rustc_symbol_mangling::mangle_internal_symbol;
1110

1211
use crate::prelude::*;
1312

1413
/// Returns whether an allocator shim was created
1514
pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
16-
let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
17-
codegen_inner(
18-
tcx,
19-
module,
20-
kind,
21-
tcx.alloc_error_handler_kind(()).unwrap(),
22-
tcx.sess.opts.unstable_opts.oom,
23-
);
24-
true
15+
if needs_allocator_shim(tcx) {
16+
codegen_inner(
17+
tcx,
18+
module,
19+
tcx.alloc_error_handler_kind(()).unwrap(),
20+
tcx.sess.opts.unstable_opts.oom,
21+
);
22+
true
23+
} else {
24+
false
25+
}
2526
}
2627

2728
fn codegen_inner(
2829
tcx: TyCtxt<'_>,
2930
module: &mut dyn Module,
30-
kind: AllocatorKind,
3131
alloc_error_handler_kind: AllocatorKind,
3232
oom_strategy: OomStrategy,
3333
) {
3434
let usize_ty = module.target_config().pointer_type();
3535

36-
if kind == AllocatorKind::Default {
37-
for method in ALLOCATOR_METHODS {
38-
let mut arg_tys = Vec::with_capacity(method.inputs.len());
39-
for input in method.inputs.iter() {
40-
match input.ty {
41-
AllocatorTy::Layout => {
42-
arg_tys.push(usize_ty); // size
43-
arg_tys.push(usize_ty); // align
44-
}
45-
AllocatorTy::Ptr => arg_tys.push(usize_ty),
46-
AllocatorTy::Usize => arg_tys.push(usize_ty),
47-
48-
AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
49-
}
50-
}
51-
let output = match method.output {
52-
AllocatorTy::ResultPtr => Some(usize_ty),
53-
AllocatorTy::Unit => None,
54-
55-
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
56-
panic!("invalid allocator output")
57-
}
58-
};
59-
60-
let sig = Signature {
61-
call_conv: module.target_config().default_call_conv,
62-
params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
63-
returns: output.into_iter().map(AbiParam::new).collect(),
64-
};
65-
crate::common::create_wrapper_function(
66-
module,
67-
sig,
68-
&mangle_internal_symbol(tcx, &global_fn_name(method.name)),
69-
&mangle_internal_symbol(tcx, &default_fn_name(method.name)),
70-
);
71-
}
72-
}
73-
7436
let sig = Signature {
7537
call_conv: module.target_config().default_call_conv,
7638
params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],

compiler/rustc_codegen_gcc/src/allocator.rs

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ use gccjit::{Context, FunctionType, GlobalKind, ToRValue, Type};
22
#[cfg(feature = "master")]
33
use gccjit::{FnAttribute, VarAttribute};
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+
AllocatorKind, NO_ALLOC_SHIM_IS_UNSTABLE, alloc_error_handler_name,
76
};
87
use rustc_middle::bug;
98
use rustc_middle::ty::TyCtxt;
@@ -18,7 +17,6 @@ pub(crate) unsafe fn codegen(
1817
tcx: TyCtxt<'_>,
1918
mods: &mut GccContext,
2019
_module_name: &str,
21-
kind: AllocatorKind,
2220
alloc_error_handler_kind: AllocatorKind,
2321
) {
2422
let context = &mods.context;
@@ -29,37 +27,6 @@ pub(crate) unsafe fn codegen(
2927
tws => bug!("Unsupported target word size for int: {}", tws),
3028
};
3129
let i8 = context.new_type::<i8>();
32-
let i8p = i8.make_pointer();
33-
34-
if kind == AllocatorKind::Default {
35-
for method in ALLOCATOR_METHODS {
36-
let mut types = Vec::with_capacity(method.inputs.len());
37-
for input in method.inputs.iter() {
38-
match input.ty {
39-
AllocatorTy::Layout => {
40-
types.push(usize);
41-
types.push(usize);
42-
}
43-
AllocatorTy::Ptr => types.push(i8p),
44-
AllocatorTy::Usize => types.push(usize),
45-
46-
AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
47-
}
48-
}
49-
let output = match method.output {
50-
AllocatorTy::ResultPtr => Some(i8p),
51-
AllocatorTy::Unit => None,
52-
53-
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
54-
panic!("invalid allocator output")
55-
}
56-
};
57-
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
58-
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
59-
60-
create_wrapper_function(tcx, context, &from_name, &to_name, &types, output);
61-
}
62-
}
6330

6431
// FIXME(bjorn3): Add noreturn attribute
6532
create_wrapper_function(

compiler/rustc_codegen_gcc/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,6 @@ impl ExtraBackendMethods for GccCodegenBackend {
278278
&self,
279279
tcx: TyCtxt<'_>,
280280
module_name: &str,
281-
kind: AllocatorKind,
282281
alloc_error_handler_kind: AllocatorKind,
283282
) -> Self::Module {
284283
let mut mods = GccContext {
@@ -289,7 +288,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
289288
};
290289

291290
unsafe {
292-
allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind);
291+
allocator::codegen(tcx, &mut mods, module_name, alloc_error_handler_kind);
293292
}
294293
mods
295294
}

compiler/rustc_codegen_llvm/src/allocator.rs

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
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+
AllocatorKind, NO_ALLOC_SHIM_IS_UNSTABLE, alloc_error_handler_name,
54
};
65
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
76
use rustc_middle::bug;
@@ -18,7 +17,6 @@ pub(crate) unsafe fn codegen(
1817
tcx: TyCtxt<'_>,
1918
cx: SimpleCx<'_>,
2019
module_name: &str,
21-
kind: AllocatorKind,
2220
alloc_error_handler_kind: AllocatorKind,
2321
) {
2422
let usize = match tcx.sess.target.pointer_width {
@@ -28,38 +26,6 @@ pub(crate) unsafe fn codegen(
2826
tws => bug!("Unsupported target word size for int: {}", tws),
2927
};
3028
let i8 = cx.type_i8();
31-
let i8p = cx.type_ptr();
32-
33-
if kind == AllocatorKind::Default {
34-
for method in ALLOCATOR_METHODS {
35-
let mut args = Vec::with_capacity(method.inputs.len());
36-
for input in method.inputs.iter() {
37-
match input.ty {
38-
AllocatorTy::Layout => {
39-
args.push(usize); // size
40-
args.push(usize); // align
41-
}
42-
AllocatorTy::Ptr => args.push(i8p),
43-
AllocatorTy::Usize => args.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-
57-
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
58-
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
59-
60-
create_wrapper_function(tcx, &cx, &from_name, &to_name, &args, output, false);
61-
}
62-
}
6329

6430
// rust alloc error handler
6531
create_wrapper_function(

compiler/rustc_codegen_llvm/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,13 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
108108
&self,
109109
tcx: TyCtxt<'tcx>,
110110
module_name: &str,
111-
kind: AllocatorKind,
112111
alloc_error_handler_kind: AllocatorKind,
113112
) -> ModuleLlvm {
114113
let module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
115114
let cx =
116115
SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size);
117116
unsafe {
118-
allocator::codegen(tcx, cx, module_name, kind, alloc_error_handler_kind);
117+
allocator::codegen(tcx, cx, module_name, alloc_error_handler_kind);
119118
}
120119
module_llvm
121120
}

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_symbol_mangling::mangle_internal_symbol;
1818
use rustc_target::spec::{SanitizerSet, TlsModel};
1919
use tracing::debug;
2020

21-
use crate::base::allocator_kind_for_codegen;
21+
use crate::base::needs_allocator_shim;
2222

2323
fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
2424
crates_export_threshold(tcx.crate_types())
@@ -212,7 +212,7 @@ fn exported_symbols_provider_local<'tcx>(
212212
}
213213

214214
// Mark allocator shim symbols as exported only if they were generated.
215-
if allocator_kind_for_codegen(tcx).is_some() {
215+
if needs_allocator_shim(tcx) {
216216
for symbol_name in ALLOCATOR_METHODS
217217
.iter()
218218
.map(|method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str()))

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::time::{Duration, Instant};
66
use itertools::Itertools;
77
use rustc_abi::FIRST_VARIANT;
88
use rustc_ast as ast;
9-
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_name};
9+
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, global_fn_name};
1010
use rustc_attr_data_structures::OptimizeAttr;
1111
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
1212
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
@@ -648,7 +648,7 @@ pub fn collect_debugger_visualizers_transitive(
648648
/// Decide allocator kind to codegen. If `Some(_)` this will be the same as
649649
/// `tcx.allocator_kind`, but it may be `None` in more cases (e.g. if using
650650
/// allocator definitions from a dylib dependency).
651-
pub fn allocator_kind_for_codegen(tcx: TyCtxt<'_>) -> Option<AllocatorKind> {
651+
pub fn needs_allocator_shim(tcx: TyCtxt<'_>) -> bool {
652652
// If the crate doesn't have an `allocator_kind` set then there's definitely
653653
// no shim to generate. Otherwise we also check our dependency graph for all
654654
// our output crate types. If anything there looks like its a `Dynamic`
@@ -659,7 +659,7 @@ pub fn allocator_kind_for_codegen(tcx: TyCtxt<'_>) -> Option<AllocatorKind> {
659659
use rustc_middle::middle::dependency_format::Linkage;
660660
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
661661
});
662-
if any_dynamic_crate { None } else { tcx.allocator_kind(()) }
662+
if any_dynamic_crate { false } else { tcx.allocator_kind(()).is_some() }
663663
}
664664

665665
pub fn codegen_crate<B: ExtraBackendMethods>(
@@ -705,14 +705,13 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
705705
let ongoing_codegen = start_async_codegen(backend.clone(), tcx, target_cpu);
706706

707707
// Codegen an allocator shim, if necessary.
708-
if let Some(kind) = allocator_kind_for_codegen(tcx) {
708+
if needs_allocator_shim(tcx) {
709709
let llmod_id =
710710
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
711711
let module_llvm = tcx.sess.time("write_allocator_module", || {
712712
backend.codegen_allocator(
713713
tcx,
714714
&llmod_id,
715-
kind,
716715
// If allocator_kind is Some then alloc_error_handler_kind must
717716
// also be Some.
718717
tcx.alloc_error_handler_kind(()).unwrap(),

compiler/rustc_codegen_ssa/src/traits/backend.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ pub trait ExtraBackendMethods:
107107
&self,
108108
tcx: TyCtxt<'tcx>,
109109
module_name: &str,
110-
kind: AllocatorKind,
111110
alloc_error_handler_kind: AllocatorKind,
112111
) -> Self::Module;
113112

compiler/rustc_metadata/src/creader.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,8 @@ fn fn_spans(krate: &ast::Crate, name: Symbol) -> Vec<Span> {
14061406
if let Some(ident) = item.kind.ident()
14071407
&& ident.name == self.name
14081408
&& attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
1409+
// Ignore the default allocator in libstd with weak linkage
1410+
&& attr::find_by_name(&item.attrs, sym::linkage).is_none()
14091411
{
14101412
self.spans.push(item.span);
14111413
}

compiler/rustc_monomorphize/src/partitioning.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,7 @@ fn mono_item_visibility<'tcx>(
898898
// Removal of these functions can't be done by LLVM but rather must be
899899
// done by the linker as it's a non-local decision.
900900
//
901+
// FIXME update comment
901902
// * Second is "std internal symbols". Currently this is primarily used
902903
// for allocator symbols. Allocators are a little weird in their
903904
// implementation, but the idea is that the compiler, at the last

library/alloc/src/alloc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ unsafe extern "Rust" {
1212
// These are the magic symbols to call the global allocator. rustc generates
1313
// them to call the global allocator if there is a `#[global_allocator]` attribute
1414
// (the code expanding that attribute macro generates those functions), or to call
15-
// the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`)
15+
// the default implementations in std (weak symbols in `library/std/src/alloc.rs`)
1616
// otherwise.
1717
#[rustc_allocator]
1818
#[rustc_nounwind]

library/std/src/alloc.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -383,9 +383,8 @@ pub fn rust_oom(layout: Layout) -> ! {
383383
#[unstable(feature = "alloc_internals", issue = "none")]
384384
pub mod __default_lib_allocator {
385385
use super::{GlobalAlloc, Layout, System};
386-
// These magic symbol names are used as a fallback for implementing the
387-
// `__rust_alloc` etc symbols (see `src/liballoc/alloc.rs`) when there is
388-
// no `#[global_allocator]` attribute.
386+
// These are used as a fallback for implementing the `__rust_alloc`, etc symbols
387+
// (see `src/liballoc/alloc.rs`) when there is no `#[global_allocator]` attribute.
389388

390389
// for symbol names src/librustc_ast/expand/allocator.rs
391390
// for signatures src/librustc_allocator/lib.rs
@@ -394,7 +393,8 @@ pub mod __default_lib_allocator {
394393
// ABI
395394

396395
#[rustc_std_internal_symbol]
397-
pub unsafe extern "C" fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
396+
#[linkage = "weak"]
397+
pub unsafe extern "Rust" fn __rust_alloc(size: usize, align: usize) -> *mut u8 {
398398
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
399399
// `GlobalAlloc::alloc`.
400400
unsafe {
@@ -404,14 +404,16 @@ pub mod __default_lib_allocator {
404404
}
405405

406406
#[rustc_std_internal_symbol]
407-
pub unsafe extern "C" fn __rdl_dealloc(ptr: *mut u8, size: usize, align: usize) {
407+
#[linkage = "weak"]
408+
pub unsafe extern "Rust" fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize) {
408409
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
409410
// `GlobalAlloc::dealloc`.
410411
unsafe { System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) }
411412
}
412413

413414
#[rustc_std_internal_symbol]
414-
pub unsafe extern "C" fn __rdl_realloc(
415+
#[linkage = "weak"]
416+
pub unsafe extern "Rust" fn __rust_realloc(
415417
ptr: *mut u8,
416418
old_size: usize,
417419
align: usize,
@@ -426,7 +428,8 @@ pub mod __default_lib_allocator {
426428
}
427429

428430
#[rustc_std_internal_symbol]
429-
pub unsafe extern "C" fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
431+
#[linkage = "weak"]
432+
pub unsafe extern "Rust" fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
430433
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
431434
// `GlobalAlloc::alloc_zeroed`.
432435
unsafe {

0 commit comments

Comments
 (0)