Skip to content

Commit 8133ec5

Browse files
Rollup merge of rust-lang#158666 - scottmcm:scalar-but-packed, r=workingjubilee
Carry the `b_offset` inside `BackendRepr::ScalarPair` Inspired by rust-lang/compiler-team#1007 but doesn't actually change any of the layout rules just yet. This turned out to be a nice change even if we didn't use the extra flexibility, IMHO, because it allowed so many things like ```diff @@ -222,12 +224,12 @@ fn from_const_alloc<Bx: BuilderMethods<'a, 'tcx, Value = V>>( let val = read_scalar(offset, size, s, bx.immediate_backend_type(layout)); OperandRef { val: OperandValue::Immediate(val), layout, move_annotation: None } } - BackendRepr::ScalarPair( - a @ abi::Scalar::Initialized { .. }, - b @ abi::Scalar::Initialized { .. }, - ) => { + BackendRepr::ScalarPair { + a: a @ abi::Scalar::Initialized { .. }, + b: b @ abi::Scalar::Initialized { .. }, + b_offset, + } => { let (a_size, b_size) = (a.size(bx), b.size(bx)); - let b_offset = (offset + a_size).align_to(b.default_align(bx).abi); assert!(b_offset.bytes() > 0); let a_val = read_scalar( offset, ``` as *oh my* was that little magic incantation copy-pasted all over the place. Apologies for the pretty-giant PR. I tried to make it as direct a change as I could: if it was `(..)` before it's `{ .. }` now, if it was `(_, _)` before it's `{ a: _, b: _, b_offset: _ }` now. I kept the names the same so the code lines were unchanged even if normally I might have just renamed things, etc. I'll add some inline notes for places of particular interest. r? @workingjubilee
2 parents 219e490 + 47a510b commit 8133ec5

59 files changed

Lines changed: 414 additions & 317 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_abi/src/callconv.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
8989
unreachable!("`homogeneous_aggregate` should not be called for scalable vectors")
9090
}
9191

92-
BackendRepr::ScalarPair(..) | BackendRepr::Memory { sized: true } => {
92+
BackendRepr::ScalarPair { .. } | BackendRepr::Memory { sized: true } => {
9393
// Helper for computing `homogeneous_aggregate`, allowing a custom
9494
// starting offset (used below for handling variants).
9595
let from_fields_at =

compiler/rustc_abi/src/layout.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
476476
Err(AbiMismatch) | Ok(None) => BackendRepr::Memory { sized: true },
477477
Ok(Some((repr, _))) => match repr {
478478
// Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
479-
BackendRepr::Scalar(_) | BackendRepr::ScalarPair(_, _)
479+
BackendRepr::Scalar(_) | BackendRepr::ScalarPair { .. }
480480
if repr.scalar_platform_align(dl).unwrap() != align =>
481481
{
482482
BackendRepr::Memory { sized: true }
@@ -489,7 +489,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
489489
}
490490
// the alignment tests passed and we can use this
491491
BackendRepr::Scalar(..)
492-
| BackendRepr::ScalarPair(..)
492+
| BackendRepr::ScalarPair { .. }
493493
| BackendRepr::SimdVector { .. }
494494
| BackendRepr::SimdScalableVector { .. }
495495
| BackendRepr::Memory { .. } => repr,
@@ -558,7 +558,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
558558
};
559559
match &mut st.backend_repr {
560560
BackendRepr::Scalar(scalar) => hide_niches(scalar),
561-
BackendRepr::ScalarPair(a, b) => {
561+
BackendRepr::ScalarPair { a, b, b_offset: _ } => {
562562
hide_niches(a);
563563
hide_niches(b);
564564
}
@@ -701,13 +701,21 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
701701
// When the total alignment and size match, we can use the
702702
// same ABI as the scalar variant with the reserved niche.
703703
BackendRepr::Scalar(_) => BackendRepr::Scalar(niche_scalar),
704-
BackendRepr::ScalarPair(first, second) => {
704+
BackendRepr::ScalarPair { a: first, b: second, b_offset } => {
705705
// Only the niche is guaranteed to be initialised,
706706
// so use union layouts for the other primitive.
707707
if niche_offset == Size::ZERO {
708-
BackendRepr::ScalarPair(niche_scalar, second.to_union())
708+
BackendRepr::ScalarPair {
709+
a: niche_scalar,
710+
b: second.to_union(),
711+
b_offset,
712+
}
709713
} else {
710-
BackendRepr::ScalarPair(first.to_union(), niche_scalar)
714+
BackendRepr::ScalarPair {
715+
a: first.to_union(),
716+
b: niche_scalar,
717+
b_offset,
718+
}
711719
}
712720
}
713721
_ => BackendRepr::Memory { sized: true },
@@ -1037,7 +1045,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
10371045
// If we pick a "clever" (by-value) ABI, we might have to adjust the ABI of the
10381046
// variants to ensure they are consistent. This is because a downcast is
10391047
// semantically a NOP, and thus should not affect layout.
1040-
if matches!(abi, BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)) {
1048+
if matches!(abi, BackendRepr::Scalar(..) | BackendRepr::ScalarPair { .. }) {
10411049
for variant in &mut layout_variants {
10421050
// We only do this for variants with fields; the others are not accessed anyway.
10431051
// Also do not overwrite any already existing "clever" ABIs.
@@ -1354,7 +1362,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
13541362
}
13551363
// But scalar pairs are Rust-specific and get
13561364
// treated as aggregates by C ABIs anyway.
1357-
BackendRepr::ScalarPair(..) => {
1365+
BackendRepr::ScalarPair { .. } => {
13581366
abi = field.backend_repr;
13591367
}
13601368
_ => {}

compiler/rustc_abi/src/layout/simple.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
110110
offsets: [Size::ZERO, b_offset].into(),
111111
in_memory_order: [FieldIdx::new(0), FieldIdx::new(1)].into(),
112112
},
113-
backend_repr: BackendRepr::ScalarPair(a, b),
113+
backend_repr: BackendRepr::ScalarPair { a, b, b_offset },
114114
largest_niche,
115115
uninhabited: false,
116116
align: AbiAlign::new(align),

compiler/rustc_abi/src/lib.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,14 +1796,18 @@ impl IntoDiagArg for NumScalableVectors {
17961796
pub enum BackendRepr {
17971797
Scalar(Scalar),
17981798
/// The data contained in this type can be entirely represented by two scalars.
1799-
/// The two scalars are listed in *memory* order, so the first is at offset zero
1800-
/// and the second at a non-zero offset.
1799+
/// The two scalars are listed in *memory* order, so `a` is at offset zero
1800+
/// and `b` is at non-zero offset `b_offset`.
18011801
/// These need not be `FieldIdx(0)` and `FieldIdx(1)`.
18021802
///
1803-
/// As of June 2026 the offset to the second scalar is the size of the first
1804-
/// scalar rounded up to the platform alignment of the second scalar.
1803+
/// As of June 2026 the `b_offset` is always the size of the `a`
1804+
/// scalar rounded up to the platform alignment of the `b` scalar.
18051805
/// That may soon change, however; see MCP#1007.
1806-
ScalarPair(Scalar, Scalar),
1806+
ScalarPair {
1807+
a: Scalar,
1808+
b: Scalar,
1809+
b_offset: Size,
1810+
},
18071811
SimdScalableVector {
18081812
element: Scalar,
18091813
count: u64,
@@ -1826,7 +1830,7 @@ impl BackendRepr {
18261830
pub fn is_unsized(&self) -> bool {
18271831
match *self {
18281832
BackendRepr::Scalar(_)
1829-
| BackendRepr::ScalarPair(..)
1833+
| BackendRepr::ScalarPair { .. }
18301834
// FIXME(rustc_scalable_vector): Scalable vectors are `Sized` while the
18311835
// `sized_hierarchy` feature is not yet fully implemented. After `sized_hierarchy` is
18321836
// fully implemented, scalable vectors will remain `Sized`, they just won't be
@@ -1875,7 +1879,7 @@ impl BackendRepr {
18751879
pub fn scalar_platform_align<C: HasDataLayout>(&self, cx: &C) -> Option<Align> {
18761880
match *self {
18771881
BackendRepr::Scalar(s) => Some(s.default_align(cx).abi),
1878-
BackendRepr::ScalarPair(s1, s2) => {
1882+
BackendRepr::ScalarPair { a: s1, b: s2, b_offset: _ } => {
18791883
Some(s1.default_align(cx).max(s2.default_align(cx)).abi)
18801884
}
18811885
// The align of a Vector can vary in surprising ways
@@ -1893,8 +1897,7 @@ impl BackendRepr {
18931897
// No padding in scalars.
18941898
BackendRepr::Scalar(s) => Some(s.size(cx)),
18951899
// May have some padding between the pair.
1896-
BackendRepr::ScalarPair(s1, s2) => {
1897-
let field2_offset = s1.size(cx).align_to(s2.default_align(cx).abi);
1900+
BackendRepr::ScalarPair { a: _, b: s2, b_offset: field2_offset } => {
18981901
let size = (field2_offset + s2.size(cx)).align_to(
18991902
self.scalar_platform_align(cx)
19001903
// We absolutely must have an answer here or everything is FUBAR.
@@ -1913,8 +1916,8 @@ impl BackendRepr {
19131916
pub fn to_union(&self) -> Self {
19141917
match *self {
19151918
BackendRepr::Scalar(s) => BackendRepr::Scalar(s.to_union()),
1916-
BackendRepr::ScalarPair(s1, s2) => {
1917-
BackendRepr::ScalarPair(s1.to_union(), s2.to_union())
1919+
BackendRepr::ScalarPair { a: s1, b: s2, b_offset } => {
1920+
BackendRepr::ScalarPair { a: s1.to_union(), b: s2.to_union(), b_offset }
19181921
}
19191922
BackendRepr::SimdVector { element, count } => {
19201923
BackendRepr::SimdVector { element: element.to_union(), count }
@@ -1939,8 +1942,13 @@ impl BackendRepr {
19391942
BackendRepr::SimdVector { element: element_l, count: count_l },
19401943
BackendRepr::SimdVector { element: element_r, count: count_r },
19411944
) => element_l.primitive() == element_r.primitive() && count_l == count_r,
1942-
(BackendRepr::ScalarPair(l1, l2), BackendRepr::ScalarPair(r1, r2)) => {
1943-
l1.primitive() == r1.primitive() && l2.primitive() == r2.primitive()
1945+
(
1946+
BackendRepr::ScalarPair { a: l1, b: l2, b_offset: l_offset },
1947+
BackendRepr::ScalarPair { a: r1, b: r2, b_offset: r_offset },
1948+
) => {
1949+
l1.primitive() == r1.primitive()
1950+
&& l2.primitive() == r2.primitive()
1951+
&& l_offset == r_offset
19441952
}
19451953
// Everything else must be strictly identical.
19461954
_ => self == other,
@@ -2180,7 +2188,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
21802188
BackendRepr::Scalar(_)
21812189
| BackendRepr::SimdVector { .. }
21822190
| BackendRepr::SimdScalableVector { .. } => false,
2183-
BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => true,
2191+
BackendRepr::ScalarPair { .. } | BackendRepr::Memory { .. } => true,
21842192
}
21852193
}
21862194

@@ -2294,7 +2302,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
22942302
pub fn is_zst(&self) -> bool {
22952303
match self.backend_repr {
22962304
BackendRepr::Scalar(_)
2297-
| BackendRepr::ScalarPair(..)
2305+
| BackendRepr::ScalarPair { .. }
22982306
| BackendRepr::SimdScalableVector { .. }
22992307
| BackendRepr::SimdVector { .. } => false,
23002308
BackendRepr::Memory { sized } => sized && self.size.bytes() == 0,

compiler/rustc_codegen_cranelift/src/abi/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ fn make_local_place<'tcx>(
220220
);
221221
}
222222
let place = if is_ssa {
223-
if let BackendRepr::ScalarPair(_, _) = layout.backend_repr {
223+
if let BackendRepr::ScalarPair { a: _, b: _, b_offset: _ } = layout.backend_repr {
224224
CPlace::new_var_pair(fx, local, layout)
225225
} else {
226226
CPlace::new_var(fx, local, layout)

compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
112112
_ => unreachable!("{:?}", self.layout.backend_repr),
113113
},
114114
PassMode::Pair(attrs_a, attrs_b) => match self.layout.backend_repr {
115-
BackendRepr::ScalarPair(a, b) => {
115+
BackendRepr::ScalarPair { a, b, b_offset: _ } => {
116116
let a = scalar_to_clif_type(tcx, a);
117117
let b = scalar_to_clif_type(tcx, b);
118118
smallvec![
@@ -167,7 +167,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
167167
_ => unreachable!("{:?}", self.layout.backend_repr),
168168
},
169169
PassMode::Pair(attrs_a, attrs_b) => match self.layout.backend_repr {
170-
BackendRepr::ScalarPair(a, b) => {
170+
BackendRepr::ScalarPair { a, b, b_offset: _ } => {
171171
let a = scalar_to_clif_type(tcx, a);
172172
let b = scalar_to_clif_type(tcx, b);
173173
(

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
695695
}
696696
UnOp::PtrMetadata => match layout.backend_repr {
697697
BackendRepr::Scalar(_) => CValue::zst(dest_layout),
698-
BackendRepr::ScalarPair(_, _) => {
698+
BackendRepr::ScalarPair { a: _, b: _, b_offset: _ } => {
699699
CValue::by_val(operand.load_scalar_pair(fx).1, dest_layout)
700700
}
701701
_ => bug!("Unexpected `PtrToMetadata` operand: {operand:?}"),

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,9 @@ fn codegen_regular_intrinsic_call<'tcx>(
572572
let layout = fx.layout_of(generic_args.type_at(0));
573573
// Note: Can't use is_unsized here as truly unsized types need to take the fixed size
574574
// branch
575-
let meta = if let BackendRepr::ScalarPair(_, _) = ptr.layout().backend_repr {
575+
let meta = if let BackendRepr::ScalarPair { a: _, b: _, b_offset: _ } =
576+
ptr.layout().backend_repr
577+
{
576578
Some(ptr.load_scalar_pair(fx).1)
577579
} else {
578580
None
@@ -586,7 +588,9 @@ fn codegen_regular_intrinsic_call<'tcx>(
586588
let layout = fx.layout_of(generic_args.type_at(0));
587589
// Note: Can't use is_unsized here as truly unsized types need to take the fixed size
588590
// branch
589-
let meta = if let BackendRepr::ScalarPair(_, _) = ptr.layout().backend_repr {
591+
let meta = if let BackendRepr::ScalarPair { a: _, b: _, b_offset: _ } =
592+
ptr.layout().backend_repr
593+
{
590594
Some(ptr.load_scalar_pair(fx).1)
591595
} else {
592596
None

compiler/rustc_codegen_cranelift/src/value_and_place.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ fn codegen_field<'tcx>(
5555
}
5656
}
5757

58-
fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: Scalar, b_scalar: Scalar) -> Offset32 {
59-
let b_offset = a_scalar.size(&tcx).align_to(b_scalar.default_align(&tcx).abi);
58+
fn scalar_pair_convert_b_offset(b_offset: Size) -> Offset32 {
6059
Offset32::new(b_offset.bytes().try_into().unwrap())
6160
}
6261

@@ -159,11 +158,11 @@ impl<'tcx> CValue<'tcx> {
159158
let layout = self.1;
160159
match self.0 {
161160
CValueInner::ByRef(ptr, None) => {
162-
let (a_scalar, b_scalar) = match layout.backend_repr {
163-
BackendRepr::ScalarPair(a, b) => (a, b),
161+
let (a_scalar, b_scalar, b_offset) = match layout.backend_repr {
162+
BackendRepr::ScalarPair { a, b, b_offset } => (a, b, b_offset),
164163
_ => unreachable!("load_scalar_pair({:?})", self),
165164
};
166-
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
165+
let b_offset = scalar_pair_convert_b_offset(b_offset);
167166
let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar);
168167
let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar);
169168
let mut flags = MemFlags::new();
@@ -189,7 +188,7 @@ impl<'tcx> CValue<'tcx> {
189188
match self.0 {
190189
CValueInner::ByVal(_) => unreachable!(),
191190
CValueInner::ByValPair(val1, val2) => match layout.backend_repr {
192-
BackendRepr::ScalarPair(_, _) => {
191+
BackendRepr::ScalarPair { a: _, b: _, b_offset: _ } => {
193192
let val = match field.as_u32() {
194193
0 => val1,
195194
1 => val2,
@@ -580,7 +579,7 @@ impl<'tcx> CPlace<'tcx> {
580579
}
581580
CPlaceInner::VarPair(_local, var1, var2) => {
582581
let (data1, data2) = match from.1.backend_repr {
583-
BackendRepr::ScalarPair(_, _) => {
582+
BackendRepr::ScalarPair { a: _, b: _, b_offset: _ } => {
584583
CValue(from.0, dst_layout).load_scalar_pair(fx)
585584
}
586585
_ => {
@@ -607,9 +606,8 @@ impl<'tcx> CPlace<'tcx> {
607606
to_ptr.store(fx, val, flags);
608607
}
609608
CValueInner::ByValPair(val1, val2) => match from.layout().backend_repr {
610-
BackendRepr::ScalarPair(a_scalar, b_scalar) => {
611-
let b_offset =
612-
scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
609+
BackendRepr::ScalarPair { a: _, b: _, b_offset } => {
610+
let b_offset = scalar_pair_convert_b_offset(b_offset);
613611
to_ptr.store(fx, val1, flags);
614612
to_ptr.offset(fx, b_offset).store(fx, val2, flags);
615613
}
@@ -627,9 +625,8 @@ impl<'tcx> CPlace<'tcx> {
627625
to_ptr.store(fx, val, flags);
628626
return;
629627
}
630-
BackendRepr::ScalarPair(a_scalar, b_scalar) => {
631-
let b_offset =
632-
scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
628+
BackendRepr::ScalarPair { a: _, b: _, b_offset } => {
629+
let b_offset = scalar_pair_convert_b_offset(b_offset);
633630
let (val1, val2) = from.load_scalar_pair(fx);
634631
to_ptr.store(fx, val1, flags);
635632
to_ptr.offset(fx, b_offset).store(fx, val2, flags);

compiler/rustc_codegen_cranelift/src/vtable.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,14 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
5656
}
5757
}
5858

59-
let (ptr, vtable) = if let BackendRepr::ScalarPair(_, _) = arg.layout().backend_repr {
60-
let (ptr, vtable) = arg.load_scalar_pair(fx);
61-
(Pointer::new(ptr), vtable)
62-
} else {
63-
let (ptr, vtable) = arg.try_to_ptr().unwrap();
64-
(ptr, vtable.unwrap())
65-
};
59+
let (ptr, vtable) =
60+
if let BackendRepr::ScalarPair { a: _, b: _, b_offset: _ } = arg.layout().backend_repr {
61+
let (ptr, vtable) = arg.load_scalar_pair(fx);
62+
(Pointer::new(ptr), vtable)
63+
} else {
64+
let (ptr, vtable) = arg.try_to_ptr().unwrap();
65+
(ptr, vtable.unwrap())
66+
};
6667

6768
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
6869
let func_ref = fx.bcx.ins().load(

0 commit comments

Comments
 (0)