Skip to content

Commit dbe8342

Browse files
committed
Unify Rvalue::Aggregate paths in cg_ssa
1 parent 19dacee commit dbe8342

File tree

4 files changed

+30
-22
lines changed

4 files changed

+30
-22
lines changed

compiler/rustc_abi/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1255,7 +1255,7 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
12551255

12561256
/// Gets source indices of the fields by increasing offsets.
12571257
#[inline]
1258-
pub fn index_by_increasing_offset(&self) -> impl Iterator<Item = usize> + '_ {
1258+
pub fn index_by_increasing_offset(&self) -> impl ExactSizeIterator<Item = usize> + '_ {
12591259
let mut inverse_small = [0u8; 64];
12601260
let mut inverse_big = IndexVec::new();
12611261
let use_small = self.count() <= inverse_small.len();

compiler/rustc_codegen_ssa/src/mir/operand.rs

+13
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,19 @@ impl<V> OperandValue<V> {
8686
};
8787
OperandValue::Pair(a, b)
8888
}
89+
90+
pub(crate) fn is_expected_variant_for_type<'tcx, Cx: LayoutTypeMethods<'tcx>>(
91+
&self,
92+
cx: &Cx,
93+
ty: TyAndLayout<'tcx>,
94+
) -> bool {
95+
match self {
96+
OperandValue::ZeroSized => ty.is_zst(),
97+
OperandValue::Immediate(_) => cx.is_backend_immediate(ty),
98+
OperandValue::Pair(_, _) => cx.is_backend_scalar_pair(ty),
99+
OperandValue::Ref(_) => cx.is_backend_ref(ty),
100+
}
101+
}
89102
}
90103

91104
/// An `OperandRef` is an "SSA" reference to a Rust value, along with

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+15-20
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_span::{Span, DUMMY_SP};
1818
use rustc_target::abi::{self, FieldIdx, FIRST_VARIANT};
1919

2020
use arrayvec::ArrayVec;
21+
use either::Either;
2122

2223
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
2324
#[instrument(level = "trace", skip(self, bx))]
@@ -722,35 +723,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
722723
OperandRef { val: OperandValue::Immediate(static_), layout }
723724
}
724725
mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
725-
mir::Rvalue::Aggregate(box mir::AggregateKind::RawPtr(..), ref fields) => {
726-
let ty = rvalue.ty(self.mir, self.cx.tcx());
727-
let layout = self.cx.layout_of(self.monomorphize(ty));
728-
let [data, meta] = &*fields.raw else {
729-
bug!("RawPtr fields: {fields:?}");
730-
};
731-
let data = self.codegen_operand(bx, data);
732-
let meta = self.codegen_operand(bx, meta);
733-
match (data.val, meta.val) {
734-
(p @ OperandValue::Immediate(_), OperandValue::ZeroSized) => {
735-
OperandRef { val: p, layout }
736-
}
737-
(OperandValue::Immediate(p), OperandValue::Immediate(m)) => {
738-
OperandRef { val: OperandValue::Pair(p, m), layout }
739-
}
740-
_ => bug!("RawPtr operands {data:?} {meta:?}"),
741-
}
742-
}
743726
mir::Rvalue::Repeat(..) => bug!("{rvalue:?} in codegen_rvalue_operand"),
744-
mir::Rvalue::Aggregate(_, ref fields) => {
727+
mir::Rvalue::Aggregate(ref kind, ref fields) => {
745728
let ty = rvalue.ty(self.mir, self.cx.tcx());
746729
let ty = self.monomorphize(ty);
747730
let layout = self.cx.layout_of(ty);
748731

732+
let field_indices = if let mir::AggregateKind::RawPtr(..) = **kind {
733+
// `index_by_increasing_offset` gives an empty iterator for primitives
734+
Either::Left([0_usize, 1_usize].iter().copied())
735+
} else {
736+
Either::Right(layout.fields.index_by_increasing_offset())
737+
};
738+
debug_assert_eq!(field_indices.len(), fields.len());
739+
749740
// `rvalue_creates_operand` has arranged that we only get here if
750741
// we can build the aggregate immediate from the field immediates.
751742
let mut inputs = ArrayVec::<Bx::Value, 2>::new();
752743
let mut input_scalars = ArrayVec::<abi::Scalar, 2>::new();
753-
for field_idx in layout.fields.index_by_increasing_offset() {
744+
for field_idx in field_indices {
754745
let field_idx = FieldIdx::from_usize(field_idx);
755746
let op = self.codegen_operand(bx, &fields[field_idx]);
756747
let values = op.val.immediates_or_place().left_or_else(|p| {
@@ -774,6 +765,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
774765
);
775766

776767
let val = OperandValue::from_immediates(inputs);
768+
debug_assert!(
769+
val.is_expected_variant_for_type(self.cx, layout),
770+
"Made wrong variant {val:?} for type {layout:?}",
771+
);
777772
OperandRef { val, layout }
778773
}
779774
mir::Rvalue::ShallowInitBox(ref operand, content_ty) => {

tests/codegen/mir-aggregate-no-alloca.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub fn make_cell_of_bool(b: bool) -> std::cell::Cell<bool> {
5555
std::cell::Cell::new(b)
5656
}
5757

58-
// CHECK-LABLE: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16 noundef %s)
58+
// CHECK-LABEL: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16 noundef %s)
5959
#[no_mangle]
6060
pub fn make_cell_of_bool_and_short(b: bool, s: u16) -> std::cell::Cell<(bool, u16)> {
6161
// CHECK-NOT: alloca

0 commit comments

Comments
 (0)