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

`+

}

`