From 26df816f520d00fe5ddf332a0a08ad6e26a5698d Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 9 Mar 2017 20:36:01 +0200 Subject: [PATCH] apply pre-trans passes to Shim MIR --- src/librustc_mir/shim.rs | 23 +++--- src/librustc_mir/transform/add_call_guards.rs | 82 ++++++++++--------- src/librustc_mir/transform/no_landing_pads.rs | 10 ++- src/librustc_mir/transform/simplify.rs | 14 ++-- 4 files changed, 69 insertions(+), 60 deletions(-) diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 35ad296006d..2d9ef124ad2 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -28,6 +28,8 @@ use std::cell::RefCell; use std::iter; use std::mem; +use transform::{add_call_guards, no_landing_pads, simplify}; + pub fn provide(providers: &mut Providers) { providers.mir_shims = make_shim; } @@ -42,7 +44,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, let param_env = tcx.construct_parameter_environment(span, did, ROOT_CODE_EXTENT); - let result = match instance { + let mut result = match instance { ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance), ty::InstanceDef::FnPtrShim(def_id, ty) => { @@ -103,6 +105,10 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, bug!("creating shims from intrinsics ({:?}) is unsupported", instance) } }; + 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); debug!("make_shim({:?}) = {:?}", instance, result); let result = tcx.alloc_mir(result); @@ -230,18 +236,13 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, }) }; - let have_unwind = match (rcvr_adjustment, tcx.sess.no_landing_pads()) { - (Adjustment::RefMut, false) => true, - _ => false - }; - // BB #0 block(&mut blocks, statements, TerminatorKind::Call { func: callee, args: args, destination: Some((Lvalue::Local(RETURN_POINTER), BasicBlock::new(1))), - cleanup: if have_unwind { + cleanup: if let Adjustment::RefMut = rcvr_adjustment { Some(BasicBlock::new(3)) } else { None @@ -253,16 +254,12 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, block(&mut blocks, vec![], TerminatorKind::Drop { location: Lvalue::Local(rcvr_arg), target: BasicBlock::new(2), - unwind: if have_unwind { - Some(BasicBlock::new(4)) - } else { - None - } + unwind: None }, false); } // BB #1/#2 - return block(&mut blocks, vec![], TerminatorKind::Return, false); - if have_unwind { + if let Adjustment::RefMut = rcvr_adjustment { // BB #3 - drop if closure panics block(&mut blocks, vec![], TerminatorKind::Drop { location: Lvalue::Local(rcvr_arg), diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index 89e644e4fb0..80b17c6a008 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -37,46 +37,50 @@ pub struct AddCallGuards; impl<'tcx> MirPass<'tcx> for AddCallGuards { fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { - 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(); - - 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 } - }) - }; - - // 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()); - - mir.basic_blocks_mut().extend(new_blocks); + add_call_guards(mir); } } +pub fn add_call_guards(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(); + + 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 } + }) + }; + + // 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()); + + mir.basic_blocks_mut().extend(new_blocks); +} + impl Pass for AddCallGuards {} diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index 55a26f4b37f..3654ae6940c 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -42,12 +42,16 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads { } } +pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) { + if tcx.sess.no_landing_pads() { + NoLandingPads.visit_mir(mir); + } +} + impl<'tcx> MirPass<'tcx> for NoLandingPads { fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { - if tcx.sess.no_landing_pads() { - self.visit_mir(mir); - } + no_landing_pads(tcx, mir) } } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index a762507f35e..0a8f147b214 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -53,14 +53,18 @@ impl<'a> SimplifyCfg<'a> { } } +pub fn simplify_cfg(mir: &mut Mir) { + CfgSimplifier::new(mir).simplify(); + remove_dead_blocks(mir); + + // FIXME: Should probably be moved into some kind of pass manager + mir.basic_blocks_mut().raw.shrink_to_fit(); +} + impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> { fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir); - CfgSimplifier::new(mir).simplify(); - remove_dead_blocks(mir); - - // FIXME: Should probably be moved into some kind of pass manager - mir.basic_blocks_mut().raw.shrink_to_fit(); + simplify_cfg(mir); } }