librustc: Add a new nop statement to the MIR.

This is useful when passes want to remove statements without affecting
`Location`s.
This commit is contained in:
Patrick Walton 2016-09-15 18:17:58 -07:00
parent 5f6f838448
commit 2e6a91812c
9 changed files with 33 additions and 5 deletions

View File

@ -187,6 +187,14 @@ impl<'tcx> Mir<'tcx> {
self.var_decls.len() +
self.temp_decls.len() + 1
}
/// Changes a statement to a nop. This is both faster than deleting instructions and avoids
/// invalidating statement indices in `Location`s.
pub fn make_statement_nop(&mut self, location: Location) {
let block = &mut self[location.block];
debug_assert!(location.statement_index < block.statements.len());
block.statements[location.statement_index].make_nop()
}
}
impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
@ -686,6 +694,14 @@ pub struct Statement<'tcx> {
pub kind: StatementKind<'tcx>,
}
impl<'tcx> Statement<'tcx> {
/// Changes a statement to a nop. This is both faster than deleting instructions and avoids
/// invalidating statement indices in `Location`s.
pub fn make_nop(&mut self) {
self.kind = StatementKind::Nop
}
}
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum StatementKind<'tcx> {
/// Write the RHS Rvalue to the LHS Lvalue.
@ -699,6 +715,9 @@ pub enum StatementKind<'tcx> {
/// End the current live range for the storage of the local.
StorageDead(Lvalue<'tcx>),
/// No-op. Useful for deleting instructions without affecting statement indices.
Nop,
}
impl<'tcx> Debug for Statement<'tcx> {
@ -711,6 +730,7 @@ impl<'tcx> Debug for Statement<'tcx> {
SetDiscriminant{lvalue: ref lv, variant_index: index} => {
write!(fmt, "discriminant({:?}) = {:?}", lv, index)
}
Nop => write!(fmt, "nop"),
}
}
}

View File

@ -346,6 +346,7 @@ macro_rules! make_mir_visitor {
StatementKind::StorageDead(ref $($mutability)* lvalue) => {
self.visit_lvalue(lvalue, LvalueContext::StorageDead, location);
}
StatementKind::Nop => {}
}
}

View File

@ -455,7 +455,8 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
});
}
repr::StatementKind::StorageLive(_) |
repr::StatementKind::StorageDead(_) => {}
repr::StatementKind::StorageDead(_) |
repr::StatementKind::Nop => {}
}
}

View File

@ -105,7 +105,8 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
(lvalue, rvalue)
}
repr::StatementKind::StorageLive(_) |
repr::StatementKind::StorageDead(_) => continue,
repr::StatementKind::StorageDead(_) |
repr::StatementKind::Nop => continue,
repr::StatementKind::SetDiscriminant{ .. } =>
span_bug!(stmt.source_info.span,
"sanity_check should run before Deaggregator inserts SetDiscriminant"),

View File

@ -389,7 +389,8 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
|moi| callback(moi, DropFlagState::Present))
}
repr::StatementKind::StorageLive(_) |
repr::StatementKind::StorageDead(_) => {}
repr::StatementKind::StorageDead(_) |
repr::StatementKind::Nop => {}
},
None => {
debug!("drop_flag_effects: replace {:?}", block.terminator());

View File

@ -910,7 +910,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}
StatementKind::SetDiscriminant { .. } |
StatementKind::StorageLive(_) |
StatementKind::StorageDead(_) => {}
StatementKind::StorageDead(_) |
StatementKind::Nop => {}
}
});
}

View File

@ -385,6 +385,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
}
}
}
StatementKind::Nop => {}
}
}

View File

@ -292,7 +292,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
}
}
mir::StatementKind::StorageLive(_) |
mir::StatementKind::StorageDead(_) => {}
mir::StatementKind::StorageDead(_) |
mir::StatementKind::Nop => {}
mir::StatementKind::SetDiscriminant{ .. } => {
span_bug!(span, "SetDiscriminant should not appear in constants?");
}

View File

@ -78,6 +78,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
mir::StatementKind::StorageDead(ref lvalue) => {
self.trans_storage_liveness(bcx, lvalue, base::Lifetime::End)
}
mir::StatementKind::Nop => bcx,
}
}