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