6 use rustc_ast
::expand
::allocator
::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}
;
7 use rustc_session
::config
::OomStrategy
;
9 /// Returns whether an allocator shim was created
10 pub(crate) fn codegen(
12 module
: &mut impl Module
,
13 unwind_context
: &mut UnwindContext
,
15 let any_dynamic_crate
= tcx
.dependency_formats(()).iter().any(|(_
, list
)| {
16 use rustc_middle
::middle
::dependency_format
::Linkage
;
17 list
.iter().any(|&linkage
| linkage
== Linkage
::Dynamic
)
19 if any_dynamic_crate
{
21 } else if let Some(kind
) = tcx
.allocator_kind(()) {
26 tcx
.lang_items().oom().is_some(),
27 tcx
.sess
.opts
.debugging_opts
.oom
,
36 module
: &mut impl Module
,
37 unwind_context
: &mut UnwindContext
,
39 has_alloc_error_handler
: bool
,
40 oom_strategy
: OomStrategy
,
42 let usize_ty
= module
.target_config().pointer_type();
44 for method
in ALLOCATOR_METHODS
{
45 let mut arg_tys
= Vec
::with_capacity(method
.inputs
.len());
46 for ty
in method
.inputs
.iter() {
48 AllocatorTy
::Layout
=> {
49 arg_tys
.push(usize_ty
); // size
50 arg_tys
.push(usize_ty
); // align
52 AllocatorTy
::Ptr
=> arg_tys
.push(usize_ty
),
53 AllocatorTy
::Usize
=> arg_tys
.push(usize_ty
),
55 AllocatorTy
::ResultPtr
| AllocatorTy
::Unit
=> panic
!("invalid allocator arg"),
58 let output
= match method
.output
{
59 AllocatorTy
::ResultPtr
=> Some(usize_ty
),
60 AllocatorTy
::Unit
=> None
,
62 AllocatorTy
::Layout
| AllocatorTy
::Usize
| AllocatorTy
::Ptr
=> {
63 panic
!("invalid allocator output")
68 call_conv
: CallConv
::triple_default(module
.isa().triple()),
69 params
: arg_tys
.iter().cloned().map(AbiParam
::new
).collect(),
70 returns
: output
.into_iter().map(AbiParam
::new
).collect(),
73 let caller_name
= format
!("__rust_{}", method
.name
);
74 let callee_name
= kind
.fn_name(method
.name
);
76 let func_id
= module
.declare_function(&caller_name
, Linkage
::Export
, &sig
).unwrap();
78 let callee_func_id
= module
.declare_function(&callee_name
, Linkage
::Import
, &sig
).unwrap();
80 let mut ctx
= Context
::new();
81 ctx
.func
= Function
::with_name_signature(ExternalName
::user(0, 0), sig
.clone());
83 let mut func_ctx
= FunctionBuilderContext
::new();
84 let mut bcx
= FunctionBuilder
::new(&mut ctx
.func
, &mut func_ctx
);
86 let block
= bcx
.create_block();
87 bcx
.switch_to_block(block
);
90 .map(|ty
| bcx
.append_block_param(block
, ty
))
91 .collect
::<Vec
<Value
>>();
93 let callee_func_ref
= module
.declare_func_in_func(callee_func_id
, &mut bcx
.func
);
94 let call_inst
= bcx
.ins().call(callee_func_ref
, &args
);
95 let results
= bcx
.inst_results(call_inst
).to_vec(); // Clone to prevent borrow error
97 bcx
.ins().return_(&results
);
98 bcx
.seal_all_blocks();
101 module
.define_function(func_id
, &mut ctx
).unwrap();
102 unwind_context
.add_function(func_id
, &ctx
, module
.isa());
105 let sig
= Signature
{
106 call_conv
: CallConv
::triple_default(module
.isa().triple()),
107 params
: vec
![AbiParam
::new(usize_ty
), AbiParam
::new(usize_ty
)],
111 let callee_name
= if has_alloc_error_handler { "__rg_oom" }
else { "__rdl_oom" }
;
114 module
.declare_function("__rust_alloc_error_handler", Linkage
::Export
, &sig
).unwrap();
116 let callee_func_id
= module
.declare_function(callee_name
, Linkage
::Import
, &sig
).unwrap();
118 let mut ctx
= Context
::new();
119 ctx
.func
= Function
::with_name_signature(ExternalName
::user(0, 0), sig
);
121 let mut func_ctx
= FunctionBuilderContext
::new();
122 let mut bcx
= FunctionBuilder
::new(&mut ctx
.func
, &mut func_ctx
);
124 let block
= bcx
.create_block();
125 bcx
.switch_to_block(block
);
126 let args
= (&[usize_ty
, usize_ty
])
128 .map(|&ty
| bcx
.append_block_param(block
, ty
))
129 .collect
::<Vec
<Value
>>();
131 let callee_func_ref
= module
.declare_func_in_func(callee_func_id
, &mut bcx
.func
);
132 bcx
.ins().call(callee_func_ref
, &args
);
134 bcx
.ins().trap(TrapCode
::UnreachableCodeReached
);
135 bcx
.seal_all_blocks();
138 module
.define_function(func_id
, &mut ctx
).unwrap();
139 unwind_context
.add_function(func_id
, &ctx
, module
.isa());
141 let data_id
= module
.declare_data(OomStrategy
::SYMBOL
, Linkage
::Export
, false, false).unwrap();
142 let mut data_ctx
= DataContext
::new();
143 data_ctx
.set_align(1);
144 let val
= oom_strategy
.should_panic();
145 data_ctx
.define(Box
::new([val
]));
146 module
.define_data(data_id
, &data_ctx
).unwrap();