type Item = BasicBlock;
type Iter = IntoIter<BasicBlock>;
}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
+pub struct Location {
+ /// the location is within this block
+ pub block: BasicBlock,
+
+ /// the location is the start of the this statement; or, if `statement_index`
+ /// == num-statements, then the start of the terminator.
+ pub statement_index: usize,
+}
+
fn visit_statement(&mut self,
block: BasicBlock,
- statement: & $($mutability)* Statement<'tcx>) {
- self.super_statement(block, statement);
+ statement: & $($mutability)* Statement<'tcx>,
+ location: Location) {
+ self.super_statement(block, statement, location);
}
fn visit_assign(&mut self,
block: BasicBlock,
lvalue: & $($mutability)* Lvalue<'tcx>,
- rvalue: & $($mutability)* Rvalue<'tcx>) {
- self.super_assign(block, lvalue, rvalue);
+ rvalue: & $($mutability)* Rvalue<'tcx>,
+ location: Location) {
+ self.super_assign(block, lvalue, rvalue, location);
}
fn visit_terminator(&mut self,
block: BasicBlock,
- terminator: & $($mutability)* Terminator<'tcx>) {
- self.super_terminator(block, terminator);
+ terminator: & $($mutability)* Terminator<'tcx>,
+ location: Location) {
+ self.super_terminator(block, terminator, location);
}
fn visit_terminator_kind(&mut self,
block: BasicBlock,
- kind: & $($mutability)* TerminatorKind<'tcx>) {
- self.super_terminator_kind(block, kind);
+ kind: & $($mutability)* TerminatorKind<'tcx>,
+ location: Location) {
+ self.super_terminator_kind(block, kind, location);
}
fn visit_assert_message(&mut self,
- msg: & $($mutability)* AssertMessage<'tcx>) {
- self.super_assert_message(msg);
+ msg: & $($mutability)* AssertMessage<'tcx>,
+ location: Location) {
+ self.super_assert_message(msg, location);
}
fn visit_rvalue(&mut self,
- rvalue: & $($mutability)* Rvalue<'tcx>) {
- self.super_rvalue(rvalue);
+ rvalue: & $($mutability)* Rvalue<'tcx>,
+ location: Location) {
+ self.super_rvalue(rvalue, location);
}
fn visit_operand(&mut self,
- operand: & $($mutability)* Operand<'tcx>) {
- self.super_operand(operand);
+ operand: & $($mutability)* Operand<'tcx>,
+ location: Location) {
+ self.super_operand(operand, location);
}
fn visit_lvalue(&mut self,
lvalue: & $($mutability)* Lvalue<'tcx>,
- context: LvalueContext) {
- self.super_lvalue(lvalue, context);
+ context: LvalueContext,
+ location: Location) {
+ self.super_lvalue(lvalue, context, location);
}
fn visit_projection(&mut self,
lvalue: & $($mutability)* LvalueProjection<'tcx>,
- context: LvalueContext) {
- self.super_projection(lvalue, context);
+ context: LvalueContext,
+ location: Location) {
+ self.super_projection(lvalue, context, location);
}
fn visit_projection_elem(&mut self,
lvalue: & $($mutability)* LvalueElem<'tcx>,
- context: LvalueContext) {
- self.super_projection_elem(lvalue, context);
+ context: LvalueContext,
+ location: Location) {
+ self.super_projection_elem(lvalue, context, location);
}
fn visit_branch(&mut self,
}
fn visit_constant(&mut self,
- constant: & $($mutability)* Constant<'tcx>) {
- self.super_constant(constant);
+ constant: & $($mutability)* Constant<'tcx>,
+ location: Location) {
+ self.super_constant(constant, location);
}
fn visit_literal(&mut self,
- literal: & $($mutability)* Literal<'tcx>) {
- self.super_literal(literal);
+ literal: & $($mutability)* Literal<'tcx>,
+ location: Location) {
+ self.super_literal(literal, location);
}
fn visit_def_id(&mut self,
- def_id: & $($mutability)* DefId) {
+ def_id: & $($mutability)* DefId,
+ _: Location) {
self.super_def_id(def_id);
}
}
fn visit_const_val(&mut self,
- const_val: & $($mutability)* ConstVal) {
+ const_val: & $($mutability)* ConstVal,
+ _: Location) {
self.super_const_val(const_val);
}
fn visit_const_usize(&mut self,
- const_usize: & $($mutability)* ConstUsize) {
+ const_usize: & $($mutability)* ConstUsize,
+ _: Location) {
self.super_const_usize(const_usize);
}
fn visit_typed_const_val(&mut self,
- val: & $($mutability)* TypedConstVal<'tcx>) {
- self.super_typed_const_val(val);
+ val: & $($mutability)* TypedConstVal<'tcx>,
+ location: Location) {
+ self.super_typed_const_val(val, location);
}
fn visit_var_decl(&mut self,
is_cleanup: _
} = *data;
+ let mut index = 0;
for statement in statements {
- self.visit_statement(block, statement);
+ let location = Location { block: block, statement_index: index };
+ self.visit_statement(block, statement, location);
+ index += 1;
}
if let Some(ref $($mutability)* terminator) = *terminator {
- self.visit_terminator(block, terminator);
+ let location = Location { block: block, statement_index: index };
+ self.visit_terminator(block, terminator, location);
}
}
fn super_statement(&mut self,
block: BasicBlock,
- statement: & $($mutability)* Statement<'tcx>) {
+ statement: & $($mutability)* Statement<'tcx>,
+ location: Location) {
let Statement {
ref $($mutability)* source_info,
ref $($mutability)* kind,
match *kind {
StatementKind::Assign(ref $($mutability)* lvalue,
ref $($mutability)* rvalue) => {
- self.visit_assign(block, lvalue, rvalue);
+ self.visit_assign(block, lvalue, rvalue, location);
}
StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
- self.visit_lvalue(lvalue, LvalueContext::Store);
+ self.visit_lvalue(lvalue, LvalueContext::Store, location);
}
StatementKind::StorageLive(ref $($mutability)* lvalue) => {
- self.visit_lvalue(lvalue, LvalueContext::StorageLive);
+ self.visit_lvalue(lvalue, LvalueContext::StorageLive, location);
}
StatementKind::StorageDead(ref $($mutability)* lvalue) => {
- self.visit_lvalue(lvalue, LvalueContext::StorageDead);
+ self.visit_lvalue(lvalue, LvalueContext::StorageDead, location);
}
}
}
fn super_assign(&mut self,
_block: BasicBlock,
lvalue: &$($mutability)* Lvalue<'tcx>,
- rvalue: &$($mutability)* Rvalue<'tcx>) {
- self.visit_lvalue(lvalue, LvalueContext::Store);
- self.visit_rvalue(rvalue);
+ rvalue: &$($mutability)* Rvalue<'tcx>,
+ location: Location) {
+ self.visit_lvalue(lvalue, LvalueContext::Store, location);
+ self.visit_rvalue(rvalue, location);
}
fn super_terminator(&mut self,
block: BasicBlock,
- terminator: &$($mutability)* Terminator<'tcx>) {
+ terminator: &$($mutability)* Terminator<'tcx>,
+ location: Location) {
let Terminator {
ref $($mutability)* source_info,
ref $($mutability)* kind,
} = *terminator;
self.visit_source_info(source_info);
- self.visit_terminator_kind(block, kind);
+ self.visit_terminator_kind(block, kind, location);
}
fn super_terminator_kind(&mut self,
block: BasicBlock,
- kind: & $($mutability)* TerminatorKind<'tcx>) {
+ kind: & $($mutability)* TerminatorKind<'tcx>,
+ source_location: Location) {
match *kind {
TerminatorKind::Goto { target } => {
self.visit_branch(block, target);
TerminatorKind::If { ref $($mutability)* cond,
ref $($mutability)* targets } => {
- self.visit_operand(cond);
+ self.visit_operand(cond, source_location);
for &target in targets.as_slice() {
self.visit_branch(block, target);
}
TerminatorKind::Switch { ref $($mutability)* discr,
adt_def: _,
ref targets } => {
- self.visit_lvalue(discr, LvalueContext::Inspect);
+ self.visit_lvalue(discr, LvalueContext::Inspect, source_location);
for &target in targets {
self.visit_branch(block, target);
}
ref $($mutability)* switch_ty,
ref $($mutability)* values,
ref targets } => {
- self.visit_lvalue(discr, LvalueContext::Inspect);
+ self.visit_lvalue(discr, LvalueContext::Inspect, source_location);
self.visit_ty(switch_ty);
for value in values {
- self.visit_const_val(value);
+ self.visit_const_val(value, source_location);
}
for &target in targets {
self.visit_branch(block, target);
TerminatorKind::Drop { ref $($mutability)* location,
target,
unwind } => {
- self.visit_lvalue(location, LvalueContext::Drop);
+ self.visit_lvalue(location, LvalueContext::Drop, source_location);
self.visit_branch(block, target);
unwind.map(|t| self.visit_branch(block, t));
}
ref $($mutability)* value,
target,
unwind } => {
- self.visit_lvalue(location, LvalueContext::Drop);
- self.visit_operand(value);
+ self.visit_lvalue(location, LvalueContext::Drop, source_location);
+ self.visit_operand(value, source_location);
self.visit_branch(block, target);
unwind.map(|t| self.visit_branch(block, t));
}
ref $($mutability)* args,
ref $($mutability)* destination,
cleanup } => {
- self.visit_operand(func);
+ self.visit_operand(func, source_location);
for arg in args {
- self.visit_operand(arg);
+ self.visit_operand(arg, source_location);
}
if let Some((ref $($mutability)* destination, target)) = *destination {
- self.visit_lvalue(destination, LvalueContext::Call);
+ self.visit_lvalue(destination, LvalueContext::Call, source_location);
self.visit_branch(block, target);
}
cleanup.map(|t| self.visit_branch(block, t));
ref $($mutability)* msg,
target,
cleanup } => {
- self.visit_operand(cond);
- self.visit_assert_message(msg);
+ self.visit_operand(cond, source_location);
+ self.visit_assert_message(msg, source_location);
self.visit_branch(block, target);
cleanup.map(|t| self.visit_branch(block, t));
}
}
fn super_assert_message(&mut self,
- msg: & $($mutability)* AssertMessage<'tcx>) {
+ msg: & $($mutability)* AssertMessage<'tcx>,
+ location: Location) {
match *msg {
AssertMessage::BoundsCheck {
ref $($mutability)* len,
ref $($mutability)* index
} => {
- self.visit_operand(len);
- self.visit_operand(index);
+ self.visit_operand(len, location);
+ self.visit_operand(index, location);
}
AssertMessage::Math(_) => {}
}
}
fn super_rvalue(&mut self,
- rvalue: & $($mutability)* Rvalue<'tcx>) {
+ rvalue: & $($mutability)* Rvalue<'tcx>,
+ location: Location) {
match *rvalue {
Rvalue::Use(ref $($mutability)* operand) => {
- self.visit_operand(operand);
+ self.visit_operand(operand, location);
}
Rvalue::Repeat(ref $($mutability)* value,
ref $($mutability)* typed_const_val) => {
- self.visit_operand(value);
- self.visit_typed_const_val(typed_const_val);
+ self.visit_operand(value, location);
+ self.visit_typed_const_val(typed_const_val, location);
}
Rvalue::Ref(r, bk, ref $($mutability)* path) => {
self.visit_lvalue(path, LvalueContext::Borrow {
region: r,
kind: bk
- });
+ }, location);
}
Rvalue::Len(ref $($mutability)* path) => {
- self.visit_lvalue(path, LvalueContext::Inspect);
+ self.visit_lvalue(path, LvalueContext::Inspect, location);
}
Rvalue::Cast(_cast_kind,
ref $($mutability)* operand,
ref $($mutability)* ty) => {
- self.visit_operand(operand);
+ self.visit_operand(operand, location);
self.visit_ty(ty);
}
Rvalue::CheckedBinaryOp(_bin_op,
ref $($mutability)* lhs,
ref $($mutability)* rhs) => {
- self.visit_operand(lhs);
- self.visit_operand(rhs);
+ self.visit_operand(lhs, location);
+ self.visit_operand(rhs, location);
}
Rvalue::UnaryOp(_un_op, ref $($mutability)* op) => {
- self.visit_operand(op);
+ self.visit_operand(op, location);
}
Rvalue::Box(ref $($mutability)* ty) => {
}
AggregateKind::Closure(ref $($mutability)* def_id,
ref $($mutability)* closure_substs) => {
- self.visit_def_id(def_id);
+ self.visit_def_id(def_id, location);
self.visit_closure_substs(closure_substs);
}
}
for operand in operands {
- self.visit_operand(operand);
+ self.visit_operand(operand, location);
}
}
ref $($mutability)* inputs,
asm: _ } => {
for output in & $($mutability)* outputs[..] {
- self.visit_lvalue(output, LvalueContext::Store);
+ self.visit_lvalue(output, LvalueContext::Store, location);
}
for input in & $($mutability)* inputs[..] {
- self.visit_operand(input);
+ self.visit_operand(input, location);
}
}
}
}
fn super_operand(&mut self,
- operand: & $($mutability)* Operand<'tcx>) {
+ operand: & $($mutability)* Operand<'tcx>,
+ location: Location) {
match *operand {
Operand::Consume(ref $($mutability)* lvalue) => {
- self.visit_lvalue(lvalue, LvalueContext::Consume);
+ self.visit_lvalue(lvalue, LvalueContext::Consume, location);
}
Operand::Constant(ref $($mutability)* constant) => {
- self.visit_constant(constant);
+ self.visit_constant(constant, location);
}
}
}
fn super_lvalue(&mut self,
lvalue: & $($mutability)* Lvalue<'tcx>,
- context: LvalueContext) {
+ context: LvalueContext,
+ location: Location) {
match *lvalue {
Lvalue::Var(_) |
Lvalue::Temp(_) |
Lvalue::ReturnPointer => {
}
Lvalue::Static(ref $($mutability)* def_id) => {
- self.visit_def_id(def_id);
+ self.visit_def_id(def_id, location);
}
Lvalue::Projection(ref $($mutability)* proj) => {
- self.visit_projection(proj, context);
+ self.visit_projection(proj, context, location);
}
}
}
fn super_projection(&mut self,
proj: & $($mutability)* LvalueProjection<'tcx>,
- context: LvalueContext) {
+ context: LvalueContext,
+ location: Location) {
let Projection {
ref $($mutability)* base,
ref $($mutability)* elem,
} = *proj;
- self.visit_lvalue(base, LvalueContext::Projection);
- self.visit_projection_elem(elem, context);
+ self.visit_lvalue(base, LvalueContext::Projection, location);
+ self.visit_projection_elem(elem, context, location);
}
fn super_projection_elem(&mut self,
proj: & $($mutability)* LvalueElem<'tcx>,
- _context: LvalueContext) {
+ _context: LvalueContext,
+ location: Location) {
match *proj {
ProjectionElem::Deref => {
}
self.visit_ty(ty);
}
ProjectionElem::Index(ref $($mutability)* operand) => {
- self.visit_operand(operand);
+ self.visit_operand(operand, location);
}
ProjectionElem::ConstantIndex { offset: _,
min_length: _,
}
fn super_constant(&mut self,
- constant: & $($mutability)* Constant<'tcx>) {
+ constant: & $($mutability)* Constant<'tcx>,
+ location: Location) {
let Constant {
ref $($mutability)* span,
ref $($mutability)* ty,
self.visit_span(span);
self.visit_ty(ty);
- self.visit_literal(literal);
+ self.visit_literal(literal, location);
}
fn super_typed_const_val(&mut self,
- constant: & $($mutability)* TypedConstVal<'tcx>) {
+ constant: & $($mutability)* TypedConstVal<'tcx>,
+ location: Location) {
let TypedConstVal {
ref $($mutability)* span,
ref $($mutability)* ty,
self.visit_span(span);
self.visit_ty(ty);
- self.visit_const_usize(value);
+ self.visit_const_usize(value, location);
}
fn super_literal(&mut self,
- literal: & $($mutability)* Literal<'tcx>) {
+ literal: & $($mutability)* Literal<'tcx>,
+ location: Location) {
match *literal {
Literal::Item { ref $($mutability)* def_id,
ref $($mutability)* substs } => {
- self.visit_def_id(def_id);
+ self.visit_def_id(def_id, location);
self.visit_substs(substs);
}
Literal::Value { ref $($mutability)* value } => {
- self.visit_const_val(value);
+ self.visit_const_val(value, location);
}
Literal::Promoted { index: _ } => {}
}
// except according to those terms.
use rustc::ty::TyCtxt;
-use rustc::mir::repr::{self, Mir};
+use rustc::mir::repr::{self, Mir, Location};
use rustc_data_structures::indexed_vec::Idx;
-use super::super::gather_moves::{Location};
use super::super::gather_moves::{MoveOutIndex, MovePathIndex};
use super::super::MoveDataParamEnv;
use super::super::DropFlagState;
{
drop_flag_effects_for_location(
self.tcx, self.mir, ctxt,
- Location { block: bb, index: idx },
+ Location { block: bb, statement_index: idx },
|path, s| Self::update_bits(sets, path, s)
)
}
{
drop_flag_effects_for_location(
self.tcx, self.mir, ctxt,
- Location { block: bb, index: statements_len },
+ Location { block: bb, statement_index: statements_len },
|path, s| Self::update_bits(sets, path, s)
)
}
{
drop_flag_effects_for_location(
self.tcx, self.mir, ctxt,
- Location { block: bb, index: idx },
+ Location { block: bb, statement_index: idx },
|path, s| Self::update_bits(sets, path, s)
)
}
{
drop_flag_effects_for_location(
self.tcx, self.mir, ctxt,
- Location { block: bb, index: statements_len },
+ Location { block: bb, statement_index: statements_len },
|path, s| Self::update_bits(sets, path, s)
)
}
{
drop_flag_effects_for_location(
self.tcx, self.mir, ctxt,
- Location { block: bb, index: idx },
+ Location { block: bb, statement_index: idx },
|path, s| Self::update_bits(sets, path, s)
)
}
{
drop_flag_effects_for_location(
self.tcx, self.mir, ctxt,
- Location { block: bb, index: statements_len },
+ Location { block: bb, statement_index: statements_len },
|path, s| Self::update_bits(sets, path, s)
)
}
let path_map = &move_data.path_map;
let rev_lookup = &move_data.rev_lookup;
- let loc = Location { block: bb, index: idx };
+ let loc = Location { block: bb, statement_index: idx };
debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}",
stmt, loc, &loc_map[loc]);
for move_index in &loc_map[loc] {
let (mir, move_data) = (self.mir, &ctxt.move_data);
let term = mir[bb].terminator();
let loc_map = &move_data.loc_map;
- let loc = Location { block: bb, index: statements_len };
+ let loc = Location { block: bb, statement_index: statements_len };
debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}",
term, loc, &loc_map[loc]);
let bits_per_block = self.bits_per_block(ctxt);
// except according to those terms.
use indexed_set::IdxSetBuf;
-use super::gather_moves::{MoveData, MovePathIndex, MovePathContent, Location};
+use super::gather_moves::{MoveData, MovePathIndex, MovePathContent};
use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
use super::dataflow::{DataflowResults};
use super::{drop_flag_effects_for_location, on_all_children_bits};
dead: self.flow_uninits.sets().on_entry_set_for(loc.block.index())
.to_owned(),
};
- for stmt in 0..loc.index {
+ for stmt in 0..loc.statement_index {
data.apply_location(self.tcx, self.mir, self.env,
- Location { block: loc.block, index: stmt });
+ Location { block: loc.block, statement_index: stmt });
}
data
}
let init_data = self.initialization_data_at(Location {
block: bb,
- index: data.statements.len()
+ statement_index: data.statements.len()
});
let path = self.move_data().rev_lookup.find(location);
fn elaborate_drops(&mut self)
{
for (bb, data) in self.mir.basic_blocks().iter_enumerated() {
- let loc = Location { block: bb, index: data.statements.len() };
+ let loc = Location { block: bb, statement_index: data.statements.len() };
let terminator = data.terminator();
let resume_block = self.patch.resume_block();
unwind: Some(unwind)
}, bb);
on_all_children_bits(self.tcx, self.mir, self.move_data(), path, |child| {
- self.set_drop_flag(Location { block: target, index: 0 },
+ self.set_drop_flag(Location { block: target, statement_index: 0 },
child, DropFlagState::Present);
- self.set_drop_flag(Location { block: unwind, index: 0 },
+ self.set_drop_flag(Location { block: unwind, statement_index: 0 },
child, DropFlagState::Present);
});
}
let drop_block = self.drop_block(c);
if update_drop_flag {
self.set_drop_flag(
- Location { block: drop_block, index: 0 },
+ Location { block: drop_block, statement_index: 0 },
c.path,
DropFlagState::Absent
);
}
fn drop_flags_on_init(&mut self) {
- let loc = Location { block: START_BLOCK, index: 0 };
+ let loc = Location { block: START_BLOCK, statement_index: 0 };
let span = self.patch.source_info_for_location(self.mir, loc).span;
let false_ = self.constant_bool(span, false);
for flag in self.drop_flags.values() {
} = data.terminator().kind {
assert!(!self.patch.is_patched(bb));
- let loc = Location { block: tgt, index: 0 };
+ let loc = Location { block: tgt, statement_index: 0 };
let path = self.move_data().rev_lookup.find(lv);
on_all_children_bits(
self.tcx, self.mir, self.move_data(), path,
}
fn drop_flags_for_args(&mut self) {
- let loc = Location { block: START_BLOCK, index: 0 };
+ let loc = Location { block: START_BLOCK, statement_index: 0 };
super::drop_flag_effects_for_function_entry(
self.tcx, self.mir, self.env, |path, ds| {
self.set_drop_flag(loc, path, ds);
}
}
}
- let loc = Location { block: bb, index: i };
+ let loc = Location { block: bb, statement_index: i };
super::drop_flag_effects_for_location(
self.tcx, self.mir, self.env, loc, |path, ds| {
if ds == DropFlagState::Absent || allow_initializations {
} = data.terminator().kind {
assert!(!self.patch.is_patched(bb));
- let loc = Location { block: bb, index: data.statements.len() };
+ let loc = Location { block: bb, statement_index: data.statements.len() };
let path = self.move_data().rev_lookup.find(lv);
on_all_children_bits(
self.tcx, self.mir, self.move_data(), path,
type Output = [MoveOutIndex];
fn index(&self, index: Location) -> &Self::Output {
assert!(index.block.index() < self.map.len());
- assert!(index.index < self.map[index.block.index()].len());
- &self.map[index.block.index()][index.index]
+ assert!(index.statement_index < self.map[index.block.index()].len());
+ &self.map[index.block.index()][index.statement_index]
}
}
}
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Location {
- /// block where action is located
- pub block: BasicBlock,
- /// index within above block; statement when < statments.len) or
- /// the terminator (when = statements.len).
- pub index: usize,
-}
-
-impl fmt::Debug for Location {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- write!(fmt, "{:?}[{}]", self.block, self.index)
- }
-}
-
#[derive(Debug)]
pub struct MovePathData<'tcx> {
move_paths: Vec<MovePath<'tcx>>,
};
for (i, stmt) in bb_data.statements.iter().enumerate() {
- let source = Location { block: bb, index: i };
+ let source = Location { block: bb, statement_index: i };
match stmt.kind {
StatementKind::Assign(ref lval, ref rval) => {
bb_ctxt.builder.create_move_path(lval);
TerminatorKind::If { ref cond, targets: _ } => {
let source = Location { block: bb,
- index: bb_data.statements.len() };
+ statement_index: bb_data.statements.len() };
bb_ctxt.on_operand(SK::If, cond, source);
}
TerminatorKind::Drop { ref location, target: _, unwind: _ } => {
let source = Location { block: bb,
- index: bb_data.statements.len() };
+ statement_index: bb_data.statements.len() };
bb_ctxt.on_move_out_lval(SK::Drop, location, source);
}
TerminatorKind::DropAndReplace { ref location, ref value, .. } => {
bb_ctxt.path_map.fill_to(assigned_path.index());
let source = Location { block: bb,
- index: bb_data.statements.len() };
+ statement_index: bb_data.statements.len() };
bb_ctxt.on_operand(SK::Use, value, source);
}
TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => {
let source = Location { block: bb,
- index: bb_data.statements.len() };
+ statement_index: bb_data.statements.len() };
bb_ctxt.on_operand(SK::CallFn, func, source);
for arg in args {
debug!("gather_moves Call on_operand {:?} {:?}", arg, source);
stmt_kind: StmtKind,
lval: &Lvalue<'tcx>,
source: Location) {
- let i = source.index;
+ let i = source.statement_index;
let index = MoveOutIndex::new(self.moves.len());
let path = self.builder.move_path_for(lval);
use rustc::hir::intravisit::{FnKind};
use rustc::mir::repr;
-use rustc::mir::repr::{BasicBlock, BasicBlockData, Mir, Statement, Terminator};
+use rustc::mir::repr::{BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location};
use rustc::session::Session;
use rustc::ty::{self, TyCtxt};
use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults};
use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
use self::dataflow::{DefinitelyInitializedLvals};
-use self::gather_moves::{MoveData, MovePathIndex, Location};
+use self::gather_moves::{MoveData, MovePathIndex};
use self::gather_moves::{MovePathContent, MovePathData};
fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<P<MetaItem>> {
}
let block = &mir[loc.block];
- match block.statements.get(loc.index) {
+ match block.statements.get(loc.statement_index) {
Some(stmt) => match stmt.kind {
repr::StatementKind::SetDiscriminant{ .. } => {
span_bug!(stmt.source_info.span, "SetDiscrimant should not exist during borrowck");
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use super::gather_moves::Location;
use rustc::ty::Ty;
use rustc::mir::repr::*;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
};
Location {
block: bb,
- index: offset
+ statement_index: offset
}
}
}
debug!("MirPatch: adding statement {:?} at loc {:?}+{}",
stmt, loc, delta);
- loc.index += delta;
+ loc.statement_index += delta;
let source_info = Self::source_info_for_index(
&mir[loc.block], loc
);
mir[loc.block].statements.insert(
- loc.index, Statement {
+ loc.statement_index, Statement {
source_info: source_info,
kind: stmt
});
}
pub fn source_info_for_index(data: &BasicBlockData, loc: Location) -> SourceInfo {
- match data.statements.get(loc.index) {
+ match data.statements.get(loc.statement_index) {
Some(stmt) => stmt.source_info,
None => data.terminator().source_info
}
use rustc::mir;
use rustc::mir::visit::MutVisitor;
+use rustc::mir::repr::Location;
use std::cell::Cell;
use std::io;
impl<'v, 'cdata, 'codemap> mir::visit::MutVisitor<'v>
for MirDefIdAndSpanTranslator<'cdata, 'codemap>
{
- fn visit_def_id(&mut self, def_id: &mut DefId) {
+ fn visit_def_id(&mut self, def_id: &mut DefId, _: Location) {
*def_id = translate_def_id(self.crate_metadata, *def_id);
}
//! Routines for manipulating the control-flow graph.
-use build::{CFG, Location};
+use build::CFG;
use rustc::mir::repr::*;
impl<'tcx> CFG<'tcx> {
pub postdoms: Vec<Location>,
}
-#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
-pub struct Location {
- /// the location is within this block
- pub block: BasicBlock,
-
- /// the location is the start of the this statement; or, if `statement_index`
- /// == num-statements, then the start of the terminator.
- pub statement_index: usize,
-}
-
pub type ScopeAuxiliaryVec = IndexVec<ScopeId, ScopeAuxiliary>;
///////////////////////////////////////////////////////////////////////////
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use build::{Location, ScopeAuxiliaryVec, ScopeId};
+use build::{ScopeAuxiliaryVec, ScopeId};
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::mir::repr::*;
pub struct NoLandingPads;
impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
- fn visit_terminator(&mut self, bb: BasicBlock, terminator: &mut Terminator<'tcx>) {
+ fn visit_terminator(&mut self,
+ bb: BasicBlock,
+ terminator: &mut Terminator<'tcx>,
+ location: Location) {
match terminator.kind {
TerminatorKind::Goto { .. } |
TerminatorKind::Resume |
unwind.take();
},
}
- self.super_terminator(bb, terminator);
+ self.super_terminator(bb, terminator, location);
}
}
use rustc::ty::TyCtxt;
use syntax_pos::Span;
-use build::Location;
-
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use std::mem;
+use std::usize;
/// State of a temporary during collection and promotion.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
struct TempCollector {
temps: IndexVec<Temp, TempState>,
- location: Location,
span: Span
}
impl<'tcx> Visitor<'tcx> for TempCollector {
- fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext) {
- self.super_lvalue(lvalue, context);
+ fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext, location: Location) {
+ self.super_lvalue(lvalue, context, location);
if let Lvalue::Temp(index) = *lvalue {
// Ignore drops, if the temp gets promoted,
// then it's constant and thus drop is noop.
LvalueContext::Store |
LvalueContext::Call => {
*temp = TempState::Defined {
- location: self.location,
+ location: location,
uses: 0
};
return;
fn visit_source_info(&mut self, source_info: &SourceInfo) {
self.span = source_info.span;
}
-
- fn visit_statement(&mut self, bb: BasicBlock, statement: &Statement<'tcx>) {
- assert_eq!(self.location.block, bb);
- self.super_statement(bb, statement);
- self.location.statement_index += 1;
- }
-
- fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) {
- self.location.statement_index = 0;
- self.location.block = bb;
- self.super_basic_block_data(bb, data);
- }
}
pub fn collect_temps(mir: &Mir, rpo: &mut ReversePostorder) -> IndexVec<Temp, TempState> {
let mut collector = TempCollector {
temps: IndexVec::from_elem(TempState::Undefined, &mir.temp_decls),
- location: Location {
- block: START_BLOCK,
- statement_index: 0
- },
span: mir.span
};
for (bb, data) in rpo {
// Then, recurse for components in the Rvalue or Call.
if stmt_idx < no_stmts {
- self.visit_rvalue(rvalue.as_mut().unwrap());
+ self.visit_rvalue(rvalue.as_mut().unwrap(), Location {
+ block: bb,
+ statement_index: stmt_idx
+ });
} else {
- self.visit_terminator_kind(bb, call.as_mut().unwrap());
+ self.visit_terminator_kind(bb, call.as_mut().unwrap(), Location {
+ block: bb,
+ statement_index: no_stmts
+ });
}
let new_temp = self.promoted.temp_decls.push(TempDecl {
}
}
};
- self.visit_rvalue(&mut rvalue);
+ self.visit_rvalue(&mut rvalue, Location{
+ block: BasicBlock::new(0),
+ statement_index: usize::MAX
+ });
self.assign(Lvalue::ReturnPointer, rvalue, span);
self.source.promoted.push(self.promoted);
}
/// Replaces all temporaries with their promoted counterparts.
impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
- fn visit_lvalue(&mut self, lvalue: &mut Lvalue<'tcx>, context: LvalueContext) {
+ fn visit_lvalue(&mut self,
+ lvalue: &mut Lvalue<'tcx>,
+ context: LvalueContext,
+ location: Location) {
if let Lvalue::Temp(ref mut temp) = *lvalue {
*temp = self.promote_temp(*temp);
}
- self.super_lvalue(lvalue, context);
+ self.super_lvalue(lvalue, context, location);
}
}
use std::collections::hash_map::Entry;
use std::fmt;
-use build::Location;
-
use super::promote_consts::{self, Candidate, TempState};
bitflags! {
return_qualif: Option<Qualif>,
qualif: Qualif,
const_fn_arg_vars: BitVector,
- location: Location,
temp_promotion_state: IndexVec<Temp, TempState>,
promotion_candidates: Vec<Candidate>
}
return_qualif: None,
qualif: Qualif::empty(),
const_fn_arg_vars: BitVector::new(mir.var_decls.len()),
- location: Location {
- block: START_BLOCK,
- statement_index: 0
- },
temp_promotion_state: temps,
promotion_candidates: vec![]
}
}
/// Assign the current qualification to the given destination.
- fn assign(&mut self, dest: &Lvalue<'tcx>) {
+ fn assign(&mut self, dest: &Lvalue<'tcx>, location: Location) {
let qualif = self.qualif;
let span = self.span;
let store = |slot: &mut Option<Qualif>| {
// This must be an explicit assignment.
_ => {
// Catch more errors in the destination.
- self.visit_lvalue(dest, LvalueContext::Store);
+ self.visit_lvalue(dest, LvalueContext::Store, location);
self.statement_like();
}
}
self.qualif = Qualif::NOT_CONST;
for index in 0..mir.var_decls.len() {
if !self.const_fn_arg_vars.contains(index) {
- self.assign(&Lvalue::Var(Var::new(index)));
+ self.assign(&Lvalue::Var(Var::new(index)), Location {
+ block: BasicBlock::new(0),
+ statement_index: 0
+ });
}
}
/// For functions (constant or not), it also records
/// candidates for promotion in promotion_candidates.
impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
- fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext) {
+ fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext, location: Location) {
match *lvalue {
Lvalue::Arg(_) => {
self.add(Qualif::FN_ARGUMENT);
}
Lvalue::Projection(ref proj) => {
self.nest(|this| {
- this.super_lvalue(lvalue, context);
+ this.super_lvalue(lvalue, context, location);
match proj.elem {
ProjectionElem::Deref => {
if !this.try_consume() {
}
}
- fn visit_operand(&mut self, operand: &Operand<'tcx>) {
+ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
match *operand {
Operand::Consume(_) => {
self.nest(|this| {
- this.super_operand(operand);
+ this.super_operand(operand, location);
this.try_consume();
});
}
}
}
- fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
+ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
// Recurse through operands and lvalues.
- self.super_rvalue(rvalue);
+ self.super_rvalue(rvalue, location);
match *rvalue {
Rvalue::Use(_) |
}
// We might have a candidate for promotion.
- let candidate = Candidate::Ref(self.location);
+ let candidate = Candidate::Ref(location);
if self.mode == Mode::Fn || self.mode == Mode::ConstFn {
if !self.qualif.intersects(Qualif::NEVER_PROMOTE) {
// We can only promote direct borrows of temps.
}
}
- fn visit_terminator_kind(&mut self, bb: BasicBlock, kind: &TerminatorKind<'tcx>) {
+ fn visit_terminator_kind(&mut self,
+ bb: BasicBlock,
+ kind: &TerminatorKind<'tcx>,
+ location: Location) {
if let TerminatorKind::Call { ref func, ref args, ref destination, .. } = *kind {
- self.visit_operand(func);
+ self.visit_operand(func, location);
let fn_ty = func.ty(self.mir, self.tcx);
let (is_shuffle, is_const_fn) = match fn_ty.sty {
for (i, arg) in args.iter().enumerate() {
self.nest(|this| {
- this.visit_operand(arg);
+ this.visit_operand(arg, location);
if is_shuffle && i == 2 && this.mode == Mode::Fn {
let candidate = Candidate::ShuffleIndices(bb);
if !this.qualif.intersects(Qualif::NEVER_PROMOTE) {
self.deny_drop();
}
}
- self.assign(dest);
+ self.assign(dest, location);
}
} else {
// Qualify any operands inside other terminators.
- self.super_terminator_kind(bb, kind);
+ self.super_terminator_kind(bb, kind, location);
}
}
- fn visit_assign(&mut self, _: BasicBlock, dest: &Lvalue<'tcx>, rvalue: &Rvalue<'tcx>) {
- self.visit_rvalue(rvalue);
+ fn visit_assign(&mut self,
+ _: BasicBlock,
+ dest: &Lvalue<'tcx>,
+ rvalue: &Rvalue<'tcx>,
+ location: Location) {
+ self.visit_rvalue(rvalue, location);
// Check the allowed const fn argument forms.
if let (Mode::ConstFn, &Lvalue::Var(index)) = (self.mode, dest) {
}
}
- self.assign(dest);
+ self.assign(dest, location);
}
fn visit_source_info(&mut self, source_info: &SourceInfo) {
self.span = source_info.span;
}
- fn visit_statement(&mut self, bb: BasicBlock, statement: &Statement<'tcx>) {
- assert_eq!(self.location.block, bb);
- self.nest(|this| {
- this.visit_source_info(&statement.source_info);
- match statement.kind {
- StatementKind::Assign(ref lvalue, ref rvalue) => {
- this.visit_assign(bb, lvalue, rvalue);
- }
- StatementKind::SetDiscriminant { .. } |
- StatementKind::StorageLive(_) |
- StatementKind::StorageDead(_) => {}
- }
- });
- self.location.statement_index += 1;
- }
-
- fn visit_terminator(&mut self, bb: BasicBlock, terminator: &Terminator<'tcx>) {
- assert_eq!(self.location.block, bb);
- self.nest(|this| this.super_terminator(bb, terminator));
+ fn visit_statement(&mut self, bb: BasicBlock, statement: &Statement<'tcx>, location: Location) {
+ self.nest(|this| this.super_statement(bb, statement, location));
}
- fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) {
- self.location.statement_index = 0;
- self.location.block = bb;
- self.super_basic_block_data(bb, data);
+ fn visit_terminator(&mut self,
+ bb: BasicBlock,
+ terminator: &Terminator<'tcx>,
+ location: Location) {
+ self.nest(|this| this.super_terminator(bb, terminator, location));
}
}
}
}
- fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, _context: visit::LvalueContext) {
- self.sanitize_lvalue(lvalue);
+ fn visit_lvalue(&mut self,
+ lvalue: &Lvalue<'tcx>,
+ _context: visit::LvalueContext,
+ location: Location) {
+ self.sanitize_lvalue(lvalue, location);
}
- fn visit_constant(&mut self, constant: &Constant<'tcx>) {
- self.super_constant(constant);
+ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
+ self.super_constant(constant, location);
self.sanitize_type(constant, constant.ty);
}
- fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
- self.super_rvalue(rvalue);
+ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+ self.super_rvalue(rvalue, location);
if let Some(ty) = rvalue.ty(self.mir, self.tcx()) {
self.sanitize_type(rvalue, ty);
}
}
}
- fn sanitize_lvalue(&mut self, lvalue: &Lvalue<'tcx>) -> LvalueTy<'tcx> {
+ fn sanitize_lvalue(&mut self, lvalue: &Lvalue<'tcx>, location: Location) -> LvalueTy<'tcx> {
debug!("sanitize_lvalue: {:?}", lvalue);
match *lvalue {
Lvalue::Var(index) => LvalueTy::Ty { ty: self.mir.var_decls[index].ty },
LvalueTy::Ty { ty: self.mir.return_ty }
}
Lvalue::Projection(ref proj) => {
- let base_ty = self.sanitize_lvalue(&proj.base);
+ let base_ty = self.sanitize_lvalue(&proj.base, location);
if let LvalueTy::Ty { ty } = base_ty {
if ty.references_error() {
assert!(self.errors_reported);
return LvalueTy::Ty { ty: self.tcx().types.err };
}
}
- self.sanitize_projection(base_ty, &proj.elem, lvalue)
+ self.sanitize_projection(base_ty, &proj.elem, lvalue, location)
}
}
}
fn sanitize_projection(&mut self,
base: LvalueTy<'tcx>,
pi: &LvalueElem<'tcx>,
- lvalue: &Lvalue<'tcx>)
+ lvalue: &Lvalue<'tcx>,
+ location: Location)
-> LvalueTy<'tcx> {
debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, lvalue);
let tcx = self.tcx();
}
}
ProjectionElem::Index(ref i) => {
- self.visit_operand(i);
+ self.visit_operand(i, location);
let index_ty = i.ty(self.mir, tcx);
if index_ty != tcx.types.usize {
LvalueTy::Ty {
use rustc::mir::repr as mir;
use rustc::mir::visit as mir_visit;
use rustc::mir::visit::Visitor as MirVisitor;
+use rustc::mir::repr::Location;
use rustc_const_eval as const_eval;
impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
- fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>) {
+ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
debug!("visiting rvalue {:?}", *rvalue);
match *rvalue {
_ => { /* not interesting */ }
}
- self.super_rvalue(rvalue);
+ self.super_rvalue(rvalue, location);
}
fn visit_lvalue(&mut self,
lvalue: &mir::Lvalue<'tcx>,
- context: mir_visit::LvalueContext) {
+ context: mir_visit::LvalueContext,
+ location: Location) {
debug!("visiting lvalue {:?}", *lvalue);
if let mir_visit::LvalueContext::Drop = context {
self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
}
- self.super_lvalue(lvalue, context);
+ self.super_lvalue(lvalue, context, location);
}
- fn visit_operand(&mut self, operand: &mir::Operand<'tcx>) {
+ fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
debug!("visiting operand {:?}", *operand);
let callee = match *operand {
}
}
- self.super_operand(operand);
+ self.super_operand(operand, location);
fn can_result_in_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
// we would not register drop-glues.
fn visit_terminator_kind(&mut self,
block: mir::BasicBlock,
- kind: &mir::TerminatorKind<'tcx>) {
+ kind: &mir::TerminatorKind<'tcx>,
+ location: Location) {
let tcx = self.scx.tcx();
match *kind {
mir::TerminatorKind::Call {
_ => { /* Nothing to do. */ }
}
- self.super_terminator_kind(block, kind);
+ self.super_terminator_kind(block, kind, location);
fn is_drop_in_place_intrinsic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc::mir::repr as mir;
use rustc::mir::repr::TerminatorKind;
+use rustc::mir::repr::Location;
use rustc::mir::visit::{Visitor, LvalueContext};
use rustc::mir::traversal;
use common::{self, Block, BlockAndBuilder};
fn visit_assign(&mut self,
block: mir::BasicBlock,
lvalue: &mir::Lvalue<'tcx>,
- rvalue: &mir::Rvalue<'tcx>) {
+ rvalue: &mir::Rvalue<'tcx>,
+ location: Location) {
debug!("visit_assign(block={:?}, lvalue={:?}, rvalue={:?})", block, lvalue, rvalue);
if let Some(index) = self.mir.local_index(lvalue) {
self.mark_as_lvalue(index);
}
} else {
- self.visit_lvalue(lvalue, LvalueContext::Store);
+ self.visit_lvalue(lvalue, LvalueContext::Store, location);
}
- self.visit_rvalue(rvalue);
+ self.visit_rvalue(rvalue, location);
}
fn visit_terminator_kind(&mut self,
block: mir::BasicBlock,
- kind: &mir::TerminatorKind<'tcx>) {
+ kind: &mir::TerminatorKind<'tcx>,
+ location: Location) {
match *kind {
mir::TerminatorKind::Call {
func: mir::Operand::Constant(mir::Constant {
// is not guaranteed to be statically dominated by the
// definition of x, so x must always be in an alloca.
if let mir::Operand::Consume(ref lvalue) = args[0] {
- self.visit_lvalue(lvalue, LvalueContext::Drop);
+ self.visit_lvalue(lvalue, LvalueContext::Drop, location);
}
}
_ => {}
}
- self.super_terminator_kind(block, kind);
+ self.super_terminator_kind(block, kind, location);
}
fn visit_lvalue(&mut self,
lvalue: &mir::Lvalue<'tcx>,
- context: LvalueContext) {
+ context: LvalueContext,
+ location: Location) {
debug!("visit_lvalue(lvalue={:?}, context={:?})", lvalue, context);
// Allow uses of projections of immediate pair fields.
// A deref projection only reads the pointer, never needs the lvalue.
if let mir::Lvalue::Projection(ref proj) = *lvalue {
if let mir::ProjectionElem::Deref = proj.elem {
- return self.visit_lvalue(&proj.base, LvalueContext::Consume);
+ return self.visit_lvalue(&proj.base, LvalueContext::Consume, location);
}
}
- self.super_lvalue(lvalue, context);
+ self.super_lvalue(lvalue, context, location);
}
}
extern crate syntax;
use rustc::mir::transform::{self, MirPass, MirSource};
-use rustc::mir::repr::{Mir, Literal};
+use rustc::mir::repr::{Mir, Literal, Location};
use rustc::mir::visit::MutVisitor;
use rustc::ty::TyCtxt;
use rustc::middle::const_val::ConstVal;
struct Visitor;
impl<'tcx> MutVisitor<'tcx> for Visitor {
- fn visit_literal(&mut self, literal: &mut Literal<'tcx>) {
+ fn visit_literal(&mut self, literal: &mut Literal<'tcx>, _: Location) {
if let Literal::Value { ref mut value } = *literal {
if let ConstVal::Integral(ConstInt::I32(ref mut i @ 11)) = *value {
*i = 42;