Skip to content

Commit 45b6cd6

Browse files
committed
Fix a crash for 11 single byte fields passed through the C abi
Fixes rust-lang#1234
1 parent c1ac2df commit 45b6cd6

File tree

2 files changed

+37
-20
lines changed

2 files changed

+37
-20
lines changed

example/mini_core_hello_world.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,23 @@ fn call_return_u128_pair() {
124124
return_u128_pair();
125125
}
126126

127+
#[repr(C)]
128+
pub struct bool_11 {
129+
field0: bool,
130+
field1: bool,
131+
field2: bool,
132+
field3: bool,
133+
field4: bool,
134+
field5: bool,
135+
field6: bool,
136+
field7: bool,
137+
field8: bool,
138+
field9: bool,
139+
field10: bool,
140+
}
141+
142+
extern "C" fn bool_struct_in_11(arg0: bool_11) {}
143+
127144
#[allow(unreachable_code)] // FIXME false positive
128145
fn main() {
129146
take_unique(Unique {
@@ -134,6 +151,20 @@ fn main() {
134151

135152
call_return_u128_pair();
136153

154+
bool_struct_in_11(bool_11 {
155+
field0: true,
156+
field1: true,
157+
field2: true,
158+
field3: true,
159+
field4: true,
160+
field5: true,
161+
field6: true,
162+
field7: true,
163+
field8: true,
164+
field9: true,
165+
field10: true,
166+
});
167+
137168
let slice = &[0, 1] as &[i32];
138169
let slice_ptr = slice as *const [i32] as *const i32;
139170

src/abi/pass_mode.rs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam {
1818
let clif_ty = match (reg.kind, reg.size.bytes()) {
1919
(RegKind::Integer, 1) => types::I8,
2020
(RegKind::Integer, 2) => types::I16,
21-
(RegKind::Integer, 4) => types::I32,
22-
(RegKind::Integer, 8) => types::I64,
23-
(RegKind::Integer, 16) => types::I128,
21+
(RegKind::Integer, 3..=4) => types::I32,
22+
(RegKind::Integer, 5..=8) => types::I64,
23+
(RegKind::Integer, 9..=16) => types::I128,
2424
(RegKind::Float, 4) => types::F32,
2525
(RegKind::Float, 8) => types::F64,
2626
(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]> {
4848
)
4949
};
5050

51-
if cast.prefix.iter().all(|x| x.is_none()) {
52-
// Simplify to a single unit when there is no prefix and size <= unit size
53-
if cast.rest.total <= cast.rest.unit.size {
54-
let clif_ty = match (cast.rest.unit.kind, cast.rest.unit.size.bytes()) {
55-
(RegKind::Integer, 1) => types::I8,
56-
(RegKind::Integer, 2) => types::I16,
57-
(RegKind::Integer, 3..=4) => types::I32,
58-
(RegKind::Integer, 5..=8) => types::I64,
59-
(RegKind::Integer, 9..=16) => types::I128,
60-
(RegKind::Float, 4) => types::F32,
61-
(RegKind::Float, 8) => types::F64,
62-
(RegKind::Vector, size) => types::I8.by(u16::try_from(size).unwrap()).unwrap(),
63-
_ => unreachable!("{:?}", cast.rest.unit),
64-
};
65-
return smallvec![AbiParam::new(clif_ty)];
66-
}
67-
}
51+
// Note: Unlike the LLVM equivalent of this code we don't have separate branches for when there
52+
// is no prefix as a single unit, an array and a heterogeneous struct are not represented using
53+
// different types in Cranelift IR. Instead a single array of primitive types is used.
6854

6955
// Create list of fields in the main structure
7056
let mut args = cast

0 commit comments

Comments
 (0)