Skip to content

Commit 8f81593

Browse files
committed
rustc_target: switch homogeneous_aggregate to returning Result.
1 parent 1d28952 commit 8f81593

13 files changed

+108
-89
lines changed

src/librustc_target/abi/call/aarch64.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ where
66
Ty: TyLayoutMethods<'a, C> + Copy,
77
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout,
88
{
9-
arg.layout.homogeneous_aggregate(cx).unit().and_then(|unit| {
9+
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
1010
let size = arg.layout.size;
1111

1212
// Ensure we have at most four uniquely addressable members.

src/librustc_target/abi/call/arm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ where
77
Ty: TyLayoutMethods<'a, C> + Copy,
88
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout,
99
{
10-
arg.layout.homogeneous_aggregate(cx).unit().and_then(|unit| {
10+
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
1111
let size = arg.layout.size;
1212

1313
// Ensure we have at most four uniquely addressable members.

src/librustc_target/abi/call/mod.rs

+80-61
Original file line numberDiff line numberDiff line change
@@ -219,26 +219,47 @@ impl CastTarget {
219219
}
220220
}
221221

222-
/// Returns value from the `homogeneous_aggregate` test function.
222+
/// Return value from the `homogeneous_aggregate` test function.
223223
#[derive(Copy, Clone, Debug)]
224224
pub enum HomogeneousAggregate {
225225
/// Yes, all the "leaf fields" of this struct are passed in the
226226
/// same way (specified in the `Reg` value).
227227
Homogeneous(Reg),
228228

229-
/// There are distinct leaf fields passed in different ways,
230-
/// or this is uninhabited.
231-
Heterogeneous,
232-
233229
/// There are no leaf fields at all.
234230
NoData,
235231
}
236232

233+
/// Error from the `homogeneous_aggregate` test function, indicating
234+
/// there are distinct leaf fields passed in different ways,
235+
/// or this is uninhabited.
236+
#[derive(Copy, Clone, Debug)]
237+
pub struct Heterogeneous;
238+
237239
impl HomogeneousAggregate {
238240
/// If this is a homogeneous aggregate, returns the homogeneous
239241
/// unit, else `None`.
240242
pub fn unit(self) -> Option<Reg> {
241-
if let HomogeneousAggregate::Homogeneous(r) = self { Some(r) } else { None }
243+
match self {
244+
HomogeneousAggregate::Homogeneous(reg) => Some(reg),
245+
HomogeneousAggregate::NoData => None,
246+
}
247+
}
248+
249+
/// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in
250+
/// the same `struct`. Only succeeds if only one of them has any data,
251+
/// or both units are identical.
252+
fn merge(self, other: HomogeneousAggregate) -> Result<HomogeneousAggregate, Heterogeneous> {
253+
match (self, other) {
254+
(x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x),
255+
256+
(HomogeneousAggregate::Homogeneous(a), HomogeneousAggregate::Homogeneous(b)) => {
257+
if a != b {
258+
return Err(Heterogeneous);
259+
}
260+
Ok(self)
261+
}
262+
}
242263
}
243264
}
244265

@@ -250,8 +271,8 @@ impl<'a, Ty> TyLayout<'a, Ty> {
250271
}
251272
}
252273

253-
/// Returns `true` if this layout is an aggregate containing fields of only
254-
/// a single type (e.g., `(u32, u32)`). Such aggregates are often
274+
/// Returns `Homogeneous` if this layout is an aggregate containing fields of
275+
/// only a single type (e.g., `(u32, u32)`). Such aggregates are often
255276
/// special-cased in ABIs.
256277
///
257278
/// Note: We generally ignore fields of zero-sized type when computing
@@ -260,94 +281,92 @@ impl<'a, Ty> TyLayout<'a, Ty> {
260281
/// This is public so that it can be used in unit tests, but
261282
/// should generally only be relevant to the ABI details of
262283
/// specific targets.
263-
pub fn homogeneous_aggregate<C>(&self, cx: &C) -> HomogeneousAggregate
284+
pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous>
264285
where
265286
Ty: TyLayoutMethods<'a, C> + Copy,
266287
C: LayoutOf<Ty = Ty, TyLayout = Self>,
267288
{
268289
match self.abi {
269-
Abi::Uninhabited => HomogeneousAggregate::Heterogeneous,
290+
Abi::Uninhabited => Err(Heterogeneous),
270291

271292
// The primitive for this algorithm.
272293
Abi::Scalar(ref scalar) => {
273294
let kind = match scalar.value {
274295
abi::Int(..) | abi::Pointer => RegKind::Integer,
275296
abi::F32 | abi::F64 => RegKind::Float,
276297
};
277-
HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size })
298+
Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
278299
}
279300

280301
Abi::Vector { .. } => {
281302
assert!(!self.is_zst());
282-
HomogeneousAggregate::Homogeneous(Reg { kind: RegKind::Vector, size: self.size })
303+
Ok(HomogeneousAggregate::Homogeneous(Reg {
304+
kind: RegKind::Vector,
305+
size: self.size,
306+
}))
283307
}
284308

285309
Abi::ScalarPair(..) | Abi::Aggregate { .. } => {
286-
let mut total = Size::ZERO;
287-
let mut result = None;
288-
289-
let is_union = match self.fields {
290-
FieldPlacement::Array { count, .. } => {
291-
if count > 0 {
292-
return self.field(cx, 0).homogeneous_aggregate(cx);
293-
} else {
294-
return HomogeneousAggregate::NoData;
295-
}
296-
}
297-
FieldPlacement::Union(_) => true,
298-
FieldPlacement::Arbitrary { .. } => false,
299-
};
310+
// Helper for computing `homogenous_aggregate`, allowing a custom
311+
// starting offset (TODO(eddyb): use this to handle variants).
312+
let from_fields_at =
313+
|layout: Self,
314+
start: Size|
315+
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
316+
let is_union = match layout.fields {
317+
FieldPlacement::Array { count, .. } => {
318+
assert_eq!(start, Size::ZERO);
319+
320+
let result = if count > 0 {
321+
layout.field(cx, 0).homogeneous_aggregate(cx)?
322+
} else {
323+
HomogeneousAggregate::NoData
324+
};
325+
return Ok((result, layout.size));
326+
}
327+
FieldPlacement::Union(_) => true,
328+
FieldPlacement::Arbitrary { .. } => false,
329+
};
300330

301-
for i in 0..self.fields.count() {
302-
if !is_union && total != self.fields.offset(i) {
303-
return HomogeneousAggregate::Heterogeneous;
304-
}
331+
let mut result = HomogeneousAggregate::NoData;
332+
let mut total = start;
305333

306-
let field = self.field(cx, i);
334+
for i in 0..layout.fields.count() {
335+
if !is_union && total != layout.fields.offset(i) {
336+
return Err(Heterogeneous);
337+
}
307338

308-
match (result, field.homogeneous_aggregate(cx)) {
309-
(_, HomogeneousAggregate::NoData) => {
310-
// Ignore fields that have no data
311-
}
312-
(_, HomogeneousAggregate::Heterogeneous) => {
313-
// The field itself must be a homogeneous aggregate.
314-
return HomogeneousAggregate::Heterogeneous;
315-
}
316-
// If this is the first field, record the unit.
317-
(None, HomogeneousAggregate::Homogeneous(unit)) => {
318-
result = Some(unit);
319-
}
320-
// For all following fields, the unit must be the same.
321-
(Some(prev_unit), HomogeneousAggregate::Homogeneous(unit)) => {
322-
if prev_unit != unit {
323-
return HomogeneousAggregate::Heterogeneous;
339+
let field = layout.field(cx, i);
340+
341+
result = result.merge(field.homogeneous_aggregate(cx)?)?;
342+
343+
// Keep track of the offset (without padding).
344+
let size = field.size;
345+
if is_union {
346+
total = total.max(size);
347+
} else {
348+
total += size;
324349
}
325350
}
326-
}
327351

328-
// Keep track of the offset (without padding).
329-
let size = field.size;
330-
if is_union {
331-
total = total.max(size);
332-
} else {
333-
total += size;
334-
}
335-
}
352+
Ok((result, total))
353+
};
354+
355+
let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;
336356

337357
// There needs to be no padding.
338358
if total != self.size {
339-
HomogeneousAggregate::Heterogeneous
359+
Err(Heterogeneous)
340360
} else {
341361
match result {
342-
Some(reg) => {
362+
HomogeneousAggregate::Homogeneous(_) => {
343363
assert_ne!(total, Size::ZERO);
344-
HomogeneousAggregate::Homogeneous(reg)
345364
}
346-
None => {
365+
HomogeneousAggregate::NoData => {
347366
assert_eq!(total, Size::ZERO);
348-
HomogeneousAggregate::NoData
349367
}
350368
}
369+
Ok(result)
351370
}
352371
}
353372
}

src/librustc_target/abi/call/powerpc64.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ where
2222
Ty: TyLayoutMethods<'a, C> + Copy,
2323
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout,
2424
{
25-
arg.layout.homogeneous_aggregate(cx).unit().and_then(|unit| {
25+
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
2626
// ELFv1 only passes one-member aggregates transparently.
2727
// ELFv2 passes up to eight uniquely addressable members.
2828
if (abi == ELFv1 && arg.layout.size > unit.size)

src/librustc_target/abi/call/sparc64.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ where
88
Ty: TyLayoutMethods<'a, C> + Copy,
99
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout,
1010
{
11-
arg.layout.homogeneous_aggregate(cx).unit().and_then(|unit| {
11+
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
1212
// Ensure we have at most eight uniquely addressable members.
1313
if arg.layout.size > unit.size.checked_mul(8, cx).unwrap() {
1414
return None;

src/librustc_target/abi/call/wasm32.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ where
77
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout,
88
{
99
if val.layout.is_aggregate() {
10-
if let Some(unit) = val.layout.homogeneous_aggregate(cx).unit() {
10+
if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) {
1111
let size = val.layout.size;
1212
if unit.size == size {
1313
val.cast_to(Uniform { unit, total: size });

src/librustc_target/abi/call/x86.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ where
100100
};
101101

102102
// At this point we know this must be a primitive of sorts.
103-
let unit = arg.layout.homogeneous_aggregate(cx).unit().unwrap();
103+
let unit = arg.layout.homogeneous_aggregate(cx).unwrap().unit().unwrap();
104104
assert_eq!(unit.size, arg.layout.size);
105105
if unit.kind == RegKind::Float {
106106
continue;

src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub struct Middle {
2020

2121
#[rustc_layout(homogeneous_aggregate)]
2222
pub type TestMiddle = Middle;
23-
//~^ ERROR homogeneous_aggregate: Homogeneous
23+
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
2424

2525
#[repr(C)]
2626
pub struct Final {
@@ -31,6 +31,6 @@ pub struct Final {
3131

3232
#[rustc_layout(homogeneous_aggregate)]
3333
pub type TestFinal = Final;
34-
//~^ ERROR homogeneous_aggregate: Homogeneous
34+
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
3535

3636
fn main() { }

src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
1+
error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
22
--> $DIR/homogeneous-aggr-zero-sized-c-struct.rs:22:1
33
|
44
LL | pub type TestMiddle = Middle;
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66

7-
error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
7+
error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
88
--> $DIR/homogeneous-aggr-zero-sized-c-struct.rs:33:1
99
|
1010
LL | pub type TestFinal = Final;

src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,22 @@ pub struct WithEmptyRustEnum {
5252

5353
#[rustc_layout(homogeneous_aggregate)]
5454
pub type Test1 = BaseCase;
55-
//~^ ERROR homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
55+
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
5656

5757
#[rustc_layout(homogeneous_aggregate)]
5858
pub type Test2 = WithPhantomData;
59-
//~^ ERROR homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
59+
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
6060

6161
#[rustc_layout(homogeneous_aggregate)]
6262
pub type Test3 = WithEmptyRustStruct;
63-
//~^ ERROR homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
63+
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
6464

6565
#[rustc_layout(homogeneous_aggregate)]
6666
pub type Test4 = WithTransitivelyEmptyRustStruct;
67-
//~^ ERROR homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
67+
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
6868

6969
#[rustc_layout(homogeneous_aggregate)]
7070
pub type Test5 = WithEmptyRustEnum;
71-
//~^ ERROR homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
71+
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
7272

7373
fn main() { }

src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
1+
error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
22
--> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:54:1
33
|
44
LL | pub type Test1 = BaseCase;
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
66

7-
error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
7+
error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
88
--> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:58:1
99
|
1010
LL | pub type Test2 = WithPhantomData;
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

13-
error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
13+
error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
1414
--> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:62:1
1515
|
1616
LL | pub type Test3 = WithEmptyRustStruct;
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818

19-
error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
19+
error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
2020
--> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:66:1
2121
|
2222
LL | pub type Test4 = WithTransitivelyEmptyRustStruct;
2323
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2424

25-
error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
25+
error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } }))
2626
--> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:70:1
2727
|
2828
LL | pub type Test5 = WithEmptyRustEnum;

src/test/ui/layout/zero-sized-array-union.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct Baz1 {
5757

5858
#[rustc_layout(homogeneous_aggregate)]
5959
type TestBaz1 = Baz1;
60-
//~^ ERROR homogeneous_aggregate: Homogeneous
60+
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
6161

6262
#[repr(C)]
6363
struct Baz2 {
@@ -68,7 +68,7 @@ struct Baz2 {
6868

6969
#[rustc_layout(homogeneous_aggregate)]
7070
type TestBaz2 = Baz2;
71-
//~^ ERROR homogeneous_aggregate: Homogeneous
71+
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
7272

7373
#[repr(C)]
7474
struct Baz3 {
@@ -79,7 +79,7 @@ struct Baz3 {
7979

8080
#[rustc_layout(homogeneous_aggregate)]
8181
type TestBaz3 = Baz3;
82-
//~^ ERROR homogeneous_aggregate: Homogeneous
82+
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
8383

8484
#[repr(C)]
8585
struct Baz4 {
@@ -90,6 +90,6 @@ struct Baz4 {
9090

9191
#[rustc_layout(homogeneous_aggregate)]
9292
type TestBaz4 = Baz4;
93-
//~^ ERROR homogeneous_aggregate: Homogeneous
93+
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
9494

9595
fn main() { }

0 commit comments

Comments
 (0)