]> git.lizzy.rs Git - rust.git/commitdiff
run AddCallGuards for *all* call edges before running AddValidation
authorRalf Jung <post@ralfj.de>
Wed, 9 Aug 2017 18:30:55 +0000 (11:30 -0700)
committerRalf Jung <post@ralfj.de>
Wed, 9 Aug 2017 19:16:59 +0000 (12:16 -0700)
src/librustc_driver/driver.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/add_call_guards.rs

index 12cb556afdabcb20cd7366b2ffcb90545edd4488..443bdf6a373ade70dbae53976e3644b0d437f807 100644 (file)
@@ -942,15 +942,16 @@ macro_rules! try_with_f {
 
     // These next passes must be executed together
     passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
+    // AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs
+    // an AllCallEdges pass right before it.
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AllCallEdges);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_validation::AddValidation);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
     // No lifetime analysis based on borrowing can be done from here on out.
 
-    // AddValidation needs to run after ElaborateDrops and before EraseRegions.
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_validation::AddValidation);
-
     // From here on out, regions are gone.
     passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions);
 
@@ -960,7 +961,7 @@ macro_rules! try_with_f {
     passes.push_pass(MIR_OPTIMIZED, mir::transform::deaggregator::Deaggregator);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::copy_prop::CopyPropagation);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyLocals);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::dump_mir::Marker("PreTrans"));
 
     TyCtxt::create_and_enter(sess,
index 11ad5d1509d29bcd17b2cd0bb1c541986de4cf31..62e762be93a71938a7a3f93ccfdc40d1186a43f7 100644 (file)
@@ -105,7 +105,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
         debug!("make_shim({:?}) = untransformed {:?}", instance, result);
         no_landing_pads::no_landing_pads(tcx, &mut result);
         simplify::simplify_cfg(&mut result);
-        add_call_guards::add_call_guards(&mut result);
+        add_call_guards::CriticalCallEdges.add_call_guards(&mut result);
     debug!("make_shim({:?}) = {:?}", instance, result);
 
     tcx.alloc_mir(result)
index b7c7a1774dd356f3ab2aac43decccb7002904a36..23a9c4c57ca6a39b107b2fef139c8540e3145457 100644 (file)
 use rustc::mir::transform::{MirPass, MirSource};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
-pub struct AddCallGuards;
+#[derive(PartialEq)]
+pub enum AddCallGuards {
+    AllCallEdges,
+    CriticalCallEdges,
+}
+pub use self::AddCallGuards::*;
 
 /**
  * Breaks outgoing critical edges for call terminators in the MIR.
@@ -40,48 +45,52 @@ fn run_pass<'a, 'tcx>(&self,
                           _tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource,
                           mir: &mut Mir<'tcx>) {
-        add_call_guards(mir);
+        self.add_call_guards(mir);
     }
 }
 
-pub fn add_call_guards(mir: &mut Mir) {
-    let pred_count: IndexVec<_, _> =
-        mir.predecessors().iter().map(|ps| ps.len()).collect();
+impl AddCallGuards {
+    pub fn add_call_guards(&self, mir: &mut Mir) {
+        let pred_count: IndexVec<_, _> =
+            mir.predecessors().iter().map(|ps| ps.len()).collect();
 
-    // We need a place to store the new blocks generated
-    let mut new_blocks = Vec::new();
+        // We need a place to store the new blocks generated
+        let mut new_blocks = Vec::new();
 
-    let cur_len = mir.basic_blocks().len();
+        let cur_len = mir.basic_blocks().len();
 
-    for block in mir.basic_blocks_mut() {
-        match block.terminator {
-            Some(Terminator {
-                kind: TerminatorKind::Call {
-                    destination: Some((_, ref mut destination)),
-                    cleanup: Some(_),
-                    ..
-                }, source_info
-            }) if pred_count[*destination] > 1 => {
-                // It's a critical edge, break it
-                let call_guard = BasicBlockData {
-                    statements: vec![],
-                    is_cleanup: block.is_cleanup,
-                    terminator: Some(Terminator {
-                        source_info: source_info,
-                        kind: TerminatorKind::Goto { target: *destination }
-                    })
-                };
+        for block in mir.basic_blocks_mut() {
+            match block.terminator {
+                Some(Terminator {
+                    kind: TerminatorKind::Call {
+                        destination: Some((_, ref mut destination)),
+                        cleanup,
+                        ..
+                    }, source_info
+                }) if pred_count[*destination] > 1 &&
+                      (cleanup.is_some() || self == &AllCallEdges) =>
+                {
+                    // It's a critical edge, break it
+                    let call_guard = BasicBlockData {
+                        statements: vec![],
+                        is_cleanup: block.is_cleanup,
+                        terminator: Some(Terminator {
+                            source_info: source_info,
+                            kind: TerminatorKind::Goto { target: *destination }
+                        })
+                    };
 
-                // Get the index it will be when inserted into the MIR
-                let idx = cur_len + new_blocks.len();
-                new_blocks.push(call_guard);
-                *destination = BasicBlock::new(idx);
+                    // Get the index it will be when inserted into the MIR
+                    let idx = cur_len + new_blocks.len();
+                    new_blocks.push(call_guard);
+                    *destination = BasicBlock::new(idx);
+                }
+                _ => {}
             }
-            _ => {}
         }
-    }
 
-    debug!("Broke {} N edges", new_blocks.len());
+        debug!("Broke {} N edges", new_blocks.len());
 
-    mir.basic_blocks_mut().extend(new_blocks);
+        mir.basic_blocks_mut().extend(new_blocks);
+    }
 }