Do not compute actual aggregate type.

This commit is contained in:
Camille GILLOT 2023-05-03 18:36:53 +00:00
parent f110f22060
commit 23d4857080

View File

@ -56,6 +56,7 @@
use rustc_const_eval::interpret::{ImmTy, InterpCx, MemPlaceMeta, OpTy, Projectable, Scalar}; use rustc_const_eval::interpret::{ImmTy, InterpCx, MemPlaceMeta, OpTy, Projectable, Scalar};
use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::graph::dominators::Dominators;
use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
use rustc_index::IndexVec; use rustc_index::IndexVec;
use rustc_macros::newtype_index; use rustc_macros::newtype_index;
@ -64,6 +65,7 @@ use rustc_middle::mir::visit::*;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut};
use rustc_span::def_id::DefId;
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
use rustc_target::abi::{self, Abi, Size, VariantIdx, FIRST_VARIANT}; use rustc_target::abi::{self, Abi, Size, VariantIdx, FIRST_VARIANT};
use std::borrow::Cow; use std::borrow::Cow;
@ -136,6 +138,16 @@ newtype_index! {
struct VnIndex {} struct VnIndex {}
} }
/// Computing the aggregate's type can be quite slow, so we only keep the minimal amount of
/// information to reconstruct it when needed.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
enum AggregateTy<'tcx> {
/// Invariant: this must not be used for an empty array.
Array,
Tuple,
Def(DefId, ty::GenericArgsRef<'tcx>),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
enum AddressKind { enum AddressKind {
Ref(BorrowKind), Ref(BorrowKind),
@ -152,7 +164,7 @@ enum Value<'tcx> {
Constant(Const<'tcx>), Constant(Const<'tcx>),
/// An aggregate value, either tuple/closure/struct/enum. /// An aggregate value, either tuple/closure/struct/enum.
/// This does not contain unions, as we cannot reason with the value. /// This does not contain unions, as we cannot reason with the value.
Aggregate(Ty<'tcx>, VariantIdx, Vec<VnIndex>), Aggregate(AggregateTy<'tcx>, VariantIdx, Vec<VnIndex>),
/// This corresponds to a `[value; count]` expression. /// This corresponds to a `[value; count]` expression.
Repeat(VnIndex, ty::Const<'tcx>), Repeat(VnIndex, ty::Const<'tcx>),
/// The address of a place. /// The address of a place.
@ -289,11 +301,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
Repeat(..) => return None, Repeat(..) => return None,
Constant(ref constant) => self.ecx.eval_mir_constant(constant, None, None).ok()?, Constant(ref constant) => self.ecx.eval_mir_constant(constant, None, None).ok()?,
Aggregate(ty, variant, ref fields) => { Aggregate(kind, variant, ref fields) => {
let fields = fields let fields = fields
.iter() .iter()
.map(|&f| self.evaluated[f].as_ref()) .map(|&f| self.evaluated[f].as_ref())
.collect::<Option<Vec<_>>>()?; .collect::<Option<Vec<_>>>()?;
let ty = match kind {
AggregateTy::Array => {
assert!(fields.len() > 0);
Ty::new_array(self.tcx, fields[0].layout.ty, fields.len() as u64)
}
AggregateTy::Tuple => {
Ty::new_tup_from_iter(self.tcx, fields.iter().map(|f| f.layout.ty))
}
AggregateTy::Def(def_id, args) => {
self.tcx.type_of(def_id).instantiate(self.tcx, args)
}
};
let variant = if ty.is_enum() { Some(variant) } else { None }; let variant = if ty.is_enum() { Some(variant) } else { None };
let ty = self.ecx.layout_of(ty).ok()?; let ty = self.ecx.layout_of(ty).ok()?;
if ty.is_zst() { if ty.is_zst() {
@ -510,7 +534,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
Value::Repeat(inner, _) => { Value::Repeat(inner, _) => {
return Some(*inner); return Some(*inner);
} }
Value::Aggregate(ty, _, operands) if ty.is_array() => { Value::Aggregate(AggregateTy::Array, _, operands) => {
let offset = if from_end { let offset = if from_end {
operands.len() - offset as usize operands.len() - offset as usize
} else { } else {
@ -659,12 +683,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
} }
Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty), Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
Rvalue::Aggregate(box ref kind, ref mut fields) => { Rvalue::Aggregate(box ref kind, ref mut fields) => {
let variant_index = match *kind { let (ty, variant_index) = match *kind {
AggregateKind::Array(..) // For empty arrays, we have not mean to recover the type. They are ZSTs
| AggregateKind::Tuple // anyway, so return them as such.
| AggregateKind::Closure(..) AggregateKind::Array(..) | AggregateKind::Tuple if fields.is_empty() => {
| AggregateKind::Coroutine(..) => FIRST_VARIANT, return Some(self.insert(Value::Constant(Const::zero_sized(
AggregateKind::Adt(_, variant_index, _, _, None) => variant_index, rvalue.ty(self.local_decls, self.tcx),
))));
}
AggregateKind::Array(..) => (AggregateTy::Array, FIRST_VARIANT),
AggregateKind::Tuple => (AggregateTy::Tuple, FIRST_VARIANT),
AggregateKind::Closure(did, substs)
| AggregateKind::Coroutine(did, substs, _) => {
(AggregateTy::Def(did, substs), FIRST_VARIANT)
}
AggregateKind::Adt(did, variant_index, substs, _, None) => {
(AggregateTy::Def(did, substs), variant_index)
}
// Do not track unions. // Do not track unions.
AggregateKind::Adt(_, _, _, _, Some(_)) => return None, AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
}; };
@ -672,7 +707,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
.iter_mut() .iter_mut()
.map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque())) .map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque()))
.collect(); .collect();
let ty = rvalue.ty(self.local_decls, self.tcx);
Value::Aggregate(ty, variant_index, fields?) Value::Aggregate(ty, variant_index, fields?)
} }
Rvalue::Ref(_, borrow_kind, ref mut place) => { Rvalue::Ref(_, borrow_kind, ref mut place) => {
@ -725,8 +759,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
fn simplify_discriminant(&mut self, place: VnIndex) -> Option<VnIndex> { fn simplify_discriminant(&mut self, place: VnIndex) -> Option<VnIndex> {
if let Value::Aggregate(enum_ty, variant, _) = *self.get(place) if let Value::Aggregate(enum_ty, variant, _) = *self.get(place)
&& enum_ty.is_enum() && let AggregateTy::Def(enum_did, enum_substs) = enum_ty
&& let DefKind::Enum = self.tcx.def_kind(enum_did)
{ {
let enum_ty = self.tcx.type_of(enum_did).instantiate(self.tcx, enum_substs);
let discr = self.ecx.discriminant_for_variant(enum_ty, variant).ok()?; let discr = self.ecx.discriminant_for_variant(enum_ty, variant).ok()?;
return Some(self.insert_scalar(discr.to_scalar(), discr.layout.ty)); return Some(self.insert_scalar(discr.to_scalar(), discr.layout.ty));
} }