MIR: s/lv(al(ue)?)?/place in function/variable/module names.
This commit is contained in:
parent
511743c438
commit
473f044225
60 changed files with 1047 additions and 1046 deletions
|
@ -272,24 +272,24 @@ for mir::StatementKind<'gcx> {
|
||||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
|
mir::StatementKind::Assign(ref place, ref rvalue) => {
|
||||||
lvalue.hash_stable(hcx, hasher);
|
place.hash_stable(hcx, hasher);
|
||||||
rvalue.hash_stable(hcx, hasher);
|
rvalue.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::StatementKind::SetDiscriminant { ref lvalue, variant_index } => {
|
mir::StatementKind::SetDiscriminant { ref place, variant_index } => {
|
||||||
lvalue.hash_stable(hcx, hasher);
|
place.hash_stable(hcx, hasher);
|
||||||
variant_index.hash_stable(hcx, hasher);
|
variant_index.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::StatementKind::StorageLive(ref lvalue) |
|
mir::StatementKind::StorageLive(ref place) |
|
||||||
mir::StatementKind::StorageDead(ref lvalue) => {
|
mir::StatementKind::StorageDead(ref place) => {
|
||||||
lvalue.hash_stable(hcx, hasher);
|
place.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::StatementKind::EndRegion(ref region_scope) => {
|
mir::StatementKind::EndRegion(ref region_scope) => {
|
||||||
region_scope.hash_stable(hcx, hasher);
|
region_scope.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::StatementKind::Validate(ref op, ref lvalues) => {
|
mir::StatementKind::Validate(ref op, ref places) => {
|
||||||
op.hash_stable(hcx, hasher);
|
op.hash_stable(hcx, hasher);
|
||||||
lvalues.hash_stable(hcx, hasher);
|
places.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::StatementKind::Nop => {}
|
mir::StatementKind::Nop => {}
|
||||||
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||||
|
@ -309,7 +309,7 @@ impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
|
||||||
hcx: &mut StableHashingContext<'gcx>,
|
hcx: &mut StableHashingContext<'gcx>,
|
||||||
hasher: &mut StableHasher<W>)
|
hasher: &mut StableHasher<W>)
|
||||||
{
|
{
|
||||||
self.lval.hash_stable(hcx, hasher);
|
self.place.hash_stable(hcx, hasher);
|
||||||
self.ty.hash_stable(hcx, hasher);
|
self.ty.hash_stable(hcx, hasher);
|
||||||
self.re.hash_stable(hcx, hasher);
|
self.re.hash_stable(hcx, hasher);
|
||||||
self.mutbl.hash_stable(hcx, hasher);
|
self.mutbl.hash_stable(hcx, hasher);
|
||||||
|
@ -330,8 +330,8 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Place<'gcx> {
|
||||||
mir::Place::Static(ref statik) => {
|
mir::Place::Static(ref statik) => {
|
||||||
statik.hash_stable(hcx, hasher);
|
statik.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::Place::Projection(ref lvalue_projection) => {
|
mir::Place::Projection(ref place_projection) => {
|
||||||
lvalue_projection.hash_stable(hcx, hasher);
|
place_projection.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,11 +420,11 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Operand<'gcx> {
|
||||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
mir::Operand::Copy(ref lvalue) => {
|
mir::Operand::Copy(ref place) => {
|
||||||
lvalue.hash_stable(hcx, hasher);
|
place.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::Operand::Move(ref lvalue) => {
|
mir::Operand::Move(ref place) => {
|
||||||
lvalue.hash_stable(hcx, hasher);
|
place.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::Operand::Constant(ref constant) => {
|
mir::Operand::Constant(ref constant) => {
|
||||||
constant.hash_stable(hcx, hasher);
|
constant.hash_stable(hcx, hasher);
|
||||||
|
@ -447,13 +447,13 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Rvalue<'gcx> {
|
||||||
operand.hash_stable(hcx, hasher);
|
operand.hash_stable(hcx, hasher);
|
||||||
val.hash_stable(hcx, hasher);
|
val.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::Rvalue::Ref(region, borrow_kind, ref lvalue) => {
|
mir::Rvalue::Ref(region, borrow_kind, ref place) => {
|
||||||
region.hash_stable(hcx, hasher);
|
region.hash_stable(hcx, hasher);
|
||||||
borrow_kind.hash_stable(hcx, hasher);
|
borrow_kind.hash_stable(hcx, hasher);
|
||||||
lvalue.hash_stable(hcx, hasher);
|
place.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::Rvalue::Len(ref lvalue) => {
|
mir::Rvalue::Len(ref place) => {
|
||||||
lvalue.hash_stable(hcx, hasher);
|
place.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::Rvalue::Cast(cast_kind, ref operand, ty) => {
|
mir::Rvalue::Cast(cast_kind, ref operand, ty) => {
|
||||||
cast_kind.hash_stable(hcx, hasher);
|
cast_kind.hash_stable(hcx, hasher);
|
||||||
|
@ -470,8 +470,8 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Rvalue<'gcx> {
|
||||||
op.hash_stable(hcx, hasher);
|
op.hash_stable(hcx, hasher);
|
||||||
operand.hash_stable(hcx, hasher);
|
operand.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::Rvalue::Discriminant(ref lvalue) => {
|
mir::Rvalue::Discriminant(ref place) => {
|
||||||
lvalue.hash_stable(hcx, hasher);
|
place.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::Rvalue::NullaryOp(op, ty) => {
|
mir::Rvalue::NullaryOp(op, ty) => {
|
||||||
op.hash_stable(hcx, hasher);
|
op.hash_stable(hcx, hasher);
|
||||||
|
|
|
@ -139,7 +139,7 @@ impl<'tcx> Mir<'tcx> {
|
||||||
upvar_decls: Vec<UpvarDecl>,
|
upvar_decls: Vec<UpvarDecl>,
|
||||||
span: Span) -> Self
|
span: Span) -> Self
|
||||||
{
|
{
|
||||||
// We need `arg_count` locals, and one for the return pointer
|
// We need `arg_count` locals, and one for the return place
|
||||||
assert!(local_decls.len() >= arg_count + 1,
|
assert!(local_decls.len() >= arg_count + 1,
|
||||||
"expected at least {} locals, got {}", arg_count + 1, local_decls.len());
|
"expected at least {} locals, got {}", arg_count + 1, local_decls.len());
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ impl<'tcx> Mir<'tcx> {
|
||||||
let index = local.0 as usize;
|
let index = local.0 as usize;
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
debug_assert!(self.local_decls[local].mutability == Mutability::Mut,
|
debug_assert!(self.local_decls[local].mutability == Mutability::Mut,
|
||||||
"return pointer should be mutable");
|
"return place should be mutable");
|
||||||
|
|
||||||
LocalKind::ReturnPointer
|
LocalKind::ReturnPointer
|
||||||
} else if index < self.arg_count + 1 {
|
} else if index < self.arg_count + 1 {
|
||||||
|
@ -249,7 +249,7 @@ impl<'tcx> Mir<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
|
/// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
|
||||||
/// locals that are neither arguments nor the return pointer).
|
/// locals that are neither arguments nor the return place).
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn vars_and_temps_iter(&self) -> impl Iterator<Item=Local> {
|
pub fn vars_and_temps_iter(&self) -> impl Iterator<Item=Local> {
|
||||||
let arg_count = self.arg_count;
|
let arg_count = self.arg_count;
|
||||||
|
@ -280,7 +280,7 @@ impl<'tcx> Mir<'tcx> {
|
||||||
|
|
||||||
/// Return the return type, it always return first element from `local_decls` array
|
/// Return the return type, it always return first element from `local_decls` array
|
||||||
pub fn return_ty(&self) -> Ty<'tcx> {
|
pub fn return_ty(&self) -> Ty<'tcx> {
|
||||||
self.local_decls[RETURN_POINTER].ty
|
self.local_decls[RETURN_PLACE].ty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +417,7 @@ pub enum BorrowKind {
|
||||||
newtype_index!(Local
|
newtype_index!(Local
|
||||||
{
|
{
|
||||||
DEBUG_FORMAT = "_{}",
|
DEBUG_FORMAT = "_{}",
|
||||||
const RETURN_POINTER = 0,
|
const RETURN_PLACE = 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Classifies locals into categories. See `Mir::local_kind`.
|
/// Classifies locals into categories. See `Mir::local_kind`.
|
||||||
|
@ -436,12 +436,12 @@ pub enum LocalKind {
|
||||||
/// A MIR local.
|
/// A MIR local.
|
||||||
///
|
///
|
||||||
/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
|
/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
|
||||||
/// argument, or the return pointer.
|
/// argument, or the return place.
|
||||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||||
pub struct LocalDecl<'tcx> {
|
pub struct LocalDecl<'tcx> {
|
||||||
/// `let mut x` vs `let x`.
|
/// `let mut x` vs `let x`.
|
||||||
///
|
///
|
||||||
/// Temporaries and the return pointer are always mutable.
|
/// Temporaries and the return place are always mutable.
|
||||||
pub mutability: Mutability,
|
pub mutability: Mutability,
|
||||||
|
|
||||||
/// True if this corresponds to a user-declared local variable.
|
/// True if this corresponds to a user-declared local variable.
|
||||||
|
@ -520,11 +520,11 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a `LocalDecl` for the return pointer.
|
/// Builds a `LocalDecl` for the return place.
|
||||||
///
|
///
|
||||||
/// This must be inserted into the `local_decls` list as the first local.
|
/// This must be inserted into the `local_decls` list as the first local.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_return_pointer(return_ty: Ty, span: Span) -> LocalDecl {
|
pub fn new_return_place(return_ty: Ty, span: Span) -> LocalDecl {
|
||||||
LocalDecl {
|
LocalDecl {
|
||||||
mutability: Mutability::Mut,
|
mutability: Mutability::Mut,
|
||||||
ty: return_ty,
|
ty: return_ty,
|
||||||
|
@ -634,8 +634,8 @@ pub enum TerminatorKind<'tcx> {
|
||||||
/// continue. Emitted by build::scope::diverge_cleanup.
|
/// continue. Emitted by build::scope::diverge_cleanup.
|
||||||
Resume,
|
Resume,
|
||||||
|
|
||||||
/// Indicates a normal return. The return pointer lvalue should
|
/// Indicates a normal return. The return place should have
|
||||||
/// have been filled in by now. This should occur at most once.
|
/// been filled in by now. This should occur at most once.
|
||||||
Return,
|
Return,
|
||||||
|
|
||||||
/// Indicates a terminator that can never be reached.
|
/// Indicates a terminator that can never be reached.
|
||||||
|
@ -650,7 +650,7 @@ pub enum TerminatorKind<'tcx> {
|
||||||
|
|
||||||
/// Drop the Place 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
|
/// that the assignment to LV occurs *even if* the destructor for
|
||||||
/// lvalue unwinds. Its semantics are best explained by by the
|
/// place unwinds. Its semantics are best explained by by the
|
||||||
/// elaboration:
|
/// elaboration:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -878,7 +878,7 @@ impl<'tcx> TerminatorKind<'tcx> {
|
||||||
use self::TerminatorKind::*;
|
use self::TerminatorKind::*;
|
||||||
match *self {
|
match *self {
|
||||||
Goto { .. } => write!(fmt, "goto"),
|
Goto { .. } => write!(fmt, "goto"),
|
||||||
SwitchInt { discr: ref lv, .. } => write!(fmt, "switchInt({:?})", lv),
|
SwitchInt { discr: ref place, .. } => write!(fmt, "switchInt({:?})", place),
|
||||||
Return => write!(fmt, "return"),
|
Return => write!(fmt, "return"),
|
||||||
GeneratorDrop => write!(fmt, "generator_drop"),
|
GeneratorDrop => write!(fmt, "generator_drop"),
|
||||||
Resume => write!(fmt, "resume"),
|
Resume => write!(fmt, "resume"),
|
||||||
|
@ -1006,7 +1006,7 @@ pub enum StatementKind<'tcx> {
|
||||||
Assign(Place<'tcx>, Rvalue<'tcx>),
|
Assign(Place<'tcx>, Rvalue<'tcx>),
|
||||||
|
|
||||||
/// Write the discriminant for a variant to the enum Place.
|
/// Write the discriminant for a variant to the enum Place.
|
||||||
SetDiscriminant { lvalue: Place<'tcx>, variant_index: usize },
|
SetDiscriminant { place: Place<'tcx>, variant_index: usize },
|
||||||
|
|
||||||
/// Start a live range for the storage of the local.
|
/// Start a live range for the storage of the local.
|
||||||
StorageLive(Local),
|
StorageLive(Local),
|
||||||
|
@ -1021,7 +1021,7 @@ pub enum StatementKind<'tcx> {
|
||||||
inputs: Vec<Operand<'tcx>>
|
inputs: Vec<Operand<'tcx>>
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Assert the given lvalues to be valid inhabitants of their type. These statements are
|
/// Assert the given places 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.
|
/// 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.
|
/// See <https://internals.rust-lang.org/t/types-as-contracts/5562/73> for more details.
|
||||||
Validate(ValidationOp, Vec<ValidationOperand<'tcx, Place<'tcx>>>),
|
Validate(ValidationOp, Vec<ValidationOperand<'tcx, Place<'tcx>>>),
|
||||||
|
@ -1038,9 +1038,9 @@ pub enum StatementKind<'tcx> {
|
||||||
/// `Validate` statement.
|
/// `Validate` statement.
|
||||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq)]
|
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq)]
|
||||||
pub enum ValidationOp {
|
pub enum ValidationOp {
|
||||||
/// Recursively traverse the lvalue following the type and validate that all type
|
/// Recursively traverse the place following the type and validate that all type
|
||||||
/// invariants are maintained. Furthermore, acquire exclusive/read-only access to the
|
/// invariants are maintained. Furthermore, acquire exclusive/read-only access to the
|
||||||
/// memory reachable from the lvalue.
|
/// memory reachable from the place.
|
||||||
Acquire,
|
Acquire,
|
||||||
/// Recursive traverse the *mutable* part of the type and relinquish all exclusive
|
/// Recursive traverse the *mutable* part of the type and relinquish all exclusive
|
||||||
/// access.
|
/// access.
|
||||||
|
@ -1065,7 +1065,7 @@ impl Debug for ValidationOp {
|
||||||
// This is generic so that it can be reused by miri
|
// This is generic so that it can be reused by miri
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub struct ValidationOperand<'tcx, T> {
|
pub struct ValidationOperand<'tcx, T> {
|
||||||
pub lval: T,
|
pub place: T,
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
pub re: Option<region::Scope>,
|
pub re: Option<region::Scope>,
|
||||||
pub mutbl: hir::Mutability,
|
pub mutbl: hir::Mutability,
|
||||||
|
@ -1073,7 +1073,7 @@ pub struct ValidationOperand<'tcx, T> {
|
||||||
|
|
||||||
impl<'tcx, T: Debug> Debug for ValidationOperand<'tcx, T> {
|
impl<'tcx, T: Debug> Debug for ValidationOperand<'tcx, T> {
|
||||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||||
write!(fmt, "{:?}: {:?}", self.lval, self.ty)?;
|
write!(fmt, "{:?}: {:?}", self.place, self.ty)?;
|
||||||
if let Some(ce) = self.re {
|
if let Some(ce) = self.re {
|
||||||
// (reuse lifetime rendering policy from ppaux.)
|
// (reuse lifetime rendering policy from ppaux.)
|
||||||
write!(fmt, "/{}", ty::ReScope(ce))?;
|
write!(fmt, "/{}", ty::ReScope(ce))?;
|
||||||
|
@ -1089,14 +1089,14 @@ impl<'tcx> Debug for Statement<'tcx> {
|
||||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||||
use self::StatementKind::*;
|
use self::StatementKind::*;
|
||||||
match self.kind {
|
match self.kind {
|
||||||
Assign(ref lv, ref rv) => write!(fmt, "{:?} = {:?}", lv, rv),
|
Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
|
||||||
// (reuse lifetime rendering policy from ppaux.)
|
// (reuse lifetime rendering policy from ppaux.)
|
||||||
EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
|
EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
|
||||||
Validate(ref op, ref lvalues) => write!(fmt, "Validate({:?}, {:?})", op, lvalues),
|
Validate(ref op, ref places) => write!(fmt, "Validate({:?}, {:?})", op, places),
|
||||||
StorageLive(ref lv) => write!(fmt, "StorageLive({:?})", lv),
|
StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
|
||||||
StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv),
|
StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
|
||||||
SetDiscriminant{lvalue: ref lv, variant_index: index} => {
|
SetDiscriminant { ref place, variant_index } => {
|
||||||
write!(fmt, "discriminant({:?}) = {:?}", lv, index)
|
write!(fmt, "discriminant({:?}) = {:?}", place, variant_index)
|
||||||
},
|
},
|
||||||
InlineAsm { ref asm, ref outputs, ref inputs } => {
|
InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||||
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
|
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
|
||||||
|
@ -1119,7 +1119,7 @@ pub enum Place<'tcx> {
|
||||||
/// static or static mut variable
|
/// static or static mut variable
|
||||||
Static(Box<Static<'tcx>>),
|
Static(Box<Static<'tcx>>),
|
||||||
|
|
||||||
/// projection out of an lvalue (access a field, deref a pointer, etc)
|
/// projection out of a place (access a field, deref a pointer, etc)
|
||||||
Projection(Box<PlaceProjection<'tcx>>),
|
Projection(Box<PlaceProjection<'tcx>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1184,11 +1184,11 @@ pub enum ProjectionElem<'tcx, V, T> {
|
||||||
Downcast(&'tcx AdtDef, usize),
|
Downcast(&'tcx AdtDef, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alias for projections as they appear in lvalues, where the base is an lvalue
|
/// Alias for projections as they appear in places, where the base is a place
|
||||||
/// and the index is a local.
|
/// and the index is a local.
|
||||||
pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'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
|
/// Alias for projections as they appear in places, where the base is a place
|
||||||
/// and the index is a local.
|
/// and the index is a local.
|
||||||
pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
|
pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
|
||||||
|
|
||||||
|
@ -1273,13 +1273,13 @@ pub struct VisibilityScopeData {
|
||||||
// Operands
|
// Operands
|
||||||
|
|
||||||
/// These are values that can appear inside an rvalue (or an index
|
/// These are values that can appear inside an rvalue (or an index
|
||||||
/// lvalue). They are intentionally limited to prevent rvalues from
|
/// place). They are intentionally limited to prevent rvalues from
|
||||||
/// being nested in one another.
|
/// being nested in one another.
|
||||||
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum Operand<'tcx> {
|
pub enum Operand<'tcx> {
|
||||||
/// Copy: The value must be available for use afterwards.
|
/// Copy: The value must be available for use afterwards.
|
||||||
///
|
///
|
||||||
/// This implies that the type of the lvalue must be `Copy`; this is true
|
/// This implies that the type of the place must be `Copy`; this is true
|
||||||
/// by construction during build, but also checked by the MIR type checker.
|
/// by construction during build, but also checked by the MIR type checker.
|
||||||
Copy(Place<'tcx>),
|
Copy(Place<'tcx>),
|
||||||
/// Move: The value (including old borrows of it) will not be used again.
|
/// Move: The value (including old borrows of it) will not be used again.
|
||||||
|
@ -1296,8 +1296,8 @@ impl<'tcx> Debug for Operand<'tcx> {
|
||||||
use self::Operand::*;
|
use self::Operand::*;
|
||||||
match *self {
|
match *self {
|
||||||
Constant(ref a) => write!(fmt, "{:?}", a),
|
Constant(ref a) => write!(fmt, "{:?}", a),
|
||||||
Copy(ref lv) => write!(fmt, "{:?}", lv),
|
Copy(ref place) => write!(fmt, "{:?}", place),
|
||||||
Move(ref lv) => write!(fmt, "move {:?}", lv),
|
Move(ref place) => write!(fmt, "move {:?}", place),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1470,18 +1470,20 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||||
use self::Rvalue::*;
|
use self::Rvalue::*;
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Use(ref lvalue) => write!(fmt, "{:?}", lvalue),
|
Use(ref place) => write!(fmt, "{:?}", place),
|
||||||
Repeat(ref a, ref b) => write!(fmt, "[{:?}; {:?}]", a, b),
|
Repeat(ref a, ref b) => write!(fmt, "[{:?}; {:?}]", a, b),
|
||||||
Len(ref a) => write!(fmt, "Len({:?})", a),
|
Len(ref a) => write!(fmt, "Len({:?})", a),
|
||||||
Cast(ref kind, ref lv, ref ty) => write!(fmt, "{:?} as {:?} ({:?})", lv, ty, kind),
|
Cast(ref kind, ref place, ref ty) => {
|
||||||
|
write!(fmt, "{:?} as {:?} ({:?})", place, ty, kind)
|
||||||
|
}
|
||||||
BinaryOp(ref op, ref a, ref b) => write!(fmt, "{:?}({:?}, {:?})", op, a, b),
|
BinaryOp(ref op, ref a, ref b) => write!(fmt, "{:?}({:?}, {:?})", op, a, b),
|
||||||
CheckedBinaryOp(ref op, ref a, ref b) => {
|
CheckedBinaryOp(ref op, ref a, ref b) => {
|
||||||
write!(fmt, "Checked{:?}({:?}, {:?})", op, a, b)
|
write!(fmt, "Checked{:?}({:?}, {:?})", op, a, b)
|
||||||
}
|
}
|
||||||
UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
|
UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
|
||||||
Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval),
|
Discriminant(ref place) => write!(fmt, "discriminant({:?})", place),
|
||||||
NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
|
NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
|
||||||
Ref(region, borrow_kind, ref lv) => {
|
Ref(region, borrow_kind, ref place) => {
|
||||||
let kind_str = match borrow_kind {
|
let kind_str = match borrow_kind {
|
||||||
BorrowKind::Shared => "",
|
BorrowKind::Shared => "",
|
||||||
BorrowKind::Mut | BorrowKind::Unique => "mut ",
|
BorrowKind::Mut | BorrowKind::Unique => "mut ",
|
||||||
|
@ -1496,26 +1498,26 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||||
// Do not even print 'static
|
// Do not even print 'static
|
||||||
"".to_owned()
|
"".to_owned()
|
||||||
};
|
};
|
||||||
write!(fmt, "&{}{}{:?}", region, kind_str, lv)
|
write!(fmt, "&{}{}{:?}", region, kind_str, place)
|
||||||
}
|
}
|
||||||
|
|
||||||
Aggregate(ref kind, ref lvs) => {
|
Aggregate(ref kind, ref places) => {
|
||||||
fn fmt_tuple(fmt: &mut Formatter, lvs: &[Operand]) -> fmt::Result {
|
fn fmt_tuple(fmt: &mut Formatter, places: &[Operand]) -> fmt::Result {
|
||||||
let mut tuple_fmt = fmt.debug_tuple("");
|
let mut tuple_fmt = fmt.debug_tuple("");
|
||||||
for lv in lvs {
|
for place in places {
|
||||||
tuple_fmt.field(lv);
|
tuple_fmt.field(place);
|
||||||
}
|
}
|
||||||
tuple_fmt.finish()
|
tuple_fmt.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
match **kind {
|
match **kind {
|
||||||
AggregateKind::Array(_) => write!(fmt, "{:?}", lvs),
|
AggregateKind::Array(_) => write!(fmt, "{:?}", places),
|
||||||
|
|
||||||
AggregateKind::Tuple => {
|
AggregateKind::Tuple => {
|
||||||
match lvs.len() {
|
match places.len() {
|
||||||
0 => write!(fmt, "()"),
|
0 => write!(fmt, "()"),
|
||||||
1 => write!(fmt, "({:?},)", lvs[0]),
|
1 => write!(fmt, "({:?},)", places[0]),
|
||||||
_ => fmt_tuple(fmt, lvs),
|
_ => fmt_tuple(fmt, places),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1526,11 +1528,11 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||||
|
|
||||||
match variant_def.ctor_kind {
|
match variant_def.ctor_kind {
|
||||||
CtorKind::Const => Ok(()),
|
CtorKind::Const => Ok(()),
|
||||||
CtorKind::Fn => fmt_tuple(fmt, lvs),
|
CtorKind::Fn => fmt_tuple(fmt, places),
|
||||||
CtorKind::Fictive => {
|
CtorKind::Fictive => {
|
||||||
let mut struct_fmt = fmt.debug_struct("");
|
let mut struct_fmt = fmt.debug_struct("");
|
||||||
for (field, lv) in variant_def.fields.iter().zip(lvs) {
|
for (field, place) in variant_def.fields.iter().zip(places) {
|
||||||
struct_fmt.field(&field.name.as_str(), lv);
|
struct_fmt.field(&field.name.as_str(), place);
|
||||||
}
|
}
|
||||||
struct_fmt.finish()
|
struct_fmt.finish()
|
||||||
}
|
}
|
||||||
|
@ -1547,9 +1549,9 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||||
let mut struct_fmt = fmt.debug_struct(&name);
|
let mut struct_fmt = fmt.debug_struct(&name);
|
||||||
|
|
||||||
tcx.with_freevars(node_id, |freevars| {
|
tcx.with_freevars(node_id, |freevars| {
|
||||||
for (freevar, lv) in freevars.iter().zip(lvs) {
|
for (freevar, place) in freevars.iter().zip(places) {
|
||||||
let var_name = tcx.hir.name(freevar.var_id());
|
let var_name = tcx.hir.name(freevar.var_id());
|
||||||
struct_fmt.field(&var_name.as_str(), lv);
|
struct_fmt.field(&var_name.as_str(), place);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1565,14 +1567,14 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||||
let mut struct_fmt = fmt.debug_struct(&name);
|
let mut struct_fmt = fmt.debug_struct(&name);
|
||||||
|
|
||||||
tcx.with_freevars(node_id, |freevars| {
|
tcx.with_freevars(node_id, |freevars| {
|
||||||
for (freevar, lv) in freevars.iter().zip(lvs) {
|
for (freevar, place) in freevars.iter().zip(places) {
|
||||||
let var_name = tcx.hir.name(freevar.var_id());
|
let var_name = tcx.hir.name(freevar.var_id());
|
||||||
struct_fmt.field(&var_name.as_str(), lv);
|
struct_fmt.field(&var_name.as_str(), place);
|
||||||
}
|
}
|
||||||
struct_fmt.field("$state", &lvs[freevars.len()]);
|
struct_fmt.field("$state", &places[freevars.len()]);
|
||||||
for i in (freevars.len() + 1)..lvs.len() {
|
for i in (freevars.len() + 1)..places.len() {
|
||||||
struct_fmt.field(&format!("${}", i - freevars.len() - 1),
|
struct_fmt.field(&format!("${}", i - freevars.len() - 1),
|
||||||
&lvs[i]);
|
&places[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1831,7 +1833,7 @@ impl<'tcx> TypeFoldable<'tcx> for BasicBlockData<'tcx> {
|
||||||
impl<'tcx> TypeFoldable<'tcx> for ValidationOperand<'tcx, Place<'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 {
|
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||||
ValidationOperand {
|
ValidationOperand {
|
||||||
lval: self.lval.fold_with(folder),
|
place: self.place.fold_with(folder),
|
||||||
ty: self.ty.fold_with(folder),
|
ty: self.ty.fold_with(folder),
|
||||||
re: self.re,
|
re: self.re,
|
||||||
mutbl: self.mutbl,
|
mutbl: self.mutbl,
|
||||||
|
@ -1839,7 +1841,7 @@ impl<'tcx> TypeFoldable<'tcx> for ValidationOperand<'tcx, Place<'tcx>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||||
self.lval.visit_with(visitor) || self.ty.visit_with(visitor)
|
self.place.visit_with(visitor) || self.ty.visit_with(visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1848,9 +1850,9 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
|
||||||
use mir::StatementKind::*;
|
use mir::StatementKind::*;
|
||||||
|
|
||||||
let kind = match self.kind {
|
let kind = match self.kind {
|
||||||
Assign(ref lval, ref rval) => Assign(lval.fold_with(folder), rval.fold_with(folder)),
|
Assign(ref place, ref rval) => Assign(place.fold_with(folder), rval.fold_with(folder)),
|
||||||
SetDiscriminant { ref lvalue, variant_index } => SetDiscriminant {
|
SetDiscriminant { ref place, variant_index } => SetDiscriminant {
|
||||||
lvalue: lvalue.fold_with(folder),
|
place: place.fold_with(folder),
|
||||||
variant_index,
|
variant_index,
|
||||||
},
|
},
|
||||||
StorageLive(ref local) => StorageLive(local.fold_with(folder)),
|
StorageLive(ref local) => StorageLive(local.fold_with(folder)),
|
||||||
|
@ -1867,9 +1869,9 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
|
||||||
// trait with a `fn fold_scope`.
|
// trait with a `fn fold_scope`.
|
||||||
EndRegion(ref region_scope) => EndRegion(region_scope.clone()),
|
EndRegion(ref region_scope) => EndRegion(region_scope.clone()),
|
||||||
|
|
||||||
Validate(ref op, ref lvals) =>
|
Validate(ref op, ref places) =>
|
||||||
Validate(op.clone(),
|
Validate(op.clone(),
|
||||||
lvals.iter().map(|operand| operand.fold_with(folder)).collect()),
|
places.iter().map(|operand| operand.fold_with(folder)).collect()),
|
||||||
|
|
||||||
Nop => Nop,
|
Nop => Nop,
|
||||||
};
|
};
|
||||||
|
@ -1883,8 +1885,8 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
|
||||||
use mir::StatementKind::*;
|
use mir::StatementKind::*;
|
||||||
|
|
||||||
match self.kind {
|
match self.kind {
|
||||||
Assign(ref lval, ref rval) => { lval.visit_with(visitor) || rval.visit_with(visitor) }
|
Assign(ref place, ref rval) => { place.visit_with(visitor) || rval.visit_with(visitor) }
|
||||||
SetDiscriminant { ref lvalue, .. } => lvalue.visit_with(visitor),
|
SetDiscriminant { ref place, .. } => place.visit_with(visitor),
|
||||||
StorageLive(ref local) |
|
StorageLive(ref local) |
|
||||||
StorageDead(ref local) => local.visit_with(visitor),
|
StorageDead(ref local) => local.visit_with(visitor),
|
||||||
InlineAsm { ref outputs, ref inputs, .. } =>
|
InlineAsm { ref outputs, ref inputs, .. } =>
|
||||||
|
@ -1896,8 +1898,8 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
|
||||||
// trait with a `fn visit_scope`.
|
// trait with a `fn visit_scope`.
|
||||||
EndRegion(ref _scope) => false,
|
EndRegion(ref _scope) => false,
|
||||||
|
|
||||||
Validate(ref _op, ref lvalues) =>
|
Validate(ref _op, ref places) =>
|
||||||
lvalues.iter().any(|ty_and_lvalue| ty_and_lvalue.visit_with(visitor)),
|
places.iter().any(|ty_and_place| ty_and_place.visit_with(visitor)),
|
||||||
|
|
||||||
Nop => false,
|
Nop => false,
|
||||||
}
|
}
|
||||||
|
@ -2035,15 +2037,16 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
|
||||||
match *self {
|
match *self {
|
||||||
Use(ref op) => Use(op.fold_with(folder)),
|
Use(ref op) => Use(op.fold_with(folder)),
|
||||||
Repeat(ref op, len) => Repeat(op.fold_with(folder), len),
|
Repeat(ref op, len) => Repeat(op.fold_with(folder), len),
|
||||||
Ref(region, bk, ref lval) => Ref(region.fold_with(folder), bk, lval.fold_with(folder)),
|
Ref(region, bk, ref place) =>
|
||||||
Len(ref lval) => Len(lval.fold_with(folder)),
|
Ref(region.fold_with(folder), bk, place.fold_with(folder)),
|
||||||
|
Len(ref place) => Len(place.fold_with(folder)),
|
||||||
Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
|
Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
|
||||||
BinaryOp(op, ref rhs, ref lhs) =>
|
BinaryOp(op, ref rhs, ref lhs) =>
|
||||||
BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
|
BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
|
||||||
CheckedBinaryOp(op, ref rhs, ref lhs) =>
|
CheckedBinaryOp(op, ref rhs, ref lhs) =>
|
||||||
CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
|
CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
|
||||||
UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
|
UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
|
||||||
Discriminant(ref lval) => Discriminant(lval.fold_with(folder)),
|
Discriminant(ref place) => Discriminant(place.fold_with(folder)),
|
||||||
NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
|
NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
|
||||||
Aggregate(ref kind, ref fields) => {
|
Aggregate(ref kind, ref fields) => {
|
||||||
let kind = box match **kind {
|
let kind = box match **kind {
|
||||||
|
@ -2068,14 +2071,14 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
|
||||||
match *self {
|
match *self {
|
||||||
Use(ref op) => op.visit_with(visitor),
|
Use(ref op) => op.visit_with(visitor),
|
||||||
Repeat(ref op, _) => op.visit_with(visitor),
|
Repeat(ref op, _) => op.visit_with(visitor),
|
||||||
Ref(region, _, ref lval) => region.visit_with(visitor) || lval.visit_with(visitor),
|
Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
|
||||||
Len(ref lval) => lval.visit_with(visitor),
|
Len(ref place) => place.visit_with(visitor),
|
||||||
Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
|
Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
|
||||||
BinaryOp(_, ref rhs, ref lhs) |
|
BinaryOp(_, ref rhs, ref lhs) |
|
||||||
CheckedBinaryOp(_, ref rhs, ref lhs) =>
|
CheckedBinaryOp(_, ref rhs, ref lhs) =>
|
||||||
rhs.visit_with(visitor) || lhs.visit_with(visitor),
|
rhs.visit_with(visitor) || lhs.visit_with(visitor),
|
||||||
UnaryOp(_, ref val) => val.visit_with(visitor),
|
UnaryOp(_, ref val) => val.visit_with(visitor),
|
||||||
Discriminant(ref lval) => lval.visit_with(visitor),
|
Discriminant(ref place) => place.visit_with(visitor),
|
||||||
NullaryOp(_, ty) => ty.visit_with(visitor),
|
NullaryOp(_, ty) => ty.visit_with(visitor),
|
||||||
Aggregate(ref kind, ref fields) => {
|
Aggregate(ref kind, ref fields) => {
|
||||||
(match **kind {
|
(match **kind {
|
||||||
|
@ -2094,16 +2097,16 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
|
||||||
impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
|
impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
|
||||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||||
match *self {
|
match *self {
|
||||||
Operand::Copy(ref lval) => Operand::Copy(lval.fold_with(folder)),
|
Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)),
|
||||||
Operand::Move(ref lval) => Operand::Move(lval.fold_with(folder)),
|
Operand::Move(ref place) => Operand::Move(place.fold_with(folder)),
|
||||||
Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
|
Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Operand::Copy(ref lval) |
|
Operand::Copy(ref place) |
|
||||||
Operand::Move(ref lval) => lval.visit_with(visitor),
|
Operand::Move(ref place) => place.visit_with(visitor),
|
||||||
Operand::Constant(ref c) => c.visit_with(visitor)
|
Operand::Constant(ref c) => c.visit_with(visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,11 +151,11 @@ impl<'tcx> Rvalue<'tcx> {
|
||||||
Rvalue::Repeat(ref operand, count) => {
|
Rvalue::Repeat(ref operand, count) => {
|
||||||
tcx.mk_array_const_usize(operand.ty(local_decls, tcx), count)
|
tcx.mk_array_const_usize(operand.ty(local_decls, tcx), count)
|
||||||
}
|
}
|
||||||
Rvalue::Ref(reg, bk, ref lv) => {
|
Rvalue::Ref(reg, bk, ref place) => {
|
||||||
let lv_ty = lv.ty(local_decls, tcx).to_ty(tcx);
|
let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
|
||||||
tcx.mk_ref(reg,
|
tcx.mk_ref(reg,
|
||||||
ty::TypeAndMut {
|
ty::TypeAndMut {
|
||||||
ty: lv_ty,
|
ty: place_ty,
|
||||||
mutbl: bk.to_mutbl_lossy()
|
mutbl: bk.to_mutbl_lossy()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -177,8 +177,8 @@ impl<'tcx> Rvalue<'tcx> {
|
||||||
Rvalue::UnaryOp(UnOp::Neg, ref operand) => {
|
Rvalue::UnaryOp(UnOp::Neg, ref operand) => {
|
||||||
operand.ty(local_decls, tcx)
|
operand.ty(local_decls, tcx)
|
||||||
}
|
}
|
||||||
Rvalue::Discriminant(ref lval) => {
|
Rvalue::Discriminant(ref place) => {
|
||||||
let ty = lval.ty(local_decls, tcx).to_ty(tcx);
|
let ty = place.ty(local_decls, tcx).to_ty(tcx);
|
||||||
if let ty::TyAdt(adt_def, _) = ty.sty {
|
if let ty::TyAdt(adt_def, _) = ty.sty {
|
||||||
adt_def.repr.discr_type().to_ty(tcx)
|
adt_def.repr.discr_type().to_ty(tcx)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -107,10 +107,10 @@ macro_rules! make_mir_visitor {
|
||||||
|
|
||||||
fn visit_assign(&mut self,
|
fn visit_assign(&mut self,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
lvalue: & $($mutability)* Place<'tcx>,
|
place: & $($mutability)* Place<'tcx>,
|
||||||
rvalue: & $($mutability)* Rvalue<'tcx>,
|
rvalue: & $($mutability)* Rvalue<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
self.super_assign(block, lvalue, rvalue, location);
|
self.super_assign(block, place, rvalue, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_terminator(&mut self,
|
fn visit_terminator(&mut self,
|
||||||
|
@ -145,11 +145,11 @@ macro_rules! make_mir_visitor {
|
||||||
self.super_operand(operand, location);
|
self.super_operand(operand, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lvalue(&mut self,
|
fn visit_place(&mut self,
|
||||||
lvalue: & $($mutability)* Place<'tcx>,
|
place: & $($mutability)* Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
self.super_lvalue(lvalue, context, location);
|
self.super_place(place, context, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_static(&mut self,
|
fn visit_static(&mut self,
|
||||||
|
@ -160,17 +160,17 @@ macro_rules! make_mir_visitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_projection(&mut self,
|
fn visit_projection(&mut self,
|
||||||
lvalue: & $($mutability)* PlaceProjection<'tcx>,
|
place: & $($mutability)* PlaceProjection<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
self.super_projection(lvalue, context, location);
|
self.super_projection(place, context, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_projection_elem(&mut self,
|
fn visit_projection_elem(&mut self,
|
||||||
lvalue: & $($mutability)* PlaceElem<'tcx>,
|
place: & $($mutability)* PlaceElem<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
self.super_projection_elem(lvalue, context, location);
|
self.super_projection_elem(place, context, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_branch(&mut self,
|
fn visit_branch(&mut self,
|
||||||
|
@ -350,21 +350,21 @@ macro_rules! make_mir_visitor {
|
||||||
|
|
||||||
self.visit_source_info(source_info);
|
self.visit_source_info(source_info);
|
||||||
match *kind {
|
match *kind {
|
||||||
StatementKind::Assign(ref $($mutability)* lvalue,
|
StatementKind::Assign(ref $($mutability)* place,
|
||||||
ref $($mutability)* rvalue) => {
|
ref $($mutability)* rvalue) => {
|
||||||
self.visit_assign(block, lvalue, rvalue, location);
|
self.visit_assign(block, place, rvalue, location);
|
||||||
}
|
}
|
||||||
StatementKind::EndRegion(_) => {}
|
StatementKind::EndRegion(_) => {}
|
||||||
StatementKind::Validate(_, ref $($mutability)* lvalues) => {
|
StatementKind::Validate(_, ref $($mutability)* places) => {
|
||||||
for operand in lvalues {
|
for operand in places {
|
||||||
self.visit_lvalue(& $($mutability)* operand.lval,
|
self.visit_place(& $($mutability)* operand.place,
|
||||||
PlaceContext::Validate, location);
|
PlaceContext::Validate, location);
|
||||||
self.visit_ty(& $($mutability)* operand.ty,
|
self.visit_ty(& $($mutability)* operand.ty,
|
||||||
TyContext::Location(location));
|
TyContext::Location(location));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
|
StatementKind::SetDiscriminant{ ref $($mutability)* place, .. } => {
|
||||||
self.visit_lvalue(lvalue, PlaceContext::Store, location);
|
self.visit_place(place, PlaceContext::Store, location);
|
||||||
}
|
}
|
||||||
StatementKind::StorageLive(ref $($mutability)* local) => {
|
StatementKind::StorageLive(ref $($mutability)* local) => {
|
||||||
self.visit_local(local, PlaceContext::StorageLive, location);
|
self.visit_local(local, PlaceContext::StorageLive, location);
|
||||||
|
@ -376,7 +376,7 @@ macro_rules! make_mir_visitor {
|
||||||
ref $($mutability)* inputs,
|
ref $($mutability)* inputs,
|
||||||
asm: _ } => {
|
asm: _ } => {
|
||||||
for output in & $($mutability)* outputs[..] {
|
for output in & $($mutability)* outputs[..] {
|
||||||
self.visit_lvalue(output, PlaceContext::Store, location);
|
self.visit_place(output, PlaceContext::Store, location);
|
||||||
}
|
}
|
||||||
for input in & $($mutability)* inputs[..] {
|
for input in & $($mutability)* inputs[..] {
|
||||||
self.visit_operand(input, location);
|
self.visit_operand(input, location);
|
||||||
|
@ -388,10 +388,10 @@ macro_rules! make_mir_visitor {
|
||||||
|
|
||||||
fn super_assign(&mut self,
|
fn super_assign(&mut self,
|
||||||
_block: BasicBlock,
|
_block: BasicBlock,
|
||||||
lvalue: &$($mutability)* Place<'tcx>,
|
place: &$($mutability)* Place<'tcx>,
|
||||||
rvalue: &$($mutability)* Rvalue<'tcx>,
|
rvalue: &$($mutability)* Rvalue<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
self.visit_lvalue(lvalue, PlaceContext::Store, location);
|
self.visit_place(place, PlaceContext::Store, location);
|
||||||
self.visit_rvalue(rvalue, location);
|
self.visit_rvalue(rvalue, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +440,7 @@ macro_rules! make_mir_visitor {
|
||||||
TerminatorKind::Drop { ref $($mutability)* location,
|
TerminatorKind::Drop { ref $($mutability)* location,
|
||||||
target,
|
target,
|
||||||
unwind } => {
|
unwind } => {
|
||||||
self.visit_lvalue(location, PlaceContext::Drop, source_location);
|
self.visit_place(location, PlaceContext::Drop, source_location);
|
||||||
self.visit_branch(block, target);
|
self.visit_branch(block, target);
|
||||||
unwind.map(|t| self.visit_branch(block, t));
|
unwind.map(|t| self.visit_branch(block, t));
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ macro_rules! make_mir_visitor {
|
||||||
ref $($mutability)* value,
|
ref $($mutability)* value,
|
||||||
target,
|
target,
|
||||||
unwind } => {
|
unwind } => {
|
||||||
self.visit_lvalue(location, PlaceContext::Drop, source_location);
|
self.visit_place(location, PlaceContext::Drop, source_location);
|
||||||
self.visit_operand(value, source_location);
|
self.visit_operand(value, source_location);
|
||||||
self.visit_branch(block, target);
|
self.visit_branch(block, target);
|
||||||
unwind.map(|t| self.visit_branch(block, t));
|
unwind.map(|t| self.visit_branch(block, t));
|
||||||
|
@ -464,7 +464,7 @@ macro_rules! make_mir_visitor {
|
||||||
self.visit_operand(arg, source_location);
|
self.visit_operand(arg, source_location);
|
||||||
}
|
}
|
||||||
if let Some((ref $($mutability)* destination, target)) = *destination {
|
if let Some((ref $($mutability)* destination, target)) = *destination {
|
||||||
self.visit_lvalue(destination, PlaceContext::Call, source_location);
|
self.visit_place(destination, PlaceContext::Call, source_location);
|
||||||
self.visit_branch(block, target);
|
self.visit_branch(block, target);
|
||||||
}
|
}
|
||||||
cleanup.map(|t| self.visit_branch(block, t));
|
cleanup.map(|t| self.visit_branch(block, t));
|
||||||
|
@ -532,14 +532,14 @@ macro_rules! make_mir_visitor {
|
||||||
|
|
||||||
Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => {
|
Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => {
|
||||||
self.visit_region(r, location);
|
self.visit_region(r, location);
|
||||||
self.visit_lvalue(path, PlaceContext::Borrow {
|
self.visit_place(path, PlaceContext::Borrow {
|
||||||
region: *r,
|
region: *r,
|
||||||
kind: bk
|
kind: bk
|
||||||
}, location);
|
}, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Len(ref $($mutability)* path) => {
|
Rvalue::Len(ref $($mutability)* path) => {
|
||||||
self.visit_lvalue(path, PlaceContext::Inspect, location);
|
self.visit_place(path, PlaceContext::Inspect, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Cast(_cast_kind,
|
Rvalue::Cast(_cast_kind,
|
||||||
|
@ -563,8 +563,8 @@ macro_rules! make_mir_visitor {
|
||||||
self.visit_operand(op, location);
|
self.visit_operand(op, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Discriminant(ref $($mutability)* lvalue) => {
|
Rvalue::Discriminant(ref $($mutability)* place) => {
|
||||||
self.visit_lvalue(lvalue, PlaceContext::Inspect, location);
|
self.visit_place(place, PlaceContext::Inspect, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
|
Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
|
||||||
|
@ -611,11 +611,11 @@ macro_rules! make_mir_visitor {
|
||||||
operand: & $($mutability)* Operand<'tcx>,
|
operand: & $($mutability)* Operand<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
match *operand {
|
match *operand {
|
||||||
Operand::Copy(ref $($mutability)* lvalue) => {
|
Operand::Copy(ref $($mutability)* place) => {
|
||||||
self.visit_lvalue(lvalue, PlaceContext::Copy, location);
|
self.visit_place(place, PlaceContext::Copy, location);
|
||||||
}
|
}
|
||||||
Operand::Move(ref $($mutability)* lvalue) => {
|
Operand::Move(ref $($mutability)* place) => {
|
||||||
self.visit_lvalue(lvalue, PlaceContext::Move, location);
|
self.visit_place(place, PlaceContext::Move, location);
|
||||||
}
|
}
|
||||||
Operand::Constant(ref $($mutability)* constant) => {
|
Operand::Constant(ref $($mutability)* constant) => {
|
||||||
self.visit_constant(constant, location);
|
self.visit_constant(constant, location);
|
||||||
|
@ -623,11 +623,11 @@ macro_rules! make_mir_visitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn super_lvalue(&mut self,
|
fn super_place(&mut self,
|
||||||
lvalue: & $($mutability)* Place<'tcx>,
|
place: & $($mutability)* Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
match *lvalue {
|
match *place {
|
||||||
Place::Local(ref $($mutability)* local) => {
|
Place::Local(ref $($mutability)* local) => {
|
||||||
self.visit_local(local, context, location);
|
self.visit_local(local, context, location);
|
||||||
}
|
}
|
||||||
|
@ -665,7 +665,7 @@ macro_rules! make_mir_visitor {
|
||||||
} else {
|
} else {
|
||||||
PlaceContext::Projection(Mutability::Not)
|
PlaceContext::Projection(Mutability::Not)
|
||||||
};
|
};
|
||||||
self.visit_lvalue(base, context, location);
|
self.visit_place(base, context, location);
|
||||||
self.visit_projection_elem(elem, context, location);
|
self.visit_projection_elem(elem, context, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,10 +847,10 @@ pub enum PlaceContext<'tcx> {
|
||||||
// Being borrowed
|
// Being borrowed
|
||||||
Borrow { region: Region<'tcx>, kind: BorrowKind },
|
Borrow { region: Region<'tcx>, kind: BorrowKind },
|
||||||
|
|
||||||
// Used as base for another lvalue, e.g. `x` in `x.y`.
|
// Used as base for another place, e.g. `x` in `x.y`.
|
||||||
//
|
//
|
||||||
// The `Mutability` argument specifies whether the projection is being performed in order to
|
// The `Mutability` argument specifies whether the projection is being performed in order to
|
||||||
// (potentially) mutate the lvalue. For example, the projection `x.y` is marked as a mutation
|
// (potentially) mutate the place. For example, the projection `x.y` is marked as a mutation
|
||||||
// in these cases:
|
// in these cases:
|
||||||
//
|
//
|
||||||
// x.y = ...;
|
// x.y = ...;
|
||||||
|
@ -875,7 +875,7 @@ pub enum PlaceContext<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> PlaceContext<'tcx> {
|
impl<'tcx> PlaceContext<'tcx> {
|
||||||
/// Returns true if this lvalue context represents a drop.
|
/// Returns true if this place context represents a drop.
|
||||||
pub fn is_drop(&self) -> bool {
|
pub fn is_drop(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
PlaceContext::Drop => true,
|
PlaceContext::Drop => true,
|
||||||
|
@ -883,7 +883,7 @@ impl<'tcx> PlaceContext<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this lvalue context represents a storage live or storage dead marker.
|
/// Returns true if this place context represents a storage live or storage dead marker.
|
||||||
pub fn is_storage_marker(&self) -> bool {
|
pub fn is_storage_marker(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
PlaceContext::StorageLive | PlaceContext::StorageDead => true,
|
PlaceContext::StorageLive | PlaceContext::StorageDead => true,
|
||||||
|
@ -891,7 +891,7 @@ impl<'tcx> PlaceContext<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this lvalue context represents a storage live marker.
|
/// Returns true if this place context represents a storage live marker.
|
||||||
pub fn is_storage_live_marker(&self) -> bool {
|
pub fn is_storage_live_marker(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
PlaceContext::StorageLive => true,
|
PlaceContext::StorageLive => true,
|
||||||
|
@ -899,7 +899,7 @@ impl<'tcx> PlaceContext<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this lvalue context represents a storage dead marker.
|
/// Returns true if this place context represents a storage dead marker.
|
||||||
pub fn is_storage_dead_marker(&self) -> bool {
|
pub fn is_storage_dead_marker(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
PlaceContext::StorageDead => true,
|
PlaceContext::StorageDead => true,
|
||||||
|
@ -907,7 +907,7 @@ impl<'tcx> PlaceContext<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this lvalue context represents a use that potentially changes the value.
|
/// Returns true if this place context represents a use that potentially changes the value.
|
||||||
pub fn is_mutating_use(&self) -> bool {
|
pub fn is_mutating_use(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
PlaceContext::Store | PlaceContext::Call |
|
PlaceContext::Store | PlaceContext::Call |
|
||||||
|
@ -924,7 +924,7 @@ impl<'tcx> PlaceContext<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this lvalue context represents a use that does not change the value.
|
/// Returns true if this place context represents a use that does not change the value.
|
||||||
pub fn is_nonmutating_use(&self) -> bool {
|
pub fn is_nonmutating_use(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
PlaceContext::Inspect | PlaceContext::Borrow { kind: BorrowKind::Shared, .. } |
|
PlaceContext::Inspect | PlaceContext::Borrow { kind: BorrowKind::Shared, .. } |
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -61,11 +61,11 @@ impl<'tcx> CFG<'tcx> {
|
||||||
pub fn push_assign(&mut self,
|
pub fn push_assign(&mut self,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
rvalue: Rvalue<'tcx>) {
|
rvalue: Rvalue<'tcx>) {
|
||||||
self.push(block, Statement {
|
self.push(block, Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Assign(lvalue.clone(), rvalue)
|
kind: StatementKind::Assign(place.clone(), rvalue)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +81,8 @@ impl<'tcx> CFG<'tcx> {
|
||||||
pub fn push_assign_unit(&mut self,
|
pub fn push_assign_unit(&mut self,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
lvalue: &Place<'tcx>) {
|
place: &Place<'tcx>) {
|
||||||
self.push_assign(block, source_info, lvalue, Rvalue::Aggregate(
|
self.push_assign(block, source_info, place, Rvalue::Aggregate(
|
||||||
box AggregateKind::Tuple, vec![]
|
box AggregateKind::Tuple, vec![]
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile `expr` into a value that can be used as an operand.
|
/// Compile `expr` into a value that can be used as an operand.
|
||||||
/// If `expr` is an lvalue like `x`, this will introduce a
|
/// If `expr` is a place like `x`, this will introduce a
|
||||||
/// temporary `tmp = x`, so that we capture the value of `x` at
|
/// temporary `tmp = x`, so that we capture the value of `x` at
|
||||||
/// this time.
|
/// this time.
|
||||||
///
|
///
|
||||||
|
|
|
@ -18,22 +18,22 @@ use rustc::mir::*;
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
/// Compile `expr`, yielding an lvalue that we can move from etc.
|
/// Compile `expr`, yielding a place that we can move from etc.
|
||||||
pub fn as_lvalue<M>(&mut self,
|
pub fn as_place<M>(&mut self,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
expr: M)
|
expr: M)
|
||||||
-> BlockAnd<Place<'tcx>>
|
-> BlockAnd<Place<'tcx>>
|
||||||
where M: Mirror<'tcx, Output=Expr<'tcx>>
|
where M: Mirror<'tcx, Output=Expr<'tcx>>
|
||||||
{
|
{
|
||||||
let expr = self.hir.mirror(expr);
|
let expr = self.hir.mirror(expr);
|
||||||
self.expr_as_lvalue(block, expr)
|
self.expr_as_place(block, expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_as_lvalue(&mut self,
|
fn expr_as_place(&mut self,
|
||||||
mut block: BasicBlock,
|
mut block: BasicBlock,
|
||||||
expr: Expr<'tcx>)
|
expr: Expr<'tcx>)
|
||||||
-> BlockAnd<Place<'tcx>> {
|
-> BlockAnd<Place<'tcx>> {
|
||||||
debug!("expr_as_lvalue(block={:?}, expr={:?})", block, expr);
|
debug!("expr_as_place(block={:?}, expr={:?})", block, expr);
|
||||||
|
|
||||||
let this = self;
|
let this = self;
|
||||||
let expr_span = expr.span;
|
let expr_span = expr.span;
|
||||||
|
@ -41,24 +41,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Scope { region_scope, lint_level, value } => {
|
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||||
this.in_scope((region_scope, source_info), lint_level, block, |this| {
|
this.in_scope((region_scope, source_info), lint_level, block, |this| {
|
||||||
this.as_lvalue(block, value)
|
this.as_place(block, value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ExprKind::Field { lhs, name } => {
|
ExprKind::Field { lhs, name } => {
|
||||||
let lvalue = unpack!(block = this.as_lvalue(block, lhs));
|
let place = unpack!(block = this.as_place(block, lhs));
|
||||||
let lvalue = lvalue.field(name, expr.ty);
|
let place = place.field(name, expr.ty);
|
||||||
block.and(lvalue)
|
block.and(place)
|
||||||
}
|
}
|
||||||
ExprKind::Deref { arg } => {
|
ExprKind::Deref { arg } => {
|
||||||
let lvalue = unpack!(block = this.as_lvalue(block, arg));
|
let place = unpack!(block = this.as_place(block, arg));
|
||||||
let lvalue = lvalue.deref();
|
let place = place.deref();
|
||||||
block.and(lvalue)
|
block.and(place)
|
||||||
}
|
}
|
||||||
ExprKind::Index { lhs, index } => {
|
ExprKind::Index { lhs, index } => {
|
||||||
let (usize_ty, bool_ty) = (this.hir.usize_ty(), this.hir.bool_ty());
|
let (usize_ty, bool_ty) = (this.hir.usize_ty(), this.hir.bool_ty());
|
||||||
|
|
||||||
let slice = unpack!(block = this.as_lvalue(block, lhs));
|
let slice = unpack!(block = this.as_place(block, lhs));
|
||||||
// region_scope=None so lvalue indexes live forever. They are scalars so they
|
// region_scope=None so place indexes live forever. They are scalars so they
|
||||||
// do not need storage annotations, and they are often copied between
|
// do not need storage annotations, and they are often copied between
|
||||||
// places.
|
// places.
|
||||||
let idx = unpack!(block = this.as_temp(block, None, index));
|
let idx = unpack!(block = this.as_temp(block, None, index));
|
||||||
|
@ -122,7 +122,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
ExprKind::InlineAsm { .. } |
|
ExprKind::InlineAsm { .. } |
|
||||||
ExprKind::Yield { .. } |
|
ExprKind::Yield { .. } |
|
||||||
ExprKind::Call { .. } => {
|
ExprKind::Call { .. } => {
|
||||||
// these are not lvalues, so we need to make a temporary.
|
// these are not places, so we need to make a temporary.
|
||||||
debug_assert!(match Category::of(&expr.kind) {
|
debug_assert!(match Category::of(&expr.kind) {
|
||||||
Some(Category::Place) => false,
|
Some(Category::Place) => false,
|
||||||
_ => true,
|
_ => true,
|
|
@ -68,8 +68,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
block.and(Rvalue::Repeat(value_operand, count))
|
block.and(Rvalue::Repeat(value_operand, count))
|
||||||
}
|
}
|
||||||
ExprKind::Borrow { region, borrow_kind, arg } => {
|
ExprKind::Borrow { region, borrow_kind, arg } => {
|
||||||
let arg_lvalue = unpack!(block = this.as_lvalue(block, arg));
|
let arg_place = unpack!(block = this.as_place(block, arg));
|
||||||
block.and(Rvalue::Ref(region, borrow_kind, arg_lvalue))
|
block.and(Rvalue::Ref(region, borrow_kind, arg_place))
|
||||||
}
|
}
|
||||||
ExprKind::Binary { op, lhs, rhs } => {
|
ExprKind::Binary { op, lhs, rhs } => {
|
||||||
let lhs = unpack!(block = this.as_operand(block, scope, lhs));
|
let lhs = unpack!(block = this.as_operand(block, scope, lhs));
|
||||||
|
@ -229,7 +229,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
let field_names = this.hir.all_fields(adt_def, variant_index);
|
let field_names = this.hir.all_fields(adt_def, variant_index);
|
||||||
|
|
||||||
let fields = if let Some(FruInfo { base, field_types }) = base {
|
let fields = if let Some(FruInfo { base, field_types }) = base {
|
||||||
let base = unpack!(block = this.as_lvalue(block, base));
|
let base = unpack!(block = this.as_place(block, base));
|
||||||
|
|
||||||
// MIR does not natively support FRU, so for each
|
// MIR does not natively support FRU, so for each
|
||||||
// base-supplied field, generate an operand that
|
// base-supplied field, generate an operand that
|
||||||
|
|
|
@ -58,16 +58,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Careful here not to cause an infinite cycle. If we always
|
// Careful here not to cause an infinite cycle. If we always
|
||||||
// called `into`, then for lvalues like `x.f`, it would
|
// called `into`, then for places like `x.f`, it would
|
||||||
// eventually fallback to us, and we'd loop. There's a reason
|
// eventually fallback to us, and we'd loop. There's a reason
|
||||||
// for this: `as_temp` is the point where we bridge the "by
|
// for this: `as_temp` is the point where we bridge the "by
|
||||||
// reference" semantics of `as_lvalue` with the "by value"
|
// reference" semantics of `as_place` with the "by value"
|
||||||
// semantics of `into`, `as_operand`, `as_rvalue`, and (of
|
// semantics of `into`, `as_operand`, `as_rvalue`, and (of
|
||||||
// course) `as_temp`.
|
// course) `as_temp`.
|
||||||
match Category::of(&expr.kind).unwrap() {
|
match Category::of(&expr.kind).unwrap() {
|
||||||
Category::Place => {
|
Category::Place => {
|
||||||
let lvalue = unpack!(block = this.as_lvalue(block, expr));
|
let place = unpack!(block = this.as_place(block, expr));
|
||||||
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(lvalue));
|
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
|
||||||
this.cfg.push_assign(block, source_info, &Place::Local(temp), rvalue);
|
this.cfg.push_assign(block, source_info, &Place::Local(temp), rvalue);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -24,13 +24,13 @@
|
||||||
//! - `as_operand` -- evaluates the value and yields an `Operand`,
|
//! - `as_operand` -- evaluates the value and yields an `Operand`,
|
||||||
//! suitable for use as an argument to an `Rvalue`
|
//! suitable for use as an argument to an `Rvalue`
|
||||||
//! - `as_temp` -- evaluates into a temporary; this is similar to `as_operand`
|
//! - `as_temp` -- evaluates into a temporary; this is similar to `as_operand`
|
||||||
//! except it always returns a fresh lvalue, even for constants
|
//! except it always returns a fresh place, even for constants
|
||||||
//! - `as_rvalue` -- yields an `Rvalue`, suitable for use in an assignment;
|
//! - `as_rvalue` -- yields an `Rvalue`, suitable for use in an assignment;
|
||||||
//! as of this writing, never needed outside of the `expr` module itself
|
//! as of this writing, never needed outside of the `expr` module itself
|
||||||
//!
|
//!
|
||||||
//! Sometimes though want the expression's *location*. An example
|
//! Sometimes though want the expression's *location*. An example
|
||||||
//! would be during a match statement, or the operand of the `&`
|
//! would be during a match statement, or the operand of the `&`
|
||||||
//! operator. In that case, you want `as_lvalue`. This will create a
|
//! operator. In that case, you want `as_place`. This will create a
|
||||||
//! temporary if necessary.
|
//! temporary if necessary.
|
||||||
//!
|
//!
|
||||||
//! Finally, if it's a constant you seek, then call
|
//! Finally, if it's a constant you seek, then call
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
//! struct expression (or other expression that creates a new value)
|
//! struct expression (or other expression that creates a new value)
|
||||||
//! is typically easiest to write in terms of `as_rvalue` or `into`,
|
//! is typically easiest to write in terms of `as_rvalue` or `into`,
|
||||||
//! whereas a reference to a field is easiest to write in terms of
|
//! whereas a reference to a field is easiest to write in terms of
|
||||||
//! `as_lvalue`. (The exception to this is scope and paren
|
//! `as_place`. (The exception to this is scope and paren
|
||||||
//! expressions, which have no category.)
|
//! expressions, which have no category.)
|
||||||
//!
|
//!
|
||||||
//! Therefore, the various functions above make use of one another in
|
//! Therefore, the various functions above make use of one another in
|
||||||
|
@ -54,12 +54,12 @@
|
||||||
//! the most suitable spot to implement it, and then just let the
|
//! the most suitable spot to implement it, and then just let the
|
||||||
//! other fns cycle around. The handoff works like this:
|
//! other fns cycle around. The handoff works like this:
|
||||||
//!
|
//!
|
||||||
//! - `into(lv)` -> fallback is to create a rvalue with `as_rvalue` and assign it to `lv`
|
//! - `into(place)` -> fallback is to create a rvalue with `as_rvalue` and assign it to `place`
|
||||||
//! - `as_rvalue` -> fallback is to create an Operand with `as_operand` and use `Rvalue::use`
|
//! - `as_rvalue` -> fallback is to create an Operand with `as_operand` and use `Rvalue::use`
|
||||||
//! - `as_operand` -> either invokes `as_constant` or `as_temp`
|
//! - `as_operand` -> either invokes `as_constant` or `as_temp`
|
||||||
//! - `as_constant` -> (no fallback)
|
//! - `as_constant` -> (no fallback)
|
||||||
//! - `as_temp` -> creates a temporary and either calls `as_lvalue` or `into`
|
//! - `as_temp` -> creates a temporary and either calls `as_place` or `into`
|
||||||
//! - `as_lvalue` -> for rvalues, falls back to `as_temp` and returns that
|
//! - `as_place` -> for rvalues, falls back to `as_temp` and returns that
|
||||||
//!
|
//!
|
||||||
//! As you can see, there is a cycle where `into` can (in theory) fallback to `as_temp`
|
//! As you can see, there is a cycle where `into` can (in theory) fallback to `as_temp`
|
||||||
//! which can fallback to `into`. So if one of the `ExprKind` variants is not, in fact,
|
//! which can fallback to `into`. So if one of the `ExprKind` variants is not, in fact,
|
||||||
|
@ -68,10 +68,10 @@
|
||||||
//! Of those fallbacks, the most interesting one is `as_temp`, because
|
//! Of those fallbacks, the most interesting one is `as_temp`, because
|
||||||
//! it discriminates based on the category of the expression. This is
|
//! it discriminates based on the category of the expression. This is
|
||||||
//! basically the point where the "by value" operations are bridged
|
//! basically the point where the "by value" operations are bridged
|
||||||
//! over to the "by reference" mode (`as_lvalue`).
|
//! over to the "by reference" mode (`as_place`).
|
||||||
|
|
||||||
mod as_constant;
|
mod as_constant;
|
||||||
mod as_lvalue;
|
mod as_place;
|
||||||
mod as_rvalue;
|
mod as_rvalue;
|
||||||
mod as_operand;
|
mod as_operand;
|
||||||
mod as_temp;
|
mod as_temp;
|
||||||
|
|
|
@ -41,14 +41,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
// dropped.
|
// dropped.
|
||||||
if this.hir.needs_drop(lhs.ty) {
|
if this.hir.needs_drop(lhs.ty) {
|
||||||
let rhs = unpack!(block = this.as_local_operand(block, rhs));
|
let rhs = unpack!(block = this.as_local_operand(block, rhs));
|
||||||
let lhs = unpack!(block = this.as_lvalue(block, lhs));
|
let lhs = unpack!(block = this.as_place(block, lhs));
|
||||||
unpack!(block = this.build_drop_and_replace(
|
unpack!(block = this.build_drop_and_replace(
|
||||||
block, lhs_span, lhs, rhs
|
block, lhs_span, lhs, rhs
|
||||||
));
|
));
|
||||||
block.unit()
|
block.unit()
|
||||||
} else {
|
} else {
|
||||||
let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
|
let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
|
||||||
let lhs = unpack!(block = this.as_lvalue(block, lhs));
|
let lhs = unpack!(block = this.as_place(block, lhs));
|
||||||
this.cfg.push_assign(block, source_info, &lhs, rhs);
|
this.cfg.push_assign(block, source_info, &lhs, rhs);
|
||||||
block.unit()
|
block.unit()
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// As above, RTL.
|
// As above, RTL.
|
||||||
let rhs = unpack!(block = this.as_local_operand(block, rhs));
|
let rhs = unpack!(block = this.as_local_operand(block, rhs));
|
||||||
let lhs = unpack!(block = this.as_lvalue(block, lhs));
|
let lhs = unpack!(block = this.as_place(block, lhs));
|
||||||
|
|
||||||
// we don't have to drop prior contents or anything
|
// we don't have to drop prior contents or anything
|
||||||
// because AssignOp is only legal for Copy types
|
// because AssignOp is only legal for Copy types
|
||||||
|
@ -107,12 +107,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
ExprKind::Return { value } => {
|
ExprKind::Return { value } => {
|
||||||
block = match value {
|
block = match value {
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
unpack!(this.into(&Place::Local(RETURN_POINTER), block, value))
|
unpack!(this.into(&Place::Local(RETURN_PLACE), block, value))
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
this.cfg.push_assign_unit(block,
|
this.cfg.push_assign_unit(block,
|
||||||
source_info,
|
source_info,
|
||||||
&Place::Local(RETURN_POINTER));
|
&Place::Local(RETURN_PLACE));
|
||||||
block
|
block
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -123,7 +123,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
ExprKind::InlineAsm { asm, outputs, inputs } => {
|
ExprKind::InlineAsm { asm, outputs, inputs } => {
|
||||||
let outputs = outputs.into_iter().map(|output| {
|
let outputs = outputs.into_iter().map(|output| {
|
||||||
unpack!(block = this.as_lvalue(block, output))
|
unpack!(block = this.as_place(block, output))
|
||||||
}).collect();
|
}).collect();
|
||||||
let inputs = inputs.into_iter().map(|input| {
|
let inputs = inputs.into_iter().map(|input| {
|
||||||
unpack!(block = this.as_local_operand(block, input))
|
unpack!(block = this.as_local_operand(block, input))
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
discriminant: ExprRef<'tcx>,
|
discriminant: ExprRef<'tcx>,
|
||||||
arms: Vec<Arm<'tcx>>)
|
arms: Vec<Arm<'tcx>>)
|
||||||
-> BlockAnd<()> {
|
-> BlockAnd<()> {
|
||||||
let discriminant_lvalue = unpack!(block = self.as_lvalue(block, discriminant));
|
let discriminant_place = unpack!(block = self.as_place(block, discriminant));
|
||||||
|
|
||||||
let mut arm_blocks = ArmBlocks {
|
let mut arm_blocks = ArmBlocks {
|
||||||
blocks: arms.iter()
|
blocks: arms.iter()
|
||||||
|
@ -77,7 +77,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
(pre_binding_block, next_candidate_pre_binding_block))| {
|
(pre_binding_block, next_candidate_pre_binding_block))| {
|
||||||
Candidate {
|
Candidate {
|
||||||
span: pattern.span,
|
span: pattern.span,
|
||||||
match_pairs: vec![MatchPair::new(discriminant_lvalue.clone(), pattern)],
|
match_pairs: vec![MatchPair::new(discriminant_place.clone(), pattern)],
|
||||||
bindings: vec![],
|
bindings: vec![],
|
||||||
guard,
|
guard,
|
||||||
arm_index,
|
arm_index,
|
||||||
|
@ -91,7 +91,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
self.cfg.terminate(*pre_binding_blocks.last().unwrap(),
|
self.cfg.terminate(*pre_binding_blocks.last().unwrap(),
|
||||||
outer_source_info, TerminatorKind::Unreachable);
|
outer_source_info, TerminatorKind::Unreachable);
|
||||||
|
|
||||||
// this will generate code to test discriminant_lvalue and
|
// this will generate code to test discriminant_place and
|
||||||
// branch to the appropriate arm block
|
// branch to the appropriate arm block
|
||||||
let otherwise = self.match_candidates(span, &mut arm_blocks, candidates, block);
|
let otherwise = self.match_candidates(span, &mut arm_blocks, candidates, block);
|
||||||
|
|
||||||
|
@ -139,19 +139,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
PatternKind::Binding { mode: BindingMode::ByValue,
|
PatternKind::Binding { mode: BindingMode::ByValue,
|
||||||
var,
|
var,
|
||||||
subpattern: None, .. } => {
|
subpattern: None, .. } => {
|
||||||
let lvalue = self.storage_live_binding(block, var, irrefutable_pat.span);
|
let place = self.storage_live_binding(block, var, irrefutable_pat.span);
|
||||||
unpack!(block = self.into(&lvalue, block, initializer));
|
unpack!(block = self.into(&place, block, initializer));
|
||||||
self.schedule_drop_for_binding(var, irrefutable_pat.span);
|
self.schedule_drop_for_binding(var, irrefutable_pat.span);
|
||||||
block.unit()
|
block.unit()
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let lvalue = unpack!(block = self.as_lvalue(block, initializer));
|
let place = unpack!(block = self.as_place(block, initializer));
|
||||||
self.lvalue_into_pattern(block, irrefutable_pat, &lvalue)
|
self.place_into_pattern(block, irrefutable_pat, &place)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lvalue_into_pattern(&mut self,
|
pub fn place_into_pattern(&mut self,
|
||||||
mut block: BasicBlock,
|
mut block: BasicBlock,
|
||||||
irrefutable_pat: Pattern<'tcx>,
|
irrefutable_pat: Pattern<'tcx>,
|
||||||
initializer: &Place<'tcx>)
|
initializer: &Place<'tcx>)
|
||||||
|
@ -315,8 +315,8 @@ struct Binding<'tcx> {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MatchPair<'pat, 'tcx:'pat> {
|
pub struct MatchPair<'pat, 'tcx:'pat> {
|
||||||
// this lvalue...
|
// this place...
|
||||||
lvalue: Place<'tcx>,
|
place: Place<'tcx>,
|
||||||
|
|
||||||
// ... must match this pattern.
|
// ... must match this pattern.
|
||||||
pattern: &'pat Pattern<'tcx>,
|
pattern: &'pat Pattern<'tcx>,
|
||||||
|
@ -635,7 +635,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
match test.kind {
|
match test.kind {
|
||||||
TestKind::SwitchInt { switch_ty, ref mut options, ref mut indices } => {
|
TestKind::SwitchInt { switch_ty, ref mut options, ref mut indices } => {
|
||||||
for candidate in candidates.iter() {
|
for candidate in candidates.iter() {
|
||||||
if !self.add_cases_to_switch(&match_pair.lvalue,
|
if !self.add_cases_to_switch(&match_pair.place,
|
||||||
candidate,
|
candidate,
|
||||||
switch_ty,
|
switch_ty,
|
||||||
options,
|
options,
|
||||||
|
@ -646,7 +646,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
TestKind::Switch { adt_def: _, ref mut variants} => {
|
TestKind::Switch { adt_def: _, ref mut variants} => {
|
||||||
for candidate in candidates.iter() {
|
for candidate in candidates.iter() {
|
||||||
if !self.add_variants_to_switch(&match_pair.lvalue,
|
if !self.add_variants_to_switch(&match_pair.place,
|
||||||
candidate,
|
candidate,
|
||||||
variants) {
|
variants) {
|
||||||
break;
|
break;
|
||||||
|
@ -661,7 +661,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
// vector of candidates. Those are the candidates that still
|
// vector of candidates. Those are the candidates that still
|
||||||
// apply if the test has that particular outcome.
|
// apply if the test has that particular outcome.
|
||||||
debug!("match_candidates: test={:?} match_pair={:?}", test, match_pair);
|
debug!("match_candidates: test={:?} match_pair={:?}", test, match_pair);
|
||||||
let target_blocks = self.perform_test(block, &match_pair.lvalue, &test);
|
let target_blocks = self.perform_test(block, &match_pair.place, &test);
|
||||||
let mut target_candidates: Vec<_> = (0..target_blocks.len()).map(|_| vec![]).collect();
|
let mut target_candidates: Vec<_> = (0..target_blocks.len()).map(|_| vec![]).collect();
|
||||||
|
|
||||||
// Sort the candidates into the appropriate vector in
|
// Sort the candidates into the appropriate vector in
|
||||||
|
@ -670,7 +670,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
// that point, we stop sorting.
|
// that point, we stop sorting.
|
||||||
let tested_candidates =
|
let tested_candidates =
|
||||||
candidates.iter()
|
candidates.iter()
|
||||||
.take_while(|c| self.sort_candidate(&match_pair.lvalue,
|
.take_while(|c| self.sort_candidate(&match_pair.place,
|
||||||
&test,
|
&test,
|
||||||
c,
|
c,
|
||||||
&mut target_candidates))
|
&mut target_candidates))
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
|
|
||||||
//! Simplifying Candidates
|
//! Simplifying Candidates
|
||||||
//!
|
//!
|
||||||
//! *Simplifying* a match pair `lvalue @ pattern` means breaking it down
|
//! *Simplifying* a match pair `place @ pattern` means breaking it down
|
||||||
//! into bindings or other, simpler match pairs. For example:
|
//! into bindings or other, simpler match pairs. For example:
|
||||||
//!
|
//!
|
||||||
//! - `lvalue @ (P1, P2)` can be simplified to `[lvalue.0 @ P1, lvalue.1 @ P2]`
|
//! - `place @ (P1, P2)` can be simplified to `[place.0 @ P1, place.1 @ P2]`
|
||||||
//! - `lvalue @ x` can be simplified to `[]` by binding `x` to `lvalue`
|
//! - `place @ x` can be simplified to `[]` by binding `x` to `place`
|
||||||
//!
|
//!
|
||||||
//! The `simplify_candidate` routine just repeatedly applies these
|
//! The `simplify_candidate` routine just repeatedly applies these
|
||||||
//! sort of simplifications until there is nothing left to
|
//! sort of simplifications until there is nothing left to
|
||||||
|
@ -73,7 +73,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
name,
|
name,
|
||||||
mutability,
|
mutability,
|
||||||
span: match_pair.pattern.span,
|
span: match_pair.pattern.span,
|
||||||
source: match_pair.lvalue.clone(),
|
source: match_pair.place.clone(),
|
||||||
var_id: var,
|
var_id: var,
|
||||||
var_ty: ty,
|
var_ty: ty,
|
||||||
binding_mode: mode,
|
binding_mode: mode,
|
||||||
|
@ -81,7 +81,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
if let Some(subpattern) = subpattern.as_ref() {
|
if let Some(subpattern) = subpattern.as_ref() {
|
||||||
// this is the `x @ P` case; have to keep matching against `P` now
|
// this is the `x @ P` case; have to keep matching against `P` now
|
||||||
candidate.match_pairs.push(MatchPair::new(match_pair.lvalue, subpattern));
|
candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -105,8 +105,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if irrefutable {
|
if irrefutable {
|
||||||
let lvalue = match_pair.lvalue.downcast(adt_def, variant_index);
|
let place = match_pair.place.downcast(adt_def, variant_index);
|
||||||
candidate.match_pairs.extend(self.field_match_pairs(lvalue, subpatterns));
|
candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns));
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(match_pair)
|
Err(match_pair)
|
||||||
|
@ -115,7 +115,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
|
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
|
||||||
self.prefix_slice_suffix(&mut candidate.match_pairs,
|
self.prefix_slice_suffix(&mut candidate.match_pairs,
|
||||||
&match_pair.lvalue,
|
&match_pair.place,
|
||||||
prefix,
|
prefix,
|
||||||
slice.as_ref(),
|
slice.as_ref(),
|
||||||
suffix);
|
suffix);
|
||||||
|
@ -125,13 +125,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
PatternKind::Leaf { ref subpatterns } => {
|
PatternKind::Leaf { ref subpatterns } => {
|
||||||
// tuple struct, match subpats (if any)
|
// tuple struct, match subpats (if any)
|
||||||
candidate.match_pairs
|
candidate.match_pairs
|
||||||
.extend(self.field_match_pairs(match_pair.lvalue, subpatterns));
|
.extend(self.field_match_pairs(match_pair.place, subpatterns));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
PatternKind::Deref { ref subpattern } => {
|
PatternKind::Deref { ref subpattern } => {
|
||||||
let lvalue = match_pair.lvalue.deref();
|
let place = match_pair.place.deref();
|
||||||
candidate.match_pairs.push(MatchPair::new(lvalue, subpattern));
|
candidate.match_pairs.push(MatchPair::new(place, subpattern));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,21 +109,21 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_cases_to_switch<'pat>(&mut self,
|
pub fn add_cases_to_switch<'pat>(&mut self,
|
||||||
test_lvalue: &Place<'tcx>,
|
test_place: &Place<'tcx>,
|
||||||
candidate: &Candidate<'pat, 'tcx>,
|
candidate: &Candidate<'pat, 'tcx>,
|
||||||
switch_ty: Ty<'tcx>,
|
switch_ty: Ty<'tcx>,
|
||||||
options: &mut Vec<&'tcx ty::Const<'tcx>>,
|
options: &mut Vec<&'tcx ty::Const<'tcx>>,
|
||||||
indices: &mut FxHashMap<&'tcx ty::Const<'tcx>, usize>)
|
indices: &mut FxHashMap<&'tcx ty::Const<'tcx>, usize>)
|
||||||
-> bool
|
-> bool
|
||||||
{
|
{
|
||||||
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.lvalue == *test_lvalue) {
|
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
|
||||||
Some(match_pair) => match_pair,
|
Some(match_pair) => match_pair,
|
||||||
_ => { return false; }
|
_ => { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
match *match_pair.pattern.kind {
|
match *match_pair.pattern.kind {
|
||||||
PatternKind::Constant { value } => {
|
PatternKind::Constant { value } => {
|
||||||
// if the lvalues match, the type should match
|
// if the places match, the type should match
|
||||||
assert_eq!(match_pair.pattern.ty, switch_ty);
|
assert_eq!(match_pair.pattern.ty, switch_ty);
|
||||||
|
|
||||||
indices.entry(value)
|
indices.entry(value)
|
||||||
|
@ -150,12 +150,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_variants_to_switch<'pat>(&mut self,
|
pub fn add_variants_to_switch<'pat>(&mut self,
|
||||||
test_lvalue: &Place<'tcx>,
|
test_place: &Place<'tcx>,
|
||||||
candidate: &Candidate<'pat, 'tcx>,
|
candidate: &Candidate<'pat, 'tcx>,
|
||||||
variants: &mut BitVector)
|
variants: &mut BitVector)
|
||||||
-> bool
|
-> bool
|
||||||
{
|
{
|
||||||
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.lvalue == *test_lvalue) {
|
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
|
||||||
Some(match_pair) => match_pair,
|
Some(match_pair) => match_pair,
|
||||||
_ => { return false; }
|
_ => { return false; }
|
||||||
};
|
};
|
||||||
|
@ -177,7 +177,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
/// Generates the code to perform a test.
|
/// Generates the code to perform a test.
|
||||||
pub fn perform_test(&mut self,
|
pub fn perform_test(&mut self,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
test: &Test<'tcx>)
|
test: &Test<'tcx>)
|
||||||
-> Vec<BasicBlock> {
|
-> Vec<BasicBlock> {
|
||||||
let source_info = self.source_info(test.span);
|
let source_info = self.source_info(test.span);
|
||||||
|
@ -212,7 +212,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
let discr_ty = adt_def.repr.discr_type().to_ty(tcx);
|
let discr_ty = adt_def.repr.discr_type().to_ty(tcx);
|
||||||
let discr = self.temp(discr_ty, test.span);
|
let discr = self.temp(discr_ty, test.span);
|
||||||
self.cfg.push_assign(block, source_info, &discr,
|
self.cfg.push_assign(block, source_info, &discr,
|
||||||
Rvalue::Discriminant(lvalue.clone()));
|
Rvalue::Discriminant(place.clone()));
|
||||||
assert_eq!(values.len() + 1, targets.len());
|
assert_eq!(values.len() + 1, targets.len());
|
||||||
self.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
|
self.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
|
||||||
discr: Operand::Move(discr),
|
discr: Operand::Move(discr),
|
||||||
|
@ -233,7 +233,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
ConstVal::Bool(false) => vec![false_bb, true_bb],
|
ConstVal::Bool(false) => vec![false_bb, true_bb],
|
||||||
v => span_bug!(test.span, "expected boolean value but got {:?}", v)
|
v => span_bug!(test.span, "expected boolean value but got {:?}", v)
|
||||||
};
|
};
|
||||||
(ret, TerminatorKind::if_(self.hir.tcx(), Operand::Copy(lvalue.clone()),
|
(ret, TerminatorKind::if_(self.hir.tcx(), Operand::Copy(place.clone()),
|
||||||
true_bb, false_bb))
|
true_bb, false_bb))
|
||||||
} else {
|
} else {
|
||||||
// The switch may be inexhaustive so we
|
// The switch may be inexhaustive so we
|
||||||
|
@ -248,7 +248,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
v.val.to_const_int().expect("switching on integral")
|
v.val.to_const_int().expect("switching on integral")
|
||||||
).collect();
|
).collect();
|
||||||
(targets.clone(), TerminatorKind::SwitchInt {
|
(targets.clone(), TerminatorKind::SwitchInt {
|
||||||
discr: Operand::Copy(lvalue.clone()),
|
discr: Operand::Copy(place.clone()),
|
||||||
switch_ty,
|
switch_ty,
|
||||||
values: From::from(values),
|
values: From::from(values),
|
||||||
targets,
|
targets,
|
||||||
|
@ -259,14 +259,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
TestKind::Eq { value, mut ty } => {
|
TestKind::Eq { value, mut ty } => {
|
||||||
let mut val = Operand::Copy(lvalue.clone());
|
let mut val = Operand::Copy(place.clone());
|
||||||
|
|
||||||
// If we're using b"..." as a pattern, we need to insert an
|
// If we're using b"..." as a pattern, we need to insert an
|
||||||
// unsizing coercion, as the byte string has the type &[u8; N].
|
// unsizing coercion, as the byte string has the type &[u8; N].
|
||||||
let expect = if let ConstVal::ByteStr(bytes) = value.val {
|
let expect = if let ConstVal::ByteStr(bytes) = value.val {
|
||||||
let tcx = self.hir.tcx();
|
let tcx = self.hir.tcx();
|
||||||
|
|
||||||
// Unsize the lvalue to &[u8], too, if necessary.
|
// Unsize the place to &[u8], too, if necessary.
|
||||||
if let ty::TyRef(region, mt) = ty.sty {
|
if let ty::TyRef(region, mt) = ty.sty {
|
||||||
if let ty::TyArray(_, _) = mt.ty.sty {
|
if let ty::TyArray(_, _) = mt.ty.sty {
|
||||||
ty = tcx.mk_imm_ref(region, tcx.mk_slice(tcx.types.u8));
|
ty = tcx.mk_imm_ref(region, tcx.mk_slice(tcx.types.u8));
|
||||||
|
@ -335,7 +335,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
// Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
|
// Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
|
||||||
let lo = self.literal_operand(test.span, ty.clone(), lo.clone());
|
let lo = self.literal_operand(test.span, ty.clone(), lo.clone());
|
||||||
let hi = self.literal_operand(test.span, ty.clone(), hi.clone());
|
let hi = self.literal_operand(test.span, ty.clone(), hi.clone());
|
||||||
let val = Operand::Copy(lvalue.clone());
|
let val = Operand::Copy(place.clone());
|
||||||
|
|
||||||
let fail = self.cfg.start_new_block();
|
let fail = self.cfg.start_new_block();
|
||||||
let block = self.compare(block, fail, test.span, BinOp::Le, lo, val.clone());
|
let block = self.compare(block, fail, test.span, BinOp::Le, lo, val.clone());
|
||||||
|
@ -352,9 +352,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
let (actual, result) = (self.temp(usize_ty, test.span),
|
let (actual, result) = (self.temp(usize_ty, test.span),
|
||||||
self.temp(bool_ty, test.span));
|
self.temp(bool_ty, test.span));
|
||||||
|
|
||||||
// actual = len(lvalue)
|
// actual = len(place)
|
||||||
self.cfg.push_assign(block, source_info,
|
self.cfg.push_assign(block, source_info,
|
||||||
&actual, Rvalue::Len(lvalue.clone()));
|
&actual, Rvalue::Len(place.clone()));
|
||||||
|
|
||||||
// expected = <N>
|
// expected = <N>
|
||||||
let expected = self.push_usize(block, source_info, len);
|
let expected = self.push_usize(block, source_info, len);
|
||||||
|
@ -399,7 +399,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
target_block
|
target_block
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given that we are performing `test` against `test_lvalue`,
|
/// Given that we are performing `test` against `test_place`,
|
||||||
/// this job sorts out what the status of `candidate` will be
|
/// this job sorts out what the status of `candidate` will be
|
||||||
/// after the test. The `resulting_candidates` vector stores, for
|
/// after the test. The `resulting_candidates` vector stores, for
|
||||||
/// each possible outcome of `test`, a vector of the candidates
|
/// each possible outcome of `test`, a vector of the candidates
|
||||||
|
@ -430,12 +430,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
/// not apply to this candidate, but it might be we can get
|
/// not apply to this candidate, but it might be we can get
|
||||||
/// tighter match code if we do something a bit different.
|
/// tighter match code if we do something a bit different.
|
||||||
pub fn sort_candidate<'pat>(&mut self,
|
pub fn sort_candidate<'pat>(&mut self,
|
||||||
test_lvalue: &Place<'tcx>,
|
test_place: &Place<'tcx>,
|
||||||
test: &Test<'tcx>,
|
test: &Test<'tcx>,
|
||||||
candidate: &Candidate<'pat, 'tcx>,
|
candidate: &Candidate<'pat, 'tcx>,
|
||||||
resulting_candidates: &mut [Vec<Candidate<'pat, 'tcx>>])
|
resulting_candidates: &mut [Vec<Candidate<'pat, 'tcx>>])
|
||||||
-> bool {
|
-> bool {
|
||||||
// Find the match_pair for this lvalue (if any). At present,
|
// Find the match_pair for this place (if any). At present,
|
||||||
// afaik, there can be at most one. (In the future, if we
|
// afaik, there can be at most one. (In the future, if we
|
||||||
// adopted a more general `@` operator, there might be more
|
// adopted a more general `@` operator, there might be more
|
||||||
// than one, but it'd be very unusual to have two sides that
|
// than one, but it'd be very unusual to have two sides that
|
||||||
|
@ -443,12 +443,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
// away.)
|
// away.)
|
||||||
let tested_match_pair = candidate.match_pairs.iter()
|
let tested_match_pair = candidate.match_pairs.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|&(_, mp)| mp.lvalue == *test_lvalue)
|
.filter(|&(_, mp)| mp.place == *test_place)
|
||||||
.next();
|
.next();
|
||||||
let (match_pair_index, match_pair) = match tested_match_pair {
|
let (match_pair_index, match_pair) = match tested_match_pair {
|
||||||
Some(pair) => pair,
|
Some(pair) => pair,
|
||||||
None => {
|
None => {
|
||||||
// We are not testing this lvalue. Therefore, this
|
// We are not testing this place. Therefore, this
|
||||||
// candidate applies to ALL outcomes.
|
// candidate applies to ALL outcomes.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -614,7 +614,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
self.candidate_without_match_pair(match_pair_index, candidate);
|
self.candidate_without_match_pair(match_pair_index, candidate);
|
||||||
self.prefix_slice_suffix(
|
self.prefix_slice_suffix(
|
||||||
&mut new_candidate.match_pairs,
|
&mut new_candidate.match_pairs,
|
||||||
&candidate.match_pairs[match_pair_index].lvalue,
|
&candidate.match_pairs[match_pair_index].place,
|
||||||
prefix,
|
prefix,
|
||||||
opt_slice,
|
opt_slice,
|
||||||
suffix);
|
suffix);
|
||||||
|
@ -635,15 +635,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
// we want to create a set of derived match-patterns like
|
// we want to create a set of derived match-patterns like
|
||||||
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
|
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
|
||||||
let elem = ProjectionElem::Downcast(adt_def, variant_index);
|
let elem = ProjectionElem::Downcast(adt_def, variant_index);
|
||||||
let downcast_lvalue = match_pair.lvalue.clone().elem(elem); // `(x as Variant)`
|
let downcast_place = match_pair.place.clone().elem(elem); // `(x as Variant)`
|
||||||
let consequent_match_pairs =
|
let consequent_match_pairs =
|
||||||
subpatterns.iter()
|
subpatterns.iter()
|
||||||
.map(|subpattern| {
|
.map(|subpattern| {
|
||||||
// e.g., `(x as Variant).0`
|
// e.g., `(x as Variant).0`
|
||||||
let lvalue = downcast_lvalue.clone().field(subpattern.field,
|
let place = downcast_place.clone().field(subpattern.field,
|
||||||
subpattern.pattern.ty);
|
subpattern.pattern.ty);
|
||||||
// e.g., `(x as Variant).0 @ P1`
|
// e.g., `(x as Variant).0 @ P1`
|
||||||
MatchPair::new(lvalue, &subpattern.pattern)
|
MatchPair::new(place, &subpattern.pattern)
|
||||||
});
|
});
|
||||||
|
|
||||||
// In addition, we need all the other match pairs from the old candidate.
|
// In addition, we need all the other match pairs from the old candidate.
|
||||||
|
|
|
@ -16,21 +16,21 @@ use std::u32;
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
pub fn field_match_pairs<'pat>(&mut self,
|
pub fn field_match_pairs<'pat>(&mut self,
|
||||||
lvalue: Place<'tcx>,
|
place: Place<'tcx>,
|
||||||
subpatterns: &'pat [FieldPattern<'tcx>])
|
subpatterns: &'pat [FieldPattern<'tcx>])
|
||||||
-> Vec<MatchPair<'pat, 'tcx>> {
|
-> Vec<MatchPair<'pat, 'tcx>> {
|
||||||
subpatterns.iter()
|
subpatterns.iter()
|
||||||
.map(|fieldpat| {
|
.map(|fieldpat| {
|
||||||
let lvalue = lvalue.clone().field(fieldpat.field,
|
let place = place.clone().field(fieldpat.field,
|
||||||
fieldpat.pattern.ty);
|
fieldpat.pattern.ty);
|
||||||
MatchPair::new(lvalue, &fieldpat.pattern)
|
MatchPair::new(place, &fieldpat.pattern)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prefix_slice_suffix<'pat>(&mut self,
|
pub fn prefix_slice_suffix<'pat>(&mut self,
|
||||||
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
|
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
prefix: &'pat [Pattern<'tcx>],
|
prefix: &'pat [Pattern<'tcx>],
|
||||||
opt_slice: Option<&'pat Pattern<'tcx>>,
|
opt_slice: Option<&'pat Pattern<'tcx>>,
|
||||||
suffix: &'pat [Pattern<'tcx>]) {
|
suffix: &'pat [Pattern<'tcx>]) {
|
||||||
|
@ -47,13 +47,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
min_length,
|
min_length,
|
||||||
from_end: false,
|
from_end: false,
|
||||||
};
|
};
|
||||||
let lvalue = lvalue.clone().elem(elem);
|
let place = place.clone().elem(elem);
|
||||||
MatchPair::new(lvalue, subpattern)
|
MatchPair::new(place, subpattern)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(subslice_pat) = opt_slice {
|
if let Some(subslice_pat) = opt_slice {
|
||||||
let subslice = lvalue.clone().elem(ProjectionElem::Subslice {
|
let subslice = place.clone().elem(ProjectionElem::Subslice {
|
||||||
from: prefix.len() as u32,
|
from: prefix.len() as u32,
|
||||||
to: suffix.len() as u32
|
to: suffix.len() as u32
|
||||||
});
|
});
|
||||||
|
@ -70,17 +70,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
min_length,
|
min_length,
|
||||||
from_end: true,
|
from_end: true,
|
||||||
};
|
};
|
||||||
let lvalue = lvalue.clone().elem(elem);
|
let place = place.clone().elem(elem);
|
||||||
MatchPair::new(lvalue, subpattern)
|
MatchPair::new(place, subpattern)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||||
pub fn new(lvalue: Place<'tcx>, pattern: &'pat Pattern<'tcx>) -> MatchPair<'pat, 'tcx> {
|
pub fn new(place: Place<'tcx>, pattern: &'pat Pattern<'tcx>) -> MatchPair<'pat, 'tcx> {
|
||||||
MatchPair {
|
MatchPair {
|
||||||
lvalue,
|
place,
|
||||||
pattern,
|
pattern,
|
||||||
slice_len_checked: false,
|
slice_len_checked: false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
/// call `schedule_drop` once the temporary is initialized.
|
/// call `schedule_drop` once the temporary is initialized.
|
||||||
pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'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 temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
|
||||||
let lvalue = Place::Local(temp);
|
let place = Place::Local(temp);
|
||||||
debug!("temp: created temp {:?} with type {:?}",
|
debug!("temp: created temp {:?} with type {:?}",
|
||||||
lvalue, self.local_decls[temp].ty);
|
place, self.local_decls[temp].ty);
|
||||||
lvalue
|
place
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn literal_operand(&mut self,
|
pub fn literal_operand(&mut self,
|
||||||
|
@ -134,13 +134,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
temp
|
temp
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn consume_by_copy_or_move(&self, lvalue: Place<'tcx>) -> Operand<'tcx> {
|
pub fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
|
||||||
let tcx = self.hir.tcx();
|
let tcx = self.hir.tcx();
|
||||||
let ty = lvalue.ty(&self.local_decls, tcx).to_ty(tcx);
|
let ty = place.ty(&self.local_decls, tcx).to_ty(tcx);
|
||||||
if self.hir.type_moves_by_default(ty, DUMMY_SP) {
|
if self.hir.type_moves_by_default(ty, DUMMY_SP) {
|
||||||
Operand::Move(lvalue)
|
Operand::Move(place)
|
||||||
} else {
|
} else {
|
||||||
Operand::Copy(lvalue)
|
Operand::Copy(place)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -480,7 +480,7 @@ fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||||
|
|
||||||
let mut block = START_BLOCK;
|
let mut block = START_BLOCK;
|
||||||
let expr = builder.hir.mirror(ast_expr);
|
let expr = builder.hir.mirror(ast_expr);
|
||||||
unpack!(block = builder.into_expr(&Place::Local(RETURN_POINTER), block, expr));
|
unpack!(block = builder.into_expr(&Place::Local(RETURN_PLACE), block, expr));
|
||||||
|
|
||||||
let source_info = builder.source_info(span);
|
let source_info = builder.source_info(span);
|
||||||
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
|
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
|
||||||
|
@ -523,7 +523,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
push_unsafe_count: 0,
|
push_unsafe_count: 0,
|
||||||
unpushed_unsafe: safety,
|
unpushed_unsafe: safety,
|
||||||
breakable_scopes: vec![],
|
breakable_scopes: vec![],
|
||||||
local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty,
|
local_decls: IndexVec::from_elem_n(LocalDecl::new_return_place(return_ty,
|
||||||
span), 1),
|
span), 1),
|
||||||
var_indices: NodeMap(),
|
var_indices: NodeMap(),
|
||||||
unit_temp: None,
|
unit_temp: None,
|
||||||
|
@ -597,9 +597,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
let mut scope = None;
|
let mut scope = None;
|
||||||
// Bind the argument patterns
|
// Bind the argument patterns
|
||||||
for (index, &(ty, pattern)) in arguments.iter().enumerate() {
|
for (index, &(ty, pattern)) in arguments.iter().enumerate() {
|
||||||
// Function arguments always get the first Local indices after the return pointer
|
// Function arguments always get the first Local indices after the return place
|
||||||
let local = Local::new(index + 1);
|
let local = Local::new(index + 1);
|
||||||
let lvalue = Place::Local(local);
|
let place = Place::Local(local);
|
||||||
|
|
||||||
if let Some(pattern) = pattern {
|
if let Some(pattern) = pattern {
|
||||||
let pattern = self.hir.pattern_from_hir(pattern);
|
let pattern = self.hir.pattern_from_hir(pattern);
|
||||||
|
@ -613,14 +613,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
_ => {
|
_ => {
|
||||||
scope = self.declare_bindings(scope, ast_body.span,
|
scope = self.declare_bindings(scope, ast_body.span,
|
||||||
LintLevel::Inherited, &pattern);
|
LintLevel::Inherited, &pattern);
|
||||||
unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
|
unpack!(block = self.place_into_pattern(block, pattern, &place));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we drop (parts of) the argument even when not matched on.
|
// Make sure we drop (parts of) the argument even when not matched on.
|
||||||
self.schedule_drop(pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
|
self.schedule_drop(pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
|
||||||
argument_scope, &lvalue, ty);
|
argument_scope, &place, ty);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,7 +630,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = self.hir.mirror(ast_body);
|
let body = self.hir.mirror(ast_body);
|
||||||
self.into(&Place::Local(RETURN_POINTER), block, body)
|
self.into(&Place::Local(RETURN_PLACE), block, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_unit_temp(&mut self) -> Place<'tcx> {
|
fn get_unit_temp(&mut self) -> Place<'tcx> {
|
||||||
|
|
|
@ -39,10 +39,10 @@ mapping is from one scope to a vector of SEME regions.
|
||||||
### Drops
|
### Drops
|
||||||
|
|
||||||
The primary purpose for scopes is to insert drops: while translating
|
The primary purpose for scopes is to insert drops: while translating
|
||||||
the contents, we also accumulate lvalues that need to be dropped upon
|
the contents, we also accumulate places that need to be dropped upon
|
||||||
exit from each scope. This is done by calling `schedule_drop`. Once a
|
exit from each scope. This is done by calling `schedule_drop`. Once a
|
||||||
drop is scheduled, whenever we branch out we will insert drops of all
|
drop is scheduled, whenever we branch out we will insert drops of all
|
||||||
those lvalues onto the outgoing edge. Note that we don't know the full
|
those places onto the outgoing edge. Note that we don't know the full
|
||||||
set of scheduled drops up front, and so whenever we exit from the
|
set of scheduled drops up front, and so whenever we exit from the
|
||||||
scope we only drop the values scheduled thus far. For example, consider
|
scope we only drop the values scheduled thus far. For example, consider
|
||||||
the scope S corresponding to this loop:
|
the scope S corresponding to this loop:
|
||||||
|
@ -120,7 +120,7 @@ pub struct Scope<'tcx> {
|
||||||
/// * freeing up stack space has no effect during unwinding
|
/// * freeing up stack space has no effect during unwinding
|
||||||
needs_cleanup: bool,
|
needs_cleanup: bool,
|
||||||
|
|
||||||
/// set of lvalues to drop when exiting this scope. This starts
|
/// set of places to drop when exiting this scope. This starts
|
||||||
/// out empty but grows as variables are declared during the
|
/// out empty but grows as variables are declared during the
|
||||||
/// building process. This is a stack, so we always drop from the
|
/// building process. This is a stack, so we always drop from the
|
||||||
/// end of the vector (top of the stack) first.
|
/// end of the vector (top of the stack) first.
|
||||||
|
@ -138,10 +138,10 @@ pub struct Scope<'tcx> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct DropData<'tcx> {
|
struct DropData<'tcx> {
|
||||||
/// span where drop obligation was incurred (typically where lvalue was declared)
|
/// span where drop obligation was incurred (typically where place was declared)
|
||||||
span: Span,
|
span: Span,
|
||||||
|
|
||||||
/// lvalue to drop
|
/// place to drop
|
||||||
location: Place<'tcx>,
|
location: Place<'tcx>,
|
||||||
|
|
||||||
/// Whether this is a full value Drop, or just a StorageDead.
|
/// Whether this is a full value Drop, or just a StorageDead.
|
||||||
|
@ -608,19 +608,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// Scheduling drops
|
// Scheduling drops
|
||||||
// ================
|
// ================
|
||||||
/// Indicates that `lvalue` should be dropped on exit from
|
/// Indicates that `place` should be dropped on exit from
|
||||||
/// `region_scope`.
|
/// `region_scope`.
|
||||||
pub fn schedule_drop(&mut self,
|
pub fn schedule_drop(&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
region_scope: region::Scope,
|
region_scope: region::Scope,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
lvalue_ty: Ty<'tcx>) {
|
place_ty: Ty<'tcx>) {
|
||||||
let needs_drop = self.hir.needs_drop(lvalue_ty);
|
let needs_drop = self.hir.needs_drop(place_ty);
|
||||||
let drop_kind = if needs_drop {
|
let drop_kind = if needs_drop {
|
||||||
DropKind::Value { cached_block: CachedBlock::default() }
|
DropKind::Value { cached_block: CachedBlock::default() }
|
||||||
} else {
|
} else {
|
||||||
// Only temps and vars need their storage dead.
|
// Only temps and vars need their storage dead.
|
||||||
match *lvalue {
|
match *place {
|
||||||
Place::Local(index) if index.index() > self.arg_count => DropKind::Storage,
|
Place::Local(index) if index.index() > self.arg_count => DropKind::Storage,
|
||||||
_ => return
|
_ => return
|
||||||
}
|
}
|
||||||
|
@ -685,13 +685,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
let scope_end = region_scope_span.with_lo(region_scope_span.hi());
|
let scope_end = region_scope_span.with_lo(region_scope_span.hi());
|
||||||
scope.drops.push(DropData {
|
scope.drops.push(DropData {
|
||||||
span: scope_end,
|
span: scope_end,
|
||||||
location: lvalue.clone(),
|
location: place.clone(),
|
||||||
kind: drop_kind
|
kind: drop_kind
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
span_bug!(span, "region scope {:?} not in scope to drop {:?}", region_scope, lvalue);
|
span_bug!(span, "region scope {:?} not in scope to drop {:?}", region_scope, place);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
|
||||||
{
|
{
|
||||||
let mut next_child = move_data.move_paths[path].first_child;
|
let mut next_child = move_data.move_paths[path].first_child;
|
||||||
while let Some(child_index) = next_child {
|
while let Some(child_index) = next_child {
|
||||||
match move_data.move_paths[child_index].lvalue {
|
match move_data.move_paths[child_index].place {
|
||||||
mir::Place::Projection(ref proj) => {
|
mir::Place::Projection(ref proj) => {
|
||||||
if cond(proj) {
|
if cond(proj) {
|
||||||
return Some(child_index)
|
return Some(child_index)
|
||||||
|
@ -56,19 +56,19 @@ pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
|
||||||
/// is no need to maintain separate drop flags to track such state.
|
/// is no need to maintain separate drop flags to track such state.
|
||||||
///
|
///
|
||||||
/// FIXME: we have to do something for moving slice patterns.
|
/// 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>,
|
fn place_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
lv: &mir::Place<'tcx>) -> bool {
|
place: &mir::Place<'tcx>) -> bool {
|
||||||
let ty = lv.ty(mir, tcx).to_ty(tcx);
|
let ty = place.ty(mir, tcx).to_ty(tcx);
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyArray(..) | ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
|
ty::TyArray(..) | ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
|
||||||
debug!("lvalue_contents_drop_state_cannot_differ lv: {:?} ty: {:?} refd => true",
|
debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
|
||||||
lv, ty);
|
place, ty);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
ty::TyAdt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
|
ty::TyAdt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
|
||||||
debug!("lvalue_contents_drop_state_cannot_differ lv: {:?} ty: {:?} Drop => true",
|
debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true",
|
||||||
lv, ty);
|
place, ty);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -109,8 +109,8 @@ pub(crate) fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
|
||||||
move_data: &MoveData<'tcx>,
|
move_data: &MoveData<'tcx>,
|
||||||
path: MovePathIndex) -> bool
|
path: MovePathIndex) -> bool
|
||||||
{
|
{
|
||||||
lvalue_contents_drop_state_cannot_differ(
|
place_contents_drop_state_cannot_differ(
|
||||||
tcx, mir, &move_data.move_paths[path].lvalue)
|
tcx, mir, &move_data.move_paths[path].place)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
|
fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
|
||||||
|
@ -145,9 +145,9 @@ pub(crate) fn on_all_drop_children_bits<'a, 'gcx, 'tcx, F>(
|
||||||
where F: FnMut(MovePathIndex)
|
where F: FnMut(MovePathIndex)
|
||||||
{
|
{
|
||||||
on_all_children_bits(tcx, mir, &ctxt.move_data, path, |child| {
|
on_all_children_bits(tcx, mir, &ctxt.move_data, path, |child| {
|
||||||
let lvalue = &ctxt.move_data.move_paths[path].lvalue;
|
let place = &ctxt.move_data.move_paths[path].place;
|
||||||
let ty = lvalue.ty(mir, tcx).to_ty(tcx);
|
let ty = place.ty(mir, tcx).to_ty(tcx);
|
||||||
debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, lvalue, ty);
|
debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, place, ty);
|
||||||
|
|
||||||
let gcx = tcx.global_tcx();
|
let gcx = tcx.global_tcx();
|
||||||
let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap();
|
let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap();
|
||||||
|
@ -168,8 +168,8 @@ pub(crate) fn drop_flag_effects_for_function_entry<'a, 'gcx, 'tcx, F>(
|
||||||
{
|
{
|
||||||
let move_data = &ctxt.move_data;
|
let move_data = &ctxt.move_data;
|
||||||
for arg in mir.args_iter() {
|
for arg in mir.args_iter() {
|
||||||
let lvalue = mir::Place::Local(arg);
|
let place = mir::Place::Local(arg);
|
||||||
let lookup_result = move_data.rev_lookup.find(&lvalue);
|
let lookup_result = move_data.rev_lookup.find(&place);
|
||||||
on_lookup_result_bits(tcx, mir, move_data,
|
on_lookup_result_bits(tcx, mir, move_data,
|
||||||
lookup_result,
|
lookup_result,
|
||||||
|mpi| callback(mpi, DropFlagState::Present));
|
|mpi| callback(mpi, DropFlagState::Present));
|
||||||
|
|
|
@ -42,7 +42,7 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// temporarily allow some dead fields: `kind` and `region` will be
|
// temporarily allow some dead fields: `kind` and `region` will be
|
||||||
// needed by borrowck; `lvalue` will probably be a MovePathIndex when
|
// needed by borrowck; `place` will probably be a MovePathIndex when
|
||||||
// that is extended to include borrowed data paths.
|
// that is extended to include borrowed data paths.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -50,7 +50,7 @@ pub struct BorrowData<'tcx> {
|
||||||
pub(crate) location: Location,
|
pub(crate) location: Location,
|
||||||
pub(crate) kind: mir::BorrowKind,
|
pub(crate) kind: mir::BorrowKind,
|
||||||
pub(crate) region: Region<'tcx>,
|
pub(crate) region: Region<'tcx>,
|
||||||
pub(crate) lvalue: mir::Place<'tcx>,
|
pub(crate) place: mir::Place<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Display for BorrowData<'tcx> {
|
impl<'tcx> fmt::Display for BorrowData<'tcx> {
|
||||||
|
@ -62,7 +62,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
|
||||||
};
|
};
|
||||||
let region = format!("{}", self.region);
|
let region = format!("{}", self.region);
|
||||||
let region = if region.len() > 0 { format!("{} ", region) } else { region };
|
let region = if region.len() > 0 { format!("{} ", region) } else { region };
|
||||||
write!(w, "&{}{}{:?}", region, kind, self.lvalue)
|
write!(w, "&{}{}{:?}", region, kind, self.place)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,11 +101,11 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
|
||||||
fn visit_rvalue(&mut self,
|
fn visit_rvalue(&mut self,
|
||||||
rvalue: &mir::Rvalue<'tcx>,
|
rvalue: &mir::Rvalue<'tcx>,
|
||||||
location: mir::Location) {
|
location: mir::Location) {
|
||||||
if let mir::Rvalue::Ref(region, kind, ref lvalue) = *rvalue {
|
if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
|
||||||
if is_unsafe_lvalue(self.tcx, self.mir, lvalue) { return; }
|
if is_unsafe_place(self.tcx, self.mir, place) { return; }
|
||||||
|
|
||||||
let borrow = BorrowData {
|
let borrow = BorrowData {
|
||||||
location: location, kind: kind, region: region, lvalue: lvalue.clone(),
|
location: location, kind: kind, region: region, place: place.clone(),
|
||||||
};
|
};
|
||||||
let idx = self.idx_vec.push(borrow);
|
let idx = self.idx_vec.push(borrow);
|
||||||
self.location_map.insert(location, idx);
|
self.location_map.insert(location, idx);
|
||||||
|
@ -206,8 +206,8 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::StatementKind::Assign(_, ref rhs) => {
|
mir::StatementKind::Assign(_, ref rhs) => {
|
||||||
if let mir::Rvalue::Ref(region, _, ref lvalue) = *rhs {
|
if let mir::Rvalue::Ref(region, _, ref place) = *rhs {
|
||||||
if is_unsafe_lvalue(self.tcx, self.mir, lvalue) { return; }
|
if is_unsafe_place(self.tcx, self.mir, place) { return; }
|
||||||
let index = self.location_map.get(&location).unwrap_or_else(|| {
|
let index = self.location_map.get(&location).unwrap_or_else(|| {
|
||||||
panic!("could not find BorrowIndex for location {:?}", location);
|
panic!("could not find BorrowIndex for location {:?}", location);
|
||||||
});
|
});
|
||||||
|
@ -269,7 +269,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
||||||
_in_out: &mut IdxSet<BorrowIndex>,
|
_in_out: &mut IdxSet<BorrowIndex>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
_dest_lval: &mir::Place) {
|
_dest_place: &mir::Place) {
|
||||||
// there are no effects on the region scopes from method calls.
|
// there are no effects on the region scopes from method calls.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,15 +288,15 @@ impl<'a, 'gcx, 'tcx> DataflowOperator for Borrows<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_unsafe_lvalue<'a, 'gcx: 'tcx, 'tcx: 'a>(
|
fn is_unsafe_place<'a, 'gcx: 'tcx, 'tcx: 'a>(
|
||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
mir: &'a Mir<'tcx>,
|
mir: &'a Mir<'tcx>,
|
||||||
lvalue: &mir::Place<'tcx>
|
place: &mir::Place<'tcx>
|
||||||
) -> bool {
|
) -> bool {
|
||||||
use self::mir::Place::*;
|
use self::mir::Place::*;
|
||||||
use self::mir::ProjectionElem;
|
use self::mir::ProjectionElem;
|
||||||
|
|
||||||
match *lvalue {
|
match *place {
|
||||||
Local(_) => false,
|
Local(_) => false,
|
||||||
Static(ref static_) => tcx.is_static_mut(static_.def_id),
|
Static(ref static_) => tcx.is_static_mut(static_.def_id),
|
||||||
Projection(ref proj) => {
|
Projection(ref proj) => {
|
||||||
|
@ -306,13 +306,13 @@ fn is_unsafe_lvalue<'a, 'gcx: 'tcx, 'tcx: 'a>(
|
||||||
ProjectionElem::Subslice { .. } |
|
ProjectionElem::Subslice { .. } |
|
||||||
ProjectionElem::ConstantIndex { .. } |
|
ProjectionElem::ConstantIndex { .. } |
|
||||||
ProjectionElem::Index(_) => {
|
ProjectionElem::Index(_) => {
|
||||||
is_unsafe_lvalue(tcx, mir, &proj.base)
|
is_unsafe_place(tcx, mir, &proj.base)
|
||||||
}
|
}
|
||||||
ProjectionElem::Deref => {
|
ProjectionElem::Deref => {
|
||||||
let ty = proj.base.ty(mir, tcx).to_ty(tcx);
|
let ty = proj.base.ty(mir, tcx).to_ty(tcx);
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyRawPtr(..) => true,
|
ty::TyRawPtr(..) => true,
|
||||||
_ => is_unsafe_lvalue(tcx, mir, &proj.base),
|
_ => is_unsafe_place(tcx, mir, &proj.base),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -368,11 +368,11 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
|
||||||
in_out: &mut IdxSet<MovePathIndex>,
|
in_out: &mut IdxSet<MovePathIndex>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
dest_lval: &mir::Place) {
|
dest_place: &mir::Place) {
|
||||||
// when a call returns successfully, that means we need to set
|
// when a call returns successfully, that means we need to set
|
||||||
// the bits for that dest_lval to 1 (initialized).
|
// the bits for that dest_place to 1 (initialized).
|
||||||
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
||||||
self.move_data().rev_lookup.find(dest_lval),
|
self.move_data().rev_lookup.find(dest_place),
|
||||||
|mpi| { in_out.add(&mpi); });
|
|mpi| { in_out.add(&mpi); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,7 +384,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
|
||||||
self.move_data().move_paths.len()
|
self.move_data().move_paths.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets on_entry bits for Arg lvalues
|
// sets on_entry bits for Arg places
|
||||||
fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>) {
|
fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>) {
|
||||||
// set all bits to 1 (uninit) before gathering counterevidence
|
// set all bits to 1 (uninit) before gathering counterevidence
|
||||||
for e in sets.on_entry.words_mut() { *e = !0; }
|
for e in sets.on_entry.words_mut() { *e = !0; }
|
||||||
|
@ -423,11 +423,11 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
|
||||||
in_out: &mut IdxSet<MovePathIndex>,
|
in_out: &mut IdxSet<MovePathIndex>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
dest_lval: &mir::Place) {
|
dest_place: &mir::Place) {
|
||||||
// when a call returns successfully, that means we need to set
|
// when a call returns successfully, that means we need to set
|
||||||
// the bits for that dest_lval to 0 (initialized).
|
// the bits for that dest_place to 0 (initialized).
|
||||||
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
||||||
self.move_data().rev_lookup.find(dest_lval),
|
self.move_data().rev_lookup.find(dest_place),
|
||||||
|mpi| { in_out.remove(&mpi); });
|
|mpi| { in_out.remove(&mpi); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,7 +439,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'gcx, 'tcx
|
||||||
self.move_data().move_paths.len()
|
self.move_data().move_paths.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets on_entry bits for Arg lvalues
|
// sets on_entry bits for Arg places
|
||||||
fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>) {
|
fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>) {
|
||||||
for e in sets.on_entry.words_mut() { *e = 0; }
|
for e in sets.on_entry.words_mut() { *e = 0; }
|
||||||
|
|
||||||
|
@ -477,11 +477,11 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'gcx, 'tcx
|
||||||
in_out: &mut IdxSet<MovePathIndex>,
|
in_out: &mut IdxSet<MovePathIndex>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
dest_lval: &mir::Place) {
|
dest_place: &mir::Place) {
|
||||||
// when a call returns successfully, that means we need to set
|
// when a call returns successfully, that means we need to set
|
||||||
// the bits for that dest_lval to 1 (initialized).
|
// the bits for that dest_place to 1 (initialized).
|
||||||
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
||||||
self.move_data().rev_lookup.find(dest_lval),
|
self.move_data().rev_lookup.find(dest_place),
|
||||||
|mpi| { in_out.add(&mpi); });
|
|mpi| { in_out.add(&mpi); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -561,7 +561,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> {
|
||||||
in_out: &mut IdxSet<MoveOutIndex>,
|
in_out: &mut IdxSet<MoveOutIndex>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
dest_lval: &mir::Place) {
|
dest_place: &mir::Place) {
|
||||||
let move_data = self.move_data();
|
let move_data = self.move_data();
|
||||||
let bits_per_block = self.bits_per_block();
|
let bits_per_block = self.bits_per_block();
|
||||||
|
|
||||||
|
@ -569,7 +569,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> {
|
||||||
on_lookup_result_bits(self.tcx,
|
on_lookup_result_bits(self.tcx,
|
||||||
self.mir,
|
self.mir,
|
||||||
move_data,
|
move_data,
|
||||||
move_data.rev_lookup.find(dest_lval),
|
move_data.rev_lookup.find(dest_place),
|
||||||
|mpi| for moi in &path_map[mpi] {
|
|mpi| for moi in &path_map[mpi] {
|
||||||
assert!(moi.index() < bits_per_block);
|
assert!(moi.index() < bits_per_block);
|
||||||
in_out.remove(&moi);
|
in_out.remove(&moi);
|
||||||
|
@ -647,7 +647,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> {
|
||||||
in_out: &mut IdxSet<InitIndex>,
|
in_out: &mut IdxSet<InitIndex>,
|
||||||
call_bb: mir::BasicBlock,
|
call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
_dest_lval: &mir::Place) {
|
_dest_place: &mir::Place) {
|
||||||
let move_data = self.move_data();
|
let move_data = self.move_data();
|
||||||
let bits_per_block = self.bits_per_block();
|
let bits_per_block = self.bits_per_block();
|
||||||
let init_loc_map = &move_data.init_loc_map;
|
let init_loc_map = &move_data.init_loc_map;
|
||||||
|
|
|
@ -62,7 +62,7 @@ impl<'a, 'tcx> BitDenotation for MaybeStorageLive<'a, 'tcx> {
|
||||||
_in_out: &mut IdxSet<Local>,
|
_in_out: &mut IdxSet<Local>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
_dest_lval: &mir::Place) {
|
_dest_place: &mir::Place) {
|
||||||
// Nothing to do when a call returns successfully
|
// Nothing to do when a call returns successfully
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -610,7 +610,7 @@ pub trait BitDenotation: DataflowOperator {
|
||||||
in_out: &mut IdxSet<Self::Idx>,
|
in_out: &mut IdxSet<Self::Idx>,
|
||||||
call_bb: mir::BasicBlock,
|
call_bb: mir::BasicBlock,
|
||||||
dest_bb: mir::BasicBlock,
|
dest_bb: mir::BasicBlock,
|
||||||
dest_lval: &mir::Place);
|
dest_place: &mir::Place);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
impl<'a, 'gcx, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
||||||
|
@ -714,11 +714,11 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
||||||
self.propagate_bits_into_entry_set_for(in_out, changed, unwind);
|
self.propagate_bits_into_entry_set_for(in_out, changed, unwind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some((ref dest_lval, ref dest_bb)) = *destination {
|
if let Some((ref dest_place, ref dest_bb)) = *destination {
|
||||||
// N.B.: This must be done *last*, after all other
|
// N.B.: This must be done *last*, after all other
|
||||||
// propagation, as documented in comment above.
|
// propagation, as documented in comment above.
|
||||||
self.flow_state.operator.propagate_call_return(
|
self.flow_state.operator.propagate_call_return(
|
||||||
in_out, bb, *dest_bb, dest_lval);
|
in_out, bb, *dest_bb, dest_place);
|
||||||
self.propagate_bits_into_entry_set_for(in_out, changed, dest_bb);
|
self.propagate_bits_into_entry_set_for(in_out, changed, dest_bb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,14 +68,14 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
|
||||||
path_map: &mut IndexVec<MovePathIndex, Vec<MoveOutIndex>>,
|
path_map: &mut IndexVec<MovePathIndex, Vec<MoveOutIndex>>,
|
||||||
init_path_map: &mut IndexVec<MovePathIndex, Vec<InitIndex>>,
|
init_path_map: &mut IndexVec<MovePathIndex, Vec<InitIndex>>,
|
||||||
parent: Option<MovePathIndex>,
|
parent: Option<MovePathIndex>,
|
||||||
lvalue: Place<'tcx>)
|
place: Place<'tcx>)
|
||||||
-> MovePathIndex
|
-> MovePathIndex
|
||||||
{
|
{
|
||||||
let move_path = move_paths.push(MovePath {
|
let move_path = move_paths.push(MovePath {
|
||||||
next_sibling: None,
|
next_sibling: None,
|
||||||
first_child: None,
|
first_child: None,
|
||||||
parent,
|
parent,
|
||||||
lvalue,
|
place,
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(parent) = parent {
|
if let Some(parent) = parent {
|
||||||
|
@ -95,52 +95,52 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
/// This creates a MovePath for a given lvalue, returning an `MovePathError`
|
/// This creates a MovePath for a given place, returning an `MovePathError`
|
||||||
/// if that lvalue can't be moved from.
|
/// if that place can't be moved from.
|
||||||
///
|
///
|
||||||
/// NOTE: lvalues behind references *do not* get a move path, which is
|
/// NOTE: places behind references *do not* get a move path, which is
|
||||||
/// problematic for borrowck.
|
/// problematic for borrowck.
|
||||||
///
|
///
|
||||||
/// Maybe we should have separate "borrowck" and "moveck" modes.
|
/// Maybe we should have separate "borrowck" and "moveck" modes.
|
||||||
fn move_path_for(&mut self, lval: &Place<'tcx>)
|
fn move_path_for(&mut self, place: &Place<'tcx>)
|
||||||
-> Result<MovePathIndex, MoveError<'tcx>>
|
-> Result<MovePathIndex, MoveError<'tcx>>
|
||||||
{
|
{
|
||||||
debug!("lookup({:?})", lval);
|
debug!("lookup({:?})", place);
|
||||||
match *lval {
|
match *place {
|
||||||
Place::Local(local) => Ok(self.builder.data.rev_lookup.locals[local]),
|
Place::Local(local) => Ok(self.builder.data.rev_lookup.locals[local]),
|
||||||
Place::Static(..) => {
|
Place::Static(..) => {
|
||||||
let span = self.builder.mir.source_info(self.loc).span;
|
let span = self.builder.mir.source_info(self.loc).span;
|
||||||
Err(MoveError::cannot_move_out_of(span, Static))
|
Err(MoveError::cannot_move_out_of(span, Static))
|
||||||
}
|
}
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
self.move_path_for_projection(lval, proj)
|
self.move_path_for_projection(place, proj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_move_path(&mut self, lval: &Place<'tcx>) {
|
fn create_move_path(&mut self, place: &Place<'tcx>) {
|
||||||
// This is an assignment, not a move, so this not being a valid
|
// This is an assignment, not a move, so this not being a valid
|
||||||
// move path is OK.
|
// move path is OK.
|
||||||
let _ = self.move_path_for(lval);
|
let _ = self.move_path_for(place);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_path_for_projection(&mut self,
|
fn move_path_for_projection(&mut self,
|
||||||
lval: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
proj: &PlaceProjection<'tcx>)
|
proj: &PlaceProjection<'tcx>)
|
||||||
-> Result<MovePathIndex, MoveError<'tcx>>
|
-> Result<MovePathIndex, MoveError<'tcx>>
|
||||||
{
|
{
|
||||||
let base = try!(self.move_path_for(&proj.base));
|
let base = try!(self.move_path_for(&proj.base));
|
||||||
let mir = self.builder.mir;
|
let mir = self.builder.mir;
|
||||||
let tcx = self.builder.tcx;
|
let tcx = self.builder.tcx;
|
||||||
let lv_ty = proj.base.ty(mir, tcx).to_ty(tcx);
|
let place_ty = proj.base.ty(mir, tcx).to_ty(tcx);
|
||||||
match lv_ty.sty {
|
match place_ty.sty {
|
||||||
ty::TyRef(..) | ty::TyRawPtr(..) =>
|
ty::TyRef(..) | ty::TyRawPtr(..) =>
|
||||||
return Err(MoveError::cannot_move_out_of(mir.source_info(self.loc).span,
|
return Err(MoveError::cannot_move_out_of(mir.source_info(self.loc).span,
|
||||||
BorrowedContent)),
|
BorrowedContent)),
|
||||||
ty::TyAdt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() =>
|
ty::TyAdt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() =>
|
||||||
return Err(MoveError::cannot_move_out_of(mir.source_info(self.loc).span,
|
return Err(MoveError::cannot_move_out_of(mir.source_info(self.loc).span,
|
||||||
InteriorOfTypeWithDestructor {
|
InteriorOfTypeWithDestructor {
|
||||||
container_ty: lv_ty
|
container_ty: place_ty
|
||||||
})),
|
})),
|
||||||
// move out of union - always move the entire union
|
// move out of union - always move the entire union
|
||||||
ty::TyAdt(adt, _) if adt.is_union() =>
|
ty::TyAdt(adt, _) if adt.is_union() =>
|
||||||
|
@ -149,7 +149,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
return Err(MoveError::cannot_move_out_of(
|
return Err(MoveError::cannot_move_out_of(
|
||||||
mir.source_info(self.loc).span,
|
mir.source_info(self.loc).span,
|
||||||
InteriorOfSliceOrArray {
|
InteriorOfSliceOrArray {
|
||||||
ty: lv_ty, is_index: match proj.elem {
|
ty: place_ty, is_index: match proj.elem {
|
||||||
ProjectionElem::Index(..) => true,
|
ProjectionElem::Index(..) => true,
|
||||||
_ => false
|
_ => false
|
||||||
},
|
},
|
||||||
|
@ -159,7 +159,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
return Err(MoveError::cannot_move_out_of(
|
return Err(MoveError::cannot_move_out_of(
|
||||||
mir.source_info(self.loc).span,
|
mir.source_info(self.loc).span,
|
||||||
InteriorOfSliceOrArray {
|
InteriorOfSliceOrArray {
|
||||||
ty: lv_ty, is_index: true
|
ty: place_ty, is_index: true
|
||||||
})),
|
})),
|
||||||
_ => {
|
_ => {
|
||||||
// FIXME: still badly broken
|
// FIXME: still badly broken
|
||||||
|
@ -175,7 +175,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
&mut self.builder.data.path_map,
|
&mut self.builder.data.path_map,
|
||||||
&mut self.builder.data.init_path_map,
|
&mut self.builder.data.init_path_map,
|
||||||
Some(base),
|
Some(base),
|
||||||
lval.clone()
|
place.clone()
|
||||||
);
|
);
|
||||||
ent.insert(path);
|
ent.insert(path);
|
||||||
Ok(path)
|
Ok(path)
|
||||||
|
@ -265,16 +265,16 @@ struct Gatherer<'b, 'a: 'b, 'gcx: 'tcx, 'tcx: 'a> {
|
||||||
impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
|
fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
|
||||||
match stmt.kind {
|
match stmt.kind {
|
||||||
StatementKind::Assign(ref lval, ref rval) => {
|
StatementKind::Assign(ref place, ref rval) => {
|
||||||
self.create_move_path(lval);
|
self.create_move_path(place);
|
||||||
if let RvalueInitializationState::Shallow = rval.initialization_state() {
|
if let RvalueInitializationState::Shallow = rval.initialization_state() {
|
||||||
// Box starts out uninitialized - need to create a separate
|
// Box starts out uninitialized - need to create a separate
|
||||||
// move-path for the interior so it will be separate from
|
// move-path for the interior so it will be separate from
|
||||||
// the exterior.
|
// the exterior.
|
||||||
self.create_move_path(&lval.clone().deref());
|
self.create_move_path(&place.clone().deref());
|
||||||
self.gather_init(lval, InitKind::Shallow);
|
self.gather_init(place, InitKind::Shallow);
|
||||||
} else {
|
} else {
|
||||||
self.gather_init(lval, InitKind::Deep);
|
self.gather_init(place, InitKind::Deep);
|
||||||
}
|
}
|
||||||
self.gather_rvalue(rval);
|
self.gather_rvalue(rval);
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
Rvalue::NullaryOp(NullOp::Box, _) => {
|
Rvalue::NullaryOp(NullOp::Box, _) => {
|
||||||
// This returns an rvalue with uninitialized contents. We can't
|
// This returns an rvalue with uninitialized contents. We can't
|
||||||
// move out of it here because it is an rvalue - assignments always
|
// move out of it here because it is an rvalue - assignments always
|
||||||
// completely initialize their lvalue.
|
// completely initialize their place.
|
||||||
//
|
//
|
||||||
// However, this does not matter - MIR building is careful to
|
// However, this does not matter - MIR building is careful to
|
||||||
// only emit a shallow free for the partially-initialized
|
// only emit a shallow free for the partially-initialized
|
||||||
|
@ -339,7 +339,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
TerminatorKind::Unreachable => { }
|
TerminatorKind::Unreachable => { }
|
||||||
|
|
||||||
TerminatorKind::Return => {
|
TerminatorKind::Return => {
|
||||||
self.gather_move(&Place::Local(RETURN_POINTER));
|
self.gather_move(&Place::Local(RETURN_PLACE));
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminatorKind::Assert { .. } |
|
TerminatorKind::Assert { .. } |
|
||||||
|
@ -376,16 +376,16 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
match *operand {
|
match *operand {
|
||||||
Operand::Constant(..) |
|
Operand::Constant(..) |
|
||||||
Operand::Copy(..) => {} // not-a-move
|
Operand::Copy(..) => {} // not-a-move
|
||||||
Operand::Move(ref lval) => { // a move
|
Operand::Move(ref place) => { // a move
|
||||||
self.gather_move(lval);
|
self.gather_move(place);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_move(&mut self, lval: &Place<'tcx>) {
|
fn gather_move(&mut self, place: &Place<'tcx>) {
|
||||||
debug!("gather_move({:?}, {:?})", self.loc, lval);
|
debug!("gather_move({:?}, {:?})", self.loc, place);
|
||||||
|
|
||||||
let path = match self.move_path_for(lval) {
|
let path = match self.move_path_for(place) {
|
||||||
Ok(path) | Err(MoveError::UnionMove { path }) => path,
|
Ok(path) | Err(MoveError::UnionMove { path }) => path,
|
||||||
Err(error @ MoveError::IllegalMove { .. }) => {
|
Err(error @ MoveError::IllegalMove { .. }) => {
|
||||||
self.builder.errors.push(error);
|
self.builder.errors.push(error);
|
||||||
|
@ -395,16 +395,16 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
let move_out = self.builder.data.moves.push(MoveOut { path: path, source: self.loc });
|
let move_out = self.builder.data.moves.push(MoveOut { path: path, source: self.loc });
|
||||||
|
|
||||||
debug!("gather_move({:?}, {:?}): adding move {:?} of {:?}",
|
debug!("gather_move({:?}, {:?}): adding move {:?} of {:?}",
|
||||||
self.loc, lval, move_out, path);
|
self.loc, place, move_out, path);
|
||||||
|
|
||||||
self.builder.data.path_map[path].push(move_out);
|
self.builder.data.path_map[path].push(move_out);
|
||||||
self.builder.data.loc_map[self.loc].push(move_out);
|
self.builder.data.loc_map[self.loc].push(move_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_init(&mut self, lval: &Place<'tcx>, kind: InitKind) {
|
fn gather_init(&mut self, place: &Place<'tcx>, kind: InitKind) {
|
||||||
debug!("gather_init({:?}, {:?})", self.loc, lval);
|
debug!("gather_init({:?}, {:?})", self.loc, place);
|
||||||
|
|
||||||
if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(lval) {
|
if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(place) {
|
||||||
let init = self.builder.data.inits.push(Init {
|
let init = self.builder.data.inits.push(Init {
|
||||||
span: self.builder.mir.source_info(self.loc).span,
|
span: self.builder.mir.source_info(self.loc).span,
|
||||||
path,
|
path,
|
||||||
|
@ -412,7 +412,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
});
|
});
|
||||||
|
|
||||||
debug!("gather_init({:?}, {:?}): adding init {:?} of {:?}",
|
debug!("gather_init({:?}, {:?}): adding init {:?} of {:?}",
|
||||||
self.loc, lval, init, path);
|
self.loc, place, init, path);
|
||||||
|
|
||||||
self.builder.data.init_path_map[path].push(init);
|
self.builder.data.init_path_map[path].push(init);
|
||||||
self.builder.data.init_loc_map[self.loc].push(init);
|
self.builder.data.init_loc_map[self.loc].push(init);
|
||||||
|
|
|
@ -94,7 +94,7 @@ pub struct MovePath<'tcx> {
|
||||||
pub next_sibling: Option<MovePathIndex>,
|
pub next_sibling: Option<MovePathIndex>,
|
||||||
pub first_child: Option<MovePathIndex>,
|
pub first_child: Option<MovePathIndex>,
|
||||||
pub parent: Option<MovePathIndex>,
|
pub parent: Option<MovePathIndex>,
|
||||||
pub lvalue: Place<'tcx>,
|
pub place: Place<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for MovePath<'tcx> {
|
impl<'tcx> fmt::Debug for MovePath<'tcx> {
|
||||||
|
@ -109,13 +109,13 @@ impl<'tcx> fmt::Debug for MovePath<'tcx> {
|
||||||
if let Some(next_sibling) = self.next_sibling {
|
if let Some(next_sibling) = self.next_sibling {
|
||||||
write!(w, " next_sibling: {:?}", next_sibling)?;
|
write!(w, " next_sibling: {:?}", next_sibling)?;
|
||||||
}
|
}
|
||||||
write!(w, " lvalue: {:?} }}", self.lvalue)
|
write!(w, " place: {:?} }}", self.place)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Display for MovePath<'tcx> {
|
impl<'tcx> fmt::Display for MovePath<'tcx> {
|
||||||
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(w, "{:?}", self.lvalue)
|
write!(w, "{:?}", self.place)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,11 +224,11 @@ impl fmt::Debug for Init {
|
||||||
pub struct MovePathLookup<'tcx> {
|
pub struct MovePathLookup<'tcx> {
|
||||||
locals: IndexVec<Local, MovePathIndex>,
|
locals: IndexVec<Local, MovePathIndex>,
|
||||||
|
|
||||||
/// projections are made from a base-lvalue and a projection
|
/// projections are made from a base-place and a projection
|
||||||
/// elem. The base-lvalue will have a unique MovePathIndex; we use
|
/// elem. The base-place will have a unique MovePathIndex; we use
|
||||||
/// the latter as the index into the outer vector (narrowing
|
/// the latter as the index into the outer vector (narrowing
|
||||||
/// subsequent search so that it is solely relative to that
|
/// subsequent search so that it is solely relative to that
|
||||||
/// base-lvalue). For the remaining lookup, we map the projection
|
/// base-place). For the remaining lookup, we map the projection
|
||||||
/// elem to the associated MovePathIndex.
|
/// elem to the associated MovePathIndex.
|
||||||
projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex>
|
projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex>
|
||||||
}
|
}
|
||||||
|
@ -246,8 +246,8 @@ impl<'tcx> MovePathLookup<'tcx> {
|
||||||
// alternative will *not* create a MovePath on the fly for an
|
// alternative will *not* create a MovePath on the fly for an
|
||||||
// unknown l-value, but will rather return the nearest available
|
// unknown l-value, but will rather return the nearest available
|
||||||
// parent.
|
// parent.
|
||||||
pub fn find(&self, lval: &Place<'tcx>) -> LookupResult {
|
pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
|
||||||
match *lval {
|
match *place {
|
||||||
Place::Local(local) => LookupResult::Exact(self.locals[local]),
|
Place::Local(local) => LookupResult::Exact(self.locals[local]),
|
||||||
Place::Static(..) => LookupResult::Parent(None),
|
Place::Static(..) => LookupResult::Parent(None),
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
|
|
|
@ -116,7 +116,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
overloaded_lvalue(cx, hir_expr, adjustment.target, Some(call), vec![expr.to_ref()])
|
overloaded_place(cx, hir_expr, adjustment.target, Some(call), vec![expr.to_ref()])
|
||||||
}
|
}
|
||||||
Adjust::Borrow(AutoBorrow::Ref(r, m)) => {
|
Adjust::Borrow(AutoBorrow::Ref(r, m)) => {
|
||||||
ExprKind::Borrow {
|
ExprKind::Borrow {
|
||||||
|
@ -335,7 +335,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
|
|
||||||
hir::ExprIndex(ref lhs, ref index) => {
|
hir::ExprIndex(ref lhs, ref index) => {
|
||||||
if cx.tables().is_method_call(expr) {
|
if cx.tables().is_method_call(expr) {
|
||||||
overloaded_lvalue(cx, expr, expr_ty, None, vec![lhs.to_ref(), index.to_ref()])
|
overloaded_place(cx, expr, expr_ty, None, vec![lhs.to_ref(), index.to_ref()])
|
||||||
} else {
|
} else {
|
||||||
ExprKind::Index {
|
ExprKind::Index {
|
||||||
lhs: lhs.to_ref(),
|
lhs: lhs.to_ref(),
|
||||||
|
@ -346,7 +346,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
|
|
||||||
hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => {
|
hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => {
|
||||||
if cx.tables().is_method_call(expr) {
|
if cx.tables().is_method_call(expr) {
|
||||||
overloaded_lvalue(cx, expr, expr_ty, None, vec![arg.to_ref()])
|
overloaded_place(cx, expr, expr_ty, None, vec![arg.to_ref()])
|
||||||
} else {
|
} else {
|
||||||
ExprKind::Deref { arg: arg.to_ref() }
|
ExprKind::Deref { arg: arg.to_ref() }
|
||||||
}
|
}
|
||||||
|
@ -844,15 +844,15 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
fn overloaded_place<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
expr: &'tcx hir::Expr,
|
expr: &'tcx hir::Expr,
|
||||||
lvalue_ty: Ty<'tcx>,
|
place_ty: Ty<'tcx>,
|
||||||
custom_callee: Option<(DefId, &'tcx Substs<'tcx>)>,
|
custom_callee: Option<(DefId, &'tcx Substs<'tcx>)>,
|
||||||
args: Vec<ExprRef<'tcx>>)
|
args: Vec<ExprRef<'tcx>>)
|
||||||
-> ExprKind<'tcx> {
|
-> ExprKind<'tcx> {
|
||||||
// For an overloaded *x or x[y] expression of type T, the method
|
// For an overloaded *x or x[y] expression of type T, the method
|
||||||
// call returns an &T and we must add the deref so that the types
|
// call returns an &T and we must add the deref so that the types
|
||||||
// line up (this is because `*x` and `x[y]` represent lvalues):
|
// line up (this is because `*x` and `x[y]` represent places):
|
||||||
|
|
||||||
let recv_ty = match args[0] {
|
let recv_ty = match args[0] {
|
||||||
ExprRef::Hair(e) => cx.tables().expr_ty_adjusted(e),
|
ExprRef::Hair(e) => cx.tables().expr_ty_adjusted(e),
|
||||||
|
@ -864,10 +864,10 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
|
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
|
||||||
let (region, mt) = match recv_ty.sty {
|
let (region, mt) = match recv_ty.sty {
|
||||||
ty::TyRef(region, mt) => (region, mt),
|
ty::TyRef(region, mt) => (region, mt),
|
||||||
_ => span_bug!(expr.span, "overloaded_lvalue: receiver is not a reference"),
|
_ => span_bug!(expr.span, "overloaded_place: receiver is not a reference"),
|
||||||
};
|
};
|
||||||
let ref_ty = cx.tcx.mk_ref(region, ty::TypeAndMut {
|
let ref_ty = cx.tcx.mk_ref(region, ty::TypeAndMut {
|
||||||
ty: lvalue_ty,
|
ty: place_ty,
|
||||||
mutbl: mt.mutbl,
|
mutbl: mt.mutbl,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -384,14 +384,14 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
let rcvr = Place::Local(Local::new(1+0)).deref();
|
let rcvr = Place::Local(Local::new(1+0)).deref();
|
||||||
let ret_statement = self.make_statement(
|
let ret_statement = self.make_statement(
|
||||||
StatementKind::Assign(
|
StatementKind::Assign(
|
||||||
Place::Local(RETURN_POINTER),
|
Place::Local(RETURN_PLACE),
|
||||||
Rvalue::Use(Operand::Copy(rcvr))
|
Rvalue::Use(Operand::Copy(rcvr))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
self.block(vec![ret_statement], TerminatorKind::Return, false);
|
self.block(vec![ret_statement], TerminatorKind::Return, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_lvalue(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
|
fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
|
||||||
let span = self.span;
|
let span = self.span;
|
||||||
Place::Local(
|
Place::Local(
|
||||||
self.local_decls.push(temp_decl(mutability, ty, span))
|
self.local_decls.push(temp_decl(mutability, ty, span))
|
||||||
|
@ -427,7 +427,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let ref_loc = self.make_lvalue(
|
let ref_loc = self.make_place(
|
||||||
Mutability::Not,
|
Mutability::Not,
|
||||||
tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
|
tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
|
||||||
ty,
|
ty,
|
||||||
|
@ -435,7 +435,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let loc = self.make_lvalue(Mutability::Not, ty);
|
let loc = self.make_place(Mutability::Not, ty);
|
||||||
|
|
||||||
// `let ref_loc: &ty = &rcvr_field;`
|
// `let ref_loc: &ty = &rcvr_field;`
|
||||||
let statement = self.make_statement(
|
let statement = self.make_statement(
|
||||||
|
@ -466,7 +466,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
) {
|
) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
||||||
let cond = self.make_lvalue(Mutability::Mut, tcx.types.bool);
|
let cond = self.make_place(Mutability::Mut, tcx.types.bool);
|
||||||
let compute_cond = self.make_statement(
|
let compute_cond = self.make_statement(
|
||||||
StatementKind::Assign(
|
StatementKind::Assign(
|
||||||
cond.clone(),
|
cond.clone(),
|
||||||
|
@ -502,8 +502,8 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
let rcvr = Place::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 beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span));
|
||||||
let end = self.make_lvalue(Mutability::Not, tcx.types.usize);
|
let end = self.make_place(Mutability::Not, tcx.types.usize);
|
||||||
let ret = self.make_lvalue(Mutability::Mut, tcx.mk_array(ty, len));
|
let ret = self.make_place(Mutability::Mut, tcx.mk_array(ty, len));
|
||||||
|
|
||||||
// BB #0
|
// BB #0
|
||||||
// `let mut beg = 0;`
|
// `let mut beg = 0;`
|
||||||
|
@ -567,7 +567,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
// `return ret;`
|
// `return ret;`
|
||||||
let ret_statement = self.make_statement(
|
let ret_statement = self.make_statement(
|
||||||
StatementKind::Assign(
|
StatementKind::Assign(
|
||||||
Place::Local(RETURN_POINTER),
|
Place::Local(RETURN_PLACE),
|
||||||
Rvalue::Use(Operand::Move(ret.clone())),
|
Rvalue::Use(Operand::Move(ret.clone())),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -663,7 +663,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
// `return kind(returns[0], returns[1], ..., returns[tys.len() - 1]);`
|
// `return kind(returns[0], returns[1], ..., returns[tys.len() - 1]);`
|
||||||
let ret_statement = self.make_statement(
|
let ret_statement = self.make_statement(
|
||||||
StatementKind::Assign(
|
StatementKind::Assign(
|
||||||
Place::Local(RETURN_POINTER),
|
Place::Local(RETURN_PLACE),
|
||||||
Rvalue::Aggregate(
|
Rvalue::Aggregate(
|
||||||
box kind,
|
box kind,
|
||||||
returns.into_iter().map(Operand::Move).collect()
|
returns.into_iter().map(Operand::Move).collect()
|
||||||
|
@ -749,8 +749,8 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
if let Some(untuple_args) = untuple_args {
|
if let Some(untuple_args) = untuple_args {
|
||||||
args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
|
args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
|
||||||
let arg_lv = Place::Local(Local::new(1+1));
|
let arg_place = Place::Local(Local::new(1+1));
|
||||||
Operand::Move(arg_lv.field(Field::new(i), *ity))
|
Operand::Move(arg_place.field(Field::new(i), *ity))
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
args.extend((1..sig.inputs().len()).map(|i| {
|
args.extend((1..sig.inputs().len()).map(|i| {
|
||||||
|
@ -771,7 +771,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
block(&mut blocks, statements, TerminatorKind::Call {
|
block(&mut blocks, statements, TerminatorKind::Call {
|
||||||
func: callee,
|
func: callee,
|
||||||
args,
|
args,
|
||||||
destination: Some((Place::Local(RETURN_POINTER),
|
destination: Some((Place::Local(RETURN_PLACE),
|
||||||
BasicBlock::new(1))),
|
BasicBlock::new(1))),
|
||||||
cleanup: if let Adjustment::RefMut = rcvr_adjustment {
|
cleanup: if let Adjustment::RefMut = rcvr_adjustment {
|
||||||
Some(BasicBlock::new(3))
|
Some(BasicBlock::new(3))
|
||||||
|
@ -864,7 +864,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
statements: vec![Statement {
|
statements: vec![Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Assign(
|
kind: StatementKind::Assign(
|
||||||
Place::Local(RETURN_POINTER),
|
Place::Local(RETURN_PLACE),
|
||||||
Rvalue::Aggregate(
|
Rvalue::Aggregate(
|
||||||
box AggregateKind::Adt(adt_def, variant_no, substs, None),
|
box AggregateKind::Adt(adt_def, variant_no, substs, None),
|
||||||
(1..sig.inputs().len()+1).map(|i| {
|
(1..sig.inputs().len()+1).map(|i| {
|
||||||
|
|
|
@ -22,9 +22,9 @@ use transform::{MirPass, MirSource};
|
||||||
|
|
||||||
pub struct AddValidation;
|
pub struct AddValidation;
|
||||||
|
|
||||||
/// Determine the "context" of the lval: Mutability and region.
|
/// Determine the "context" of the place: Mutability and region.
|
||||||
fn lval_context<'a, 'tcx, D>(
|
fn place_context<'a, 'tcx, D>(
|
||||||
lval: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
local_decls: &D,
|
local_decls: &D,
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>
|
tcx: TyCtxt<'a, 'tcx, 'tcx>
|
||||||
) -> (Option<region::Scope>, hir::Mutability)
|
) -> (Option<region::Scope>, hir::Mutability)
|
||||||
|
@ -32,7 +32,7 @@ fn lval_context<'a, 'tcx, D>(
|
||||||
{
|
{
|
||||||
use rustc::mir::Place::*;
|
use rustc::mir::Place::*;
|
||||||
|
|
||||||
match *lval {
|
match *place {
|
||||||
Local { .. } => (None, hir::MutMutable),
|
Local { .. } => (None, hir::MutMutable),
|
||||||
Static(_) => (None, hir::MutImmutable),
|
Static(_) => (None, hir::MutImmutable),
|
||||||
Projection(ref proj) => {
|
Projection(ref proj) => {
|
||||||
|
@ -66,7 +66,7 @@ fn lval_context<'a, 'tcx, D>(
|
||||||
// This is already as restricted as it gets, no need to even recurse
|
// This is already as restricted as it gets, no need to even recurse
|
||||||
context
|
context
|
||||||
} else {
|
} else {
|
||||||
let base_context = lval_context(&proj.base, local_decls, tcx);
|
let base_context = place_context(&proj.base, local_decls, tcx);
|
||||||
// The region of the outermost Deref is always most restrictive.
|
// The region of the outermost Deref is always most restrictive.
|
||||||
let re = context.0.or(base_context.0);
|
let re = context.0.or(base_context.0);
|
||||||
let mutbl = context.1.and(base_context.1);
|
let mutbl = context.1.and(base_context.1);
|
||||||
|
@ -74,7 +74,7 @@ fn lval_context<'a, 'tcx, D>(
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
_ => lval_context(&proj.base, local_decls, tcx),
|
_ => place_context(&proj.base, local_decls, tcx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,11 +198,11 @@ impl MirPass for AddValidation {
|
||||||
let restricted_validation = emit_validate == 1 && fn_contains_unsafe(tcx, src);
|
let restricted_validation = emit_validate == 1 && fn_contains_unsafe(tcx, src);
|
||||||
let local_decls = mir.local_decls.clone(); // FIXME: Find a way to get rid of this clone.
|
let local_decls = mir.local_decls.clone(); // FIXME: Find a way to get rid of this clone.
|
||||||
|
|
||||||
// Convert an lvalue to a validation operand.
|
// Convert a place to a validation operand.
|
||||||
let lval_to_operand = |lval: Place<'tcx>| -> ValidationOperand<'tcx, Place<'tcx>> {
|
let place_to_operand = |place: Place<'tcx>| -> ValidationOperand<'tcx, Place<'tcx>> {
|
||||||
let (re, mutbl) = lval_context(&lval, &local_decls, tcx);
|
let (re, mutbl) = place_context(&place, &local_decls, tcx);
|
||||||
let ty = lval.ty(&local_decls, tcx).to_ty(tcx);
|
let ty = place.ty(&local_decls, tcx).to_ty(tcx);
|
||||||
ValidationOperand { lval, ty, re, mutbl }
|
ValidationOperand { place, ty, re, mutbl }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Emit an Acquire at the beginning of the given block. If we are in restricted emission
|
// Emit an Acquire at the beginning of the given block. If we are in restricted emission
|
||||||
|
@ -237,7 +237,7 @@ impl MirPass for AddValidation {
|
||||||
};
|
};
|
||||||
// Gather all arguments, skip return value.
|
// Gather all arguments, skip return value.
|
||||||
let operands = mir.local_decls.iter_enumerated().skip(1).take(mir.arg_count)
|
let operands = mir.local_decls.iter_enumerated().skip(1).take(mir.arg_count)
|
||||||
.map(|(local, _)| lval_to_operand(Place::Local(local))).collect();
|
.map(|(local, _)| place_to_operand(Place::Local(local))).collect();
|
||||||
emit_acquire(&mut mir.basic_blocks_mut()[START_BLOCK], source_info, operands);
|
emit_acquire(&mut mir.basic_blocks_mut()[START_BLOCK], source_info, operands);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,13 +256,13 @@ impl MirPass for AddValidation {
|
||||||
let release_stmt = Statement {
|
let release_stmt = Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Validate(ValidationOp::Release,
|
kind: StatementKind::Validate(ValidationOp::Release,
|
||||||
destination.iter().map(|dest| lval_to_operand(dest.0.clone()))
|
destination.iter().map(|dest| place_to_operand(dest.0.clone()))
|
||||||
.chain(
|
.chain(
|
||||||
args.iter().filter_map(|op| {
|
args.iter().filter_map(|op| {
|
||||||
match op {
|
match op {
|
||||||
&Operand::Copy(ref lval) |
|
&Operand::Copy(ref place) |
|
||||||
&Operand::Move(ref lval) =>
|
&Operand::Move(ref place) =>
|
||||||
Some(lval_to_operand(lval.clone())),
|
Some(place_to_operand(place.clone())),
|
||||||
&Operand::Constant(..) => { None },
|
&Operand::Constant(..) => { None },
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -275,16 +275,16 @@ impl MirPass for AddValidation {
|
||||||
returns.push((source_info, destination.0.clone(), destination.1));
|
returns.push((source_info, destination.0.clone(), destination.1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(Terminator { kind: TerminatorKind::Drop { location: ref lval, .. },
|
Some(Terminator { kind: TerminatorKind::Drop { location: ref place, .. },
|
||||||
source_info }) |
|
source_info }) |
|
||||||
Some(Terminator { kind: TerminatorKind::DropAndReplace { location: ref lval, .. },
|
Some(Terminator { kind: TerminatorKind::DropAndReplace { location: ref place, .. },
|
||||||
source_info }) => {
|
source_info }) => {
|
||||||
// Before the call: Release all arguments
|
// Before the call: Release all arguments
|
||||||
if !restricted_validation {
|
if !restricted_validation {
|
||||||
let release_stmt = Statement {
|
let release_stmt = Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Validate(ValidationOp::Release,
|
kind: StatementKind::Validate(ValidationOp::Release,
|
||||||
vec![lval_to_operand(lval.clone())]),
|
vec![place_to_operand(place.clone())]),
|
||||||
};
|
};
|
||||||
block_data.statements.push(release_stmt);
|
block_data.statements.push(release_stmt);
|
||||||
}
|
}
|
||||||
|
@ -296,11 +296,11 @@ impl MirPass for AddValidation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Now we go over the returns we collected to acquire the return values.
|
// Now we go over the returns we collected to acquire the return values.
|
||||||
for (source_info, dest_lval, dest_block) in returns {
|
for (source_info, dest_place, dest_block) in returns {
|
||||||
emit_acquire(
|
emit_acquire(
|
||||||
&mut mir.basic_blocks_mut()[dest_block],
|
&mut mir.basic_blocks_mut()[dest_block],
|
||||||
source_info,
|
source_info,
|
||||||
vec![lval_to_operand(dest_lval)]
|
vec![place_to_operand(dest_place)]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,22 +321,20 @@ impl MirPass for AddValidation {
|
||||||
StatementKind::Assign(_, Rvalue::Ref(_, _, _)) => {
|
StatementKind::Assign(_, Rvalue::Ref(_, _, _)) => {
|
||||||
// Due to a lack of NLL; we can't capture anything directly here.
|
// Due to a lack of NLL; we can't capture anything directly here.
|
||||||
// Instead, we have to re-match and clone there.
|
// Instead, we have to re-match and clone there.
|
||||||
let (dest_lval, re, src_lval) = match block_data.statements[i].kind {
|
let (dest_place, re, src_place) = match block_data.statements[i].kind {
|
||||||
StatementKind::Assign(ref dest_lval,
|
StatementKind::Assign(ref dest_place,
|
||||||
Rvalue::Ref(re, _, ref src_lval)) => {
|
Rvalue::Ref(re, _, ref src_place)) => {
|
||||||
(dest_lval.clone(), re, src_lval.clone())
|
(dest_place.clone(), re, src_place.clone())
|
||||||
},
|
},
|
||||||
_ => bug!("We already matched this."),
|
_ => bug!("We already matched this."),
|
||||||
};
|
};
|
||||||
// So this is a ref, and we got all the data we wanted.
|
// So this is a ref, and we got all the data we wanted.
|
||||||
// Do an acquire of the result -- but only what it points to, so add a Deref
|
// Do an acquire of the result -- but only what it points to, so add a Deref
|
||||||
// projection.
|
// projection.
|
||||||
let dest_lval = Projection { base: dest_lval, elem: ProjectionElem::Deref };
|
|
||||||
let dest_lval = Place::Projection(Box::new(dest_lval));
|
|
||||||
let acquire_stmt = Statement {
|
let acquire_stmt = Statement {
|
||||||
source_info: block_data.statements[i].source_info,
|
source_info: block_data.statements[i].source_info,
|
||||||
kind: StatementKind::Validate(ValidationOp::Acquire,
|
kind: StatementKind::Validate(ValidationOp::Acquire,
|
||||||
vec![lval_to_operand(dest_lval)]),
|
vec![place_to_operand(dest_place.deref())]),
|
||||||
};
|
};
|
||||||
block_data.statements.insert(i+1, acquire_stmt);
|
block_data.statements.insert(i+1, acquire_stmt);
|
||||||
|
|
||||||
|
@ -349,7 +347,7 @@ impl MirPass for AddValidation {
|
||||||
};
|
};
|
||||||
let release_stmt = Statement {
|
let release_stmt = Statement {
|
||||||
source_info: block_data.statements[i].source_info,
|
source_info: block_data.statements[i].source_info,
|
||||||
kind: StatementKind::Validate(op, vec![lval_to_operand(src_lval)]),
|
kind: StatementKind::Validate(op, vec![place_to_operand(src_place)]),
|
||||||
};
|
};
|
||||||
block_data.statements.insert(i, release_stmt);
|
block_data.statements.insert(i, release_stmt);
|
||||||
}
|
}
|
||||||
|
@ -360,13 +358,13 @@ impl MirPass for AddValidation {
|
||||||
{
|
{
|
||||||
// Due to a lack of NLL; we can't capture anything directly here.
|
// Due to a lack of NLL; we can't capture anything directly here.
|
||||||
// Instead, we have to re-match and clone there.
|
// Instead, we have to re-match and clone there.
|
||||||
let (dest_lval, src_lval) = match block_data.statements[i].kind {
|
let (dest_place, src_place) = match block_data.statements[i].kind {
|
||||||
StatementKind::Assign(ref dest_lval,
|
StatementKind::Assign(ref dest_place,
|
||||||
Rvalue::Cast(_, Operand::Copy(ref src_lval), _)) |
|
Rvalue::Cast(_, Operand::Copy(ref src_place), _)) |
|
||||||
StatementKind::Assign(ref dest_lval,
|
StatementKind::Assign(ref dest_place,
|
||||||
Rvalue::Cast(_, Operand::Move(ref src_lval), _)) =>
|
Rvalue::Cast(_, Operand::Move(ref src_place), _)) =>
|
||||||
{
|
{
|
||||||
(dest_lval.clone(), src_lval.clone())
|
(dest_place.clone(), src_place.clone())
|
||||||
},
|
},
|
||||||
_ => bug!("We already matched this."),
|
_ => bug!("We already matched this."),
|
||||||
};
|
};
|
||||||
|
@ -375,7 +373,7 @@ impl MirPass for AddValidation {
|
||||||
let acquire_stmt = Statement {
|
let acquire_stmt = Statement {
|
||||||
source_info: block_data.statements[i].source_info,
|
source_info: block_data.statements[i].source_info,
|
||||||
kind: StatementKind::Validate(ValidationOp::Acquire,
|
kind: StatementKind::Validate(ValidationOp::Acquire,
|
||||||
vec![lval_to_operand(dest_lval)]),
|
vec![place_to_operand(dest_place)]),
|
||||||
};
|
};
|
||||||
block_data.statements.insert(i+1, acquire_stmt);
|
block_data.statements.insert(i+1, acquire_stmt);
|
||||||
|
|
||||||
|
@ -383,7 +381,7 @@ impl MirPass for AddValidation {
|
||||||
let release_stmt = Statement {
|
let release_stmt = Statement {
|
||||||
source_info: block_data.statements[i].source_info,
|
source_info: block_data.statements[i].source_info,
|
||||||
kind: StatementKind::Validate(ValidationOp::Release,
|
kind: StatementKind::Validate(ValidationOp::Release,
|
||||||
vec![lval_to_operand(src_lval)]),
|
vec![place_to_operand(src_place)]),
|
||||||
};
|
};
|
||||||
block_data.statements.insert(i, release_stmt);
|
block_data.statements.insert(i, release_stmt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,12 +135,12 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||||
self.super_rvalue(rvalue, location);
|
self.super_rvalue(rvalue, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lvalue(&mut self,
|
fn visit_place(&mut self,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
if let PlaceContext::Borrow { .. } = context {
|
if let PlaceContext::Borrow { .. } = context {
|
||||||
if util::is_disaligned(self.tcx, self.mir, self.param_env, lvalue) {
|
if util::is_disaligned(self.tcx, self.mir, self.param_env, place) {
|
||||||
let source_info = self.source_info;
|
let source_info = self.source_info;
|
||||||
let lint_root =
|
let lint_root =
|
||||||
self.visibility_scope_info[source_info.scope].lint_root;
|
self.visibility_scope_info[source_info.scope].lint_root;
|
||||||
|
@ -152,7 +152,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match lvalue {
|
match place {
|
||||||
&Place::Projection(box Projection {
|
&Place::Projection(box Projection {
|
||||||
ref base, ref elem
|
ref base, ref elem
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -180,7 +180,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||||
_ => span_bug!(
|
_ => span_bug!(
|
||||||
self.source_info.span,
|
self.source_info.span,
|
||||||
"non-field projection {:?} from union?",
|
"non-field projection {:?} from union?",
|
||||||
lvalue)
|
place)
|
||||||
};
|
};
|
||||||
if elem_ty.moves_by_default(self.tcx, self.param_env,
|
if elem_ty.moves_by_default(self.tcx, self.param_env,
|
||||||
self.source_info.span) {
|
self.source_info.span) {
|
||||||
|
@ -216,7 +216,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.super_lvalue(lvalue, context, location);
|
self.super_place(place, context, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,8 +108,8 @@ impl MirPass for CopyPropagation {
|
||||||
dest_local);
|
dest_local);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let dest_lvalue_def = dest_use_info.defs_not_including_drop().next().unwrap();
|
let dest_place_def = dest_use_info.defs_not_including_drop().next().unwrap();
|
||||||
location = dest_lvalue_def.location;
|
location = dest_place_def.location;
|
||||||
|
|
||||||
let basic_block = &mir[location.block];
|
let basic_block = &mir[location.block];
|
||||||
let statement_index = location.statement_index;
|
let statement_index = location.statement_index;
|
||||||
|
@ -126,9 +126,9 @@ impl MirPass for CopyPropagation {
|
||||||
StatementKind::Assign(Place::Local(local), Rvalue::Use(ref operand)) if
|
StatementKind::Assign(Place::Local(local), Rvalue::Use(ref operand)) if
|
||||||
local == dest_local => {
|
local == dest_local => {
|
||||||
let maybe_action = match *operand {
|
let maybe_action = match *operand {
|
||||||
Operand::Copy(ref src_lvalue) |
|
Operand::Copy(ref src_place) |
|
||||||
Operand::Move(ref src_lvalue) => {
|
Operand::Move(ref src_place) => {
|
||||||
Action::local_copy(&mir, &def_use_analysis, src_lvalue)
|
Action::local_copy(&mir, &def_use_analysis, src_place)
|
||||||
}
|
}
|
||||||
Operand::Constant(ref src_constant) => {
|
Operand::Constant(ref src_constant) => {
|
||||||
Action::constant(src_constant)
|
Action::constant(src_constant)
|
||||||
|
@ -202,10 +202,10 @@ enum Action<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Action<'tcx> {
|
impl<'tcx> Action<'tcx> {
|
||||||
fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis, src_lvalue: &Place<'tcx>)
|
fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis, src_place: &Place<'tcx>)
|
||||||
-> Option<Action<'tcx>> {
|
-> Option<Action<'tcx>> {
|
||||||
// The source must be a local.
|
// The source must be a local.
|
||||||
let src_local = if let Place::Local(local) = *src_lvalue {
|
let src_local = if let Place::Local(local) = *src_place {
|
||||||
local
|
local
|
||||||
} else {
|
} else {
|
||||||
debug!(" Can't copy-propagate local: source is not a local");
|
debug!(" Can't copy-propagate local: source is not a local");
|
||||||
|
@ -269,14 +269,14 @@ impl<'tcx> Action<'tcx> {
|
||||||
debug!(" Replacing all uses of {:?} with {:?} (local)",
|
debug!(" Replacing all uses of {:?} with {:?} (local)",
|
||||||
dest_local,
|
dest_local,
|
||||||
src_local);
|
src_local);
|
||||||
for lvalue_use in &def_use_analysis.local_info(dest_local).defs_and_uses {
|
for place_use in &def_use_analysis.local_info(dest_local).defs_and_uses {
|
||||||
if lvalue_use.context.is_storage_marker() {
|
if place_use.context.is_storage_marker() {
|
||||||
mir.make_statement_nop(lvalue_use.location)
|
mir.make_statement_nop(place_use.location)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for lvalue_use in &def_use_analysis.local_info(src_local).defs_and_uses {
|
for place_use in &def_use_analysis.local_info(src_local).defs_and_uses {
|
||||||
if lvalue_use.context.is_storage_marker() {
|
if place_use.context.is_storage_marker() {
|
||||||
mir.make_statement_nop(lvalue_use.location)
|
mir.make_statement_nop(place_use.location)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,22 +297,22 @@ impl<'tcx> Action<'tcx> {
|
||||||
dest_local,
|
dest_local,
|
||||||
src_constant);
|
src_constant);
|
||||||
let dest_local_info = def_use_analysis.local_info(dest_local);
|
let dest_local_info = def_use_analysis.local_info(dest_local);
|
||||||
for lvalue_use in &dest_local_info.defs_and_uses {
|
for place_use in &dest_local_info.defs_and_uses {
|
||||||
if lvalue_use.context.is_storage_marker() {
|
if place_use.context.is_storage_marker() {
|
||||||
mir.make_statement_nop(lvalue_use.location)
|
mir.make_statement_nop(place_use.location)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace all uses of the destination local with the constant.
|
// Replace all uses of the destination local with the constant.
|
||||||
let mut visitor = ConstantPropagationVisitor::new(dest_local,
|
let mut visitor = ConstantPropagationVisitor::new(dest_local,
|
||||||
src_constant);
|
src_constant);
|
||||||
for dest_lvalue_use in &dest_local_info.defs_and_uses {
|
for dest_place_use in &dest_local_info.defs_and_uses {
|
||||||
visitor.visit_location(mir, dest_lvalue_use.location)
|
visitor.visit_location(mir, dest_place_use.location)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zap the assignment instruction if we eliminated all the uses. We won't have been
|
// Zap the assignment instruction if we eliminated all the uses. We won't have been
|
||||||
// able to do that if the destination was used in a projection, because projections
|
// able to do that if the destination was used in a projection, because projections
|
||||||
// must have lvalues on their LHS.
|
// must have places on their LHS.
|
||||||
let use_count = dest_local_info.use_count();
|
let use_count = dest_local_info.use_count();
|
||||||
if visitor.uses_replaced == use_count {
|
if visitor.uses_replaced == use_count {
|
||||||
debug!(" {} of {} use(s) replaced; deleting assignment",
|
debug!(" {} of {} use(s) replaced; deleting assignment",
|
||||||
|
|
|
@ -92,7 +92,7 @@ impl MirPass for Deaggregator {
|
||||||
if adt_def.is_enum() {
|
if adt_def.is_enum() {
|
||||||
let set_discriminant = Statement {
|
let set_discriminant = Statement {
|
||||||
kind: StatementKind::SetDiscriminant {
|
kind: StatementKind::SetDiscriminant {
|
||||||
lvalue: lhs.clone(),
|
place: lhs.clone(),
|
||||||
variant_index: variant,
|
variant_index: variant,
|
||||||
},
|
},
|
||||||
source_info: src_info,
|
source_info: src_info,
|
||||||
|
|
|
@ -358,7 +358,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||||
});
|
});
|
||||||
|
|
||||||
let path = self.move_data().rev_lookup.find(location);
|
let path = self.move_data().rev_lookup.find(location);
|
||||||
debug!("collect_drop_flags: {:?}, lv {:?} ({:?})",
|
debug!("collect_drop_flags: {:?}, place {:?} ({:?})",
|
||||||
bb, location, path);
|
bb, location, path);
|
||||||
|
|
||||||
let path = match path {
|
let path = match path {
|
||||||
|
@ -368,7 +368,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||||
let (_maybe_live, maybe_dead) = init_data.state(parent);
|
let (_maybe_live, maybe_dead) = init_data.state(parent);
|
||||||
if maybe_dead {
|
if maybe_dead {
|
||||||
span_bug!(terminator.source_info.span,
|
span_bug!(terminator.source_info.span,
|
||||||
"drop of untracked, uninitialized value {:?}, lv {:?} ({:?})",
|
"drop of untracked, uninitialized value {:?}, place {:?} ({:?})",
|
||||||
bb, location, path);
|
bb, location, path);
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
@ -443,7 +443,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||||
/// The desugaring drops the location if needed, and then writes
|
/// The desugaring drops the location if needed, and then writes
|
||||||
/// the value (including setting the drop flag) over it in *both* arms.
|
/// the value (including setting the drop flag) over it in *both* arms.
|
||||||
///
|
///
|
||||||
/// The `replace` terminator can also be called on lvalues that
|
/// The `replace` terminator can also be called on places that
|
||||||
/// are not tracked by elaboration (for example,
|
/// are not tracked by elaboration (for example,
|
||||||
/// `replace x[i] <- tmp0`). The borrow checker requires that
|
/// `replace x[i] <- tmp0`). The borrow checker requires that
|
||||||
/// these locations are initialized before the assignment,
|
/// these locations are initialized before the assignment,
|
||||||
|
@ -554,12 +554,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||||
fn drop_flags_for_fn_rets(&mut self) {
|
fn drop_flags_for_fn_rets(&mut self) {
|
||||||
for (bb, data) in self.mir.basic_blocks().iter_enumerated() {
|
for (bb, data) in self.mir.basic_blocks().iter_enumerated() {
|
||||||
if let TerminatorKind::Call {
|
if let TerminatorKind::Call {
|
||||||
destination: Some((ref lv, tgt)), cleanup: Some(_), ..
|
destination: Some((ref place, tgt)), cleanup: Some(_), ..
|
||||||
} = data.terminator().kind {
|
} = data.terminator().kind {
|
||||||
assert!(!self.patch.is_patched(bb));
|
assert!(!self.patch.is_patched(bb));
|
||||||
|
|
||||||
let loc = Location { block: tgt, statement_index: 0 };
|
let loc = Location { block: tgt, statement_index: 0 };
|
||||||
let path = self.move_data().rev_lookup.find(lv);
|
let path = self.move_data().rev_lookup.find(place);
|
||||||
on_lookup_result_bits(
|
on_lookup_result_bits(
|
||||||
self.tcx, self.mir, self.move_data(), path,
|
self.tcx, self.mir, self.move_data(), path,
|
||||||
|child| self.set_drop_flag(loc, child, DropFlagState::Present)
|
|child| self.set_drop_flag(loc, child, DropFlagState::Present)
|
||||||
|
@ -628,12 +628,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||||
// so mark the return as initialized *before* the
|
// so mark the return as initialized *before* the
|
||||||
// call.
|
// call.
|
||||||
if let TerminatorKind::Call {
|
if let TerminatorKind::Call {
|
||||||
destination: Some((ref lv, _)), cleanup: None, ..
|
destination: Some((ref place, _)), cleanup: None, ..
|
||||||
} = data.terminator().kind {
|
} = data.terminator().kind {
|
||||||
assert!(!self.patch.is_patched(bb));
|
assert!(!self.patch.is_patched(bb));
|
||||||
|
|
||||||
let loc = Location { block: bb, statement_index: data.statements.len() };
|
let loc = Location { block: bb, statement_index: data.statements.len() };
|
||||||
let path = self.move_data().rev_lookup.find(lv);
|
let path = self.move_data().rev_lookup.find(place);
|
||||||
on_lookup_result_bits(
|
on_lookup_result_bits(
|
||||||
self.tcx, self.mir, self.move_data(), path,
|
self.tcx, self.mir, self.move_data(), path,
|
||||||
|child| self.set_drop_flag(loc, child, DropFlagState::Present)
|
|child| self.set_drop_flag(loc, child, DropFlagState::Present)
|
||||||
|
|
|
@ -108,17 +108,17 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
|
||||||
assert_ne!(*local, self_arg());
|
assert_ne!(*local, self_arg());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lvalue(&mut self,
|
fn visit_place(&mut self,
|
||||||
lvalue: &mut Place<'tcx>,
|
place: &mut Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
if *lvalue == Place::Local(self_arg()) {
|
if *place == Place::Local(self_arg()) {
|
||||||
*lvalue = Place::Projection(Box::new(Projection {
|
*place = Place::Projection(Box::new(Projection {
|
||||||
base: lvalue.clone(),
|
base: place.clone(),
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
self.super_lvalue(lvalue, context, location);
|
self.super_place(place, context, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ struct TransformVisitor<'a, 'tcx: 'a> {
|
||||||
// A list of suspension points, generated during the transform
|
// A list of suspension points, generated during the transform
|
||||||
suspension_points: Vec<SuspensionPoint>,
|
suspension_points: Vec<SuspensionPoint>,
|
||||||
|
|
||||||
// The original RETURN_POINTER local
|
// The original RETURN_PLACE local
|
||||||
new_ret_local: Local,
|
new_ret_local: Local,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,17 +200,17 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
|
||||||
assert_eq!(self.remap.get(local), None);
|
assert_eq!(self.remap.get(local), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lvalue(&mut self,
|
fn visit_place(&mut self,
|
||||||
lvalue: &mut Place<'tcx>,
|
place: &mut Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
if let Place::Local(l) = *lvalue {
|
if let Place::Local(l) = *place {
|
||||||
// Replace an Local in the remap with a generator struct access
|
// Replace an Local in the remap with a generator struct access
|
||||||
if let Some(&(ty, idx)) = self.remap.get(&l) {
|
if let Some(&(ty, idx)) = self.remap.get(&l) {
|
||||||
*lvalue = self.make_field(idx, ty);
|
*place = self.make_field(idx, ty);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.super_lvalue(lvalue, context, location);
|
self.super_place(place, context, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
|
||||||
// We must assign the value first in case it gets declared dead below
|
// We must assign the value first in case it gets declared dead below
|
||||||
data.statements.push(Statement {
|
data.statements.push(Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Assign(Place::Local(RETURN_POINTER),
|
kind: StatementKind::Assign(Place::Local(RETURN_PLACE),
|
||||||
self.make_state(state_idx, v)),
|
self.make_state(state_idx, v)),
|
||||||
});
|
});
|
||||||
let state = if let Some(resume) = resume { // Yield
|
let state = if let Some(resume) = resume { // Yield
|
||||||
|
@ -310,7 +310,7 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>,
|
||||||
mir.local_decls.swap(0, new_ret_local.index());
|
mir.local_decls.swap(0, new_ret_local.index());
|
||||||
|
|
||||||
RenameLocalVisitor {
|
RenameLocalVisitor {
|
||||||
from: RETURN_POINTER,
|
from: RETURN_PLACE,
|
||||||
to: new_ret_local,
|
to: new_ret_local,
|
||||||
}.visit_mir(mir);
|
}.visit_mir(mir);
|
||||||
|
|
||||||
|
@ -557,7 +557,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the return variable
|
// Replace the return variable
|
||||||
mir.local_decls[RETURN_POINTER] = LocalDecl {
|
mir.local_decls[RETURN_PLACE] = LocalDecl {
|
||||||
mutability: Mutability::Mut,
|
mutability: Mutability::Mut,
|
||||||
ty: tcx.mk_nil(),
|
ty: tcx.mk_nil(),
|
||||||
name: None,
|
name: None,
|
||||||
|
@ -783,8 +783,8 @@ impl MirPass for StateTransform {
|
||||||
Kind::from(mir.return_ty())].iter());
|
Kind::from(mir.return_ty())].iter());
|
||||||
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
|
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
|
||||||
|
|
||||||
// We rename RETURN_POINTER which has type mir.return_ty to new_ret_local
|
// We rename RETURN_PLACE which has type mir.return_ty to new_ret_local
|
||||||
// RETURN_POINTER then is a fresh unused local with type ret_ty.
|
// RETURN_PLACE then is a fresh unused local with type ret_ty.
|
||||||
let new_ret_local = replace_result_variable(ret_ty, mir);
|
let new_ret_local = replace_result_variable(ret_ty, mir);
|
||||||
|
|
||||||
// Extract locals which are live across suspension point into `layout`
|
// Extract locals which are live across suspension point into `layout`
|
||||||
|
|
|
@ -406,9 +406,9 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||||
// `i : &mut usize`, then just duplicating the `a[*i]`
|
// `i : &mut usize`, then just duplicating the `a[*i]`
|
||||||
// Place 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
|
// writes to `i`. To prevent this we need to create a temporary
|
||||||
// borrow of the lvalue and pass the destination as `*temp` instead.
|
// borrow of the place and pass the destination as `*temp` instead.
|
||||||
fn dest_needs_borrow(lval: &Place) -> bool {
|
fn dest_needs_borrow(place: &Place) -> bool {
|
||||||
match *lval {
|
match *place {
|
||||||
Place::Projection(ref p) => {
|
Place::Projection(ref p) => {
|
||||||
match p.elem {
|
match p.elem {
|
||||||
ProjectionElem::Deref |
|
ProjectionElem::Deref |
|
||||||
|
@ -456,8 +456,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||||
// needs to generate the cast.
|
// needs to generate the cast.
|
||||||
// FIXME: we should probably just generate correct MIR in the first place...
|
// FIXME: we should probably just generate correct MIR in the first place...
|
||||||
|
|
||||||
let arg = if let Operand::Move(ref lval) = args[0] {
|
let arg = if let Operand::Move(ref place) = args[0] {
|
||||||
lval.clone()
|
place.clone()
|
||||||
} else {
|
} else {
|
||||||
bug!("Constant arg to \"box_free\"");
|
bug!("Constant arg to \"box_free\"");
|
||||||
};
|
};
|
||||||
|
@ -715,13 +715,13 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
|
||||||
local: &mut Local,
|
local: &mut Local,
|
||||||
_ctxt: PlaceContext<'tcx>,
|
_ctxt: PlaceContext<'tcx>,
|
||||||
_location: Location) {
|
_location: Location) {
|
||||||
if *local == RETURN_POINTER {
|
if *local == RETURN_PLACE {
|
||||||
match self.destination {
|
match self.destination {
|
||||||
Place::Local(l) => {
|
Place::Local(l) => {
|
||||||
*local = l;
|
*local = l;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
ref lval => bug!("Return lvalue is {:?}, not local", lval)
|
ref place => bug!("Return place is {:?}, not local", place)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let idx = local.index() - 1;
|
let idx = local.index() - 1;
|
||||||
|
@ -732,15 +732,15 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
|
||||||
*local = self.local_map[Local::new(idx - self.args.len())];
|
*local = self.local_map[Local::new(idx - self.args.len())];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lvalue(&mut self,
|
fn visit_place(&mut self,
|
||||||
lvalue: &mut Place<'tcx>,
|
place: &mut Place<'tcx>,
|
||||||
_ctxt: PlaceContext<'tcx>,
|
_ctxt: PlaceContext<'tcx>,
|
||||||
_location: Location) {
|
_location: Location) {
|
||||||
if let Place::Local(RETURN_POINTER) = *lvalue {
|
if let Place::Local(RETURN_PLACE) = *place {
|
||||||
// Return pointer; update the lvalue itself
|
// Return pointer; update the place itself
|
||||||
*lvalue = self.destination.clone();
|
*place = self.destination.clone();
|
||||||
} else {
|
} else {
|
||||||
self.super_lvalue(lvalue, _ctxt, _location);
|
self.super_place(place, _ctxt, _location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,14 +52,14 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
|
||||||
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
|
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
|
||||||
if self.optimizations.and_stars.remove(&location) {
|
if self.optimizations.and_stars.remove(&location) {
|
||||||
debug!("Replacing `&*`: {:?}", rvalue);
|
debug!("Replacing `&*`: {:?}", rvalue);
|
||||||
let new_lvalue = match *rvalue {
|
let new_place = match *rvalue {
|
||||||
Rvalue::Ref(_, _, Place::Projection(ref mut projection)) => {
|
Rvalue::Ref(_, _, Place::Projection(ref mut projection)) => {
|
||||||
// Replace with dummy
|
// Replace with dummy
|
||||||
mem::replace(&mut projection.base, Place::Local(Local::new(0)))
|
mem::replace(&mut projection.base, Place::Local(Local::new(0)))
|
||||||
}
|
}
|
||||||
_ => bug!("Detected `&*` but didn't find `&*`!"),
|
_ => bug!("Detected `&*` but didn't find `&*`!"),
|
||||||
};
|
};
|
||||||
*rvalue = Rvalue::Use(Operand::Copy(new_lvalue))
|
*rvalue = Rvalue::Use(Operand::Copy(new_place))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(constant) = self.optimizations.arrays_lengths.remove(&location) {
|
if let Some(constant) = self.optimizations.arrays_lengths.remove(&location) {
|
||||||
|
@ -98,9 +98,9 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Rvalue::Len(ref lvalue) = *rvalue {
|
if let Rvalue::Len(ref place) = *rvalue {
|
||||||
let lvalue_ty = lvalue.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
|
let place_ty = place.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
|
||||||
if let TypeVariants::TyArray(_, len) = lvalue_ty.sty {
|
if let TypeVariants::TyArray(_, len) = place_ty.sty {
|
||||||
let span = self.mir.source_info(location).span;
|
let span = self.mir.source_info(location).span;
|
||||||
let ty = self.tcx.types.usize;
|
let ty = self.tcx.types.usize;
|
||||||
let literal = Literal::Value { value: len };
|
let literal = Literal::Value { value: len };
|
||||||
|
|
|
@ -75,19 +75,19 @@ impl Lower128Bit {
|
||||||
};
|
};
|
||||||
|
|
||||||
let bin_statement = block.statements.pop().unwrap();
|
let bin_statement = block.statements.pop().unwrap();
|
||||||
let (source_info, lvalue, lhs, mut rhs) = match bin_statement {
|
let (source_info, place, lhs, mut rhs) = match bin_statement {
|
||||||
Statement {
|
Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Assign(
|
kind: StatementKind::Assign(
|
||||||
lvalue,
|
place,
|
||||||
Rvalue::BinaryOp(_, lhs, rhs))
|
Rvalue::BinaryOp(_, lhs, rhs))
|
||||||
} => (source_info, lvalue, lhs, rhs),
|
} => (source_info, place, lhs, rhs),
|
||||||
Statement {
|
Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Assign(
|
kind: StatementKind::Assign(
|
||||||
lvalue,
|
place,
|
||||||
Rvalue::CheckedBinaryOp(_, lhs, rhs))
|
Rvalue::CheckedBinaryOp(_, lhs, rhs))
|
||||||
} => (source_info, lvalue, lhs, rhs),
|
} => (source_info, place, lhs, rhs),
|
||||||
_ => bug!("Statement doesn't match pattern any more?"),
|
_ => bug!("Statement doesn't match pattern any more?"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ impl Lower128Bit {
|
||||||
}
|
}
|
||||||
|
|
||||||
let call_did = check_lang_item_type(
|
let call_did = check_lang_item_type(
|
||||||
lang_item, &lvalue, &lhs, &rhs, local_decls, tcx);
|
lang_item, &place, &lhs, &rhs, local_decls, tcx);
|
||||||
|
|
||||||
let bb = BasicBlock::new(cur_len + new_blocks.len());
|
let bb = BasicBlock::new(cur_len + new_blocks.len());
|
||||||
new_blocks.push(after_call);
|
new_blocks.push(after_call);
|
||||||
|
@ -121,7 +121,7 @@ impl Lower128Bit {
|
||||||
func: Operand::function_handle(tcx, call_did,
|
func: Operand::function_handle(tcx, call_did,
|
||||||
Slice::empty(), source_info.span),
|
Slice::empty(), source_info.span),
|
||||||
args: vec![lhs, rhs],
|
args: vec![lhs, rhs],
|
||||||
destination: Some((lvalue, bb)),
|
destination: Some((place, bb)),
|
||||||
cleanup: None,
|
cleanup: None,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -134,7 +134,7 @@ impl Lower128Bit {
|
||||||
|
|
||||||
fn check_lang_item_type<'a, 'tcx, D>(
|
fn check_lang_item_type<'a, 'tcx, D>(
|
||||||
lang_item: LangItem,
|
lang_item: LangItem,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
lhs: &Operand<'tcx>,
|
lhs: &Operand<'tcx>,
|
||||||
rhs: &Operand<'tcx>,
|
rhs: &Operand<'tcx>,
|
||||||
local_decls: &D,
|
local_decls: &D,
|
||||||
|
@ -147,8 +147,8 @@ fn check_lang_item_type<'a, 'tcx, D>(
|
||||||
let sig = tcx.no_late_bound_regions(&poly_sig).unwrap();
|
let sig = tcx.no_late_bound_regions(&poly_sig).unwrap();
|
||||||
let lhs_ty = lhs.ty(local_decls, tcx);
|
let lhs_ty = lhs.ty(local_decls, tcx);
|
||||||
let rhs_ty = rhs.ty(local_decls, tcx);
|
let rhs_ty = rhs.ty(local_decls, tcx);
|
||||||
let lvalue_ty = lvalue.ty(local_decls, tcx).to_ty(tcx);
|
let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
|
||||||
let expected = [lhs_ty, rhs_ty, lvalue_ty];
|
let expected = [lhs_ty, rhs_ty, place_ty];
|
||||||
assert_eq!(sig.inputs_and_output[..], expected,
|
assert_eq!(sig.inputs_and_output[..], expected,
|
||||||
"lang item {}", tcx.def_symbol_name(did));
|
"lang item {}", tcx.def_symbol_name(did));
|
||||||
did
|
did
|
||||||
|
|
|
@ -189,9 +189,9 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
location: Location,
|
location: Location,
|
||||||
borrow_region: ty::Region<'tcx>,
|
borrow_region: ty::Region<'tcx>,
|
||||||
borrowed_lv: &Place<'tcx>,
|
borrowed_place: &Place<'tcx>,
|
||||||
) {
|
) {
|
||||||
if let Projection(ref proj) = *borrowed_lv {
|
if let Projection(ref proj) = *borrowed_place {
|
||||||
let PlaceProjection { ref base, ref elem } = **proj;
|
let PlaceProjection { ref base, ref elem } = **proj;
|
||||||
|
|
||||||
if let ProjectionElem::Deref = *elem {
|
if let ProjectionElem::Deref = *elem {
|
||||||
|
@ -232,8 +232,8 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
|
||||||
// where L is the path that is borrowed. In that case, we have
|
// where L is the path that is borrowed. In that case, we have
|
||||||
// to add the reborrow constraints (which don't fall out
|
// to add the reborrow constraints (which don't fall out
|
||||||
// naturally from the type-checker).
|
// naturally from the type-checker).
|
||||||
if let Rvalue::Ref(region, _bk, ref borrowed_lv) = *rvalue {
|
if let Rvalue::Ref(region, _bk, ref borrowed_place) = *rvalue {
|
||||||
self.add_reborrow_constraint(location, region, borrowed_lv);
|
self.add_reborrow_constraint(location, region, borrowed_place);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.super_rvalue(rvalue, location);
|
self.super_rvalue(rvalue, location);
|
||||||
|
|
|
@ -316,7 +316,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
statement_index: usize::MAX
|
statement_index: usize::MAX
|
||||||
});
|
});
|
||||||
|
|
||||||
self.assign(RETURN_POINTER, rvalue, span);
|
self.assign(RETURN_PLACE, rvalue, span);
|
||||||
self.source.promoted.push(self.promoted);
|
self.source.promoted.push(self.promoted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,8 +373,8 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Declare return pointer local
|
// Declare return place local
|
||||||
let initial_locals = iter::once(LocalDecl::new_return_pointer(ty, span))
|
let initial_locals = iter::once(LocalDecl::new_return_place(ty, span))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut promoter = Promoter {
|
let mut promoter = Promoter {
|
||||||
|
|
|
@ -51,7 +51,7 @@ bitflags! {
|
||||||
// Function argument.
|
// Function argument.
|
||||||
const FN_ARGUMENT = 1 << 2;
|
const FN_ARGUMENT = 1 << 2;
|
||||||
|
|
||||||
// Static lvalue or move from a static.
|
// Static place or move from a static.
|
||||||
const STATIC = 1 << 3;
|
const STATIC = 1 << 3;
|
||||||
|
|
||||||
// Reference to a static.
|
// Reference to a static.
|
||||||
|
@ -261,7 +261,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||||
store(&mut self.temp_qualif[index])
|
store(&mut self.temp_qualif[index])
|
||||||
}
|
}
|
||||||
Place::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);
|
debug!("store to return place {:?}", index);
|
||||||
store(&mut self.return_qualif)
|
store(&mut self.return_qualif)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||||
// This must be an explicit assignment.
|
// This must be an explicit assignment.
|
||||||
_ => {
|
_ => {
|
||||||
// Catch more errors in the destination.
|
// Catch more errors in the destination.
|
||||||
self.visit_lvalue(dest, PlaceContext::Store, location);
|
self.visit_place(dest, PlaceContext::Store, location);
|
||||||
self.statement_like();
|
self.statement_like();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -438,11 +438,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lvalue(&mut self,
|
fn visit_place(&mut self,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
match *lvalue {
|
match *place {
|
||||||
Place::Local(ref local) => self.visit_local(local, context, location),
|
Place::Local(ref local) => self.visit_local(local, context, location),
|
||||||
Place::Static(ref global) => {
|
Place::Static(ref global) => {
|
||||||
self.add(Qualif::STATIC);
|
self.add(Qualif::STATIC);
|
||||||
|
@ -467,7 +467,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||||
}
|
}
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
self.nest(|this| {
|
self.nest(|this| {
|
||||||
this.super_lvalue(lvalue, context, location);
|
this.super_place(place, context, location);
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
ProjectionElem::Deref => {
|
ProjectionElem::Deref => {
|
||||||
if !this.try_consume() {
|
if !this.try_consume() {
|
||||||
|
@ -502,7 +502,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||||
"cannot refer to the interior of another \
|
"cannot refer to the interior of another \
|
||||||
static, use a constant instead");
|
static, use a constant instead");
|
||||||
}
|
}
|
||||||
let ty = lvalue.ty(this.mir, this.tcx).to_ty(this.tcx);
|
let ty = place.ty(this.mir, this.tcx).to_ty(this.tcx);
|
||||||
this.qualif.restrict(ty, this.tcx, this.param_env);
|
this.qualif.restrict(ty, this.tcx, this.param_env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,15 +519,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||||
|
|
||||||
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
|
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
|
||||||
match *operand {
|
match *operand {
|
||||||
Operand::Copy(ref lvalue) |
|
Operand::Copy(ref place) |
|
||||||
Operand::Move(ref lvalue) => {
|
Operand::Move(ref place) => {
|
||||||
self.nest(|this| {
|
self.nest(|this| {
|
||||||
this.super_operand(operand, location);
|
this.super_operand(operand, location);
|
||||||
this.try_consume();
|
this.try_consume();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mark the consumed locals to indicate later drops are noops.
|
// Mark the consumed locals to indicate later drops are noops.
|
||||||
if let Place::Local(local) = *lvalue {
|
if let Place::Local(local) = *place {
|
||||||
self.local_needs_drop[local] = None;
|
self.local_needs_drop[local] = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -555,7 +555,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
|
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||||
// Recurse through operands and lvalues.
|
// Recurse through operands and places.
|
||||||
self.super_rvalue(rvalue, location);
|
self.super_rvalue(rvalue, location);
|
||||||
|
|
||||||
match *rvalue {
|
match *rvalue {
|
||||||
|
@ -572,20 +572,20 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||||
Rvalue::Discriminant(..) => {}
|
Rvalue::Discriminant(..) => {}
|
||||||
|
|
||||||
Rvalue::Len(_) => {
|
Rvalue::Len(_) => {
|
||||||
// Static lvalues in consts would have errored already,
|
// Static places in consts would have errored already,
|
||||||
// don't treat length checks as reads from statics.
|
// don't treat length checks as reads from statics.
|
||||||
self.qualif = self.qualif - Qualif::STATIC;
|
self.qualif = self.qualif - Qualif::STATIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Ref(_, kind, ref lvalue) => {
|
Rvalue::Ref(_, kind, ref place) => {
|
||||||
// Static lvalues in consts would have errored already,
|
// Static places in consts would have errored already,
|
||||||
// only keep track of references to them here.
|
// only keep track of references to them here.
|
||||||
if self.qualif.intersects(Qualif::STATIC) {
|
if self.qualif.intersects(Qualif::STATIC) {
|
||||||
self.qualif = self.qualif - Qualif::STATIC;
|
self.qualif = self.qualif - Qualif::STATIC;
|
||||||
self.add(Qualif::STATIC_REF);
|
self.add(Qualif::STATIC_REF);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
|
let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||||
if kind == BorrowKind::Mut {
|
if kind == BorrowKind::Mut {
|
||||||
// In theory, any zero-sized value could be borrowed
|
// In theory, any zero-sized value could be borrowed
|
||||||
// mutably without consequences. However, only &mut []
|
// mutably without consequences. However, only &mut []
|
||||||
|
@ -635,7 +635,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||||
let candidate = Candidate::Ref(location);
|
let candidate = Candidate::Ref(location);
|
||||||
if !self.qualif.intersects(Qualif::NEVER_PROMOTE) {
|
if !self.qualif.intersects(Qualif::NEVER_PROMOTE) {
|
||||||
// We can only promote direct borrows of temps.
|
// We can only promote direct borrows of temps.
|
||||||
if let Place::Local(local) = *lvalue {
|
if let Place::Local(local) = *place {
|
||||||
if self.mir.local_kind(local) == LocalKind::Temp {
|
if self.mir.local_kind(local) == LocalKind::Temp {
|
||||||
self.promotion_candidates.push(candidate);
|
self.promotion_candidates.push(candidate);
|
||||||
}
|
}
|
||||||
|
@ -829,14 +829,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||||
}
|
}
|
||||||
self.assign(dest, location);
|
self.assign(dest, location);
|
||||||
}
|
}
|
||||||
} else if let TerminatorKind::Drop { location: ref lvalue, .. } = *kind {
|
} else if let TerminatorKind::Drop { location: ref place, .. } = *kind {
|
||||||
self.super_terminator_kind(bb, kind, location);
|
self.super_terminator_kind(bb, kind, location);
|
||||||
|
|
||||||
// Deny *any* live drops anywhere other than functions.
|
// Deny *any* live drops anywhere other than functions.
|
||||||
if self.mode != Mode::Fn {
|
if self.mode != Mode::Fn {
|
||||||
// HACK(eddyb) Emulate a bit of dataflow analysis,
|
// HACK(eddyb) Emulate a bit of dataflow analysis,
|
||||||
// conservatively, that drop elaboration will do.
|
// conservatively, that drop elaboration will do.
|
||||||
let needs_drop = if let Place::Local(local) = *lvalue {
|
let needs_drop = if let Place::Local(local) = *place {
|
||||||
self.local_needs_drop[local]
|
self.local_needs_drop[local]
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -844,7 +844,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||||
|
|
||||||
if let Some(span) = needs_drop {
|
if let Some(span) = needs_drop {
|
||||||
// Double-check the type being dropped, to minimize false positives.
|
// Double-check the type being dropped, to minimize false positives.
|
||||||
let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
|
let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||||
if ty.needs_drop(self.tcx, self.param_env) {
|
if ty.needs_drop(self.tcx, self.param_env) {
|
||||||
struct_span_err!(self.tcx.sess, span, E0493,
|
struct_span_err!(self.tcx.sess, span, E0493,
|
||||||
"destructors cannot be evaluated at compile-time")
|
"destructors cannot be evaluated at compile-time")
|
||||||
|
@ -905,8 +905,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||||
self.nest(|this| {
|
self.nest(|this| {
|
||||||
this.visit_source_info(&statement.source_info);
|
this.visit_source_info(&statement.source_info);
|
||||||
match statement.kind {
|
match statement.kind {
|
||||||
StatementKind::Assign(ref lvalue, ref rvalue) => {
|
StatementKind::Assign(ref place, ref rvalue) => {
|
||||||
this.visit_assign(bb, lvalue, rvalue, location);
|
this.visit_assign(bb, place, rvalue, location);
|
||||||
}
|
}
|
||||||
StatementKind::SetDiscriminant { .. } |
|
StatementKind::SetDiscriminant { .. } |
|
||||||
StatementKind::StorageLive(_) |
|
StatementKind::StorageLive(_) |
|
||||||
|
|
|
@ -123,13 +123,13 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
assert!(args.len() == 1);
|
assert!(args.len() == 1);
|
||||||
let peek_arg_lval = match args[0] {
|
let peek_arg_place = match args[0] {
|
||||||
mir::Operand::Copy(ref lval @ mir::Place::Local(_)) |
|
mir::Operand::Copy(ref place @ mir::Place::Local(_)) |
|
||||||
mir::Operand::Move(ref lval @ mir::Place::Local(_)) => Some(lval),
|
mir::Operand::Move(ref place @ mir::Place::Local(_)) => Some(place),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let peek_arg_lval = match peek_arg_lval {
|
let peek_arg_place = match peek_arg_place {
|
||||||
Some(arg) => arg,
|
Some(arg) => arg,
|
||||||
None => {
|
None => {
|
||||||
tcx.sess.diagnostic().span_err(
|
tcx.sess.diagnostic().span_err(
|
||||||
|
@ -143,8 +143,8 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let mut kill = results.0.sets.kill_set_for(bb.index()).to_owned();
|
let mut kill = results.0.sets.kill_set_for(bb.index()).to_owned();
|
||||||
|
|
||||||
// Emulate effect of all statements in the block up to (but not
|
// Emulate effect of all statements in the block up to (but not
|
||||||
// including) the borrow within `peek_arg_lval`. Do *not* include
|
// including) the borrow within `peek_arg_place`. Do *not* include
|
||||||
// call to `peek_arg_lval` itself (since we are peeking the state
|
// call to `peek_arg_place` itself (since we are peeking the state
|
||||||
// of the argument at time immediate preceding Call to
|
// of the argument at time immediate preceding Call to
|
||||||
// `rustc_peek`).
|
// `rustc_peek`).
|
||||||
|
|
||||||
|
@ -154,9 +154,9 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
for (j, stmt) in statements.iter().enumerate() {
|
for (j, stmt) in statements.iter().enumerate() {
|
||||||
debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt);
|
debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt);
|
||||||
let (lvalue, rvalue) = match stmt.kind {
|
let (place, rvalue) = match stmt.kind {
|
||||||
mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
|
mir::StatementKind::Assign(ref place, ref rvalue) => {
|
||||||
(lvalue, rvalue)
|
(place, rvalue)
|
||||||
}
|
}
|
||||||
mir::StatementKind::StorageLive(_) |
|
mir::StatementKind::StorageLive(_) |
|
||||||
mir::StatementKind::StorageDead(_) |
|
mir::StatementKind::StorageDead(_) |
|
||||||
|
@ -169,14 +169,14 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
"sanity_check should run before Deaggregator inserts SetDiscriminant"),
|
"sanity_check should run before Deaggregator inserts SetDiscriminant"),
|
||||||
};
|
};
|
||||||
|
|
||||||
if lvalue == peek_arg_lval {
|
if place == peek_arg_place {
|
||||||
if let mir::Rvalue::Ref(_, mir::BorrowKind::Shared, ref peeking_at_lval) = *rvalue {
|
if let mir::Rvalue::Ref(_, mir::BorrowKind::Shared, ref peeking_at_place) = *rvalue {
|
||||||
// Okay, our search is over.
|
// Okay, our search is over.
|
||||||
match move_data.rev_lookup.find(peeking_at_lval) {
|
match move_data.rev_lookup.find(peeking_at_place) {
|
||||||
LookupResult::Exact(peek_mpi) => {
|
LookupResult::Exact(peek_mpi) => {
|
||||||
let bit_state = sets.on_entry.contains(&peek_mpi);
|
let bit_state = sets.on_entry.contains(&peek_mpi);
|
||||||
debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
|
debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
|
||||||
lvalue, peeking_at_lval, bit_state);
|
place, peeking_at_place, bit_state);
|
||||||
if !bit_state {
|
if !bit_state {
|
||||||
tcx.sess.span_err(span, "rustc_peek: bit not set");
|
tcx.sess.span_err(span, "rustc_peek: bit not set");
|
||||||
}
|
}
|
||||||
|
@ -196,10 +196,10 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let lhs_mpi = move_data.rev_lookup.find(lvalue);
|
let lhs_mpi = move_data.rev_lookup.find(place);
|
||||||
|
|
||||||
debug!("rustc_peek: computing effect on lvalue: {:?} ({:?}) in stmt: {:?}",
|
debug!("rustc_peek: computing effect on place: {:?} ({:?}) in stmt: {:?}",
|
||||||
lvalue, lhs_mpi, stmt);
|
place, lhs_mpi, stmt);
|
||||||
// reset GEN and KILL sets before emulating their effect.
|
// reset GEN and KILL sets before emulating their effect.
|
||||||
for e in sets.gen_set.words_mut() { *e = 0; }
|
for e in sets.gen_set.words_mut() { *e = 0; }
|
||||||
for e in sets.kill_set.words_mut() { *e = 0; }
|
for e in sets.kill_set.words_mut() { *e = 0; }
|
||||||
|
|
|
@ -104,13 +104,13 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lvalue(
|
fn visit_place(
|
||||||
&mut self,
|
&mut self,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
context: PlaceContext,
|
context: PlaceContext,
|
||||||
location: Location,
|
location: Location,
|
||||||
) {
|
) {
|
||||||
self.sanitize_lvalue(lvalue, location, context);
|
self.sanitize_place(place, location, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
|
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
|
||||||
|
@ -164,18 +164,18 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sanitize_lvalue(&mut self,
|
fn sanitize_place(&mut self,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
location: Location,
|
location: Location,
|
||||||
context: PlaceContext)
|
context: PlaceContext)
|
||||||
-> PlaceTy<'tcx> {
|
-> PlaceTy<'tcx> {
|
||||||
debug!("sanitize_lvalue: {:?}", lvalue);
|
debug!("sanitize_place: {:?}", place);
|
||||||
let lvalue_ty = match *lvalue {
|
let place_ty = match *place {
|
||||||
Place::Local(index) => PlaceTy::Ty {
|
Place::Local(index) => PlaceTy::Ty {
|
||||||
ty: self.mir.local_decls[index].ty,
|
ty: self.mir.local_decls[index].ty,
|
||||||
},
|
},
|
||||||
Place::Static(box Static { def_id, ty: sty }) => {
|
Place::Static(box Static { def_id, ty: sty }) => {
|
||||||
let sty = self.sanitize_type(lvalue, sty);
|
let sty = self.sanitize_type(place, sty);
|
||||||
let ty = self.tcx().type_of(def_id);
|
let ty = self.tcx().type_of(def_id);
|
||||||
let ty = self.cx.normalize(&ty, location);
|
let ty = self.cx.normalize(&ty, location);
|
||||||
if let Err(terr) = self.cx
|
if let Err(terr) = self.cx
|
||||||
|
@ -183,7 +183,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
{
|
{
|
||||||
span_mirbug!(
|
span_mirbug!(
|
||||||
self,
|
self,
|
||||||
lvalue,
|
place,
|
||||||
"bad static type ({:?}: {:?}): {:?}",
|
"bad static type ({:?}: {:?}): {:?}",
|
||||||
ty,
|
ty,
|
||||||
sty,
|
sty,
|
||||||
|
@ -198,7 +198,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
PlaceContext::Projection(Mutability::Not)
|
PlaceContext::Projection(Mutability::Not)
|
||||||
};
|
};
|
||||||
let base_ty = self.sanitize_lvalue(&proj.base, location, base_context);
|
let base_ty = self.sanitize_place(&proj.base, location, base_context);
|
||||||
if let PlaceTy::Ty { ty } = base_ty {
|
if let PlaceTy::Ty { ty } = base_ty {
|
||||||
if ty.references_error() {
|
if ty.references_error() {
|
||||||
assert!(self.errors_reported);
|
assert!(self.errors_reported);
|
||||||
|
@ -207,27 +207,27 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.sanitize_projection(base_ty, &proj.elem, lvalue, location)
|
self.sanitize_projection(base_ty, &proj.elem, place, location)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let PlaceContext::Copy = context {
|
if let PlaceContext::Copy = context {
|
||||||
let ty = lvalue_ty.to_ty(self.tcx());
|
let ty = place_ty.to_ty(self.tcx());
|
||||||
if self.cx.infcx.type_moves_by_default(self.cx.param_env, ty, DUMMY_SP) {
|
if self.cx.infcx.type_moves_by_default(self.cx.param_env, ty, DUMMY_SP) {
|
||||||
span_mirbug!(self, lvalue,
|
span_mirbug!(self, place,
|
||||||
"attempted copy of non-Copy type ({:?})", ty);
|
"attempted copy of non-Copy type ({:?})", ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lvalue_ty
|
place_ty
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sanitize_projection(
|
fn sanitize_projection(
|
||||||
&mut self,
|
&mut self,
|
||||||
base: PlaceTy<'tcx>,
|
base: PlaceTy<'tcx>,
|
||||||
pi: &PlaceElem<'tcx>,
|
pi: &PlaceElem<'tcx>,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
location: Location,
|
location: Location,
|
||||||
) -> PlaceTy<'tcx> {
|
) -> PlaceTy<'tcx> {
|
||||||
debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, lvalue);
|
debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let base_ty = base.to_ty(tcx);
|
let base_ty = base.to_ty(tcx);
|
||||||
let span = self.last_span;
|
let span = self.last_span;
|
||||||
|
@ -236,7 +236,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
let deref_ty = base_ty.builtin_deref(true, ty::LvaluePreference::NoPreference);
|
let deref_ty = base_ty.builtin_deref(true, ty::LvaluePreference::NoPreference);
|
||||||
PlaceTy::Ty {
|
PlaceTy::Ty {
|
||||||
ty: deref_ty.map(|t| t.ty).unwrap_or_else(|| {
|
ty: deref_ty.map(|t| t.ty).unwrap_or_else(|| {
|
||||||
span_mirbug_and_err!(self, lvalue, "deref of non-pointer {:?}", base_ty)
|
span_mirbug_and_err!(self, place, "deref of non-pointer {:?}", base_ty)
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
PlaceTy::Ty {
|
PlaceTy::Ty {
|
||||||
ty: base_ty.builtin_index().unwrap_or_else(|| {
|
ty: base_ty.builtin_index().unwrap_or_else(|| {
|
||||||
span_mirbug_and_err!(self, lvalue, "index of non-array {:?}", base_ty)
|
span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
// consider verifying in-bounds
|
// consider verifying in-bounds
|
||||||
PlaceTy::Ty {
|
PlaceTy::Ty {
|
||||||
ty: base_ty.builtin_index().unwrap_or_else(|| {
|
ty: base_ty.builtin_index().unwrap_or_else(|| {
|
||||||
span_mirbug_and_err!(self, lvalue, "index of non-array {:?}", base_ty)
|
span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,14 +272,14 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
span_mirbug_and_err!(
|
span_mirbug_and_err!(
|
||||||
self,
|
self,
|
||||||
lvalue,
|
place,
|
||||||
"taking too-small slice of {:?}",
|
"taking too-small slice of {:?}",
|
||||||
base_ty
|
base_ty
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::TySlice(..) => base_ty,
|
ty::TySlice(..) => base_ty,
|
||||||
_ => span_mirbug_and_err!(self, lvalue, "slice of non-array {:?}", base_ty),
|
_ => span_mirbug_and_err!(self, place, "slice of non-array {:?}", base_ty),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty {
|
ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty {
|
||||||
|
@ -288,7 +288,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
PlaceTy::Ty {
|
PlaceTy::Ty {
|
||||||
ty: span_mirbug_and_err!(
|
ty: span_mirbug_and_err!(
|
||||||
self,
|
self,
|
||||||
lvalue,
|
place,
|
||||||
"cast to variant #{:?} but enum only has {:?}",
|
"cast to variant #{:?} but enum only has {:?}",
|
||||||
index,
|
index,
|
||||||
adt_def.variants.len()
|
adt_def.variants.len()
|
||||||
|
@ -305,7 +305,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
_ => PlaceTy::Ty {
|
_ => PlaceTy::Ty {
|
||||||
ty: span_mirbug_and_err!(
|
ty: span_mirbug_and_err!(
|
||||||
self,
|
self,
|
||||||
lvalue,
|
place,
|
||||||
"can't downcast {:?} as {:?}",
|
"can't downcast {:?} as {:?}",
|
||||||
base_ty,
|
base_ty,
|
||||||
adt_def1
|
adt_def1
|
||||||
|
@ -313,13 +313,13 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ProjectionElem::Field(field, fty) => {
|
ProjectionElem::Field(field, fty) => {
|
||||||
let fty = self.sanitize_type(lvalue, fty);
|
let fty = self.sanitize_type(place, fty);
|
||||||
match self.field_ty(lvalue, base, field, location) {
|
match self.field_ty(place, base, field, location) {
|
||||||
Ok(ty) => {
|
Ok(ty) => {
|
||||||
if let Err(terr) = self.cx.eq_types(span, ty, fty, location.at_self()) {
|
if let Err(terr) = self.cx.eq_types(span, ty, fty, location.at_self()) {
|
||||||
span_mirbug!(
|
span_mirbug!(
|
||||||
self,
|
self,
|
||||||
lvalue,
|
place,
|
||||||
"bad field access ({:?}: {:?}): {:?}",
|
"bad field access ({:?}: {:?}): {:?}",
|
||||||
ty,
|
ty,
|
||||||
fty,
|
fty,
|
||||||
|
@ -329,7 +329,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
Err(FieldAccessError::OutOfRange { field_count }) => span_mirbug!(
|
Err(FieldAccessError::OutOfRange { field_count }) => span_mirbug!(
|
||||||
self,
|
self,
|
||||||
lvalue,
|
place,
|
||||||
"accessed field #{} but variant only has {}",
|
"accessed field #{} but variant only has {}",
|
||||||
field.index(),
|
field.index(),
|
||||||
field_count
|
field_count
|
||||||
|
@ -551,17 +551,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
debug!("check_stmt: {:?}", stmt);
|
debug!("check_stmt: {:?}", stmt);
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
match stmt.kind {
|
match stmt.kind {
|
||||||
StatementKind::Assign(ref lv, ref rv) => {
|
StatementKind::Assign(ref place, ref rv) => {
|
||||||
let lv_ty = lv.ty(mir, tcx).to_ty(tcx);
|
let place_ty = place.ty(mir, tcx).to_ty(tcx);
|
||||||
let rv_ty = rv.ty(mir, tcx);
|
let rv_ty = rv.ty(mir, tcx);
|
||||||
if let Err(terr) =
|
if let Err(terr) =
|
||||||
self.sub_types(rv_ty, lv_ty, location.at_successor_within_block())
|
self.sub_types(rv_ty, place_ty, location.at_successor_within_block())
|
||||||
{
|
{
|
||||||
span_mirbug!(
|
span_mirbug!(
|
||||||
self,
|
self,
|
||||||
stmt,
|
stmt,
|
||||||
"bad assignment ({:?} = {:?}): {:?}",
|
"bad assignment ({:?} = {:?}): {:?}",
|
||||||
lv_ty,
|
place_ty,
|
||||||
rv_ty,
|
rv_ty,
|
||||||
terr
|
terr
|
||||||
);
|
);
|
||||||
|
@ -569,17 +569,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
self.check_rvalue(mir, rv, location);
|
self.check_rvalue(mir, rv, location);
|
||||||
}
|
}
|
||||||
StatementKind::SetDiscriminant {
|
StatementKind::SetDiscriminant {
|
||||||
ref lvalue,
|
ref place,
|
||||||
variant_index,
|
variant_index,
|
||||||
} => {
|
} => {
|
||||||
let lvalue_type = lvalue.ty(mir, tcx).to_ty(tcx);
|
let place_type = place.ty(mir, tcx).to_ty(tcx);
|
||||||
let adt = match lvalue_type.sty {
|
let adt = match place_type.sty {
|
||||||
TypeVariants::TyAdt(adt, _) if adt.is_enum() => adt,
|
TypeVariants::TyAdt(adt, _) if adt.is_enum() => adt,
|
||||||
_ => {
|
_ => {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
stmt.source_info.span,
|
stmt.source_info.span,
|
||||||
"bad set discriminant ({:?} = {:?}): lhs is not an enum",
|
"bad set discriminant ({:?} = {:?}): lhs is not an enum",
|
||||||
lvalue,
|
place,
|
||||||
variant_index
|
variant_index
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -588,7 +588,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
stmt.source_info.span,
|
stmt.source_info.span,
|
||||||
"bad set discriminant ({:?} = {:?}): value of of range",
|
"bad set discriminant ({:?} = {:?}): value of of range",
|
||||||
lvalue,
|
place,
|
||||||
variant_index
|
variant_index
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -627,19 +627,19 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
target,
|
target,
|
||||||
unwind,
|
unwind,
|
||||||
} => {
|
} => {
|
||||||
let lv_ty = location.ty(mir, tcx).to_ty(tcx);
|
let place_ty = location.ty(mir, tcx).to_ty(tcx);
|
||||||
let rv_ty = value.ty(mir, tcx);
|
let rv_ty = value.ty(mir, tcx);
|
||||||
|
|
||||||
let locations = Locations {
|
let locations = Locations {
|
||||||
from_location: term_location,
|
from_location: term_location,
|
||||||
at_location: target.start_location(),
|
at_location: target.start_location(),
|
||||||
};
|
};
|
||||||
if let Err(terr) = self.sub_types(rv_ty, lv_ty, locations) {
|
if let Err(terr) = self.sub_types(rv_ty, place_ty, locations) {
|
||||||
span_mirbug!(
|
span_mirbug!(
|
||||||
self,
|
self,
|
||||||
term,
|
term,
|
||||||
"bad DropAndReplace ({:?} = {:?}): {:?}",
|
"bad DropAndReplace ({:?} = {:?}): {:?}",
|
||||||
lv_ty,
|
place_ty,
|
||||||
rv_ty,
|
rv_ty,
|
||||||
terr
|
terr
|
||||||
);
|
);
|
||||||
|
@ -653,12 +653,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
from_location: term_location,
|
from_location: term_location,
|
||||||
at_location: unwind.start_location(),
|
at_location: unwind.start_location(),
|
||||||
};
|
};
|
||||||
if let Err(terr) = self.sub_types(rv_ty, lv_ty, locations) {
|
if let Err(terr) = self.sub_types(rv_ty, place_ty, locations) {
|
||||||
span_mirbug!(
|
span_mirbug!(
|
||||||
self,
|
self,
|
||||||
term,
|
term,
|
||||||
"bad DropAndReplace ({:?} = {:?}): {:?}",
|
"bad DropAndReplace ({:?} = {:?}): {:?}",
|
||||||
lv_ty,
|
place_ty,
|
||||||
rv_ty,
|
rv_ty,
|
||||||
terr
|
terr
|
||||||
);
|
);
|
||||||
|
@ -1209,8 +1209,8 @@ trait AtLocation {
|
||||||
/// its successor within the block is the at-location. This means
|
/// its successor within the block is the at-location. This means
|
||||||
/// that any required region relationships must hold only upon
|
/// that any required region relationships must hold only upon
|
||||||
/// **exiting** the statement/terminator indicated by `self`. This
|
/// **exiting** the statement/terminator indicated by `self`. This
|
||||||
/// is for example used when you have a `lv = rv` statement: it
|
/// is for example used when you have a `place = rv` statement: it
|
||||||
/// indicates that the `typeof(rv) <: typeof(lv)` as of the
|
/// indicates that the `typeof(rv) <: typeof(place)` as of the
|
||||||
/// **next** statement.
|
/// **next** statement.
|
||||||
fn at_successor_within_block(self) -> Locations;
|
fn at_successor_within_block(self) -> Locations;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,32 +12,32 @@
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
|
|
||||||
/// Return `true` if this lvalue is allowed to be less aligned
|
/// Return `true` if this place is allowed to be less aligned
|
||||||
/// than its containing struct (because it is within a packed
|
/// than its containing struct (because it is within a packed
|
||||||
/// struct).
|
/// struct).
|
||||||
pub fn is_disaligned<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
pub fn is_disaligned<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
local_decls: &L,
|
local_decls: &L,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
lvalue: &Place<'tcx>)
|
place: &Place<'tcx>)
|
||||||
-> bool
|
-> bool
|
||||||
where L: HasLocalDecls<'tcx>
|
where L: HasLocalDecls<'tcx>
|
||||||
{
|
{
|
||||||
debug!("is_disaligned({:?})", lvalue);
|
debug!("is_disaligned({:?})", place);
|
||||||
if !is_within_packed(tcx, local_decls, lvalue) {
|
if !is_within_packed(tcx, local_decls, place) {
|
||||||
debug!("is_disaligned({:?}) - not within packed", lvalue);
|
debug!("is_disaligned({:?}) - not within packed", place);
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty = lvalue.ty(local_decls, tcx).to_ty(tcx);
|
let ty = place.ty(local_decls, tcx).to_ty(tcx);
|
||||||
match tcx.layout_raw(param_env.and(ty)) {
|
match tcx.layout_raw(param_env.and(ty)) {
|
||||||
Ok(layout) if layout.align.abi() == 1 => {
|
Ok(layout) if layout.align.abi() == 1 => {
|
||||||
// if the alignment is 1, the type can't be further
|
// if the alignment is 1, the type can't be further
|
||||||
// disaligned.
|
// disaligned.
|
||||||
debug!("is_disaligned({:?}) - align = 1", lvalue);
|
debug!("is_disaligned({:?}) - align = 1", place);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
debug!("is_disaligned({:?}) - true", lvalue);
|
debug!("is_disaligned({:?}) - true", place);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,14 +45,14 @@ pub fn is_disaligned<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
fn is_within_packed<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn is_within_packed<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
local_decls: &L,
|
local_decls: &L,
|
||||||
lvalue: &Place<'tcx>)
|
place: &Place<'tcx>)
|
||||||
-> bool
|
-> bool
|
||||||
where L: HasLocalDecls<'tcx>
|
where L: HasLocalDecls<'tcx>
|
||||||
{
|
{
|
||||||
let mut lvalue = lvalue;
|
let mut place = place;
|
||||||
while let &Place::Projection(box Projection {
|
while let &Place::Projection(box Projection {
|
||||||
ref base, ref elem
|
ref base, ref elem
|
||||||
}) = lvalue {
|
}) = place {
|
||||||
match *elem {
|
match *elem {
|
||||||
// encountered a Deref, which is ABI-aligned
|
// encountered a Deref, which is ABI-aligned
|
||||||
ProjectionElem::Deref => break,
|
ProjectionElem::Deref => break,
|
||||||
|
@ -67,7 +67,7 @@ fn is_within_packed<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
lvalue = base;
|
place = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
|
|
|
@ -64,10 +64,10 @@ impl<'tcx> DefUseAnalysis<'tcx> {
|
||||||
where F: for<'a> FnMut(&'a mut Local,
|
where F: for<'a> FnMut(&'a mut Local,
|
||||||
PlaceContext<'tcx>,
|
PlaceContext<'tcx>,
|
||||||
Location) {
|
Location) {
|
||||||
for lvalue_use in &self.info[local].defs_and_uses {
|
for place_use in &self.info[local].defs_and_uses {
|
||||||
MutateUseVisitor::new(local,
|
MutateUseVisitor::new(local,
|
||||||
&mut callback,
|
&mut callback,
|
||||||
mir).visit_location(mir, lvalue_use.location)
|
mir).visit_location(mir, place_use.location)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ impl<'tcx> Info<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def_count(&self) -> usize {
|
pub fn def_count(&self) -> usize {
|
||||||
self.defs_and_uses.iter().filter(|lvalue_use| lvalue_use.context.is_mutating_use()).count()
|
self.defs_and_uses.iter().filter(|place_use| place_use.context.is_mutating_use()).count()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def_count_not_including_drop(&self) -> usize {
|
pub fn def_count_not_including_drop(&self) -> usize {
|
||||||
|
@ -118,14 +118,14 @@ impl<'tcx> Info<'tcx> {
|
||||||
pub fn defs_not_including_drop(
|
pub fn defs_not_including_drop(
|
||||||
&self,
|
&self,
|
||||||
) -> iter::Filter<slice::Iter<Use<'tcx>>, fn(&&Use<'tcx>) -> bool> {
|
) -> iter::Filter<slice::Iter<Use<'tcx>>, fn(&&Use<'tcx>) -> bool> {
|
||||||
self.defs_and_uses.iter().filter(|lvalue_use| {
|
self.defs_and_uses.iter().filter(|place_use| {
|
||||||
lvalue_use.context.is_mutating_use() && !lvalue_use.context.is_drop()
|
place_use.context.is_mutating_use() && !place_use.context.is_drop()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn use_count(&self) -> usize {
|
pub fn use_count(&self) -> usize {
|
||||||
self.defs_and_uses.iter().filter(|lvalue_use| {
|
self.defs_and_uses.iter().filter(|place_use| {
|
||||||
lvalue_use.context.is_nonmutating_use()
|
place_use.context.is_nonmutating_use()
|
||||||
}).count()
|
}).count()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ struct DropCtxt<'l, 'b: 'l, 'tcx: 'b, D>
|
||||||
|
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
|
|
||||||
lvalue: &'l Place<'tcx>,
|
place: &'l Place<'tcx>,
|
||||||
path: D::Path,
|
path: D::Path,
|
||||||
succ: BasicBlock,
|
succ: BasicBlock,
|
||||||
unwind: Unwind,
|
unwind: Unwind,
|
||||||
|
@ -114,7 +114,7 @@ struct DropCtxt<'l, 'b: 'l, 'tcx: 'b, D>
|
||||||
pub fn elaborate_drop<'b, 'tcx, D>(
|
pub fn elaborate_drop<'b, 'tcx, D>(
|
||||||
elaborator: &mut D,
|
elaborator: &mut D,
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
path: D::Path,
|
path: D::Path,
|
||||||
succ: BasicBlock,
|
succ: BasicBlock,
|
||||||
unwind: Unwind,
|
unwind: Unwind,
|
||||||
|
@ -122,15 +122,15 @@ pub fn elaborate_drop<'b, 'tcx, D>(
|
||||||
where D: DropElaborator<'b, 'tcx>
|
where D: DropElaborator<'b, 'tcx>
|
||||||
{
|
{
|
||||||
DropCtxt {
|
DropCtxt {
|
||||||
elaborator, source_info, lvalue, path, succ, unwind
|
elaborator, source_info, place, path, succ, unwind
|
||||||
}.elaborate_drop(bb)
|
}.elaborate_drop(bb)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
where D: DropElaborator<'b, 'tcx>
|
where D: DropElaborator<'b, 'tcx>
|
||||||
{
|
{
|
||||||
fn lvalue_ty(&self, lvalue: &Place<'tcx>) -> Ty<'tcx> {
|
fn place_ty(&self, place: &Place<'tcx>) -> Ty<'tcx> {
|
||||||
lvalue.ty(self.elaborator.mir(), self.tcx()).to_ty(self.tcx())
|
place.ty(self.elaborator.mir(), self.tcx()).to_ty(self.tcx())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||||
|
@ -169,7 +169,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
let loc = self.terminator_loc(bb);
|
let loc = self.terminator_loc(bb);
|
||||||
self.elaborator.clear_drop_flag(loc, self.path, DropFlagMode::Deep);
|
self.elaborator.clear_drop_flag(loc, self.path, DropFlagMode::Deep);
|
||||||
self.elaborator.patch().patch_terminator(bb, TerminatorKind::Drop {
|
self.elaborator.patch().patch_terminator(bb, TerminatorKind::Drop {
|
||||||
location: self.lvalue.clone(),
|
location: self.place.clone(),
|
||||||
target: self.succ,
|
target: self.succ,
|
||||||
unwind: self.unwind.into_option(),
|
unwind: self.unwind.into_option(),
|
||||||
});
|
});
|
||||||
|
@ -191,10 +191,10 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the lvalue and move path for each field of `variant`,
|
/// Return the place and move path for each field of `variant`,
|
||||||
/// (the move path is `None` if the field is a rest field).
|
/// (the move path is `None` if the field is a rest field).
|
||||||
fn move_paths_for_fields(&self,
|
fn move_paths_for_fields(&self,
|
||||||
base_lv: &Place<'tcx>,
|
base_place: &Place<'tcx>,
|
||||||
variant_path: D::Path,
|
variant_path: D::Path,
|
||||||
variant: &'tcx ty::VariantDef,
|
variant: &'tcx ty::VariantDef,
|
||||||
substs: &'tcx Substs<'tcx>)
|
substs: &'tcx Substs<'tcx>)
|
||||||
|
@ -209,32 +209,32 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
&f.ty(self.tcx(), substs),
|
&f.ty(self.tcx(), substs),
|
||||||
self.elaborator.param_env()
|
self.elaborator.param_env()
|
||||||
);
|
);
|
||||||
(base_lv.clone().field(field, field_ty), subpath)
|
(base_place.clone().field(field, field_ty), subpath)
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drop_subpath(&mut self,
|
fn drop_subpath(&mut self,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
path: Option<D::Path>,
|
path: Option<D::Path>,
|
||||||
succ: BasicBlock,
|
succ: BasicBlock,
|
||||||
unwind: Unwind)
|
unwind: Unwind)
|
||||||
-> BasicBlock
|
-> BasicBlock
|
||||||
{
|
{
|
||||||
if let Some(path) = path {
|
if let Some(path) = path {
|
||||||
debug!("drop_subpath: for std field {:?}", lvalue);
|
debug!("drop_subpath: for std field {:?}", place);
|
||||||
|
|
||||||
DropCtxt {
|
DropCtxt {
|
||||||
elaborator: self.elaborator,
|
elaborator: self.elaborator,
|
||||||
source_info: self.source_info,
|
source_info: self.source_info,
|
||||||
path, lvalue, succ, unwind,
|
path, place, succ, unwind,
|
||||||
}.elaborated_drop_block()
|
}.elaborated_drop_block()
|
||||||
} else {
|
} else {
|
||||||
debug!("drop_subpath: for rest field {:?}", lvalue);
|
debug!("drop_subpath: for rest field {:?}", place);
|
||||||
|
|
||||||
DropCtxt {
|
DropCtxt {
|
||||||
elaborator: self.elaborator,
|
elaborator: self.elaborator,
|
||||||
source_info: self.source_info,
|
source_info: self.source_info,
|
||||||
lvalue, succ, unwind,
|
place, succ, unwind,
|
||||||
// Using `self.path` here to condition the drop on
|
// Using `self.path` here to condition the drop on
|
||||||
// our own drop flag.
|
// our own drop flag.
|
||||||
path: self.path
|
path: self.path
|
||||||
|
@ -256,8 +256,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
{
|
{
|
||||||
Some(succ).into_iter().chain(
|
Some(succ).into_iter().chain(
|
||||||
fields.iter().rev().zip(unwind_ladder)
|
fields.iter().rev().zip(unwind_ladder)
|
||||||
.map(|(&(ref lv, path), &unwind_succ)| {
|
.map(|(&(ref place, path), &unwind_succ)| {
|
||||||
succ = self.drop_subpath(lv, path, succ, unwind_succ);
|
succ = self.drop_subpath(place, path, succ, unwind_succ);
|
||||||
succ
|
succ
|
||||||
})
|
})
|
||||||
).collect()
|
).collect()
|
||||||
|
@ -302,8 +302,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
debug!("drop_ladder({:?}, {:?})", self, fields);
|
debug!("drop_ladder({:?}, {:?})", self, fields);
|
||||||
|
|
||||||
let mut fields = fields;
|
let mut fields = fields;
|
||||||
fields.retain(|&(ref lvalue, _)| {
|
fields.retain(|&(ref place, _)| {
|
||||||
self.lvalue_ty(lvalue).needs_drop(self.tcx(), self.elaborator.param_env())
|
self.place_ty(place).needs_drop(self.tcx(), self.elaborator.param_env())
|
||||||
});
|
});
|
||||||
|
|
||||||
debug!("drop_ladder - fields needing drop: {:?}", fields);
|
debug!("drop_ladder - fields needing drop: {:?}", fields);
|
||||||
|
@ -328,7 +328,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
debug!("open_drop_for_tuple({:?}, {:?})", self, tys);
|
debug!("open_drop_for_tuple({:?}, {:?})", self, tys);
|
||||||
|
|
||||||
let fields = tys.iter().enumerate().map(|(i, &ty)| {
|
let fields = tys.iter().enumerate().map(|(i, &ty)| {
|
||||||
(self.lvalue.clone().field(Field::new(i), ty),
|
(self.place.clone().field(Field::new(i), ty),
|
||||||
self.elaborator.field_subpath(self.path, Field::new(i)))
|
self.elaborator.field_subpath(self.path, Field::new(i)))
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
|
@ -340,7 +340,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
{
|
{
|
||||||
debug!("open_drop_for_box({:?}, {:?})", self, ty);
|
debug!("open_drop_for_box({:?}, {:?})", self, ty);
|
||||||
|
|
||||||
let interior = self.lvalue.clone().deref();
|
let interior = self.place.clone().deref();
|
||||||
let interior_path = self.elaborator.deref_subpath(self.path);
|
let interior_path = self.elaborator.deref_subpath(self.path);
|
||||||
|
|
||||||
let succ = self.succ; // FIXME(#6393)
|
let succ = self.succ; // FIXME(#6393)
|
||||||
|
@ -386,7 +386,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
let (succ, unwind) = self.drop_ladder_bottom();
|
let (succ, unwind) = self.drop_ladder_bottom();
|
||||||
if !adt.is_enum() {
|
if !adt.is_enum() {
|
||||||
let fields = self.move_paths_for_fields(
|
let fields = self.move_paths_for_fields(
|
||||||
self.lvalue,
|
self.place,
|
||||||
self.path,
|
self.path,
|
||||||
&adt.variants[0],
|
&adt.variants[0],
|
||||||
substs
|
substs
|
||||||
|
@ -416,11 +416,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
let subpath = self.elaborator.downcast_subpath(
|
let subpath = self.elaborator.downcast_subpath(
|
||||||
self.path, variant_index);
|
self.path, variant_index);
|
||||||
if let Some(variant_path) = subpath {
|
if let Some(variant_path) = subpath {
|
||||||
let base_lv = self.lvalue.clone().elem(
|
let base_place = self.place.clone().elem(
|
||||||
ProjectionElem::Downcast(adt, variant_index)
|
ProjectionElem::Downcast(adt, variant_index)
|
||||||
);
|
);
|
||||||
let fields = self.move_paths_for_fields(
|
let fields = self.move_paths_for_fields(
|
||||||
&base_lv,
|
&base_place,
|
||||||
variant_path,
|
variant_path,
|
||||||
&adt.variants[variant_index],
|
&adt.variants[variant_index],
|
||||||
substs);
|
substs);
|
||||||
|
@ -492,7 +492,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
// way lies only trouble.
|
// way lies only trouble.
|
||||||
let discr_ty = adt.repr.discr_type().to_ty(self.tcx());
|
let discr_ty = adt.repr.discr_type().to_ty(self.tcx());
|
||||||
let discr = Place::Local(self.new_temp(discr_ty));
|
let discr = Place::Local(self.new_temp(discr_ty));
|
||||||
let discr_rv = Rvalue::Discriminant(self.lvalue.clone());
|
let discr_rv = Rvalue::Discriminant(self.place.clone());
|
||||||
let switch_block = BasicBlockData {
|
let switch_block = BasicBlockData {
|
||||||
statements: vec![self.assign(&discr, discr_rv)],
|
statements: vec![self.assign(&discr, discr_rv)],
|
||||||
terminator: Some(Terminator {
|
terminator: Some(Terminator {
|
||||||
|
@ -517,26 +517,26 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let drop_trait = tcx.lang_items().drop_trait().unwrap();
|
let drop_trait = tcx.lang_items().drop_trait().unwrap();
|
||||||
let drop_fn = tcx.associated_items(drop_trait).next().unwrap();
|
let drop_fn = tcx.associated_items(drop_trait).next().unwrap();
|
||||||
let ty = self.lvalue_ty(self.lvalue);
|
let ty = self.place_ty(self.place);
|
||||||
let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
|
let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
|
||||||
|
|
||||||
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
|
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
|
||||||
ty,
|
ty,
|
||||||
mutbl: hir::Mutability::MutMutable
|
mutbl: hir::Mutability::MutMutable
|
||||||
});
|
});
|
||||||
let ref_lvalue = self.new_temp(ref_ty);
|
let ref_place = self.new_temp(ref_ty);
|
||||||
let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
|
let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
|
||||||
|
|
||||||
let result = BasicBlockData {
|
let result = BasicBlockData {
|
||||||
statements: vec![self.assign(
|
statements: vec![self.assign(
|
||||||
&Place::Local(ref_lvalue),
|
&Place::Local(ref_place),
|
||||||
Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, self.lvalue.clone())
|
Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, self.place.clone())
|
||||||
)],
|
)],
|
||||||
terminator: Some(Terminator {
|
terminator: Some(Terminator {
|
||||||
kind: TerminatorKind::Call {
|
kind: TerminatorKind::Call {
|
||||||
func: Operand::function_handle(tcx, drop_fn.def_id, substs,
|
func: Operand::function_handle(tcx, drop_fn.def_id, substs,
|
||||||
self.source_info.span),
|
self.source_info.span),
|
||||||
args: vec![Operand::Move(Place::Local(ref_lvalue))],
|
args: vec![Operand::Move(Place::Local(ref_place))],
|
||||||
destination: Some((unit_temp, succ)),
|
destination: Some((unit_temp, succ)),
|
||||||
cleanup: unwind.into_option(),
|
cleanup: unwind.into_option(),
|
||||||
},
|
},
|
||||||
|
@ -572,8 +572,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
ptr_based: bool)
|
ptr_based: bool)
|
||||||
-> BasicBlock
|
-> BasicBlock
|
||||||
{
|
{
|
||||||
let copy = |lv: &Place<'tcx>| Operand::Copy(lv.clone());
|
let copy = |place: &Place<'tcx>| Operand::Copy(place.clone());
|
||||||
let move_ = |lv: &Place<'tcx>| Operand::Move(lv.clone());
|
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
||||||
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
|
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
|
||||||
|
@ -591,7 +591,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
(Rvalue::Ref(
|
(Rvalue::Ref(
|
||||||
tcx.types.re_erased,
|
tcx.types.re_erased,
|
||||||
BorrowKind::Mut,
|
BorrowKind::Mut,
|
||||||
self.lvalue.clone().index(cur)),
|
self.place.clone().index(cur)),
|
||||||
Rvalue::BinaryOp(BinOp::Add, copy(&Place::Local(cur)), one))
|
Rvalue::BinaryOp(BinOp::Add, copy(&Place::Local(cur)), one))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -643,7 +643,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
|
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
||||||
let move_ = |lv: &Place<'tcx>| Operand::Move(lv.clone());
|
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
|
||||||
let size = &Place::Local(self.new_temp(tcx.types.usize));
|
let size = &Place::Local(self.new_temp(tcx.types.usize));
|
||||||
let size_is_zero = &Place::Local(self.new_temp(tcx.types.bool));
|
let size_is_zero = &Place::Local(self.new_temp(tcx.types.bool));
|
||||||
let base_block = BasicBlockData {
|
let base_block = BasicBlockData {
|
||||||
|
@ -667,7 +667,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
self.elaborator.patch().new_block(base_block)
|
self.elaborator.patch().new_block(base_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a pair of drop-loops of `lvalue`, which drops its contents
|
// create a pair of drop-loops of `place`, which drops its contents
|
||||||
// even in the case of 1 panic. If `ptr_based`, create a pointer loop,
|
// even in the case of 1 panic. If `ptr_based`, create a pointer loop,
|
||||||
// otherwise create an index loop.
|
// otherwise create an index loop.
|
||||||
fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock {
|
fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock {
|
||||||
|
@ -708,15 +708,15 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
let cur = Place::Local(cur);
|
let cur = Place::Local(cur);
|
||||||
let zero = self.constant_usize(0);
|
let zero = self.constant_usize(0);
|
||||||
let mut drop_block_stmts = vec![];
|
let mut drop_block_stmts = vec![];
|
||||||
drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.lvalue.clone())));
|
drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.place.clone())));
|
||||||
if ptr_based {
|
if ptr_based {
|
||||||
let tmp_ty = tcx.mk_mut_ptr(self.lvalue_ty(self.lvalue));
|
let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
|
||||||
let tmp = Place::Local(self.new_temp(tmp_ty));
|
let tmp = Place::Local(self.new_temp(tmp_ty));
|
||||||
// tmp = &LV;
|
// tmp = &LV;
|
||||||
// cur = tmp as *mut T;
|
// cur = tmp as *mut T;
|
||||||
// end = Offset(cur, len);
|
// end = Offset(cur, len);
|
||||||
drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref(
|
drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref(
|
||||||
tcx.types.re_erased, BorrowKind::Mut, self.lvalue.clone()
|
tcx.types.re_erased, BorrowKind::Mut, self.place.clone()
|
||||||
)));
|
)));
|
||||||
drop_block_stmts.push(self.assign(&cur, Rvalue::Cast(
|
drop_block_stmts.push(self.assign(&cur, Rvalue::Cast(
|
||||||
CastKind::Misc, Operand::Move(tmp.clone()), iter_ty
|
CastKind::Misc, Operand::Move(tmp.clone()), iter_ty
|
||||||
|
@ -752,7 +752,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
/// This creates a "drop ladder" that drops the needed fields of the
|
/// This creates a "drop ladder" that drops the needed fields of the
|
||||||
/// ADT, both in the success case or if one of the destructors fail.
|
/// ADT, both in the success case or if one of the destructors fail.
|
||||||
fn open_drop<'a>(&mut self) -> BasicBlock {
|
fn open_drop<'a>(&mut self) -> BasicBlock {
|
||||||
let ty = self.lvalue_ty(self.lvalue);
|
let ty = self.place_ty(self.place);
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyClosure(def_id, substs) |
|
ty::TyClosure(def_id, substs) |
|
||||||
// Note that `elaborate_drops` only drops the upvars of a generator,
|
// Note that `elaborate_drops` only drops the upvars of a generator,
|
||||||
|
@ -786,13 +786,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a basic block that drop an lvalue using the context
|
/// Return a basic block that drop a place using the context
|
||||||
/// and path in `c`. If `mode` is something, also clear `c`
|
/// and path in `c`. If `mode` is something, also clear `c`
|
||||||
/// according to it.
|
/// according to it.
|
||||||
///
|
///
|
||||||
/// if FLAG(self.path)
|
/// if FLAG(self.path)
|
||||||
/// if let Some(mode) = mode: FLAG(self.path)[mode] = false
|
/// if let Some(mode) = mode: FLAG(self.path)[mode] = false
|
||||||
/// drop(self.lv)
|
/// drop(self.place)
|
||||||
fn complete_drop<'a>(&mut self,
|
fn complete_drop<'a>(&mut self,
|
||||||
drop_mode: Option<DropFlagMode>,
|
drop_mode: Option<DropFlagMode>,
|
||||||
succ: BasicBlock,
|
succ: BasicBlock,
|
||||||
|
@ -855,7 +855,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
|
|
||||||
let call = TerminatorKind::Call {
|
let call = TerminatorKind::Call {
|
||||||
func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
|
func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
|
||||||
args: vec![Operand::Move(self.lvalue.clone())],
|
args: vec![Operand::Move(self.place.clone())],
|
||||||
destination: Some((unit_temp, target)),
|
destination: Some((unit_temp, target)),
|
||||||
cleanup: None
|
cleanup: None
|
||||||
}; // FIXME(#6393)
|
}; // FIXME(#6393)
|
||||||
|
@ -868,7 +868,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
|
|
||||||
fn drop_block<'a>(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock {
|
fn drop_block<'a>(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock {
|
||||||
let block = TerminatorKind::Drop {
|
let block = TerminatorKind::Drop {
|
||||||
location: self.lvalue.clone(),
|
location: self.place.clone(),
|
||||||
target,
|
target,
|
||||||
unwind: unwind.into_option()
|
unwind: unwind.into_option()
|
||||||
};
|
};
|
||||||
|
|
|
@ -127,8 +127,8 @@ impl<'tcx> MirPatch<'tcx> {
|
||||||
self.new_statements.push((loc, stmt));
|
self.new_statements.push((loc, stmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_assign(&mut self, loc: Location, lv: Place<'tcx>, rv: Rvalue<'tcx>) {
|
pub fn add_assign(&mut self, loc: Location, place: Place<'tcx>, rv: Rvalue<'tcx>) {
|
||||||
self.add_statement(loc, StatementKind::Assign(lv, rv));
|
self.add_statement(loc, StatementKind::Assign(place, rv));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply(self, mir: &mut Mir<'tcx>) {
|
pub fn apply(self, mir: &mut Mir<'tcx>) {
|
||||||
|
|
|
@ -344,12 +344,12 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print return pointer
|
// Print return place
|
||||||
let indented_retptr = format!("{}let mut {:?}: {};",
|
let indented_retptr = format!("{}let mut {:?}: {};",
|
||||||
INDENT,
|
INDENT,
|
||||||
RETURN_POINTER,
|
RETURN_PLACE,
|
||||||
mir.local_decls[RETURN_POINTER].ty);
|
mir.local_decls[RETURN_PLACE].ty);
|
||||||
writeln!(w, "{0:1$} // return pointer",
|
writeln!(w, "{0:1$} // return place",
|
||||||
indented_retptr,
|
indented_retptr,
|
||||||
ALIGN)?;
|
ALIGN)?;
|
||||||
|
|
||||||
|
|
|
@ -188,41 +188,41 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
|
||||||
self.super_operand(operand, location);
|
self.super_operand(operand, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lvalue(&mut self,
|
fn visit_place(&mut self,
|
||||||
lvalue: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
context: mir_visit::PlaceContext<'tcx>,
|
context: mir_visit::PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
self.record("Place", lvalue);
|
self.record("Place", place);
|
||||||
self.record(match *lvalue {
|
self.record(match *place {
|
||||||
Place::Local(..) => "Place::Local",
|
Place::Local(..) => "Place::Local",
|
||||||
Place::Static(..) => "Place::Static",
|
Place::Static(..) => "Place::Static",
|
||||||
Place::Projection(..) => "Place::Projection",
|
Place::Projection(..) => "Place::Projection",
|
||||||
}, lvalue);
|
}, place);
|
||||||
self.super_lvalue(lvalue, context, location);
|
self.super_place(place, context, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_projection(&mut self,
|
fn visit_projection(&mut self,
|
||||||
lvalue: &PlaceProjection<'tcx>,
|
place: &PlaceProjection<'tcx>,
|
||||||
context: mir_visit::PlaceContext<'tcx>,
|
context: mir_visit::PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
self.record("PlaceProjection", lvalue);
|
self.record("PlaceProjection", place);
|
||||||
self.super_projection(lvalue, context, location);
|
self.super_projection(place, context, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_projection_elem(&mut self,
|
fn visit_projection_elem(&mut self,
|
||||||
lvalue: &PlaceElem<'tcx>,
|
place: &PlaceElem<'tcx>,
|
||||||
context: mir_visit::PlaceContext<'tcx>,
|
context: mir_visit::PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
self.record("PlaceElem", lvalue);
|
self.record("PlaceElem", place);
|
||||||
self.record(match *lvalue {
|
self.record(match *place {
|
||||||
ProjectionElem::Deref => "PlaceElem::Deref",
|
ProjectionElem::Deref => "PlaceElem::Deref",
|
||||||
ProjectionElem::Subslice { .. } => "PlaceElem::Subslice",
|
ProjectionElem::Subslice { .. } => "PlaceElem::Subslice",
|
||||||
ProjectionElem::Field(..) => "PlaceElem::Field",
|
ProjectionElem::Field(..) => "PlaceElem::Field",
|
||||||
ProjectionElem::Index(..) => "PlaceElem::Index",
|
ProjectionElem::Index(..) => "PlaceElem::Index",
|
||||||
ProjectionElem::ConstantIndex { .. } => "PlaceElem::ConstantIndex",
|
ProjectionElem::ConstantIndex { .. } => "PlaceElem::ConstantIndex",
|
||||||
ProjectionElem::Downcast(..) => "PlaceElem::Downcast",
|
ProjectionElem::Downcast(..) => "PlaceElem::Downcast",
|
||||||
}, lvalue);
|
}, place);
|
||||||
self.super_projection_elem(lvalue, context, location);
|
self.super_projection_elem(place, context, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_constant(&mut self,
|
fn visit_constant(&mut self,
|
||||||
|
|
|
@ -30,7 +30,7 @@ use cabi_sparc64;
|
||||||
use cabi_nvptx;
|
use cabi_nvptx;
|
||||||
use cabi_nvptx64;
|
use cabi_nvptx64;
|
||||||
use cabi_hexagon;
|
use cabi_hexagon;
|
||||||
use mir::lvalue::{Alignment, PlaceRef};
|
use mir::place::{Alignment, PlaceRef};
|
||||||
use mir::operand::OperandValue;
|
use mir::operand::OperandValue;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use type_of::{LayoutLlvmExt, PointerKind};
|
use type_of::{LayoutLlvmExt, PointerKind};
|
||||||
|
@ -545,14 +545,14 @@ impl<'a, 'tcx> ArgType<'tcx> {
|
||||||
self.mode == PassMode::Ignore
|
self.mode == PassMode::Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the LLVM type for an lvalue of the original Rust type of
|
/// Get the LLVM type for an place of the original Rust type of
|
||||||
/// this argument/return, i.e. the result of `type_of::type_of`.
|
/// this argument/return, i.e. the result of `type_of::type_of`.
|
||||||
pub fn memory_ty(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
|
pub fn memory_ty(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
|
||||||
self.layout.llvm_type(ccx)
|
self.layout.llvm_type(ccx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Store a direct/indirect value described by this ArgType into a
|
/// Store a direct/indirect value described by this ArgType into a
|
||||||
/// lvalue for the original Rust type of this argument/return.
|
/// place for the original Rust type of this argument/return.
|
||||||
/// Can be used for both storing formal arguments into Rust variables
|
/// Can be used for both storing formal arguments into Rust variables
|
||||||
/// or results of call/invoke instructions into their destinations.
|
/// or results of call/invoke instructions into their destinations.
|
||||||
pub fn store(&self, bcx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
|
pub fn store(&self, bcx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
|
||||||
|
|
|
@ -18,7 +18,7 @@ use builder::Builder;
|
||||||
|
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
|
|
||||||
use mir::lvalue::PlaceRef;
|
use mir::place::PlaceRef;
|
||||||
use mir::operand::OperandValue;
|
use mir::operand::OperandValue;
|
||||||
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
@ -37,15 +37,15 @@ pub fn trans_inline_asm<'a, 'tcx>(
|
||||||
|
|
||||||
// Prepare the output operands
|
// Prepare the output operands
|
||||||
let mut indirect_outputs = vec![];
|
let mut indirect_outputs = vec![];
|
||||||
for (i, (out, lvalue)) in ia.outputs.iter().zip(&outputs).enumerate() {
|
for (i, (out, place)) in ia.outputs.iter().zip(&outputs).enumerate() {
|
||||||
if out.is_rw {
|
if out.is_rw {
|
||||||
inputs.push(lvalue.load(bcx).immediate());
|
inputs.push(place.load(bcx).immediate());
|
||||||
ext_constraints.push(i.to_string());
|
ext_constraints.push(i.to_string());
|
||||||
}
|
}
|
||||||
if out.is_indirect {
|
if out.is_indirect {
|
||||||
indirect_outputs.push(lvalue.load(bcx).immediate());
|
indirect_outputs.push(place.load(bcx).immediate());
|
||||||
} else {
|
} else {
|
||||||
output_types.push(lvalue.layout.llvm_type(bcx.ccx));
|
output_types.push(place.layout.llvm_type(bcx.ccx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !indirect_outputs.is_empty() {
|
if !indirect_outputs.is_empty() {
|
||||||
|
@ -100,9 +100,9 @@ pub fn trans_inline_asm<'a, 'tcx>(
|
||||||
|
|
||||||
// Again, based on how many outputs we have
|
// Again, based on how many outputs we have
|
||||||
let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect);
|
let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect);
|
||||||
for (i, (_, &lvalue)) in outputs.enumerate() {
|
for (i, (_, &place)) in outputs.enumerate() {
|
||||||
let v = if num_outputs == 1 { r } else { bcx.extract_value(r, i as u64) };
|
let v = if num_outputs == 1 { r } else { bcx.extract_value(r, i as u64) };
|
||||||
OperandValue::Immediate(v).store(bcx, lvalue);
|
OperandValue::Immediate(v).store(bcx, place);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store mark in a metadata node so we can map LLVM errors
|
// Store mark in a metadata node so we can map LLVM errors
|
||||||
|
|
|
@ -50,7 +50,7 @@ use rustc::session::config::{self, NoDebugInfo};
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc_incremental;
|
use rustc_incremental;
|
||||||
use allocator;
|
use allocator;
|
||||||
use mir::lvalue::PlaceRef;
|
use mir::place::PlaceRef;
|
||||||
use attributes;
|
use attributes;
|
||||||
use builder::Builder;
|
use builder::Builder;
|
||||||
use callee;
|
use callee;
|
||||||
|
|
|
@ -14,7 +14,7 @@ use intrinsics::{self, Intrinsic};
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::{ValueRef};
|
use llvm::{ValueRef};
|
||||||
use abi::{Abi, FnType, PassMode};
|
use abi::{Abi, FnType, PassMode};
|
||||||
use mir::lvalue::{PlaceRef, Alignment};
|
use mir::place::{PlaceRef, Alignment};
|
||||||
use mir::operand::{OperandRef, OperandValue};
|
use mir::operand::{OperandRef, OperandValue};
|
||||||
use base::*;
|
use base::*;
|
||||||
use common::*;
|
use common::*;
|
||||||
|
|
|
@ -22,7 +22,7 @@ use rustc::ty::layout::LayoutOf;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use super::MirContext;
|
use super::MirContext;
|
||||||
|
|
||||||
pub fn lvalue_locals<'a, 'tcx>(mircx: &MirContext<'a, 'tcx>) -> BitVector {
|
pub fn memory_locals<'a, 'tcx>(mircx: &MirContext<'a, 'tcx>) -> BitVector {
|
||||||
let mir = mircx.mir;
|
let mir = mircx.mir;
|
||||||
let mut analyzer = LocalAnalyzer::new(mircx);
|
let mut analyzer = LocalAnalyzer::new(mircx);
|
||||||
|
|
||||||
|
@ -44,16 +44,16 @@ pub fn lvalue_locals<'a, 'tcx>(mircx: &MirContext<'a, 'tcx>) -> BitVector {
|
||||||
// (e.g. structs) into an alloca unconditionally, just so
|
// (e.g. structs) into an alloca unconditionally, just so
|
||||||
// that we don't have to deal with having two pathways
|
// that we don't have to deal with having two pathways
|
||||||
// (gep vs extractvalue etc).
|
// (gep vs extractvalue etc).
|
||||||
analyzer.mark_as_lvalue(mir::Local::new(index));
|
analyzer.mark_as_memory(mir::Local::new(index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
analyzer.lvalue_locals
|
analyzer.memory_locals
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LocalAnalyzer<'mir, 'a: 'mir, 'tcx: 'a> {
|
struct LocalAnalyzer<'mir, 'a: 'mir, 'tcx: 'a> {
|
||||||
cx: &'mir MirContext<'a, 'tcx>,
|
cx: &'mir MirContext<'a, 'tcx>,
|
||||||
lvalue_locals: BitVector,
|
memory_locals: BitVector,
|
||||||
seen_assigned: BitVector
|
seen_assigned: BitVector
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> {
|
||||||
fn new(mircx: &'mir MirContext<'a, 'tcx>) -> LocalAnalyzer<'mir, 'a, 'tcx> {
|
fn new(mircx: &'mir MirContext<'a, 'tcx>) -> LocalAnalyzer<'mir, 'a, 'tcx> {
|
||||||
let mut analyzer = LocalAnalyzer {
|
let mut analyzer = LocalAnalyzer {
|
||||||
cx: mircx,
|
cx: mircx,
|
||||||
lvalue_locals: BitVector::new(mircx.mir.local_decls.len()),
|
memory_locals: BitVector::new(mircx.mir.local_decls.len()),
|
||||||
seen_assigned: BitVector::new(mircx.mir.local_decls.len())
|
seen_assigned: BitVector::new(mircx.mir.local_decls.len())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,14 +73,14 @@ impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> {
|
||||||
analyzer
|
analyzer
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_as_lvalue(&mut self, local: mir::Local) {
|
fn mark_as_memory(&mut self, local: mir::Local) {
|
||||||
debug!("marking {:?} as lvalue", local);
|
debug!("marking {:?} as memory", local);
|
||||||
self.lvalue_locals.insert(local.index());
|
self.memory_locals.insert(local.index());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_assigned(&mut self, local: mir::Local) {
|
fn mark_assigned(&mut self, local: mir::Local) {
|
||||||
if !self.seen_assigned.insert(local.index()) {
|
if !self.seen_assigned.insert(local.index()) {
|
||||||
self.mark_as_lvalue(local);
|
self.mark_as_memory(local);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,18 +88,18 @@ impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> {
|
||||||
impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
|
impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
|
||||||
fn visit_assign(&mut self,
|
fn visit_assign(&mut self,
|
||||||
block: mir::BasicBlock,
|
block: mir::BasicBlock,
|
||||||
lvalue: &mir::Place<'tcx>,
|
place: &mir::Place<'tcx>,
|
||||||
rvalue: &mir::Rvalue<'tcx>,
|
rvalue: &mir::Rvalue<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
debug!("visit_assign(block={:?}, lvalue={:?}, rvalue={:?})", block, lvalue, rvalue);
|
debug!("visit_assign(block={:?}, place={:?}, rvalue={:?})", block, place, rvalue);
|
||||||
|
|
||||||
if let mir::Place::Local(index) = *lvalue {
|
if let mir::Place::Local(index) = *place {
|
||||||
self.mark_assigned(index);
|
self.mark_assigned(index);
|
||||||
if !self.cx.rvalue_creates_operand(rvalue) {
|
if !self.cx.rvalue_creates_operand(rvalue) {
|
||||||
self.mark_as_lvalue(index);
|
self.mark_as_memory(index);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.visit_lvalue(lvalue, PlaceContext::Store, location);
|
self.visit_place(place, PlaceContext::Store, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.visit_rvalue(rvalue, location);
|
self.visit_rvalue(rvalue, location);
|
||||||
|
@ -121,8 +121,8 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
|
||||||
// box_free(x) shares with `drop x` the property that it
|
// box_free(x) shares with `drop x` the property that it
|
||||||
// is not guaranteed to be statically dominated by the
|
// is not guaranteed to be statically dominated by the
|
||||||
// definition of x, so x must always be in an alloca.
|
// definition of x, so x must always be in an alloca.
|
||||||
if let mir::Operand::Move(ref lvalue) = args[0] {
|
if let mir::Operand::Move(ref place) = args[0] {
|
||||||
self.visit_lvalue(lvalue, PlaceContext::Drop, location);
|
self.visit_place(place, PlaceContext::Drop, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -131,14 +131,14 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
|
||||||
self.super_terminator_kind(block, kind, location);
|
self.super_terminator_kind(block, kind, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lvalue(&mut self,
|
fn visit_place(&mut self,
|
||||||
lvalue: &mir::Place<'tcx>,
|
place: &mir::Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
debug!("visit_lvalue(lvalue={:?}, context={:?})", lvalue, context);
|
debug!("visit_place(place={:?}, context={:?})", place, context);
|
||||||
let ccx = self.cx.ccx;
|
let ccx = self.cx.ccx;
|
||||||
|
|
||||||
if let mir::Place::Projection(ref proj) = *lvalue {
|
if let mir::Place::Projection(ref proj) = *place {
|
||||||
// Allow uses of projections that are ZSTs or from scalar fields.
|
// Allow uses of projections that are ZSTs or from scalar fields.
|
||||||
let is_consume = match context {
|
let is_consume = match context {
|
||||||
PlaceContext::Copy | PlaceContext::Move => true,
|
PlaceContext::Copy | PlaceContext::Move => true,
|
||||||
|
@ -160,20 +160,20 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
|
||||||
if layout.is_llvm_immediate() || layout.is_llvm_scalar_pair() {
|
if layout.is_llvm_immediate() || layout.is_llvm_scalar_pair() {
|
||||||
// Recurse with the same context, instead of `Projection`,
|
// Recurse with the same context, instead of `Projection`,
|
||||||
// potentially stopping at non-operand projections,
|
// potentially stopping at non-operand projections,
|
||||||
// which would trigger `mark_as_lvalue` on locals.
|
// which would trigger `mark_as_memory` on locals.
|
||||||
self.visit_lvalue(&proj.base, context, location);
|
self.visit_place(&proj.base, context, location);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A deref projection only reads the pointer, never needs the lvalue.
|
// A deref projection only reads the pointer, never needs the place.
|
||||||
if let mir::ProjectionElem::Deref = proj.elem {
|
if let mir::ProjectionElem::Deref = proj.elem {
|
||||||
return self.visit_lvalue(&proj.base, PlaceContext::Copy, location);
|
return self.visit_place(&proj.base, PlaceContext::Copy, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.super_lvalue(lvalue, context, location);
|
self.super_place(place, context, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_local(&mut self,
|
fn visit_local(&mut self,
|
||||||
|
@ -195,16 +195,16 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
|
||||||
PlaceContext::Store |
|
PlaceContext::Store |
|
||||||
PlaceContext::Borrow { .. } |
|
PlaceContext::Borrow { .. } |
|
||||||
PlaceContext::Projection(..) => {
|
PlaceContext::Projection(..) => {
|
||||||
self.mark_as_lvalue(index);
|
self.mark_as_memory(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaceContext::Drop => {
|
PlaceContext::Drop => {
|
||||||
let ty = mir::Place::Local(index).ty(self.cx.mir, self.cx.ccx.tcx());
|
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()));
|
let ty = self.cx.monomorphize(&ty.to_ty(self.cx.ccx.tcx()));
|
||||||
|
|
||||||
// Only need the lvalue if we're actually dropping it.
|
// Only need the place if we're actually dropping it.
|
||||||
if self.cx.ccx.shared().type_needs_drop(ty) {
|
if self.cx.ccx.shared().type_needs_drop(ty) {
|
||||||
self.mark_as_lvalue(index);
|
self.mark_as_memory(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ use syntax_pos::Pos;
|
||||||
|
|
||||||
use super::{MirContext, LocalRef};
|
use super::{MirContext, LocalRef};
|
||||||
use super::constant::Const;
|
use super::constant::Const;
|
||||||
use super::lvalue::{Alignment, PlaceRef};
|
use super::place::{Alignment, PlaceRef};
|
||||||
use super::operand::OperandRef;
|
use super::operand::OperandRef;
|
||||||
use super::operand::OperandValue::{Pair, Ref, Immediate};
|
use super::operand::OperandValue::{Pair, Ref, Immediate};
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
PassMode::Direct(_) | PassMode::Pair(..) => {
|
PassMode::Direct(_) | PassMode::Pair(..) => {
|
||||||
let op = self.trans_consume(&bcx, &mir::Place::Local(mir::RETURN_POINTER));
|
let op = self.trans_consume(&bcx, &mir::Place::Local(mir::RETURN_PLACE));
|
||||||
if let Ref(llval, align) = op.val {
|
if let Ref(llval, align) = op.val {
|
||||||
bcx.load(llval, align.non_abi())
|
bcx.load(llval, align.non_abi())
|
||||||
} else {
|
} else {
|
||||||
|
@ -223,13 +223,13 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
PassMode::Cast(cast_ty) => {
|
PassMode::Cast(cast_ty) => {
|
||||||
let op = match self.locals[mir::RETURN_POINTER] {
|
let op = match self.locals[mir::RETURN_PLACE] {
|
||||||
LocalRef::Operand(Some(op)) => op,
|
LocalRef::Operand(Some(op)) => op,
|
||||||
LocalRef::Operand(None) => bug!("use of return before def"),
|
LocalRef::Operand(None) => bug!("use of return before def"),
|
||||||
LocalRef::Place(tr_lvalue) => {
|
LocalRef::Place(tr_place) => {
|
||||||
OperandRef {
|
OperandRef {
|
||||||
val: Ref(tr_lvalue.llval, tr_lvalue.alignment),
|
val: Ref(tr_place.llval, tr_place.alignment),
|
||||||
layout: tr_lvalue.layout
|
layout: tr_place.layout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -241,7 +241,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
Ref(llval, align) => {
|
Ref(llval, align) => {
|
||||||
assert_eq!(align, Alignment::AbiAligned,
|
assert_eq!(align, Alignment::AbiAligned,
|
||||||
"return pointer is unaligned!");
|
"return place is unaligned!");
|
||||||
llval
|
llval
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -268,9 +268,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let lvalue = self.trans_lvalue(&bcx, location);
|
let place = self.trans_place(&bcx, location);
|
||||||
let mut args: &[_] = &[lvalue.llval, lvalue.llextra];
|
let mut args: &[_] = &[place.llval, place.llextra];
|
||||||
args = &args[..1 + lvalue.has_extra() as usize];
|
args = &args[..1 + place.has_extra() as usize];
|
||||||
let (drop_fn, fn_ty) = match ty.sty {
|
let (drop_fn, fn_ty) = match ty.sty {
|
||||||
ty::TyDynamic(..) => {
|
ty::TyDynamic(..) => {
|
||||||
let fn_ty = common::instance_ty(bcx.ccx.tcx(), &drop_fn);
|
let fn_ty = common::instance_ty(bcx.ccx.tcx(), &drop_fn);
|
||||||
|
@ -278,7 +278,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig);
|
let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig);
|
||||||
let fn_ty = FnType::new_vtable(bcx.ccx, sig, &[]);
|
let fn_ty = FnType::new_vtable(bcx.ccx, sig, &[]);
|
||||||
args = &args[..1];
|
args = &args[..1];
|
||||||
(meth::DESTRUCTOR.get_fn(&bcx, lvalue.llextra, &fn_ty), fn_ty)
|
(meth::DESTRUCTOR.get_fn(&bcx, place.llextra, &fn_ty), fn_ty)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
(callee::get_fn(bcx.ccx, drop_fn),
|
(callee::get_fn(bcx.ccx, drop_fn),
|
||||||
|
@ -792,7 +792,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Place(dest) => dest,
|
LocalRef::Place(dest) => dest,
|
||||||
LocalRef::Operand(None) => {
|
LocalRef::Operand(None) => {
|
||||||
// Handle temporary lvalues, specifically Operand ones, as
|
// Handle temporary places, specifically Operand ones, as
|
||||||
// they don't have allocas
|
// they don't have allocas
|
||||||
return if fn_ret.is_indirect() {
|
return if fn_ret.is_indirect() {
|
||||||
// Odd, but possible, case, we have an operand temporary,
|
// Odd, but possible, case, we have an operand temporary,
|
||||||
|
@ -813,11 +813,11 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
LocalRef::Operand(Some(_)) => {
|
LocalRef::Operand(Some(_)) => {
|
||||||
bug!("lvalue local already assigned to");
|
bug!("place local already assigned to");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.trans_lvalue(bcx, dest)
|
self.trans_place(bcx, dest)
|
||||||
};
|
};
|
||||||
if fn_ret.is_indirect() {
|
if fn_ret.is_indirect() {
|
||||||
match dest.alignment {
|
match dest.alignment {
|
||||||
|
@ -845,15 +845,15 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
dst: &mir::Place<'tcx>) {
|
dst: &mir::Place<'tcx>) {
|
||||||
if let mir::Place::Local(index) = *dst {
|
if let mir::Place::Local(index) = *dst {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Place(lvalue) => self.trans_transmute_into(bcx, src, lvalue),
|
LocalRef::Place(place) => self.trans_transmute_into(bcx, src, place),
|
||||||
LocalRef::Operand(None) => {
|
LocalRef::Operand(None) => {
|
||||||
let dst_layout = bcx.ccx.layout_of(self.monomorphized_lvalue_ty(dst));
|
let dst_layout = bcx.ccx.layout_of(self.monomorphized_place_ty(dst));
|
||||||
assert!(!dst_layout.ty.has_erasable_regions());
|
assert!(!dst_layout.ty.has_erasable_regions());
|
||||||
let lvalue = PlaceRef::alloca(bcx, dst_layout, "transmute_temp");
|
let place = PlaceRef::alloca(bcx, dst_layout, "transmute_temp");
|
||||||
lvalue.storage_live(bcx);
|
place.storage_live(bcx);
|
||||||
self.trans_transmute_into(bcx, src, lvalue);
|
self.trans_transmute_into(bcx, src, place);
|
||||||
let op = lvalue.load(bcx);
|
let op = place.load(bcx);
|
||||||
lvalue.storage_dead(bcx);
|
place.storage_dead(bcx);
|
||||||
self.locals[index] = LocalRef::Operand(Some(op));
|
self.locals[index] = LocalRef::Operand(Some(op));
|
||||||
}
|
}
|
||||||
LocalRef::Operand(Some(op)) => {
|
LocalRef::Operand(Some(op)) => {
|
||||||
|
@ -862,7 +862,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let dst = self.trans_lvalue(bcx, dst);
|
let dst = self.trans_place(bcx, dst);
|
||||||
self.trans_transmute_into(bcx, src, dst);
|
self.trans_transmute_into(bcx, src, dst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -918,8 +918,8 @@ enum ReturnDest<'tcx> {
|
||||||
Nothing,
|
Nothing,
|
||||||
// Store the return value to the pointer
|
// Store the return value to the pointer
|
||||||
Store(PlaceRef<'tcx>),
|
Store(PlaceRef<'tcx>),
|
||||||
// Stores an indirect return value to an operand local lvalue
|
// Stores an indirect return value to an operand local place
|
||||||
IndirectOperand(PlaceRef<'tcx>, mir::Local),
|
IndirectOperand(PlaceRef<'tcx>, mir::Local),
|
||||||
// Stores a direct return value to an operand local lvalue
|
// Stores a direct return value to an operand local place
|
||||||
DirectOperand(mir::Local)
|
DirectOperand(mir::Local)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ use syntax::ast;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use super::lvalue::Alignment;
|
use super::place::Alignment;
|
||||||
use super::operand::{OperandRef, OperandValue};
|
use super::operand::{OperandRef, OperandValue};
|
||||||
use super::MirContext;
|
use super::MirContext;
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ impl<'a, 'tcx> Const<'tcx> {
|
||||||
self.get_pair(ccx)
|
self.get_pair(ccx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_lvalue(&self) -> ConstPlace<'tcx> {
|
fn as_place(&self) -> ConstPlace<'tcx> {
|
||||||
ConstPlace {
|
ConstPlace {
|
||||||
base: Base::Value(self.llval),
|
base: Base::Value(self.llval),
|
||||||
llextra: ptr::null_mut(),
|
llextra: ptr::null_mut(),
|
||||||
|
@ -210,7 +210,7 @@ enum Base {
|
||||||
Static(ValueRef)
|
Static(ValueRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An lvalue as seen from a constant.
|
/// An place as seen from a constant.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct ConstPlace<'tcx> {
|
struct ConstPlace<'tcx> {
|
||||||
base: Base,
|
base: Base,
|
||||||
|
@ -348,7 +348,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||||
mir::TerminatorKind::Goto { target } => target,
|
mir::TerminatorKind::Goto { target } => target,
|
||||||
mir::TerminatorKind::Return => {
|
mir::TerminatorKind::Return => {
|
||||||
failure?;
|
failure?;
|
||||||
return self.locals[mir::RETURN_POINTER].clone().unwrap_or_else(|| {
|
return self.locals[mir::RETURN_PLACE].clone().unwrap_or_else(|| {
|
||||||
span_bug!(span, "no returned value in constant");
|
span_bug!(span, "no returned value in constant");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -437,17 +437,17 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn const_lvalue(&self, lvalue: &mir::Place<'tcx>, span: Span)
|
fn const_place(&self, place: &mir::Place<'tcx>, span: Span)
|
||||||
-> Result<ConstPlace<'tcx>, ConstEvalErr<'tcx>> {
|
-> Result<ConstPlace<'tcx>, ConstEvalErr<'tcx>> {
|
||||||
let tcx = self.ccx.tcx();
|
let tcx = self.ccx.tcx();
|
||||||
|
|
||||||
if let mir::Place::Local(index) = *lvalue {
|
if let mir::Place::Local(index) = *place {
|
||||||
return self.locals[index].clone().unwrap_or_else(|| {
|
return self.locals[index].clone().unwrap_or_else(|| {
|
||||||
span_bug!(span, "{:?} not initialized", lvalue)
|
span_bug!(span, "{:?} not initialized", place)
|
||||||
}).map(|v| v.as_lvalue());
|
}).map(|v| v.as_place());
|
||||||
}
|
}
|
||||||
|
|
||||||
let lvalue = match *lvalue {
|
let place = match *place {
|
||||||
mir::Place::Local(_) => bug!(), // handled above
|
mir::Place::Local(_) => bug!(), // handled above
|
||||||
mir::Place::Static(box mir::Static { def_id, ty }) => {
|
mir::Place::Static(box mir::Static { def_id, ty }) => {
|
||||||
ConstPlace {
|
ConstPlace {
|
||||||
|
@ -457,7 +457,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::Place::Projection(ref projection) => {
|
mir::Place::Projection(ref projection) => {
|
||||||
let tr_base = self.const_lvalue(&projection.base, span)?;
|
let tr_base = self.const_place(&projection.base, span)?;
|
||||||
let projected_ty = PlaceTy::Ty { ty: tr_base.ty }
|
let projected_ty = PlaceTy::Ty { ty: tr_base.ty }
|
||||||
.projection_ty(tcx, &projection.elem);
|
.projection_ty(tcx, &projection.elem);
|
||||||
let base = tr_base.to_const(span);
|
let base = tr_base.to_const(span);
|
||||||
|
@ -533,16 +533,16 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(lvalue)
|
Ok(place)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn const_operand(&self, operand: &mir::Operand<'tcx>, span: Span)
|
fn const_operand(&self, operand: &mir::Operand<'tcx>, span: Span)
|
||||||
-> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
|
-> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
|
||||||
debug!("const_operand({:?} @ {:?})", operand, span);
|
debug!("const_operand({:?} @ {:?})", operand, span);
|
||||||
let result = match *operand {
|
let result = match *operand {
|
||||||
mir::Operand::Copy(ref lvalue) |
|
mir::Operand::Copy(ref place) |
|
||||||
mir::Operand::Move(ref lvalue) => {
|
mir::Operand::Move(ref place) => {
|
||||||
Ok(self.const_lvalue(lvalue, span)?.to_const(span))
|
Ok(self.const_place(place, span)?.to_const(span))
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Operand::Constant(ref constant) => {
|
mir::Operand::Constant(ref constant) => {
|
||||||
|
@ -779,14 +779,14 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||||
Const::new(val, cast_ty)
|
Const::new(val, cast_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::Ref(_, bk, ref lvalue) => {
|
mir::Rvalue::Ref(_, bk, ref place) => {
|
||||||
let tr_lvalue = self.const_lvalue(lvalue, span)?;
|
let tr_place = self.const_place(place, span)?;
|
||||||
|
|
||||||
let ty = tr_lvalue.ty;
|
let ty = tr_place.ty;
|
||||||
let ref_ty = tcx.mk_ref(tcx.types.re_erased,
|
let ref_ty = tcx.mk_ref(tcx.types.re_erased,
|
||||||
ty::TypeAndMut { ty: ty, mutbl: bk.to_mutbl_lossy() });
|
ty::TypeAndMut { ty: ty, mutbl: bk.to_mutbl_lossy() });
|
||||||
|
|
||||||
let base = match tr_lvalue.base {
|
let base = match tr_place.base {
|
||||||
Base::Value(llval) => {
|
Base::Value(llval) => {
|
||||||
// FIXME: may be wrong for &*(&simd_vec as &fmt::Debug)
|
// FIXME: may be wrong for &*(&simd_vec as &fmt::Debug)
|
||||||
let align = if self.ccx.shared().type_is_sized(ty) {
|
let align = if self.ccx.shared().type_is_sized(ty) {
|
||||||
|
@ -807,14 +807,14 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||||
let ptr = if self.ccx.shared().type_is_sized(ty) {
|
let ptr = if self.ccx.shared().type_is_sized(ty) {
|
||||||
base
|
base
|
||||||
} else {
|
} else {
|
||||||
C_fat_ptr(self.ccx, base, tr_lvalue.llextra)
|
C_fat_ptr(self.ccx, base, tr_place.llextra)
|
||||||
};
|
};
|
||||||
Const::new(ptr, ref_ty)
|
Const::new(ptr, ref_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::Len(ref lvalue) => {
|
mir::Rvalue::Len(ref place) => {
|
||||||
let tr_lvalue = self.const_lvalue(lvalue, span)?;
|
let tr_place = self.const_place(place, span)?;
|
||||||
Const::new(tr_lvalue.len(self.ccx), tcx.types.usize)
|
Const::new(tr_place.len(self.ccx), tcx.types.usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
|
mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
|
||||||
|
|
|
@ -35,7 +35,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||||
pub use self::constant::trans_static_initializer;
|
pub use self::constant::trans_static_initializer;
|
||||||
|
|
||||||
use self::analyze::CleanupKind;
|
use self::analyze::CleanupKind;
|
||||||
use self::lvalue::{Alignment, PlaceRef};
|
use self::place::{Alignment, PlaceRef};
|
||||||
use rustc::mir::traversal;
|
use rustc::mir::traversal;
|
||||||
|
|
||||||
use self::operand::{OperandRef, OperandValue};
|
use self::operand::{OperandRef, OperandValue};
|
||||||
|
@ -87,7 +87,7 @@ pub struct MirContext<'a, 'tcx:'a> {
|
||||||
/// - the type of the local must be judged "immediate" by `is_llvm_immediate`
|
/// - the type of the local must be judged "immediate" by `is_llvm_immediate`
|
||||||
/// - the operand must never be referenced indirectly
|
/// - the operand must never be referenced indirectly
|
||||||
/// - we should not take its address using the `&` operator
|
/// - we should not take its address using the `&` operator
|
||||||
/// - nor should it appear in an lvalue path like `tmp.a`
|
/// - nor should it appear in a place path like `tmp.a`
|
||||||
/// - the operand must be defined by an rvalue that can generate immediate
|
/// - the operand must be defined by an rvalue that can generate immediate
|
||||||
/// values
|
/// values
|
||||||
///
|
///
|
||||||
|
@ -244,11 +244,11 @@ pub fn trans_mir<'a, 'tcx: 'a>(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let lvalue_locals = analyze::lvalue_locals(&mircx);
|
let memory_locals = analyze::memory_locals(&mircx);
|
||||||
|
|
||||||
// Allocate variable and temp allocas
|
// Allocate variable and temp allocas
|
||||||
mircx.locals = {
|
mircx.locals = {
|
||||||
let args = arg_local_refs(&bcx, &mircx, &mircx.scopes, &lvalue_locals);
|
let args = arg_local_refs(&bcx, &mircx, &mircx.scopes, &memory_locals);
|
||||||
|
|
||||||
let mut allocate_local = |local| {
|
let mut allocate_local = |local| {
|
||||||
let decl = &mir.local_decls[local];
|
let decl = &mir.local_decls[local];
|
||||||
|
@ -260,30 +260,30 @@ pub fn trans_mir<'a, 'tcx: 'a>(
|
||||||
let debug_scope = mircx.scopes[decl.source_info.scope];
|
let debug_scope = mircx.scopes[decl.source_info.scope];
|
||||||
let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo;
|
let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo;
|
||||||
|
|
||||||
if !lvalue_locals.contains(local.index()) && !dbg {
|
if !memory_locals.contains(local.index()) && !dbg {
|
||||||
debug!("alloc: {:?} ({}) -> operand", local, name);
|
debug!("alloc: {:?} ({}) -> operand", local, name);
|
||||||
return LocalRef::new_operand(bcx.ccx, layout);
|
return LocalRef::new_operand(bcx.ccx, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("alloc: {:?} ({}) -> lvalue", local, name);
|
debug!("alloc: {:?} ({}) -> place", local, name);
|
||||||
let lvalue = PlaceRef::alloca(&bcx, layout, &name.as_str());
|
let place = PlaceRef::alloca(&bcx, layout, &name.as_str());
|
||||||
if dbg {
|
if dbg {
|
||||||
let (scope, span) = mircx.debug_loc(decl.source_info);
|
let (scope, span) = mircx.debug_loc(decl.source_info);
|
||||||
declare_local(&bcx, &mircx.debug_context, name, layout.ty, scope,
|
declare_local(&bcx, &mircx.debug_context, name, layout.ty, scope,
|
||||||
VariableAccess::DirectVariable { alloca: lvalue.llval },
|
VariableAccess::DirectVariable { alloca: place.llval },
|
||||||
VariableKind::LocalVariable, span);
|
VariableKind::LocalVariable, span);
|
||||||
}
|
}
|
||||||
LocalRef::Place(lvalue)
|
LocalRef::Place(place)
|
||||||
} else {
|
} else {
|
||||||
// Temporary or return pointer
|
// Temporary or return place
|
||||||
if local == mir::RETURN_POINTER && mircx.fn_ty.ret.is_indirect() {
|
if local == mir::RETURN_PLACE && mircx.fn_ty.ret.is_indirect() {
|
||||||
debug!("alloc: {:?} (return pointer) -> lvalue", local);
|
debug!("alloc: {:?} (return place) -> place", local);
|
||||||
let llretptr = llvm::get_param(llfn, 0);
|
let llretptr = llvm::get_param(llfn, 0);
|
||||||
LocalRef::Place(PlaceRef::new_sized(llretptr,
|
LocalRef::Place(PlaceRef::new_sized(llretptr,
|
||||||
layout,
|
layout,
|
||||||
Alignment::AbiAligned))
|
Alignment::AbiAligned))
|
||||||
} else if lvalue_locals.contains(local.index()) {
|
} else if memory_locals.contains(local.index()) {
|
||||||
debug!("alloc: {:?} -> lvalue", local);
|
debug!("alloc: {:?} -> place", local);
|
||||||
LocalRef::Place(PlaceRef::alloca(&bcx, layout, &format!("{:?}", local)))
|
LocalRef::Place(PlaceRef::alloca(&bcx, layout, &format!("{:?}", local)))
|
||||||
} else {
|
} else {
|
||||||
// If this is an immediate local, we do not create an
|
// If this is an immediate local, we do not create an
|
||||||
|
@ -295,7 +295,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let retptr = allocate_local(mir::RETURN_POINTER);
|
let retptr = allocate_local(mir::RETURN_PLACE);
|
||||||
iter::once(retptr)
|
iter::once(retptr)
|
||||||
.chain(args.into_iter())
|
.chain(args.into_iter())
|
||||||
.chain(mir.vars_and_temps_iter().map(allocate_local))
|
.chain(mir.vars_and_temps_iter().map(allocate_local))
|
||||||
|
@ -355,12 +355,12 @@ fn create_funclets<'a, 'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce, for each argument, a `ValueRef` pointing at the
|
/// Produce, for each argument, a `ValueRef` pointing at the
|
||||||
/// argument's value. As arguments are lvalues, these are always
|
/// argument's value. As arguments are places, these are always
|
||||||
/// indirect.
|
/// indirect.
|
||||||
fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
||||||
mircx: &MirContext<'a, 'tcx>,
|
mircx: &MirContext<'a, 'tcx>,
|
||||||
scopes: &IndexVec<mir::VisibilityScope, debuginfo::MirDebugScope>,
|
scopes: &IndexVec<mir::VisibilityScope, debuginfo::MirDebugScope>,
|
||||||
lvalue_locals: &BitVector)
|
memory_locals: &BitVector)
|
||||||
-> Vec<LocalRef<'tcx>> {
|
-> Vec<LocalRef<'tcx>> {
|
||||||
let mir = mircx.mir;
|
let mir = mircx.mir;
|
||||||
let tcx = bcx.tcx();
|
let tcx = bcx.tcx();
|
||||||
|
@ -400,18 +400,18 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
||||||
_ => bug!("spread argument isn't a tuple?!")
|
_ => bug!("spread argument isn't a tuple?!")
|
||||||
};
|
};
|
||||||
|
|
||||||
let lvalue = PlaceRef::alloca(bcx, bcx.ccx.layout_of(arg_ty), &name);
|
let place = PlaceRef::alloca(bcx, bcx.ccx.layout_of(arg_ty), &name);
|
||||||
for i in 0..tupled_arg_tys.len() {
|
for i in 0..tupled_arg_tys.len() {
|
||||||
let arg = &mircx.fn_ty.args[idx];
|
let arg = &mircx.fn_ty.args[idx];
|
||||||
idx += 1;
|
idx += 1;
|
||||||
arg.store_fn_arg(bcx, &mut llarg_idx, lvalue.project_field(bcx, i));
|
arg.store_fn_arg(bcx, &mut llarg_idx, place.project_field(bcx, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we have one alloca that contains the aggregate value,
|
// Now that we have one alloca that contains the aggregate value,
|
||||||
// we can create one debuginfo entry for the argument.
|
// we can create one debuginfo entry for the argument.
|
||||||
arg_scope.map(|scope| {
|
arg_scope.map(|scope| {
|
||||||
let variable_access = VariableAccess::DirectVariable {
|
let variable_access = VariableAccess::DirectVariable {
|
||||||
alloca: lvalue.llval
|
alloca: place.llval
|
||||||
};
|
};
|
||||||
declare_local(
|
declare_local(
|
||||||
bcx,
|
bcx,
|
||||||
|
@ -424,7 +424,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return LocalRef::Place(lvalue);
|
return LocalRef::Place(place);
|
||||||
}
|
}
|
||||||
|
|
||||||
let arg = &mircx.fn_ty.args[idx];
|
let arg = &mircx.fn_ty.args[idx];
|
||||||
|
@ -433,7 +433,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
||||||
llarg_idx += 1;
|
llarg_idx += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if arg_scope.is_none() && !lvalue_locals.contains(local.index()) {
|
if arg_scope.is_none() && !memory_locals.contains(local.index()) {
|
||||||
// We don't have to cast or keep the argument in the alloca.
|
// We don't have to cast or keep the argument in the alloca.
|
||||||
// FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
|
// FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
|
||||||
// of putting everything in allocas just so we can use llvm.dbg.declare.
|
// of putting everything in allocas just so we can use llvm.dbg.declare.
|
||||||
|
@ -467,7 +467,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let lvalue = if arg.is_indirect() {
|
let place = if arg.is_indirect() {
|
||||||
// Don't copy an indirect argument to an alloca, the caller
|
// Don't copy an indirect argument to an alloca, the caller
|
||||||
// already put it in a temporary alloca and gave it up.
|
// already put it in a temporary alloca and gave it up.
|
||||||
// FIXME: lifetimes
|
// FIXME: lifetimes
|
||||||
|
@ -487,13 +487,13 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
||||||
// need to insert a deref here, but the C ABI uses a pointer and a copy using the
|
// need to insert a deref here, but the C ABI uses a pointer and a copy using the
|
||||||
// byval attribute, for which LLVM does the deref itself, so we must not add it.
|
// byval attribute, for which LLVM does the deref itself, so we must not add it.
|
||||||
let mut variable_access = VariableAccess::DirectVariable {
|
let mut variable_access = VariableAccess::DirectVariable {
|
||||||
alloca: lvalue.llval
|
alloca: place.llval
|
||||||
};
|
};
|
||||||
|
|
||||||
if let PassMode::Indirect(ref attrs) = arg.mode {
|
if let PassMode::Indirect(ref attrs) = arg.mode {
|
||||||
if !attrs.contains(ArgAttribute::ByVal) {
|
if !attrs.contains(ArgAttribute::ByVal) {
|
||||||
variable_access = VariableAccess::IndirectVariable {
|
variable_access = VariableAccess::IndirectVariable {
|
||||||
alloca: lvalue.llval,
|
alloca: place.llval,
|
||||||
address_operations: &deref_op,
|
address_operations: &deref_op,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -535,10 +535,10 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
||||||
let alloc = PlaceRef::alloca(bcx,
|
let alloc = PlaceRef::alloca(bcx,
|
||||||
bcx.ccx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
|
bcx.ccx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
|
||||||
"__debuginfo_env_ptr");
|
"__debuginfo_env_ptr");
|
||||||
bcx.store(lvalue.llval, alloc.llval, None);
|
bcx.store(place.llval, alloc.llval, None);
|
||||||
alloc.llval
|
alloc.llval
|
||||||
} else {
|
} else {
|
||||||
lvalue.llval
|
place.llval
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() {
|
for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() {
|
||||||
|
@ -580,14 +580,14 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
LocalRef::Place(lvalue)
|
LocalRef::Place(place)
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
mod analyze;
|
mod analyze;
|
||||||
mod block;
|
mod block;
|
||||||
mod constant;
|
mod constant;
|
||||||
pub mod lvalue;
|
pub mod place;
|
||||||
pub mod operand;
|
pub mod operand;
|
||||||
mod rvalue;
|
mod rvalue;
|
||||||
mod statement;
|
mod statement;
|
||||||
|
|
|
@ -25,7 +25,7 @@ use std::fmt;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use super::{MirContext, LocalRef};
|
use super::{MirContext, LocalRef};
|
||||||
use super::lvalue::{Alignment, PlaceRef};
|
use super::place::{Alignment, PlaceRef};
|
||||||
|
|
||||||
/// The representation of a Rust value. The enum variant is in fact
|
/// The representation of a Rust value. The enum variant is in fact
|
||||||
/// uniquely determined by the value's type, but is kept as a
|
/// uniquely determined by the value's type, but is kept as a
|
||||||
|
@ -243,20 +243,20 @@ impl<'a, 'tcx> OperandValue {
|
||||||
impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
fn maybe_trans_consume_direct(&mut self,
|
fn maybe_trans_consume_direct(&mut self,
|
||||||
bcx: &Builder<'a, 'tcx>,
|
bcx: &Builder<'a, 'tcx>,
|
||||||
lvalue: &mir::Place<'tcx>)
|
place: &mir::Place<'tcx>)
|
||||||
-> Option<OperandRef<'tcx>>
|
-> Option<OperandRef<'tcx>>
|
||||||
{
|
{
|
||||||
debug!("maybe_trans_consume_direct(lvalue={:?})", lvalue);
|
debug!("maybe_trans_consume_direct(place={:?})", place);
|
||||||
|
|
||||||
// watch out for locals that do not have an
|
// watch out for locals that do not have an
|
||||||
// alloca; they are handled somewhat differently
|
// alloca; they are handled somewhat differently
|
||||||
if let mir::Place::Local(index) = *lvalue {
|
if let mir::Place::Local(index) = *place {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Operand(Some(o)) => {
|
LocalRef::Operand(Some(o)) => {
|
||||||
return Some(o);
|
return Some(o);
|
||||||
}
|
}
|
||||||
LocalRef::Operand(None) => {
|
LocalRef::Operand(None) => {
|
||||||
bug!("use of {:?} before def", lvalue);
|
bug!("use of {:?} before def", place);
|
||||||
}
|
}
|
||||||
LocalRef::Place(..) => {
|
LocalRef::Place(..) => {
|
||||||
// use path below
|
// use path below
|
||||||
|
@ -265,7 +265,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Moves out of scalar and scalar pair fields are trivial.
|
// Moves out of scalar and scalar pair fields are trivial.
|
||||||
if let &mir::Place::Projection(ref proj) = lvalue {
|
if let &mir::Place::Projection(ref proj) = place {
|
||||||
if let mir::ProjectionElem::Field(ref f, _) = proj.elem {
|
if let mir::ProjectionElem::Field(ref f, _) = proj.elem {
|
||||||
if let Some(o) = self.maybe_trans_consume_direct(bcx, &proj.base) {
|
if let Some(o) = self.maybe_trans_consume_direct(bcx, &proj.base) {
|
||||||
return Some(o.extract_field(bcx, f.index()));
|
return Some(o.extract_field(bcx, f.index()));
|
||||||
|
@ -278,12 +278,12 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
|
|
||||||
pub fn trans_consume(&mut self,
|
pub fn trans_consume(&mut self,
|
||||||
bcx: &Builder<'a, 'tcx>,
|
bcx: &Builder<'a, 'tcx>,
|
||||||
lvalue: &mir::Place<'tcx>)
|
place: &mir::Place<'tcx>)
|
||||||
-> OperandRef<'tcx>
|
-> OperandRef<'tcx>
|
||||||
{
|
{
|
||||||
debug!("trans_consume(lvalue={:?})", lvalue);
|
debug!("trans_consume(place={:?})", place);
|
||||||
|
|
||||||
let ty = self.monomorphized_lvalue_ty(lvalue);
|
let ty = self.monomorphized_place_ty(place);
|
||||||
let layout = bcx.ccx.layout_of(ty);
|
let layout = bcx.ccx.layout_of(ty);
|
||||||
|
|
||||||
// ZSTs don't require any actual memory access.
|
// ZSTs don't require any actual memory access.
|
||||||
|
@ -291,13 +291,13 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
return OperandRef::new_zst(bcx.ccx, layout);
|
return OperandRef::new_zst(bcx.ccx, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(o) = self.maybe_trans_consume_direct(bcx, lvalue) {
|
if let Some(o) = self.maybe_trans_consume_direct(bcx, place) {
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for most lvalues, to consume them we just load them
|
// for most places, to consume them we just load them
|
||||||
// out from their home
|
// out from their home
|
||||||
self.trans_lvalue(bcx, lvalue).load(bcx)
|
self.trans_place(bcx, place).load(bcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_operand(&mut self,
|
pub fn trans_operand(&mut self,
|
||||||
|
@ -308,9 +308,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
debug!("trans_operand(operand={:?})", operand);
|
debug!("trans_operand(operand={:?})", operand);
|
||||||
|
|
||||||
match *operand {
|
match *operand {
|
||||||
mir::Operand::Copy(ref lvalue) |
|
mir::Operand::Copy(ref place) |
|
||||||
mir::Operand::Move(ref lvalue) => {
|
mir::Operand::Move(ref place) => {
|
||||||
self.trans_consume(bcx, lvalue)
|
self.trans_consume(bcx, place)
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Operand::Constant(ref constant) => {
|
mir::Operand::Constant(ref constant) => {
|
||||||
|
|
|
@ -74,16 +74,16 @@ impl Alignment {
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct PlaceRef<'tcx> {
|
pub struct PlaceRef<'tcx> {
|
||||||
/// Pointer to the contents of the lvalue
|
/// Pointer to the contents of the place
|
||||||
pub llval: ValueRef,
|
pub llval: ValueRef,
|
||||||
|
|
||||||
/// This lvalue's extra data if it is unsized, or null
|
/// This place's extra data if it is unsized, or null
|
||||||
pub llextra: ValueRef,
|
pub llextra: ValueRef,
|
||||||
|
|
||||||
/// Monomorphized type of this lvalue, including variant information
|
/// Monomorphized type of this place, including variant information
|
||||||
pub layout: TyLayout<'tcx>,
|
pub layout: TyLayout<'tcx>,
|
||||||
|
|
||||||
/// Whether this lvalue is known to be aligned according to its layout
|
/// Whether this place is known to be aligned according to its layout
|
||||||
pub alignment: Alignment,
|
pub alignment: Alignment,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,27 +444,27 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
pub fn trans_lvalue(&mut self,
|
pub fn trans_place(&mut self,
|
||||||
bcx: &Builder<'a, 'tcx>,
|
bcx: &Builder<'a, 'tcx>,
|
||||||
lvalue: &mir::Place<'tcx>)
|
place: &mir::Place<'tcx>)
|
||||||
-> PlaceRef<'tcx> {
|
-> PlaceRef<'tcx> {
|
||||||
debug!("trans_lvalue(lvalue={:?})", lvalue);
|
debug!("trans_place(place={:?})", place);
|
||||||
|
|
||||||
let ccx = bcx.ccx;
|
let ccx = bcx.ccx;
|
||||||
let tcx = ccx.tcx();
|
let tcx = ccx.tcx();
|
||||||
|
|
||||||
if let mir::Place::Local(index) = *lvalue {
|
if let mir::Place::Local(index) = *place {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Place(lvalue) => {
|
LocalRef::Place(place) => {
|
||||||
return lvalue;
|
return place;
|
||||||
}
|
}
|
||||||
LocalRef::Operand(..) => {
|
LocalRef::Operand(..) => {
|
||||||
bug!("using operand local {:?} as lvalue", lvalue);
|
bug!("using operand local {:?} as place", place);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = match *lvalue {
|
let result = match *place {
|
||||||
mir::Place::Local(_) => bug!(), // handled above
|
mir::Place::Local(_) => bug!(), // handled above
|
||||||
mir::Place::Static(box mir::Static { def_id, ty }) => {
|
mir::Place::Static(box mir::Static { def_id, ty }) => {
|
||||||
PlaceRef::new_sized(consts::get_static(ccx, def_id),
|
PlaceRef::new_sized(consts::get_static(ccx, def_id),
|
||||||
|
@ -479,7 +479,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
self.trans_consume(bcx, base).deref(bcx.ccx)
|
self.trans_consume(bcx, base).deref(bcx.ccx)
|
||||||
}
|
}
|
||||||
mir::Place::Projection(ref projection) => {
|
mir::Place::Projection(ref projection) => {
|
||||||
let tr_base = self.trans_lvalue(bcx, &projection.base);
|
let tr_base = self.trans_place(bcx, &projection.base);
|
||||||
|
|
||||||
match projection.elem {
|
match projection.elem {
|
||||||
mir::ProjectionElem::Deref => bug!(),
|
mir::ProjectionElem::Deref => bug!(),
|
||||||
|
@ -519,7 +519,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
C_usize(bcx.ccx, (from as u64) + (to as u64)));
|
C_usize(bcx.ccx, (from as u64) + (to as u64)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cast the lvalue pointer type to the new
|
// Cast the place pointer type to the new
|
||||||
// array or slice type (*[%_; new_len]).
|
// array or slice type (*[%_; new_len]).
|
||||||
subslice.llval = bcx.pointercast(subslice.llval,
|
subslice.llval = bcx.pointercast(subslice.llval,
|
||||||
subslice.layout.llvm_type(bcx.ccx).ptr_to());
|
subslice.layout.llvm_type(bcx.ccx).ptr_to());
|
||||||
|
@ -532,14 +532,14 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
debug!("trans_lvalue(lvalue={:?}) => {:?}", lvalue, result);
|
debug!("trans_place(place={:?}) => {:?}", place, result);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn monomorphized_lvalue_ty(&self, lvalue: &mir::Place<'tcx>) -> Ty<'tcx> {
|
pub fn monomorphized_place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
|
||||||
let tcx = self.ccx.tcx();
|
let tcx = self.ccx.tcx();
|
||||||
let lvalue_ty = lvalue.ty(self.mir, tcx);
|
let place_ty = place.ty(self.mir, tcx);
|
||||||
self.monomorphize(&lvalue_ty.to_ty(tcx))
|
self.monomorphize(&place_ty.to_ty(tcx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ use value::Value;
|
||||||
use super::{MirContext, LocalRef};
|
use super::{MirContext, LocalRef};
|
||||||
use super::constant::const_scalar_checked_binop;
|
use super::constant::const_scalar_checked_binop;
|
||||||
use super::operand::{OperandRef, OperandValue};
|
use super::operand::{OperandRef, OperandValue};
|
||||||
use super::lvalue::PlaceRef;
|
use super::place::PlaceRef;
|
||||||
|
|
||||||
impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
pub fn trans_rvalue(&mut self,
|
pub fn trans_rvalue(&mut self,
|
||||||
|
@ -334,17 +334,17 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::Ref(_, bk, ref lvalue) => {
|
mir::Rvalue::Ref(_, bk, ref place) => {
|
||||||
let tr_lvalue = self.trans_lvalue(&bcx, lvalue);
|
let tr_place = self.trans_place(&bcx, place);
|
||||||
|
|
||||||
let ty = tr_lvalue.layout.ty;
|
let ty = tr_place.layout.ty;
|
||||||
|
|
||||||
// Note: lvalues are indirect, so storing the `llval` into the
|
// Note: places are indirect, so storing the `llval` into the
|
||||||
// destination effectively creates a reference.
|
// destination effectively creates a reference.
|
||||||
let val = if !bcx.ccx.shared().type_has_metadata(ty) {
|
let val = if !bcx.ccx.shared().type_has_metadata(ty) {
|
||||||
OperandValue::Immediate(tr_lvalue.llval)
|
OperandValue::Immediate(tr_place.llval)
|
||||||
} else {
|
} else {
|
||||||
OperandValue::Pair(tr_lvalue.llval, tr_lvalue.llextra)
|
OperandValue::Pair(tr_place.llval, tr_place.llextra)
|
||||||
};
|
};
|
||||||
(bcx, OperandRef {
|
(bcx, OperandRef {
|
||||||
val,
|
val,
|
||||||
|
@ -355,8 +355,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::Len(ref lvalue) => {
|
mir::Rvalue::Len(ref place) => {
|
||||||
let size = self.evaluate_array_len(&bcx, lvalue);
|
let size = self.evaluate_array_len(&bcx, place);
|
||||||
let operand = OperandRef {
|
let operand = OperandRef {
|
||||||
val: OperandValue::Immediate(size),
|
val: OperandValue::Immediate(size),
|
||||||
layout: bcx.ccx.layout_of(bcx.tcx().types.usize),
|
layout: bcx.ccx.layout_of(bcx.tcx().types.usize),
|
||||||
|
@ -424,9 +424,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::Discriminant(ref lvalue) => {
|
mir::Rvalue::Discriminant(ref place) => {
|
||||||
let discr_ty = rvalue.ty(&*self.mir, bcx.tcx());
|
let discr_ty = rvalue.ty(&*self.mir, bcx.tcx());
|
||||||
let discr = self.trans_lvalue(&bcx, lvalue)
|
let discr = self.trans_place(&bcx, place)
|
||||||
.trans_get_discr(&bcx, discr_ty);
|
.trans_get_discr(&bcx, discr_ty);
|
||||||
(bcx, OperandRef {
|
(bcx, OperandRef {
|
||||||
val: OperandValue::Immediate(discr),
|
val: OperandValue::Immediate(discr),
|
||||||
|
@ -486,11 +486,11 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
|
|
||||||
fn evaluate_array_len(&mut self,
|
fn evaluate_array_len(&mut self,
|
||||||
bcx: &Builder<'a, 'tcx>,
|
bcx: &Builder<'a, 'tcx>,
|
||||||
lvalue: &mir::Place<'tcx>) -> ValueRef
|
place: &mir::Place<'tcx>) -> ValueRef
|
||||||
{
|
{
|
||||||
// ZST are passed as operands and require special handling
|
// ZST are passed as operands and require special handling
|
||||||
// because trans_lvalue() panics if Local is operand.
|
// because trans_place() panics if Local is operand.
|
||||||
if let mir::Place::Local(index) = *lvalue {
|
if let mir::Place::Local(index) = *place {
|
||||||
if let LocalRef::Operand(Some(op)) = self.locals[index] {
|
if let LocalRef::Operand(Some(op)) = self.locals[index] {
|
||||||
if let ty::TyArray(_, n) = op.layout.ty.sty {
|
if let ty::TyArray(_, n) = op.layout.ty.sty {
|
||||||
let n = n.val.to_const_int().unwrap().to_u64().unwrap();
|
let n = n.val.to_const_int().unwrap().to_u64().unwrap();
|
||||||
|
@ -499,7 +499,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// use common size calculation for non zero-sized types
|
// use common size calculation for non zero-sized types
|
||||||
let tr_value = self.trans_lvalue(&bcx, lvalue);
|
let tr_value = self.trans_place(&bcx, place);
|
||||||
return tr_value.len(bcx.ccx);
|
return tr_value.len(bcx.ccx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
|
|
||||||
self.set_debug_loc(&bcx, statement.source_info);
|
self.set_debug_loc(&bcx, statement.source_info);
|
||||||
match statement.kind {
|
match statement.kind {
|
||||||
mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
|
mir::StatementKind::Assign(ref place, ref rvalue) => {
|
||||||
if let mir::Place::Local(index) = *lvalue {
|
if let mir::Place::Local(index) = *place {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Place(tr_dest) => {
|
LocalRef::Place(tr_dest) => {
|
||||||
self.trans_rvalue(bcx, tr_dest, rvalue)
|
self.trans_rvalue(bcx, tr_dest, rvalue)
|
||||||
|
@ -49,30 +49,30 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let tr_dest = self.trans_lvalue(&bcx, lvalue);
|
let tr_dest = self.trans_place(&bcx, place);
|
||||||
self.trans_rvalue(bcx, tr_dest, rvalue)
|
self.trans_rvalue(bcx, tr_dest, rvalue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::StatementKind::SetDiscriminant{ref lvalue, variant_index} => {
|
mir::StatementKind::SetDiscriminant{ref place, variant_index} => {
|
||||||
self.trans_lvalue(&bcx, lvalue)
|
self.trans_place(&bcx, place)
|
||||||
.trans_set_discr(&bcx, variant_index);
|
.trans_set_discr(&bcx, variant_index);
|
||||||
bcx
|
bcx
|
||||||
}
|
}
|
||||||
mir::StatementKind::StorageLive(local) => {
|
mir::StatementKind::StorageLive(local) => {
|
||||||
if let LocalRef::Place(tr_lval) = self.locals[local] {
|
if let LocalRef::Place(tr_place) = self.locals[local] {
|
||||||
tr_lval.storage_live(&bcx);
|
tr_place.storage_live(&bcx);
|
||||||
}
|
}
|
||||||
bcx
|
bcx
|
||||||
}
|
}
|
||||||
mir::StatementKind::StorageDead(local) => {
|
mir::StatementKind::StorageDead(local) => {
|
||||||
if let LocalRef::Place(tr_lval) = self.locals[local] {
|
if let LocalRef::Place(tr_place) = self.locals[local] {
|
||||||
tr_lval.storage_dead(&bcx);
|
tr_place.storage_dead(&bcx);
|
||||||
}
|
}
|
||||||
bcx
|
bcx
|
||||||
}
|
}
|
||||||
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||||
let outputs = outputs.iter().map(|output| {
|
let outputs = outputs.iter().map(|output| {
|
||||||
self.trans_lvalue(&bcx, output)
|
self.trans_place(&bcx, output)
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
let input_vals = inputs.iter().map(|input| {
|
let input_vals = inputs.iter().map(|input| {
|
||||||
|
|
Loading…
Add table
Reference in a new issue