]>
Commit | Line | Data |
---|---|---|
c295e0f8 XL |
1 | use std::cell::{Cell, RefCell}; |
2 | ||
5e7ed085 | 3 | use gccjit::{Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, RValue, Struct, Type}; |
c295e0f8 XL |
4 | use rustc_codegen_ssa::base::wants_msvc_seh; |
5 | use rustc_codegen_ssa::traits::{ | |
6 | BackendTypes, | |
7 | MiscMethods, | |
8 | }; | |
9 | use rustc_data_structures::base_n; | |
10 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; | |
11 | use rustc_middle::span_bug; | |
12 | use rustc_middle::mir::mono::CodegenUnit; | |
13 | use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; | |
14 | use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers}; | |
15 | use rustc_session::Session; | |
064997fb | 16 | use rustc_span::Span; |
c295e0f8 XL |
17 | use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; |
18 | use rustc_target::spec::{HasTargetSpec, Target, TlsModel}; | |
19 | ||
20 | use crate::callee::get_fn; | |
c295e0f8 XL |
21 | |
22 | #[derive(Clone)] | |
23 | pub struct FuncSig<'gcc> { | |
24 | pub params: Vec<Type<'gcc>>, | |
25 | pub return_type: Type<'gcc>, | |
26 | } | |
27 | ||
28 | pub struct CodegenCx<'gcc, 'tcx> { | |
29 | pub check_overflow: bool, | |
30 | pub codegen_unit: &'tcx CodegenUnit<'tcx>, | |
31 | pub context: &'gcc Context<'gcc>, | |
32 | ||
5e7ed085 | 33 | // TODO(bjorn3): Can this field be removed? |
c295e0f8 XL |
34 | pub current_func: RefCell<Option<Function<'gcc>>>, |
35 | pub normal_function_addresses: RefCell<FxHashSet<RValue<'gcc>>>, | |
36 | ||
37 | pub functions: RefCell<FxHashMap<String, Function<'gcc>>>, | |
923072b8 | 38 | pub intrinsics: RefCell<FxHashMap<String, Function<'gcc>>>, |
c295e0f8 XL |
39 | |
40 | pub tls_model: gccjit::TlsModel, | |
41 | ||
42 | pub bool_type: Type<'gcc>, | |
43 | pub i8_type: Type<'gcc>, | |
44 | pub i16_type: Type<'gcc>, | |
45 | pub i32_type: Type<'gcc>, | |
46 | pub i64_type: Type<'gcc>, | |
47 | pub i128_type: Type<'gcc>, | |
48 | pub isize_type: Type<'gcc>, | |
49 | ||
50 | pub u8_type: Type<'gcc>, | |
51 | pub u16_type: Type<'gcc>, | |
52 | pub u32_type: Type<'gcc>, | |
53 | pub u64_type: Type<'gcc>, | |
54 | pub u128_type: Type<'gcc>, | |
55 | pub usize_type: Type<'gcc>, | |
56 | ||
923072b8 FG |
57 | pub char_type: Type<'gcc>, |
58 | pub uchar_type: Type<'gcc>, | |
59 | pub short_type: Type<'gcc>, | |
60 | pub ushort_type: Type<'gcc>, | |
c295e0f8 XL |
61 | pub int_type: Type<'gcc>, |
62 | pub uint_type: Type<'gcc>, | |
63 | pub long_type: Type<'gcc>, | |
64 | pub ulong_type: Type<'gcc>, | |
923072b8 | 65 | pub longlong_type: Type<'gcc>, |
c295e0f8 XL |
66 | pub ulonglong_type: Type<'gcc>, |
67 | pub sizet_type: Type<'gcc>, | |
68 | ||
5e7ed085 FG |
69 | pub supports_128bit_integers: bool, |
70 | ||
c295e0f8 XL |
71 | pub float_type: Type<'gcc>, |
72 | pub double_type: Type<'gcc>, | |
73 | ||
74 | pub linkage: Cell<FunctionType>, | |
75 | pub scalar_types: RefCell<FxHashMap<Ty<'tcx>, Type<'gcc>>>, | |
76 | pub types: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), Type<'gcc>>>, | |
77 | pub tcx: TyCtxt<'tcx>, | |
78 | ||
79 | pub struct_types: RefCell<FxHashMap<Vec<Type<'gcc>>, Type<'gcc>>>, | |
80 | ||
81 | pub types_with_fields_to_set: RefCell<FxHashMap<Type<'gcc>, (Struct<'gcc>, TyAndLayout<'tcx>)>>, | |
82 | ||
83 | /// Cache instances of monomorphic and polymorphic items | |
84 | pub instances: RefCell<FxHashMap<Instance<'tcx>, LValue<'gcc>>>, | |
85 | /// Cache function instances of monomorphic and polymorphic items | |
86 | pub function_instances: RefCell<FxHashMap<Instance<'tcx>, RValue<'gcc>>>, | |
87 | /// Cache generated vtables | |
88 | pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>, | |
89 | ||
5e7ed085 FG |
90 | // TODO(antoyo): improve the SSA API to not require those. |
91 | // Mapping from function pointer type to indexes of on stack parameters. | |
92 | pub on_stack_params: RefCell<FxHashMap<FunctionPtrType<'gcc>, FxHashSet<usize>>>, | |
93 | // Mapping from function to indexes of on stack parameters. | |
94 | pub on_stack_function_params: RefCell<FxHashMap<Function<'gcc>, FxHashSet<usize>>>, | |
95 | ||
c295e0f8 XL |
96 | /// Cache of emitted const globals (value -> global) |
97 | pub const_globals: RefCell<FxHashMap<RValue<'gcc>, RValue<'gcc>>>, | |
98 | ||
5e7ed085 FG |
99 | /// Map from the address of a global variable (rvalue) to the global variable itself (lvalue). |
100 | /// TODO(antoyo): remove when the rustc API is fixed. | |
101 | pub global_lvalues: RefCell<FxHashMap<RValue<'gcc>, LValue<'gcc>>>, | |
102 | ||
c295e0f8 | 103 | /// Cache of constant strings, |
064997fb | 104 | pub const_str_cache: RefCell<FxHashMap<String, LValue<'gcc>>>, |
c295e0f8 XL |
105 | |
106 | /// Cache of globals. | |
107 | pub globals: RefCell<FxHashMap<String, RValue<'gcc>>>, | |
108 | ||
109 | /// A counter that is used for generating local symbol names | |
110 | local_gen_sym_counter: Cell<usize>, | |
c295e0f8 XL |
111 | |
112 | eh_personality: Cell<Option<RValue<'gcc>>>, | |
113 | ||
114 | pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>, | |
115 | ||
116 | /// NOTE: a hack is used because the rustc API is not suitable to libgccjit and as such, | |
117 | /// `const_undef()` returns struct as pointer so that they can later be assigned a value. | |
118 | /// As such, this set remembers which of these pointers were returned by this function so that | |
5e7ed085 | 119 | /// they can be dereferenced later. |
c295e0f8 XL |
120 | /// FIXME(antoyo): fix the rustc API to avoid having this hack. |
121 | pub structs_as_pointer: RefCell<FxHashSet<RValue<'gcc>>>, | |
122 | } | |
123 | ||
124 | impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { | |
5e7ed085 | 125 | pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>, tcx: TyCtxt<'tcx>, supports_128bit_integers: bool) -> Self { |
c295e0f8 | 126 | let check_overflow = tcx.sess.overflow_checks(); |
5e7ed085 FG |
127 | |
128 | let i8_type = context.new_c_type(CType::Int8t); | |
129 | let i16_type = context.new_c_type(CType::Int16t); | |
130 | let i32_type = context.new_c_type(CType::Int32t); | |
131 | let i64_type = context.new_c_type(CType::Int64t); | |
132 | let u8_type = context.new_c_type(CType::UInt8t); | |
133 | let u16_type = context.new_c_type(CType::UInt16t); | |
134 | let u32_type = context.new_c_type(CType::UInt32t); | |
135 | let u64_type = context.new_c_type(CType::UInt64t); | |
136 | ||
137 | let (i128_type, u128_type) = | |
138 | if supports_128bit_integers { | |
139 | let i128_type = context.new_c_type(CType::Int128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?; | |
140 | let u128_type = context.new_c_type(CType::UInt128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?; | |
141 | (i128_type, u128_type) | |
142 | } | |
143 | else { | |
144 | let i128_type = context.new_array_type(None, i64_type, 2); | |
145 | let u128_type = context.new_array_type(None, u64_type, 2); | |
146 | (i128_type, u128_type) | |
147 | }; | |
c295e0f8 XL |
148 | |
149 | let tls_model = to_gcc_tls_mode(tcx.sess.tls_model()); | |
150 | ||
151 | let float_type = context.new_type::<f32>(); | |
152 | let double_type = context.new_type::<f64>(); | |
153 | ||
923072b8 FG |
154 | let char_type = context.new_c_type(CType::Char); |
155 | let uchar_type = context.new_c_type(CType::UChar); | |
156 | let short_type = context.new_c_type(CType::Short); | |
157 | let ushort_type = context.new_c_type(CType::UShort); | |
c295e0f8 XL |
158 | let int_type = context.new_c_type(CType::Int); |
159 | let uint_type = context.new_c_type(CType::UInt); | |
160 | let long_type = context.new_c_type(CType::Long); | |
161 | let ulong_type = context.new_c_type(CType::ULong); | |
923072b8 | 162 | let longlong_type = context.new_c_type(CType::LongLong); |
c295e0f8 XL |
163 | let ulonglong_type = context.new_c_type(CType::ULongLong); |
164 | let sizet_type = context.new_c_type(CType::SizeT); | |
165 | ||
5e7ed085 FG |
166 | let isize_type = context.new_c_type(CType::LongLong); |
167 | let usize_type = context.new_c_type(CType::ULongLong); | |
168 | let bool_type = context.new_type::<bool>(); | |
169 | ||
170 | // TODO(antoyo): only have those assertions on x86_64. | |
171 | assert_eq!(isize_type.get_size(), i64_type.get_size()); | |
172 | assert_eq!(usize_type.get_size(), u64_type.get_size()); | |
c295e0f8 XL |
173 | |
174 | let mut functions = FxHashMap::default(); | |
175 | let builtins = [ | |
176 | "__builtin_unreachable", "abort", "__builtin_expect", "__builtin_add_overflow", "__builtin_mul_overflow", | |
177 | "__builtin_saddll_overflow", /*"__builtin_sadd_overflow",*/ "__builtin_smulll_overflow", /*"__builtin_smul_overflow",*/ | |
178 | "__builtin_ssubll_overflow", /*"__builtin_ssub_overflow",*/ "__builtin_sub_overflow", "__builtin_uaddll_overflow", | |
179 | "__builtin_uadd_overflow", "__builtin_umulll_overflow", "__builtin_umul_overflow", "__builtin_usubll_overflow", | |
180 | "__builtin_usub_overflow", "sqrtf", "sqrt", "__builtin_powif", "__builtin_powi", "sinf", "sin", "cosf", "cos", | |
181 | "powf", "pow", "expf", "exp", "exp2f", "exp2", "logf", "log", "log10f", "log10", "log2f", "log2", "fmaf", | |
182 | "fma", "fabsf", "fabs", "fminf", "fmin", "fmaxf", "fmax", "copysignf", "copysign", "floorf", "floor", "ceilf", | |
183 | "ceil", "truncf", "trunc", "rintf", "rint", "nearbyintf", "nearbyint", "roundf", "round", | |
184 | "__builtin_expect_with_probability", | |
185 | ]; | |
186 | ||
187 | for builtin in builtins.iter() { | |
188 | functions.insert(builtin.to_string(), context.get_builtin_function(builtin)); | |
189 | } | |
190 | ||
191 | Self { | |
192 | check_overflow, | |
193 | codegen_unit, | |
194 | context, | |
c295e0f8 XL |
195 | current_func: RefCell::new(None), |
196 | normal_function_addresses: Default::default(), | |
197 | functions: RefCell::new(functions), | |
923072b8 | 198 | intrinsics: RefCell::new(FxHashMap::default()), |
c295e0f8 XL |
199 | |
200 | tls_model, | |
201 | ||
202 | bool_type, | |
203 | i8_type, | |
204 | i16_type, | |
205 | i32_type, | |
206 | i64_type, | |
207 | i128_type, | |
208 | isize_type, | |
209 | usize_type, | |
210 | u8_type, | |
211 | u16_type, | |
212 | u32_type, | |
213 | u64_type, | |
214 | u128_type, | |
923072b8 FG |
215 | char_type, |
216 | uchar_type, | |
217 | short_type, | |
218 | ushort_type, | |
c295e0f8 XL |
219 | int_type, |
220 | uint_type, | |
221 | long_type, | |
222 | ulong_type, | |
923072b8 | 223 | longlong_type, |
c295e0f8 XL |
224 | ulonglong_type, |
225 | sizet_type, | |
226 | ||
5e7ed085 FG |
227 | supports_128bit_integers, |
228 | ||
c295e0f8 XL |
229 | float_type, |
230 | double_type, | |
231 | ||
232 | linkage: Cell::new(FunctionType::Internal), | |
233 | instances: Default::default(), | |
234 | function_instances: Default::default(), | |
5e7ed085 FG |
235 | on_stack_params: Default::default(), |
236 | on_stack_function_params: Default::default(), | |
c295e0f8 XL |
237 | vtables: Default::default(), |
238 | const_globals: Default::default(), | |
5e7ed085 FG |
239 | global_lvalues: Default::default(), |
240 | const_str_cache: Default::default(), | |
c295e0f8 XL |
241 | globals: Default::default(), |
242 | scalar_types: Default::default(), | |
243 | types: Default::default(), | |
244 | tcx, | |
245 | struct_types: Default::default(), | |
246 | types_with_fields_to_set: Default::default(), | |
247 | local_gen_sym_counter: Cell::new(0), | |
c295e0f8 XL |
248 | eh_personality: Cell::new(None), |
249 | pointee_infos: Default::default(), | |
250 | structs_as_pointer: Default::default(), | |
251 | } | |
252 | } | |
253 | ||
254 | pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> { | |
255 | let function: Function<'gcc> = unsafe { std::mem::transmute(value) }; | |
256 | debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(), | |
257 | "{:?} ({:?}) is not a function", value, value.get_type()); | |
258 | function | |
259 | } | |
260 | ||
5e7ed085 FG |
261 | pub fn is_native_int_type(&self, typ: Type<'gcc>) -> bool { |
262 | let types = [ | |
263 | self.u8_type, | |
264 | self.u16_type, | |
265 | self.u32_type, | |
266 | self.u64_type, | |
267 | self.i8_type, | |
268 | self.i16_type, | |
269 | self.i32_type, | |
270 | self.i64_type, | |
271 | ]; | |
272 | ||
273 | for native_type in types { | |
274 | if native_type.is_compatible_with(typ) { | |
275 | return true; | |
276 | } | |
277 | } | |
278 | ||
279 | self.supports_128bit_integers && | |
280 | (self.u128_type.is_compatible_with(typ) || self.i128_type.is_compatible_with(typ)) | |
281 | } | |
282 | ||
283 | pub fn is_non_native_int_type(&self, typ: Type<'gcc>) -> bool { | |
284 | !self.supports_128bit_integers && | |
285 | (self.u128_type.is_compatible_with(typ) || self.i128_type.is_compatible_with(typ)) | |
286 | } | |
287 | ||
288 | pub fn is_native_int_type_or_bool(&self, typ: Type<'gcc>) -> bool { | |
923072b8 | 289 | self.is_native_int_type(typ) || typ.is_compatible_with(self.bool_type) |
5e7ed085 FG |
290 | } |
291 | ||
292 | pub fn is_int_type_or_bool(&self, typ: Type<'gcc>) -> bool { | |
923072b8 | 293 | self.is_native_int_type(typ) || self.is_non_native_int_type(typ) || typ.is_compatible_with(self.bool_type) |
5e7ed085 FG |
294 | } |
295 | ||
c295e0f8 XL |
296 | pub fn sess(&self) -> &Session { |
297 | &self.tcx.sess | |
298 | } | |
923072b8 FG |
299 | |
300 | pub fn bitcast_if_needed(&self, value: RValue<'gcc>, expected_type: Type<'gcc>) -> RValue<'gcc> { | |
301 | if value.get_type() != expected_type { | |
302 | self.context.new_bitcast(None, value, expected_type) | |
303 | } | |
304 | else { | |
305 | value | |
306 | } | |
307 | } | |
c295e0f8 XL |
308 | } |
309 | ||
310 | impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> { | |
311 | type Value = RValue<'gcc>; | |
312 | type Function = RValue<'gcc>; | |
313 | ||
314 | type BasicBlock = Block<'gcc>; | |
315 | type Type = Type<'gcc>; | |
316 | type Funclet = (); // TODO(antoyo) | |
317 | ||
318 | type DIScope = (); // TODO(antoyo) | |
319 | type DILocation = (); // TODO(antoyo) | |
320 | type DIVariable = (); // TODO(antoyo) | |
321 | } | |
322 | ||
323 | impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> { | |
324 | fn vtables(&self) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>> { | |
325 | &self.vtables | |
326 | } | |
327 | ||
328 | fn get_fn(&self, instance: Instance<'tcx>) -> RValue<'gcc> { | |
329 | let func = get_fn(self, instance); | |
330 | *self.current_func.borrow_mut() = Some(self.rvalue_as_function(func)); | |
331 | func | |
332 | } | |
333 | ||
334 | fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> { | |
923072b8 FG |
335 | let func_name = self.tcx.symbol_name(instance).name; |
336 | ||
337 | let func = | |
338 | if self.intrinsics.borrow().contains_key(func_name) { | |
339 | self.intrinsics.borrow()[func_name].clone() | |
340 | } | |
341 | else { | |
342 | let func = get_fn(self, instance); | |
343 | self.rvalue_as_function(func) | |
344 | }; | |
c295e0f8 XL |
345 | let ptr = func.get_address(None); |
346 | ||
347 | // TODO(antoyo): don't do this twice: i.e. in declare_fn and here. | |
348 | // FIXME(antoyo): the rustc API seems to call get_fn_addr() when not needed (e.g. for FFI). | |
349 | ||
350 | self.normal_function_addresses.borrow_mut().insert(ptr); | |
351 | ||
352 | ptr | |
353 | } | |
354 | ||
355 | fn eh_personality(&self) -> RValue<'gcc> { | |
356 | // The exception handling personality function. | |
357 | // | |
358 | // If our compilation unit has the `eh_personality` lang item somewhere | |
359 | // within it, then we just need to codegen that. Otherwise, we're | |
360 | // building an rlib which will depend on some upstream implementation of | |
361 | // this function, so we just codegen a generic reference to it. We don't | |
362 | // specify any of the types for the function, we just make it a symbol | |
363 | // that LLVM can later use. | |
364 | // | |
365 | // Note that MSVC is a little special here in that we don't use the | |
366 | // `eh_personality` lang item at all. Currently LLVM has support for | |
367 | // both Dwarf and SEH unwind mechanisms for MSVC targets and uses the | |
368 | // *name of the personality function* to decide what kind of unwind side | |
369 | // tables/landing pads to emit. It looks like Dwarf is used by default, | |
370 | // injecting a dependency on the `_Unwind_Resume` symbol for resuming | |
371 | // an "exception", but for MSVC we want to force SEH. This means that we | |
372 | // can't actually have the personality function be our standard | |
373 | // `rust_eh_personality` function, but rather we wired it up to the | |
374 | // CRT's custom personality function, which forces LLVM to consider | |
375 | // landing pads as "landing pads for SEH". | |
376 | if let Some(llpersonality) = self.eh_personality.get() { | |
377 | return llpersonality; | |
378 | } | |
379 | let tcx = self.tcx; | |
380 | let llfn = match tcx.lang_items().eh_personality() { | |
381 | Some(def_id) if !wants_msvc_seh(self.sess()) => self.get_fn_addr( | |
382 | ty::Instance::resolve( | |
383 | tcx, | |
384 | ty::ParamEnv::reveal_all(), | |
385 | def_id, | |
386 | tcx.intern_substs(&[]), | |
387 | ) | |
388 | .unwrap().unwrap(), | |
389 | ), | |
390 | _ => { | |
391 | let _name = if wants_msvc_seh(self.sess()) { | |
392 | "__CxxFrameHandler3" | |
393 | } else { | |
394 | "rust_eh_personality" | |
395 | }; | |
396 | //let func = self.declare_func(name, self.type_i32(), &[], true); | |
397 | // FIXME(antoyo): this hack should not be needed. That will probably be removed when | |
398 | // unwinding support is added. | |
399 | self.context.new_rvalue_from_int(self.int_type, 0) | |
400 | } | |
401 | }; | |
402 | // TODO(antoyo): apply target cpu attributes. | |
403 | self.eh_personality.set(Some(llfn)); | |
404 | llfn | |
405 | } | |
406 | ||
407 | fn sess(&self) -> &Session { | |
408 | &self.tcx.sess | |
409 | } | |
410 | ||
411 | fn check_overflow(&self) -> bool { | |
412 | self.check_overflow | |
413 | } | |
414 | ||
415 | fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> { | |
416 | self.codegen_unit | |
417 | } | |
418 | ||
419 | fn used_statics(&self) -> &RefCell<Vec<RValue<'gcc>>> { | |
420 | unimplemented!(); | |
421 | } | |
422 | ||
423 | fn set_frame_pointer_type(&self, _llfn: RValue<'gcc>) { | |
424 | // TODO(antoyo) | |
425 | } | |
426 | ||
427 | fn apply_target_cpu_attr(&self, _llfn: RValue<'gcc>) { | |
428 | // TODO(antoyo) | |
429 | } | |
430 | ||
431 | fn create_used_variable(&self) { | |
432 | unimplemented!(); | |
433 | } | |
434 | ||
435 | fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> { | |
436 | if self.get_declared_value("main").is_none() { | |
437 | Some(self.declare_cfn("main", fn_type)) | |
438 | } | |
439 | else { | |
440 | // If the symbol already exists, it is an error: for example, the user wrote | |
441 | // #[no_mangle] extern "C" fn main(..) {..} | |
442 | // instead of #[start] | |
443 | None | |
444 | } | |
445 | } | |
446 | ||
447 | fn compiler_used_statics(&self) -> &RefCell<Vec<RValue<'gcc>>> { | |
448 | unimplemented!() | |
449 | } | |
450 | ||
451 | fn create_compiler_used_variable(&self) { | |
452 | unimplemented!() | |
453 | } | |
454 | } | |
455 | ||
456 | impl<'gcc, 'tcx> HasTyCtxt<'tcx> for CodegenCx<'gcc, 'tcx> { | |
457 | fn tcx(&self) -> TyCtxt<'tcx> { | |
458 | self.tcx | |
459 | } | |
460 | } | |
461 | ||
462 | impl<'gcc, 'tcx> HasDataLayout for CodegenCx<'gcc, 'tcx> { | |
463 | fn data_layout(&self) -> &TargetDataLayout { | |
464 | &self.tcx.data_layout | |
465 | } | |
466 | } | |
467 | ||
468 | impl<'gcc, 'tcx> HasTargetSpec for CodegenCx<'gcc, 'tcx> { | |
469 | fn target_spec(&self) -> &Target { | |
470 | &self.tcx.sess.target | |
471 | } | |
472 | } | |
473 | ||
474 | impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { | |
475 | type LayoutOfResult = TyAndLayout<'tcx>; | |
476 | ||
477 | #[inline] | |
478 | fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { | |
479 | if let LayoutError::SizeOverflow(_) = err { | |
480 | self.sess().span_fatal(span, &err.to_string()) | |
481 | } else { | |
482 | span_bug!(span, "failed to get layout for `{}`: {}", ty, err) | |
483 | } | |
484 | } | |
485 | } | |
486 | ||
487 | impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { | |
488 | type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; | |
489 | ||
490 | #[inline] | |
491 | fn handle_fn_abi_err( | |
492 | &self, | |
493 | err: FnAbiError<'tcx>, | |
494 | span: Span, | |
495 | fn_abi_request: FnAbiRequest<'tcx>, | |
496 | ) -> ! { | |
497 | if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { | |
498 | self.sess().span_fatal(span, &err.to_string()) | |
499 | } else { | |
500 | match fn_abi_request { | |
501 | FnAbiRequest::OfFnPtr { sig, extra_args } => { | |
502 | span_bug!( | |
503 | span, | |
504 | "`fn_abi_of_fn_ptr({}, {:?})` failed: {}", | |
505 | sig, | |
506 | extra_args, | |
507 | err | |
508 | ); | |
509 | } | |
510 | FnAbiRequest::OfInstance { instance, extra_args } => { | |
511 | span_bug!( | |
512 | span, | |
513 | "`fn_abi_of_instance({}, {:?})` failed: {}", | |
514 | instance, | |
515 | extra_args, | |
516 | err | |
517 | ); | |
518 | } | |
519 | } | |
520 | } | |
521 | } | |
522 | } | |
523 | ||
524 | impl<'tcx, 'gcc> HasParamEnv<'tcx> for CodegenCx<'gcc, 'tcx> { | |
525 | fn param_env(&self) -> ParamEnv<'tcx> { | |
526 | ParamEnv::reveal_all() | |
527 | } | |
528 | } | |
529 | ||
530 | impl<'b, 'tcx> CodegenCx<'b, 'tcx> { | |
531 | /// Generates a new symbol name with the given prefix. This symbol name must | |
532 | /// only be used for definitions with `internal` or `private` linkage. | |
533 | pub fn generate_local_symbol_name(&self, prefix: &str) -> String { | |
534 | let idx = self.local_gen_sym_counter.get(); | |
535 | self.local_gen_sym_counter.set(idx + 1); | |
536 | // Include a '.' character, so there can be no accidental conflicts with | |
537 | // user defined names | |
538 | let mut name = String::with_capacity(prefix.len() + 6); | |
539 | name.push_str(prefix); | |
540 | name.push_str("."); | |
541 | base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name); | |
542 | name | |
543 | } | |
544 | } | |
545 | ||
c295e0f8 XL |
546 | fn to_gcc_tls_mode(tls_model: TlsModel) -> gccjit::TlsModel { |
547 | match tls_model { | |
548 | TlsModel::GeneralDynamic => gccjit::TlsModel::GlobalDynamic, | |
549 | TlsModel::LocalDynamic => gccjit::TlsModel::LocalDynamic, | |
550 | TlsModel::InitialExec => gccjit::TlsModel::InitialExec, | |
551 | TlsModel::LocalExec => gccjit::TlsModel::LocalExec, | |
552 | } | |
553 | } |