extend Terminator into a struct so it can have additional fields
This commit is contained in:
parent
e752d4cde3
commit
3a16f57fbb
@ -228,8 +228,13 @@ pub struct BasicBlockData<'tcx> {
|
||||
pub is_cleanup: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct Terminator<'tcx> {
|
||||
pub kind: TerminatorKind<'tcx>
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
pub enum Terminator<'tcx> {
|
||||
pub enum TerminatorKind<'tcx> {
|
||||
/// block should have one successor in the graph; we jump there
|
||||
Goto {
|
||||
target: BasicBlock,
|
||||
@ -299,7 +304,17 @@ pub enum Terminator<'tcx> {
|
||||
|
||||
impl<'tcx> Terminator<'tcx> {
|
||||
pub fn successors(&self) -> Cow<[BasicBlock]> {
|
||||
use self::Terminator::*;
|
||||
self.kind.successors()
|
||||
}
|
||||
|
||||
pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
|
||||
self.kind.successors_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TerminatorKind<'tcx> {
|
||||
pub fn successors(&self) -> Cow<[BasicBlock]> {
|
||||
use self::TerminatorKind::*;
|
||||
match *self {
|
||||
Goto { target: ref b } => slice::ref_slice(b).into_cow(),
|
||||
If { targets: (b1, b2), .. } => vec![b1, b2].into_cow(),
|
||||
@ -320,7 +335,7 @@ impl<'tcx> Terminator<'tcx> {
|
||||
// FIXME: no mootable cow. I’m honestly not sure what a “cow” between `&mut [BasicBlock]` and
|
||||
// `Vec<&mut BasicBlock>` would look like in the first place.
|
||||
pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
|
||||
use self::Terminator::*;
|
||||
use self::TerminatorKind::*;
|
||||
match *self {
|
||||
Goto { target: ref mut b } => vec![b],
|
||||
If { targets: (ref mut b1, ref mut b2), .. } => vec![b1, b2],
|
||||
@ -360,7 +375,7 @@ impl<'tcx> BasicBlockData<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Debug for Terminator<'tcx> {
|
||||
impl<'tcx> Debug for TerminatorKind<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||
self.fmt_head(fmt)?;
|
||||
let successors = self.successors();
|
||||
@ -387,12 +402,12 @@ impl<'tcx> Debug for Terminator<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Terminator<'tcx> {
|
||||
impl<'tcx> TerminatorKind<'tcx> {
|
||||
/// Write the "head" part of the terminator; that is, its name and the data it uses to pick the
|
||||
/// successor basic block, if any. The only information not inlcuded is the list of possible
|
||||
/// successors, which may be rendered differently between the text and the graphviz format.
|
||||
pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
|
||||
use self::Terminator::*;
|
||||
use self::TerminatorKind::*;
|
||||
match *self {
|
||||
Goto { .. } => write!(fmt, "goto"),
|
||||
If { cond: ref lv, .. } => write!(fmt, "if({:?})", lv),
|
||||
@ -419,7 +434,7 @@ impl<'tcx> Terminator<'tcx> {
|
||||
|
||||
/// Return the list of labels for the edges to the successor basic blocks.
|
||||
pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
|
||||
use self::Terminator::*;
|
||||
use self::TerminatorKind::*;
|
||||
match *self {
|
||||
Return | Resume => vec![],
|
||||
Goto { .. } => vec!["".into()],
|
||||
|
@ -138,52 +138,54 @@ macro_rules! make_mir_visitor {
|
||||
fn super_terminator(&mut self,
|
||||
block: BasicBlock,
|
||||
terminator: &$($mutability)* Terminator<'tcx>) {
|
||||
match *terminator {
|
||||
Terminator::Goto { target } => {
|
||||
match terminator.kind {
|
||||
TerminatorKind::Goto { target } => {
|
||||
self.visit_branch(block, target);
|
||||
}
|
||||
|
||||
Terminator::If { ref $($mutability)* cond,
|
||||
ref $($mutability)* targets } => {
|
||||
TerminatorKind::If { ref $($mutability)* cond,
|
||||
ref $($mutability)* targets } => {
|
||||
self.visit_operand(cond);
|
||||
for &target in targets.as_slice() {
|
||||
self.visit_branch(block, target);
|
||||
}
|
||||
}
|
||||
|
||||
Terminator::Switch { ref $($mutability)* discr,
|
||||
adt_def: _,
|
||||
ref targets } => {
|
||||
TerminatorKind::Switch { ref $($mutability)* discr,
|
||||
adt_def: _,
|
||||
ref targets } => {
|
||||
self.visit_lvalue(discr, LvalueContext::Inspect);
|
||||
for &target in targets {
|
||||
self.visit_branch(block, target);
|
||||
}
|
||||
}
|
||||
|
||||
Terminator::SwitchInt { ref $($mutability)* discr,
|
||||
switch_ty: _,
|
||||
values: _,
|
||||
ref targets } => {
|
||||
TerminatorKind::SwitchInt { ref $($mutability)* discr,
|
||||
switch_ty: _,
|
||||
values: _,
|
||||
ref targets } => {
|
||||
self.visit_lvalue(discr, LvalueContext::Inspect);
|
||||
for &target in targets {
|
||||
self.visit_branch(block, target);
|
||||
}
|
||||
}
|
||||
|
||||
Terminator::Resume |
|
||||
Terminator::Return => {
|
||||
TerminatorKind::Resume |
|
||||
TerminatorKind::Return => {
|
||||
}
|
||||
|
||||
Terminator::Drop { ref $($mutability)* value, target, unwind } => {
|
||||
TerminatorKind::Drop { ref $($mutability)* value,
|
||||
target,
|
||||
unwind } => {
|
||||
self.visit_lvalue(value, LvalueContext::Drop);
|
||||
self.visit_branch(block, target);
|
||||
unwind.map(|t| self.visit_branch(block, t));
|
||||
}
|
||||
|
||||
Terminator::Call { ref $($mutability)* func,
|
||||
ref $($mutability)* args,
|
||||
ref $($mutability)* destination,
|
||||
cleanup } => {
|
||||
TerminatorKind::Call { ref $($mutability)* func,
|
||||
ref $($mutability)* args,
|
||||
ref $($mutability)* destination,
|
||||
cleanup } => {
|
||||
self.visit_operand(func);
|
||||
for arg in args {
|
||||
self.visit_operand(arg);
|
||||
|
@ -410,29 +410,28 @@ impl<D: BitDenotation> DataflowState<D> {
|
||||
bb: &repr::BasicBlockData,
|
||||
on_return: OnReturn) where OnReturn: Fn(&D, &mut [usize], &repr::Lvalue)
|
||||
{
|
||||
let term = if let Some(ref term) = bb.terminator { term } else { return };
|
||||
match *term {
|
||||
repr::Terminator::Return |
|
||||
repr::Terminator::Resume => {}
|
||||
repr::Terminator::Goto { ref target } |
|
||||
repr::Terminator::Drop { ref target, value: _, unwind: None } => {
|
||||
match bb.terminator().kind {
|
||||
repr::TerminatorKind::Return |
|
||||
repr::TerminatorKind::Resume => {}
|
||||
repr::TerminatorKind::Goto { ref target } |
|
||||
repr::TerminatorKind::Drop { ref target, value: _, unwind: None } => {
|
||||
self.propagate_bits_into_entry_set_for(in_out, changed, target);
|
||||
}
|
||||
repr::Terminator::Drop { ref target, value: _, unwind: Some(ref unwind) } => {
|
||||
repr::TerminatorKind::Drop { ref target, value: _, unwind: Some(ref unwind) } => {
|
||||
self.propagate_bits_into_entry_set_for(in_out, changed, target);
|
||||
self.propagate_bits_into_entry_set_for(in_out, changed, unwind);
|
||||
}
|
||||
repr::Terminator::If { ref targets, .. } => {
|
||||
repr::TerminatorKind::If { ref targets, .. } => {
|
||||
self.propagate_bits_into_entry_set_for(in_out, changed, &targets.0);
|
||||
self.propagate_bits_into_entry_set_for(in_out, changed, &targets.1);
|
||||
}
|
||||
repr::Terminator::Switch { ref targets, .. } |
|
||||
repr::Terminator::SwitchInt { ref targets, .. } => {
|
||||
repr::TerminatorKind::Switch { ref targets, .. } |
|
||||
repr::TerminatorKind::SwitchInt { ref targets, .. } => {
|
||||
for target in targets {
|
||||
self.propagate_bits_into_entry_set_for(in_out, changed, target);
|
||||
}
|
||||
}
|
||||
repr::Terminator::Call { ref cleanup, ref destination, func: _, args: _ } => {
|
||||
repr::TerminatorKind::Call { ref cleanup, ref destination, func: _, args: _ } => {
|
||||
if let Some(ref unwind) = *cleanup {
|
||||
self.propagate_bits_into_entry_set_for(in_out, changed, unwind);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
use rustc::middle::ty;
|
||||
use rustc::mir::repr::{self, Mir, BasicBlock, Lvalue, Rvalue};
|
||||
use rustc::mir::repr::{StatementKind, Terminator};
|
||||
use rustc::mir::repr::{StatementKind, TerminatorKind};
|
||||
use rustc::util::nodemap::FnvHashMap;
|
||||
|
||||
use std::cell::{Cell};
|
||||
@ -577,50 +577,48 @@ fn gather_moves<'tcx>(mir: &Mir<'tcx>, tcx: &ty::TyCtxt<'tcx>) -> MoveData<'tcx>
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref term) = bb_data.terminator {
|
||||
match *term {
|
||||
Terminator::Goto { target: _ } | Terminator::Resume => { }
|
||||
match bb_data.terminator().kind {
|
||||
TerminatorKind::Goto { target: _ } | TerminatorKind::Resume => { }
|
||||
|
||||
Terminator::Return => {
|
||||
let source = Location { block: bb,
|
||||
index: bb_data.statements.len() };
|
||||
let lval = &Lvalue::ReturnPointer.deref();
|
||||
bb_ctxt.on_move_out_lval(SK::Return, lval, source);
|
||||
TerminatorKind::Return => {
|
||||
let source = Location { block: bb,
|
||||
index: bb_data.statements.len() };
|
||||
let lval = &Lvalue::ReturnPointer.deref();
|
||||
bb_ctxt.on_move_out_lval(SK::Return, lval, source);
|
||||
}
|
||||
|
||||
TerminatorKind::If { ref cond, targets: _ } => {
|
||||
// The `cond` is always of (copyable) type `bool`,
|
||||
// so there will never be anything to move.
|
||||
let _ = cond;
|
||||
}
|
||||
|
||||
TerminatorKind::SwitchInt { switch_ty: _, values: _, targets: _, ref discr } |
|
||||
TerminatorKind::Switch { adt_def: _, targets: _, ref discr } => {
|
||||
// The `discr` is not consumed; that is instead
|
||||
// encoded on specific match arms (and for
|
||||
// SwitchInt`, it is always a copyable integer
|
||||
// type anyway).
|
||||
let _ = discr;
|
||||
}
|
||||
|
||||
TerminatorKind::Drop { value: ref lval, target: _, unwind: _ } => {
|
||||
let source = Location { block: bb,
|
||||
index: bb_data.statements.len() };
|
||||
bb_ctxt.on_move_out_lval(SK::Drop, lval, source);
|
||||
}
|
||||
|
||||
TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => {
|
||||
let source = Location { block: bb,
|
||||
index: bb_data.statements.len() };
|
||||
bb_ctxt.on_operand(SK::CallFn, func, source);
|
||||
for arg in args {
|
||||
bb_ctxt.on_operand(SK::CallArg, arg, source);
|
||||
}
|
||||
|
||||
Terminator::If { ref cond, targets: _ } => {
|
||||
// The `cond` is always of (copyable) type `bool`,
|
||||
// so there will never be anything to move.
|
||||
let _ = cond;
|
||||
}
|
||||
|
||||
Terminator::SwitchInt { switch_ty: _, values: _, targets: _, ref discr } |
|
||||
Terminator::Switch { adt_def: _, targets: _, ref discr } => {
|
||||
// The `discr` is not consumed; that is instead
|
||||
// encoded on specific match arms (and for
|
||||
// SwitchInt`, it is always a copyable integer
|
||||
// type anyway).
|
||||
let _ = discr;
|
||||
}
|
||||
|
||||
Terminator::Drop { value: ref lval, target: _, unwind: _ } => {
|
||||
let source = Location { block: bb,
|
||||
index: bb_data.statements.len() };
|
||||
bb_ctxt.on_move_out_lval(SK::Drop, lval, source);
|
||||
}
|
||||
|
||||
Terminator::Call { ref func, ref args, ref destination, cleanup: _ } => {
|
||||
let source = Location { block: bb,
|
||||
index: bb_data.statements.len() };
|
||||
bb_ctxt.on_operand(SK::CallFn, func, source);
|
||||
for arg in args {
|
||||
bb_ctxt.on_operand(SK::CallArg, arg, source);
|
||||
}
|
||||
if let Some((ref destination, _bb)) = *destination {
|
||||
// Create MovePath for `destination`, then
|
||||
// discard returned index.
|
||||
bb_ctxt.builder.move_path_for(destination);
|
||||
}
|
||||
if let Some((ref destination, _bb)) = *destination {
|
||||
// Create MovePath for `destination`, then
|
||||
// discard returned index.
|
||||
bb_ctxt.builder.move_path_for(destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,9 +83,11 @@ impl<'tcx> CFG<'tcx> {
|
||||
|
||||
pub fn terminate(&mut self,
|
||||
block: BasicBlock,
|
||||
terminator: Terminator<'tcx>) {
|
||||
kind: TerminatorKind<'tcx>) {
|
||||
debug_assert!(self.block_data(block).terminator.is_none(),
|
||||
"terminate: block {:?} already has a terminator set", block);
|
||||
self.block_data_mut(block).terminator = Some(terminator);
|
||||
self.block_data_mut(block).terminator = Some(Terminator {
|
||||
kind: kind
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
let (success, failure) = (this.cfg.start_new_block(), this.cfg.start_new_block());
|
||||
this.cfg.terminate(block,
|
||||
Terminator::If {
|
||||
TerminatorKind::If {
|
||||
cond: Operand::Consume(lt),
|
||||
targets: (success, failure),
|
||||
});
|
||||
|
@ -53,7 +53,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
let mut then_block = this.cfg.start_new_block();
|
||||
let mut else_block = this.cfg.start_new_block();
|
||||
this.cfg.terminate(block, Terminator::If {
|
||||
this.cfg.terminate(block, TerminatorKind::If {
|
||||
cond: operand,
|
||||
targets: (then_block, else_block)
|
||||
});
|
||||
@ -70,8 +70,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
};
|
||||
|
||||
let join_block = this.cfg.start_new_block();
|
||||
this.cfg.terminate(then_block, Terminator::Goto { target: join_block });
|
||||
this.cfg.terminate(else_block, Terminator::Goto { target: join_block });
|
||||
this.cfg.terminate(then_block, TerminatorKind::Goto { target: join_block });
|
||||
this.cfg.terminate(else_block, TerminatorKind::Goto { target: join_block });
|
||||
|
||||
join_block.unit()
|
||||
}
|
||||
@ -97,10 +97,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
LogicalOp::And => (else_block, false_block),
|
||||
LogicalOp::Or => (true_block, else_block),
|
||||
};
|
||||
this.cfg.terminate(block, Terminator::If { cond: lhs, targets: blocks });
|
||||
this.cfg.terminate(block, TerminatorKind::If { cond: lhs, targets: blocks });
|
||||
|
||||
let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
|
||||
this.cfg.terminate(else_block, Terminator::If {
|
||||
this.cfg.terminate(else_block, TerminatorKind::If {
|
||||
cond: rhs,
|
||||
targets: (true_block, false_block)
|
||||
});
|
||||
@ -121,8 +121,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
literal: this.hir.false_literal(),
|
||||
});
|
||||
|
||||
this.cfg.terminate(true_block, Terminator::Goto { target: join_block });
|
||||
this.cfg.terminate(false_block, Terminator::Goto { target: join_block });
|
||||
this.cfg.terminate(true_block, TerminatorKind::Goto { target: join_block });
|
||||
this.cfg.terminate(false_block, TerminatorKind::Goto { target: join_block });
|
||||
|
||||
join_block.unit()
|
||||
}
|
||||
@ -146,7 +146,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let exit_block = this.cfg.start_new_block();
|
||||
|
||||
// start the loop
|
||||
this.cfg.terminate(block, Terminator::Goto { target: loop_block });
|
||||
this.cfg.terminate(block, TerminatorKind::Goto { target: loop_block });
|
||||
|
||||
let might_break = this.in_loop_scope(loop_block, exit_block, move |this| {
|
||||
// conduct the test, if necessary
|
||||
@ -159,7 +159,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let cond = unpack!(loop_block_end = this.as_operand(loop_block, cond_expr));
|
||||
body_block = this.cfg.start_new_block();
|
||||
this.cfg.terminate(loop_block_end,
|
||||
Terminator::If {
|
||||
TerminatorKind::If {
|
||||
cond: cond,
|
||||
targets: (body_block, exit_block)
|
||||
});
|
||||
@ -175,7 +175,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let tmp = this.get_unit_temp();
|
||||
// Execute the body, branching back to the test.
|
||||
let body_block_end = unpack!(this.into(&tmp, body_block, body));
|
||||
this.cfg.terminate(body_block_end, Terminator::Goto { target: loop_block });
|
||||
this.cfg.terminate(body_block_end, TerminatorKind::Goto { target: loop_block });
|
||||
});
|
||||
// If the loop may reach its exit_block, we assign an empty tuple to the
|
||||
// destination to keep the MIR well-formed.
|
||||
@ -254,7 +254,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
let success = this.cfg.start_new_block();
|
||||
let cleanup = this.diverge_cleanup();
|
||||
this.cfg.terminate(block, Terminator::Call {
|
||||
this.cfg.terminate(block, TerminatorKind::Call {
|
||||
func: fun,
|
||||
args: args,
|
||||
cleanup: cleanup,
|
||||
|
@ -97,7 +97,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
for (arm_index, arm_body) in arm_bodies.into_iter().enumerate() {
|
||||
let mut arm_block = arm_blocks.blocks[arm_index];
|
||||
unpack!(arm_block = self.into(destination, arm_block, arm_body));
|
||||
self.cfg.terminate(arm_block, Terminator::Goto { target: end_block });
|
||||
self.cfg.terminate(arm_block, TerminatorKind::Goto { target: end_block });
|
||||
}
|
||||
|
||||
end_block.unit()
|
||||
@ -383,7 +383,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
} else {
|
||||
let join_block = self.cfg.start_new_block();
|
||||
for block in otherwise {
|
||||
self.cfg.terminate(block, Terminator::Goto { target: join_block });
|
||||
self.cfg.terminate(block, TerminatorKind::Goto { target: join_block });
|
||||
}
|
||||
join_block
|
||||
}
|
||||
@ -555,11 +555,11 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
// guard, this block is simply unreachable
|
||||
let cond = unpack!(block = self.as_operand(block, guard));
|
||||
let otherwise = self.cfg.start_new_block();
|
||||
self.cfg.terminate(block, Terminator::If { cond: cond,
|
||||
self.cfg.terminate(block, TerminatorKind::If { cond: cond,
|
||||
targets: (arm_block, otherwise)});
|
||||
Some(otherwise)
|
||||
} else {
|
||||
self.cfg.terminate(block, Terminator::Goto { target: arm_block });
|
||||
self.cfg.terminate(block, TerminatorKind::Goto { target: arm_block });
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let target_blocks: Vec<_> =
|
||||
(0..num_enum_variants).map(|_| self.cfg.start_new_block())
|
||||
.collect();
|
||||
self.cfg.terminate(block, Terminator::Switch {
|
||||
self.cfg.terminate(block, TerminatorKind::Switch {
|
||||
discr: lvalue.clone(),
|
||||
adt_def: adt_def,
|
||||
targets: target_blocks.clone()
|
||||
@ -168,7 +168,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
.map(|_| self.cfg.start_new_block())
|
||||
.chain(Some(otherwise))
|
||||
.collect();
|
||||
self.cfg.terminate(block, Terminator::SwitchInt {
|
||||
self.cfg.terminate(block, TerminatorKind::SwitchInt {
|
||||
discr: lvalue.clone(),
|
||||
switch_ty: switch_ty,
|
||||
values: options.clone(),
|
||||
@ -286,7 +286,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
// branch based on result
|
||||
let target_blocks: Vec<_> = vec![self.cfg.start_new_block(),
|
||||
self.cfg.start_new_block()];
|
||||
self.cfg.terminate(block, Terminator::If {
|
||||
self.cfg.terminate(block, TerminatorKind::If {
|
||||
cond: Operand::Consume(result),
|
||||
targets: (target_blocks[0], target_blocks[1])
|
||||
});
|
||||
@ -313,7 +313,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
// branch based on result
|
||||
let target_block = self.cfg.start_new_block();
|
||||
self.cfg.terminate(block, Terminator::If {
|
||||
self.cfg.terminate(block, TerminatorKind::If {
|
||||
cond: Operand::Consume(result),
|
||||
targets: (target_block, fail_block)
|
||||
});
|
||||
|
@ -166,8 +166,8 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
|
||||
argument_extent,
|
||||
ast_block));
|
||||
|
||||
builder.cfg.terminate(block, Terminator::Goto { target: END_BLOCK });
|
||||
builder.cfg.terminate(END_BLOCK, Terminator::Return);
|
||||
builder.cfg.terminate(block, TerminatorKind::Goto { target: END_BLOCK });
|
||||
builder.cfg.terminate(END_BLOCK, TerminatorKind::Return);
|
||||
|
||||
MirPlusPlus {
|
||||
mir: Mir {
|
||||
|
@ -295,7 +295,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
.postdoms
|
||||
.push(self.cfg.current_location(block));
|
||||
}
|
||||
self.cfg.terminate(block, Terminator::Goto { target: target });
|
||||
self.cfg.terminate(block, TerminatorKind::Goto { target: target });
|
||||
}
|
||||
|
||||
// Finding scopes
|
||||
@ -432,7 +432,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
pub fn build_drop(&mut self, block: BasicBlock, value: Lvalue<'tcx>) -> BlockAnd<()> {
|
||||
let next_target = self.cfg.start_new_block();
|
||||
let diverge_target = self.diverge_cleanup();
|
||||
self.cfg.terminate(block, Terminator::Drop {
|
||||
self.cfg.terminate(block, TerminatorKind::Drop {
|
||||
value: value,
|
||||
target: next_target,
|
||||
unwind: diverge_target,
|
||||
@ -474,7 +474,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
self.cfg.push_assign(block, scope_id, span, &tuple_ref, // tuple_ref = &tuple;
|
||||
Rvalue::Ref(region, BorrowKind::Shared, tuple));
|
||||
let cleanup = self.diverge_cleanup();
|
||||
self.cfg.terminate(block, Terminator::Call {
|
||||
self.cfg.terminate(block, TerminatorKind::Call {
|
||||
func: Operand::Constant(func),
|
||||
args: vec![Operand::Consume(tuple_ref), index, len],
|
||||
destination: None,
|
||||
@ -516,7 +516,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
self.cfg.push_assign(block, scope_id, span, &tuple_ref, // tuple_ref = &tuple;
|
||||
Rvalue::Ref(region, BorrowKind::Shared, tuple));
|
||||
let cleanup = self.diverge_cleanup();
|
||||
self.cfg.terminate(block, Terminator::Call {
|
||||
self.cfg.terminate(block, TerminatorKind::Call {
|
||||
func: Operand::Constant(func),
|
||||
args: vec![Operand::Consume(tuple_ref)],
|
||||
cleanup: cleanup,
|
||||
@ -575,7 +575,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
|
||||
earlier_scopes.iter().rev().flat_map(|s| s.cached_block()).next()
|
||||
});
|
||||
let next = cfg.start_new_block();
|
||||
cfg.terminate(block, Terminator::Drop {
|
||||
cfg.terminate(block, TerminatorKind::Drop {
|
||||
value: drop_data.value.clone(),
|
||||
target: next,
|
||||
unwind: on_diverge
|
||||
@ -600,7 +600,7 @@ fn build_diverge_scope<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
for drop_data in scope.drops.iter_mut().rev() {
|
||||
if let Some(cached_block) = drop_data.cached_block {
|
||||
if let Some((previous_block, previous_value)) = previous {
|
||||
cfg.terminate(previous_block, Terminator::Drop {
|
||||
cfg.terminate(previous_block, TerminatorKind::Drop {
|
||||
value: previous_value,
|
||||
target: cached_block,
|
||||
unwind: None
|
||||
@ -613,7 +613,7 @@ fn build_diverge_scope<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
let block = cfg.start_new_cleanup_block();
|
||||
drop_data.cached_block = Some(block);
|
||||
if let Some((previous_block, previous_value)) = previous {
|
||||
cfg.terminate(previous_block, Terminator::Drop {
|
||||
cfg.terminate(previous_block, TerminatorKind::Drop {
|
||||
value: previous_value,
|
||||
target: block,
|
||||
unwind: None
|
||||
@ -628,7 +628,7 @@ fn build_diverge_scope<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
// Prepare the end target for this chain.
|
||||
let mut target = target.unwrap_or_else(||{
|
||||
let b = cfg.start_new_cleanup_block();
|
||||
cfg.terminate(b, Terminator::Resume);
|
||||
cfg.terminate(b, TerminatorKind::Resume);
|
||||
b
|
||||
});
|
||||
|
||||
@ -646,7 +646,7 @@ fn build_diverge_scope<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
|
||||
if let Some((previous_block, previous_value)) = previous {
|
||||
// Finally, branch into that just-built `target` from the `previous_block`.
|
||||
cfg.terminate(previous_block, Terminator::Drop {
|
||||
cfg.terminate(previous_block, TerminatorKind::Drop {
|
||||
value: previous_value,
|
||||
target: target,
|
||||
unwind: None
|
||||
@ -662,14 +662,15 @@ fn build_diverge_scope<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
fn build_free<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
unit_temp: Lvalue<'tcx>,
|
||||
data: &FreeData<'tcx>,
|
||||
target: BasicBlock) -> Terminator<'tcx> {
|
||||
target: BasicBlock)
|
||||
-> TerminatorKind<'tcx> {
|
||||
let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
|
||||
.unwrap_or_else(|e| tcx.sess.fatal(&e));
|
||||
let substs = tcx.mk_substs(Substs::new(
|
||||
VecPerParamSpace::new(vec![], vec![], vec![data.item_ty]),
|
||||
VecPerParamSpace::new(vec![], vec![], vec![])
|
||||
));
|
||||
Terminator::Call {
|
||||
TerminatorKind::Call {
|
||||
func: Operand::Constant(Constant {
|
||||
span: data.span,
|
||||
ty: tcx.lookup_item_type(free_func).ty.subst(tcx, substs),
|
||||
|
@ -83,7 +83,7 @@ pub fn write_node_label<W: Write, INIT, FINI>(block: BasicBlock,
|
||||
// Terminator head at the bottom, not including the list of successor blocks. Those will be
|
||||
// displayed as labels on the edges between blocks.
|
||||
let mut terminator_head = String::new();
|
||||
data.terminator().fmt_head(&mut terminator_head).unwrap();
|
||||
data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
|
||||
write!(w, r#"<tr><td align="left">{}</td></tr>"#, dot::escape_html(&terminator_head))?;
|
||||
|
||||
fini(w)?;
|
||||
@ -104,7 +104,7 @@ fn write_node<W: Write>(block: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<(
|
||||
/// Write graphviz DOT edges with labels between the given basic block and all of its successors.
|
||||
fn write_edges<W: Write>(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
|
||||
let terminator = &mir.basic_block_data(source).terminator();
|
||||
let labels = terminator.fmt_successor_labels();
|
||||
let labels = terminator.kind.fmt_successor_labels();
|
||||
|
||||
for (&target, label) in terminator.successors().iter().zip(labels) {
|
||||
writeln!(w, r#" {} -> {} [label="{}"];"#, node(source), node(target), label)?;
|
||||
|
@ -58,17 +58,17 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_terminator(&mut self, bb: BasicBlock, terminator: &mut Terminator<'tcx>) {
|
||||
match *terminator {
|
||||
Terminator::Goto { .. } |
|
||||
Terminator::Resume |
|
||||
Terminator::Return |
|
||||
Terminator::If { .. } |
|
||||
Terminator::Switch { .. } |
|
||||
Terminator::Drop { .. } |
|
||||
Terminator::Call { .. } => {
|
||||
match terminator.kind {
|
||||
TerminatorKind::Goto { .. } |
|
||||
TerminatorKind::Resume |
|
||||
TerminatorKind::Return |
|
||||
TerminatorKind::If { .. } |
|
||||
TerminatorKind::Switch { .. } |
|
||||
TerminatorKind::Drop { .. } |
|
||||
TerminatorKind::Call { .. } => {
|
||||
/* nothing to do */
|
||||
},
|
||||
Terminator::SwitchInt { ref mut switch_ty, .. } => {
|
||||
TerminatorKind::SwitchInt { ref mut switch_ty, .. } => {
|
||||
*switch_ty = self.tcx.erase_regions(switch_ty);
|
||||
},
|
||||
}
|
||||
|
@ -21,19 +21,19 @@ pub struct NoLandingPads;
|
||||
|
||||
impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
|
||||
fn visit_terminator(&mut self, bb: BasicBlock, terminator: &mut Terminator<'tcx>) {
|
||||
match *terminator {
|
||||
Terminator::Goto { .. } |
|
||||
Terminator::Resume |
|
||||
Terminator::Return |
|
||||
Terminator::If { .. } |
|
||||
Terminator::Switch { .. } |
|
||||
Terminator::SwitchInt { .. } => {
|
||||
match terminator.kind {
|
||||
TerminatorKind::Goto { .. } |
|
||||
TerminatorKind::Resume |
|
||||
TerminatorKind::Return |
|
||||
TerminatorKind::If { .. } |
|
||||
TerminatorKind::Switch { .. } |
|
||||
TerminatorKind::SwitchInt { .. } => {
|
||||
/* nothing to do */
|
||||
},
|
||||
Terminator::Drop { ref mut unwind, .. } => {
|
||||
TerminatorKind::Drop { ref mut unwind, .. } => {
|
||||
unwind.take();
|
||||
},
|
||||
Terminator::Call { ref mut cleanup, .. } => {
|
||||
TerminatorKind::Call { ref mut cleanup, .. } => {
|
||||
cleanup.take();
|
||||
},
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ impl SimplifyCfg {
|
||||
let mut seen: Vec<BasicBlock> = Vec::with_capacity(8);
|
||||
|
||||
while mir.basic_block_data(target).statements.is_empty() {
|
||||
match mir.basic_block_data(target).terminator {
|
||||
Some(Terminator::Goto { target: next }) => {
|
||||
match mir.basic_block_data(target).terminator().kind {
|
||||
TerminatorKind::Goto { target: next } => {
|
||||
if seen.contains(&next) {
|
||||
return None;
|
||||
}
|
||||
@ -71,27 +71,27 @@ impl SimplifyCfg {
|
||||
for bb in mir.all_basic_blocks() {
|
||||
let basic_block = mir.basic_block_data_mut(bb);
|
||||
let mut terminator = basic_block.terminator_mut();
|
||||
*terminator = match *terminator {
|
||||
Terminator::If { ref targets, .. } if targets.0 == targets.1 => {
|
||||
terminator.kind = match terminator.kind {
|
||||
TerminatorKind::If { ref targets, .. } if targets.0 == targets.1 => {
|
||||
changed = true;
|
||||
Terminator::Goto { target: targets.0 }
|
||||
TerminatorKind::Goto { target: targets.0 }
|
||||
}
|
||||
|
||||
Terminator::If { ref targets, cond: Operand::Constant(Constant {
|
||||
TerminatorKind::If { ref targets, cond: Operand::Constant(Constant {
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Bool(cond)
|
||||
}, ..
|
||||
}) } => {
|
||||
changed = true;
|
||||
if cond {
|
||||
Terminator::Goto { target: targets.0 }
|
||||
TerminatorKind::Goto { target: targets.0 }
|
||||
} else {
|
||||
Terminator::Goto { target: targets.1 }
|
||||
TerminatorKind::Goto { target: targets.1 }
|
||||
}
|
||||
}
|
||||
|
||||
Terminator::SwitchInt { ref targets, .. } if targets.len() == 1 => {
|
||||
Terminator::Goto { target: targets[0] }
|
||||
TerminatorKind::SwitchInt { ref targets, .. } if targets.len() == 1 => {
|
||||
TerminatorKind::Goto { target: targets[0] }
|
||||
}
|
||||
_ => continue
|
||||
}
|
||||
|
@ -376,15 +376,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
term: &Terminator<'tcx>) {
|
||||
debug!("check_terminator: {:?}", term);
|
||||
let tcx = self.tcx();
|
||||
match *term {
|
||||
Terminator::Goto { .. } |
|
||||
Terminator::Resume |
|
||||
Terminator::Return |
|
||||
Terminator::Drop { .. } => {
|
||||
match term.kind {
|
||||
TerminatorKind::Goto { .. } |
|
||||
TerminatorKind::Resume |
|
||||
TerminatorKind::Return |
|
||||
TerminatorKind::Drop { .. } => {
|
||||
// no checks needed for these
|
||||
}
|
||||
|
||||
Terminator::If { ref cond, .. } => {
|
||||
TerminatorKind::If { ref cond, .. } => {
|
||||
let cond_ty = mir.operand_ty(tcx, cond);
|
||||
match cond_ty.sty {
|
||||
ty::TyBool => {}
|
||||
@ -393,7 +393,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Terminator::SwitchInt { ref discr, switch_ty, .. } => {
|
||||
TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
|
||||
let discr_ty = mir.lvalue_ty(tcx, discr).to_ty(tcx);
|
||||
if let Err(terr) = self.mk_subty(self.last_span, discr_ty, switch_ty) {
|
||||
span_mirbug!(self, term, "bad SwitchInt ({:?} on {:?}): {:?}",
|
||||
@ -406,7 +406,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
// FIXME: check the values
|
||||
}
|
||||
Terminator::Switch { ref discr, adt_def, ref targets } => {
|
||||
TerminatorKind::Switch { ref discr, adt_def, ref targets } => {
|
||||
let discr_ty = mir.lvalue_ty(tcx, discr).to_ty(tcx);
|
||||
match discr_ty.sty {
|
||||
ty::TyEnum(def, _)
|
||||
@ -418,7 +418,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Terminator::Call { ref func, ref args, ref destination, .. } => {
|
||||
TerminatorKind::Call { ref func, ref args, ref destination, .. } => {
|
||||
let func_ty = mir.operand_ty(tcx, func);
|
||||
debug!("check_terminator: call, func_ty={:?}", func_ty);
|
||||
let func_ty = match func_ty.sty {
|
||||
|
@ -56,8 +56,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
|
||||
debug!("trans_block: terminator: {:?}", data.terminator());
|
||||
|
||||
match *data.terminator() {
|
||||
mir::Terminator::Resume => {
|
||||
match data.terminator().kind {
|
||||
mir::TerminatorKind::Resume => {
|
||||
if let Some(cleanup_pad) = cleanup_pad {
|
||||
bcx.cleanup_ret(cleanup_pad, None);
|
||||
} else {
|
||||
@ -70,18 +70,18 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
mir::Terminator::Goto { target } => {
|
||||
mir::TerminatorKind::Goto { target } => {
|
||||
funclet_br(bcx, self.llblock(target));
|
||||
}
|
||||
|
||||
mir::Terminator::If { ref cond, targets: (true_bb, false_bb) } => {
|
||||
mir::TerminatorKind::If { ref cond, targets: (true_bb, false_bb) } => {
|
||||
let cond = self.trans_operand(&bcx, cond);
|
||||
let lltrue = self.llblock(true_bb);
|
||||
let llfalse = self.llblock(false_bb);
|
||||
bcx.cond_br(cond.immediate(), lltrue, llfalse);
|
||||
}
|
||||
|
||||
mir::Terminator::Switch { ref discr, ref adt_def, ref targets } => {
|
||||
mir::TerminatorKind::Switch { ref discr, ref adt_def, ref targets } => {
|
||||
let discr_lvalue = self.trans_lvalue(&bcx, discr);
|
||||
let ty = discr_lvalue.ty.to_ty(bcx.tcx());
|
||||
let repr = adt::represent_type(bcx.ccx(), ty);
|
||||
@ -103,7 +103,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
mir::Terminator::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
|
||||
mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
|
||||
let (otherwise, targets) = targets.split_last().unwrap();
|
||||
let discr = bcx.load(self.trans_lvalue(&bcx, discr).llval);
|
||||
let discr = bcx.with_block(|bcx| base::to_immediate(bcx, discr, switch_ty));
|
||||
@ -115,13 +115,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
mir::Terminator::Return => {
|
||||
mir::TerminatorKind::Return => {
|
||||
bcx.with_block(|bcx| {
|
||||
self.fcx.build_return_block(bcx, DebugLoc::None);
|
||||
})
|
||||
}
|
||||
|
||||
mir::Terminator::Drop { ref value, target, unwind } => {
|
||||
mir::TerminatorKind::Drop { ref value, target, unwind } => {
|
||||
let lvalue = self.trans_lvalue(&bcx, value);
|
||||
let ty = lvalue.ty.to_ty(bcx.tcx());
|
||||
// Double check for necessity to drop
|
||||
@ -152,7 +152,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
mir::Terminator::Call { ref func, ref args, ref destination, ref cleanup } => {
|
||||
mir::TerminatorKind::Call { ref func, ref args, ref destination, ref cleanup } => {
|
||||
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
|
||||
let callee = self.trans_operand(&bcx, func);
|
||||
|
||||
@ -569,3 +569,4 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
self.blocks[bb.index()].llbb
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user