Skip to content

Commit 53a75bc

Browse files
committed
rustc: use layout::Abi::ScalarPair for structs in more cases.
1 parent 671d011 commit 53a75bc

File tree

1 file changed

+54
-42
lines changed

1 file changed

+54
-42
lines changed

src/librustc/ty/layout.rs

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,60 +1067,72 @@ impl<'a, 'tcx> CachedLayout {
10671067
packed
10681068
};
10691069

1070-
// Unpack newtype ABIs.
1071-
if sized && optimize && size.bytes() > 0 {
1072-
// All but one field must be ZSTs, and so they all start at 0.
1073-
if offsets.iter().all(|o| o.bytes() == 0) {
1074-
let mut non_zst_fields = fields.iter().filter(|f| !f.is_zst());
1075-
1076-
// We have exactly one non-ZST field.
1077-
match (non_zst_fields.next(), non_zst_fields.next()) {
1078-
(Some(field), None) => {
1079-
// Field size matches and it has a scalar or scalar pair ABI.
1080-
if size == field.size {
1070+
// Unpack newtype ABIs and find scalar pairs.
1071+
if sized && size.bytes() > 0 {
1072+
// All other fields must be ZSTs, and we need them to all start at 0.
1073+
let mut zst_offsets =
1074+
offsets.iter().enumerate().filter(|&(i, _)| fields[i].is_zst());
1075+
if zst_offsets.all(|(_, o)| o.bytes() == 0) {
1076+
let mut non_zst_fields =
1077+
fields.iter().enumerate().filter(|&(_, f)| !f.is_zst());
1078+
1079+
match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
1080+
// We have exactly one non-ZST field.
1081+
(Some((i, field)), None, None) => {
1082+
// Field fills the struct and it has a scalar or scalar pair ABI.
1083+
if offsets[i].bytes() == 0 && size == field.size {
10811084
match field.abi {
1082-
Abi::Scalar(_) |
1085+
// For plain scalars we can't unpack newtypes
1086+
// for `#[repr(C)]`, as that affects C ABIs.
1087+
Abi::Scalar(_) if optimize => {
1088+
abi = field.abi.clone();
1089+
}
1090+
// But scalar pairs are Rust-specific and get
1091+
// treated as aggregates by C ABIs anyway.
10831092
Abi::ScalarPair(..) => {
10841093
abi = field.abi.clone();
10851094
}
10861095
_ => {}
10871096
}
10881097
}
10891098
}
1090-
_ => {}
1091-
}
1092-
}
1093-
}
10941099

1095-
// Look for a scalar pair, as an ABI optimization.
1096-
// FIXME(eddyb) ignore extra ZST fields and field ordering.
1097-
if sized && !packed && fields.len() == 2 {
1098-
match (&fields[0].abi, &fields[1].abi) {
1099-
(&Abi::Scalar(ref a), &Abi::Scalar(ref b)) => {
1100-
let pair = scalar_pair(a.clone(), b.clone());
1101-
let pair_offsets = match pair.fields {
1102-
FieldPlacement::Arbitrary {
1103-
ref offsets,
1104-
ref memory_index
1105-
} => {
1106-
assert_eq!(memory_index, &[0, 1]);
1107-
offsets
1100+
// Two non-ZST fields, and they're both scalars.
1101+
(Some((i, &TyLayout {
1102+
cached: &CachedLayout { abi: Abi::Scalar(ref a), .. }, ..
1103+
})), Some((j, &TyLayout {
1104+
cached: &CachedLayout { abi: Abi::Scalar(ref b), .. }, ..
1105+
})), None) => {
1106+
// Order by the memory placement, not source order.
1107+
let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
1108+
((i, a), (j, b))
1109+
} else {
1110+
((j, b), (i, a))
1111+
};
1112+
let pair = scalar_pair(a.clone(), b.clone());
1113+
let pair_offsets = match pair.fields {
1114+
FieldPlacement::Arbitrary {
1115+
ref offsets,
1116+
ref memory_index
1117+
} => {
1118+
assert_eq!(memory_index, &[0, 1]);
1119+
offsets
1120+
}
1121+
_ => bug!()
1122+
};
1123+
if offsets[i] == pair_offsets[0] &&
1124+
offsets[j] == pair_offsets[1] &&
1125+
align == pair.align &&
1126+
primitive_align == pair.primitive_align &&
1127+
size == pair.size {
1128+
// We can use `ScalarPair` only when it matches our
1129+
// already computed layout (including `#[repr(C)]`).
1130+
abi = pair.abi;
11081131
}
1109-
_ => bug!()
1110-
};
1111-
if offsets[0] == pair_offsets[0] &&
1112-
offsets[1] == pair_offsets[1] &&
1113-
memory_index[0] == 0 &&
1114-
memory_index[1] == 1 &&
1115-
align == pair.align &&
1116-
primitive_align == pair.primitive_align &&
1117-
size == pair.size {
1118-
// We can use `ScalarPair` only when it matches our
1119-
// already computed layout (including `#[repr(C)]`).
1120-
abi = pair.abi;
11211132
}
1133+
1134+
_ => {}
11221135
}
1123-
_ => {}
11241136
}
11251137
}
11261138

0 commit comments

Comments
 (0)