]>
Commit | Line | Data |
---|---|---|
c295e0f8 | 1 | use gccjit::{RValue, Struct, Type}; |
064997fb | 2 | use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, TypeMembershipMethods}; |
c295e0f8 | 3 | use rustc_codegen_ssa::common::TypeKind; |
923072b8 | 4 | use rustc_middle::{bug, ty}; |
c295e0f8 XL |
5 | use rustc_middle::ty::layout::TyAndLayout; |
6 | use rustc_target::abi::{AddressSpace, Align, Integer, Size}; | |
7 | ||
923072b8 | 8 | use crate::common::TypeReflection; |
c295e0f8 XL |
9 | use crate::context::CodegenCx; |
10 | use crate::type_of::LayoutGccExt; | |
11 | ||
12 | impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { | |
13 | pub fn type_ix(&self, num_bits: u64) -> Type<'gcc> { | |
14 | // gcc only supports 1, 2, 4 or 8-byte integers. | |
15 | // FIXME(antoyo): this is misleading to use the next power of two as rustc_codegen_ssa | |
16 | // sometimes use 96-bit numbers and the following code will give an integer of a different | |
17 | // size. | |
18 | let bytes = (num_bits / 8).next_power_of_two() as i32; | |
19 | match bytes { | |
20 | 1 => self.i8_type, | |
21 | 2 => self.i16_type, | |
22 | 4 => self.i32_type, | |
23 | 8 => self.i64_type, | |
24 | 16 => self.i128_type, | |
25 | _ => panic!("unexpected num_bits: {}", num_bits), | |
26 | } | |
27 | } | |
28 | ||
29 | pub fn type_void(&self) -> Type<'gcc> { | |
30 | self.context.new_type::<()>() | |
31 | } | |
32 | ||
33 | pub fn type_size_t(&self) -> Type<'gcc> { | |
34 | self.context.new_type::<usize>() | |
35 | } | |
36 | ||
37 | pub fn type_u8(&self) -> Type<'gcc> { | |
38 | self.u8_type | |
39 | } | |
40 | ||
41 | pub fn type_u16(&self) -> Type<'gcc> { | |
42 | self.u16_type | |
43 | } | |
44 | ||
45 | pub fn type_u32(&self) -> Type<'gcc> { | |
46 | self.u32_type | |
47 | } | |
48 | ||
49 | pub fn type_u64(&self) -> Type<'gcc> { | |
50 | self.u64_type | |
51 | } | |
52 | ||
53 | pub fn type_u128(&self) -> Type<'gcc> { | |
54 | self.u128_type | |
55 | } | |
56 | ||
57 | pub fn type_pointee_for_align(&self, align: Align) -> Type<'gcc> { | |
58 | // FIXME(eddyb) We could find a better approximation if ity.align < align. | |
59 | let ity = Integer::approximate_align(self, align); | |
60 | self.type_from_integer(ity) | |
61 | } | |
923072b8 FG |
62 | |
63 | pub fn type_vector(&self, ty: Type<'gcc>, len: u64) -> Type<'gcc> { | |
64 | self.context.new_vector_type(ty, len) | |
65 | } | |
66 | ||
67 | pub fn type_float_from_ty(&self, t: ty::FloatTy) -> Type<'gcc> { | |
68 | match t { | |
69 | ty::FloatTy::F32 => self.type_f32(), | |
70 | ty::FloatTy::F64 => self.type_f64(), | |
71 | } | |
72 | } | |
c295e0f8 XL |
73 | } |
74 | ||
75 | impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { | |
76 | fn type_i1(&self) -> Type<'gcc> { | |
77 | self.bool_type | |
78 | } | |
79 | ||
80 | fn type_i8(&self) -> Type<'gcc> { | |
81 | self.i8_type | |
82 | } | |
83 | ||
84 | fn type_i16(&self) -> Type<'gcc> { | |
85 | self.i16_type | |
86 | } | |
87 | ||
88 | fn type_i32(&self) -> Type<'gcc> { | |
89 | self.i32_type | |
90 | } | |
91 | ||
92 | fn type_i64(&self) -> Type<'gcc> { | |
93 | self.i64_type | |
94 | } | |
95 | ||
96 | fn type_i128(&self) -> Type<'gcc> { | |
97 | self.i128_type | |
98 | } | |
99 | ||
100 | fn type_isize(&self) -> Type<'gcc> { | |
101 | self.isize_type | |
102 | } | |
103 | ||
104 | fn type_f32(&self) -> Type<'gcc> { | |
105 | self.context.new_type::<f32>() | |
106 | } | |
107 | ||
108 | fn type_f64(&self) -> Type<'gcc> { | |
109 | self.context.new_type::<f64>() | |
110 | } | |
111 | ||
112 | fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> { | |
113 | self.context.new_function_pointer_type(None, return_type, params, false) | |
114 | } | |
115 | ||
923072b8 | 116 | fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> { |
c295e0f8 XL |
117 | let types = fields.to_vec(); |
118 | if let Some(typ) = self.struct_types.borrow().get(fields) { | |
119 | return typ.clone(); | |
120 | } | |
121 | let fields: Vec<_> = fields.iter().enumerate() | |
122 | .map(|(index, field)| self.context.new_field(None, *field, &format!("field{}_TODO", index))) | |
123 | .collect(); | |
c295e0f8 | 124 | let typ = self.context.new_struct_type(None, "struct", &fields).as_type(); |
923072b8 FG |
125 | if packed { |
126 | #[cfg(feature="master")] | |
127 | typ.set_packed(); | |
128 | } | |
c295e0f8 XL |
129 | self.struct_types.borrow_mut().insert(types, typ); |
130 | typ | |
131 | } | |
132 | ||
133 | fn type_kind(&self, typ: Type<'gcc>) -> TypeKind { | |
5e7ed085 | 134 | if self.is_int_type_or_bool(typ) { |
c295e0f8 XL |
135 | TypeKind::Integer |
136 | } | |
5e7ed085 FG |
137 | else if typ.is_compatible_with(self.float_type) { |
138 | TypeKind::Float | |
139 | } | |
140 | else if typ.is_compatible_with(self.double_type) { | |
141 | TypeKind::Double | |
142 | } | |
923072b8 | 143 | else if typ.is_vector() { |
c295e0f8 XL |
144 | TypeKind::Vector |
145 | } | |
146 | else { | |
147 | // TODO(antoyo): support other types. | |
148 | TypeKind::Void | |
149 | } | |
150 | } | |
151 | ||
152 | fn type_ptr_to(&self, ty: Type<'gcc>) -> Type<'gcc> { | |
153 | ty.make_pointer() | |
154 | } | |
155 | ||
156 | fn type_ptr_to_ext(&self, ty: Type<'gcc>, _address_space: AddressSpace) -> Type<'gcc> { | |
923072b8 | 157 | // TODO(antoyo): use address_space, perhaps with TYPE_ADDR_SPACE? |
c295e0f8 XL |
158 | ty.make_pointer() |
159 | } | |
160 | ||
161 | fn element_type(&self, ty: Type<'gcc>) -> Type<'gcc> { | |
a2a8927a | 162 | if let Some(typ) = ty.dyncast_array() { |
c295e0f8 XL |
163 | typ |
164 | } | |
a2a8927a | 165 | else if let Some(vector_type) = ty.dyncast_vector() { |
c295e0f8 XL |
166 | vector_type.get_element_type() |
167 | } | |
168 | else if let Some(typ) = ty.get_pointee() { | |
169 | typ | |
170 | } | |
171 | else { | |
172 | unreachable!() | |
173 | } | |
174 | } | |
175 | ||
176 | fn vector_length(&self, _ty: Type<'gcc>) -> usize { | |
177 | unimplemented!(); | |
178 | } | |
179 | ||
180 | fn float_width(&self, typ: Type<'gcc>) -> usize { | |
181 | let f32 = self.context.new_type::<f32>(); | |
182 | let f64 = self.context.new_type::<f64>(); | |
923072b8 | 183 | if typ.is_compatible_with(f32) { |
c295e0f8 XL |
184 | 32 |
185 | } | |
923072b8 | 186 | else if typ.is_compatible_with(f64) { |
c295e0f8 XL |
187 | 64 |
188 | } | |
189 | else { | |
190 | panic!("Cannot get width of float type {:?}", typ); | |
191 | } | |
192 | // TODO(antoyo): support other sizes. | |
193 | } | |
194 | ||
195 | fn int_width(&self, typ: Type<'gcc>) -> u64 { | |
5e7ed085 | 196 | self.gcc_int_width(typ) |
c295e0f8 XL |
197 | } |
198 | ||
199 | fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> { | |
200 | value.get_type() | |
201 | } | |
487cf647 | 202 | |
353b0b11 FG |
203 | fn type_array(&self, ty: Type<'gcc>, len: u64) -> Type<'gcc> { |
204 | // TODO: remove this as well? | |
205 | /*if let Some(struct_type) = ty.is_struct() { | |
487cf647 FG |
206 | if struct_type.get_field_count() == 0 { |
207 | // NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a | |
208 | // size of usize::MAX in test_binary_search, we workaround this by setting the size to | |
209 | // zero for ZSTs. | |
210 | // FIXME(antoyo): fix gccjit API. | |
211 | len = 0; | |
212 | } | |
353b0b11 | 213 | }*/ |
487cf647 FG |
214 | |
215 | self.context.new_array_type(None, ty, len) | |
216 | } | |
c295e0f8 XL |
217 | } |
218 | ||
219 | impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { | |
220 | pub fn type_padding_filler(&self, size: Size, align: Align) -> Type<'gcc> { | |
221 | let unit = Integer::approximate_align(self, align); | |
222 | let size = size.bytes(); | |
223 | let unit_size = unit.size().bytes(); | |
224 | assert_eq!(size % unit_size, 0); | |
225 | self.type_array(self.type_from_integer(unit), size / unit_size) | |
226 | } | |
227 | ||
923072b8 | 228 | pub fn set_struct_body(&self, typ: Struct<'gcc>, fields: &[Type<'gcc>], packed: bool) { |
c295e0f8 XL |
229 | let fields: Vec<_> = fields.iter().enumerate() |
230 | .map(|(index, field)| self.context.new_field(None, *field, &format!("field_{}", index))) | |
231 | .collect(); | |
232 | typ.set_fields(None, &fields); | |
923072b8 FG |
233 | if packed { |
234 | #[cfg(feature="master")] | |
235 | typ.as_type().set_packed(); | |
236 | } | |
c295e0f8 XL |
237 | } |
238 | ||
239 | pub fn type_named_struct(&self, name: &str) -> Struct<'gcc> { | |
240 | self.context.new_opaque_struct_type(None, name) | |
241 | } | |
c295e0f8 XL |
242 | } |
243 | ||
244 | pub fn struct_fields<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout<'tcx>) -> (Vec<Type<'gcc>>, bool) { | |
245 | let field_count = layout.fields.count(); | |
246 | ||
247 | let mut packed = false; | |
248 | let mut offset = Size::ZERO; | |
249 | let mut prev_effective_align = layout.align.abi; | |
250 | let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2); | |
251 | for i in layout.fields.index_by_increasing_offset() { | |
252 | let target_offset = layout.fields.offset(i as usize); | |
253 | let field = layout.field(cx, i); | |
254 | let effective_field_align = | |
255 | layout.align.abi.min(field.align.abi).restrict_for_offset(target_offset); | |
256 | packed |= effective_field_align < field.align.abi; | |
257 | ||
258 | assert!(target_offset >= offset); | |
259 | let padding = target_offset - offset; | |
260 | let padding_align = prev_effective_align.min(effective_field_align); | |
261 | assert_eq!(offset.align_to(padding_align) + padding, target_offset); | |
262 | result.push(cx.type_padding_filler(padding, padding_align)); | |
263 | ||
353b0b11 | 264 | result.push(field.gcc_type(cx)); |
c295e0f8 XL |
265 | offset = target_offset + field.size; |
266 | prev_effective_align = effective_field_align; | |
267 | } | |
487cf647 | 268 | if layout.is_sized() && field_count > 0 { |
c295e0f8 XL |
269 | if offset > layout.size { |
270 | bug!("layout: {:#?} stride: {:?} offset: {:?}", layout, layout.size, offset); | |
271 | } | |
272 | let padding = layout.size - offset; | |
273 | let padding_align = prev_effective_align; | |
274 | assert_eq!(offset.align_to(padding_align) + padding, layout.size); | |
275 | result.push(cx.type_padding_filler(padding, padding_align)); | |
276 | assert_eq!(result.len(), 1 + field_count * 2); | |
277 | } | |
278 | ||
279 | (result, packed) | |
280 | } | |
064997fb FG |
281 | |
282 | impl<'gcc, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'gcc, 'tcx> { | |
064997fb | 283 | } |