diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 03f6ce355b85a..fbb185303e06d 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -876,10 +876,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks); passes.push_pass(box mir::transform::type_check::TypeckMir); passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg); - // Late passes - passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads); passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks); - passes.push_pass(box mir::transform::erase_regions::EraseRegions); // And run everything. passes.run_passes(tcx, &mut mir_map); }); @@ -933,22 +930,24 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, /// Run the translation phase to LLVM, after which the AST and analysis can pub fn phase_4_translate_to_llvm<'tcx>(tcx: &TyCtxt<'tcx>, mut mir_map: MirMap<'tcx>, - analysis: ty::CrateAnalysis) - -> trans::CrateTranslation { + analysis: ty::CrateAnalysis) -> trans::CrateTranslation { let time_passes = tcx.sess.time_passes(); time(time_passes, "resolving dependency formats", || dependency_format::calculate(&tcx.sess)); - time(time_passes, - "erasing regions from MIR", - || mir::transform::erase_regions::erase_regions(tcx, &mut mir_map)); - - time(time_passes, "breaking critical edges", - || mir::transform::break_critical_edges::break_critical_edges(&mut mir_map)); + // Run the passes that transform the MIR into a more suitable for translation + // to LLVM code. + time(time_passes, "Prepare MIR codegen passes", || { + let mut passes = ::rustc::mir::transform::Passes::new(); + passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads); + passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks); + passes.push_pass(box mir::transform::erase_regions::EraseRegions); + passes.push_pass(box mir::transform::break_critical_edges::BreakCriticalEdges); + passes.run_passes(tcx, &mut mir_map); + }); - // Option dance to work around the lack of stack once closures. time(time_passes, "translation", move || trans::trans_crate(tcx, &mir_map, analysis)) diff --git a/src/librustc_mir/transform/break_critical_edges.rs b/src/librustc_mir/transform/break_critical_edges.rs index 6ce9f3489172d..e78c8e8fd7355 100644 --- a/src/librustc_mir/transform/break_critical_edges.rs +++ b/src/librustc_mir/transform/break_critical_edges.rs @@ -7,11 +7,16 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. + +use rustc::ty::TyCtxt; use rustc::mir::repr::*; -use rustc::mir::mir_map::MirMap; +use rustc::mir::transform::{MirPass, Pass}; +use syntax::ast::NodeId; use traversal; +pub struct BreakCriticalEdges; + /** * Breaks critical edges in the MIR. * @@ -34,13 +39,16 @@ use traversal; * NOTE: Simplify CFG will happily undo most of the work this pass does. * */ -pub fn break_critical_edges<'tcx>(mir_map: &mut MirMap<'tcx>) { - for (_, mir) in &mut mir_map.map { - break_critical_edges_fn(mir); + +impl<'tcx> MirPass<'tcx> for BreakCriticalEdges { + fn run_pass(&mut self, _: &TyCtxt<'tcx>, _: NodeId, mir: &mut Mir<'tcx>) { + break_critical_edges(mir); } } -fn break_critical_edges_fn(mir: &mut Mir) { +impl Pass for BreakCriticalEdges {} + +fn break_critical_edges(mir: &mut Mir) { let mut pred_count = vec![0u32; mir.basic_blocks.len()]; // Build the precedecessor map for the MIR @@ -63,13 +71,19 @@ fn break_critical_edges_fn(mir: &mut Mir) { if let Some(ref mut term) = data.terminator { let is_invoke = term_is_invoke(term); + let term_span = term.span; + let term_scope = term.scope; let succs = term.successors_mut(); if succs.len() > 1 || (succs.len() > 0 && is_invoke) { for tgt in succs { let num_preds = pred_count[tgt.index()]; if num_preds > 1 { // It's a critical edge, break it - let goto = Terminator::Goto { target: *tgt }; + let goto = Terminator { + span: term_span, + scope: term_scope, + kind: TerminatorKind::Goto { target: *tgt } + }; let data = BasicBlockData::new(Some(goto)); // Get the index it will be when inserted into the MIR let idx = cur_len + new_blocks.len(); @@ -88,9 +102,9 @@ fn break_critical_edges_fn(mir: &mut Mir) { // Returns true if the terminator would use an invoke in LLVM. fn term_is_invoke(term: &Terminator) -> bool { - match *term { - Terminator::Call { cleanup: Some(_), .. } | - Terminator::Drop { unwind: Some(_), .. } => true, + match term.kind { + TerminatorKind::Call { cleanup: Some(_), .. } | + TerminatorKind::Drop { unwind: Some(_), .. } => true, _ => false } } diff --git a/src/librustc_mir/traversal.rs b/src/librustc_mir/traversal.rs index fc53881bd816c..8b6821136f511 100644 --- a/src/librustc_mir/traversal.rs +++ b/src/librustc_mir/traversal.rs @@ -163,7 +163,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { // Now that the top of the stack has no successors we can traverse, each item will // be popped off during iteration until we get back to `A`. This yeilds [E, D, B]. // - // When we yeild `B` and call `traverse_successor`, We push `C` to the stack, but + // When we yield `B` and call `traverse_successor`, we push `C` to the stack, but // since we've already visited `E`, that child isn't added to the stack. The last // two iterations yield `C` and finally `A` for a final traversal of [E, D, B, C, A] loop { diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index e1a0d33fa135f..91577fc654a46 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -19,7 +19,7 @@ use common::{self, Block, BlockAndBuilder, FunctionContext}; use std::ops::Deref; use std::rc::Rc; -use trans::basic_block::BasicBlock; +use basic_block::BasicBlock; use rustc_data_structures::bitvec::BitVector;