]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_gcc/src/type_.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_codegen_gcc / src / type_.rs
CommitLineData
c295e0f8 1use gccjit::{RValue, Struct, Type};
064997fb 2use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, TypeMembershipMethods};
c295e0f8 3use rustc_codegen_ssa::common::TypeKind;
923072b8 4use rustc_middle::{bug, ty};
c295e0f8
XL
5use rustc_middle::ty::layout::TyAndLayout;
6use rustc_target::abi::{AddressSpace, Align, Integer, Size};
7
923072b8 8use crate::common::TypeReflection;
c295e0f8
XL
9use crate::context::CodegenCx;
10use crate::type_of::LayoutGccExt;
11
12impl<'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
75impl<'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
219impl<'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
244pub 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
282impl<'gcc, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
064997fb 283}