Don’t generate landing-pads if -Z no-landing-pads
This commit is contained in:
parent
20ec53a0d3
commit
cef6aee369
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user