]>
Commit | Line | Data |
---|---|---|
5e7ed085 | 1 | use gccjit::{FunctionType, GlobalKind, ToRValue}; |
c295e0f8 XL |
2 | use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; |
3 | use rustc_middle::bug; | |
4 | use rustc_middle::ty::TyCtxt; | |
5e7ed085 | 5 | use rustc_session::config::OomStrategy; |
c295e0f8 XL |
6 | use rustc_span::symbol::sym; |
7 | ||
8 | use crate::GccContext; | |
9 | ||
10 | pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool) { | |
11 | let context = &mods.context; | |
12 | let usize = | |
13 | match tcx.sess.target.pointer_width { | |
14 | 16 => context.new_type::<u16>(), | |
15 | 32 => context.new_type::<u32>(), | |
16 | 64 => context.new_type::<u64>(), | |
17 | tws => bug!("Unsupported target word size for int: {}", tws), | |
18 | }; | |
19 | let i8 = context.new_type::<i8>(); | |
20 | let i8p = i8.make_pointer(); | |
21 | let void = context.new_type::<()>(); | |
22 | ||
23 | for method in ALLOCATOR_METHODS { | |
24 | let mut types = Vec::with_capacity(method.inputs.len()); | |
25 | for ty in method.inputs.iter() { | |
26 | match *ty { | |
27 | AllocatorTy::Layout => { | |
28 | types.push(usize); | |
29 | types.push(usize); | |
30 | } | |
31 | AllocatorTy::Ptr => types.push(i8p), | |
32 | AllocatorTy::Usize => types.push(usize), | |
33 | ||
34 | AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), | |
35 | } | |
36 | } | |
37 | let output = match method.output { | |
38 | AllocatorTy::ResultPtr => Some(i8p), | |
39 | AllocatorTy::Unit => None, | |
40 | ||
41 | AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { | |
42 | panic!("invalid allocator output") | |
43 | } | |
44 | }; | |
45 | let name = format!("__rust_{}", method.name); | |
46 | ||
47 | let args: Vec<_> = types.iter().enumerate() | |
48 | .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) | |
49 | .collect(); | |
50 | let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false); | |
51 | ||
52 | if tcx.sess.target.options.default_hidden_visibility { | |
53 | // TODO(antoyo): set visibility. | |
54 | } | |
55 | if tcx.sess.must_emit_unwind_tables() { | |
56 | // TODO(antoyo): emit unwind tables. | |
57 | } | |
58 | ||
59 | let callee = kind.fn_name(method.name); | |
60 | let args: Vec<_> = types.iter().enumerate() | |
61 | .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) | |
62 | .collect(); | |
63 | let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false); | |
64 | // TODO(antoyo): set visibility. | |
65 | ||
66 | let block = func.new_block("entry"); | |
67 | ||
68 | let args = args | |
69 | .iter() | |
70 | .enumerate() | |
71 | .map(|(i, _)| func.get_param(i as i32).to_rvalue()) | |
72 | .collect::<Vec<_>>(); | |
73 | let ret = context.new_call(None, callee, &args); | |
74 | //llvm::LLVMSetTailCall(ret, True); | |
75 | if output.is_some() { | |
76 | block.end_with_return(None, ret); | |
77 | } | |
78 | else { | |
79 | block.end_with_void_return(None); | |
80 | } | |
81 | ||
82 | // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances | |
83 | // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643 | |
84 | } | |
85 | ||
86 | let types = [usize, usize]; | |
87 | let name = "__rust_alloc_error_handler".to_string(); | |
88 | let args: Vec<_> = types.iter().enumerate() | |
89 | .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) | |
90 | .collect(); | |
91 | let func = context.new_function(None, FunctionType::Exported, void, &args, name, false); | |
92 | ||
93 | let kind = | |
94 | if has_alloc_error_handler { | |
95 | AllocatorKind::Global | |
96 | } | |
97 | else { | |
98 | AllocatorKind::Default | |
99 | }; | |
100 | let callee = kind.fn_name(sym::oom); | |
101 | let args: Vec<_> = types.iter().enumerate() | |
102 | .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) | |
103 | .collect(); | |
104 | let callee = context.new_function(None, FunctionType::Extern, void, &args, callee, false); | |
105 | //llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); | |
106 | ||
107 | let block = func.new_block("entry"); | |
108 | ||
109 | let args = args | |
110 | .iter() | |
111 | .enumerate() | |
112 | .map(|(i, _)| func.get_param(i as i32).to_rvalue()) | |
113 | .collect::<Vec<_>>(); | |
114 | let _ret = context.new_call(None, callee, &args); | |
115 | //llvm::LLVMSetTailCall(ret, True); | |
116 | block.end_with_void_return(None); | |
5e7ed085 FG |
117 | |
118 | let name = OomStrategy::SYMBOL.to_string(); | |
119 | let global = context.new_global(None, GlobalKind::Exported, i8, name); | |
064997fb | 120 | let value = tcx.sess.opts.unstable_opts.oom.should_panic(); |
5e7ed085 FG |
121 | let value = context.new_rvalue_from_int(i8, value as i32); |
122 | global.global_set_initializer_rvalue(value); | |
c295e0f8 | 123 | } |