3 use rustc_ast
::expand
::allocator
::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}
;
5 use rustc_middle
::ty
::TyCtxt
;
7 use crate::llvm
::{self, False, True}
;
10 pub(crate) unsafe fn codegen(tcx
: TyCtxt
<'_
>, mods
: &mut ModuleLlvm
, kind
: AllocatorKind
) {
11 let llcx
= &*mods
.llcx
;
12 let llmod
= mods
.llmod();
13 let usize = match &tcx
.sess
.target
.target
.target_pointer_width
[..] {
14 "16" => llvm
::LLVMInt16TypeInContext(llcx
),
15 "32" => llvm
::LLVMInt32TypeInContext(llcx
),
16 "64" => llvm
::LLVMInt64TypeInContext(llcx
),
17 tws
=> bug
!("Unsupported target word size for int: {}", tws
),
19 let i8 = llvm
::LLVMInt8TypeInContext(llcx
);
20 let i8p
= llvm
::LLVMPointerType(i8, 0);
21 let void
= llvm
::LLVMVoidTypeInContext(llcx
);
23 for method
in ALLOCATOR_METHODS
{
24 let mut args
= Vec
::with_capacity(method
.inputs
.len());
25 for ty
in method
.inputs
.iter() {
27 AllocatorTy
::Layout
=> {
28 args
.push(usize); // size
29 args
.push(usize); // align
31 AllocatorTy
::Ptr
=> args
.push(i8p
),
32 AllocatorTy
::Usize
=> args
.push(usize),
34 AllocatorTy
::ResultPtr
| AllocatorTy
::Unit
=> panic
!("invalid allocator arg"),
37 let output
= match method
.output
{
38 AllocatorTy
::ResultPtr
=> Some(i8p
),
39 AllocatorTy
::Unit
=> None
,
41 AllocatorTy
::Layout
| AllocatorTy
::Usize
| AllocatorTy
::Ptr
=> {
42 panic
!("invalid allocator output")
45 let ty
= llvm
::LLVMFunctionType(
46 output
.unwrap_or(void
),
51 let name
= format
!("__rust_{}", method
.name
);
52 let llfn
= llvm
::LLVMRustGetOrInsertFunction(llmod
, name
.as_ptr().cast(), name
.len(), ty
);
54 if tcx
.sess
.target
.target
.options
.default_hidden_visibility
{
55 llvm
::LLVMRustSetVisibility(llfn
, llvm
::Visibility
::Hidden
);
57 if tcx
.sess
.must_emit_unwind_tables() {
58 attributes
::emit_uwtable(llfn
, true);
61 let callee
= kind
.fn_name(method
.name
);
63 llvm
::LLVMRustGetOrInsertFunction(llmod
, callee
.as_ptr().cast(), callee
.len(), ty
);
64 llvm
::LLVMRustSetVisibility(callee
, llvm
::Visibility
::Hidden
);
66 let llbb
= llvm
::LLVMAppendBasicBlockInContext(llcx
, llfn
, "entry\0".as_ptr().cast());
68 let llbuilder
= llvm
::LLVMCreateBuilderInContext(llcx
);
69 llvm
::LLVMPositionBuilderAtEnd(llbuilder
, llbb
);
73 .map(|(i
, _
)| llvm
::LLVMGetParam(llfn
, i
as c_uint
))
76 llvm
::LLVMRustBuildCall(llbuilder
, callee
, args
.as_ptr(), args
.len() as c_uint
, None
);
77 llvm
::LLVMSetTailCall(ret
, True
);
79 llvm
::LLVMBuildRet(llbuilder
, ret
);
81 llvm
::LLVMBuildRetVoid(llbuilder
);
83 llvm
::LLVMDisposeBuilder(llbuilder
);