Skip to content

Commit cc2f018

Browse files
eddybsw17ch
authored andcommitted
rustc_target: treat enum variants like union members, in call ABIs.
1 parent d8d737b commit cc2f018

File tree

3 files changed

+37
-11
lines changed

3 files changed

+37
-11
lines changed

src/librustc_target/abi/call/mod.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ impl<'a, Ty> TyLayout<'a, Ty> {
308308

309309
Abi::ScalarPair(..) | Abi::Aggregate { .. } => {
310310
// Helper for computing `homogenous_aggregate`, allowing a custom
311-
// starting offset (TODO(eddyb): use this to handle variants).
311+
// starting offset (used below for handling variants).
312312
let from_fields_at =
313313
|layout: Self,
314314
start: Size|
@@ -354,6 +354,24 @@ impl<'a, Ty> TyLayout<'a, Ty> {
354354

355355
let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;
356356

357+
match &self.variants {
358+
abi::Variants::Single { .. } => {}
359+
abi::Variants::Multiple { variants, .. } => {
360+
// Treat enum variants like union members.
361+
// HACK(eddyb) pretend the `enum` field (discriminant)
362+
// is at the start of every variant (otherwise the gap
363+
// at the start of all variants would disqualify them).
364+
let variant_start = total;
365+
for variant_idx in variants.indices() {
366+
let (variant_result, variant_total) =
367+
from_fields_at(self.for_variant(cx, variant_idx), variant_start)?;
368+
369+
result = result.merge(variant_result)?;
370+
total = total.max(variant_total);
371+
}
372+
}
373+
}
374+
357375
// There needs to be no padding.
358376
if total != self.size {
359377
Err(Heterogeneous)

src/librustc_target/abi/call/x86_64.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,24 @@ where
5656

5757
Abi::Vector { .. } => Class::Sse,
5858

59-
Abi::ScalarPair(..) | Abi::Aggregate { .. } => match layout.variants {
60-
abi::Variants::Single { .. } => {
61-
for i in 0..layout.fields.count() {
62-
let field_off = off + layout.fields.offset(i);
63-
classify(cx, layout.field(cx, i), cls, field_off)?;
59+
Abi::ScalarPair(..) | Abi::Aggregate { .. } => {
60+
for i in 0..layout.fields.count() {
61+
let field_off = off + layout.fields.offset(i);
62+
classify(cx, layout.field(cx, i), cls, field_off)?;
63+
}
64+
65+
match &layout.variants {
66+
abi::Variants::Single { .. } => {}
67+
abi::Variants::Multiple { variants, .. } => {
68+
// Treat enum variants like union members.
69+
for variant_idx in variants.indices() {
70+
classify(cx, layout.for_variant(cx, variant_idx), cls, off)?;
71+
}
6472
}
65-
return Ok(());
6673
}
67-
abi::Variants::Multiple { .. } => return Err(Memory),
68-
},
74+
75+
return Ok(());
76+
}
6977
};
7078

7179
// Fill in `cls` for scalars (Int/Sse) and vectors (Sse).

src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/nonclike.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ pub enum T {
1414
}
1515

1616
extern "C" {
17-
pub fn t_add(a: T) -> u64;
17+
pub fn t_add(a: T, b: T) -> u64;
1818
pub fn tt_add(a: TT, b: TT) -> u64;
1919
}
2020

2121
fn main() {
2222
assert_eq!(33, unsafe { tt_add(TT::AA(1,2), TT::AA(10,20)) });
23-
assert_eq!(11, unsafe { t_add(T::A(1)) });
23+
assert_eq!(11, unsafe { t_add(T::A(1), T::A(10)) });
2424
}

0 commit comments

Comments
 (0)