Auto merge of #123886 - scottmcm:more-rvalue-operands, r=matthewjasper · rust-lang/rust@6e1d947 (original) (raw)
`@@ -8,14 +8,16 @@ use crate::traits::*;
`
8
8
`use crate::MemFlags;
`
9
9
``
10
10
`use rustc_hir as hir;
`
11
``
`-
use rustc_middle::mir::{self, AggregateKind, Operand};
`
``
11
`+
use rustc_middle::mir;
`
12
12
`use rustc_middle::ty::cast::{CastTy, IntTy};
`
13
13
`use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
`
14
14
`use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, Ty, TyCtxt};
`
15
15
`use rustc_middle::{bug, span_bug};
`
16
16
`use rustc_session::config::OptLevel;
`
17
17
`use rustc_span::{Span, DUMMY_SP};
`
18
``
`-
use rustc_target::abi::{self, FIRST_VARIANT};
`
``
18
`+
use rustc_target::abi::{self, FieldIdx, FIRST_VARIANT};
`
``
19
+
``
20
`+
use arrayvec::ArrayVec;
`
19
21
``
20
22
`impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
21
23
`#[instrument(level = "trace", skip(self, bx))]
`
`@@ -579,7 +581,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
579
581
`self.codegen_place_to_pointer(bx, place, mk_ref)
`
580
582
`}
`
581
583
``
582
``
`-
mir::Rvalue::CopyForDeref(place) => self.codegen_operand(bx, &Operand::Copy(place)),
`
``
584
`+
mir::Rvalue::CopyForDeref(place) => {
`
``
585
`+
self.codegen_operand(bx, &mir::Operand::Copy(place))
`
``
586
`+
}
`
583
587
` mir::Rvalue::AddressOf(mutability, place) => {
`
584
588
`let mk_ptr =
`
585
589
`move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| Ty::new_ptr(tcx, ty, mutability);
`
`@@ -736,11 +740,41 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
736
740
` _ => bug!("RawPtr operands {data:?} {meta:?}"),
`
737
741
`}
`
738
742
`}
`
739
``
`-
mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => {
`
740
``
`` -
// According to rvalue_creates_operand
, only ZST
``
741
``
`-
// aggregate rvalues are allowed to be operands.
`
``
743
`+
mir::Rvalue::Repeat(..) => bug!("{rvalue:?} in codegen_rvalue_operand"),
`
``
744
`+
mir::Rvalue::Aggregate(_, ref fields) => {
`
742
745
`let ty = rvalue.ty(self.mir, self.cx.tcx());
`
743
``
`-
OperandRef::zero_sized(self.cx.layout_of(self.monomorphize(ty)))
`
``
746
`+
let ty = self.monomorphize(ty);
`
``
747
`+
let layout = self.cx.layout_of(ty);
`
``
748
+
``
749
`` +
// rvalue_creates_operand
has arranged that we only get here if
``
``
750
`+
// we can build the aggregate immediate from the field immediates.
`
``
751
`+
let mut inputs = ArrayVec::<Bx::Value, 2>::new();
`
``
752
`+
let mut input_scalars = ArrayVec::<abi::Scalar, 2>::new();
`
``
753
`+
for field_idx in layout.fields.index_by_increasing_offset() {
`
``
754
`+
let field_idx = FieldIdx::from_usize(field_idx);
`
``
755
`+
let op = self.codegen_operand(bx, &fields[field_idx]);
`
``
756
`+
let values = op.val.immediates_or_place().left_or_else(|p| {
`
``
757
`+
bug!("Field {field_idx:?} is {p:?} making {layout:?}");
`
``
758
`+
});
`
``
759
`+
inputs.extend(values);
`
``
760
`+
let scalars = self.value_kind(op.layout).scalars().unwrap();
`
``
761
`+
input_scalars.extend(scalars);
`
``
762
`+
}
`
``
763
+
``
764
`+
let output_scalars = self.value_kind(layout).scalars().unwrap();
`
``
765
`+
itertools::izip!(&mut inputs, input_scalars, output_scalars).for_each(
`
``
766
`+
|(v, in_s, out_s)| {
`
``
767
`+
if in_s != out_s {
`
``
768
`+
// We have to be really careful about bool here, because
`
``
769
`` +
// (bool,)
stays i1 but Cell<bool>
becomes i8.
``
``
770
`+
*v = bx.from_immediate(*v);
`
``
771
`+
*v = bx.to_immediate_scalar(*v, out_s);
`
``
772
`+
}
`
``
773
`+
},
`
``
774
`+
);
`
``
775
+
``
776
`+
let val = OperandValue::from_immediates(inputs);
`
``
777
`+
OperandRef { val, layout }
`
744
778
`}
`
745
779
` mir::Rvalue::ShallowInitBox(ref operand, content_ty) => {
`
746
780
`let operand = self.codegen_operand(bx, operand);
`
`@@ -1047,14 +1081,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
1047
1081
` mir::Rvalue::ThreadLocalRef(_) |
`
1048
1082
` mir::Rvalue::Use(..) => // (*)
`
1049
1083
`true,
`
1050
``
`` -
// This always produces a ty::RawPtr
, so will be Immediate or Pair
``
1051
``
`-
mir::Rvalue::Aggregate(box AggregateKind::RawPtr(..), ..) => true,
`
1052
``
`-
mir::Rvalue::Repeat(..) |
`
1053
``
`-
mir::Rvalue::Aggregate(..) => {
`
``
1084
`+
// Arrays are always aggregates, so it's not worth checking anything here.
`
``
1085
`` +
// (If it's really [(); N]
or [T; 0]
and we use the place path, fine.)
``
``
1086
`+
mir::Rvalue::Repeat(..) => false,
`
``
1087
`+
mir::Rvalue::Aggregate(ref kind, _) => {
`
``
1088
`+
let allowed_kind = match **kind {
`
``
1089
`` +
// This always produces a ty::RawPtr
, so will be Immediate or Pair
``
``
1090
`+
mir::AggregateKind::RawPtr(..) => true,
`
``
1091
`+
mir::AggregateKind::Array(..) => false,
`
``
1092
`+
mir::AggregateKind::Tuple => true,
`
``
1093
`+
mir::AggregateKind::Adt(def_id, ..) => {
`
``
1094
`+
let adt_def = self.cx.tcx().adt_def(def_id);
`
``
1095
`+
adt_def.is_struct() && !adt_def.repr().simd()
`
``
1096
`+
}
`
``
1097
`+
mir::AggregateKind::Closure(..) => true,
`
``
1098
`+
// FIXME: Can we do this for simple coroutines too?
`
``
1099
`+
mir::AggregateKind::Coroutine(..) | mir::AggregateKind::CoroutineClosure(..) => false,
`
``
1100
`+
};
`
``
1101
`+
allowed_kind && {
`
1054
1102
`let ty = rvalue.ty(self.mir, self.cx.tcx());
`
1055
1103
`let ty = self.monomorphize(ty);
`
1056
``
`` -
// For ZST this can be OperandValueKind::ZeroSized
.
``
1057
``
`-
self.cx.spanned_layout_of(ty, span).is_zst()
`
``
1104
`+
let layout = self.cx.spanned_layout_of(ty, span);
`
``
1105
`+
!self.cx.is_backend_ref(layout)
`
``
1106
`+
}
`
1058
1107
`}
`
1059
1108
`}
`
1060
1109
``
`@@ -1096,3 +1145,14 @@ enum OperandValueKind {
`
1096
1145
`Pair(abi::Scalar, abi::Scalar),
`
1097
1146
`ZeroSized,
`
1098
1147
`}
`
``
1148
+
``
1149
`+
impl OperandValueKind {
`
``
1150
`+
fn scalars(self) -> Option<ArrayVec<abi::Scalar, 2>> {
`
``
1151
`+
Some(match self {
`
``
1152
`+
OperandValueKind::ZeroSized => ArrayVec::new(),
`
``
1153
`+
OperandValueKind::Immediate(a) => ArrayVec::from_iter([a]),
`
``
1154
`+
OperandValueKind::Pair(a, b) => [a, b].into(),
`
``
1155
`+
OperandValueKind::Ref => return None,
`
``
1156
`+
})
`
``
1157
`+
}
`
``
1158
`+
}
`