6 use cranelift_codegen
::binemit
::{NullStackMapSink, NullTrapSink}
;
7 use rustc_ast
::expand
::allocator
::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}
;
8 use rustc_span
::symbol
::sym
;
10 /// Returns whether an allocator shim was created
11 pub(crate) fn codegen(
13 module
: &mut impl Module
,
14 unwind_context
: &mut UnwindContext
,
16 let any_dynamic_crate
= tcx
.dependency_formats(()).iter().any(|(_
, list
)| {
17 use rustc_middle
::middle
::dependency_format
::Linkage
;
18 list
.iter().any(|&linkage
| linkage
== Linkage
::Dynamic
)
20 if any_dynamic_crate
{
22 } else if let Some(kind
) = tcx
.allocator_kind(()) {
23 codegen_inner(module
, unwind_context
, kind
);
31 module
: &mut impl Module
,
32 unwind_context
: &mut UnwindContext
,
35 let usize_ty
= module
.target_config().pointer_type();
37 for method
in ALLOCATOR_METHODS
{
38 let mut arg_tys
= Vec
::with_capacity(method
.inputs
.len());
39 for ty
in method
.inputs
.iter() {
41 AllocatorTy
::Layout
=> {
42 arg_tys
.push(usize_ty
); // size
43 arg_tys
.push(usize_ty
); // align
45 AllocatorTy
::Ptr
=> arg_tys
.push(usize_ty
),
46 AllocatorTy
::Usize
=> arg_tys
.push(usize_ty
),
48 AllocatorTy
::ResultPtr
| AllocatorTy
::Unit
=> panic
!("invalid allocator arg"),
51 let output
= match method
.output
{
52 AllocatorTy
::ResultPtr
=> Some(usize_ty
),
53 AllocatorTy
::Unit
=> None
,
55 AllocatorTy
::Layout
| AllocatorTy
::Usize
| AllocatorTy
::Ptr
=> {
56 panic
!("invalid allocator output")
61 call_conv
: CallConv
::triple_default(module
.isa().triple()),
62 params
: arg_tys
.iter().cloned().map(AbiParam
::new
).collect(),
63 returns
: output
.into_iter().map(AbiParam
::new
).collect(),
66 let caller_name
= format
!("__rust_{}", method
.name
);
67 let callee_name
= kind
.fn_name(method
.name
);
68 //eprintln!("Codegen allocator shim {} -> {} ({:?} -> {:?})", caller_name, callee_name, sig.params, sig.returns);
70 let func_id
= module
.declare_function(&caller_name
, Linkage
::Export
, &sig
).unwrap();
72 let callee_func_id
= module
.declare_function(&callee_name
, Linkage
::Import
, &sig
).unwrap();
74 let mut ctx
= Context
::new();
75 ctx
.func
= Function
::with_name_signature(ExternalName
::user(0, 0), sig
.clone());
77 let mut func_ctx
= FunctionBuilderContext
::new();
78 let mut bcx
= FunctionBuilder
::new(&mut ctx
.func
, &mut func_ctx
);
80 let block
= bcx
.create_block();
81 bcx
.switch_to_block(block
);
84 .map(|ty
| bcx
.append_block_param(block
, ty
))
85 .collect
::<Vec
<Value
>>();
87 let callee_func_ref
= module
.declare_func_in_func(callee_func_id
, &mut bcx
.func
);
88 let call_inst
= bcx
.ins().call(callee_func_ref
, &args
);
89 let results
= bcx
.inst_results(call_inst
).to_vec(); // Clone to prevent borrow error
91 bcx
.ins().return_(&results
);
92 bcx
.seal_all_blocks();
96 .define_function(func_id
, &mut ctx
, &mut NullTrapSink {}
, &mut NullStackMapSink {}
)
98 unwind_context
.add_function(func_id
, &ctx
, module
.isa());
101 let sig
= Signature
{
102 call_conv
: CallConv
::triple_default(module
.isa().triple()),
103 params
: vec
![AbiParam
::new(usize_ty
), AbiParam
::new(usize_ty
)],
107 let callee_name
= kind
.fn_name(sym
::oom
);
108 //eprintln!("Codegen allocator shim {} -> {} ({:?} -> {:?})", caller_name, callee_name, sig.params, sig.returns);
111 module
.declare_function("__rust_alloc_error_handler", Linkage
::Export
, &sig
).unwrap();
113 let callee_func_id
= module
.declare_function(&callee_name
, Linkage
::Import
, &sig
).unwrap();
115 let mut ctx
= Context
::new();
116 ctx
.func
= Function
::with_name_signature(ExternalName
::user(0, 0), sig
);
118 let mut func_ctx
= FunctionBuilderContext
::new();
119 let mut bcx
= FunctionBuilder
::new(&mut ctx
.func
, &mut func_ctx
);
121 let block
= bcx
.create_block();
122 bcx
.switch_to_block(block
);
123 let args
= (&[usize_ty
, usize_ty
])
125 .map(|&ty
| bcx
.append_block_param(block
, ty
))
126 .collect
::<Vec
<Value
>>();
128 let callee_func_ref
= module
.declare_func_in_func(callee_func_id
, &mut bcx
.func
);
129 bcx
.ins().call(callee_func_ref
, &args
);
131 bcx
.ins().trap(TrapCode
::UnreachableCodeReached
);
132 bcx
.seal_all_blocks();
136 .define_function(func_id
, &mut ctx
, &mut NullTrapSink {}
, &mut NullStackMapSink {}
)
138 unwind_context
.add_function(func_id
, &ctx
, module
.isa());