impl_stable_hash_for!(enum mir::ValidationOp { Acquire, Release, Suspend(region_scope) });
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Lvalue<'gcx> {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Place<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
- mir::Lvalue::Local(ref local) => {
+ mir::Place::Local(ref local) => {
local.hash_stable(hcx, hasher);
}
- mir::Lvalue::Static(ref statik) => {
+ mir::Place::Static(ref statik) => {
statik.hash_stable(hcx, hasher);
}
- mir::Lvalue::Projection(ref lvalue_projection) => {
+ mir::Place::Projection(ref lvalue_projection) => {
lvalue_projection.hash_stable(hcx, hasher);
}
}
use middle::free_region::{FreeRegionMap, RegionRelations};
use middle::region;
use middle::lang_items;
-use mir::tcx::LvalueTy;
+use mir::tcx::PlaceTy;
use ty::subst::{Kind, Subst, Substs};
use ty::{TyVid, IntVid, FloatVid};
use ty::{self, Ty, TyCtxt};
ty::ExistentialTraitRef<'gcx>
);
-impl<'gcx> TransNormalize<'gcx> for LvalueTy<'gcx> {
+impl<'gcx> TransNormalize<'gcx> for PlaceTy<'gcx> {
fn trans_normalize<'a, 'tcx>(&self,
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>)
-> Self {
match *self {
- LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.trans_normalize(infcx, param_env) },
- LvalueTy::Downcast { adt_def, substs, variant_index } => {
- LvalueTy::Downcast {
+ PlaceTy::Ty { ty } => PlaceTy::Ty { ty: ty.trans_normalize(infcx, param_env) },
+ PlaceTy::Downcast { adt_def, substs, variant_index } => {
+ PlaceTy::Downcast {
adt_def,
substs: substs.trans_normalize(infcx, param_env),
variant_index,
/// Indicates a terminator that can never be reached.
Unreachable,
- /// Drop the Lvalue
+ /// Drop the Place
Drop {
- location: Lvalue<'tcx>,
+ location: Place<'tcx>,
target: BasicBlock,
unwind: Option<BasicBlock>
},
- /// Drop the Lvalue and assign the new value over it. This ensures
+ /// Drop the Place and assign the new value over it. This ensures
/// that the assignment to LV occurs *even if* the destructor for
/// lvalue unwinds. Its semantics are best explained by by the
/// elaboration:
/// }
/// ```
DropAndReplace {
- location: Lvalue<'tcx>,
+ location: Place<'tcx>,
value: Operand<'tcx>,
target: BasicBlock,
unwind: Option<BasicBlock>,
/// reused across function calls without duplicating the contents.
args: Vec<Operand<'tcx>>,
/// Destination for the return value. If some, the call is converging.
- destination: Option<(Lvalue<'tcx>, BasicBlock)>,
+ destination: Option<(Place<'tcx>, BasicBlock)>,
/// Cleanups to be done if the call unwinds.
cleanup: Option<BasicBlock>
},
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum StatementKind<'tcx> {
- /// Write the RHS Rvalue to the LHS Lvalue.
- Assign(Lvalue<'tcx>, Rvalue<'tcx>),
+ /// Write the RHS Rvalue to the LHS Place.
+ Assign(Place<'tcx>, Rvalue<'tcx>),
- /// Write the discriminant for a variant to the enum Lvalue.
- SetDiscriminant { lvalue: Lvalue<'tcx>, variant_index: usize },
+ /// Write the discriminant for a variant to the enum Place.
+ SetDiscriminant { lvalue: Place<'tcx>, variant_index: usize },
/// Start a live range for the storage of the local.
StorageLive(Local),
/// Execute a piece of inline Assembly.
InlineAsm {
asm: Box<InlineAsm>,
- outputs: Vec<Lvalue<'tcx>>,
+ outputs: Vec<Place<'tcx>>,
inputs: Vec<Operand<'tcx>>
},
/// Assert the given lvalues to be valid inhabitants of their type. These statements are
/// currently only interpreted by miri and only generated when "-Z mir-emit-validate" is passed.
/// See <https://internals.rust-lang.org/t/types-as-contracts/5562/73> for more details.
- Validate(ValidationOp, Vec<ValidationOperand<'tcx, Lvalue<'tcx>>>),
+ Validate(ValidationOp, Vec<ValidationOperand<'tcx, Place<'tcx>>>),
/// Mark one terminating point of a region scope (i.e. static region).
/// (The starting point(s) arise implicitly from borrows.)
}
///////////////////////////////////////////////////////////////////////////
-// Lvalues
+// Places
/// A path to a value; something that can be evaluated without
/// changing or disturbing program state.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
-pub enum Lvalue<'tcx> {
+pub enum Place<'tcx> {
/// local variable
Local(Local),
Static(Box<Static<'tcx>>),
/// projection out of an lvalue (access a field, deref a pointer, etc)
- Projection(Box<LvalueProjection<'tcx>>),
+ Projection(Box<PlaceProjection<'tcx>>),
}
/// The def-id of a static, along with its normalized type (which is
/// The `Projection` data structure defines things of the form `B.x`
/// or `*B` or `B[index]`. Note that it is parameterized because it is
-/// shared between `Constant` and `Lvalue`. See the aliases
-/// `LvalueProjection` etc below.
+/// shared between `Constant` and `Place`. See the aliases
+/// `PlaceProjection` etc below.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct Projection<'tcx, B, V, T> {
pub base: B,
/// Alias for projections as they appear in lvalues, where the base is an lvalue
/// and the index is a local.
-pub type LvalueProjection<'tcx> = Projection<'tcx, Lvalue<'tcx>, Local, Ty<'tcx>>;
+pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>;
/// Alias for projections as they appear in lvalues, where the base is an lvalue
/// and the index is a local.
-pub type LvalueElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
+pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
newtype_index!(Field { DEBUG_FORMAT = "field[{}]" });
-impl<'tcx> Lvalue<'tcx> {
- pub fn field(self, f: Field, ty: Ty<'tcx>) -> Lvalue<'tcx> {
+impl<'tcx> Place<'tcx> {
+ pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
self.elem(ProjectionElem::Field(f, ty))
}
- pub fn deref(self) -> Lvalue<'tcx> {
+ pub fn deref(self) -> Place<'tcx> {
self.elem(ProjectionElem::Deref)
}
- pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Lvalue<'tcx> {
+ pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Place<'tcx> {
self.elem(ProjectionElem::Downcast(adt_def, variant_index))
}
- pub fn index(self, index: Local) -> Lvalue<'tcx> {
+ pub fn index(self, index: Local) -> Place<'tcx> {
self.elem(ProjectionElem::Index(index))
}
- pub fn elem(self, elem: LvalueElem<'tcx>) -> Lvalue<'tcx> {
- Lvalue::Projection(Box::new(LvalueProjection {
+ pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> {
+ Place::Projection(Box::new(PlaceProjection {
base: self,
elem,
}))
}
}
-impl<'tcx> Debug for Lvalue<'tcx> {
+impl<'tcx> Debug for Place<'tcx> {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
- use self::Lvalue::*;
+ use self::Place::*;
match *self {
Local(id) => write!(fmt, "{:?}", id),
///
/// This implies that the type of the lvalue must be `Copy`; this is true
/// by construction during build, but also checked by the MIR type checker.
- Copy(Lvalue<'tcx>),
+ Copy(Place<'tcx>),
/// Move: The value (including old borrows of it) will not be used again.
///
/// Safe for values of all types (modulo future developments towards `?Move`).
/// Correct usage patterns are enforced by the borrow checker for safe code.
/// `Copy` may be converted to `Move` to enable "last-use" optimizations.
- Move(Lvalue<'tcx>),
+ Move(Place<'tcx>),
Constant(Box<Constant<'tcx>>),
}
Repeat(Operand<'tcx>, ConstUsize),
/// &x or &mut x
- Ref(Region<'tcx>, BorrowKind, Lvalue<'tcx>),
+ Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
/// length of a [X] or [X;n] value
- Len(Lvalue<'tcx>),
+ Len(Place<'tcx>),
Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
///
/// Undefined (i.e. no effort is made to make it defined, but there’s no reason why it cannot
/// be defined to return, say, a 0) if ADT is not an enum.
- Discriminant(Lvalue<'tcx>),
+ Discriminant(Place<'tcx>),
/// Create an aggregate value, like a tuple or struct. This is
/// only needed because we want to distinguish `dest = Foo { x:
}
}
-impl<'tcx> TypeFoldable<'tcx> for ValidationOperand<'tcx, Lvalue<'tcx>> {
+impl<'tcx> TypeFoldable<'tcx> for ValidationOperand<'tcx, Place<'tcx>> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ValidationOperand {
lval: self.lval.fold_with(folder),
}
}
-impl<'tcx> TypeFoldable<'tcx> for Lvalue<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
match self {
- &Lvalue::Projection(ref p) => Lvalue::Projection(p.fold_with(folder)),
+ &Place::Projection(ref p) => Place::Projection(p.fold_with(folder)),
_ => self.clone()
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
- if let &Lvalue::Projection(ref p) = self {
+ if let &Place::Projection(ref p) = self {
p.visit_with(visitor)
} else {
false
use ty::util::IntTypeExt;
#[derive(Copy, Clone, Debug)]
-pub enum LvalueTy<'tcx> {
+pub enum PlaceTy<'tcx> {
/// Normal type.
Ty { ty: Ty<'tcx> },
variant_index: usize },
}
-impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> {
- pub fn from_ty(ty: Ty<'tcx>) -> LvalueTy<'tcx> {
- LvalueTy::Ty { ty: ty }
+impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
+ pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
+ PlaceTy::Ty { ty: ty }
}
pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
match *self {
- LvalueTy::Ty { ty } =>
+ PlaceTy::Ty { ty } =>
ty,
- LvalueTy::Downcast { adt_def, substs, variant_index: _ } =>
+ PlaceTy::Downcast { adt_def, substs, variant_index: _ } =>
tcx.mk_adt(adt_def, substs),
}
}
pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
- elem: &LvalueElem<'tcx>)
- -> LvalueTy<'tcx>
+ elem: &PlaceElem<'tcx>)
+ -> PlaceTy<'tcx>
{
match *elem {
ProjectionElem::Deref => {
bug!("deref projection of non-dereferencable ty {:?}", self)
})
.ty;
- LvalueTy::Ty {
+ PlaceTy::Ty {
ty,
}
}
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
- LvalueTy::Ty {
+ PlaceTy::Ty {
ty: self.to_ty(tcx).builtin_index().unwrap()
},
ProjectionElem::Subslice { from, to } => {
let ty = self.to_ty(tcx);
- LvalueTy::Ty {
+ PlaceTy::Ty {
ty: match ty.sty {
ty::TyArray(inner, size) => {
let size = size.val.to_const_int().unwrap().to_u64().unwrap();
assert!(adt_def.is_enum());
assert!(index < adt_def.variants.len());
assert_eq!(adt_def, adt_def1);
- LvalueTy::Downcast { adt_def,
+ PlaceTy::Downcast { adt_def,
substs,
variant_index: index }
}
bug!("cannot downcast non-ADT type: `{:?}`", self)
}
},
- ProjectionElem::Field(_, fty) => LvalueTy::Ty { ty: fty }
+ ProjectionElem::Field(_, fty) => PlaceTy::Ty { ty: fty }
}
}
}
-impl<'tcx> TypeFoldable<'tcx> for LvalueTy<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for PlaceTy<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
match *self {
- LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.fold_with(folder) },
- LvalueTy::Downcast { adt_def, substs, variant_index } => {
- LvalueTy::Downcast {
+ PlaceTy::Ty { ty } => PlaceTy::Ty { ty: ty.fold_with(folder) },
+ PlaceTy::Downcast { adt_def, substs, variant_index } => {
+ PlaceTy::Downcast {
adt_def,
substs: substs.fold_with(folder),
variant_index,
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match *self {
- LvalueTy::Ty { ty } => ty.visit_with(visitor),
- LvalueTy::Downcast { substs, .. } => substs.visit_with(visitor)
+ PlaceTy::Ty { ty } => ty.visit_with(visitor),
+ PlaceTy::Downcast { substs, .. } => substs.visit_with(visitor)
}
}
}
-impl<'tcx> Lvalue<'tcx> {
- pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx>
+impl<'tcx> Place<'tcx> {
+ pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PlaceTy<'tcx>
where D: HasLocalDecls<'tcx>
{
match *self {
- Lvalue::Local(index) =>
- LvalueTy::Ty { ty: local_decls.local_decls()[index].ty },
- Lvalue::Static(ref data) =>
- LvalueTy::Ty { ty: data.ty },
- Lvalue::Projection(ref proj) =>
+ Place::Local(index) =>
+ PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
+ Place::Static(ref data) =>
+ PlaceTy::Ty { ty: data.ty },
+ Place::Projection(ref proj) =>
proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
}
}
} else {
// Undefined behaviour, bug for now; may want to return something for
// the `discriminant` intrinsic later.
- bug!("Rvalue::Discriminant on Lvalue of type {:?}", ty);
+ bug!("Rvalue::Discriminant on Place of type {:?}", ty);
}
}
Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t),
fn visit_assign(&mut self,
block: BasicBlock,
- lvalue: & $($mutability)* Lvalue<'tcx>,
+ lvalue: & $($mutability)* Place<'tcx>,
rvalue: & $($mutability)* Rvalue<'tcx>,
location: Location) {
self.super_assign(block, lvalue, rvalue, location);
}
fn visit_lvalue(&mut self,
- lvalue: & $($mutability)* Lvalue<'tcx>,
- context: LvalueContext<'tcx>,
+ lvalue: & $($mutability)* Place<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
self.super_lvalue(lvalue, context, location);
}
fn visit_static(&mut self,
static_: & $($mutability)* Static<'tcx>,
- context: LvalueContext<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
self.super_static(static_, context, location);
}
fn visit_projection(&mut self,
- lvalue: & $($mutability)* LvalueProjection<'tcx>,
- context: LvalueContext<'tcx>,
+ lvalue: & $($mutability)* PlaceProjection<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
self.super_projection(lvalue, context, location);
}
fn visit_projection_elem(&mut self,
- lvalue: & $($mutability)* LvalueElem<'tcx>,
- context: LvalueContext<'tcx>,
+ lvalue: & $($mutability)* PlaceElem<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
self.super_projection_elem(lvalue, context, location);
}
fn visit_local(&mut self,
_local: & $($mutability)* Local,
- _context: LvalueContext<'tcx>,
+ _context: PlaceContext<'tcx>,
_location: Location) {
}
StatementKind::Validate(_, ref $($mutability)* lvalues) => {
for operand in lvalues {
self.visit_lvalue(& $($mutability)* operand.lval,
- LvalueContext::Validate, location);
+ PlaceContext::Validate, location);
self.visit_ty(& $($mutability)* operand.ty,
TyContext::Location(location));
}
}
StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
- self.visit_lvalue(lvalue, LvalueContext::Store, location);
+ self.visit_lvalue(lvalue, PlaceContext::Store, location);
}
StatementKind::StorageLive(ref $($mutability)* local) => {
- self.visit_local(local, LvalueContext::StorageLive, location);
+ self.visit_local(local, PlaceContext::StorageLive, location);
}
StatementKind::StorageDead(ref $($mutability)* local) => {
- self.visit_local(local, LvalueContext::StorageDead, location);
+ self.visit_local(local, PlaceContext::StorageDead, location);
}
StatementKind::InlineAsm { ref $($mutability)* outputs,
ref $($mutability)* inputs,
asm: _ } => {
for output in & $($mutability)* outputs[..] {
- self.visit_lvalue(output, LvalueContext::Store, location);
+ self.visit_lvalue(output, PlaceContext::Store, location);
}
for input in & $($mutability)* inputs[..] {
self.visit_operand(input, location);
fn super_assign(&mut self,
_block: BasicBlock,
- lvalue: &$($mutability)* Lvalue<'tcx>,
+ lvalue: &$($mutability)* Place<'tcx>,
rvalue: &$($mutability)* Rvalue<'tcx>,
location: Location) {
- self.visit_lvalue(lvalue, LvalueContext::Store, location);
+ self.visit_lvalue(lvalue, PlaceContext::Store, location);
self.visit_rvalue(rvalue, location);
}
TerminatorKind::Drop { ref $($mutability)* location,
target,
unwind } => {
- self.visit_lvalue(location, LvalueContext::Drop, source_location);
+ self.visit_lvalue(location, PlaceContext::Drop, source_location);
self.visit_branch(block, target);
unwind.map(|t| self.visit_branch(block, t));
}
ref $($mutability)* value,
target,
unwind } => {
- self.visit_lvalue(location, LvalueContext::Drop, source_location);
+ self.visit_lvalue(location, PlaceContext::Drop, source_location);
self.visit_operand(value, source_location);
self.visit_branch(block, target);
unwind.map(|t| self.visit_branch(block, t));
self.visit_operand(arg, source_location);
}
if let Some((ref $($mutability)* destination, target)) = *destination {
- self.visit_lvalue(destination, LvalueContext::Call, source_location);
+ self.visit_lvalue(destination, PlaceContext::Call, source_location);
self.visit_branch(block, target);
}
cleanup.map(|t| self.visit_branch(block, t));
Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => {
self.visit_region(r, location);
- self.visit_lvalue(path, LvalueContext::Borrow {
+ self.visit_lvalue(path, PlaceContext::Borrow {
region: *r,
kind: bk
}, location);
}
Rvalue::Len(ref $($mutability)* path) => {
- self.visit_lvalue(path, LvalueContext::Inspect, location);
+ self.visit_lvalue(path, PlaceContext::Inspect, location);
}
Rvalue::Cast(_cast_kind,
}
Rvalue::Discriminant(ref $($mutability)* lvalue) => {
- self.visit_lvalue(lvalue, LvalueContext::Inspect, location);
+ self.visit_lvalue(lvalue, PlaceContext::Inspect, location);
}
Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
location: Location) {
match *operand {
Operand::Copy(ref $($mutability)* lvalue) => {
- self.visit_lvalue(lvalue, LvalueContext::Copy, location);
+ self.visit_lvalue(lvalue, PlaceContext::Copy, location);
}
Operand::Move(ref $($mutability)* lvalue) => {
- self.visit_lvalue(lvalue, LvalueContext::Move, location);
+ self.visit_lvalue(lvalue, PlaceContext::Move, location);
}
Operand::Constant(ref $($mutability)* constant) => {
self.visit_constant(constant, location);
}
fn super_lvalue(&mut self,
- lvalue: & $($mutability)* Lvalue<'tcx>,
- context: LvalueContext<'tcx>,
+ lvalue: & $($mutability)* Place<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
match *lvalue {
- Lvalue::Local(ref $($mutability)* local) => {
+ Place::Local(ref $($mutability)* local) => {
self.visit_local(local, context, location);
}
- Lvalue::Static(ref $($mutability)* static_) => {
+ Place::Static(ref $($mutability)* static_) => {
self.visit_static(static_, context, location);
}
- Lvalue::Projection(ref $($mutability)* proj) => {
+ Place::Projection(ref $($mutability)* proj) => {
self.visit_projection(proj, context, location);
}
}
fn super_static(&mut self,
static_: & $($mutability)* Static<'tcx>,
- _context: LvalueContext<'tcx>,
+ _context: PlaceContext<'tcx>,
location: Location) {
let Static {
ref $($mutability)* def_id,
}
fn super_projection(&mut self,
- proj: & $($mutability)* LvalueProjection<'tcx>,
- context: LvalueContext<'tcx>,
+ proj: & $($mutability)* PlaceProjection<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
let Projection {
ref $($mutability)* base,
ref $($mutability)* elem,
} = *proj;
let context = if context.is_mutating_use() {
- LvalueContext::Projection(Mutability::Mut)
+ PlaceContext::Projection(Mutability::Mut)
} else {
- LvalueContext::Projection(Mutability::Not)
+ PlaceContext::Projection(Mutability::Not)
};
self.visit_lvalue(base, context, location);
self.visit_projection_elem(elem, context, location);
}
fn super_projection_elem(&mut self,
- proj: & $($mutability)* LvalueElem<'tcx>,
- _context: LvalueContext<'tcx>,
+ proj: & $($mutability)* PlaceElem<'tcx>,
+ _context: PlaceContext<'tcx>,
location: Location) {
match *proj {
ProjectionElem::Deref => {
self.visit_ty(ty, TyContext::Location(location));
}
ProjectionElem::Index(ref $($mutability)* local) => {
- self.visit_local(local, LvalueContext::Copy, location);
+ self.visit_local(local, PlaceContext::Copy, location);
}
ProjectionElem::ConstantIndex { offset: _,
min_length: _,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum LvalueContext<'tcx> {
+pub enum PlaceContext<'tcx> {
// Appears as LHS of an assignment
Store,
Validate,
}
-impl<'tcx> LvalueContext<'tcx> {
+impl<'tcx> PlaceContext<'tcx> {
/// Returns true if this lvalue context represents a drop.
pub fn is_drop(&self) -> bool {
match *self {
- LvalueContext::Drop => true,
+ PlaceContext::Drop => true,
_ => false,
}
}
/// Returns true if this lvalue context represents a storage live or storage dead marker.
pub fn is_storage_marker(&self) -> bool {
match *self {
- LvalueContext::StorageLive | LvalueContext::StorageDead => true,
+ PlaceContext::StorageLive | PlaceContext::StorageDead => true,
_ => false,
}
}
/// Returns true if this lvalue context represents a storage live marker.
pub fn is_storage_live_marker(&self) -> bool {
match *self {
- LvalueContext::StorageLive => true,
+ PlaceContext::StorageLive => true,
_ => false,
}
}
/// Returns true if this lvalue context represents a storage dead marker.
pub fn is_storage_dead_marker(&self) -> bool {
match *self {
- LvalueContext::StorageDead => true,
+ PlaceContext::StorageDead => true,
_ => false,
}
}
/// Returns true if this lvalue context represents a use that potentially changes the value.
pub fn is_mutating_use(&self) -> bool {
match *self {
- LvalueContext::Store | LvalueContext::Call |
- LvalueContext::Borrow { kind: BorrowKind::Mut, .. } |
- LvalueContext::Projection(Mutability::Mut) |
- LvalueContext::Drop => true,
- LvalueContext::Inspect |
- LvalueContext::Borrow { kind: BorrowKind::Shared, .. } |
- LvalueContext::Borrow { kind: BorrowKind::Unique, .. } |
- LvalueContext::Projection(Mutability::Not) |
- LvalueContext::Copy | LvalueContext::Move |
- LvalueContext::StorageLive | LvalueContext::StorageDead |
- LvalueContext::Validate => false,
+ PlaceContext::Store | PlaceContext::Call |
+ PlaceContext::Borrow { kind: BorrowKind::Mut, .. } |
+ PlaceContext::Projection(Mutability::Mut) |
+ PlaceContext::Drop => true,
+ PlaceContext::Inspect |
+ PlaceContext::Borrow { kind: BorrowKind::Shared, .. } |
+ PlaceContext::Borrow { kind: BorrowKind::Unique, .. } |
+ PlaceContext::Projection(Mutability::Not) |
+ PlaceContext::Copy | PlaceContext::Move |
+ PlaceContext::StorageLive | PlaceContext::StorageDead |
+ PlaceContext::Validate => false,
}
}
/// Returns true if this lvalue context represents a use that does not change the value.
pub fn is_nonmutating_use(&self) -> bool {
match *self {
- LvalueContext::Inspect | LvalueContext::Borrow { kind: BorrowKind::Shared, .. } |
- LvalueContext::Borrow { kind: BorrowKind::Unique, .. } |
- LvalueContext::Projection(Mutability::Not) |
- LvalueContext::Copy | LvalueContext::Move => true,
- LvalueContext::Borrow { kind: BorrowKind::Mut, .. } | LvalueContext::Store |
- LvalueContext::Call | LvalueContext::Projection(Mutability::Mut) |
- LvalueContext::Drop | LvalueContext::StorageLive | LvalueContext::StorageDead |
- LvalueContext::Validate => false,
+ PlaceContext::Inspect | PlaceContext::Borrow { kind: BorrowKind::Shared, .. } |
+ PlaceContext::Borrow { kind: BorrowKind::Unique, .. } |
+ PlaceContext::Projection(Mutability::Not) |
+ PlaceContext::Copy | PlaceContext::Move => true,
+ PlaceContext::Borrow { kind: BorrowKind::Mut, .. } | PlaceContext::Store |
+ PlaceContext::Call | PlaceContext::Projection(Mutability::Mut) |
+ PlaceContext::Drop | PlaceContext::StorageLive | PlaceContext::StorageDead |
+ PlaceContext::Validate => false,
}
}
use rustc::infer::{InferCtxt};
use rustc::ty::{self, TyCtxt, ParamEnv};
use rustc::ty::maps::Providers;
-use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Lvalue, Local};
+use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Place, Local};
use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind};
use transform::nll;
StatementKind::StorageDead(local) => {
self.access_lvalue(ContextKind::StorageDead.new(location),
- (&Lvalue::Local(local), span),
+ (&Place::Local(local), span),
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
LocalMutationIsAllowed::Yes,
flow_state);
PrefixSet::All
).last().unwrap();
match root_lvalue {
- Lvalue::Static(_) => {
+ Place::Static(_) => {
self.access_lvalue(
ContextKind::StorageDead.new(loc),
(&root_lvalue, self.mir.source_info(borrow.location).span),
flow_state
);
}
- Lvalue::Local(_) => {
+ Place::Local(_) => {
self.access_lvalue(
ContextKind::StorageDead.new(loc),
(&root_lvalue, self.mir.source_info(borrow.location).span),
flow_state
);
}
- Lvalue::Projection(_) => ()
+ Place::Projection(_) => ()
}
}
}
/// Returns true if an error is reported, false otherwise.
fn access_lvalue(&mut self,
context: Context,
- lvalue_span: (&Lvalue<'tcx>, Span),
+ lvalue_span: (&Place<'tcx>, Span),
kind: (ShallowOrDeep, ReadOrWrite),
is_local_mutation_allowed: LocalMutationIsAllowed,
flow_state: &InProgress<'cx, 'gcx, 'tcx>) {
let (sd, rw) = kind;
let storage_dead_or_drop_local = match (lvalue_span.0, rw) {
- (&Lvalue::Local(local), Write(WriteKind::StorageDeadOrDrop)) => Some(local),
+ (&Place::Local(local), Write(WriteKind::StorageDeadOrDrop)) => Some(local),
_ => None
};
fn mutate_lvalue(&mut self,
context: Context,
- lvalue_span: (&Lvalue<'tcx>, Span),
+ lvalue_span: (&Place<'tcx>, Span),
kind: ShallowOrDeep,
mode: MutateMode,
flow_state: &InProgress<'cx, 'gcx, 'tcx>) {
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
fn check_if_reassignment_to_immutable_state(&mut self,
context: Context,
- (lvalue, span): (&Lvalue<'tcx>, Span),
+ (lvalue, span): (&Place<'tcx>, Span),
flow_state: &InProgress<'cx, 'gcx, 'tcx>) {
let move_data = self.move_data;
fn check_if_path_is_moved(&mut self,
context: Context,
desired_action: InitializationRequiringAction,
- lvalue_span: (&Lvalue<'tcx>, Span),
+ lvalue_span: (&Place<'tcx>, Span),
flow_state: &InProgress<'cx, 'gcx, 'tcx>) {
// FIXME: analogous code in check_loans first maps `lvalue` to
// its base_path ... but is that what we want here?
/// An Err result includes a tag indicated why the search failed.
/// Currenly this can only occur if the lvalue is built off of a
/// static variable, as we do not track those in the MoveData.
- fn move_path_closest_to(&mut self, lvalue: &Lvalue<'tcx>)
+ fn move_path_closest_to(&mut self, lvalue: &Place<'tcx>)
-> Result<MovePathIndex, NoMovePathFound>
{
let mut last_prefix = lvalue;
last_prefix = prefix;
}
match *last_prefix {
- Lvalue::Local(_) => panic!("should have move path for every Local"),
- Lvalue::Projection(_) => panic!("PrefixSet::All meant dont stop for Projection"),
- Lvalue::Static(_) => return Err(NoMovePathFound::ReachedStatic),
+ Place::Local(_) => panic!("should have move path for every Local"),
+ Place::Projection(_) => panic!("PrefixSet::All meant dont stop for Projection"),
+ Place::Static(_) => return Err(NoMovePathFound::ReachedStatic),
}
}
fn move_path_for_lvalue(&mut self,
- lvalue: &Lvalue<'tcx>)
+ lvalue: &Place<'tcx>)
-> Option<MovePathIndex>
{
// If returns None, then there is no move path corresponding
fn check_if_assigned_path_is_moved(&mut self,
context: Context,
- (lvalue, span): (&Lvalue<'tcx>, Span),
+ (lvalue, span): (&Place<'tcx>, Span),
flow_state: &InProgress<'cx, 'gcx, 'tcx>) {
// recur down lvalue; dispatch to check_if_path_is_moved when necessary
let mut lvalue = lvalue;
loop {
match *lvalue {
- Lvalue::Local(_) | Lvalue::Static(_) => {
+ Place::Local(_) | Place::Static(_) => {
// assigning to `x` does not require `x` be initialized.
break;
}
- Lvalue::Projection(ref proj) => {
+ Place::Projection(ref proj) => {
let Projection { ref base, ref elem } = **proj;
match *elem {
ProjectionElem::Deref |
///
/// Returns true if an error is reported, false otherwise.
fn check_access_permissions(&self,
- (lvalue, span): (&Lvalue<'tcx>, Span),
+ (lvalue, span): (&Place<'tcx>, Span),
kind: ReadOrWrite,
is_local_mutation_allowed: LocalMutationIsAllowed)
-> bool {
/// Can this value be written or borrowed mutably
fn is_mutable<'d>(&self,
- lvalue: &'d Lvalue<'tcx>,
+ lvalue: &'d Place<'tcx>,
is_local_mutation_allowed: LocalMutationIsAllowed)
- -> Result<(), &'d Lvalue<'tcx>> {
+ -> Result<(), &'d Place<'tcx>> {
match *lvalue {
- Lvalue::Local(local) => {
+ Place::Local(local) => {
let local = &self.mir.local_decls[local];
match local.mutability {
Mutability::Not =>
Mutability::Mut => Ok(())
}
},
- Lvalue::Static(ref static_) => {
+ Place::Static(ref static_) => {
if !self.tcx.is_static_mut(static_.def_id) {
Err(lvalue)
} else {
Ok(())
}
},
- Lvalue::Projection(ref proj) => {
+ Place::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Deref => {
let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
}
/// Does this lvalue have a unique path
- fn is_unique<'d>(&self, lvalue: &'d Lvalue<'tcx>) -> Result<(), &'d Lvalue<'tcx>> {
+ fn is_unique<'d>(&self, lvalue: &'d Place<'tcx>) -> Result<(), &'d Place<'tcx>> {
match *lvalue {
- Lvalue::Local(..) => {
+ Place::Local(..) => {
// Local variables are unique
Ok(())
},
- Lvalue::Static(..) => {
+ Place::Static(..) => {
// Static variables are not
Err(lvalue)
},
- Lvalue::Projection(ref proj) => {
+ Place::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Deref => {
let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
fn each_borrow_involving_path<F>(&mut self,
_context: Context,
- access_lvalue: (ShallowOrDeep, &Lvalue<'tcx>),
+ access_lvalue: (ShallowOrDeep, &Place<'tcx>),
flow_state: &InProgress<'cx, 'gcx, 'tcx>,
mut op: F)
- where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>, &Lvalue<'tcx>) -> Control
+ where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>, &Place<'tcx>) -> Control
{
let (access, lvalue) = access_lvalue;
use rustc::hir;
use rustc::ty::{self, TyCtxt};
- use rustc::mir::{Lvalue, Mir, ProjectionElem};
+ use rustc::mir::{Place, Mir, ProjectionElem};
pub trait IsPrefixOf<'tcx> {
- fn is_prefix_of(&self, other: &Lvalue<'tcx>) -> bool;
+ fn is_prefix_of(&self, other: &Place<'tcx>) -> bool;
}
- impl<'tcx> IsPrefixOf<'tcx> for Lvalue<'tcx> {
- fn is_prefix_of(&self, other: &Lvalue<'tcx>) -> bool {
+ impl<'tcx> IsPrefixOf<'tcx> for Place<'tcx> {
+ fn is_prefix_of(&self, other: &Place<'tcx>) -> bool {
let mut cursor = other;
loop {
if self == cursor {
}
match *cursor {
- Lvalue::Local(_) |
- Lvalue::Static(_) => return false,
- Lvalue::Projection(ref proj) => {
+ Place::Local(_) |
+ Place::Static(_) => return false,
+ Place::Projection(ref proj) => {
cursor = &proj.base;
}
}
mir: &'cx Mir<'tcx>,
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
kind: PrefixSet,
- next: Option<&'cx Lvalue<'tcx>>,
+ next: Option<&'cx Place<'tcx>>,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
/// (inclusive) from longest to smallest, potentially
/// terminating the iteration early based on `kind`.
pub(super) fn prefixes(&self,
- lvalue: &'cx Lvalue<'tcx>,
+ lvalue: &'cx Place<'tcx>,
kind: PrefixSet)
-> Prefixes<'cx, 'gcx, 'tcx>
{
}
impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> {
- type Item = &'cx Lvalue<'tcx>;
+ type Item = &'cx Place<'tcx>;
fn next(&mut self) -> Option<Self::Item> {
let mut cursor = match self.next {
None => return None,
'cursor: loop {
let proj = match *cursor {
- Lvalue::Local(_) | // search yielded this leaf
- Lvalue::Static(_) => {
+ Place::Local(_) | // search yielded this leaf
+ Place::Static(_) => {
self.next = None;
return Some(cursor);
}
- Lvalue::Projection(ref proj) => proj,
+ Place::Projection(ref proj) => proj,
};
match proj.elem {
fn report_use_of_moved_or_uninitialized(&mut self,
_context: Context,
desired_action: InitializationRequiringAction,
- (lvalue, span): (&Lvalue<'tcx>, Span),
+ (lvalue, span): (&Place<'tcx>, Span),
mpi: MovePathIndex,
curr_move_out: &IdxSetBuf<MoveOutIndex>) {
fn report_move_out_while_borrowed(&mut self,
_context: Context,
- (lvalue, span): (&Lvalue<'tcx>, Span),
+ (lvalue, span): (&Place<'tcx>, Span),
borrow: &BorrowData<'tcx>) {
let value_msg = match self.describe_lvalue(lvalue) {
Some(name) => format!("`{}`", name),
fn report_use_while_mutably_borrowed(&mut self,
_context: Context,
- (lvalue, span): (&Lvalue<'tcx>, Span),
+ (lvalue, span): (&Place<'tcx>, Span),
borrow : &BorrowData<'tcx>) {
let mut err = self.tcx.cannot_use_when_mutably_borrowed(
use rustc::hir::ExprClosure;
use rustc::mir::AggregateKind;
- let local = if let StatementKind::Assign(Lvalue::Local(local), _) =
+ let local = if let StatementKind::Assign(Place::Local(local), _) =
self.mir[location.block].statements[location.statement_index].kind
{
local
self.tcx.with_freevars(node_id, |freevars| {
for (v, lv) in freevars.iter().zip(lvs) {
match *lv {
- Operand::Copy(Lvalue::Local(l)) |
- Operand::Move(Lvalue::Local(l)) if local == l => {
+ Operand::Copy(Place::Local(l)) |
+ Operand::Move(Place::Local(l)) if local == l => {
debug!(
"find_closure_span: found captured local {:?}",
l
fn report_conflicting_borrow(&mut self,
context: Context,
- common_prefix: &Lvalue<'tcx>,
- (lvalue, span): (&Lvalue<'tcx>, Span),
+ common_prefix: &Place<'tcx>,
+ (lvalue, span): (&Place<'tcx>, Span),
gen_borrow_kind: BorrowKind,
issued_borrow: &BorrowData,
end_issued_loan_span: Option<Span>) {
fn report_borrowed_value_does_not_live_long_enough(&mut self,
_: Context,
- (lvalue, span): (&Lvalue, Span),
+ (lvalue, span): (&Place, Span),
end_span: Option<Span>) {
let proper_span = match *lvalue {
- Lvalue::Local(local) => self.mir.local_decls[local].source_info.span,
+ Place::Local(local) => self.mir.local_decls[local].source_info.span,
_ => span
};
fn report_illegal_mutation_of_borrowed(&mut self,
_: Context,
- (lvalue, span): (&Lvalue<'tcx>, Span),
+ (lvalue, span): (&Place<'tcx>, Span),
loan: &BorrowData) {
let mut err = self.tcx.cannot_assign_to_borrowed(
span,
fn report_illegal_reassignment(&mut self,
_context: Context,
- (lvalue, span): (&Lvalue<'tcx>, Span),
+ (lvalue, span): (&Place<'tcx>, Span),
assigned_span: Span) {
let mut err = self.tcx.cannot_reassign_immutable(span,
&self.describe_lvalue(lvalue).unwrap_or("_".to_owned()),
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// End-user visible description of `lvalue` if one can be found. If the
// lvalue is a temporary for instance, None will be returned.
- fn describe_lvalue(&self, lvalue: &Lvalue<'tcx>) -> Option<String> {
+ fn describe_lvalue(&self, lvalue: &Place<'tcx>) -> Option<String> {
let mut buf = String::new();
match self.append_lvalue_to_string(lvalue, &mut buf, false) {
Ok(()) => Some(buf),
/// then returns the index of the field being projected. Note that this closure will always
/// be `self` in the current MIR, because that is the only time we directly access the fields
/// of a closure type.
- fn is_upvar_field_projection(&self, lvalue: &Lvalue<'tcx>) -> Option<Field> {
+ fn is_upvar_field_projection(&self, lvalue: &Place<'tcx>) -> Option<Field> {
match *lvalue {
- Lvalue::Projection(ref proj) => {
+ Place::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Field(field, _ty) => {
let is_projection_from_ty_closure = proj.base.ty(self.mir, self.tcx)
// Appends end-user visible description of `lvalue` to `buf`.
fn append_lvalue_to_string(&self,
- lvalue: &Lvalue<'tcx>,
+ lvalue: &Place<'tcx>,
buf: &mut String,
mut autoderef: bool) -> Result<(), ()> {
match *lvalue {
- Lvalue::Local(local) => {
+ Place::Local(local) => {
self.append_local_to_string(local, buf,)?;
}
- Lvalue::Static(ref static_) => {
+ Place::Static(ref static_) => {
buf.push_str(&format!("{}", &self.tcx.item_name(static_.def_id)));
}
- Lvalue::Projection(ref proj) => {
+ Place::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Deref => {
if let Some(field) = self.is_upvar_field_projection(&proj.base) {
}
// End-user visible description of the `field`nth field of `base`
- fn describe_field(&self, base: &Lvalue, field: Field) -> String {
+ fn describe_field(&self, base: &Place, field: Field) -> String {
match *base {
- Lvalue::Local(local) => {
+ Place::Local(local) => {
let local = &self.mir.local_decls[local];
self.describe_field_from_ty(&local.ty, field)
},
- Lvalue::Static(ref static_) => {
+ Place::Static(ref static_) => {
self.describe_field_from_ty(&static_.ty, field)
},
- Lvalue::Projection(ref proj) => {
+ Place::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Deref =>
self.describe_field(&proj.base, field),
// moves out of a Box. They should be removed when/if we stop
// treating Box specially (e.g. when/if DerefMove is added...)
- fn base_path<'d>(&self, lvalue: &'d Lvalue<'tcx>) -> &'d Lvalue<'tcx> {
+ fn base_path<'d>(&self, lvalue: &'d Place<'tcx>) -> &'d Place<'tcx> {
//! Returns the base of the leftmost (deepest) dereference of an
//! Box in `lvalue`. If there is no dereference of an Box
//! in `lvalue`, then it just returns `lvalue` itself.
let mut deepest = lvalue;
loop {
let proj = match *cursor {
- Lvalue::Local(..) | Lvalue::Static(..) => return deepest,
- Lvalue::Projection(ref proj) => proj,
+ Place::Local(..) | Place::Static(..) => return deepest,
+ Place::Projection(ref proj) => proj,
};
if proj.elem == ProjectionElem::Deref &&
lvalue.ty(self.mir, self.tcx).to_ty(self.tcx).is_box()
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
pub fn ast_block(&mut self,
- destination: &Lvalue<'tcx>,
+ destination: &Place<'tcx>,
block: BasicBlock,
ast_block: &'tcx hir::Block,
source_info: SourceInfo)
}
fn ast_block_stmts(&mut self,
- destination: &Lvalue<'tcx>,
+ destination: &Place<'tcx>,
mut block: BasicBlock,
span: Span,
stmts: Vec<StmtRef<'tcx>>,
pub fn push_assign(&mut self,
block: BasicBlock,
source_info: SourceInfo,
- lvalue: &Lvalue<'tcx>,
+ lvalue: &Place<'tcx>,
rvalue: Rvalue<'tcx>) {
self.push(block, Statement {
source_info,
pub fn push_assign_constant(&mut self,
block: BasicBlock,
source_info: SourceInfo,
- temp: &Lvalue<'tcx>,
+ temp: &Place<'tcx>,
constant: Constant<'tcx>) {
self.push_assign(block, source_info, temp,
Rvalue::Use(Operand::Constant(box constant)));
pub fn push_assign_unit(&mut self,
block: BasicBlock,
source_info: SourceInfo,
- lvalue: &Lvalue<'tcx>) {
+ lvalue: &Place<'tcx>) {
self.push_assign(block, source_info, lvalue, Rvalue::Aggregate(
box AggregateKind::Tuple, vec![]
));
pub fn as_lvalue<M>(&mut self,
block: BasicBlock,
expr: M)
- -> BlockAnd<Lvalue<'tcx>>
+ -> BlockAnd<Place<'tcx>>
where M: Mirror<'tcx, Output=Expr<'tcx>>
{
let expr = self.hir.mirror(expr);
fn expr_as_lvalue(&mut self,
mut block: BasicBlock,
expr: Expr<'tcx>)
- -> BlockAnd<Lvalue<'tcx>> {
+ -> BlockAnd<Place<'tcx>> {
debug!("expr_as_lvalue(block={:?}, expr={:?})", block, expr);
let this = self;
&len, Rvalue::Len(slice.clone()));
this.cfg.push_assign(block, source_info, // lt = idx < len
<, Rvalue::BinaryOp(BinOp::Lt,
- Operand::Copy(Lvalue::Local(idx)),
+ Operand::Copy(Place::Local(idx)),
Operand::Copy(len.clone())));
let msg = AssertMessage::BoundsCheck {
len: Operand::Move(len),
- index: Operand::Copy(Lvalue::Local(idx))
+ index: Operand::Copy(Place::Local(idx))
};
let success = this.assert(block, Operand::Move(lt), true,
msg, expr_span);
success.and(slice.index(idx))
}
ExprKind::SelfRef => {
- block.and(Lvalue::Local(Local::new(1)))
+ block.and(Place::Local(Local::new(1)))
}
ExprKind::VarRef { id } => {
let index = this.var_indices[&id];
- block.and(Lvalue::Local(index))
+ block.and(Place::Local(index))
}
ExprKind::StaticRef { id } => {
- block.and(Lvalue::Static(Box::new(Static { def_id: id, ty: expr.ty })))
+ block.and(Place::Static(Box::new(Static { def_id: id, ty: expr.ty })))
}
ExprKind::Array { .. } |
ExprKind::Call { .. } => {
// these are not lvalues, so we need to make a temporary.
debug_assert!(match Category::of(&expr.kind) {
- Some(Category::Lvalue) => false,
+ Some(Category::Place) => false,
_ => true,
});
let temp = unpack!(block = this.as_temp(block, expr.temp_lifetime, expr));
- block.and(Lvalue::Local(temp))
+ block.and(Place::Local(temp))
}
}
}
let constant = this.as_constant(expr);
block.and(Operand::Constant(box constant))
}
- Category::Lvalue |
+ Category::Place |
Category::Rvalue(..) => {
let operand =
unpack!(block = this.as_temp(block, scope, expr));
- block.and(Operand::Move(Lvalue::Local(operand)))
+ block.and(Operand::Move(Place::Local(operand)))
}
}
}
});
if let Some(scope) = scope {
// schedule a shallow free of that memory, lest we unwind:
- this.schedule_drop(expr_span, scope, &Lvalue::Local(result), value.ty);
+ this.schedule_drop(expr_span, scope, &Place::Local(result), value.ty);
}
// malloc some memory of suitable type (thus far, uninitialized):
let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
- this.cfg.push_assign(block, source_info, &Lvalue::Local(result), box_);
+ this.cfg.push_assign(block, source_info, &Place::Local(result), box_);
// initialize the box contents:
- unpack!(block = this.into(&Lvalue::Local(result).deref(), block, value));
- block.and(Rvalue::Use(Operand::Move(Lvalue::Local(result))))
+ unpack!(block = this.into(&Place::Local(result).deref(), block, value));
+ block.and(Rvalue::Use(Operand::Move(Place::Local(result))))
}
ExprKind::Cast { source } => {
let source = this.hir.mirror(source);
// semantics of `into`, `as_operand`, `as_rvalue`, and (of
// course) `as_temp`.
match Category::of(&expr.kind).unwrap() {
- Category::Lvalue => {
+ Category::Place => {
let lvalue = unpack!(block = this.as_lvalue(block, expr));
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(lvalue));
- this.cfg.push_assign(block, source_info, &Lvalue::Local(temp), rvalue);
+ this.cfg.push_assign(block, source_info, &Place::Local(temp), rvalue);
}
_ => {
- unpack!(block = this.into(&Lvalue::Local(temp), block, expr));
+ unpack!(block = this.into(&Place::Local(temp), block, expr));
}
}
// anything because no values with a destructor can be created in
// a constant at this time, even if the type may need dropping.
if let Some(temp_lifetime) = temp_lifetime {
- this.schedule_drop(expr_span, temp_lifetime, &Lvalue::Local(temp), expr_ty);
+ this.schedule_drop(expr_span, temp_lifetime, &Place::Local(temp), expr_ty);
}
block.and(temp)
// An assignable memory location like `x`, `x.f`, `foo()[3]`, that
// sort of thing. Something that could appear on the LHS of an `=`
// sign.
- Lvalue,
+ Place,
// A literal like `23` or `"foo"`. Does not include constant
// expressions like `3 + 5`.
ExprKind::SelfRef |
ExprKind::VarRef { .. } |
ExprKind::StaticRef { .. } =>
- Some(Category::Lvalue),
+ Some(Category::Place),
ExprKind::LogicalOp { .. } |
ExprKind::If { .. } |
/// Compile `expr`, storing the result into `destination`, which
/// is assumed to be uninitialized.
pub fn into_expr(&mut self,
- destination: &Lvalue<'tcx>,
+ destination: &Place<'tcx>,
mut block: BasicBlock,
expr: Expr<'tcx>)
-> BlockAnd<()>
internal: true,
is_user_variable: false
});
- let ptr_temp = Lvalue::Local(ptr_temp);
+ let ptr_temp = Place::Local(ptr_temp);
let block = unpack!(this.into(&ptr_temp, block, ptr));
this.into(&ptr_temp.deref(), block, val)
} else {
ExprKind::Return { value } => {
block = match value {
Some(value) => {
- unpack!(this.into(&Lvalue::Local(RETURN_POINTER), block, value))
+ unpack!(this.into(&Place::Local(RETURN_POINTER), block, value))
}
None => {
this.cfg.push_assign_unit(block,
source_info,
- &Lvalue::Local(RETURN_POINTER));
+ &Place::Local(RETURN_POINTER));
block
}
};
pub(in build) trait EvalInto<'tcx> {
fn eval_into<'a, 'gcx>(self,
builder: &mut Builder<'a, 'gcx, 'tcx>,
- destination: &Lvalue<'tcx>,
+ destination: &Place<'tcx>,
block: BasicBlock)
-> BlockAnd<()>;
}
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
pub fn into<E>(&mut self,
- destination: &Lvalue<'tcx>,
+ destination: &Place<'tcx>,
block: BasicBlock,
expr: E)
-> BlockAnd<()>
impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> {
fn eval_into<'a, 'gcx>(self,
builder: &mut Builder<'a, 'gcx, 'tcx>,
- destination: &Lvalue<'tcx>,
+ destination: &Place<'tcx>,
block: BasicBlock)
-> BlockAnd<()> {
let expr = builder.hir.mirror(self);
impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
fn eval_into<'a, 'gcx>(self,
builder: &mut Builder<'a, 'gcx, 'tcx>,
- destination: &Lvalue<'tcx>,
+ destination: &Place<'tcx>,
block: BasicBlock)
-> BlockAnd<()> {
builder.into_expr(destination, block, self)
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
pub fn match_expr(&mut self,
- destination: &Lvalue<'tcx>,
+ destination: &Place<'tcx>,
span: Span,
mut block: BasicBlock,
discriminant: ExprRef<'tcx>,
pub fn lvalue_into_pattern(&mut self,
mut block: BasicBlock,
irrefutable_pat: Pattern<'tcx>,
- initializer: &Lvalue<'tcx>)
+ initializer: &Place<'tcx>)
-> BlockAnd<()> {
// create a dummy candidate
let mut candidate = Candidate {
}
pub fn storage_live_binding(&mut self, block: BasicBlock, var: NodeId, span: Span)
- -> Lvalue<'tcx>
+ -> Place<'tcx>
{
let local_id = self.var_indices[&var];
let source_info = self.source_info(span);
source_info,
kind: StatementKind::StorageLive(local_id)
});
- Lvalue::Local(local_id)
+ Place::Local(local_id)
}
pub fn schedule_drop_for_binding(&mut self, var: NodeId, span: Span) {
let var_ty = self.local_decls[local_id].ty;
let hir_id = self.hir.tcx().hir.node_to_hir_id(var);
let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id);
- self.schedule_drop(span, region_scope, &Lvalue::Local(local_id), var_ty);
+ self.schedule_drop(span, region_scope, &Place::Local(local_id), var_ty);
}
pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, f: &mut F)
#[derive(Clone, Debug)]
struct Binding<'tcx> {
span: Span,
- source: Lvalue<'tcx>,
+ source: Place<'tcx>,
name: Name,
var_id: NodeId,
var_ty: Ty<'tcx>,
#[derive(Clone, Debug)]
pub struct MatchPair<'pat, 'tcx:'pat> {
// this lvalue...
- lvalue: Lvalue<'tcx>,
+ lvalue: Place<'tcx>,
// ... must match this pattern.
pattern: &'pat Pattern<'tcx>,
}
pub fn add_cases_to_switch<'pat>(&mut self,
- test_lvalue: &Lvalue<'tcx>,
+ test_lvalue: &Place<'tcx>,
candidate: &Candidate<'pat, 'tcx>,
switch_ty: Ty<'tcx>,
options: &mut Vec<&'tcx ty::Const<'tcx>>,
}
pub fn add_variants_to_switch<'pat>(&mut self,
- test_lvalue: &Lvalue<'tcx>,
+ test_lvalue: &Place<'tcx>,
candidate: &Candidate<'pat, 'tcx>,
variants: &mut BitVector)
-> bool
/// Generates the code to perform a test.
pub fn perform_test(&mut self,
block: BasicBlock,
- lvalue: &Lvalue<'tcx>,
+ lvalue: &Place<'tcx>,
test: &Test<'tcx>)
-> Vec<BasicBlock> {
let source_info = self.source_info(test.span);
/// not apply to this candidate, but it might be we can get
/// tighter match code if we do something a bit different.
pub fn sort_candidate<'pat>(&mut self,
- test_lvalue: &Lvalue<'tcx>,
+ test_lvalue: &Place<'tcx>,
test: &Test<'tcx>,
candidate: &Candidate<'pat, 'tcx>,
resulting_candidates: &mut [Vec<Candidate<'pat, 'tcx>>])
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
pub fn field_match_pairs<'pat>(&mut self,
- lvalue: Lvalue<'tcx>,
+ lvalue: Place<'tcx>,
subpatterns: &'pat [FieldPattern<'tcx>])
-> Vec<MatchPair<'pat, 'tcx>> {
subpatterns.iter()
pub fn prefix_slice_suffix<'pat>(&mut self,
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
- lvalue: &Lvalue<'tcx>,
+ lvalue: &Place<'tcx>,
prefix: &'pat [Pattern<'tcx>],
opt_slice: Option<&'pat Pattern<'tcx>>,
suffix: &'pat [Pattern<'tcx>]) {
}
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
- pub fn new(lvalue: Lvalue<'tcx>, pattern: &'pat Pattern<'tcx>) -> MatchPair<'pat, 'tcx> {
+ pub fn new(lvalue: Place<'tcx>, pattern: &'pat Pattern<'tcx>) -> MatchPair<'pat, 'tcx> {
MatchPair {
lvalue,
pattern,
///
/// NB: **No cleanup is scheduled for this temporary.** You should
/// call `schedule_drop` once the temporary is initialized.
- pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Lvalue<'tcx> {
+ pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
- let lvalue = Lvalue::Local(temp);
+ let lvalue = Place::Local(temp);
debug!("temp: created temp {:?} with type {:?}",
lvalue, self.local_decls[temp].ty);
lvalue
block: BasicBlock,
source_info: SourceInfo,
value: u64)
- -> Lvalue<'tcx> {
+ -> Place<'tcx> {
let usize_ty = self.hir.usize_ty();
let temp = self.temp(usize_ty, source_info.span);
self.cfg.push_assign_constant(
temp
}
- pub fn consume_by_copy_or_move(&self, lvalue: Lvalue<'tcx>) -> Operand<'tcx> {
+ pub fn consume_by_copy_or_move(&self, lvalue: Place<'tcx>) -> Operand<'tcx> {
let tcx = self.hir.tcx();
let ty = lvalue.ty(&self.local_decls, tcx).to_ty(tcx);
if self.hir.type_moves_by_default(ty, DUMMY_SP) {
/// Maps node ids of variable bindings to the `Local`s created for them.
var_indices: NodeMap<Local>,
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
- unit_temp: Option<Lvalue<'tcx>>,
+ unit_temp: Option<Place<'tcx>>,
/// cached block with the RESUME terminator; this is created
/// when first set of cleanups are built.
let mut block = START_BLOCK;
let expr = builder.hir.mirror(ast_expr);
- unpack!(block = builder.into_expr(&Lvalue::Local(RETURN_POINTER), block, expr));
+ unpack!(block = builder.into_expr(&Place::Local(RETURN_POINTER), block, expr));
let source_info = builder.source_info(span);
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
for (index, &(ty, pattern)) in arguments.iter().enumerate() {
// Function arguments always get the first Local indices after the return pointer
let local = Local::new(index + 1);
- let lvalue = Lvalue::Local(local);
+ let lvalue = Place::Local(local);
if let Some(pattern) = pattern {
let pattern = self.hir.pattern_from_hir(pattern);
}
let body = self.hir.mirror(ast_body);
- self.into(&Lvalue::Local(RETURN_POINTER), block, body)
+ self.into(&Place::Local(RETURN_POINTER), block, body)
}
- fn get_unit_temp(&mut self) -> Lvalue<'tcx> {
+ fn get_unit_temp(&mut self) -> Place<'tcx> {
match self.unit_temp {
Some(ref tmp) => tmp.clone(),
None => {
span: Span,
/// lvalue to drop
- location: Lvalue<'tcx>,
+ location: Place<'tcx>,
/// Whether this is a full value Drop, or just a StorageDead.
kind: DropKind
pub break_block: BasicBlock,
/// The destination of the loop/block expression itself (i.e. where to put the result of a
/// `break` expression)
- pub break_destination: Lvalue<'tcx>,
+ pub break_destination: Place<'tcx>,
}
impl CachedBlock {
pub fn in_breakable_scope<F, R>(&mut self,
loop_block: Option<BasicBlock>,
break_block: BasicBlock,
- break_destination: Lvalue<'tcx>,
+ break_destination: Place<'tcx>,
f: F) -> R
where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> R
{
pub fn schedule_drop(&mut self,
span: Span,
region_scope: region::Scope,
- lvalue: &Lvalue<'tcx>,
+ lvalue: &Place<'tcx>,
lvalue_ty: Ty<'tcx>) {
let needs_drop = self.hir.needs_drop(lvalue_ty);
let drop_kind = if needs_drop {
} else {
// Only temps and vars need their storage dead.
match *lvalue {
- Lvalue::Local(index) if index.index() > self.arg_count => DropKind::Storage,
+ Place::Local(index) if index.index() > self.arg_count => DropKind::Storage,
_ => return
}
};
pub fn build_drop(&mut self,
block: BasicBlock,
span: Span,
- location: Lvalue<'tcx>,
+ location: Place<'tcx>,
ty: Ty<'tcx>) -> BlockAnd<()> {
if !self.hir.needs_drop(ty) {
return block.unit();
pub fn build_drop_and_replace(&mut self,
block: BasicBlock,
span: Span,
- location: Lvalue<'tcx>,
+ location: Place<'tcx>,
value: Operand<'tcx>) -> BlockAnd<()> {
let source_info = self.source_info(span);
let next_target = self.cfg.start_new_block();
// Drop the storage for both value and storage drops.
// Only temps and vars need their storage dead.
match drop_data.location {
- Lvalue::Local(index) if index.index() > arg_count => {
+ Place::Local(index) if index.index() > arg_count => {
cfg.push(block, Statement {
source_info,
kind: StatementKind::StorageDead(index)
path: MovePathIndex,
mut cond: F)
-> Option<MovePathIndex>
- where F: FnMut(&mir::LvalueProjection<'tcx>) -> bool
+ where F: FnMut(&mir::PlaceProjection<'tcx>) -> bool
{
let mut next_child = move_data.move_paths[path].first_child;
while let Some(child_index) = next_child {
match move_data.move_paths[child_index].lvalue {
- mir::Lvalue::Projection(ref proj) => {
+ mir::Place::Projection(ref proj) => {
if cond(proj) {
return Some(child_index)
}
/// paths (1.) past arrays, slices, and pointers, nor (2.) into a type
/// that implements `Drop`.
///
-/// Lvalues behind references or arrays are not tracked by elaboration
+/// Places behind references or arrays are not tracked by elaboration
/// and are always assumed to be initialized when accessible. As
/// references and indexes can be reseated, trying to track them can
/// only lead to trouble.
///
-/// Lvalues behind ADT's with a Drop impl are not tracked by
+/// Places behind ADT's with a Drop impl are not tracked by
/// elaboration since they can never have a drop-flag state that
/// differs from that of the parent with the Drop impl.
///
/// FIXME: we have to do something for moving slice patterns.
fn lvalue_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
- lv: &mir::Lvalue<'tcx>) -> bool {
+ lv: &mir::Place<'tcx>) -> bool {
let ty = lv.ty(mir, tcx).to_ty(tcx);
match ty.sty {
ty::TyArray(..) | ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
{
let move_data = &ctxt.move_data;
for arg in mir.args_iter() {
- let lvalue = mir::Lvalue::Local(arg);
+ let lvalue = mir::Place::Local(arg);
let lookup_result = move_data.rev_lookup.find(&lvalue);
on_lookup_result_bits(tcx, mir, move_data,
lookup_result,
pub(crate) location: Location,
pub(crate) kind: mir::BorrowKind,
pub(crate) region: Region<'tcx>,
- pub(crate) lvalue: mir::Lvalue<'tcx>,
+ pub(crate) lvalue: mir::Place<'tcx>,
}
impl<'tcx> fmt::Display for BorrowData<'tcx> {
_in_out: &mut IdxSet<BorrowIndex>,
_call_bb: mir::BasicBlock,
_dest_bb: mir::BasicBlock,
- _dest_lval: &mir::Lvalue) {
+ _dest_lval: &mir::Place) {
// there are no effects on the region scopes from method calls.
}
}
fn is_unsafe_lvalue<'a, 'gcx: 'tcx, 'tcx: 'a>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
- lvalue: &mir::Lvalue<'tcx>
+ lvalue: &mir::Place<'tcx>
) -> bool {
- use self::mir::Lvalue::*;
+ use self::mir::Place::*;
use self::mir::ProjectionElem;
match *lvalue {
in_out: &mut IdxSet<MovePathIndex>,
_call_bb: mir::BasicBlock,
_dest_bb: mir::BasicBlock,
- dest_lval: &mir::Lvalue) {
+ dest_lval: &mir::Place) {
// when a call returns successfully, that means we need to set
// the bits for that dest_lval to 1 (initialized).
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
in_out: &mut IdxSet<MovePathIndex>,
_call_bb: mir::BasicBlock,
_dest_bb: mir::BasicBlock,
- dest_lval: &mir::Lvalue) {
+ dest_lval: &mir::Place) {
// when a call returns successfully, that means we need to set
// the bits for that dest_lval to 0 (initialized).
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
in_out: &mut IdxSet<MovePathIndex>,
_call_bb: mir::BasicBlock,
_dest_bb: mir::BasicBlock,
- dest_lval: &mir::Lvalue) {
+ dest_lval: &mir::Place) {
// when a call returns successfully, that means we need to set
// the bits for that dest_lval to 1 (initialized).
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
in_out: &mut IdxSet<MoveOutIndex>,
_call_bb: mir::BasicBlock,
_dest_bb: mir::BasicBlock,
- dest_lval: &mir::Lvalue) {
+ dest_lval: &mir::Place) {
let move_data = self.move_data();
let bits_per_block = self.bits_per_block();
mir::StatementKind::StorageDead(local) => {
// End inits for StorageDead, so that an immutable variable can
// be reinitialized on the next iteration of the loop.
- if let LookupResult::Exact(mpi) = rev_lookup.find(&mir::Lvalue::Local(local)) {
+ if let LookupResult::Exact(mpi) = rev_lookup.find(&mir::Place::Local(local)) {
debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
stmt, location, &init_path_map[mpi]);
for ii in &init_path_map[mpi] {
in_out: &mut IdxSet<InitIndex>,
call_bb: mir::BasicBlock,
_dest_bb: mir::BasicBlock,
- _dest_lval: &mir::Lvalue) {
+ _dest_lval: &mir::Place) {
let move_data = self.move_data();
let bits_per_block = self.bits_per_block();
let init_loc_map = &move_data.init_loc_map;
_in_out: &mut IdxSet<Local>,
_call_bb: mir::BasicBlock,
_dest_bb: mir::BasicBlock,
- _dest_lval: &mir::Lvalue) {
+ _dest_lval: &mir::Place) {
// Nothing to do when a call returns successfully
}
}
in_out: &mut IdxSet<Self::Idx>,
call_bb: mir::BasicBlock,
dest_bb: mir::BasicBlock,
- dest_lval: &mir::Lvalue);
+ dest_lval: &mir::Place);
}
impl<'a, 'gcx, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
// except according to those terms.
//! The move-analysis portion of borrowck needs to work in an abstract
-//! domain of lifted Lvalues. Most of the Lvalue variants fall into a
+//! domain of lifted Places. Most of the Place variants fall into a
//! one-to-one mapping between the concrete and abstract (e.g. a
//! field-deref on a local-variable, `x.field`, has the same meaning
//! in both domains). Indexed-Projections are the exception: `a[x]`
//! `a[x]` would still overlap them both. But that is not this
//! representation does today.)
-use rustc::mir::{Local, LvalueElem, Operand, ProjectionElem};
+use rustc::mir::{Local, PlaceElem, Operand, ProjectionElem};
use rustc::ty::Ty;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
type Abstract = AbstractType;
fn lift(&self) -> Self::Abstract { AbstractType }
}
-impl<'tcx> Lift for LvalueElem<'tcx> {
+impl<'tcx> Lift for PlaceElem<'tcx> {
type Abstract = AbstractElem<'tcx>;
fn lift(&self) -> Self::Abstract {
match *self {
moves: IndexVec::new(),
loc_map: LocationMap::new(mir),
rev_lookup: MovePathLookup {
- locals: mir.local_decls.indices().map(Lvalue::Local).map(|v| {
+ locals: mir.local_decls.indices().map(Place::Local).map(|v| {
Self::new_move_path(
&mut move_paths,
&mut path_map,
path_map: &mut IndexVec<MovePathIndex, Vec<MoveOutIndex>>,
init_path_map: &mut IndexVec<MovePathIndex, Vec<InitIndex>>,
parent: Option<MovePathIndex>,
- lvalue: Lvalue<'tcx>)
+ lvalue: Place<'tcx>)
-> MovePathIndex
{
let move_path = move_paths.push(MovePath {
/// problematic for borrowck.
///
/// Maybe we should have separate "borrowck" and "moveck" modes.
- fn move_path_for(&mut self, lval: &Lvalue<'tcx>)
+ fn move_path_for(&mut self, lval: &Place<'tcx>)
-> Result<MovePathIndex, MoveError<'tcx>>
{
debug!("lookup({:?})", lval);
match *lval {
- Lvalue::Local(local) => Ok(self.builder.data.rev_lookup.locals[local]),
- Lvalue::Static(..) => {
+ Place::Local(local) => Ok(self.builder.data.rev_lookup.locals[local]),
+ Place::Static(..) => {
let span = self.builder.mir.source_info(self.loc).span;
Err(MoveError::cannot_move_out_of(span, Static))
}
- Lvalue::Projection(ref proj) => {
+ Place::Projection(ref proj) => {
self.move_path_for_projection(lval, proj)
}
}
}
- fn create_move_path(&mut self, lval: &Lvalue<'tcx>) {
+ fn create_move_path(&mut self, lval: &Place<'tcx>) {
// This is an assignment, not a move, so this not being a valid
// move path is OK.
let _ = self.move_path_for(lval);
}
fn move_path_for_projection(&mut self,
- lval: &Lvalue<'tcx>,
- proj: &LvalueProjection<'tcx>)
+ lval: &Place<'tcx>,
+ proj: &PlaceProjection<'tcx>)
-> Result<MovePathIndex, MoveError<'tcx>>
{
let base = try!(self.move_path_for(&proj.base));
}
StatementKind::StorageLive(_) => {}
StatementKind::StorageDead(local) => {
- self.gather_move(&Lvalue::Local(local));
+ self.gather_move(&Place::Local(local));
}
StatementKind::SetDiscriminant{ .. } => {
span_bug!(stmt.source_info.span,
TerminatorKind::Unreachable => { }
TerminatorKind::Return => {
- self.gather_move(&Lvalue::Local(RETURN_POINTER));
+ self.gather_move(&Place::Local(RETURN_POINTER));
}
TerminatorKind::Assert { .. } |
}
}
- fn gather_move(&mut self, lval: &Lvalue<'tcx>) {
+ fn gather_move(&mut self, lval: &Place<'tcx>) {
debug!("gather_move({:?}, {:?})", self.loc, lval);
let path = match self.move_path_for(lval) {
self.builder.data.loc_map[self.loc].push(move_out);
}
- fn gather_init(&mut self, lval: &Lvalue<'tcx>, kind: InitKind) {
+ fn gather_init(&mut self, lval: &Place<'tcx>, kind: InitKind) {
debug!("gather_init({:?}, {:?})", self.loc, lval);
if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(lval) {
pub next_sibling: Option<MovePathIndex>,
pub first_child: Option<MovePathIndex>,
pub parent: Option<MovePathIndex>,
- pub lvalue: Lvalue<'tcx>,
+ pub lvalue: Place<'tcx>,
}
impl<'tcx> fmt::Debug for MovePath<'tcx> {
// alternative will *not* create a MovePath on the fly for an
// unknown l-value, but will rather return the nearest available
// parent.
- pub fn find(&self, lval: &Lvalue<'tcx>) -> LookupResult {
+ pub fn find(&self, lval: &Place<'tcx>) -> LookupResult {
match *lval {
- Lvalue::Local(local) => LookupResult::Exact(self.locals[local]),
- Lvalue::Static(..) => LookupResult::Parent(None),
- Lvalue::Projection(ref proj) => {
+ Place::Local(local) => LookupResult::Exact(self.locals[local]),
+ Place::Static(..) => LookupResult::Parent(None),
+ Place::Projection(ref proj) => {
match self.find(&proj.base) {
LookupResult::Exact(base_path) => {
match self.projections.get(&(base_path, proj.elem.lift())) {
tcx,
param_env
};
- let dropee = Lvalue::Local(Local::new(1+0)).deref();
+ let dropee = Place::Local(Local::new(1+0)).deref();
let resume_block = elaborator.patch.resume_block();
elaborate_drops::elaborate_drop(
&mut elaborator,
}
fn copy_shim(&mut self) {
- let rcvr = Lvalue::Local(Local::new(1+0)).deref();
+ let rcvr = Place::Local(Local::new(1+0)).deref();
let ret_statement = self.make_statement(
StatementKind::Assign(
- Lvalue::Local(RETURN_POINTER),
+ Place::Local(RETURN_POINTER),
Rvalue::Use(Operand::Copy(rcvr))
)
);
self.block(vec![ret_statement], TerminatorKind::Return, false);
}
- fn make_lvalue(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Lvalue<'tcx> {
+ fn make_lvalue(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
let span = self.span;
- Lvalue::Local(
+ Place::Local(
self.local_decls.push(temp_decl(mutability, ty, span))
)
}
fn make_clone_call(
&mut self,
ty: Ty<'tcx>,
- rcvr_field: Lvalue<'tcx>,
+ rcvr_field: Place<'tcx>,
next: BasicBlock,
cleanup: BasicBlock
- ) -> Lvalue<'tcx> {
+ ) -> Place<'tcx> {
let tcx = self.tcx;
let substs = Substs::for_item(
fn loop_header(
&mut self,
- beg: Lvalue<'tcx>,
- end: Lvalue<'tcx>,
+ beg: Place<'tcx>,
+ end: Place<'tcx>,
loop_body: BasicBlock,
loop_end: BasicBlock,
is_cleanup: bool
fn array_shim(&mut self, ty: Ty<'tcx>, len: u64) {
let tcx = self.tcx;
let span = self.span;
- let rcvr = Lvalue::Local(Local::new(1+0)).deref();
+ let rcvr = Place::Local(Local::new(1+0)).deref();
let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span));
let end = self.make_lvalue(Mutability::Not, tcx.types.usize);
let inits = vec![
self.make_statement(
StatementKind::Assign(
- Lvalue::Local(beg),
+ Place::Local(beg),
Rvalue::Use(Operand::Constant(self.make_usize(0)))
)
),
// BB #3;
// }
// BB #4;
- self.loop_header(Lvalue::Local(beg), end, BasicBlock::new(2), BasicBlock::new(4), false);
+ self.loop_header(Place::Local(beg), end, BasicBlock::new(2), BasicBlock::new(4), false);
// BB #2
// `let cloned = Clone::clone(rcvr[beg])`;
),
self.make_statement(
StatementKind::Assign(
- Lvalue::Local(beg),
+ Place::Local(beg),
Rvalue::BinaryOp(
BinOp::Add,
- Operand::Copy(Lvalue::Local(beg)),
+ Operand::Copy(Place::Local(beg)),
Operand::Constant(self.make_usize(1))
)
)
// `return ret;`
let ret_statement = self.make_statement(
StatementKind::Assign(
- Lvalue::Local(RETURN_POINTER),
+ Place::Local(RETURN_POINTER),
Rvalue::Use(Operand::Move(ret.clone())),
)
);
let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span));
let init = self.make_statement(
StatementKind::Assign(
- Lvalue::Local(beg),
+ Place::Local(beg),
Rvalue::Use(Operand::Constant(self.make_usize(0)))
)
);
// BB #8;
// }
// BB #9;
- self.loop_header(Lvalue::Local(beg), Lvalue::Local(end),
+ self.loop_header(Place::Local(beg), Place::Local(end),
BasicBlock::new(7), BasicBlock::new(9), true);
// BB #7 (cleanup)
// `goto #6;`
let statement = self.make_statement(
StatementKind::Assign(
- Lvalue::Local(beg),
+ Place::Local(beg),
Rvalue::BinaryOp(
BinOp::Add,
- Operand::Copy(Lvalue::Local(beg)),
+ Operand::Copy(Place::Local(beg)),
Operand::Constant(self.make_usize(1))
)
)
_ => bug!("only tuples and closures are accepted"),
};
- let rcvr = Lvalue::Local(Local::new(1+0)).deref();
+ let rcvr = Place::Local(Local::new(1+0)).deref();
let mut returns = Vec::new();
for (i, ity) in tys.iter().enumerate() {
// `return kind(returns[0], returns[1], ..., returns[tys.len() - 1]);`
let ret_statement = self.make_statement(
StatementKind::Assign(
- Lvalue::Local(RETURN_POINTER),
+ Place::Local(RETURN_POINTER),
Rvalue::Aggregate(
box kind,
returns.into_iter().map(Operand::Move).collect()
let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE };
let rcvr_arg = Local::new(1+0);
- let rcvr_l = Lvalue::Local(rcvr_arg);
+ let rcvr_l = Place::Local(rcvr_arg);
let mut statements = vec![];
let rcvr = match rcvr_adjustment {
statements.push(Statement {
source_info,
kind: StatementKind::Assign(
- Lvalue::Local(ref_rcvr),
+ Place::Local(ref_rcvr),
Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, rcvr_l)
)
});
- Operand::Move(Lvalue::Local(ref_rcvr))
+ Operand::Move(Place::Local(ref_rcvr))
}
};
if let Some(untuple_args) = untuple_args {
args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
- let arg_lv = Lvalue::Local(Local::new(1+1));
+ let arg_lv = Place::Local(Local::new(1+1));
Operand::Move(arg_lv.field(Field::new(i), *ity))
}));
} else {
args.extend((1..sig.inputs().len()).map(|i| {
- Operand::Move(Lvalue::Local(Local::new(1+i)))
+ Operand::Move(Place::Local(Local::new(1+i)))
}));
}
block(&mut blocks, statements, TerminatorKind::Call {
func: callee,
args,
- destination: Some((Lvalue::Local(RETURN_POINTER),
+ destination: Some((Place::Local(RETURN_POINTER),
BasicBlock::new(1))),
cleanup: if let Adjustment::RefMut = rcvr_adjustment {
Some(BasicBlock::new(3))
if let Adjustment::RefMut = rcvr_adjustment {
// BB #1 - drop for Self
block(&mut blocks, vec![], TerminatorKind::Drop {
- location: Lvalue::Local(rcvr_arg),
+ location: Place::Local(rcvr_arg),
target: BasicBlock::new(2),
unwind: None
}, false);
if let Adjustment::RefMut = rcvr_adjustment {
// BB #3 - drop if closure panics
block(&mut blocks, vec![], TerminatorKind::Drop {
- location: Lvalue::Local(rcvr_arg),
+ location: Place::Local(rcvr_arg),
target: BasicBlock::new(4),
unwind: None
}, true);
statements: vec![Statement {
source_info,
kind: StatementKind::Assign(
- Lvalue::Local(RETURN_POINTER),
+ Place::Local(RETURN_POINTER),
Rvalue::Aggregate(
box AggregateKind::Adt(adt_def, variant_no, substs, None),
(1..sig.inputs().len()+1).map(|i| {
- Operand::Move(Lvalue::Local(Local::new(i)))
+ Operand::Move(Place::Local(Local::new(i)))
}).collect()
)
)
patch.add_statement(
loc, StatementKind::StorageLive(temp));
- patch.add_assign(loc, Lvalue::Local(temp),
+ patch.add_assign(loc, Place::Local(temp),
Rvalue::Use(Operand::Move(location.clone())));
patch.patch_terminator(loc.block, TerminatorKind::Drop {
- location: Lvalue::Local(temp),
+ location: Place::Local(temp),
target: storage_dead_block,
unwind
});
/// Determine the "context" of the lval: Mutability and region.
fn lval_context<'a, 'tcx, D>(
- lval: &Lvalue<'tcx>,
+ lval: &Place<'tcx>,
local_decls: &D,
tcx: TyCtxt<'a, 'tcx, 'tcx>
) -> (Option<region::Scope>, hir::Mutability)
where D: HasLocalDecls<'tcx>
{
- use rustc::mir::Lvalue::*;
+ use rustc::mir::Place::*;
match *lval {
Local { .. } => (None, hir::MutMutable),
let local_decls = mir.local_decls.clone(); // FIXME: Find a way to get rid of this clone.
// Convert an lvalue to a validation operand.
- let lval_to_operand = |lval: Lvalue<'tcx>| -> ValidationOperand<'tcx, Lvalue<'tcx>> {
+ let lval_to_operand = |lval: Place<'tcx>| -> ValidationOperand<'tcx, Place<'tcx>> {
let (re, mutbl) = lval_context(&lval, &local_decls, tcx);
let ty = lval.ty(&local_decls, tcx).to_ty(tcx);
ValidationOperand { lval, ty, re, mutbl }
};
// Gather all arguments, skip return value.
let operands = mir.local_decls.iter_enumerated().skip(1).take(mir.arg_count)
- .map(|(local, _)| lval_to_operand(Lvalue::Local(local))).collect();
+ .map(|(local, _)| lval_to_operand(Place::Local(local))).collect();
emit_acquire(&mut mir.basic_blocks_mut()[START_BLOCK], source_info, operands);
}
// PART 2
// Add ReleaseValid/AcquireValid around function call terminators. We don't use a visitor
// because we need to access the block that a Call jumps to.
- let mut returns : Vec<(SourceInfo, Lvalue<'tcx>, BasicBlock)> = Vec::new();
+ let mut returns : Vec<(SourceInfo, Place<'tcx>, BasicBlock)> = Vec::new();
for block_data in mir.basic_blocks_mut() {
match block_data.terminator {
Some(Terminator { kind: TerminatorKind::Call { ref args, ref destination, .. },
// Do an acquire of the result -- but only what it points to, so add a Deref
// projection.
let dest_lval = Projection { base: dest_lval, elem: ProjectionElem::Deref };
- let dest_lval = Lvalue::Projection(Box::new(dest_lval));
+ let dest_lval = Place::Projection(Box::new(dest_lval));
let acquire_stmt = Statement {
source_info: block_data.statements[i].source_info,
kind: StatementKind::Validate(ValidationOp::Acquire,
use rustc::hir::def_id::DefId;
use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
use rustc::mir::*;
-use rustc::mir::visit::{LvalueContext, Visitor};
+use rustc::mir::visit::{PlaceContext, Visitor};
use syntax::ast;
use syntax::symbol::Symbol;
}
fn visit_lvalue(&mut self,
- lvalue: &Lvalue<'tcx>,
- context: LvalueContext<'tcx>,
+ lvalue: &Place<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
- if let LvalueContext::Borrow { .. } = context {
+ if let PlaceContext::Borrow { .. } = context {
if util::is_disaligned(self.tcx, self.mir, self.param_env, lvalue) {
let source_info = self.source_info;
let lint_root =
}
match lvalue {
- &Lvalue::Projection(box Projection {
+ &Place::Projection(box Projection {
ref base, ref elem
}) => {
let old_source_info = self.source_info;
- if let &Lvalue::Local(local) = base {
+ if let &Place::Local(local) = base {
if self.mir.local_decls[local].internal {
// Internal locals are used in the `move_val_init` desugaring.
// We want to check unsafety against the source info of the
}
ty::TyAdt(adt, _) => {
if adt.is_union() {
- if context == LvalueContext::Store ||
- context == LvalueContext::Drop
+ if context == PlaceContext::Store ||
+ context == PlaceContext::Drop
{
let elem_ty = match elem {
&ProjectionElem::Field(_, ty) => ty,
}
self.source_info = old_source_info;
}
- &Lvalue::Local(..) => {
+ &Place::Local(..) => {
// locals are safe
}
- &Lvalue::Static(box Static { def_id, ty: _ }) => {
+ &Place::Static(box Static { def_id, ty: _ }) => {
if self.tcx.is_static_mut(def_id) {
self.require_unsafe("use of mutable static");
} else if self.tcx.is_foreign_item(def_id) {
//! future.
use rustc::hir;
-use rustc::mir::{Constant, Local, LocalKind, Location, Lvalue, Mir, Operand, Rvalue, StatementKind};
+use rustc::mir::{Constant, Local, LocalKind, Location, Place, Mir, Operand, Rvalue, StatementKind};
use rustc::mir::visit::MutVisitor;
use rustc::ty::TyCtxt;
use transform::{MirPass, MirSource};
// That use of the source must be an assignment.
match statement.kind {
- StatementKind::Assign(Lvalue::Local(local), Rvalue::Use(ref operand)) if
+ StatementKind::Assign(Place::Local(local), Rvalue::Use(ref operand)) if
local == dest_local => {
let maybe_action = match *operand {
Operand::Copy(ref src_lvalue) |
if let Some(stmt) = mir[location.block].statements.get(location.statement_index) {
match stmt.kind {
StatementKind::Assign(
- Lvalue::Local(local),
- Rvalue::Use(Operand::Copy(Lvalue::Local(src_local))),
+ Place::Local(local),
+ Rvalue::Use(Operand::Copy(Place::Local(src_local))),
) |
StatementKind::Assign(
- Lvalue::Local(local),
- Rvalue::Use(Operand::Move(Lvalue::Local(src_local))),
+ Place::Local(local),
+ Rvalue::Use(Operand::Move(Place::Local(src_local))),
) if local == dest_local && dest_local == src_local => {}
_ => {
continue;
}
impl<'tcx> Action<'tcx> {
- fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis, src_lvalue: &Lvalue<'tcx>)
+ fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis, src_lvalue: &Place<'tcx>)
-> Option<Action<'tcx>> {
// The source must be a local.
- let src_local = if let Lvalue::Local(local) = *src_lvalue {
+ let src_local = if let Place::Local(local) = *src_lvalue {
local
} else {
debug!(" Can't copy-propagate local: source is not a local");
self.super_operand(operand, location);
match *operand {
- Operand::Copy(Lvalue::Local(local)) |
- Operand::Move(Lvalue::Local(local)) if local == self.dest_local => {}
+ Operand::Copy(Place::Local(local)) |
+ Operand::Move(Place::Local(local)) if local == self.dest_local => {}
_ => return,
}
let rhs = Rvalue::Use(op.clone());
let lhs_cast = if adt_def.is_enum() {
- Lvalue::Projection(Box::new(LvalueProjection {
+ Place::Projection(Box::new(PlaceProjection {
base: lhs.clone(),
elem: ProjectionElem::Downcast(adt_def, variant),
}))
lhs.clone()
};
- let lhs_proj = Lvalue::Projection(Box::new(LvalueProjection {
+ let lhs_proj = Place::Projection(Box::new(PlaceProjection {
base: lhs_cast,
elem: ProjectionElem::Field(Field::new(i), ty),
}));
});
}
- fn drop_flag(&mut self, index: MovePathIndex) -> Option<Lvalue<'tcx>> {
- self.drop_flags.get(&index).map(|t| Lvalue::Local(*t))
+ fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
+ self.drop_flags.get(&index).map(|t| Place::Local(*t))
}
/// create a patch that elaborates all drops in the input
fn elaborate_replace(
&mut self,
loc: Location,
- location: &Lvalue<'tcx>,
+ location: &Place<'tcx>,
value: &Operand<'tcx>,
target: BasicBlock,
unwind: Option<BasicBlock>)
if let Some(&flag) = self.drop_flags.get(&path) {
let span = self.patch.source_info_for_location(self.mir, loc).span;
let val = self.constant_bool(span, val.value());
- self.patch.add_assign(loc, Lvalue::Local(flag), val);
+ self.patch.add_assign(loc, Place::Local(flag), val);
}
}
let span = self.patch.source_info_for_location(self.mir, loc).span;
let false_ = self.constant_bool(span, false);
for flag in self.drop_flags.values() {
- self.patch.add_assign(loc, Lvalue::Local(*flag), false_.clone());
+ self.patch.add_assign(loc, Place::Local(*flag), false_.clone());
}
}
use rustc::hir::def_id::DefId;
use rustc::middle::const_val::ConstVal;
use rustc::mir::*;
-use rustc::mir::visit::{LvalueContext, Visitor, MutVisitor};
+use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
use rustc::ty::{self, TyCtxt, AdtDef, Ty, GeneratorInterior};
use rustc::ty::subst::{Kind, Substs};
use util::dump_mir;
impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor {
fn visit_local(&mut self,
local: &mut Local,
- _: LvalueContext<'tcx>,
+ _: PlaceContext<'tcx>,
_: Location) {
if *local == self.from {
*local = self.to;
impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
fn visit_local(&mut self,
local: &mut Local,
- _: LvalueContext<'tcx>,
+ _: PlaceContext<'tcx>,
_: Location) {
assert_ne!(*local, self_arg());
}
fn visit_lvalue(&mut self,
- lvalue: &mut Lvalue<'tcx>,
- context: LvalueContext<'tcx>,
+ lvalue: &mut Place<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
- if *lvalue == Lvalue::Local(self_arg()) {
- *lvalue = Lvalue::Projection(Box::new(Projection {
+ if *lvalue == Place::Local(self_arg()) {
+ *lvalue = Place::Projection(Box::new(Projection {
base: lvalue.clone(),
elem: ProjectionElem::Deref,
}));
Rvalue::Aggregate(box adt, vec![val])
}
- // Create a Lvalue referencing a generator struct field
- fn make_field(&self, idx: usize, ty: Ty<'tcx>) -> Lvalue<'tcx> {
- let base = Lvalue::Local(self_arg());
+ // Create a Place referencing a generator struct field
+ fn make_field(&self, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> {
+ let base = Place::Local(self_arg());
let field = Projection {
base: base,
elem: ProjectionElem::Field(Field::new(idx), ty),
};
- Lvalue::Projection(Box::new(field))
+ Place::Projection(Box::new(field))
}
// Create a statement which changes the generator state
impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
fn visit_local(&mut self,
local: &mut Local,
- _: LvalueContext<'tcx>,
+ _: PlaceContext<'tcx>,
_: Location) {
assert_eq!(self.remap.get(local), None);
}
fn visit_lvalue(&mut self,
- lvalue: &mut Lvalue<'tcx>,
- context: LvalueContext<'tcx>,
+ lvalue: &mut Place<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
- if let Lvalue::Local(l) = *lvalue {
+ if let Place::Local(l) = *lvalue {
// Replace an Local in the remap with a generator struct access
if let Some(&(ty, idx)) = self.remap.get(&l) {
*lvalue = self.make_field(idx, ty);
let ret_val = match data.terminator().kind {
TerminatorKind::Return => Some((1,
None,
- Operand::Move(Lvalue::Local(self.new_ret_local)),
+ Operand::Move(Place::Local(self.new_ret_local)),
None)),
TerminatorKind::Yield { ref value, resume, drop } => Some((0,
Some(resume),
// We must assign the value first in case it gets declared dead below
data.statements.push(Statement {
source_info,
- kind: StatementKind::Assign(Lvalue::Local(RETURN_POINTER),
+ kind: StatementKind::Assign(Place::Local(RETURN_POINTER),
self.make_state(state_idx, v)),
});
let state = if let Some(resume) = resume { // Yield
&Terminator {
source_info,
kind: TerminatorKind::Drop {
- location: Lvalue::Local(local),
+ location: Place::Local(local),
target,
unwind
}
elaborate_drop(
&mut elaborator,
source_info,
- &Lvalue::Local(gen),
+ &Place::Local(gen),
(),
target,
unwind,
// Create a block to destroy an unresumed generators. This can only destroy upvars.
let drop_clean = BasicBlock::new(mir.basic_blocks().len());
let term = TerminatorKind::Drop {
- location: Lvalue::Local(self_arg()),
+ location: Place::Local(self_arg()),
target: return_block,
unwind: None,
};
let state_field = mir.upvar_decls.len();
- // Run the transformation which converts Lvalues from Local to generator struct
+ // Run the transformation which converts Places from Local to generator struct
// accesses for locals in `remap`.
// It also rewrites `return x` and `yield y` as writing a new generator state and returning
// GeneratorState::Complete(x) and GeneratorState::Yielded(y) respectively.
// If the call is something like `a[*i] = f(i)`, where
// `i : &mut usize`, then just duplicating the `a[*i]`
- // Lvalue could result in two different locations if `f`
+ // Place could result in two different locations if `f`
// writes to `i`. To prevent this we need to create a temporary
// borrow of the lvalue and pass the destination as `*temp` instead.
- fn dest_needs_borrow(lval: &Lvalue) -> bool {
+ fn dest_needs_borrow(lval: &Place) -> bool {
match *lval {
- Lvalue::Projection(ref p) => {
+ Place::Projection(ref p) => {
match p.elem {
ProjectionElem::Deref |
ProjectionElem::Index(_) => true,
}
// Static variables need a borrow because the callee
// might modify the same static.
- Lvalue::Static(_) => true,
+ Place::Static(_) => true,
_ => false
}
}
let temp = LocalDecl::new_temp(ty, callsite.location.span);
let tmp = caller_mir.local_decls.push(temp);
- let tmp = Lvalue::Local(tmp);
+ let tmp = Place::Local(tmp);
let stmt = Statement {
source_info: callsite.location,
}
}
- fn cast_box_free_arg(&self, arg: Lvalue<'tcx>, ptr_ty: Ty<'tcx>,
+ fn cast_box_free_arg(&self, arg: Place<'tcx>, ptr_ty: Ty<'tcx>,
callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local {
let arg = Rvalue::Ref(
self.tcx.types.re_erased,
let ty = arg.ty(caller_mir, self.tcx);
let ref_tmp = LocalDecl::new_temp(ty, callsite.location.span);
let ref_tmp = caller_mir.local_decls.push(ref_tmp);
- let ref_tmp = Lvalue::Local(ref_tmp);
+ let ref_tmp = Place::Local(ref_tmp);
let ref_stmt = Statement {
source_info: callsite.location,
let cast_stmt = Statement {
source_info: callsite.location,
- kind: StatementKind::Assign(Lvalue::Local(cast_tmp), raw_ptr)
+ kind: StatementKind::Assign(Place::Local(cast_tmp), raw_ptr)
};
caller_mir[callsite.bb]
let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_mir);
assert!(args.next().is_none());
- let tuple = Lvalue::Local(tuple);
+ let tuple = Place::Local(tuple);
let tuple_tys = if let ty::TyTuple(s, _) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
s
} else {
// FIXME: Analysis of the usage of the arguments to avoid
// unnecessary temporaries.
- if let Operand::Move(Lvalue::Local(local)) = arg {
+ if let Operand::Move(Place::Local(local)) = arg {
if caller_mir.local_kind(local) == LocalKind::Temp {
// Reuse the operand if it's a temporary already
return local;
let stmt = Statement {
source_info: callsite.location,
- kind: StatementKind::Assign(Lvalue::Local(arg_tmp), arg),
+ kind: StatementKind::Assign(Place::Local(arg_tmp), arg),
};
caller_mir[callsite.bb].statements.push(stmt);
arg_tmp
scope_map: IndexVec<VisibilityScope, VisibilityScope>,
promoted_map: IndexVec<Promoted, Promoted>,
_callsite: CallSite<'tcx>,
- destination: Lvalue<'tcx>,
+ destination: Place<'tcx>,
return_block: BasicBlock,
cleanup_block: Option<BasicBlock>,
in_cleanup_block: bool,
impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
fn visit_local(&mut self,
local: &mut Local,
- _ctxt: LvalueContext<'tcx>,
+ _ctxt: PlaceContext<'tcx>,
_location: Location) {
if *local == RETURN_POINTER {
match self.destination {
- Lvalue::Local(l) => {
+ Place::Local(l) => {
*local = l;
return;
},
}
fn visit_lvalue(&mut self,
- lvalue: &mut Lvalue<'tcx>,
- _ctxt: LvalueContext<'tcx>,
+ lvalue: &mut Place<'tcx>,
+ _ctxt: PlaceContext<'tcx>,
_location: Location) {
- if let Lvalue::Local(RETURN_POINTER) = *lvalue {
+ if let Place::Local(RETURN_POINTER) = *lvalue {
// Return pointer; update the lvalue itself
*lvalue = self.destination.clone();
} else {
//! Performs various peephole optimizations.
-use rustc::mir::{Constant, Literal, Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue, Local};
+use rustc::mir::{Constant, Literal, Location, Place, Mir, Operand, ProjectionElem, Rvalue, Local};
use rustc::mir::visit::{MutVisitor, Visitor};
use rustc::ty::{TyCtxt, TypeVariants};
use rustc::util::nodemap::{FxHashMap, FxHashSet};
// First, find optimization opportunities. This is done in a pre-pass to keep the MIR
// read-only so that we can do global analyses on the MIR in the process (e.g.
- // `Lvalue::ty()`).
+ // `Place::ty()`).
let optimizations = {
let mut optimization_finder = OptimizationFinder::new(mir, tcx);
optimization_finder.visit_mir(mir);
if self.optimizations.and_stars.remove(&location) {
debug!("Replacing `&*`: {:?}", rvalue);
let new_lvalue = match *rvalue {
- Rvalue::Ref(_, _, Lvalue::Projection(ref mut projection)) => {
+ Rvalue::Ref(_, _, Place::Projection(ref mut projection)) => {
// Replace with dummy
- mem::replace(&mut projection.base, Lvalue::Local(Local::new(0)))
+ mem::replace(&mut projection.base, Place::Local(Local::new(0)))
}
_ => bug!("Detected `&*` but didn't find `&*`!"),
};
impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
- if let Rvalue::Ref(_, _, Lvalue::Projection(ref projection)) = *rvalue {
+ if let Rvalue::Ref(_, _, Place::Projection(ref projection)) = *rvalue {
if let ProjectionElem::Deref = projection.elem {
if projection.base.ty(self.mir, self.tcx).to_ty(self.tcx).is_region_ptr() {
self.optimizations.and_stars.insert(location);
block.statements.push(Statement {
source_info: source_info,
kind: StatementKind::Assign(
- Lvalue::Local(local),
+ Place::Local(local),
Rvalue::Cast(
CastKind::Misc,
rhs,
rhs_override_ty.unwrap())),
});
- rhs = Operand::Move(Lvalue::Local(local));
+ rhs = Operand::Move(Place::Local(local));
}
let call_did = check_lang_item_type(
fn check_lang_item_type<'a, 'tcx, D>(
lang_item: LangItem,
- lvalue: &Lvalue<'tcx>,
+ lvalue: &Place<'tcx>,
lhs: &Operand<'tcx>,
rhs: &Operand<'tcx>,
local_decls: &D,
// except according to those terms.
use rustc::hir;
-use rustc::mir::{Location, Lvalue, Mir, Rvalue};
+use rustc::mir::{Location, Place, Mir, Rvalue};
use rustc::mir::visit::Visitor;
-use rustc::mir::Lvalue::Projection;
-use rustc::mir::{LvalueProjection, ProjectionElem};
+use rustc::mir::Place::Projection;
+use rustc::mir::{PlaceProjection, ProjectionElem};
use rustc::infer::InferCtxt;
use rustc::traits::{self, ObligationCause};
use rustc::ty::{self, Ty};
&mut self,
location: Location,
borrow_region: ty::Region<'tcx>,
- borrowed_lv: &Lvalue<'tcx>,
+ borrowed_lv: &Place<'tcx>,
) {
if let Projection(ref proj) = *borrowed_lv {
- let LvalueProjection { ref base, ref elem } = **proj;
+ let PlaceProjection { ref base, ref elem } = **proj;
if let ProjectionElem::Deref = *elem {
let tcx = self.infcx.tcx;
//! move analysis runs after promotion on broken MIR.
use rustc::mir::*;
-use rustc::mir::visit::{LvalueContext, MutVisitor, Visitor};
+use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
use rustc::mir::traversal::ReversePostorder;
use rustc::ty::TyCtxt;
use syntax_pos::Span;
impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
fn visit_local(&mut self,
&index: &Local,
- context: LvalueContext<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
// We're only interested in temporaries
if self.mir.local_kind(index) != LocalKind::Temp {
let temp = &mut self.temps[index];
if *temp == TempState::Undefined {
match context {
- LvalueContext::Store |
- LvalueContext::Call => {
+ PlaceContext::Store |
+ PlaceContext::Call => {
*temp = TempState::Defined {
location,
uses: 0
// We always allow borrows, even mutable ones, as we need
// to promote mutable borrows of some ZSTs e.g. `&mut []`.
let allowed_use = match context {
- LvalueContext::Borrow {..} => true,
+ PlaceContext::Borrow {..} => true,
_ => context.is_nonmutating_use()
};
if allowed_use {
span,
scope: ARGUMENT_VISIBILITY_SCOPE
},
- kind: StatementKind::Assign(Lvalue::Local(dest), rvalue)
+ kind: StatementKind::Assign(Place::Local(dest), rvalue)
});
}
func,
args,
cleanup: None,
- destination: Some((Lvalue::Local(new_temp), new_target))
+ destination: Some((Place::Local(new_temp), new_target))
},
..terminator
};
impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
fn visit_local(&mut self,
local: &mut Local,
- _: LvalueContext<'tcx>,
+ _: PlaceContext<'tcx>,
_: Location) {
if self.source.local_kind(*local) == LocalKind::Temp {
*local = self.promote_temp(*local);
"expected assignment to promote");
}
};
- if let Lvalue::Local(index) = *dest {
+ if let Place::Local(index) = *dest {
if temps[index] == TempState::PromotedOut {
// Already promoted.
continue;
for block in mir.basic_blocks_mut() {
block.statements.retain(|statement| {
match statement.kind {
- StatementKind::Assign(Lvalue::Local(index), _) |
+ StatementKind::Assign(Place::Local(index), _) |
StatementKind::StorageLive(index) |
StatementKind::StorageDead(index) => {
!promoted(index)
});
let terminator = block.terminator_mut();
match terminator.kind {
- TerminatorKind::Drop { location: Lvalue::Local(index), target, .. } => {
+ TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
if promoted(index) {
terminator.kind = TerminatorKind::Goto {
target,
use rustc::ty::maps::Providers;
use rustc::mir::*;
use rustc::mir::traversal::ReversePostorder;
-use rustc::mir::visit::{LvalueContext, Visitor};
+use rustc::mir::visit::{PlaceContext, Visitor};
use rustc::middle::lang_items;
use syntax::abi::Abi;
use syntax::attr;
self.add(original);
}
- /// Check if an Lvalue with the current qualifications could
+ /// Check if an Place with the current qualifications could
/// be consumed, by either an operand or a Deref projection.
fn try_consume(&mut self) -> bool {
if self.qualif.intersects(Qualif::STATIC) && self.mode != Mode::Fn {
}
/// Assign the current qualification to the given destination.
- fn assign(&mut self, dest: &Lvalue<'tcx>, location: Location) {
+ fn assign(&mut self, dest: &Place<'tcx>, location: Location) {
let qualif = self.qualif;
let span = self.span;
let store = |slot: &mut Option<Qualif>| {
// Only handle promotable temps in non-const functions.
if self.mode == Mode::Fn {
- if let Lvalue::Local(index) = *dest {
+ if let Place::Local(index) = *dest {
if self.mir.local_kind(index) == LocalKind::Temp
&& self.temp_promotion_state[index].is_promotable() {
debug!("store to promotable temp {:?}", index);
// When initializing a local, record whether the *value* being
// stored in it needs dropping, which it may not, even if its
// type does, e.g. `None::<String>`.
- if let Lvalue::Local(local) = *dest {
+ if let Place::Local(local) = *dest {
if qualif.intersects(Qualif::NEEDS_DROP) {
self.local_needs_drop[local] = Some(self.span);
}
}
match *dest {
- Lvalue::Local(index) if self.mir.local_kind(index) == LocalKind::Temp => {
+ Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp => {
debug!("store to temp {:?}", index);
store(&mut self.temp_qualif[index])
}
- Lvalue::Local(index) if self.mir.local_kind(index) == LocalKind::ReturnPointer => {
+ Place::Local(index) if self.mir.local_kind(index) == LocalKind::ReturnPointer => {
debug!("store to return pointer {:?}", index);
store(&mut self.return_qualif)
}
- Lvalue::Projection(box Projection {
- base: Lvalue::Local(index),
+ Place::Projection(box Projection {
+ base: Place::Local(index),
elem: ProjectionElem::Deref
}) if self.mir.local_kind(index) == LocalKind::Temp
&& self.mir.local_decls[index].ty.is_box()
// This must be an explicit assignment.
_ => {
// Catch more errors in the destination.
- self.visit_lvalue(dest, LvalueContext::Store, location);
+ self.visit_lvalue(dest, PlaceContext::Store, location);
self.statement_like();
}
}
for index in mir.vars_iter() {
if !self.const_fn_arg_vars.contains(index.index()) {
debug!("unassigned variable {:?}", index);
- self.assign(&Lvalue::Local(index), Location {
+ self.assign(&Place::Local(index), Location {
block: bb,
statement_index: usize::MAX,
});
match *candidate {
Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
match self.mir[bb].statements[stmt_idx].kind {
- StatementKind::Assign(_, Rvalue::Ref(_, _, Lvalue::Local(index))) => {
+ StatementKind::Assign(_, Rvalue::Ref(_, _, Place::Local(index))) => {
promoted_temps.add(&index);
}
_ => {}
impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
fn visit_local(&mut self,
&local: &Local,
- _: LvalueContext<'tcx>,
+ _: PlaceContext<'tcx>,
_: Location) {
match self.mir.local_kind(local) {
LocalKind::ReturnPointer => {
}
fn visit_lvalue(&mut self,
- lvalue: &Lvalue<'tcx>,
- context: LvalueContext<'tcx>,
+ lvalue: &Place<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
match *lvalue {
- Lvalue::Local(ref local) => self.visit_local(local, context, location),
- Lvalue::Static(ref global) => {
+ Place::Local(ref local) => self.visit_local(local, context, location),
+ Place::Static(ref global) => {
self.add(Qualif::STATIC);
if self.mode != Mode::Fn {
a constant instead", self.mode);
}
}
- Lvalue::Projection(ref proj) => {
+ Place::Projection(ref proj) => {
self.nest(|this| {
this.super_lvalue(lvalue, context, location);
match proj.elem {
});
// Mark the consumed locals to indicate later drops are noops.
- if let Lvalue::Local(local) = *lvalue {
+ if let Place::Local(local) = *lvalue {
self.local_needs_drop[local] = None;
}
}
let candidate = Candidate::Ref(location);
if !self.qualif.intersects(Qualif::NEVER_PROMOTE) {
// We can only promote direct borrows of temps.
- if let Lvalue::Local(local) = *lvalue {
+ if let Place::Local(local) = *lvalue {
if self.mir.local_kind(local) == LocalKind::Temp {
self.promotion_candidates.push(candidate);
}
if self.mode != Mode::Fn {
// HACK(eddyb) Emulate a bit of dataflow analysis,
// conservatively, that drop elaboration will do.
- let needs_drop = if let Lvalue::Local(local) = *lvalue {
+ let needs_drop = if let Place::Local(local) = *lvalue {
self.local_needs_drop[local]
} else {
None
fn visit_assign(&mut self,
_: BasicBlock,
- dest: &Lvalue<'tcx>,
+ dest: &Place<'tcx>,
rvalue: &Rvalue<'tcx>,
location: Location) {
self.visit_rvalue(rvalue, location);
// Check the allowed const fn argument forms.
- if let (Mode::ConstFn, &Lvalue::Local(index)) = (self.mode, dest) {
+ if let (Mode::ConstFn, &Place::Local(index)) = (self.mode, dest) {
if self.mir.local_kind(index) == LocalKind::Var &&
self.const_fn_arg_vars.insert(index.index()) {
// Direct use of an argument is permitted.
match *rvalue {
- Rvalue::Use(Operand::Copy(Lvalue::Local(local))) |
- Rvalue::Use(Operand::Move(Lvalue::Local(local))) => {
+ Rvalue::Use(Operand::Copy(Place::Local(local))) |
+ Rvalue::Use(Operand::Move(Place::Local(local))) => {
if self.mir.local_kind(local) == LocalKind::Arg {
return;
}
});
let terminator = block.terminator_mut();
match terminator.kind {
- TerminatorKind::Drop { location: Lvalue::Local(index), target, .. } => {
+ TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
if promoted_temps.contains(&index) {
terminator.kind = TerminatorKind::Goto {
target,
};
assert!(args.len() == 1);
let peek_arg_lval = match args[0] {
- mir::Operand::Copy(ref lval @ mir::Lvalue::Local(_)) |
- mir::Operand::Move(ref lval @ mir::Lvalue::Local(_)) => Some(lval),
+ mir::Operand::Copy(ref lval @ mir::Place::Local(_)) |
+ mir::Operand::Move(ref lval @ mir::Place::Local(_)) => Some(lval),
_ => None,
};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc::ty::TyCtxt;
use rustc::mir::*;
-use rustc::mir::visit::{MutVisitor, Visitor, LvalueContext};
+use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext};
use std::borrow::Cow;
use transform::{MirPass, MirSource};
}
impl<'tcx> Visitor<'tcx> for DeclMarker {
- fn visit_local(&mut self, local: &Local, ctx: LvalueContext<'tcx>, _: Location) {
+ fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) {
// ignore these altogether, they get removed along with their otherwise unused decls.
- if ctx != LvalueContext::StorageLive && ctx != LvalueContext::StorageDead {
+ if ctx != PlaceContext::StorageLive && ctx != PlaceContext::StorageDead {
self.locals.insert(local.index());
}
}
});
self.super_basic_block_data(block, data);
}
- fn visit_local(&mut self, l: &mut Local, _: LvalueContext<'tcx>, _: Location) {
+ fn visit_local(&mut self, l: &mut Local, _: PlaceContext<'tcx>, _: Location) {
*l = Local::new(self.map[l.index()]);
}
}
use rustc::ty::{self, Ty, TyCtxt, TypeVariants};
use rustc::middle::const_val::ConstVal;
use rustc::mir::*;
-use rustc::mir::tcx::LvalueTy;
-use rustc::mir::visit::{LvalueContext, Visitor};
+use rustc::mir::tcx::PlaceTy;
+use rustc::mir::visit::{PlaceContext, Visitor};
use std::fmt;
use syntax::ast;
use syntax_pos::{Span, DUMMY_SP};
fn visit_lvalue(
&mut self,
- lvalue: &Lvalue<'tcx>,
- context: LvalueContext,
+ lvalue: &Place<'tcx>,
+ context: PlaceContext,
location: Location,
) {
self.sanitize_lvalue(lvalue, location, context);
}
fn sanitize_lvalue(&mut self,
- lvalue: &Lvalue<'tcx>,
+ lvalue: &Place<'tcx>,
location: Location,
- context: LvalueContext)
- -> LvalueTy<'tcx> {
+ context: PlaceContext)
+ -> PlaceTy<'tcx> {
debug!("sanitize_lvalue: {:?}", lvalue);
let lvalue_ty = match *lvalue {
- Lvalue::Local(index) => LvalueTy::Ty {
+ Place::Local(index) => PlaceTy::Ty {
ty: self.mir.local_decls[index].ty,
},
- Lvalue::Static(box Static { def_id, ty: sty }) => {
+ Place::Static(box Static { def_id, ty: sty }) => {
let sty = self.sanitize_type(lvalue, sty);
let ty = self.tcx().type_of(def_id);
let ty = self.cx.normalize(&ty, location);
terr
);
}
- LvalueTy::Ty { ty: sty }
+ PlaceTy::Ty { ty: sty }
}
- Lvalue::Projection(ref proj) => {
+ Place::Projection(ref proj) => {
let base_context = if context.is_mutating_use() {
- LvalueContext::Projection(Mutability::Mut)
+ PlaceContext::Projection(Mutability::Mut)
} else {
- LvalueContext::Projection(Mutability::Not)
+ PlaceContext::Projection(Mutability::Not)
};
let base_ty = self.sanitize_lvalue(&proj.base, location, base_context);
- if let LvalueTy::Ty { ty } = base_ty {
+ if let PlaceTy::Ty { ty } = base_ty {
if ty.references_error() {
assert!(self.errors_reported);
- return LvalueTy::Ty {
+ return PlaceTy::Ty {
ty: self.tcx().types.err,
};
}
self.sanitize_projection(base_ty, &proj.elem, lvalue, location)
}
};
- if let LvalueContext::Copy = context {
+ if let PlaceContext::Copy = context {
let ty = lvalue_ty.to_ty(self.tcx());
if self.cx.infcx.type_moves_by_default(self.cx.param_env, ty, DUMMY_SP) {
span_mirbug!(self, lvalue,
fn sanitize_projection(
&mut self,
- base: LvalueTy<'tcx>,
- pi: &LvalueElem<'tcx>,
- lvalue: &Lvalue<'tcx>,
+ base: PlaceTy<'tcx>,
+ pi: &PlaceElem<'tcx>,
+ lvalue: &Place<'tcx>,
location: Location,
- ) -> LvalueTy<'tcx> {
+ ) -> PlaceTy<'tcx> {
debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, lvalue);
let tcx = self.tcx();
let base_ty = base.to_ty(tcx);
match *pi {
ProjectionElem::Deref => {
let deref_ty = base_ty.builtin_deref(true, ty::LvaluePreference::NoPreference);
- LvalueTy::Ty {
+ PlaceTy::Ty {
ty: deref_ty.map(|t| t.ty).unwrap_or_else(|| {
span_mirbug_and_err!(self, lvalue, "deref of non-pointer {:?}", base_ty)
}),
}
}
ProjectionElem::Index(i) => {
- let index_ty = Lvalue::Local(i).ty(self.mir, tcx).to_ty(tcx);
+ let index_ty = Place::Local(i).ty(self.mir, tcx).to_ty(tcx);
if index_ty != tcx.types.usize {
- LvalueTy::Ty {
+ PlaceTy::Ty {
ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
}
} else {
- LvalueTy::Ty {
+ PlaceTy::Ty {
ty: base_ty.builtin_index().unwrap_or_else(|| {
span_mirbug_and_err!(self, lvalue, "index of non-array {:?}", base_ty)
}),
}
ProjectionElem::ConstantIndex { .. } => {
// consider verifying in-bounds
- LvalueTy::Ty {
+ PlaceTy::Ty {
ty: base_ty.builtin_index().unwrap_or_else(|| {
span_mirbug_and_err!(self, lvalue, "index of non-array {:?}", base_ty)
}),
}
}
- ProjectionElem::Subslice { from, to } => LvalueTy::Ty {
+ ProjectionElem::Subslice { from, to } => PlaceTy::Ty {
ty: match base_ty.sty {
ty::TyArray(inner, size) => {
let size = size.val.to_const_int().unwrap().to_u64().unwrap();
ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty {
ty::TyAdt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => {
if index >= adt_def.variants.len() {
- LvalueTy::Ty {
+ PlaceTy::Ty {
ty: span_mirbug_and_err!(
self,
lvalue,
),
}
} else {
- LvalueTy::Downcast {
+ PlaceTy::Downcast {
adt_def,
substs,
variant_index: index,
}
}
}
- _ => LvalueTy::Ty {
+ _ => PlaceTy::Ty {
ty: span_mirbug_and_err!(
self,
lvalue,
field_count
),
}
- LvalueTy::Ty { ty: fty }
+ PlaceTy::Ty { ty: fty }
}
}
}
fn field_ty(
&mut self,
parent: &fmt::Debug,
- base_ty: LvalueTy<'tcx>,
+ base_ty: PlaceTy<'tcx>,
field: Field,
location: Location,
) -> Result<Ty<'tcx>, FieldAccessError> {
let tcx = self.tcx();
let (variant, substs) = match base_ty {
- LvalueTy::Downcast {
+ PlaceTy::Downcast {
adt_def,
substs,
variant_index,
} => (&adt_def.variants[variant_index], substs),
- LvalueTy::Ty { ty } => match ty.sty {
+ PlaceTy::Ty { ty } => match ty.sty {
ty::TyAdt(adt_def, substs) if !adt_def.is_enum() => {
(&adt_def.variants[0], substs)
}
mir: &Mir<'tcx>,
term: &Terminator<'tcx>,
sig: &ty::FnSig<'tcx>,
- destination: &Option<(Lvalue<'tcx>, BasicBlock)>,
+ destination: &Option<(Place<'tcx>, BasicBlock)>,
term_location: Location,
) {
let tcx = self.tcx();
pub fn is_disaligned<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
local_decls: &L,
param_env: ty::ParamEnv<'tcx>,
- lvalue: &Lvalue<'tcx>)
+ lvalue: &Place<'tcx>)
-> bool
where L: HasLocalDecls<'tcx>
{
fn is_within_packed<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
local_decls: &L,
- lvalue: &Lvalue<'tcx>)
+ lvalue: &Place<'tcx>)
-> bool
where L: HasLocalDecls<'tcx>
{
let mut lvalue = lvalue;
- while let &Lvalue::Projection(box Projection {
+ while let &Place::Projection(box Projection {
ref base, ref elem
}) = lvalue {
match *elem {
//! Def-use analysis.
use rustc::mir::{Local, Location, Mir};
-use rustc::mir::visit::{LvalueContext, MutVisitor, Visitor};
+use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
use rustc_data_structures::indexed_vec::IndexVec;
use std::marker::PhantomData;
use std::mem;
#[derive(Clone)]
pub struct Use<'tcx> {
- pub context: LvalueContext<'tcx>,
+ pub context: PlaceContext<'tcx>,
pub location: Location,
}
fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Mir<'tcx>, mut callback: F)
where F: for<'a> FnMut(&'a mut Local,
- LvalueContext<'tcx>,
+ PlaceContext<'tcx>,
Location) {
for lvalue_use in &self.info[local].defs_and_uses {
MutateUseVisitor::new(local,
impl<'tcx> Visitor<'tcx> for DefUseFinder<'tcx> {
fn visit_local(&mut self,
&local: &Local,
- context: LvalueContext<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
self.info[local].defs_and_uses.push(Use {
context,
impl<'tcx, F> MutateUseVisitor<'tcx, F> {
fn new(query: Local, callback: F, _: &Mir<'tcx>)
-> MutateUseVisitor<'tcx, F>
- where F: for<'a> FnMut(&'a mut Local, LvalueContext<'tcx>, Location) {
+ where F: for<'a> FnMut(&'a mut Local, PlaceContext<'tcx>, Location) {
MutateUseVisitor {
query,
callback,
}
impl<'tcx, F> MutVisitor<'tcx> for MutateUseVisitor<'tcx, F>
- where F: for<'a> FnMut(&'a mut Local, LvalueContext<'tcx>, Location) {
+ where F: for<'a> FnMut(&'a mut Local, PlaceContext<'tcx>, Location) {
fn visit_local(&mut self,
local: &mut Local,
- context: LvalueContext<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
if *local == self.query {
(self.callback)(local, context, location)
source_info: SourceInfo,
- lvalue: &'l Lvalue<'tcx>,
+ lvalue: &'l Place<'tcx>,
path: D::Path,
succ: BasicBlock,
unwind: Unwind,
pub fn elaborate_drop<'b, 'tcx, D>(
elaborator: &mut D,
source_info: SourceInfo,
- lvalue: &Lvalue<'tcx>,
+ lvalue: &Place<'tcx>,
path: D::Path,
succ: BasicBlock,
unwind: Unwind,
impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
where D: DropElaborator<'b, 'tcx>
{
- fn lvalue_ty(&self, lvalue: &Lvalue<'tcx>) -> Ty<'tcx> {
+ fn lvalue_ty(&self, lvalue: &Place<'tcx>) -> Ty<'tcx> {
lvalue.ty(self.elaborator.mir(), self.tcx()).to_ty(self.tcx())
}
/// Return the lvalue and move path for each field of `variant`,
/// (the move path is `None` if the field is a rest field).
fn move_paths_for_fields(&self,
- base_lv: &Lvalue<'tcx>,
+ base_lv: &Place<'tcx>,
variant_path: D::Path,
variant: &'tcx ty::VariantDef,
substs: &'tcx Substs<'tcx>)
- -> Vec<(Lvalue<'tcx>, Option<D::Path>)>
+ -> Vec<(Place<'tcx>, Option<D::Path>)>
{
variant.fields.iter().enumerate().map(|(i, f)| {
let field = Field::new(i);
}
fn drop_subpath(&mut self,
- lvalue: &Lvalue<'tcx>,
+ lvalue: &Place<'tcx>,
path: Option<D::Path>,
succ: BasicBlock,
unwind: Unwind)
fn drop_halfladder(&mut self,
unwind_ladder: &[Unwind],
mut succ: BasicBlock,
- fields: &[(Lvalue<'tcx>, Option<D::Path>)])
+ fields: &[(Place<'tcx>, Option<D::Path>)])
-> Vec<BasicBlock>
{
Some(succ).into_iter().chain(
/// NOTE: this does not clear the master drop flag, so you need
/// to point succ/unwind on a `drop_ladder_bottom`.
fn drop_ladder<'a>(&mut self,
- fields: Vec<(Lvalue<'tcx>, Option<D::Path>)>,
+ fields: Vec<(Place<'tcx>, Option<D::Path>)>,
succ: BasicBlock,
unwind: Unwind)
-> (BasicBlock, Unwind)
// discriminant after it is free-ed, because that
// way lies only trouble.
let discr_ty = adt.repr.discr_type().to_ty(self.tcx());
- let discr = Lvalue::Local(self.new_temp(discr_ty));
+ let discr = Place::Local(self.new_temp(discr_ty));
let discr_rv = Rvalue::Discriminant(self.lvalue.clone());
let switch_block = BasicBlockData {
statements: vec![self.assign(&discr, discr_rv)],
mutbl: hir::Mutability::MutMutable
});
let ref_lvalue = self.new_temp(ref_ty);
- let unit_temp = Lvalue::Local(self.new_temp(tcx.mk_nil()));
+ let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
let result = BasicBlockData {
statements: vec![self.assign(
- &Lvalue::Local(ref_lvalue),
+ &Place::Local(ref_lvalue),
Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, self.lvalue.clone())
)],
terminator: Some(Terminator {
kind: TerminatorKind::Call {
func: Operand::function_handle(tcx, drop_fn.def_id, substs,
self.source_info.span),
- args: vec![Operand::Move(Lvalue::Local(ref_lvalue))],
+ args: vec![Operand::Move(Place::Local(ref_lvalue))],
destination: Some((unit_temp, succ)),
cleanup: unwind.into_option(),
},
fn drop_loop(&mut self,
succ: BasicBlock,
cur: Local,
- length_or_end: &Lvalue<'tcx>,
+ length_or_end: &Place<'tcx>,
ety: Ty<'tcx>,
unwind: Unwind,
ptr_based: bool)
-> BasicBlock
{
- let copy = |lv: &Lvalue<'tcx>| Operand::Copy(lv.clone());
- let move_ = |lv: &Lvalue<'tcx>| Operand::Move(lv.clone());
+ let copy = |lv: &Place<'tcx>| Operand::Copy(lv.clone());
+ let move_ = |lv: &Place<'tcx>| Operand::Move(lv.clone());
let tcx = self.tcx();
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
ty: ety,
mutbl: hir::Mutability::MutMutable
});
- let ptr = &Lvalue::Local(self.new_temp(ref_ty));
- let can_go = &Lvalue::Local(self.new_temp(tcx.types.bool));
+ let ptr = &Place::Local(self.new_temp(ref_ty));
+ let can_go = &Place::Local(self.new_temp(tcx.types.bool));
let one = self.constant_usize(1);
let (ptr_next, cur_next) = if ptr_based {
- (Rvalue::Use(copy(&Lvalue::Local(cur))),
- Rvalue::BinaryOp(BinOp::Offset, copy(&Lvalue::Local(cur)), one))
+ (Rvalue::Use(copy(&Place::Local(cur))),
+ Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Local(cur)), one))
} else {
(Rvalue::Ref(
tcx.types.re_erased,
BorrowKind::Mut,
self.lvalue.clone().index(cur)),
- Rvalue::BinaryOp(BinOp::Add, copy(&Lvalue::Local(cur)), one))
+ Rvalue::BinaryOp(BinOp::Add, copy(&Place::Local(cur)), one))
};
let drop_block = BasicBlockData {
statements: vec![
self.assign(ptr, ptr_next),
- self.assign(&Lvalue::Local(cur), cur_next)
+ self.assign(&Place::Local(cur), cur_next)
],
is_cleanup: unwind.is_cleanup(),
terminator: Some(Terminator {
let loop_block = BasicBlockData {
statements: vec![
self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq,
- copy(&Lvalue::Local(cur)),
+ copy(&Place::Local(cur)),
copy(length_or_end)))
],
is_cleanup: unwind.is_cleanup(),
let tcx = self.tcx();
- let move_ = |lv: &Lvalue<'tcx>| Operand::Move(lv.clone());
- let size = &Lvalue::Local(self.new_temp(tcx.types.usize));
- let size_is_zero = &Lvalue::Local(self.new_temp(tcx.types.bool));
+ let move_ = |lv: &Place<'tcx>| Operand::Move(lv.clone());
+ let size = &Place::Local(self.new_temp(tcx.types.usize));
+ let size_is_zero = &Place::Local(self.new_temp(tcx.types.bool));
let base_block = BasicBlockData {
statements: vec![
self.assign(size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
};
let cur = self.new_temp(iter_ty);
- let length = Lvalue::Local(self.new_temp(tcx.types.usize));
+ let length = Place::Local(self.new_temp(tcx.types.usize));
let length_or_end = if ptr_based {
- Lvalue::Local(self.new_temp(iter_ty))
+ Place::Local(self.new_temp(iter_ty))
} else {
length.clone()
};
unwind,
ptr_based);
- let cur = Lvalue::Local(cur);
+ let cur = Place::Local(cur);
let zero = self.constant_usize(0);
let mut drop_block_stmts = vec![];
drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.lvalue.clone())));
if ptr_based {
let tmp_ty = tcx.mk_mut_ptr(self.lvalue_ty(self.lvalue));
- let tmp = Lvalue::Local(self.new_temp(tmp_ty));
+ let tmp = Place::Local(self.new_temp(tmp_ty));
// tmp = &LV;
// cur = tmp as *mut T;
// end = Offset(cur, len);
unwind: Unwind
) -> BasicBlock {
let tcx = self.tcx();
- let unit_temp = Lvalue::Local(self.new_temp(tcx.mk_nil()));
+ let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
})
}
- fn assign(&self, lhs: &Lvalue<'tcx>, rhs: Rvalue<'tcx>) -> Statement<'tcx> {
+ fn assign(&self, lhs: &Place<'tcx>, rhs: Rvalue<'tcx>) -> Statement<'tcx> {
Statement {
source_info: self.source_info,
kind: StatementKind::Assign(lhs.clone(), rhs)
if i > 0 {
write!(w, ", ")?;
}
- write!(w, "{:?}: {}", Lvalue::Local(arg), escape(&mir.local_decls[arg].ty))?;
+ write!(w, "{:?}: {}", Place::Local(arg), escape(&mir.local_decls[arg].ty))?;
}
write!(w, ") -> {}", escape(mir.return_ty()))?;
if let Some(name) = decl.name {
write!(w, r#"{:?}: {}; // {}<br align="left"/>"#,
- Lvalue::Local(local), escape(&decl.ty), name)?;
+ Place::Local(local), escape(&decl.ty), name)?;
} else {
write!(w, r#"let mut {:?}: {};<br align="left"/>"#,
- Lvalue::Local(local), escape(&decl.ty))?;
+ Place::Local(local), escape(&decl.ty))?;
}
}
//! doesn't matter).
use rustc::mir::*;
-use rustc::mir::visit::{LvalueContext, Visitor};
+use rustc::mir::visit::{PlaceContext, Visitor};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::indexed_set::IdxSetBuf;
use util::pretty::{dump_enabled, write_basic_block, write_mir_intro};
}
impl<'tcx> Visitor<'tcx> for DefsUsesVisitor {
- fn visit_local(&mut self, &local: &Local, context: LvalueContext<'tcx>, _: Location) {
+ fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) {
match context {
///////////////////////////////////////////////////////////////////////////
// DEFS
- LvalueContext::Store |
+ PlaceContext::Store |
// We let Call define the result in both the success and
// unwind cases. This is not really correct, however it
// properly, we would apply the def in call only to the
// input from the success path and not the unwind
// path. -nmatsakis
- LvalueContext::Call |
+ PlaceContext::Call |
// Storage live and storage dead aren't proper defines, but we can ignore
// values that come before them.
- LvalueContext::StorageLive |
- LvalueContext::StorageDead => {
+ PlaceContext::StorageLive |
+ PlaceContext::StorageDead => {
self.defs_uses.add_def(local);
}
// purposes of NLL, these are special in that **all** the
// lifetimes appearing in the variable must be live for each regular use.
- LvalueContext::Projection(..) |
+ PlaceContext::Projection(..) |
// Borrows only consider their local used at the point of the borrow.
// This won't affect the results since we use this analysis for generators
// and we only care about the result at suspension points. Borrows cannot
// cross suspension points so this behavior is unproblematic.
- LvalueContext::Borrow { .. } |
+ PlaceContext::Borrow { .. } |
- LvalueContext::Inspect |
- LvalueContext::Copy |
- LvalueContext::Move |
- LvalueContext::Validate => {
+ PlaceContext::Inspect |
+ PlaceContext::Copy |
+ PlaceContext::Move |
+ PlaceContext::Validate => {
if self.mode.include_regular_use {
self.defs_uses.add_use(local);
}
// uses in drop are special because `#[may_dangle]`
// attributes can affect whether lifetimes must be live.
- LvalueContext::Drop => {
+ PlaceContext::Drop => {
if self.mode.include_drops {
self.defs_uses.add_use(local);
}
self.new_statements.push((loc, stmt));
}
- pub fn add_assign(&mut self, loc: Location, lv: Lvalue<'tcx>, rv: Rvalue<'tcx>) {
+ pub fn add_assign(&mut self, loc: Location, lv: Place<'tcx>, rv: Rvalue<'tcx>) {
self.add_statement(loc, StatementKind::Assign(lv, rv));
}
if i != 0 {
write!(w, ", ")?;
}
- write!(w, "{:?}: {}", Lvalue::Local(arg), mir.local_decls[arg].ty)?;
+ write!(w, "{:?}: {}", Place::Local(arg), mir.local_decls[arg].ty)?;
}
write!(w, ") -> {}", mir.return_ty())
use rustc_const_math::{ConstUsize};
use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
use rustc::mir::{Constant, Literal, Location, Local, LocalDecl};
-use rustc::mir::{Lvalue, LvalueElem, LvalueProjection};
+use rustc::mir::{Place, PlaceElem, PlaceProjection};
use rustc::mir::{Mir, Operand, ProjectionElem};
use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData};
}
fn visit_lvalue(&mut self,
- lvalue: &Lvalue<'tcx>,
- context: mir_visit::LvalueContext<'tcx>,
+ lvalue: &Place<'tcx>,
+ context: mir_visit::PlaceContext<'tcx>,
location: Location) {
- self.record("Lvalue", lvalue);
+ self.record("Place", lvalue);
self.record(match *lvalue {
- Lvalue::Local(..) => "Lvalue::Local",
- Lvalue::Static(..) => "Lvalue::Static",
- Lvalue::Projection(..) => "Lvalue::Projection",
+ Place::Local(..) => "Place::Local",
+ Place::Static(..) => "Place::Static",
+ Place::Projection(..) => "Place::Projection",
}, lvalue);
self.super_lvalue(lvalue, context, location);
}
fn visit_projection(&mut self,
- lvalue: &LvalueProjection<'tcx>,
- context: mir_visit::LvalueContext<'tcx>,
+ lvalue: &PlaceProjection<'tcx>,
+ context: mir_visit::PlaceContext<'tcx>,
location: Location) {
- self.record("LvalueProjection", lvalue);
+ self.record("PlaceProjection", lvalue);
self.super_projection(lvalue, context, location);
}
fn visit_projection_elem(&mut self,
- lvalue: &LvalueElem<'tcx>,
- context: mir_visit::LvalueContext<'tcx>,
+ lvalue: &PlaceElem<'tcx>,
+ context: mir_visit::PlaceContext<'tcx>,
location: Location) {
- self.record("LvalueElem", lvalue);
+ self.record("PlaceElem", lvalue);
self.record(match *lvalue {
- ProjectionElem::Deref => "LvalueElem::Deref",
- ProjectionElem::Subslice { .. } => "LvalueElem::Subslice",
- ProjectionElem::Field(..) => "LvalueElem::Field",
- ProjectionElem::Index(..) => "LvalueElem::Index",
- ProjectionElem::ConstantIndex { .. } => "LvalueElem::ConstantIndex",
- ProjectionElem::Downcast(..) => "LvalueElem::Downcast",
+ ProjectionElem::Deref => "PlaceElem::Deref",
+ ProjectionElem::Subslice { .. } => "PlaceElem::Subslice",
+ ProjectionElem::Field(..) => "PlaceElem::Field",
+ ProjectionElem::Index(..) => "PlaceElem::Index",
+ ProjectionElem::ConstantIndex { .. } => "PlaceElem::ConstantIndex",
+ ProjectionElem::Downcast(..) => "PlaceElem::Downcast",
}, lvalue);
self.super_projection_elem(lvalue, context, location);
}
use cabi_nvptx;
use cabi_nvptx64;
use cabi_hexagon;
-use mir::lvalue::{Alignment, LvalueRef};
+use mir::lvalue::{Alignment, PlaceRef};
use mir::operand::OperandValue;
use type_::Type;
use type_of::{LayoutLlvmExt, PointerKind};
/// lvalue for the original Rust type of this argument/return.
/// Can be used for both storing formal arguments into Rust variables
/// or results of call/invoke instructions into their destinations.
- pub fn store(&self, bcx: &Builder<'a, 'tcx>, val: ValueRef, dst: LvalueRef<'tcx>) {
+ pub fn store(&self, bcx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
if self.is_ignore() {
return;
}
}
}
- pub fn store_fn_arg(&self, bcx: &Builder<'a, 'tcx>, idx: &mut usize, dst: LvalueRef<'tcx>) {
+ pub fn store_fn_arg(&self, bcx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) {
if self.pad.is_some() {
*idx += 1;
}
use rustc::hir;
-use mir::lvalue::LvalueRef;
+use mir::lvalue::PlaceRef;
use mir::operand::OperandValue;
use std::ffi::CString;
pub fn trans_inline_asm<'a, 'tcx>(
bcx: &Builder<'a, 'tcx>,
ia: &hir::InlineAsm,
- outputs: Vec<LvalueRef<'tcx>>,
+ outputs: Vec<PlaceRef<'tcx>>,
mut inputs: Vec<ValueRef>
) {
let mut ext_constraints = vec![];
use rustc::session::Session;
use rustc_incremental;
use allocator;
-use mir::lvalue::LvalueRef;
+use mir::lvalue::PlaceRef;
use attributes;
use builder::Builder;
use callee;
/// Coerce `src`, which is a reference to a value of type `src_ty`,
/// to a value of type `dst_ty` and store the result in `dst`
pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
- src: LvalueRef<'tcx>,
- dst: LvalueRef<'tcx>) {
+ src: PlaceRef<'tcx>,
+ dst: PlaceRef<'tcx>) {
let src_ty = src.layout.ty;
let dst_ty = dst.layout.ty;
let coerce_ptr = || {
use llvm;
use llvm::{ValueRef};
use abi::{Abi, FnType, PassMode};
-use mir::lvalue::{LvalueRef, Alignment};
+use mir::lvalue::{PlaceRef, Alignment};
use mir::operand::{OperandRef, OperandValue};
use base::*;
use common::*;
let name = &*tcx.item_name(def_id);
let llret_ty = ccx.layout_of(ret_ty).llvm_type(ccx);
- let result = LvalueRef::new_sized(llresult, fn_ty.ret.layout, Alignment::AbiAligned);
+ let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, Alignment::AbiAligned);
let simple = get_simple_intrinsic(ccx, name);
let llval = match name {
OperandValue::Ref(ptr, align) => (ptr, align),
_ => bug!()
};
- let arg = LvalueRef::new_sized(ptr, arg.layout, align);
+ let arg = PlaceRef::new_sized(ptr, arg.layout, align);
(0..contents.len()).map(|i| {
arg.project_field(bcx, i).load(bcx).immediate()
}).collect()
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc::middle::const_val::ConstVal;
use rustc::mir::{self, Location, TerminatorKind, Literal};
-use rustc::mir::visit::{Visitor, LvalueContext};
+use rustc::mir::visit::{Visitor, PlaceContext};
use rustc::mir::traversal;
use rustc::ty;
use rustc::ty::layout::LayoutOf;
impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
fn visit_assign(&mut self,
block: mir::BasicBlock,
- lvalue: &mir::Lvalue<'tcx>,
+ lvalue: &mir::Place<'tcx>,
rvalue: &mir::Rvalue<'tcx>,
location: Location) {
debug!("visit_assign(block={:?}, lvalue={:?}, rvalue={:?})", block, lvalue, rvalue);
- if let mir::Lvalue::Local(index) = *lvalue {
+ if let mir::Place::Local(index) = *lvalue {
self.mark_assigned(index);
if !self.cx.rvalue_creates_operand(rvalue) {
self.mark_as_lvalue(index);
}
} else {
- self.visit_lvalue(lvalue, LvalueContext::Store, location);
+ self.visit_lvalue(lvalue, PlaceContext::Store, location);
}
self.visit_rvalue(rvalue, location);
// is not guaranteed to be statically dominated by the
// definition of x, so x must always be in an alloca.
if let mir::Operand::Move(ref lvalue) = args[0] {
- self.visit_lvalue(lvalue, LvalueContext::Drop, location);
+ self.visit_lvalue(lvalue, PlaceContext::Drop, location);
}
}
_ => {}
}
fn visit_lvalue(&mut self,
- lvalue: &mir::Lvalue<'tcx>,
- context: LvalueContext<'tcx>,
+ lvalue: &mir::Place<'tcx>,
+ context: PlaceContext<'tcx>,
location: Location) {
debug!("visit_lvalue(lvalue={:?}, context={:?})", lvalue, context);
let ccx = self.cx.ccx;
- if let mir::Lvalue::Projection(ref proj) = *lvalue {
+ if let mir::Place::Projection(ref proj) = *lvalue {
// Allow uses of projections that are ZSTs or from scalar fields.
let is_consume = match context {
- LvalueContext::Copy | LvalueContext::Move => true,
+ PlaceContext::Copy | PlaceContext::Move => true,
_ => false
};
if is_consume {
// A deref projection only reads the pointer, never needs the lvalue.
if let mir::ProjectionElem::Deref = proj.elem {
- return self.visit_lvalue(&proj.base, LvalueContext::Copy, location);
+ return self.visit_lvalue(&proj.base, PlaceContext::Copy, location);
}
}
fn visit_local(&mut self,
&index: &mir::Local,
- context: LvalueContext<'tcx>,
+ context: PlaceContext<'tcx>,
_: Location) {
match context {
- LvalueContext::Call => {
+ PlaceContext::Call => {
self.mark_assigned(index);
}
- LvalueContext::StorageLive |
- LvalueContext::StorageDead |
- LvalueContext::Validate |
- LvalueContext::Copy |
- LvalueContext::Move => {}
+ PlaceContext::StorageLive |
+ PlaceContext::StorageDead |
+ PlaceContext::Validate |
+ PlaceContext::Copy |
+ PlaceContext::Move => {}
- LvalueContext::Inspect |
- LvalueContext::Store |
- LvalueContext::Borrow { .. } |
- LvalueContext::Projection(..) => {
+ PlaceContext::Inspect |
+ PlaceContext::Store |
+ PlaceContext::Borrow { .. } |
+ PlaceContext::Projection(..) => {
self.mark_as_lvalue(index);
}
- LvalueContext::Drop => {
- let ty = mir::Lvalue::Local(index).ty(self.cx.mir, self.cx.ccx.tcx());
+ PlaceContext::Drop => {
+ let ty = mir::Place::Local(index).ty(self.cx.mir, self.cx.ccx.tcx());
let ty = self.cx.monomorphize(&ty.to_ty(self.cx.ccx.tcx()));
// Only need the lvalue if we're actually dropping it.
use super::{MirContext, LocalRef};
use super::constant::Const;
-use super::lvalue::{Alignment, LvalueRef};
+use super::lvalue::{Alignment, PlaceRef};
use super::operand::OperandRef;
use super::operand::OperandValue::{Pair, Ref, Immediate};
}
PassMode::Direct(_) | PassMode::Pair(..) => {
- let op = self.trans_consume(&bcx, &mir::Lvalue::Local(mir::RETURN_POINTER));
+ let op = self.trans_consume(&bcx, &mir::Place::Local(mir::RETURN_POINTER));
if let Ref(llval, align) = op.val {
bcx.load(llval, align.non_abi())
} else {
let op = match self.locals[mir::RETURN_POINTER] {
LocalRef::Operand(Some(op)) => op,
LocalRef::Operand(None) => bug!("use of return before def"),
- LocalRef::Lvalue(tr_lvalue) => {
+ LocalRef::Place(tr_lvalue) => {
OperandRef {
val: Ref(tr_lvalue.llval, tr_lvalue.alignment),
layout: tr_lvalue.layout
};
let llslot = match op.val {
Immediate(_) | Pair(..) => {
- let scratch = LvalueRef::alloca(&bcx, self.fn_ty.ret.layout, "ret");
+ let scratch = PlaceRef::alloca(&bcx, self.fn_ty.ret.layout, "ret");
op.val.store(&bcx, scratch);
scratch.llval
}
match (arg, op.val) {
(&mir::Operand::Copy(_), Ref(..)) |
(&mir::Operand::Constant(_), Ref(..)) => {
- let tmp = LvalueRef::alloca(&bcx, op.layout, "const");
+ let tmp = PlaceRef::alloca(&bcx, op.layout, "const");
op.val.store(&bcx, tmp);
op.val = Ref(tmp.llval, tmp.alignment);
}
Immediate(_) | Pair(..) => {
match arg.mode {
PassMode::Indirect(_) | PassMode::Cast(_) => {
- let scratch = LvalueRef::alloca(bcx, arg.layout, "arg");
+ let scratch = PlaceRef::alloca(bcx, arg.layout, "arg");
op.val.store(bcx, scratch);
(scratch.llval, Alignment::AbiAligned, true)
}
// think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't
// have scary latent bugs around.
- let scratch = LvalueRef::alloca(bcx, arg.layout, "arg");
+ let scratch = PlaceRef::alloca(bcx, arg.layout, "arg");
base::memcpy_ty(bcx, scratch.llval, llval, op.layout, align.non_abi());
(scratch.llval, Alignment::AbiAligned, true)
}
(align | Alignment::Packed(arg.layout.align))
.non_abi());
} else {
- // We can't use `LvalueRef::load` here because the argument
+ // We can't use `PlaceRef::load` here because the argument
// may have a type we don't treat as immediate, but the ABI
// used for this call is passing it by-value. In that case,
// the load would just produce `OperandValue::Ref` instead
// Handle both by-ref and immediate tuples.
if let Ref(llval, align) = tuple.val {
- let tuple_ptr = LvalueRef::new_sized(llval, tuple.layout, align);
+ let tuple_ptr = PlaceRef::new_sized(llval, tuple.layout, align);
for i in 0..tuple.layout.fields.count() {
let field_ptr = tuple_ptr.project_field(bcx, i);
self.trans_argument(bcx, field_ptr.load(bcx), llargs, &args[i]);
}
}
- fn get_personality_slot(&mut self, bcx: &Builder<'a, 'tcx>) -> LvalueRef<'tcx> {
+ fn get_personality_slot(&mut self, bcx: &Builder<'a, 'tcx>) -> PlaceRef<'tcx> {
let ccx = bcx.ccx;
if let Some(slot) = self.personality_slot {
slot
ccx.tcx().mk_mut_ptr(ccx.tcx().types.u8),
ccx.tcx().types.i32
], false));
- let slot = LvalueRef::alloca(bcx, layout, "personalityslot");
+ let slot = PlaceRef::alloca(bcx, layout, "personalityslot");
self.personality_slot = Some(slot);
slot
}
}
fn make_return_dest(&mut self, bcx: &Builder<'a, 'tcx>,
- dest: &mir::Lvalue<'tcx>, fn_ret: &ArgType<'tcx>,
+ dest: &mir::Place<'tcx>, fn_ret: &ArgType<'tcx>,
llargs: &mut Vec<ValueRef>, is_intrinsic: bool)
-> ReturnDest<'tcx> {
// If the return is ignored, we can just return a do-nothing ReturnDest
if fn_ret.is_ignore() {
return ReturnDest::Nothing;
}
- let dest = if let mir::Lvalue::Local(index) = *dest {
+ let dest = if let mir::Place::Local(index) = *dest {
match self.locals[index] {
- LocalRef::Lvalue(dest) => dest,
+ LocalRef::Place(dest) => dest,
LocalRef::Operand(None) => {
// Handle temporary lvalues, specifically Operand ones, as
// they don't have allocas
return if fn_ret.is_indirect() {
// Odd, but possible, case, we have an operand temporary,
// but the calling convention has an indirect return.
- let tmp = LvalueRef::alloca(bcx, fn_ret.layout, "tmp_ret");
+ let tmp = PlaceRef::alloca(bcx, fn_ret.layout, "tmp_ret");
tmp.storage_live(bcx);
llargs.push(tmp.llval);
ReturnDest::IndirectOperand(tmp, index)
// Currently, intrinsics always need a location to store
// the result. so we create a temporary alloca for the
// result
- let tmp = LvalueRef::alloca(bcx, fn_ret.layout, "tmp_ret");
+ let tmp = PlaceRef::alloca(bcx, fn_ret.layout, "tmp_ret");
tmp.storage_live(bcx);
ReturnDest::IndirectOperand(tmp, index)
} else {
fn trans_transmute(&mut self, bcx: &Builder<'a, 'tcx>,
src: &mir::Operand<'tcx>,
- dst: &mir::Lvalue<'tcx>) {
- if let mir::Lvalue::Local(index) = *dst {
+ dst: &mir::Place<'tcx>) {
+ if let mir::Place::Local(index) = *dst {
match self.locals[index] {
- LocalRef::Lvalue(lvalue) => self.trans_transmute_into(bcx, src, lvalue),
+ LocalRef::Place(lvalue) => self.trans_transmute_into(bcx, src, lvalue),
LocalRef::Operand(None) => {
let dst_layout = bcx.ccx.layout_of(self.monomorphized_lvalue_ty(dst));
assert!(!dst_layout.ty.has_erasable_regions());
- let lvalue = LvalueRef::alloca(bcx, dst_layout, "transmute_temp");
+ let lvalue = PlaceRef::alloca(bcx, dst_layout, "transmute_temp");
lvalue.storage_live(bcx);
self.trans_transmute_into(bcx, src, lvalue);
let op = lvalue.load(bcx);
fn trans_transmute_into(&mut self, bcx: &Builder<'a, 'tcx>,
src: &mir::Operand<'tcx>,
- dst: LvalueRef<'tcx>) {
+ dst: PlaceRef<'tcx>) {
let src = self.trans_operand(bcx, src);
let llty = src.layout.llvm_type(bcx.ccx);
let cast_ptr = bcx.pointercast(dst.llval, llty.ptr_to());
let align = src.layout.align.min(dst.layout.align);
src.val.store(bcx,
- LvalueRef::new_sized(cast_ptr, src.layout, Alignment::Packed(align)));
+ PlaceRef::new_sized(cast_ptr, src.layout, Alignment::Packed(align)));
}
DirectOperand(index) => {
// If there is a cast, we have to store and reload.
let op = if let PassMode::Cast(_) = ret_ty.mode {
- let tmp = LvalueRef::alloca(bcx, ret_ty.layout, "tmp_ret");
+ let tmp = PlaceRef::alloca(bcx, ret_ty.layout, "tmp_ret");
tmp.storage_live(bcx);
ret_ty.store(bcx, llval, tmp);
let op = tmp.load(bcx);
// Do nothing, the return value is indirect or ignored
Nothing,
// Store the return value to the pointer
- Store(LvalueRef<'tcx>),
+ Store(PlaceRef<'tcx>),
// Stores an indirect return value to an operand local lvalue
- IndirectOperand(LvalueRef<'tcx>, mir::Local),
+ IndirectOperand(PlaceRef<'tcx>, mir::Local),
// Stores a direct return value to an operand local lvalue
DirectOperand(mir::Local)
}
use rustc::infer::TransNormalize;
use rustc::traits;
use rustc::mir;
-use rustc::mir::tcx::LvalueTy;
+use rustc::mir::tcx::PlaceTy;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::layout::{self, LayoutOf, Size};
use rustc::ty::cast::{CastTy, IntTy};
self.get_pair(ccx)
}
- fn as_lvalue(&self) -> ConstLvalue<'tcx> {
- ConstLvalue {
+ fn as_lvalue(&self) -> ConstPlace<'tcx> {
+ ConstPlace {
base: Base::Value(self.llval),
llextra: ptr::null_mut(),
ty: self.ty
/// An lvalue as seen from a constant.
#[derive(Copy, Clone)]
-struct ConstLvalue<'tcx> {
+struct ConstPlace<'tcx> {
base: Base,
llextra: ValueRef,
ty: Ty<'tcx>
}
-impl<'tcx> ConstLvalue<'tcx> {
+impl<'tcx> ConstPlace<'tcx> {
fn to_const(&self, span: Span) -> Const<'tcx> {
match self.base {
Base::Value(val) => Const::new(val, self.ty),
assert!(self.llextra != ptr::null_mut());
self.llextra
}
- _ => bug!("unexpected type `{}` in ConstLvalue::len", self.ty)
+ _ => bug!("unexpected type `{}` in ConstPlace::len", self.ty)
}
}
}
}
fn store(&mut self,
- dest: &mir::Lvalue<'tcx>,
+ dest: &mir::Place<'tcx>,
value: Result<Const<'tcx>, ConstEvalErr<'tcx>>,
span: Span) {
- if let mir::Lvalue::Local(index) = *dest {
+ if let mir::Place::Local(index) = *dest {
self.locals[index] = Some(value);
} else {
span_bug!(span, "assignment to {:?} in constant", dest);
}
}
- fn const_lvalue(&self, lvalue: &mir::Lvalue<'tcx>, span: Span)
- -> Result<ConstLvalue<'tcx>, ConstEvalErr<'tcx>> {
+ fn const_lvalue(&self, lvalue: &mir::Place<'tcx>, span: Span)
+ -> Result<ConstPlace<'tcx>, ConstEvalErr<'tcx>> {
let tcx = self.ccx.tcx();
- if let mir::Lvalue::Local(index) = *lvalue {
+ if let mir::Place::Local(index) = *lvalue {
return self.locals[index].clone().unwrap_or_else(|| {
span_bug!(span, "{:?} not initialized", lvalue)
}).map(|v| v.as_lvalue());
}
let lvalue = match *lvalue {
- mir::Lvalue::Local(_) => bug!(), // handled above
- mir::Lvalue::Static(box mir::Static { def_id, ty }) => {
- ConstLvalue {
+ mir::Place::Local(_) => bug!(), // handled above
+ mir::Place::Static(box mir::Static { def_id, ty }) => {
+ ConstPlace {
base: Base::Static(consts::get_static(self.ccx, def_id)),
llextra: ptr::null_mut(),
ty: self.monomorphize(&ty),
}
}
- mir::Lvalue::Projection(ref projection) => {
+ mir::Place::Projection(ref projection) => {
let tr_base = self.const_lvalue(&projection.base, span)?;
- let projected_ty = LvalueTy::Ty { ty: tr_base.ty }
+ let projected_ty = PlaceTy::Ty { ty: tr_base.ty }
.projection_ty(tcx, &projection.elem);
let base = tr_base.to_const(span);
let projected_ty = self.monomorphize(&projected_ty).to_ty(tcx);
(Base::Value(llprojected), llextra)
}
mir::ProjectionElem::Index(index) => {
- let index = &mir::Operand::Copy(mir::Lvalue::Local(index));
+ let index = &mir::Operand::Copy(mir::Place::Local(index));
let llindex = self.const_operand(index, span)?.llval;
let iv = if let Some(iv) = common::const_to_opt_u128(llindex, false) {
}
_ => span_bug!(span, "{:?} in constant", projection.elem)
};
- ConstLvalue {
+ ConstPlace {
base: projected,
llextra,
ty: projected_ty
use rustc::ty::{self, Ty};
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
use rustc::mir;
-use rustc::mir::tcx::LvalueTy;
+use rustc::mir::tcx::PlaceTy;
use rustc_data_structures::indexed_vec::Idx;
use base;
use builder::Builder;
}
#[derive(Copy, Clone, Debug)]
-pub struct LvalueRef<'tcx> {
+pub struct PlaceRef<'tcx> {
/// Pointer to the contents of the lvalue
pub llval: ValueRef,
pub alignment: Alignment,
}
-impl<'a, 'tcx> LvalueRef<'tcx> {
+impl<'a, 'tcx> PlaceRef<'tcx> {
pub fn new_sized(llval: ValueRef,
layout: TyLayout<'tcx>,
alignment: Alignment)
- -> LvalueRef<'tcx> {
- LvalueRef {
+ -> PlaceRef<'tcx> {
+ PlaceRef {
llval,
llextra: ptr::null_mut(),
layout,
}
pub fn alloca(bcx: &Builder<'a, 'tcx>, layout: TyLayout<'tcx>, name: &str)
- -> LvalueRef<'tcx> {
+ -> PlaceRef<'tcx> {
debug!("alloca({:?}: {:?})", name, layout);
let tmp = bcx.alloca(layout.llvm_type(bcx.ccx), name, layout.align);
Self::new_sized(tmp, layout, Alignment::AbiAligned)
C_usize(ccx, count)
}
} else {
- bug!("unexpected layout `{:#?}` in LvalueRef::len", self.layout)
+ bug!("unexpected layout `{:#?}` in PlaceRef::len", self.layout)
}
}
}
pub fn load(&self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
- debug!("LvalueRef::load: {:?}", self);
+ debug!("PlaceRef::load: {:?}", self);
assert!(!self.has_extra());
}
/// Access a field, at a point when the value's case is known.
- pub fn project_field(self, bcx: &Builder<'a, 'tcx>, ix: usize) -> LvalueRef<'tcx> {
+ pub fn project_field(self, bcx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx> {
let ccx = bcx.ccx;
let field = self.layout.field(ccx, ix);
let offset = self.layout.fields.offset(ix);
} else {
bcx.struct_gep(self.llval, self.layout.llvm_field_index(ix))
};
- LvalueRef {
+ PlaceRef {
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
llval: bcx.pointercast(llval, field.llvm_type(ccx).ptr_to()),
llextra: if ccx.shared().type_has_metadata(field.ty) {
let ll_fty = field.llvm_type(ccx);
debug!("struct_field_ptr: Field type is {:?}", ll_fty);
- LvalueRef {
+ PlaceRef {
llval: bcx.pointercast(byte_ptr, ll_fty.ptr_to()),
llextra: self.llextra,
layout: field,
}
pub fn project_index(&self, bcx: &Builder<'a, 'tcx>, llindex: ValueRef)
- -> LvalueRef<'tcx> {
- LvalueRef {
+ -> PlaceRef<'tcx> {
+ PlaceRef {
llval: bcx.inbounds_gep(self.llval, &[C_usize(bcx.ccx, 0), llindex]),
llextra: ptr::null_mut(),
layout: self.layout.field(bcx.ccx, 0),
}
pub fn project_downcast(&self, bcx: &Builder<'a, 'tcx>, variant_index: usize)
- -> LvalueRef<'tcx> {
+ -> PlaceRef<'tcx> {
let mut downcast = *self;
downcast.layout = self.layout.for_variant(bcx.ccx, variant_index);
impl<'a, 'tcx> MirContext<'a, 'tcx> {
pub fn trans_lvalue(&mut self,
bcx: &Builder<'a, 'tcx>,
- lvalue: &mir::Lvalue<'tcx>)
- -> LvalueRef<'tcx> {
+ lvalue: &mir::Place<'tcx>)
+ -> PlaceRef<'tcx> {
debug!("trans_lvalue(lvalue={:?})", lvalue);
let ccx = bcx.ccx;
let tcx = ccx.tcx();
- if let mir::Lvalue::Local(index) = *lvalue {
+ if let mir::Place::Local(index) = *lvalue {
match self.locals[index] {
- LocalRef::Lvalue(lvalue) => {
+ LocalRef::Place(lvalue) => {
return lvalue;
}
LocalRef::Operand(..) => {
}
let result = match *lvalue {
- mir::Lvalue::Local(_) => bug!(), // handled above
- mir::Lvalue::Static(box mir::Static { def_id, ty }) => {
- LvalueRef::new_sized(consts::get_static(ccx, def_id),
+ mir::Place::Local(_) => bug!(), // handled above
+ mir::Place::Static(box mir::Static { def_id, ty }) => {
+ PlaceRef::new_sized(consts::get_static(ccx, def_id),
ccx.layout_of(self.monomorphize(&ty)),
Alignment::AbiAligned)
},
- mir::Lvalue::Projection(box mir::Projection {
+ mir::Place::Projection(box mir::Projection {
ref base,
elem: mir::ProjectionElem::Deref
}) => {
// Load the pointer from its location.
self.trans_consume(bcx, base).deref(bcx.ccx)
}
- mir::Lvalue::Projection(ref projection) => {
+ mir::Place::Projection(ref projection) => {
let tr_base = self.trans_lvalue(bcx, &projection.base);
match projection.elem {
tr_base.project_field(bcx, field.index())
}
mir::ProjectionElem::Index(index) => {
- let index = &mir::Operand::Copy(mir::Lvalue::Local(index));
+ let index = &mir::Operand::Copy(mir::Place::Local(index));
let index = self.trans_operand(bcx, index);
let llindex = index.immediate();
tr_base.project_index(bcx, llindex)
mir::ProjectionElem::Subslice { from, to } => {
let mut subslice = tr_base.project_index(bcx,
C_usize(bcx.ccx, from as u64));
- let projected_ty = LvalueTy::Ty { ty: tr_base.layout.ty }
+ let projected_ty = PlaceTy::Ty { ty: tr_base.layout.ty }
.projection_ty(tcx, &projection.elem).to_ty(bcx.tcx());
subslice.layout = bcx.ccx.layout_of(self.monomorphize(&projected_ty));
result
}
- pub fn monomorphized_lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> {
+ pub fn monomorphized_lvalue_ty(&self, lvalue: &mir::Place<'tcx>) -> Ty<'tcx> {
let tcx = self.ccx.tcx();
let lvalue_ty = lvalue.ty(self.mir, tcx);
self.monomorphize(&lvalue_ty.to_ty(tcx))
pub use self::constant::trans_static_initializer;
use self::analyze::CleanupKind;
-use self::lvalue::{Alignment, LvalueRef};
+use self::lvalue::{Alignment, PlaceRef};
use rustc::mir::traversal;
use self::operand::{OperandRef, OperandValue};
/// don't really care about it very much. Anyway, this value
/// contains an alloca into which the personality is stored and
/// then later loaded when generating the DIVERGE_BLOCK.
- personality_slot: Option<LvalueRef<'tcx>>,
+ personality_slot: Option<PlaceRef<'tcx>>,
/// A `Block` for each MIR `BasicBlock`
blocks: IndexVec<mir::BasicBlock, BasicBlockRef>,
unreachable_block: Option<BasicBlockRef>,
/// The location where each MIR arg/var/tmp/ret is stored. This is
- /// usually an `LvalueRef` representing an alloca, but not always:
+ /// usually an `PlaceRef` representing an alloca, but not always:
/// sometimes we can skip the alloca and just store the value
/// directly using an `OperandRef`, which makes for tighter LLVM
/// IR. The conditions for using an `OperandRef` are as follows:
}
enum LocalRef<'tcx> {
- Lvalue(LvalueRef<'tcx>),
+ Place(PlaceRef<'tcx>),
Operand(Option<OperandRef<'tcx>>),
}
}
debug!("alloc: {:?} ({}) -> lvalue", local, name);
- let lvalue = LvalueRef::alloca(&bcx, layout, &name.as_str());
+ let lvalue = PlaceRef::alloca(&bcx, layout, &name.as_str());
if dbg {
let (scope, span) = mircx.debug_loc(decl.source_info);
declare_local(&bcx, &mircx.debug_context, name, layout.ty, scope,
VariableAccess::DirectVariable { alloca: lvalue.llval },
VariableKind::LocalVariable, span);
}
- LocalRef::Lvalue(lvalue)
+ LocalRef::Place(lvalue)
} else {
// Temporary or return pointer
if local == mir::RETURN_POINTER && mircx.fn_ty.ret.is_indirect() {
debug!("alloc: {:?} (return pointer) -> lvalue", local);
let llretptr = llvm::get_param(llfn, 0);
- LocalRef::Lvalue(LvalueRef::new_sized(llretptr,
+ LocalRef::Place(PlaceRef::new_sized(llretptr,
layout,
Alignment::AbiAligned))
} else if lvalue_locals.contains(local.index()) {
debug!("alloc: {:?} -> lvalue", local);
- LocalRef::Lvalue(LvalueRef::alloca(&bcx, layout, &format!("{:?}", local)))
+ LocalRef::Place(PlaceRef::alloca(&bcx, layout, &format!("{:?}", local)))
} else {
// If this is an immediate local, we do not create an
// alloca in advance. Instead we wait until we see the
_ => bug!("spread argument isn't a tuple?!")
};
- let lvalue = LvalueRef::alloca(bcx, bcx.ccx.layout_of(arg_ty), &name);
+ let lvalue = PlaceRef::alloca(bcx, bcx.ccx.layout_of(arg_ty), &name);
for i in 0..tupled_arg_tys.len() {
let arg = &mircx.fn_ty.args[idx];
idx += 1;
);
});
- return LocalRef::Lvalue(lvalue);
+ return LocalRef::Place(lvalue);
}
let arg = &mircx.fn_ty.args[idx];
let llarg = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
bcx.set_value_name(llarg, &name);
llarg_idx += 1;
- LvalueRef::new_sized(llarg, arg.layout, Alignment::AbiAligned)
+ PlaceRef::new_sized(llarg, arg.layout, Alignment::AbiAligned)
} else {
- let tmp = LvalueRef::alloca(bcx, arg.layout, &name);
+ let tmp = PlaceRef::alloca(bcx, arg.layout, &name);
arg.store_fn_arg(bcx, &mut llarg_idx, tmp);
tmp
};
// doesn't actually strip the offset when splitting the closure
// environment into its components so it ends up out of bounds.
let env_ptr = if !env_ref {
- let alloc = LvalueRef::alloca(bcx,
+ let alloc = PlaceRef::alloca(bcx,
bcx.ccx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
"__debuginfo_env_ptr");
bcx.store(lvalue.llval, alloc.llval, None);
);
}
});
- LocalRef::Lvalue(lvalue)
+ LocalRef::Place(lvalue)
}).collect()
}
use std::ptr;
use super::{MirContext, LocalRef};
-use super::lvalue::{Alignment, LvalueRef};
+use super::lvalue::{Alignment, PlaceRef};
/// The representation of a Rust value. The enum variant is in fact
/// uniquely determined by the value's type, but is kept as a
}
}
- pub fn deref(self, ccx: &CrateContext<'a, 'tcx>) -> LvalueRef<'tcx> {
+ pub fn deref(self, ccx: &CrateContext<'a, 'tcx>) -> PlaceRef<'tcx> {
let projected_ty = self.layout.ty.builtin_deref(true, ty::NoPreference)
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)).ty;
let (llptr, llextra) = match self.val {
OperandValue::Pair(llptr, llextra) => (llptr, llextra),
OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self)
};
- LvalueRef {
+ PlaceRef {
llval: llptr,
llextra,
layout: ccx.layout_of(projected_ty),
}
impl<'a, 'tcx> OperandValue {
- pub fn store(self, bcx: &Builder<'a, 'tcx>, dest: LvalueRef<'tcx>) {
+ pub fn store(self, bcx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest);
// Avoid generating stores of zero-sized values, because the only way to have a zero-sized
// value is through `undef`, and store itself is useless.
impl<'a, 'tcx> MirContext<'a, 'tcx> {
fn maybe_trans_consume_direct(&mut self,
bcx: &Builder<'a, 'tcx>,
- lvalue: &mir::Lvalue<'tcx>)
+ lvalue: &mir::Place<'tcx>)
-> Option<OperandRef<'tcx>>
{
debug!("maybe_trans_consume_direct(lvalue={:?})", lvalue);
// watch out for locals that do not have an
// alloca; they are handled somewhat differently
- if let mir::Lvalue::Local(index) = *lvalue {
+ if let mir::Place::Local(index) = *lvalue {
match self.locals[index] {
LocalRef::Operand(Some(o)) => {
return Some(o);
LocalRef::Operand(None) => {
bug!("use of {:?} before def", lvalue);
}
- LocalRef::Lvalue(..) => {
+ LocalRef::Place(..) => {
// use path below
}
}
}
// Moves out of scalar and scalar pair fields are trivial.
- if let &mir::Lvalue::Projection(ref proj) = lvalue {
+ if let &mir::Place::Projection(ref proj) = lvalue {
if let mir::ProjectionElem::Field(ref f, _) = proj.elem {
if let Some(o) = self.maybe_trans_consume_direct(bcx, &proj.base) {
return Some(o.extract_field(bcx, f.index()));
pub fn trans_consume(&mut self,
bcx: &Builder<'a, 'tcx>,
- lvalue: &mir::Lvalue<'tcx>)
+ lvalue: &mir::Place<'tcx>)
-> OperandRef<'tcx>
{
debug!("trans_consume(lvalue={:?})", lvalue);
let operand = val.to_operand(bcx.ccx);
if let OperandValue::Ref(ptr, align) = operand.val {
// If this is a OperandValue::Ref to an immediate constant, load it.
- LvalueRef::new_sized(ptr, operand.layout, align).load(bcx)
+ PlaceRef::new_sized(ptr, operand.layout, align).load(bcx)
} else {
operand
}
use super::{MirContext, LocalRef};
use super::constant::const_scalar_checked_binop;
use super::operand::{OperandRef, OperandValue};
-use super::lvalue::LvalueRef;
+use super::lvalue::PlaceRef;
impl<'a, 'tcx> MirContext<'a, 'tcx> {
pub fn trans_rvalue(&mut self,
bcx: Builder<'a, 'tcx>,
- dest: LvalueRef<'tcx>,
+ dest: PlaceRef<'tcx>,
rvalue: &mir::Rvalue<'tcx>)
-> Builder<'a, 'tcx>
{
// index into the struct, and this case isn't
// important enough for it.
debug!("trans_rvalue: creating ugly alloca");
- let scratch = LvalueRef::alloca(&bcx, operand.layout, "__unsize_temp");
+ let scratch = PlaceRef::alloca(&bcx, operand.layout, "__unsize_temp");
scratch.storage_live(&bcx);
operand.val.store(&bcx, scratch);
base::coerce_unsized_into(&bcx, scratch, dest);
scratch.storage_dead(&bcx);
}
OperandValue::Ref(llref, align) => {
- let source = LvalueRef::new_sized(llref, operand.layout, align);
+ let source = PlaceRef::new_sized(llref, operand.layout, align);
base::coerce_unsized_into(&bcx, source, dest);
}
}
header_bcx.cond_br(keep_going, body_bcx.llbb(), next_bcx.llbb());
tr_elem.val.store(&body_bcx,
- LvalueRef::new_sized(current, tr_elem.layout, dest.alignment));
+ PlaceRef::new_sized(current, tr_elem.layout, dest.alignment));
let next = body_bcx.inbounds_gep(current, &[C_usize(bcx.ccx, 1)]);
body_bcx.br(header_bcx.llbb());
fn evaluate_array_len(&mut self,
bcx: &Builder<'a, 'tcx>,
- lvalue: &mir::Lvalue<'tcx>) -> ValueRef
+ lvalue: &mir::Place<'tcx>) -> ValueRef
{
// ZST are passed as operands and require special handling
// because trans_lvalue() panics if Local is operand.
- if let mir::Lvalue::Local(index) = *lvalue {
+ if let mir::Place::Local(index) = *lvalue {
if let LocalRef::Operand(Some(op)) = self.locals[index] {
if let ty::TyArray(_, n) = op.layout.ty.sty {
let n = n.val.to_const_int().unwrap().to_u64().unwrap();
self.set_debug_loc(&bcx, statement.source_info);
match statement.kind {
mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
- if let mir::Lvalue::Local(index) = *lvalue {
+ if let mir::Place::Local(index) = *lvalue {
match self.locals[index] {
- LocalRef::Lvalue(tr_dest) => {
+ LocalRef::Place(tr_dest) => {
self.trans_rvalue(bcx, tr_dest, rvalue)
}
LocalRef::Operand(None) => {
bcx
}
mir::StatementKind::StorageLive(local) => {
- if let LocalRef::Lvalue(tr_lval) = self.locals[local] {
+ if let LocalRef::Place(tr_lval) = self.locals[local] {
tr_lval.storage_live(&bcx);
}
bcx
}
mir::StatementKind::StorageDead(local) => {
- if let LocalRef::Lvalue(tr_lval) = self.locals[local] {
+ if let LocalRef::Place(tr_lval) = self.locals[local] {
tr_lval.storage_dead(&bcx);
}
bcx
}
/// Get the LLVM type corresponding to a Rust type, i.e. `rustc::ty::Ty`.
- /// The pointee type of the pointer in `LvalueRef` is always this type.
+ /// The pointee type of the pointer in `PlaceRef` is always this type.
/// For sized types, it is also the right LLVM type for an `alloca`
/// containing a value of that type, and most immediates (except `bool`).
/// Unsized types, however, are represented by a "minimal unit", e.g.
fn visit_static(&mut self,
static_: &mir::Static<'tcx>,
- context: mir::visit::LvalueContext<'tcx>,
+ context: mir::visit::PlaceContext<'tcx>,
location: Location) {
debug!("visiting static {:?} @ {:?}", static_.def_id, location);