apply pre-trans passes to Shim MIR

This commit is contained in:
Ariel Ben-Yehuda 2017-03-09 20:36:01 +02:00
parent 2b9fea1300
commit 26df816f52
4 changed files with 69 additions and 60 deletions

View File

@ -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),

View File

@ -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 {}

View File

@ -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)
}
}

View File

@ -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);
}
}