diff options
| author | bjorn3 <17426603+bjorn3@users.noreply.github.com> | 2022-06-28 14:31:32 +0000 |
|---|---|---|
| committer | bjorn3 <17426603+bjorn3@users.noreply.github.com> | 2022-06-28 14:32:31 +0000 |
| commit | 45b6cd6a8a2a3b364d22d4fabc0d72f9e37e3e50 (patch) | |
| tree | 8eb8a2815490bf10493c54966cc28f77ca22359b | |
| parent | c1ac2df0c39ed12a4f4590319fb7b8045a5db5e5 (diff) | |
| download | rust-45b6cd6a8a2a3b364d22d4fabc0d72f9e37e3e50.tar.gz rust-45b6cd6a8a2a3b364d22d4fabc0d72f9e37e3e50.zip | |
Fix a crash for 11 single byte fields passed through the C abi
Fixes #1234
| -rw-r--r-- | example/mini_core_hello_world.rs | 31 | ||||
| -rw-r--r-- | src/abi/pass_mode.rs | 26 |
2 files changed, 37 insertions, 20 deletions
diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 0f1245c2758..6111e035282 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -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; diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 9f0bd31e95f..33c5f3283be 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -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 |
