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();
}
#[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
fn main() {
take_unique(Unique {
@ -134,6 +151,20 @@ fn main() {
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_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()) {
(RegKind::Integer, 1) => types::I8,
(RegKind::Integer, 2) => types::I16,
(RegKind::Integer, 4) => types::I32,
(RegKind::Integer, 8) => types::I64,
(RegKind::Integer, 16) => types::I128,
(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(),
@ -48,23 +48,9 @@ fn cast_target_to_abi_params(cast: CastTarget) -> SmallVec<[AbiParam; 2]> {
)
};
if cast.prefix.iter().all(|x| x.is_none()) {
// Simplify to a single unit when there is no prefix and size <= unit size
if cast.rest.total <= cast.rest.unit.size {
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)];
}
}
// Note: Unlike the LLVM equivalent of this code we don't have separate branches for when there
// is no prefix as a single unit, an array and a heterogeneous struct are not represented using
// different types in Cranelift IR. Instead a single array of primitive types is used.
// Create list of fields in the main structure
let mut args = cast