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};
common::type_is_fat_ptr(bcx.tcx(), ty));
} else if common::type_is_imm_pair(bcx.ccx(), ty) {
// We allow pairs and uses of any of their 2 fields.
+ } else if !analyzer.seen_assigned.contains(index) {
+ // No assignment has been seen, which means that
+ // either the local has been marked as lvalue
+ // already, or there is no possible initialization
+ // for the local, making any reads invalid.
+ // This is useful in weeding out dead temps.
} else {
// These sorts of types require an alloca. Note that
// type_is_immediate() may *still* be true, particularly
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);
}
}