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