Create mapped places upon seeing them in the body.
This commit is contained in:
parent
44fb8575de
commit
76f5bc6a9f
12 changed files with 271 additions and 272 deletions
|
@ -32,15 +32,16 @@
|
|||
//! Because of that, we can assume that the only way to change the value behind a tracked place is
|
||||
//! by direct assignment.
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::ops::Range;
|
||||
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::{FxHashMap, StdEntry};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
|
@ -58,7 +59,7 @@ pub trait ValueAnalysis<'tcx> {
|
|||
|
||||
const NAME: &'static str;
|
||||
|
||||
fn map(&self) -> ⤅
|
||||
fn map(&self) -> &Map<'tcx>;
|
||||
|
||||
fn handle_statement(&self, statement: &Statement<'tcx>, state: &mut State<Self::Value>) {
|
||||
self.super_statement(statement, state)
|
||||
|
@ -523,12 +524,12 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
}
|
||||
|
||||
/// Assign `value` to all places that are contained in `place` or may alias one.
|
||||
pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
|
||||
pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map<'_>, value: V) {
|
||||
self.flood_with_tail_elem(place, None, map, value)
|
||||
}
|
||||
|
||||
/// Assign `TOP` to all places that are contained in `place` or may alias one.
|
||||
pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map)
|
||||
pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map<'_>)
|
||||
where
|
||||
V: HasTop,
|
||||
{
|
||||
|
@ -536,12 +537,12 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
}
|
||||
|
||||
/// Assign `value` to the discriminant of `place` and all places that may alias it.
|
||||
fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
|
||||
fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map<'_>, value: V) {
|
||||
self.flood_with_tail_elem(place, Some(TrackElem::Discriminant), map, value)
|
||||
}
|
||||
|
||||
/// Assign `TOP` to the discriminant of `place` and all places that may alias it.
|
||||
pub fn flood_discr(&mut self, place: PlaceRef<'_>, map: &Map)
|
||||
pub fn flood_discr(&mut self, place: PlaceRef<'_>, map: &Map<'_>)
|
||||
where
|
||||
V: HasTop,
|
||||
{
|
||||
|
@ -559,7 +560,7 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
&mut self,
|
||||
place: PlaceRef<'_>,
|
||||
tail_elem: Option<TrackElem>,
|
||||
map: &Map,
|
||||
map: &Map<'_>,
|
||||
value: V,
|
||||
) {
|
||||
let State::Reachable(values) = self else { return };
|
||||
|
@ -570,7 +571,7 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
/// This does nothing if the place is not tracked.
|
||||
///
|
||||
/// The target place must have been flooded before calling this method.
|
||||
fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map) {
|
||||
fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map<'_>) {
|
||||
match result {
|
||||
ValueOrPlace::Value(value) => self.insert_value_idx(target, value, map),
|
||||
ValueOrPlace::Place(source) => self.insert_place_idx(target, source, map),
|
||||
|
@ -581,7 +582,7 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
/// This does nothing if the place is not tracked.
|
||||
///
|
||||
/// The target place must have been flooded before calling this method.
|
||||
pub fn insert_value_idx(&mut self, target: PlaceIndex, value: V, map: &Map) {
|
||||
pub fn insert_value_idx(&mut self, target: PlaceIndex, value: V, map: &Map<'_>) {
|
||||
let State::Reachable(values) = self else { return };
|
||||
if let Some(value_index) = map.places[target].value_index {
|
||||
values.insert(value_index, value)
|
||||
|
@ -595,7 +596,7 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
/// places that are non-overlapping or identical.
|
||||
///
|
||||
/// The target place must have been flooded before calling this method.
|
||||
pub fn insert_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map) {
|
||||
pub fn insert_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map<'_>) {
|
||||
let State::Reachable(values) = self else { return };
|
||||
|
||||
// If both places are tracked, we copy the value to the target.
|
||||
|
@ -616,7 +617,7 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
}
|
||||
|
||||
/// Helper method to interpret `target = result`.
|
||||
pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map)
|
||||
pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map<'_>)
|
||||
where
|
||||
V: HasTop,
|
||||
{
|
||||
|
@ -627,7 +628,7 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
}
|
||||
|
||||
/// Helper method for assignments to a discriminant.
|
||||
pub fn assign_discr(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map)
|
||||
pub fn assign_discr(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map<'_>)
|
||||
where
|
||||
V: HasTop,
|
||||
{
|
||||
|
@ -638,25 +639,25 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
}
|
||||
|
||||
/// Retrieve the value stored for a place, or `None` if it is not tracked.
|
||||
pub fn try_get(&self, place: PlaceRef<'_>, map: &Map) -> Option<V> {
|
||||
pub fn try_get(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
|
||||
let place = map.find(place)?;
|
||||
self.try_get_idx(place, map)
|
||||
}
|
||||
|
||||
/// Retrieve the discriminant stored for a place, or `None` if it is not tracked.
|
||||
pub fn try_get_discr(&self, place: PlaceRef<'_>, map: &Map) -> Option<V> {
|
||||
pub fn try_get_discr(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
|
||||
let place = map.find_discr(place)?;
|
||||
self.try_get_idx(place, map)
|
||||
}
|
||||
|
||||
/// Retrieve the slice length stored for a place, or `None` if it is not tracked.
|
||||
pub fn try_get_len(&self, place: PlaceRef<'_>, map: &Map) -> Option<V> {
|
||||
pub fn try_get_len(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
|
||||
let place = map.find_len(place)?;
|
||||
self.try_get_idx(place, map)
|
||||
}
|
||||
|
||||
/// Retrieve the value stored for a place index, or `None` if it is not tracked.
|
||||
pub fn try_get_idx(&self, place: PlaceIndex, map: &Map) -> Option<V> {
|
||||
pub fn try_get_idx(&self, place: PlaceIndex, map: &Map<'_>) -> Option<V> {
|
||||
match self {
|
||||
State::Reachable(values) => {
|
||||
map.places[place].value_index.map(|v| values.get(v).clone())
|
||||
|
@ -668,7 +669,7 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
/// Retrieve the value stored for a place, or ⊤ if it is not tracked.
|
||||
///
|
||||
/// This method returns ⊥ if the place is tracked and the state is unreachable.
|
||||
pub fn get(&self, place: PlaceRef<'_>, map: &Map) -> V
|
||||
pub fn get(&self, place: PlaceRef<'_>, map: &Map<'_>) -> V
|
||||
where
|
||||
V: HasBottom + HasTop,
|
||||
{
|
||||
|
@ -682,7 +683,7 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
/// Retrieve the value stored for a place, or ⊤ if it is not tracked.
|
||||
///
|
||||
/// This method returns ⊥ the current state is unreachable.
|
||||
pub fn get_discr(&self, place: PlaceRef<'_>, map: &Map) -> V
|
||||
pub fn get_discr(&self, place: PlaceRef<'_>, map: &Map<'_>) -> V
|
||||
where
|
||||
V: HasBottom + HasTop,
|
||||
{
|
||||
|
@ -696,7 +697,7 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
/// Retrieve the value stored for a place, or ⊤ if it is not tracked.
|
||||
///
|
||||
/// This method returns ⊥ the current state is unreachable.
|
||||
pub fn get_len(&self, place: PlaceRef<'_>, map: &Map) -> V
|
||||
pub fn get_len(&self, place: PlaceRef<'_>, map: &Map<'_>) -> V
|
||||
where
|
||||
V: HasBottom + HasTop,
|
||||
{
|
||||
|
@ -710,7 +711,7 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
/// Retrieve the value stored for a place index, or ⊤ if it is not tracked.
|
||||
///
|
||||
/// This method returns ⊥ the current state is unreachable.
|
||||
pub fn get_idx(&self, place: PlaceIndex, map: &Map) -> V
|
||||
pub fn get_idx(&self, place: PlaceIndex, map: &Map<'_>) -> V
|
||||
where
|
||||
V: HasBottom + HasTop,
|
||||
{
|
||||
|
@ -746,25 +747,25 @@ impl<V: JoinSemiLattice + Clone + HasBottom> JoinSemiLattice for State<V> {
|
|||
/// - For iteration, every [`PlaceInfo`] contains an intrusive linked list of its children.
|
||||
/// - To directly get the child for a specific projection, there is a `projections` map.
|
||||
#[derive(Debug)]
|
||||
pub struct Map {
|
||||
pub struct Map<'tcx> {
|
||||
locals: IndexVec<Local, Option<PlaceIndex>>,
|
||||
projections: FxHashMap<(PlaceIndex, TrackElem), PlaceIndex>,
|
||||
places: IndexVec<PlaceIndex, PlaceInfo>,
|
||||
places: IndexVec<PlaceIndex, PlaceInfo<'tcx>>,
|
||||
value_count: usize,
|
||||
// The Range corresponds to a slice into `inner_values_buffer`.
|
||||
inner_values: IndexVec<PlaceIndex, Range<usize>>,
|
||||
inner_values_buffer: Vec<ValueIndex>,
|
||||
}
|
||||
|
||||
impl Map {
|
||||
impl<'tcx> Map<'tcx> {
|
||||
/// Returns a map that only tracks places whose type has scalar layout.
|
||||
///
|
||||
/// This is currently the only way to create a [`Map`]. The way in which the tracked places are
|
||||
/// chosen is an implementation detail and may not be relied upon (other than that their type
|
||||
/// are scalars).
|
||||
pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, value_limit: Option<usize>) -> Self {
|
||||
pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, value_limit: Option<usize>) -> Self {
|
||||
let mut map = Self {
|
||||
locals: IndexVec::new(),
|
||||
locals: IndexVec::from_elem(None, &body.local_decls),
|
||||
projections: FxHashMap::default(),
|
||||
places: IndexVec::new(),
|
||||
value_count: 0,
|
||||
|
@ -778,18 +779,15 @@ impl Map {
|
|||
}
|
||||
|
||||
/// Register all non-excluded places that have scalar layout.
|
||||
fn register<'tcx>(
|
||||
#[tracing::instrument(level = "trace", skip(self, tcx, body))]
|
||||
fn register(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
exclude: BitSet<Local>,
|
||||
value_limit: Option<usize>,
|
||||
) {
|
||||
let mut worklist = VecDeque::with_capacity(value_limit.unwrap_or(body.local_decls.len()));
|
||||
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
|
||||
|
||||
// Start by constructing the places for each bare local.
|
||||
self.locals = IndexVec::from_elem(None, &body.local_decls);
|
||||
for (local, decl) in body.local_decls.iter_enumerated() {
|
||||
if exclude.contains(local) {
|
||||
continue;
|
||||
|
@ -797,16 +795,15 @@ impl Map {
|
|||
|
||||
// Create a place for the local.
|
||||
debug_assert!(self.locals[local].is_none());
|
||||
let place = self.places.push(PlaceInfo::new(None));
|
||||
let place = self.places.push(PlaceInfo::new(decl.ty, None));
|
||||
self.locals[local] = Some(place);
|
||||
|
||||
// And push the eventual children places to the worklist.
|
||||
self.register_children(tcx, param_env, place, decl.ty, &mut worklist);
|
||||
}
|
||||
|
||||
// `place.elem1.elem2` with type `ty`.
|
||||
// `elem1` is either `Some(Variant(i))` or `None`.
|
||||
while let Some((mut place, elem1, elem2, ty)) = worklist.pop_front() {
|
||||
PlaceCollector { tcx, body, map: self }.visit_body(body);
|
||||
|
||||
// Create values for places whose type have scalar layout.
|
||||
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
|
||||
for place_info in self.places.iter_mut() {
|
||||
// The user requires a bound on the number of created values.
|
||||
if let Some(value_limit) = value_limit
|
||||
&& self.value_count >= value_limit
|
||||
|
@ -814,19 +811,18 @@ impl Map {
|
|||
break;
|
||||
}
|
||||
|
||||
// Create a place for this projection.
|
||||
for elem in [elem1, Some(elem2)].into_iter().flatten() {
|
||||
place = *self.projections.entry((place, elem)).or_insert_with(|| {
|
||||
// Prepend new child to the linked list.
|
||||
let next = self.places.push(PlaceInfo::new(Some(elem)));
|
||||
self.places[next].next_sibling = self.places[place].first_child;
|
||||
self.places[place].first_child = Some(next);
|
||||
next
|
||||
});
|
||||
if let Ok(ty) = tcx.try_normalize_erasing_regions(param_env, place_info.ty) {
|
||||
place_info.ty = ty;
|
||||
}
|
||||
|
||||
// And push the eventual children places to the worklist.
|
||||
self.register_children(tcx, param_env, place, ty, &mut worklist);
|
||||
// Allocate a value slot if it doesn't have one, and the user requested one.
|
||||
assert!(place_info.value_index.is_none());
|
||||
if let Ok(layout) = tcx.layout_of(param_env.and(place_info.ty))
|
||||
&& layout.abi.is_scalar()
|
||||
{
|
||||
place_info.value_index = Some(self.value_count.into());
|
||||
self.value_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-compute the tree of ValueIndex nested in each PlaceIndex.
|
||||
|
@ -852,68 +848,14 @@ impl Map {
|
|||
self.projections.retain(|_, child| !self.inner_values[*child].is_empty());
|
||||
}
|
||||
|
||||
/// Potentially register the (local, projection) place and its fields, recursively.
|
||||
///
|
||||
/// Invariant: The projection must only contain trackable elements.
|
||||
fn register_children<'tcx>(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
place: PlaceIndex,
|
||||
ty: Ty<'tcx>,
|
||||
worklist: &mut VecDeque<(PlaceIndex, Option<TrackElem>, TrackElem, Ty<'tcx>)>,
|
||||
) {
|
||||
// Allocate a value slot if it doesn't have one, and the user requested one.
|
||||
assert!(self.places[place].value_index.is_none());
|
||||
if tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| layout.abi.is_scalar()) {
|
||||
self.places[place].value_index = Some(self.value_count.into());
|
||||
self.value_count += 1;
|
||||
}
|
||||
|
||||
// For enums, directly create the `Discriminant`, as that's their main use.
|
||||
if ty.is_enum() {
|
||||
// Prepend new child to the linked list.
|
||||
let discr = self.places.push(PlaceInfo::new(Some(TrackElem::Discriminant)));
|
||||
self.places[discr].next_sibling = self.places[place].first_child;
|
||||
self.places[place].first_child = Some(discr);
|
||||
let old = self.projections.insert((place, TrackElem::Discriminant), discr);
|
||||
assert!(old.is_none());
|
||||
|
||||
// Allocate a value slot since it doesn't have one.
|
||||
assert!(self.places[discr].value_index.is_none());
|
||||
self.places[discr].value_index = Some(self.value_count.into());
|
||||
self.value_count += 1;
|
||||
}
|
||||
|
||||
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.kind()
|
||||
&& let ty::Slice(..) = ref_ty.kind()
|
||||
// The user may have written a predicate like `[T]: Sized` in their where clauses,
|
||||
// which makes slices scalars.
|
||||
&& self.places[place].value_index.is_none()
|
||||
{
|
||||
// Prepend new child to the linked list.
|
||||
let len = self.places.push(PlaceInfo::new(Some(TrackElem::DerefLen)));
|
||||
self.places[len].next_sibling = self.places[place].first_child;
|
||||
self.places[place].first_child = Some(len);
|
||||
|
||||
let old = self.projections.insert((place, TrackElem::DerefLen), len);
|
||||
assert!(old.is_none());
|
||||
|
||||
// Allocate a value slot since it doesn't have one.
|
||||
assert!(self.places[len].value_index.is_none());
|
||||
self.places[len].value_index = Some(self.value_count.into());
|
||||
self.value_count += 1;
|
||||
}
|
||||
|
||||
// Recurse with all fields of this place.
|
||||
iter_fields(ty, tcx, param_env, |variant, field, ty| {
|
||||
worklist.push_back((
|
||||
place,
|
||||
variant.map(TrackElem::Variant),
|
||||
TrackElem::Field(field),
|
||||
ty,
|
||||
))
|
||||
});
|
||||
#[tracing::instrument(level = "trace", skip(self), ret)]
|
||||
fn register_place(&mut self, ty: Ty<'tcx>, base: PlaceIndex, elem: TrackElem) -> PlaceIndex {
|
||||
*self.projections.entry((base, elem)).or_insert_with(|| {
|
||||
let next = self.places.push(PlaceInfo::new(ty, Some(elem)));
|
||||
self.places[next].next_sibling = self.places[base].first_child;
|
||||
self.places[base].first_child = Some(next);
|
||||
next
|
||||
})
|
||||
}
|
||||
|
||||
/// Precompute the list of values inside `root` and store it inside
|
||||
|
@ -934,7 +876,54 @@ impl Map {
|
|||
let end = self.inner_values_buffer.len();
|
||||
self.inner_values[root] = start..end;
|
||||
}
|
||||
}
|
||||
|
||||
struct PlaceCollector<'a, 'b, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'b Body<'tcx>,
|
||||
map: &'a mut Map<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, '_, 'tcx> {
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, _: Location) {
|
||||
if !ctxt.is_use() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a place for this projection.
|
||||
let Some(mut place_index) = self.map.locals[place.local] else { return };
|
||||
let mut ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty);
|
||||
tracing::trace!(?place_index, ?ty);
|
||||
|
||||
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.ty.kind()
|
||||
&& let ty::Slice(..) = ref_ty.kind()
|
||||
{
|
||||
self.map.register_place(self.tcx.types.usize, place_index, TrackElem::DerefLen);
|
||||
} else if ty.ty.is_enum() {
|
||||
let discriminant_ty = ty.ty.discriminant_ty(self.tcx);
|
||||
self.map.register_place(discriminant_ty, place_index, TrackElem::Discriminant);
|
||||
}
|
||||
|
||||
for proj in place.projection {
|
||||
let Ok(track_elem) = proj.try_into() else { return };
|
||||
ty = ty.projection_ty(self.tcx, proj);
|
||||
place_index = self.map.register_place(ty.ty, place_index, track_elem);
|
||||
tracing::trace!(?proj, ?place_index, ?ty);
|
||||
|
||||
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.ty.kind()
|
||||
&& let ty::Slice(..) = ref_ty.kind()
|
||||
{
|
||||
self.map.register_place(self.tcx.types.usize, place_index, TrackElem::DerefLen);
|
||||
} else if ty.ty.is_enum() {
|
||||
let discriminant_ty = ty.ty.discriminant_ty(self.tcx);
|
||||
self.map.register_place(discriminant_ty, place_index, TrackElem::Discriminant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Map<'tcx> {
|
||||
/// Applies a single projection element, yielding the corresponding child.
|
||||
pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option<PlaceIndex> {
|
||||
self.projections.get(&(place, elem)).copied()
|
||||
|
@ -974,7 +963,10 @@ impl Map {
|
|||
}
|
||||
|
||||
/// Iterate over all direct children.
|
||||
fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> + '_ {
|
||||
fn children(
|
||||
&self,
|
||||
parent: PlaceIndex,
|
||||
) -> impl Iterator<Item = PlaceIndex> + Captures<'_> + Captures<'tcx> {
|
||||
Children::new(self, parent)
|
||||
}
|
||||
|
||||
|
@ -1081,7 +1073,10 @@ impl Map {
|
|||
/// Together, `first_child` and `next_sibling` form an intrusive linked list, which is used to
|
||||
/// model a tree structure (a replacement for a member like `children: Vec<PlaceIndex>`).
|
||||
#[derive(Debug)]
|
||||
struct PlaceInfo {
|
||||
struct PlaceInfo<'tcx> {
|
||||
/// Type of the referenced place.
|
||||
ty: Ty<'tcx>,
|
||||
|
||||
/// We store a [`ValueIndex`] if and only if the placed is tracked by the analysis.
|
||||
value_index: Option<ValueIndex>,
|
||||
|
||||
|
@ -1095,24 +1090,24 @@ struct PlaceInfo {
|
|||
next_sibling: Option<PlaceIndex>,
|
||||
}
|
||||
|
||||
impl PlaceInfo {
|
||||
fn new(proj_elem: Option<TrackElem>) -> Self {
|
||||
Self { next_sibling: None, first_child: None, proj_elem, value_index: None }
|
||||
impl<'tcx> PlaceInfo<'tcx> {
|
||||
fn new(ty: Ty<'tcx>, proj_elem: Option<TrackElem>) -> Self {
|
||||
Self { ty, next_sibling: None, first_child: None, proj_elem, value_index: None }
|
||||
}
|
||||
}
|
||||
|
||||
struct Children<'a> {
|
||||
map: &'a Map,
|
||||
struct Children<'a, 'tcx> {
|
||||
map: &'a Map<'tcx>,
|
||||
next: Option<PlaceIndex>,
|
||||
}
|
||||
|
||||
impl<'a> Children<'a> {
|
||||
fn new(map: &'a Map, parent: PlaceIndex) -> Self {
|
||||
impl<'a, 'tcx> Children<'a, 'tcx> {
|
||||
fn new(map: &'a Map<'tcx>, parent: PlaceIndex) -> Self {
|
||||
Self { map, next: map.places[parent].first_child }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Children<'a> {
|
||||
impl Iterator for Children<'_, '_> {
|
||||
type Item = PlaceIndex;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
@ -1261,7 +1256,7 @@ fn debug_with_context_rec<V: Debug + Eq + HasBottom>(
|
|||
place_str: &str,
|
||||
new: &StateData<V>,
|
||||
old: Option<&StateData<V>>,
|
||||
map: &Map,
|
||||
map: &Map<'_>,
|
||||
f: &mut Formatter<'_>,
|
||||
) -> std::fmt::Result {
|
||||
if let Some(value) = map.places[place].value_index {
|
||||
|
@ -1305,7 +1300,7 @@ fn debug_with_context_rec<V: Debug + Eq + HasBottom>(
|
|||
fn debug_with_context<V: Debug + Eq + HasBottom>(
|
||||
new: &StateData<V>,
|
||||
old: Option<&StateData<V>>,
|
||||
map: &Map,
|
||||
map: &Map<'_>,
|
||||
f: &mut Formatter<'_>,
|
||||
) -> std::fmt::Result {
|
||||
for (local, place) in map.locals.iter_enumerated() {
|
||||
|
|
|
@ -66,7 +66,7 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
|
|||
}
|
||||
|
||||
struct ConstAnalysis<'a, 'tcx> {
|
||||
map: Map,
|
||||
map: Map<'tcx>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
local_decls: &'a LocalDecls<'tcx>,
|
||||
ecx: InterpCx<'tcx, DummyMachine>,
|
||||
|
@ -78,7 +78,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
|||
|
||||
const NAME: &'static str = "ConstAnalysis";
|
||||
|
||||
fn map(&self) -> &Map {
|
||||
fn map(&self) -> &Map<'tcx> {
|
||||
&self.map
|
||||
}
|
||||
|
||||
|
@ -330,7 +330,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map) -> Self {
|
||||
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self {
|
||||
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
|
||||
Self {
|
||||
map,
|
||||
|
@ -560,12 +560,13 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> {
|
|||
Self { patch: Patch::new(tcx), local_decls }
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, ecx, map), ret)]
|
||||
fn try_make_constant(
|
||||
&self,
|
||||
ecx: &mut InterpCx<'tcx, DummyMachine>,
|
||||
place: Place<'tcx>,
|
||||
state: &State<FlatSet<Scalar>>,
|
||||
map: &Map,
|
||||
map: &Map<'tcx>,
|
||||
) -> Option<Const<'tcx>> {
|
||||
let ty = place.ty(self.local_decls, self.patch.tcx).ty;
|
||||
let layout = ecx.layout_of(ty).ok()?;
|
||||
|
@ -598,10 +599,11 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(map), ret)]
|
||||
fn propagatable_scalar(
|
||||
place: PlaceIndex,
|
||||
state: &State<FlatSet<Scalar>>,
|
||||
map: &Map,
|
||||
map: &Map<'_>,
|
||||
) -> Option<Scalar> {
|
||||
if let FlatSet::Elem(value) = state.get_idx(place, map)
|
||||
&& value.try_to_scalar_int().is_ok()
|
||||
|
@ -613,14 +615,14 @@ fn propagatable_scalar(
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(ecx, state, map))]
|
||||
#[instrument(level = "trace", skip(ecx, state, map), ret)]
|
||||
fn try_write_constant<'tcx>(
|
||||
ecx: &mut InterpCx<'tcx, DummyMachine>,
|
||||
dest: &PlaceTy<'tcx>,
|
||||
place: PlaceIndex,
|
||||
ty: Ty<'tcx>,
|
||||
state: &State<FlatSet<Scalar>>,
|
||||
map: &Map,
|
||||
map: &Map<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let layout = ecx.layout_of(ty)?;
|
||||
|
||||
|
@ -719,6 +721,7 @@ impl<'mir, 'tcx>
|
|||
{
|
||||
type FlowState = State<FlatSet<Scalar>>;
|
||||
|
||||
#[instrument(level = "trace", skip(self, results, statement))]
|
||||
fn visit_statement_before_primary_effect(
|
||||
&mut self,
|
||||
results: &mut Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>,
|
||||
|
@ -740,6 +743,7 @@ impl<'mir, 'tcx>
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, results, statement))]
|
||||
fn visit_statement_after_primary_effect(
|
||||
&mut self,
|
||||
results: &mut Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>,
|
||||
|
@ -834,7 +838,7 @@ struct OperandCollector<'tcx, 'map, 'locals, 'a> {
|
|||
state: &'a State<FlatSet<Scalar>>,
|
||||
visitor: &'a mut Collector<'tcx, 'locals>,
|
||||
ecx: &'map mut InterpCx<'tcx, DummyMachine>,
|
||||
map: &'map Map,
|
||||
map: &'map Map<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> {
|
||||
|
|
|
@ -123,7 +123,7 @@ struct TOFinder<'tcx, 'a> {
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
ecx: InterpCx<'tcx, DummyMachine>,
|
||||
body: &'a Body<'tcx>,
|
||||
map: &'a Map,
|
||||
map: &'a Map<'tcx>,
|
||||
loop_headers: &'a BitSet<BasicBlock>,
|
||||
/// We use an arena to avoid cloning the slices when cloning `state`.
|
||||
arena: &'a DroplessArena,
|
||||
|
|
|
@ -81,101 +81,130 @@ Number of file 0 mappings: 11
|
|||
= (((c4 + Zero) + Zero) + c3)
|
||||
|
||||
Function name: try_error_result::test2
|
||||
Raw bytes (280): 0x[01, 01, 24, 01, 07, 00, 09, 03, 0d, 41, 00, 1e, 00, 41, 00, 1e, 00, 41, 00, 4a, 00, 4e, 00, 52, 41, 03, 0d, 52, 41, 03, 0d, 4e, 00, 52, 41, 03, 0d, 4a, 00, 4e, 00, 52, 41, 03, 0d, 66, 00, 45, 00, 45, 00, 66, 00, 45, 00, 7a, 00, 4d, 00, 4d, 00, 7a, 00, 4d, 00, 83, 01, 0d, 87, 01, 00, 00, 8b, 01, 8f, 01, 00, 19, 00, 28, 01, 3d, 01, 03, 17, 03, 08, 09, 00, 0e, 52, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 00, 00, 2f, 00, 30, 1e, 00, 31, 03, 35, 00, 04, 11, 00, 12, 1a, 02, 11, 04, 12, 00, 05, 11, 00, 14, 1a, 00, 17, 00, 41, 19, 00, 41, 00, 42, 00, 00, 43, 00, 5f, 00, 00, 5f, 00, 60, 00, 01, 0d, 00, 20, 00, 01, 11, 00, 14, 00, 00, 17, 00, 41, 00, 00, 41, 00, 42, 00, 00, 43, 00, 60, 00, 00, 60, 00, 61, 00, 01, 0d, 00, 20, 46, 04, 11, 00, 14, 4e, 00, 17, 00, 42, 00, 00, 42, 00, 43, 4a, 00, 44, 00, 61, 00, 00, 61, 00, 62, 46, 01, 0d, 00, 20, 62, 01, 11, 00, 14, 45, 00, 17, 01, 36, 00, 01, 36, 00, 37, 66, 01, 12, 00, 2f, 00, 00, 2f, 00, 30, 62, 01, 0d, 00, 20, 76, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 00, 02, 11, 00, 12, 7a, 01, 12, 00, 2f, 00, 01, 11, 00, 12, 76, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, 7f, 01, 01, 00, 02]
|
||||
Raw bytes (358): 0x[01, 01, 3b, 01, 07, 05, 09, 03, 0d, 41, 11, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 4a, 15, 41, 11, 46, 19, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 5e, 25, 49, 21, 49, 21, 5e, 25, 49, 21, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, 92, 01, 41, 03, 0d, 8e, 01, 29, 92, 01, 41, 03, 0d, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, a6, 01, 35, 45, 31, 45, 31, a6, 01, 35, 45, 31, ba, 01, 3d, 4d, 39, 4d, 39, ba, 01, 3d, 4d, 39, c3, 01, 0d, c7, 01, db, 01, cb, 01, cf, 01, 11, 15, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3d, 01, 03, 17, 03, 08, 09, 00, 0e, 92, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 4a, 00, 31, 03, 35, 15, 04, 11, 00, 12, 46, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 46, 00, 17, 00, 41, 19, 00, 41, 00, 42, 42, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 5e, 00, 43, 00, 60, 25, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 8e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 8a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, a6, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, ba, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 36
|
||||
Number of expressions: 59
|
||||
- expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add)
|
||||
- expression 1 operands: lhs = Zero, rhs = Counter(2)
|
||||
- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
|
||||
- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
|
||||
- expression 3 operands: lhs = Counter(16), rhs = Zero
|
||||
- expression 4 operands: lhs = Expression(7, Sub), rhs = Zero
|
||||
- expression 5 operands: lhs = Counter(16), rhs = Zero
|
||||
- expression 6 operands: lhs = Expression(7, Sub), rhs = Zero
|
||||
- expression 7 operands: lhs = Counter(16), rhs = Zero
|
||||
- expression 8 operands: lhs = Expression(18, Sub), rhs = Zero
|
||||
- expression 9 operands: lhs = Expression(19, Sub), rhs = Zero
|
||||
- expression 10 operands: lhs = Expression(20, Sub), rhs = Counter(16)
|
||||
- expression 11 operands: lhs = Expression(0, Add), rhs = Counter(3)
|
||||
- expression 12 operands: lhs = Expression(20, Sub), rhs = Counter(16)
|
||||
- expression 13 operands: lhs = Expression(0, Add), rhs = Counter(3)
|
||||
- expression 14 operands: lhs = Expression(19, Sub), rhs = Zero
|
||||
- expression 15 operands: lhs = Expression(20, Sub), rhs = Counter(16)
|
||||
- expression 16 operands: lhs = Expression(0, Add), rhs = Counter(3)
|
||||
- expression 17 operands: lhs = Expression(18, Sub), rhs = Zero
|
||||
- expression 18 operands: lhs = Expression(19, Sub), rhs = Zero
|
||||
- expression 19 operands: lhs = Expression(20, Sub), rhs = Counter(16)
|
||||
- expression 20 operands: lhs = Expression(0, Add), rhs = Counter(3)
|
||||
- expression 21 operands: lhs = Expression(25, Sub), rhs = Zero
|
||||
- expression 22 operands: lhs = Counter(17), rhs = Zero
|
||||
- expression 23 operands: lhs = Counter(17), rhs = Zero
|
||||
- expression 24 operands: lhs = Expression(25, Sub), rhs = Zero
|
||||
- expression 25 operands: lhs = Counter(17), rhs = Zero
|
||||
- expression 26 operands: lhs = Expression(30, Sub), rhs = Zero
|
||||
- expression 27 operands: lhs = Counter(19), rhs = Zero
|
||||
- expression 28 operands: lhs = Counter(19), rhs = Zero
|
||||
- expression 29 operands: lhs = Expression(30, Sub), rhs = Zero
|
||||
- expression 30 operands: lhs = Counter(19), rhs = Zero
|
||||
- expression 31 operands: lhs = Expression(32, Add), rhs = Counter(3)
|
||||
- expression 32 operands: lhs = Expression(33, Add), rhs = Zero
|
||||
- expression 33 operands: lhs = Zero, rhs = Expression(34, Add)
|
||||
- expression 34 operands: lhs = Expression(35, Add), rhs = Zero
|
||||
- expression 35 operands: lhs = Counter(6), rhs = Zero
|
||||
- expression 3 operands: lhs = Counter(16), rhs = Counter(4)
|
||||
- expression 4 operands: lhs = Expression(18, Sub), rhs = Counter(5)
|
||||
- expression 5 operands: lhs = Counter(16), rhs = Counter(4)
|
||||
- expression 6 operands: lhs = Expression(16, Sub), rhs = Counter(7)
|
||||
- expression 7 operands: lhs = Expression(17, Sub), rhs = Counter(6)
|
||||
- expression 8 operands: lhs = Expression(18, Sub), rhs = Counter(5)
|
||||
- expression 9 operands: lhs = Counter(16), rhs = Counter(4)
|
||||
- expression 10 operands: lhs = Expression(18, Sub), rhs = Counter(5)
|
||||
- expression 11 operands: lhs = Counter(16), rhs = Counter(4)
|
||||
- expression 12 operands: lhs = Expression(17, Sub), rhs = Counter(6)
|
||||
- expression 13 operands: lhs = Expression(18, Sub), rhs = Counter(5)
|
||||
- expression 14 operands: lhs = Counter(16), rhs = Counter(4)
|
||||
- expression 15 operands: lhs = Expression(16, Sub), rhs = Counter(7)
|
||||
- expression 16 operands: lhs = Expression(17, Sub), rhs = Counter(6)
|
||||
- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5)
|
||||
- expression 18 operands: lhs = Counter(16), rhs = Counter(4)
|
||||
- expression 19 operands: lhs = Expression(23, Sub), rhs = Counter(9)
|
||||
- expression 20 operands: lhs = Counter(18), rhs = Counter(8)
|
||||
- expression 21 operands: lhs = Counter(18), rhs = Counter(8)
|
||||
- expression 22 operands: lhs = Expression(23, Sub), rhs = Counter(9)
|
||||
- expression 23 operands: lhs = Counter(18), rhs = Counter(8)
|
||||
- expression 24 operands: lhs = Expression(34, Sub), rhs = Counter(11)
|
||||
- expression 25 operands: lhs = Expression(35, Sub), rhs = Counter(10)
|
||||
- expression 26 operands: lhs = Expression(36, Sub), rhs = Counter(16)
|
||||
- expression 27 operands: lhs = Expression(0, Add), rhs = Counter(3)
|
||||
- expression 28 operands: lhs = Expression(36, Sub), rhs = Counter(16)
|
||||
- expression 29 operands: lhs = Expression(0, Add), rhs = Counter(3)
|
||||
- expression 30 operands: lhs = Expression(35, Sub), rhs = Counter(10)
|
||||
- expression 31 operands: lhs = Expression(36, Sub), rhs = Counter(16)
|
||||
- expression 32 operands: lhs = Expression(0, Add), rhs = Counter(3)
|
||||
- expression 33 operands: lhs = Expression(34, Sub), rhs = Counter(11)
|
||||
- expression 34 operands: lhs = Expression(35, Sub), rhs = Counter(10)
|
||||
- expression 35 operands: lhs = Expression(36, Sub), rhs = Counter(16)
|
||||
- expression 36 operands: lhs = Expression(0, Add), rhs = Counter(3)
|
||||
- expression 37 operands: lhs = Expression(41, Sub), rhs = Counter(13)
|
||||
- expression 38 operands: lhs = Counter(17), rhs = Counter(12)
|
||||
- expression 39 operands: lhs = Counter(17), rhs = Counter(12)
|
||||
- expression 40 operands: lhs = Expression(41, Sub), rhs = Counter(13)
|
||||
- expression 41 operands: lhs = Counter(17), rhs = Counter(12)
|
||||
- expression 42 operands: lhs = Expression(46, Sub), rhs = Counter(15)
|
||||
- expression 43 operands: lhs = Counter(19), rhs = Counter(14)
|
||||
- expression 44 operands: lhs = Counter(19), rhs = Counter(14)
|
||||
- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(15)
|
||||
- expression 46 operands: lhs = Counter(19), rhs = Counter(14)
|
||||
- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(3)
|
||||
- expression 48 operands: lhs = Expression(49, Add), rhs = Expression(54, Add)
|
||||
- expression 49 operands: lhs = Expression(50, Add), rhs = Expression(51, Add)
|
||||
- expression 50 operands: lhs = Counter(4), rhs = Counter(5)
|
||||
- expression 51 operands: lhs = Expression(52, Add), rhs = Expression(53, Add)
|
||||
- expression 52 operands: lhs = Counter(6), rhs = Counter(7)
|
||||
- expression 53 operands: lhs = Counter(8), rhs = Counter(9)
|
||||
- expression 54 operands: lhs = Expression(55, Add), rhs = Expression(56, Add)
|
||||
- expression 55 operands: lhs = Counter(10), rhs = Counter(11)
|
||||
- expression 56 operands: lhs = Expression(57, Add), rhs = Expression(58, Add)
|
||||
- expression 57 operands: lhs = Counter(12), rhs = Counter(13)
|
||||
- expression 58 operands: lhs = Counter(14), rhs = Counter(15)
|
||||
Number of file 0 mappings: 40
|
||||
- Code(Counter(0)) at (prev + 61, 1) to (start + 3, 23)
|
||||
- Code(Expression(0, Add)) at (prev + 8, 9) to (start + 0, 14)
|
||||
= (c0 + (Zero + c2))
|
||||
- Code(Expression(20, Sub)) at (prev + 2, 9) to (start + 4, 26)
|
||||
= ((c0 + (Zero + c2)) - c3)
|
||||
= (c0 + (c1 + c2))
|
||||
- Code(Expression(36, Sub)) at (prev + 2, 9) to (start + 4, 26)
|
||||
= ((c0 + (c1 + c2)) - c3)
|
||||
- Code(Counter(16)) at (prev + 6, 13) to (start + 0, 47)
|
||||
- Code(Zero) at (prev + 0, 47) to (start + 0, 48)
|
||||
- Code(Expression(7, Sub)) at (prev + 0, 49) to (start + 3, 53)
|
||||
= (c16 - Zero)
|
||||
- Code(Zero) at (prev + 4, 17) to (start + 0, 18)
|
||||
- Code(Expression(6, Sub)) at (prev + 2, 17) to (start + 4, 18)
|
||||
= ((c16 - Zero) - Zero)
|
||||
- Code(Zero) at (prev + 5, 17) to (start + 0, 20)
|
||||
- Code(Expression(6, Sub)) at (prev + 0, 23) to (start + 0, 65)
|
||||
= ((c16 - Zero) - Zero)
|
||||
- Code(Counter(4)) at (prev + 0, 47) to (start + 0, 48)
|
||||
- Code(Expression(18, Sub)) at (prev + 0, 49) to (start + 3, 53)
|
||||
= (c16 - c4)
|
||||
- Code(Counter(5)) at (prev + 4, 17) to (start + 0, 18)
|
||||
- Code(Expression(17, Sub)) at (prev + 2, 17) to (start + 4, 18)
|
||||
= ((c16 - c4) - c5)
|
||||
- Code(Expression(15, Sub)) at (prev + 5, 17) to (start + 0, 20)
|
||||
= ((((c16 - c4) - c5) - c6) - c7)
|
||||
- Code(Expression(17, Sub)) at (prev + 0, 23) to (start + 0, 65)
|
||||
= ((c16 - c4) - c5)
|
||||
- Code(Counter(6)) at (prev + 0, 65) to (start + 0, 66)
|
||||
- Code(Zero) at (prev + 0, 67) to (start + 0, 95)
|
||||
- Code(Zero) at (prev + 0, 95) to (start + 0, 96)
|
||||
- Code(Zero) at (prev + 1, 13) to (start + 0, 32)
|
||||
- Code(Zero) at (prev + 1, 17) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 23) to (start + 0, 65)
|
||||
- Code(Zero) at (prev + 0, 65) to (start + 0, 66)
|
||||
- Code(Zero) at (prev + 0, 67) to (start + 0, 96)
|
||||
- Code(Zero) at (prev + 0, 96) to (start + 0, 97)
|
||||
- Code(Zero) at (prev + 1, 13) to (start + 0, 32)
|
||||
- Code(Expression(17, Sub)) at (prev + 4, 17) to (start + 0, 20)
|
||||
= (((((c0 + (Zero + c2)) - c3) - c16) - Zero) - Zero)
|
||||
- Code(Expression(19, Sub)) at (prev + 0, 23) to (start + 0, 66)
|
||||
= (((c0 + (Zero + c2)) - c3) - c16)
|
||||
- Code(Zero) at (prev + 0, 66) to (start + 0, 67)
|
||||
- Code(Expression(18, Sub)) at (prev + 0, 68) to (start + 0, 97)
|
||||
= ((((c0 + (Zero + c2)) - c3) - c16) - Zero)
|
||||
- Code(Zero) at (prev + 0, 97) to (start + 0, 98)
|
||||
- Code(Expression(17, Sub)) at (prev + 1, 13) to (start + 0, 32)
|
||||
= (((((c0 + (Zero + c2)) - c3) - c16) - Zero) - Zero)
|
||||
- Code(Expression(24, Sub)) at (prev + 1, 17) to (start + 0, 20)
|
||||
= ((c17 - Zero) - Zero)
|
||||
- Code(Expression(16, Sub)) at (prev + 0, 67) to (start + 0, 95)
|
||||
= (((c16 - c4) - c5) - c6)
|
||||
- Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96)
|
||||
- Code(Expression(15, Sub)) at (prev + 1, 13) to (start + 0, 32)
|
||||
= ((((c16 - c4) - c5) - c6) - c7)
|
||||
- Code(Expression(22, Sub)) at (prev + 1, 17) to (start + 0, 20)
|
||||
= ((c18 - c8) - c9)
|
||||
- Code(Counter(18)) at (prev + 0, 23) to (start + 0, 65)
|
||||
- Code(Counter(8)) at (prev + 0, 65) to (start + 0, 66)
|
||||
- Code(Expression(23, Sub)) at (prev + 0, 67) to (start + 0, 96)
|
||||
= (c18 - c8)
|
||||
- Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97)
|
||||
- Code(Expression(22, Sub)) at (prev + 1, 13) to (start + 0, 32)
|
||||
= ((c18 - c8) - c9)
|
||||
- Code(Expression(33, Sub)) at (prev + 4, 17) to (start + 0, 20)
|
||||
= (((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11)
|
||||
- Code(Expression(35, Sub)) at (prev + 0, 23) to (start + 0, 66)
|
||||
= (((c0 + (c1 + c2)) - c3) - c16)
|
||||
- Code(Counter(10)) at (prev + 0, 66) to (start + 0, 67)
|
||||
- Code(Expression(34, Sub)) at (prev + 0, 68) to (start + 0, 97)
|
||||
= ((((c0 + (c1 + c2)) - c3) - c16) - c10)
|
||||
- Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98)
|
||||
- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 32)
|
||||
= (((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11)
|
||||
- Code(Expression(40, Sub)) at (prev + 1, 17) to (start + 0, 20)
|
||||
= ((c17 - c12) - c13)
|
||||
- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 54)
|
||||
- Code(Zero) at (prev + 1, 54) to (start + 0, 55)
|
||||
- Code(Expression(25, Sub)) at (prev + 1, 18) to (start + 0, 47)
|
||||
= (c17 - Zero)
|
||||
- Code(Zero) at (prev + 0, 47) to (start + 0, 48)
|
||||
- Code(Expression(24, Sub)) at (prev + 1, 13) to (start + 0, 32)
|
||||
= ((c17 - Zero) - Zero)
|
||||
- Code(Expression(29, Sub)) at (prev + 1, 17) to (start + 0, 20)
|
||||
= ((c19 - Zero) - Zero)
|
||||
- Code(Counter(12)) at (prev + 1, 54) to (start + 0, 55)
|
||||
- Code(Expression(41, Sub)) at (prev + 1, 18) to (start + 0, 47)
|
||||
= (c17 - c12)
|
||||
- Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48)
|
||||
- Code(Expression(40, Sub)) at (prev + 1, 13) to (start + 0, 32)
|
||||
= ((c17 - c12) - c13)
|
||||
- Code(Expression(45, Sub)) at (prev + 1, 17) to (start + 0, 20)
|
||||
= ((c19 - c14) - c15)
|
||||
- Code(Counter(19)) at (prev + 0, 23) to (start + 1, 54)
|
||||
- Code(Zero) at (prev + 2, 17) to (start + 0, 18)
|
||||
- Code(Expression(30, Sub)) at (prev + 1, 18) to (start + 0, 47)
|
||||
= (c19 - Zero)
|
||||
- Code(Zero) at (prev + 1, 17) to (start + 0, 18)
|
||||
- Code(Expression(29, Sub)) at (prev + 2, 13) to (start + 0, 32)
|
||||
= ((c19 - Zero) - Zero)
|
||||
- Code(Counter(14)) at (prev + 2, 17) to (start + 0, 18)
|
||||
- Code(Expression(46, Sub)) at (prev + 1, 18) to (start + 0, 47)
|
||||
= (c19 - c14)
|
||||
- Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18)
|
||||
- Code(Expression(45, Sub)) at (prev + 2, 13) to (start + 0, 32)
|
||||
= ((c19 - c14) - c15)
|
||||
- Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11)
|
||||
- Code(Expression(31, Add)) at (prev + 1, 1) to (start + 0, 2)
|
||||
= (((Zero + ((c6 + Zero) + Zero)) + Zero) + c3)
|
||||
- Code(Expression(47, Add)) at (prev + 1, 1) to (start + 0, 2)
|
||||
= ((((c4 + c5) + ((c6 + c7) + (c8 + c9))) + ((c10 + c11) + ((c12 + c13) + (c14 + c15)))) + c3)
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
StorageDead(_5);
|
||||
StorageDead(_4);
|
||||
- _2 = I32(move _3);
|
||||
+ _2 = const I32(0_i32);
|
||||
+ _2 = I32(const 0_i32);
|
||||
StorageDead(_3);
|
||||
_0 = const ();
|
||||
StorageDead(_2);
|
||||
|
@ -42,10 +42,6 @@
|
|||
+ }
|
||||
+
|
||||
+ ALLOC0 (size: 4, align: 4) {
|
||||
+ 00 00 00 00 │ ....
|
||||
+ }
|
||||
+
|
||||
+ ALLOC1 (size: 4, align: 4) {
|
||||
+ 00 00 00 00 │ ....
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,6 @@ fn main() {
|
|||
// CHECK: [[x]] = const I32(0_i32);
|
||||
let x = I32(0);
|
||||
|
||||
// CHECK: [[y]] = const I32(0_i32);
|
||||
// CHECK: [[y]] = I32(const 0_i32);
|
||||
let y = I32(x.0 + x.0);
|
||||
}
|
||||
|
|
|
@ -106,8 +106,7 @@
|
|||
- _7 = (_10.0: f32);
|
||||
+ _7 = const 4f32;
|
||||
StorageLive(_8);
|
||||
- _8 = (_10.1: std::option::Option<S>);
|
||||
+ _8 = const Option::<S>::Some(S(1_i32));
|
||||
_8 = (_10.1: std::option::Option<S>);
|
||||
StorageLive(_9);
|
||||
_9 = (_10.2: &[f32]);
|
||||
StorageDead(_10);
|
||||
|
@ -157,8 +156,7 @@
|
|||
+ _23 = const 82f32;
|
||||
StorageLive(_24);
|
||||
_37 = deref_copy (*_26);
|
||||
- _24 = ((*_37).1: std::option::Option<S>);
|
||||
+ _24 = const Option::<S>::Some(S(35_i32));
|
||||
_24 = ((*_37).1: std::option::Option<S>);
|
||||
StorageLive(_25);
|
||||
_38 = deref_copy (*_26);
|
||||
_25 = ((*_38).2: &[f32]);
|
||||
|
@ -168,12 +166,11 @@
|
|||
- _28 = _23;
|
||||
+ _28 = const 82f32;
|
||||
StorageLive(_29);
|
||||
- _29 = _24;
|
||||
+ _29 = const Option::<S>::Some(S(35_i32));
|
||||
_29 = _24;
|
||||
StorageLive(_30);
|
||||
_30 = _25;
|
||||
- _27 = BigStruct(move _28, move _29, move _30);
|
||||
+ _27 = BigStruct(const 82f32, const Option::<S>::Some(S(35_i32)), move _30);
|
||||
+ _27 = BigStruct(const 82f32, move _29, move _30);
|
||||
StorageDead(_30);
|
||||
StorageDead(_29);
|
||||
StorageDead(_28);
|
||||
|
@ -199,29 +196,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
+ ALLOC2 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC3 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC4 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC5 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC6 (size: 4, align: 4) { .. }
|
||||
+ ALLOC2 (size: 4, align: 4) { .. }
|
||||
+
|
||||
ALLOC1 (static: BIG_STAT, size: 4, align: 4) { .. }
|
||||
|
||||
- ALLOC2 (size: 20, align: 4) { .. }
|
||||
+ ALLOC7 (size: 20, align: 4) { .. }
|
||||
+ ALLOC3 (size: 20, align: 4) { .. }
|
||||
|
||||
- ALLOC3 (size: 8, align: 4) { .. }
|
||||
+ ALLOC8 (size: 8, align: 4) { .. }
|
||||
+ ALLOC4 (size: 8, align: 4) { .. }
|
||||
|
||||
ALLOC0 (static: SMALL_STAT, size: 4, align: 4) { .. }
|
||||
|
||||
- ALLOC4 (size: 20, align: 4) { .. }
|
||||
+ ALLOC9 (size: 20, align: 4) { .. }
|
||||
+ ALLOC5 (size: 20, align: 4) { .. }
|
||||
|
||||
- ALLOC5 (size: 4, align: 4) { .. }
|
||||
+ ALLOC10 (size: 4, align: 4) { .. }
|
||||
+ ALLOC6 (size: 4, align: 4) { .. }
|
||||
|
||||
|
|
|
@ -106,8 +106,7 @@
|
|||
- _7 = (_10.0: f32);
|
||||
+ _7 = const 4f32;
|
||||
StorageLive(_8);
|
||||
- _8 = (_10.1: std::option::Option<S>);
|
||||
+ _8 = const Option::<S>::Some(S(1_i32));
|
||||
_8 = (_10.1: std::option::Option<S>);
|
||||
StorageLive(_9);
|
||||
_9 = (_10.2: &[f32]);
|
||||
StorageDead(_10);
|
||||
|
@ -157,8 +156,7 @@
|
|||
+ _23 = const 82f32;
|
||||
StorageLive(_24);
|
||||
_37 = deref_copy (*_26);
|
||||
- _24 = ((*_37).1: std::option::Option<S>);
|
||||
+ _24 = const Option::<S>::Some(S(35_i32));
|
||||
_24 = ((*_37).1: std::option::Option<S>);
|
||||
StorageLive(_25);
|
||||
_38 = deref_copy (*_26);
|
||||
_25 = ((*_38).2: &[f32]);
|
||||
|
@ -168,12 +166,11 @@
|
|||
- _28 = _23;
|
||||
+ _28 = const 82f32;
|
||||
StorageLive(_29);
|
||||
- _29 = _24;
|
||||
+ _29 = const Option::<S>::Some(S(35_i32));
|
||||
_29 = _24;
|
||||
StorageLive(_30);
|
||||
_30 = _25;
|
||||
- _27 = BigStruct(move _28, move _29, move _30);
|
||||
+ _27 = BigStruct(const 82f32, const Option::<S>::Some(S(35_i32)), move _30);
|
||||
+ _27 = BigStruct(const 82f32, move _29, move _30);
|
||||
StorageDead(_30);
|
||||
StorageDead(_29);
|
||||
StorageDead(_28);
|
||||
|
@ -199,29 +196,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
+ ALLOC2 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC3 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC4 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC5 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC6 (size: 4, align: 4) { .. }
|
||||
+ ALLOC2 (size: 4, align: 4) { .. }
|
||||
+
|
||||
ALLOC1 (static: BIG_STAT, size: 8, align: 8) { .. }
|
||||
|
||||
- ALLOC2 (size: 32, align: 8) { .. }
|
||||
+ ALLOC7 (size: 32, align: 8) { .. }
|
||||
+ ALLOC3 (size: 32, align: 8) { .. }
|
||||
|
||||
- ALLOC3 (size: 8, align: 4) { .. }
|
||||
+ ALLOC8 (size: 8, align: 4) { .. }
|
||||
+ ALLOC4 (size: 8, align: 4) { .. }
|
||||
|
||||
ALLOC0 (static: SMALL_STAT, size: 8, align: 8) { .. }
|
||||
|
||||
- ALLOC4 (size: 32, align: 8) { .. }
|
||||
+ ALLOC9 (size: 32, align: 8) { .. }
|
||||
+ ALLOC5 (size: 32, align: 8) { .. }
|
||||
|
||||
- ALLOC5 (size: 4, align: 4) { .. }
|
||||
+ ALLOC10 (size: 4, align: 4) { .. }
|
||||
+ ALLOC6 (size: 4, align: 4) { .. }
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ fn main() {
|
|||
const SMALL_VAL: SmallStruct = SmallStruct(4., Some(S(1)), &[]);
|
||||
|
||||
// CHECK: [[a1]] = const 4f32;
|
||||
// CHECK: [[b1]] = const Option::<S>::Some(S(1_i32));
|
||||
// CHECK: [[b1]] = ({{_.*}}.1: std::option::Option<S>);
|
||||
// CHECK: [[c1]] = ({{_.*}}.2: &[f32]);
|
||||
let SmallStruct(a1, b1, c1) = SMALL_VAL;
|
||||
|
||||
|
@ -69,12 +69,12 @@ fn main() {
|
|||
|
||||
static BIG_STAT: &BigStruct = &BigStruct(82., Some(S(35)), &[45., 72.]);
|
||||
// CHECK: [[a4]] = const 82f32;
|
||||
// CHECK: [[b4]] = const Option::<S>::Some(S(35_i32));
|
||||
// CHECK: [[b4]] = ((*{{_.*}}).1: std::option::Option<S>);
|
||||
// CHECK: [[c4]] = ((*{{_.*}}).2: &[f32]);
|
||||
let BigStruct(a4, b4, c4) = *BIG_STAT;
|
||||
|
||||
// We arbitrarily limit the size of synthetized values to 4 pointers.
|
||||
// `BigStruct` can be read, but we will keep a MIR aggregate for this.
|
||||
// CHECK: [[bs]] = BigStruct(const 82f32, const Option::<S>::Some(S(35_i32)), move {{_.*}});
|
||||
// CHECK: [[bs]] = BigStruct(const 82f32, move {{.*}}, move {{_.*}});
|
||||
let bs = BigStruct(a4, b4, c4);
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
- _14 = _6;
|
||||
- _11 = (move _12, move _13, move _14);
|
||||
+ _14 = const 11_i32;
|
||||
+ _11 = (const 6_i32, const (2_i32, 3_i32), const 11_i32);
|
||||
+ _11 = (const 6_i32, move _13, const 11_i32);
|
||||
StorageDead(_14);
|
||||
StorageDead(_13);
|
||||
StorageDead(_12);
|
||||
|
@ -99,6 +99,4 @@
|
|||
+ ALLOC1 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC2 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC3 (size: 8, align: 4) { .. }
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
- _14 = _6;
|
||||
- _11 = (move _12, move _13, move _14);
|
||||
+ _14 = const 11_i32;
|
||||
+ _11 = (const 6_i32, const (2_i32, 3_i32), const 11_i32);
|
||||
+ _11 = (const 6_i32, move _13, const 11_i32);
|
||||
StorageDead(_14);
|
||||
StorageDead(_13);
|
||||
StorageDead(_12);
|
||||
|
@ -99,6 +99,4 @@
|
|||
+ ALLOC1 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC2 (size: 8, align: 4) { .. }
|
||||
+
|
||||
+ ALLOC3 (size: 8, align: 4) { .. }
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ fn main() {
|
|||
// CHECK: [[c]] = const 11_i32;
|
||||
let c = a.0 + a.1 + b;
|
||||
|
||||
// CHECK: [[d]] = (const 6_i32, const (2_i32, 3_i32), const 11_i32);
|
||||
// CHECK: [[a2:_.*]] = const (2_i32, 3_i32);
|
||||
// CHECK: [[d]] = (const 6_i32, move [[a2]], const 11_i32);
|
||||
let d = (b, a, c);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue