Don’t generate landing-pads if -Z no-landing-pads

This commit is contained in:
Simonas Kazlauskas 2015-12-20 15:30:09 +02:00
parent 20ec53a0d3
commit cef6aee369
5 changed files with 58 additions and 30 deletions

View File

@ -192,6 +192,7 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
pub struct BasicBlockData<'tcx> {
pub statements: Vec<Statement<'tcx>>,
pub terminator: Option<Terminator<'tcx>>,
pub is_cleanup: bool,
}
#[derive(RustcEncodable, RustcDecodable)]
@ -341,6 +342,7 @@ pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> {
BasicBlockData {
statements: vec![],
terminator: terminator,
is_cleanup: false,
}
}

View File

@ -251,6 +251,7 @@ pub fn diverge_cleanup(&mut self) -> Option<BasicBlock> {
continue;
} else {
let new_block = self.cfg.start_new_block();
self.cfg.block_data_mut(new_block).is_cleanup = true;
self.cfg.terminate(new_block, terminator);
terminator = Terminator::Goto { target: new_block };
for &(kind, span, ref lvalue) in scope.drops.iter().rev() {

View File

@ -958,22 +958,28 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
sess.target.target.options.is_like_msvc && sess.target.target.arch == "x86"
}
pub fn need_invoke(bcx: Block) -> bool {
pub fn avoid_invoke(bcx: Block) -> bool {
// FIXME(#25869) currently SEH-based unwinding is pretty buggy in LLVM and
// is being overhauled as this is being written. Until that
// time such that upstream LLVM's implementation is more solid
// and we start binding it we need to skip invokes for any
// target which wants SEH-based unwinding.
if bcx.sess().no_landing_pads() || wants_msvc_seh(bcx.sess()) {
return false;
true
} else if bcx.is_lpad {
// Avoid using invoke if we are already inside a landing pad.
true
} else {
false
}
}
// Avoid using invoke if we are already inside a landing pad.
if bcx.is_lpad {
return false;
pub fn need_invoke(bcx: Block) -> bool {
if avoid_invoke(bcx) {
false
} else {
bcx.fcx.needs_invoke()
}
bcx.fcx.needs_invoke()
}
pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, t: Ty<'tcx>) -> ValueRef {

View File

@ -128,19 +128,9 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
let debugloc = DebugLoc::None;
let attrs = attributes::from_fn_type(bcx.ccx(), callee.ty);
match *targets {
mir::CallTargets::Return(ret) => {
let llret = build::Call(bcx,
callee.immediate(),
&llargs[..],
Some(attrs),
debugloc);
if !return_outptr && !common::type_is_zero_size(bcx.ccx(), ret_ty) {
base::store_ty(bcx, llret, call_dest.llval, ret_ty);
}
build::Br(bcx, self.llblock(ret), debugloc)
}
mir::CallTargets::WithCleanup((ret, cleanup)) => {
match (*targets, base::avoid_invoke(bcx)) {
(mir::CallTargets::WithCleanup((ret, cleanup)), false) => {
let cleanup = self.bcx(cleanup);
let landingpad = self.make_landing_pad(cleanup);
build::Invoke(bcx,
callee.immediate(),
@ -153,6 +143,26 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
// FIXME: What do we do here?
unimplemented!()
}
},
(t, _) => {
let ret = match t {
mir::CallTargets::Return(ret) => ret,
mir::CallTargets::WithCleanup((ret, _)) => {
// make a landing pad regardless (so it sets the personality slot.
let block = self.unreachable_block();
self.make_landing_pad(block);
ret
}
};
let llret = build::Call(bcx,
callee.immediate(),
&llargs[..],
Some(attrs),
debugloc);
if !return_outptr && !common::type_is_zero_size(bcx.ccx(), ret_ty) {
base::store_ty(bcx, llret, call_dest.llval, ret_ty);
}
build::Br(bcx, self.llblock(ret), debugloc)
}
}
},
@ -171,12 +181,9 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
}
let debugloc = DebugLoc::None;
let attrs = attributes::from_fn_type(bcx.ccx(), callee.ty);
match *cleanup {
None => {
build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
build::Unreachable(bcx);
}
Some(cleanup) => {
match (*cleanup, base::avoid_invoke(bcx)) {
(Some(cleanup), false) => {
let cleanup = self.bcx(cleanup);
let landingpad = self.make_landing_pad(cleanup);
let unreachable = self.unreachable_block();
build::Invoke(bcx,
@ -187,13 +194,22 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
Some(attrs),
debugloc);
}
(t, _) => {
if t.is_some() {
// make a landing pad regardless, so it sets the personality slot.
let block = self.unreachable_block();
self.make_landing_pad(block);
}
build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
build::Unreachable(bcx);
}
}
}
}
}
fn make_landing_pad(&mut self, cleanup: mir::BasicBlock) -> Block<'bcx, 'tcx> {
let bcx = self.bcx(cleanup).fcx.new_block(true, "cleanup", None);
fn make_landing_pad(&mut self, cleanup: Block<'bcx, 'tcx>) -> Block<'bcx, 'tcx> {
let bcx = cleanup.fcx.new_block(true, "cleanup", None);
let ccx = bcx.ccx();
let llpersonality = bcx.fcx.eh_personality();
let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
@ -208,7 +224,7 @@ fn make_landing_pad(&mut self, cleanup: mir::BasicBlock) -> Block<'bcx, 'tcx> {
build::Store(bcx, llretval, personalityslot)
}
};
build::Br(bcx, self.llblock(cleanup), DebugLoc::None);
build::Br(bcx, cleanup.llbb, DebugLoc::None);
bcx
}

View File

@ -113,7 +113,10 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {
// Allocate a `Block` for every basic block
let block_bcxs: Vec<Block<'bcx,'tcx>> =
mir_blocks.iter()
.map(|&bb| fcx.new_block(false, &format!("{:?}", bb), None))
.map(|&bb|{
let is_cleanup = mir.basic_block_data(bb).is_cleanup;
fcx.new_block(is_cleanup, &format!("{:?}", bb), None)
})
.collect();
// Branch to the START block