1
Fork 0

Refactor storage of LandingPads

This commit is contained in:
Piotr Czarnecki 2016-02-08 11:53:06 +01:00
parent 06266eb3bd
commit a9ab8096ba
7 changed files with 58 additions and 34 deletions

View file

@ -988,7 +988,7 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
} }
pub fn avoid_invoke(bcx: Block) -> bool { pub fn avoid_invoke(bcx: Block) -> bool {
bcx.sess().no_landing_pads() || bcx.lpad.borrow().is_some() bcx.sess().no_landing_pads() || bcx.lpad().is_some()
} }
pub fn need_invoke(bcx: Block) -> bool { pub fn need_invoke(bcx: Block) -> bool {
@ -1616,6 +1616,7 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
param_substs: param_substs, param_substs: param_substs,
span: sp, span: sp,
block_arena: block_arena, block_arena: block_arena,
lpad_arena: TypedArena::new(),
ccx: ccx, ccx: ccx,
debug_context: debug_context, debug_context: debug_context,
scopes: RefCell::new(Vec::new()), scopes: RefCell::new(Vec::new()),

View file

@ -150,8 +150,7 @@ pub fn Invoke(cx: Block,
cx.val_to_string(fn_), cx.val_to_string(fn_),
args.iter().map(|a| cx.val_to_string(*a)).collect::<Vec<String>>().join(", ")); args.iter().map(|a| cx.val_to_string(*a)).collect::<Vec<String>>().join(", "));
debug_loc.apply(cx.fcx); debug_loc.apply(cx.fcx);
let lpad = cx.lpad.borrow(); let bundle = cx.lpad().and_then(|b| b.bundle());
let bundle = lpad.as_ref().and_then(|b| b.bundle());
B(cx).invoke(fn_, args, then, catch, bundle, attributes) B(cx).invoke(fn_, args, then, catch, bundle, attributes)
} }
@ -916,8 +915,7 @@ pub fn Call(cx: Block,
return _UndefReturn(cx, fn_); return _UndefReturn(cx, fn_);
} }
debug_loc.apply(cx.fcx); debug_loc.apply(cx.fcx);
let lpad = cx.lpad.borrow(); let bundle = cx.lpad.get().and_then(|b| b.bundle());
let bundle = lpad.as_ref().and_then(|b| b.bundle());
B(cx).call(fn_, args, bundle, attributes) B(cx).call(fn_, args, bundle, attributes)
} }
@ -932,8 +930,7 @@ pub fn CallWithConv(cx: Block,
return _UndefReturn(cx, fn_); return _UndefReturn(cx, fn_);
} }
debug_loc.apply(cx.fcx); debug_loc.apply(cx.fcx);
let lpad = cx.lpad.borrow(); let bundle = cx.lpad.get().and_then(|b| b.bundle());
let bundle = lpad.as_ref().and_then(|b| b.bundle());
B(cx).call_with_conv(fn_, args, conv, bundle, attributes) B(cx).call_with_conv(fn_, args, conv, bundle, attributes)
} }

View file

@ -740,7 +740,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
UnwindExit(val) => { UnwindExit(val) => {
// Generate a block that will resume unwinding to the // Generate a block that will resume unwinding to the
// calling function // calling function
let bcx = self.new_block("resume", None); let bcx = self.new_block("resume", None, None);
match val { match val {
UnwindKind::LandingPad => { UnwindKind::LandingPad => {
let addr = self.landingpad_alloca.get() let addr = self.landingpad_alloca.get()
@ -830,7 +830,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
let name = scope.block_name("clean"); let name = scope.block_name("clean");
debug!("generating cleanups for {}", name); debug!("generating cleanups for {}", name);
let bcx_in = self.new_block(&name[..], None); let bcx_in = self.new_block(&name[..], None, None);
let exit_label = label.start(bcx_in); let exit_label = label.start(bcx_in);
let mut bcx_out = bcx_in; let mut bcx_out = bcx_in;
let len = scope.cleanups.len(); let len = scope.cleanups.len();
@ -873,7 +873,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
Some(llbb) => return llbb, Some(llbb) => return llbb,
None => { None => {
let name = last_scope.block_name("unwind"); let name = last_scope.block_name("unwind");
pad_bcx = self.new_block(&name[..], None); pad_bcx = self.new_block(&name[..], None, None);
last_scope.cached_landing_pad = Some(pad_bcx.llbb); last_scope.cached_landing_pad = Some(pad_bcx.llbb);
} }
} }
@ -1054,11 +1054,11 @@ impl EarlyExitLabel {
match *self { match *self {
UnwindExit(UnwindKind::CleanupPad(..)) => { UnwindExit(UnwindKind::CleanupPad(..)) => {
let pad = build::CleanupPad(bcx, None, &[]); let pad = build::CleanupPad(bcx, None, &[]);
*bcx.lpad.borrow_mut() = Some(LandingPad::msvc(pad)); bcx.lpad.set(Some(bcx.fcx.lpad_arena.alloc(LandingPad::msvc(pad))));
UnwindExit(UnwindKind::CleanupPad(pad)) UnwindExit(UnwindKind::CleanupPad(pad))
} }
UnwindExit(UnwindKind::LandingPad) => { UnwindExit(UnwindKind::LandingPad) => {
*bcx.lpad.borrow_mut() = Some(LandingPad::gnu()); bcx.lpad.set(Some(bcx.fcx.lpad_arena.alloc(LandingPad::gnu())));
*self *self
} }
label => label, label => label,

View file

@ -367,6 +367,9 @@ pub struct FunctionContext<'a, 'tcx: 'a> {
// The arena that blocks are allocated from. // The arena that blocks are allocated from.
pub block_arena: &'a TypedArena<BlockS<'a, 'tcx>>, pub block_arena: &'a TypedArena<BlockS<'a, 'tcx>>,
// The arena that landing pads are allocated from.
pub lpad_arena: TypedArena<LandingPad>,
// This function's enclosing crate context. // This function's enclosing crate context.
pub ccx: &'a CrateContext<'a, 'tcx>, pub ccx: &'a CrateContext<'a, 'tcx>,
@ -431,14 +434,19 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
pub fn new_block(&'a self, pub fn new_block(&'a self,
name: &str, name: &str,
opt_node_id: Option<ast::NodeId>) opt_node_id: Option<ast::NodeId>,
landing_pad: Option<LandingPad>)
-> Block<'a, 'tcx> { -> Block<'a, 'tcx> {
unsafe { unsafe {
let name = CString::new(name).unwrap(); let name = CString::new(name).unwrap();
let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
self.llfn, self.llfn,
name.as_ptr()); name.as_ptr());
BlockS::new(llbb, opt_node_id, self) let block = BlockS::new(llbb, opt_node_id, self);
if let Some(landing_pad) = landing_pad {
block.lpad.set(Some(self.lpad_arena.alloc(landing_pad)));
}
block
} }
} }
@ -446,13 +454,13 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
name: &str, name: &str,
node_id: ast::NodeId) node_id: ast::NodeId)
-> Block<'a, 'tcx> { -> Block<'a, 'tcx> {
self.new_block(name, Some(node_id)) self.new_block(name, Some(node_id), None)
} }
pub fn new_temp_block(&'a self, pub fn new_temp_block(&'a self,
name: &str) name: &str)
-> Block<'a, 'tcx> { -> Block<'a, 'tcx> {
self.new_block(name, None) self.new_block(name, None, None)
} }
pub fn join_blocks(&'a self, pub fn join_blocks(&'a self,
@ -584,7 +592,7 @@ pub struct BlockS<'blk, 'tcx: 'blk> {
// If this block part of a landing pad, then this is `Some` indicating what // If this block part of a landing pad, then this is `Some` indicating what
// kind of landing pad its in, otherwise this is none. // kind of landing pad its in, otherwise this is none.
pub lpad: RefCell<Option<LandingPad>>, pub lpad: Cell<Option<&'blk LandingPad>>,
// AST node-id associated with this block, if any. Used for // AST node-id associated with this block, if any. Used for
// debugging purposes only. // debugging purposes only.
@ -606,7 +614,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
llbb: llbb, llbb: llbb,
terminated: Cell::new(false), terminated: Cell::new(false),
unreachable: Cell::new(false), unreachable: Cell::new(false),
lpad: RefCell::new(None), lpad: Cell::new(None),
opt_node_id: opt_node_id, opt_node_id: opt_node_id,
fcx: fcx fcx: fcx
}) })
@ -623,6 +631,10 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
} }
pub fn sess(&self) -> &'blk Session { self.fcx.ccx.sess() } pub fn sess(&self) -> &'blk Session { self.fcx.ccx.sess() }
pub fn lpad(&self) -> Option<&'blk LandingPad> {
self.lpad.get()
}
pub fn mir(&self) -> &'blk Mir<'tcx> { pub fn mir(&self) -> &'blk Mir<'tcx> {
self.fcx.mir() self.fcx.mir()
} }
@ -747,6 +759,10 @@ impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> {
self.bcx.llbb self.bcx.llbb
} }
pub fn lpad(&self) -> Option<&'blk LandingPad> {
self.bcx.lpad()
}
pub fn mir(&self) -> &'blk Mir<'tcx> { pub fn mir(&self) -> &'blk Mir<'tcx> {
self.bcx.mir() self.bcx.mir()
} }

View file

@ -119,13 +119,16 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
if let Some(unwind) = unwind { if let Some(unwind) = unwind {
let uwbcx = self.bcx(unwind); let uwbcx = self.bcx(unwind);
let unwind = self.make_landing_pad(uwbcx); let unwind = self.make_landing_pad(uwbcx);
let bundle = bcx.lpad().and_then(|b| b.bundle());
bcx.invoke(drop_fn, bcx.invoke(drop_fn,
&[llvalue], &[llvalue],
self.llblock(target), self.llblock(target),
unwind.llbb(), unwind.llbb(),
bundle,
None); None);
} else { } else {
bcx.call(drop_fn, &[llvalue], None); let bundle = bcx.lpad().and_then(|b| b.bundle());
bcx.call(drop_fn, &[llvalue], bundle, None);
bcx.br(self.llblock(target)); bcx.br(self.llblock(target));
} }
} }
@ -187,24 +190,28 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
let cleanup = self.bcx(cleanup); let cleanup = self.bcx(cleanup);
let landingpad = self.make_landing_pad(cleanup); let landingpad = self.make_landing_pad(cleanup);
let unreachable_blk = self.unreachable_block(); let unreachable_blk = self.unreachable_block();
let bundle = bcx.lpad().and_then(|b| b.bundle());
bcx.invoke(callee.immediate(), bcx.invoke(callee.immediate(),
&llargs[..], &llargs[..],
unreachable_blk.llbb, unreachable_blk.llbb,
landingpad.llbb(), landingpad.llbb(),
bundle,
Some(attrs)); Some(attrs));
}, },
(false, false, &Some(cleanup), &Some((_, success))) => { (false, false, &Some(cleanup), &Some((_, success))) => {
let cleanup = self.bcx(cleanup); let cleanup = self.bcx(cleanup);
let landingpad = self.make_landing_pad(cleanup); let landingpad = self.make_landing_pad(cleanup);
let (target, postinvoke) = if must_copy_dest { let (target, postinvoke) = if must_copy_dest {
(bcx.fcx().new_block("", None), Some(self.bcx(success))) (bcx.fcx().new_block("", None, None).build(), Some(self.bcx(success)))
} else { } else {
(self.bcx(success), None) (self.bcx(success), None)
}; };
let bundle = bcx.lpad().and_then(|b| b.bundle());
let invokeret = bcx.invoke(callee.immediate(), let invokeret = bcx.invoke(callee.immediate(),
&llargs[..], &llargs[..],
target.llbb(), target.llbb(),
landingpad.llbb(), landingpad.llbb(),
bundle,
Some(attrs)); Some(attrs));
if let Some(postinvoketarget) = postinvoke { if let Some(postinvoketarget) = postinvoke {
// We translate the copy into a temporary block. The temporary block is // We translate the copy into a temporary block. The temporary block is
@ -240,7 +247,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
} }
}, },
(false, _, _, &None) => { (false, _, _, &None) => {
bcx.call(callee.immediate(), &llargs[..], Some(attrs)); let bundle = bcx.lpad().and_then(|b| b.bundle());
bcx.call(callee.immediate(), &llargs[..], bundle, Some(attrs));
bcx.unreachable(); bcx.unreachable();
} }
(false, _, _, &Some((_, target))) => { (false, _, _, &Some((_, target))) => {
@ -301,12 +309,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
cleanup: BlockAndBuilder<'bcx, 'tcx>) cleanup: BlockAndBuilder<'bcx, 'tcx>)
-> BlockAndBuilder<'bcx, 'tcx> -> BlockAndBuilder<'bcx, 'tcx>
{ {
let cleanup_llbb = cleanup.llbb();
let bcx = cleanup.map_block(|cleanup| { let bcx = cleanup.map_block(|cleanup| {
cleanup.fcx.new_block("cleanup", None) // FIXME(#30941) this doesn't handle msvc-style exceptions
cleanup.fcx.new_block("cleanup", None, Some(LandingPad::gnu()))
}); });
// FIXME(#30941) this doesn't handle msvc-style exceptions
*bcx.lpad.borrow_mut() = Some(LandingPad::gnu());
let bcx = bcx.build();
let ccx = bcx.ccx(); let ccx = bcx.ccx();
let llpersonality = bcx.fcx().eh_personality(); let llpersonality = bcx.fcx().eh_personality();
let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false); let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
@ -314,13 +321,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
bcx.set_cleanup(llretval); bcx.set_cleanup(llretval);
let slot = self.get_personality_slot(&bcx); let slot = self.get_personality_slot(&bcx);
bcx.store(llretval, slot); bcx.store(llretval, slot);
bcx.br(cleanup.llbb()); bcx.br(cleanup_llbb);
bcx bcx
} }
fn unreachable_block(&mut self) -> Block<'bcx, 'tcx> { fn unreachable_block(&mut self) -> Block<'bcx, 'tcx> {
self.unreachable_block.unwrap_or_else(|| { self.unreachable_block.unwrap_or_else(|| {
let bl = self.fcx.new_block("unreachable", None); let bl = self.fcx.new_block("unreachable", None, None);
bl.build().unreachable(); bl.build().unreachable();
self.unreachable_block = Some(bl); self.unreachable_block = Some(bl);
bl bl

View file

@ -114,12 +114,13 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: BlockAndBuilder<'bcx, 'tcx>) {
let block_bcxs: Vec<Block<'bcx,'tcx>> = let block_bcxs: Vec<Block<'bcx,'tcx>> =
mir_blocks.iter() mir_blocks.iter()
.map(|&bb|{ .map(|&bb|{
let bcx = fcx.new_block(&format!("{:?}", bb), None);
// FIXME(#30941) this doesn't handle msvc-style exceptions // FIXME(#30941) this doesn't handle msvc-style exceptions
if mir.basic_block_data(bb).is_cleanup { let lpad = if mir.basic_block_data(bb).is_cleanup {
*bcx.lpad.borrow_mut() = Some(LandingPad::gnu()) Some(LandingPad::gnu())
} } else {
bcx None
};
fcx.new_block(&format!("{:?}", bb), None, lpad)
}) })
.collect(); .collect();

View file

@ -497,10 +497,12 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
if input_ty == tcx.types.f32 { if input_ty == tcx.types.f32 {
let lllhs = bcx.fpext(lhs, f64t); let lllhs = bcx.fpext(lhs, f64t);
let llrhs = bcx.fpext(rhs, f64t); let llrhs = bcx.fpext(rhs, f64t);
let llres = bcx.call(llfn, &[lllhs, llrhs], None); let bundle = bcx.lpad().and_then(|b| b.bundle());
let llres = bcx.call(llfn, &[lllhs, llrhs], bundle, None);
bcx.fptrunc(llres, Type::f32(bcx.ccx())) bcx.fptrunc(llres, Type::f32(bcx.ccx()))
} else { } else {
bcx.call(llfn, &[lhs, rhs], None) let bundle = bcx.lpad().and_then(|b| b.bundle());
bcx.call(llfn, &[lhs, rhs], bundle, None)
} }
} else { } else {
bcx.frem(lhs, rhs) bcx.frem(lhs, rhs)