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