Skip to content

Commit 36b3951

Browse files
committed
Create personality slot when translating Resume
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.
1 parent f981424 commit 36b3951

File tree

2 files changed

+26
-38
lines changed

2 files changed

+26
-38
lines changed

Diff for: src/librustc_trans/trans/mir/block.rs

+26-35
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use llvm::BasicBlockRef;
11+
use llvm::{BasicBlockRef, ValueRef};
1212
use rustc::mir::repr as mir;
1313
use trans::adt;
1414
use trans::base;
@@ -80,13 +80,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
8080
}
8181

8282
mir::Terminator::Resume => {
83-
if let Some(personalityslot) = self.llpersonalityslot {
84-
let lp = build::Load(bcx, personalityslot);
85-
base::call_lifetime_end(bcx, personalityslot);
86-
build::Resume(bcx, lp);
87-
} else {
88-
panic!("resume terminator without personality slot set")
89-
}
83+
let ps = self.get_personality_slot(bcx);
84+
let lp = build::Load(bcx, ps);
85+
base::call_lifetime_end(bcx, ps);
86+
base::trans_unwind_resume(bcx, lp);
9087
}
9188

9289
mir::Terminator::Return => {
@@ -187,29 +184,17 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
187184
build::Br(target, postinvoketarget.llbb, debugloc);
188185
}
189186
},
190-
// Everything else uses the regular `Call`, but we have to be careful to
191-
// generate landing pads for later, even if we do not use it.
192-
// FIXME: maybe just change Resume to not panic in that case?
193-
(_, k@&mir::CallKind::DivergingCleanup(_)) |
194-
(_, k@&mir::CallKind::Diverging) => {
195-
if let mir::CallKind::DivergingCleanup(_) = *k {
196-
// make a landing pad regardless, so it sets the personality slot.
197-
let block = self.unreachable_block();
198-
self.make_landing_pad(block);
199-
}
187+
(_, &mir::CallKind::DivergingCleanup(_)) |
188+
(_, &mir::CallKind::Diverging) => {
200189
build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
201190
build::Unreachable(bcx);
202191
}
203192
(_, k@&mir::CallKind::ConvergingCleanup { .. }) |
204193
(_, k@&mir::CallKind::Converging { .. }) => {
205-
let ret = match *k {
194+
// Bug #20046
195+
let target = match *k {
196+
mir::CallKind::ConvergingCleanup { targets, .. } => targets.0,
206197
mir::CallKind::Converging { target, .. } => target,
207-
mir::CallKind::ConvergingCleanup { targets, .. } => {
208-
// make a landing pad regardless (so it sets the personality slot.
209-
let block = self.unreachable_block();
210-
self.make_landing_pad(block);
211-
targets.0
212-
},
213198
_ => unreachable!()
214199
};
215200
let llret = build::Call(bcx,
@@ -222,29 +207,35 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
222207
.expect("return destination and type not set");
223208
base::store_ty(bcx, llret, ret_dest.llval, ret_ty);
224209
}
225-
build::Br(bcx, self.llblock(ret), debugloc)
210+
build::Br(bcx, self.llblock(target), debugloc);
226211
}
227212
}
228213
}
229214
}
230215
}
231216

217+
fn get_personality_slot(&mut self, bcx: Block<'bcx, 'tcx>) -> ValueRef {
218+
let ccx = bcx.ccx();
219+
if let Some(slot) = self.llpersonalityslot {
220+
slot
221+
} else {
222+
let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
223+
let slot = base::alloca(bcx, llretty, "personalityslot");
224+
self.llpersonalityslot = Some(slot);
225+
base::call_lifetime_start(bcx, slot);
226+
slot
227+
}
228+
}
229+
232230
fn make_landing_pad(&mut self, cleanup: Block<'bcx, 'tcx>) -> Block<'bcx, 'tcx> {
233231
let bcx = cleanup.fcx.new_block(true, "cleanup", None);
234232
let ccx = bcx.ccx();
235233
let llpersonality = bcx.fcx.eh_personality();
236234
let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
237235
let llretval = build::LandingPad(bcx, llretty, llpersonality, 1);
238236
build::SetCleanup(bcx, llretval);
239-
match self.llpersonalityslot {
240-
Some(slot) => build::Store(bcx, llretval, slot),
241-
None => {
242-
let personalityslot = base::alloca(bcx, llretty, "personalityslot");
243-
self.llpersonalityslot = Some(personalityslot);
244-
base::call_lifetime_start(bcx, personalityslot);
245-
build::Store(bcx, llretval, personalityslot)
246-
}
247-
};
237+
let slot = self.get_personality_slot(bcx);
238+
build::Store(bcx, llretval, slot);
248239
build::Br(bcx, cleanup.llbb, DebugLoc::None);
249240
bcx
250241
}

Diff for: src/librustc_trans/trans/mir/mod.rs

-3
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,6 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {
136136

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

0 commit comments

Comments
 (0)