Skip to content

Commit

Permalink
Create personality slot when translating Resume
Browse files Browse the repository at this point in the history
This considerably simplifies code around calling functions and translation of Resume itself. This
removes requirement that a block containing Resume terminator is always translated after something
which creates a landing pad, thus allowing us to actually translate some valid MIRs we could not
translate before.

However, an assumption is added that translator is correct (in regards to landing pad generation)
and code will never reach the Resume terminator without going through a landing pad first. Breaking
these assumptions would pass an `undef` value into the personality functions.
  • Loading branch information
nagisa committed Jan 6, 2016
1 parent f981424 commit 36b3951
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 38 deletions.
61 changes: 26 additions & 35 deletions src/librustc_trans/trans/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use llvm::BasicBlockRef;
use llvm::{BasicBlockRef, ValueRef};
use rustc::mir::repr as mir;
use trans::adt;
use trans::base;
Expand Down Expand Up @@ -80,13 +80,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
}

mir::Terminator::Resume => {
if let Some(personalityslot) = self.llpersonalityslot {
let lp = build::Load(bcx, personalityslot);
base::call_lifetime_end(bcx, personalityslot);
build::Resume(bcx, lp);
} else {
panic!("resume terminator without personality slot set")
}
let ps = self.get_personality_slot(bcx);
let lp = build::Load(bcx, ps);
base::call_lifetime_end(bcx, ps);
base::trans_unwind_resume(bcx, lp);
}

mir::Terminator::Return => {
Expand Down Expand Up @@ -187,29 +184,17 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
build::Br(target, postinvoketarget.llbb, debugloc);
}
},
// Everything else uses the regular `Call`, but we have to be careful to
// generate landing pads for later, even if we do not use it.
// FIXME: maybe just change Resume to not panic in that case?
(_, k@&mir::CallKind::DivergingCleanup(_)) |
(_, k@&mir::CallKind::Diverging) => {
if let mir::CallKind::DivergingCleanup(_) = *k {
// make a landing pad regardless, so it sets the personality slot.
let block = self.unreachable_block();
self.make_landing_pad(block);
}
(_, &mir::CallKind::DivergingCleanup(_)) |
(_, &mir::CallKind::Diverging) => {
build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
build::Unreachable(bcx);
}
(_, k@&mir::CallKind::ConvergingCleanup { .. }) |
(_, k@&mir::CallKind::Converging { .. }) => {
let ret = match *k {
// Bug #20046
let target = match *k {
mir::CallKind::ConvergingCleanup { targets, .. } => targets.0,
mir::CallKind::Converging { target, .. } => target,
mir::CallKind::ConvergingCleanup { targets, .. } => {
// make a landing pad regardless (so it sets the personality slot.
let block = self.unreachable_block();
self.make_landing_pad(block);
targets.0
},
_ => unreachable!()
};
let llret = build::Call(bcx,
Expand All @@ -222,29 +207,35 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
.expect("return destination and type not set");
base::store_ty(bcx, llret, ret_dest.llval, ret_ty);
}
build::Br(bcx, self.llblock(ret), debugloc)
build::Br(bcx, self.llblock(target), debugloc);
}
}
}
}
}

fn get_personality_slot(&mut self, bcx: Block<'bcx, 'tcx>) -> ValueRef {
let ccx = bcx.ccx();
if let Some(slot) = self.llpersonalityslot {
slot
} else {
let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
let slot = base::alloca(bcx, llretty, "personalityslot");
self.llpersonalityslot = Some(slot);
base::call_lifetime_start(bcx, slot);
slot
}
}

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);
let llretval = build::LandingPad(bcx, llretty, llpersonality, 1);
build::SetCleanup(bcx, llretval);
match self.llpersonalityslot {
Some(slot) => build::Store(bcx, llretval, slot),
None => {
let personalityslot = base::alloca(bcx, llretty, "personalityslot");
self.llpersonalityslot = Some(personalityslot);
base::call_lifetime_start(bcx, personalityslot);
build::Store(bcx, llretval, personalityslot)
}
};
let slot = self.get_personality_slot(bcx);
build::Store(bcx, llretval, slot);
build::Br(bcx, cleanup.llbb, DebugLoc::None);
bcx
}
Expand Down
3 changes: 0 additions & 3 deletions src/librustc_trans/trans/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,6 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {

// Translate the body of each block
for &bb in &mir_blocks {
// NB that we do not handle the Resume terminator specially, because a block containing
// that terminator will have a higher block number than a function call which should take
// care of filling in that information.
mircx.trans_block(bb);
}
}
Expand Down

0 comments on commit 36b3951

Please sign in to comment.