Fix a crash for 11 single byte fields passed through the C abi

Fixes #1234
This commit is contained in:
bjorn3 2022-06-28 14:31:32 +00:00
parent c1ac2df0c3
commit 45b6cd6a8a
2 changed files with 37 additions and 20 deletions

View File

@ -124,6 +124,23 @@ fn call_return_u128_pair() {
return_u128_pair(); return_u128_pair();
} }
#[repr(C)]
pub struct bool_11 {
field0: bool,
field1: bool,
field2: bool,
field3: bool,
field4: bool,
field5: bool,
field6: bool,
field7: bool,
field8: bool,
field9: bool,
field10: bool,
}
extern "C" fn bool_struct_in_11(arg0: bool_11) {}
#[allow(unreachable_code)] // FIXME false positive #[allow(unreachable_code)] // FIXME false positive
fn main() { fn main() {
take_unique(Unique { take_unique(Unique {
@ -134,6 +151,20 @@ fn main() {
call_return_u128_pair(); call_return_u128_pair();
bool_struct_in_11(bool_11 {
field0: true,
field1: true,
field2: true,
field3: true,
field4: true,
field5: true,
field6: true,
field7: true,
field8: true,
field9: true,
field10: true,
});
let slice = &[0, 1] as &[i32]; let slice = &[0, 1] as &[i32];
let slice_ptr = slice as *const [i32] as *const i32; let slice_ptr = slice as *const [i32] as *const i32;

View File

@ -18,9 +18,9 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam {
let clif_ty = match (reg.kind, reg.size.bytes()) { let clif_ty = match (reg.kind, reg.size.bytes()) {
(RegKind::Integer, 1) => types::I8, (RegKind::Integer, 1) => types::I8,
(RegKind::Integer, 2) => types::I16, (RegKind::Integer, 2) => types::I16,
(RegKind::Integer, 4) => types::I32, (RegKind::Integer, 3..=4) => types::I32,
(RegKind::Integer, 8) => types::I64, (RegKind::Integer, 5..=8) => types::I64,
(RegKind::Integer, 16) => types::I128, (RegKind::Integer, 9..=16) => types::I128,
(RegKind::Float, 4) => types::F32, (RegKind::Float, 4) => types::F32,
(RegKind::Float, 8) => types::F64, (RegKind::Float, 8) => types::F64,
(RegKind::Vector, size) => types::I8.by(u16::try_from(size).unwrap()).unwrap(), (RegKind::Vector, size) => types::I8.by(u16::try_from(size).unwrap()).unwrap(),
@ -48,23 +48,9 @@ fn cast_target_to_abi_params(cast: CastTarget) -> SmallVec<[AbiParam; 2]> {
) )
}; };
if cast.prefix.iter().all(|x| x.is_none()) { // Note: Unlike the LLVM equivalent of this code we don't have separate branches for when there
// Simplify to a single unit when there is no prefix and size <= unit size // is no prefix as a single unit, an array and a heterogeneous struct are not represented using
if cast.rest.total <= cast.rest.unit.size { // different types in Cranelift IR. Instead a single array of primitive types is used.
let clif_ty = match (cast.rest.unit.kind, cast.rest.unit.size.bytes()) {
(RegKind::Integer, 1) => types::I8,
(RegKind::Integer, 2) => types::I16,
(RegKind::Integer, 3..=4) => types::I32,
(RegKind::Integer, 5..=8) => types::I64,
(RegKind::Integer, 9..=16) => types::I128,
(RegKind::Float, 4) => types::F32,
(RegKind::Float, 8) => types::F64,
(RegKind::Vector, size) => types::I8.by(u16::try_from(size).unwrap()).unwrap(),
_ => unreachable!("{:?}", cast.rest.unit),
};
return smallvec![AbiParam::new(clif_ty)];
}
}
// Create list of fields in the main structure // Create list of fields in the main structure
let mut args = cast let mut args = cast