Skip to content

Commit 66ae0b2

Browse files
committed
Implement integer cast for unsupported integer types
1 parent e46e3dd commit 66ae0b2

File tree

2 files changed

+99
-6
lines changed

2 files changed

+99
-6
lines changed

src/builder.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,8 +1053,35 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
10531053
self.cx.context.new_cast(None, value, dest_typ)
10541054
}
10551055
else {
1056-
// FIXME: that's not working since we can cast from u8 to struct u128.
1057-
self.cx.context.new_bitcast(None, value, dest_typ)
1056+
let value_type = value.get_type();
1057+
let src_size = self.cx.int_type_size(value_type);
1058+
let src_element_size = self.cx.int_type_element_size(value_type);
1059+
let dest_size = self.cx.int_type_size(dest_typ);
1060+
let factor = (dest_size / src_size) as usize;
1061+
let array_type = self.context.new_array_type(None, value_type, factor as i32);
1062+
1063+
if src_size < dest_size {
1064+
// TODO: initialize to -1 if negative.
1065+
let mut values = vec![self.context.new_rvalue_zero(value_type); factor];
1066+
// TODO: take endianness into account.
1067+
values[factor - 1] = value;
1068+
let array_value = self.context.new_rvalue_from_array(None, array_type, &values);
1069+
self.cx.context.new_bitcast(None, array_value, dest_typ)
1070+
}
1071+
else {
1072+
let mut current_size = 0;
1073+
// TODO: take endianness into account.
1074+
let mut current_index = src_size / src_element_size - 1;
1075+
let mut values = vec![];
1076+
while current_size < dest_size {
1077+
values.push(self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, current_index as i32)).to_rvalue());
1078+
current_size += src_element_size;
1079+
current_index -= 1;
1080+
}
1081+
let array_value = self.context.new_rvalue_from_array(None, array_type, &values);
1082+
// FIXME: that's not working since we can cast from u8 to struct u128.
1083+
self.cx.context.new_bitcast(None, array_value, dest_typ)
1084+
}
10581085
}
10591086
}
10601087

src/context.rs

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub struct FuncSig<'gcc> {
3838

3939
pub struct IntType<'gcc> {
4040
bits: u8,
41+
element_size: u8,
4142
typ: Type<'gcc>,
4243
signed: bool,
4344
}
@@ -79,6 +80,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
7980
pub sizet_type: Type<'gcc>,
8081

8182
pub native_int_types: Vec<IntType<'gcc>>,
83+
pub non_native_int_types: Vec<IntType<'gcc>>,
8284

8385
pub float_type: Type<'gcc>,
8486
pub double_type: Type<'gcc>,
@@ -141,9 +143,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
141143
let u32_type = context.new_c_type(CType::UInt32t);
142144
let u64_type = context.new_c_type(CType::UInt64t);
143145

144-
let field1 = context.new_field(None, u64_type, "high");
145-
let field2 = context.new_field(None, u64_type, "low");
146-
let u128_type = context.new_struct_type(None, "u128", &[field1, field2]).as_type();
146+
let u128_type = context.new_array_type(None, u64_type, 2);
147147
//let u128_type = context.new_c_type(CType::UInt128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?
148148

149149
let tls_model = to_gcc_tls_mode(tcx.sess.tls_model());
@@ -158,52 +158,87 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
158158
let ulonglong_type = context.new_c_type(CType::ULongLong);
159159
let sizet_type = context.new_c_type(CType::SizeT);
160160

161+
let mut non_native_int_types = vec![];
162+
163+
non_native_int_types.push(IntType {
164+
bits: 128,
165+
element_size: 64,
166+
signed: false,
167+
typ: u128_type,
168+
});
169+
161170
let mut native_int_types = vec![];
162171

163172
native_int_types.push(IntType {
164173
bits: 64,
174+
element_size: 64,
165175
signed: false,
166176
typ: u64_type,
167177
});
168178
native_int_types.push(IntType {
169179
bits: 64,
180+
element_size: 64,
170181
signed: true,
171182
typ: i64_type,
172183
});
173184

174185
native_int_types.push(IntType {
175186
bits: 32,
187+
element_size: 32,
176188
signed: false,
177189
typ: u32_type,
178190
});
179191
native_int_types.push(IntType {
180192
bits: 32,
193+
element_size: 32,
181194
signed: true,
182195
typ: i32_type,
183196
});
184197

185198
native_int_types.push(IntType {
186199
bits: 16,
200+
element_size: 16,
187201
signed: false,
188202
typ: u16_type,
189203
});
190204
native_int_types.push(IntType {
191205
bits: 16,
206+
element_size: 16,
192207
signed: true,
193208
typ: i16_type,
194209
});
195210

196211
native_int_types.push(IntType {
197212
bits: 8,
213+
element_size: 8,
198214
signed: false,
199215
typ: u8_type,
200216
});
201217
native_int_types.push(IntType {
202218
bits: 8,
219+
element_size: 8,
203220
signed: true,
204221
typ: i8_type,
205222
});
206223

224+
let mut new_native_int_types = vec![];
225+
let int_types = [isize_type, usize_type, int_type, uint_type, long_type, ulong_type, ulonglong_type, sizet_type];
226+
for int_type in int_types {
227+
for native_int_type in &native_int_types {
228+
if int_type.is_compatible_with(native_int_type.typ) {
229+
new_native_int_types.push(IntType {
230+
bits: native_int_type.bits,
231+
element_size: native_int_type.element_size,
232+
signed: native_int_type.signed,
233+
typ: int_type,
234+
});
235+
break;
236+
}
237+
}
238+
}
239+
240+
native_int_types.extend(new_native_int_types);
241+
207242
// TODO(antoyo): only have those assertions on x86_64.
208243
assert_eq!(isize_type.get_size(), i64_type.get_size());
209244
assert_eq!(usize_type.get_size(), u64_type.get_size());
@@ -257,6 +292,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
257292
sizet_type,
258293

259294
native_int_types,
295+
non_native_int_types,
260296

261297
float_type,
262298
double_type,
@@ -290,13 +326,43 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
290326

291327
pub fn supports_native_int_type(&self, typ: Type<'gcc>) -> bool {
292328
for native_type in &self.native_int_types {
293-
if native_type.typ == typ {
329+
if native_type.typ.is_compatible_with(typ) {
294330
return true;
295331
}
296332
}
297333
false
298334
}
299335

336+
pub fn int_type_size(&self, typ: Type<'gcc>) -> u8 {
337+
for native_type in &self.native_int_types {
338+
if native_type.typ.is_compatible_with(typ) {
339+
return native_type.bits;
340+
}
341+
}
342+
for non_native_type in &self.non_native_int_types {
343+
if non_native_type.typ.is_compatible_with(typ) {
344+
return non_native_type.bits;
345+
}
346+
}
347+
348+
panic!("{:?} not an integer type", typ);
349+
}
350+
351+
pub fn int_type_element_size(&self, typ: Type<'gcc>) -> u8 {
352+
for native_type in &self.native_int_types {
353+
if native_type.typ.is_compatible_with(typ) {
354+
return native_type.bits;
355+
}
356+
}
357+
for non_native_type in &self.non_native_int_types {
358+
if non_native_type.typ.is_compatible_with(typ) {
359+
return non_native_type.bits;
360+
}
361+
}
362+
363+
panic!("{:?} not an integer type", typ);
364+
}
365+
300366
pub fn sess(&self) -> &Session {
301367
&self.tcx.sess
302368
}

0 commit comments

Comments
 (0)