Skip to content

Commit d893285

Browse files
committed
rustc: use layout::Abi::ScalarPair for structs in more cases.
1 parent 801a1a0 commit d893285

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
@@ -1078,60 +1078,72 @@ impl<'a, 'tcx> CachedLayout {
10781078
packed
10791079
};
10801080

1081-
// Unpack newtype ABIs.
1082-
if sized && optimize && size.bytes() > 0 {
1083-
// All but one field must be ZSTs, and so they all start at 0.
1084-
if offsets.iter().all(|o| o.bytes() == 0) {
1085-
let mut non_zst_fields = fields.iter().filter(|f| !f.is_zst());
1086-
1087-
// We have exactly one non-ZST field.
1088-
match (non_zst_fields.next(), non_zst_fields.next()) {
1089-
(Some(field), None) => {
1090-
// Field size matches and it has a scalar or scalar pair ABI.
1091-
if size == field.size {
1081+
// Unpack newtype ABIs and find scalar pairs.
1082+
if sized && size.bytes() > 0 {
1083+
// All other fields must be ZSTs, and we need them to all start at 0.
1084+
let mut zst_offsets =
1085+
offsets.iter().enumerate().filter(|&(i, _)| fields[i].is_zst());
1086+
if zst_offsets.all(|(_, o)| o.bytes() == 0) {
1087+
let mut non_zst_fields =
1088+
fields.iter().enumerate().filter(|&(_, f)| !f.is_zst());
1089+
1090+
match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
1091+
// We have exactly one non-ZST field.
1092+
(Some((i, field)), None, None) => {
1093+
// Field fills the struct and it has a scalar or scalar pair ABI.
1094+
if offsets[i].bytes() == 0 && size == field.size {
10921095
match field.abi {
1093-
Abi::Scalar(_) |
1096+
// For plain scalars we can't unpack newtypes
1097+
// for `#[repr(C)]`, as that affects C ABIs.
1098+
Abi::Scalar(_) if optimize => {
1099+
abi = field.abi.clone();
1100+
}
1101+
// But scalar pairs are Rust-specific and get
1102+
// treated as aggregates by C ABIs anyway.
10941103
Abi::ScalarPair(..) => {
10951104
abi = field.abi.clone();
10961105
}
10971106
_ => {}
10981107
}
10991108
}
11001109
}
1101-
_ => {}
1102-
}
1103-
}
1104-
}
11051110

1106-
// Look for a scalar pair, as an ABI optimization.
1107-
// FIXME(eddyb) ignore extra ZST fields and field ordering.
1108-
if sized && !packed && fields.len() == 2 {
1109-
match (&fields[0].abi, &fields[1].abi) {
1110-
(&Abi::Scalar(ref a), &Abi::Scalar(ref b)) => {
1111-
let pair = scalar_pair(a.clone(), b.clone());
1112-
let pair_offsets = match pair.fields {
1113-
FieldPlacement::Arbitrary {
1114-
ref offsets,
1115-
ref memory_index
1116-
} => {
1117-
assert_eq!(memory_index, &[0, 1]);
1118-
offsets
1111+
// Two non-ZST fields, and they're both scalars.
1112+
(Some((i, &TyLayout {
1113+
cached: &CachedLayout { abi: Abi::Scalar(ref a), .. }, ..
1114+
})), Some((j, &TyLayout {
1115+
cached: &CachedLayout { abi: Abi::Scalar(ref b), .. }, ..
1116+
})), None) => {
1117+
// Order by the memory placement, not source order.
1118+
let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
1119+
((i, a), (j, b))
1120+
} else {
1121+
((j, b), (i, a))
1122+
};
1123+
let pair = scalar_pair(a.clone(), b.clone());
1124+
let pair_offsets = match pair.fields {
1125+
FieldPlacement::Arbitrary {
1126+
ref offsets,
1127+
ref memory_index
1128+
} => {
1129+
assert_eq!(memory_index, &[0, 1]);
1130+
offsets
1131+
}
1132+
_ => bug!()
1133+
};
1134+
if offsets[i] == pair_offsets[0] &&
1135+
offsets[j] == pair_offsets[1] &&
1136+
align == pair.align &&
1137+
primitive_align == pair.primitive_align &&
1138+
size == pair.size {
1139+
// We can use `ScalarPair` only when it matches our
1140+
// already computed layout (including `#[repr(C)]`).
1141+
abi = pair.abi;
11191142
}
1120-
_ => bug!()
1121-
};
1122-
if offsets[0] == pair_offsets[0] &&
1123-
offsets[1] == pair_offsets[1] &&
1124-
memory_index[0] == 0 &&
1125-
memory_index[1] == 1 &&
1126-
align == pair.align &&
1127-
primitive_align == pair.primitive_align &&
1128-
size == pair.size {
1129-
// We can use `ScalarPair` only when it matches our
1130-
// already computed layout (including `#[repr(C)]`).
1131-
abi = pair.abi;
11321143
}
1144+
1145+
_ => {}
11331146
}
1134-
_ => {}
11351147
}
11361148
}
11371149

0 commit comments

Comments
 (0)