Rename rustc_mir to rustc_const_eval.

This commit is contained in:
Camille GILLOT
2021-01-05 20:08:11 +01:00
parent fd9c04fe32
commit c5fc2609f0
64 changed files with 66 additions and 66 deletions

View File

@@ -0,0 +1,75 @@
use rustc_index::vec::Idx;
use rustc_middle::mir::*;
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_target::abi::VariantIdx;
use std::convert::TryFrom;
use std::iter::TrustedLen;
/// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
///
/// Produces something like
///
/// (lhs as Variant).field0 = arg0; // We only have a downcast if this is an enum
/// (lhs as Variant).field1 = arg1;
/// discriminant(lhs) = variant_index; // If lhs is an enum or generator.
pub fn expand_aggregate<'tcx>(
mut lhs: Place<'tcx>,
operands: impl Iterator<Item = (Operand<'tcx>, Ty<'tcx>)> + TrustedLen,
kind: AggregateKind<'tcx>,
source_info: SourceInfo,
tcx: TyCtxt<'tcx>,
) -> impl Iterator<Item = Statement<'tcx>> + TrustedLen {
let mut set_discriminant = None;
let active_field_index = match kind {
AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
if adt_def.is_enum() {
set_discriminant = Some(Statement {
kind: StatementKind::SetDiscriminant { place: Box::new(lhs), variant_index },
source_info,
});
lhs = tcx.mk_place_downcast(lhs, adt_def, variant_index);
}
active_field_index
}
AggregateKind::Generator(..) => {
// Right now we only support initializing generators to
// variant 0 (Unresumed).
let variant_index = VariantIdx::new(0);
set_discriminant = Some(Statement {
kind: StatementKind::SetDiscriminant { place: Box::new(lhs), variant_index },
source_info,
});
// Operands are upvars stored on the base place, so no
// downcast is necessary.
None
}
_ => None,
};
operands
.enumerate()
.map(move |(i, (op, ty))| {
let lhs_field = if let AggregateKind::Array(_) = kind {
let offset = u64::try_from(i).unwrap();
tcx.mk_place_elem(
lhs,
ProjectionElem::ConstantIndex {
offset,
min_length: offset + 1,
from_end: false,
},
)
} else {
let field = Field::new(active_field_index.unwrap_or(i));
tcx.mk_place_field(lhs, field, ty)
};
Statement {
source_info,
kind: StatementKind::Assign(Box::new((lhs_field, Rvalue::Use(op)))),
}
})
.chain(set_discriminant)
}

View File

@@ -0,0 +1,70 @@
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
use rustc_target::abi::Align;
/// Returns `true` if this place is allowed to be less aligned
/// than its containing struct (because it is within a packed
/// struct).
pub fn is_disaligned<'tcx, L>(
tcx: TyCtxt<'tcx>,
local_decls: &L,
param_env: ty::ParamEnv<'tcx>,
place: Place<'tcx>,
) -> bool
where
L: HasLocalDecls<'tcx>,
{
debug!("is_disaligned({:?})", place);
let pack = match is_within_packed(tcx, local_decls, place) {
None => {
debug!("is_disaligned({:?}) - not within packed", place);
return false;
}
Some(pack) => pack,
};
let ty = place.ty(local_decls, tcx).ty;
match tcx.layout_of(param_env.and(ty)) {
Ok(layout) if layout.align.abi <= pack => {
// If the packed alignment is greater or equal to the field alignment, the type won't be
// further disaligned.
debug!(
"is_disaligned({:?}) - align = {}, packed = {}; not disaligned",
place,
layout.align.abi.bytes(),
pack.bytes()
);
false
}
_ => {
debug!("is_disaligned({:?}) - true", place);
true
}
}
}
fn is_within_packed<'tcx, L>(
tcx: TyCtxt<'tcx>,
local_decls: &L,
place: Place<'tcx>,
) -> Option<Align>
where
L: HasLocalDecls<'tcx>,
{
for (place_base, elem) in place.iter_projections().rev() {
match elem {
// encountered a Deref, which is ABI-aligned
ProjectionElem::Deref => break,
ProjectionElem::Field(..) => {
let ty = place_base.ty(local_decls, tcx).ty;
match ty.kind() {
ty::Adt(def, _) => return def.repr.pack,
_ => {}
}
}
_ => {}
}
}
None
}

View File

@@ -0,0 +1,36 @@
use rustc_middle::mir::visit::PlaceContext;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{Body, Local, Location};
pub trait FindAssignments {
// Finds all statements that assign directly to local (i.e., X = ...)
// and returns their locations.
fn find_assignments(&self, local: Local) -> Vec<Location>;
}
impl<'tcx> FindAssignments for Body<'tcx> {
fn find_assignments(&self, local: Local) -> Vec<Location> {
let mut visitor = FindLocalAssignmentVisitor { needle: local, locations: vec![] };
visitor.visit_body(self);
visitor.locations
}
}
// The Visitor walks the MIR to return the assignment statements corresponding
// to a Local.
struct FindLocalAssignmentVisitor {
needle: Local,
locations: Vec<Location>,
}
impl<'tcx> Visitor<'tcx> for FindLocalAssignmentVisitor {
fn visit_local(&mut self, local: &Local, place_context: PlaceContext, location: Location) {
if self.needle != *local {
return;
}
if place_context.is_place_assignment() {
self.locations.push(location);
}
}
}

View File

@@ -0,0 +1,36 @@
use rustc_middle::mir::*;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::def_id::DefId;
/// Checks if the specified `local` is used as the `self` parameter of a method call
/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
/// returned.
pub fn find_self_call<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
local: Local,
block: BasicBlock,
) -> Option<(DefId, SubstsRef<'tcx>)> {
debug!("find_self_call(local={:?}): terminator={:?}", local, &body[block].terminator);
if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
&body[block].terminator
{
debug!("find_self_call: func={:?}", func);
if let Operand::Constant(box Constant { literal, .. }) = func {
if let ty::FnDef(def_id, substs) = *literal.ty().kind() {
if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
tcx.opt_associated_item(def_id)
{
debug!("find_self_call: args={:?}", args);
if let [Operand::Move(self_place) | Operand::Copy(self_place), ..] = **args {
if self_place.as_local() == Some(local) {
return Some((def_id, substs));
}
}
}
}
}
}
None
}

View File

@@ -0,0 +1,8 @@
pub mod aggregate;
mod alignment;
pub mod collect_writes;
mod find_self_call;
pub use self::aggregate::expand_aggregate;
pub use self::alignment::is_disaligned;
pub use self::find_self_call::find_self_call;