apply pre-trans passes to Shim MIR
This commit is contained in:
parent
2b9fea1300
commit
26df816f52
@ -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),
|
||||
|
@ -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 {}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user