Skip to content

Commit f4f6936

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 3bf62cc commit f4f6936

File tree

14 files changed

+42
-162
lines changed

14 files changed

+42
-162
lines changed

compiler/rustc_ast/src/expand/allocator.rs

-4
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

+12-50
Original file line numberDiff line numberDiff line change
@@ -2,72 +2,34 @@
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

1110
use crate::prelude::*;
1211

1312
/// Returns whether an allocator shim was created
1413
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
14+
if needs_allocator_shim(tcx) {
15+
codegen_inner(
16+
module,
17+
tcx.alloc_error_handler_kind(()).unwrap(),
18+
tcx.sess.opts.unstable_opts.oom,
19+
);
20+
true
21+
} else {
22+
false
23+
}
2324
}
2425

2526
fn codegen_inner(
2627
module: &mut dyn Module,
27-
kind: AllocatorKind,
2828
alloc_error_handler_kind: AllocatorKind,
2929
oom_strategy: OomStrategy,
3030
) {
3131
let usize_ty = module.target_config().pointer_type();
3232

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-
}
69-
}
70-
7133
let sig = Signature {
7234
call_conv: module.target_config().default_call_conv,
7335
params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],

compiler/rustc_codegen_gcc/src/allocator.rs

+1-34
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
use gccjit::FnAttribute;
33
use gccjit::{Context, FunctionType, GlobalKind, 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+
AllocatorKind, NO_ALLOC_SHIM_IS_UNSTABLE, alloc_error_handler_name,
76
};
87
use rustc_middle::bug;
98
use rustc_middle::ty::TyCtxt;
@@ -15,7 +14,6 @@ pub(crate) unsafe fn codegen(
1514
tcx: TyCtxt<'_>,
1615
mods: &mut GccContext,
1716
_module_name: &str,
18-
kind: AllocatorKind,
1917
alloc_error_handler_kind: AllocatorKind,
2018
) {
2119
let context = &mods.context;
@@ -26,37 +24,6 @@ pub(crate) unsafe fn codegen(
2624
tws => bug!("Unsupported target word size for int: {}", tws),
2725
};
2826
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-
}
6027

6128
// FIXME(bjorn3): Add noreturn attribute
6229
create_wrapper_function(

compiler/rustc_codegen_gcc/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,6 @@ impl ExtraBackendMethods for GccCodegenBackend {
291291
&self,
292292
tcx: TyCtxt<'_>,
293293
module_name: &str,
294-
kind: AllocatorKind,
295294
alloc_error_handler_kind: AllocatorKind,
296295
) -> Self::Module {
297296
let mut mods = GccContext {
@@ -301,7 +300,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
301300
};
302301

303302
unsafe {
304-
allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind);
303+
allocator::codegen(tcx, &mut mods, module_name, alloc_error_handler_kind);
305304
}
306305
mods
307306
}

compiler/rustc_codegen_llvm/src/allocator.rs

+1-35
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_middle::bug;
76
use rustc_middle::ty::TyCtxt;
@@ -15,7 +14,6 @@ pub(crate) unsafe fn codegen(
1514
tcx: TyCtxt<'_>,
1615
module_llvm: &mut ModuleLlvm,
1716
module_name: &str,
18-
kind: AllocatorKind,
1917
alloc_error_handler_kind: AllocatorKind,
2018
) {
2119
let llcx = &*module_llvm.llcx;
@@ -29,38 +27,6 @@ pub(crate) unsafe fn codegen(
2927
}
3028
};
3129
let i8 = unsafe { llvm::LLVMInt8TypeInContext(llcx) };
32-
let i8p = unsafe { llvm::LLVMPointerTypeInContext(llcx, 0) };
33-
34-
if kind == AllocatorKind::Default {
35-
for method in ALLOCATOR_METHODS {
36-
let mut args = Vec::with_capacity(method.inputs.len());
37-
for input in method.inputs.iter() {
38-
match input.ty {
39-
AllocatorTy::Layout => {
40-
args.push(usize); // size
41-
args.push(usize); // align
42-
}
43-
AllocatorTy::Ptr => args.push(i8p),
44-
AllocatorTy::Usize => args.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-
58-
let from_name = global_fn_name(method.name);
59-
let to_name = default_fn_name(method.name);
60-
61-
create_wrapper_function(tcx, llcx, llmod, &from_name, &to_name, &args, output, false);
62-
}
63-
}
6430

6531
// rust alloc error handler
6632
create_wrapper_function(

compiler/rustc_codegen_llvm/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,11 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
114114
&self,
115115
tcx: TyCtxt<'tcx>,
116116
module_name: &str,
117-
kind: AllocatorKind,
118117
alloc_error_handler_kind: AllocatorKind,
119118
) -> ModuleLlvm {
120119
let mut module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
121120
unsafe {
122-
allocator::codegen(tcx, &mut module_llvm, module_name, kind, alloc_error_handler_kind);
121+
allocator::codegen(tcx, &mut module_llvm, module_name, alloc_error_handler_kind);
123122
}
124123
module_llvm
125124
}

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_session::config::{CrateType, OomStrategy};
1616
use rustc_target::spec::{SanitizerSet, TlsModel};
1717
use tracing::debug;
1818

19-
use crate::base::allocator_kind_for_codegen;
19+
use crate::base::needs_allocator_shim;
2020

2121
fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
2222
crates_export_threshold(tcx.crate_types())
@@ -206,7 +206,7 @@ fn exported_symbols_provider_local(
206206
}
207207

208208
// Mark allocator shim symbols as exported only if they were generated.
209-
if allocator_kind_for_codegen(tcx).is_some() {
209+
if needs_allocator_shim(tcx) {
210210
for symbol_name in ALLOCATOR_METHODS
211211
.iter()
212212
.map(|method| format!("__rust_{}", method.name))

compiler/rustc_codegen_ssa/src/base.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::time::{Duration, Instant};
44

55
use itertools::Itertools;
66
use rustc_abi::FIRST_VARIANT;
7-
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_name};
7+
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, global_fn_name};
88
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
99
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
1010
use rustc_data_structures::sync::{Lrc, par_map};
@@ -584,7 +584,7 @@ pub fn collect_debugger_visualizers_transitive(
584584
/// Decide allocator kind to codegen. If `Some(_)` this will be the same as
585585
/// `tcx.allocator_kind`, but it may be `None` in more cases (e.g. if using
586586
/// allocator definitions from a dylib dependency).
587-
pub fn allocator_kind_for_codegen(tcx: TyCtxt<'_>) -> Option<AllocatorKind> {
587+
pub fn needs_allocator_shim(tcx: TyCtxt<'_>) -> bool {
588588
// If the crate doesn't have an `allocator_kind` set then there's definitely
589589
// no shim to generate. Otherwise we also check our dependency graph for all
590590
// our output crate types. If anything there looks like its a `Dynamic`
@@ -595,7 +595,7 @@ pub fn allocator_kind_for_codegen(tcx: TyCtxt<'_>) -> Option<AllocatorKind> {
595595
use rustc_middle::middle::dependency_format::Linkage;
596596
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
597597
});
598-
if any_dynamic_crate { None } else { tcx.allocator_kind(()) }
598+
if any_dynamic_crate { false } else { tcx.allocator_kind(()).is_some() }
599599
}
600600

601601
pub fn codegen_crate<B: ExtraBackendMethods>(
@@ -664,14 +664,13 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
664664
start_async_codegen(backend.clone(), tcx, target_cpu, metadata, metadata_module);
665665

666666
// Codegen an allocator shim, if necessary.
667-
if let Some(kind) = allocator_kind_for_codegen(tcx) {
667+
if needs_allocator_shim(tcx) {
668668
let llmod_id =
669669
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
670670
let module_llvm = tcx.sess.time("write_allocator_module", || {
671671
backend.codegen_allocator(
672672
tcx,
673673
&llmod_id,
674-
kind,
675674
// If allocator_kind is Some then alloc_error_handler_kind must
676675
// also be Some.
677676
tcx.alloc_error_handler_kind(()).unwrap(),

compiler/rustc_codegen_ssa/src/traits/backend.rs

-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ pub trait ExtraBackendMethods:
104104
&self,
105105
tcx: TyCtxt<'tcx>,
106106
module_name: &str,
107-
kind: AllocatorKind,
108107
alloc_error_handler_kind: AllocatorKind,
109108
) -> Self::Module;
110109

compiler/rustc_metadata/src/creader.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,8 @@ fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> {
11271127
fn visit_item(&mut self, item: &'ast ast::Item) {
11281128
if item.ident.name == self.name
11291129
&& attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
1130+
// Ignore the default allocator in libstd with weak linkage
1131+
&& attr::find_by_name(&item.attrs, sym::linkage).is_none()
11301132
{
11311133
self.spans.push(item.span);
11321134
}

compiler/rustc_monomorphize/src/partitioning.rs

+1
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,7 @@ fn mono_item_visibility<'tcx>(
887887
// Removal of these functions can't be done by LLVM but rather must be
888888
// done by the linker as it's a non-local decision.
889889
//
890+
// FIXME update comment
890891
// * Second is "std internal symbols". Currently this is primarily used
891892
// for allocator symbols. Allocators are a little weird in their
892893
// implementation, but the idea is that the compiler, at the last

library/alloc/src/alloc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ extern "Rust" {
1414
// These are the magic symbols to call the global allocator. rustc generates
1515
// them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute
1616
// (the code expanding that attribute macro generates those functions), or to call
17-
// the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`)
17+
// the default implementations in std (weak symbols in `library/std/src/alloc.rs`)
1818
// otherwise.
1919
// The rustc fork of LLVM 14 and earlier also special-cases these function names to be able to optimize them
2020
// like `malloc`, `realloc`, and `free`, respectively.

library/std/src/alloc.rs

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

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

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

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

412413
#[rustc_std_internal_symbol]
413-
pub unsafe extern "C" fn __rdl_realloc(
414+
#[linkage = "weak"]
415+
pub unsafe extern "C" fn __rust_realloc(
414416
ptr: *mut u8,
415417
old_size: usize,
416418
align: usize,
@@ -425,7 +427,8 @@ pub mod __default_lib_allocator {
425427
}
426428

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

0 commit comments

Comments
 (0)