提交 3a16f57f 编写于 作者: N Niko Matsakis

extend Terminator into a struct so it can have additional fields

上级 e752d4cd
......@@ -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 @@ pub fn successors(&self) -> Cow<[BasicBlock]> {
// 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 @@ pub fn terminator_mut(&mut self) -> &mut Terminator<'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 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
}
}
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 @@ pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
/// 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 @@ fn super_assign(&mut self,
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 @@ fn propagate_bits_into_graph_successors_of<OnReturn>(
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);
}
Terminator::If { ref cond, targets: _ } => {
// The `cond` is always of (copyable) type `bool`,
// so there will never be anything to move.
let _ = cond;
}
TerminatorKind::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;
}
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;
}
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);
}
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);
}
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);
}
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);
}
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 @@ pub fn push_assign_unit(&mut self,
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 @@ fn expr_as_lvalue(&mut self,
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 @@ pub fn into_expr(&mut self,
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 @@ pub fn into_expr(&mut self,
};
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 @@ pub fn into_expr(&mut self,
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 @@ pub fn into_expr(&mut self,
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 @@ pub fn into_expr(&mut self,
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 @@ pub fn into_expr(&mut self,
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 @@ pub fn into_expr(&mut self,
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 @@ pub fn into_expr(&mut self,
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 @@ pub fn match_expr(&mut self,
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 @@ fn join_otherwise_blocks(&mut self,
} 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 @@ fn bind_and_guard_matched_candidate<'pat>(&mut self,
// 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 @@ pub fn perform_test(&mut self,
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 @@ pub fn perform_test(&mut self,
.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 @@ pub fn perform_test(&mut self,
// 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 @@ fn compare(&mut self,
// 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 @@ pub fn exit_scope(&mut self,
.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 @@ pub fn diverge_cleanup(&mut self) -> Option<BasicBlock> {
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 @@ pub fn panic_bounds_check(&mut self,
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 @@ pub fn panic(&mut self, block: BasicBlock, msg: &'static str, span: Span) {
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 @@ fn visit_mir(&mut self, mir: &mut Mir<'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 @@
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 @@ fn final_target(mir: &Mir, mut target: BasicBlock) -> Option<BasicBlock> {
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 @@ fn simplify_branches(&self, mir: &mut Mir) -> bool {
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 @@ fn check_terminator(&self,
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 @@ fn check_terminator(&self,
}
}
}
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 @@ fn check_terminator(&self,
}
// 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 @@ fn check_terminator(&self,
}
}
}
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 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
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 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
}
}
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 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
}
}
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 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
}
}
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 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
}
}
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 @@ pub fn llblock(&self, bb: mir::BasicBlock) -> BasicBlockRef {
self.blocks[bb.index()].llbb
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册