From a9ab8096ba4445f6495684b85a7c9b34fd94049c Mon Sep 17 00:00:00 2001 From: Piotr Czarnecki Date: Mon, 8 Feb 2016 11:53:06 +0100 Subject: [PATCH] Refactor storage of `LandingPad`s --- src/librustc_trans/trans/base.rs | 3 ++- src/librustc_trans/trans/build.rs | 9 +++------ src/librustc_trans/trans/cleanup.rs | 10 ++++----- src/librustc_trans/trans/common.rs | 28 ++++++++++++++++++++------ src/librustc_trans/trans/mir/block.rs | 25 ++++++++++++++--------- src/librustc_trans/trans/mir/mod.rs | 11 +++++----- src/librustc_trans/trans/mir/rvalue.rs | 6 ++++-- 7 files changed, 58 insertions(+), 34 deletions(-) diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index bcca4963781f..57e69a0efa95 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -988,7 +988,7 @@ pub fn wants_msvc_seh(sess: &Session) -> 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 { @@ -1616,6 +1616,7 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, param_substs: param_substs, span: sp, block_arena: block_arena, + lpad_arena: TypedArena::new(), ccx: ccx, debug_context: debug_context, scopes: RefCell::new(Vec::new()), diff --git a/src/librustc_trans/trans/build.rs b/src/librustc_trans/trans/build.rs index e501855b5d5f..ce541c8d411b 100644 --- a/src/librustc_trans/trans/build.rs +++ b/src/librustc_trans/trans/build.rs @@ -150,8 +150,7 @@ pub fn Invoke(cx: Block, cx.val_to_string(fn_), args.iter().map(|a| cx.val_to_string(*a)).collect::>().join(", ")); debug_loc.apply(cx.fcx); - let lpad = cx.lpad.borrow(); - let bundle = lpad.as_ref().and_then(|b| b.bundle()); + let bundle = cx.lpad().and_then(|b| b.bundle()); B(cx).invoke(fn_, args, then, catch, bundle, attributes) } @@ -916,8 +915,7 @@ pub fn Call(cx: Block, return _UndefReturn(cx, fn_); } debug_loc.apply(cx.fcx); - let lpad = cx.lpad.borrow(); - let bundle = lpad.as_ref().and_then(|b| b.bundle()); + let bundle = cx.lpad.get().and_then(|b| b.bundle()); B(cx).call(fn_, args, bundle, attributes) } @@ -932,8 +930,7 @@ pub fn CallWithConv(cx: Block, return _UndefReturn(cx, fn_); } debug_loc.apply(cx.fcx); - let lpad = cx.lpad.borrow(); - let bundle = lpad.as_ref().and_then(|b| b.bundle()); + let bundle = cx.lpad.get().and_then(|b| b.bundle()); B(cx).call_with_conv(fn_, args, conv, bundle, attributes) } diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index 7c98868dfe7c..1b69784c0966 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -740,7 +740,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx UnwindExit(val) => { // Generate a block that will resume unwinding to the // calling function - let bcx = self.new_block("resume", None); + let bcx = self.new_block("resume", None, None); match val { UnwindKind::LandingPad => { 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"); 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 mut bcx_out = bcx_in; let len = scope.cleanups.len(); @@ -873,7 +873,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx Some(llbb) => return llbb, None => { 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); } } @@ -1054,11 +1054,11 @@ impl EarlyExitLabel { match *self { UnwindExit(UnwindKind::CleanupPad(..)) => { 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::LandingPad) => { - *bcx.lpad.borrow_mut() = Some(LandingPad::gnu()); + bcx.lpad.set(Some(bcx.fcx.lpad_arena.alloc(LandingPad::gnu()))); *self } label => label, diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index a23d879bba92..20c48357719d 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -367,6 +367,9 @@ pub struct FunctionContext<'a, 'tcx: 'a> { // The arena that blocks are allocated from. pub block_arena: &'a TypedArena>, + // The arena that landing pads are allocated from. + pub lpad_arena: TypedArena, + // This function's enclosing crate context. pub ccx: &'a CrateContext<'a, 'tcx>, @@ -431,14 +434,19 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { pub fn new_block(&'a self, name: &str, - opt_node_id: Option) + opt_node_id: Option, + landing_pad: Option) -> Block<'a, 'tcx> { unsafe { let name = CString::new(name).unwrap(); let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn, 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, node_id: ast::NodeId) -> 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, name: &str) -> Block<'a, 'tcx> { - self.new_block(name, None) + self.new_block(name, None, None) } 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 // kind of landing pad its in, otherwise this is none. - pub lpad: RefCell>, + pub lpad: Cell>, // AST node-id associated with this block, if any. Used for // debugging purposes only. @@ -606,7 +614,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { llbb: llbb, terminated: Cell::new(false), unreachable: Cell::new(false), - lpad: RefCell::new(None), + lpad: Cell::new(None), opt_node_id: opt_node_id, fcx: fcx }) @@ -623,6 +631,10 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { } 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> { self.fcx.mir() } @@ -747,6 +759,10 @@ impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> { self.bcx.llbb } + pub fn lpad(&self) -> Option<&'blk LandingPad> { + self.bcx.lpad() + } + pub fn mir(&self) -> &'blk Mir<'tcx> { self.bcx.mir() } diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs index 113970d2fc1a..6c1a5ac74d01 100644 --- a/src/librustc_trans/trans/mir/block.rs +++ b/src/librustc_trans/trans/mir/block.rs @@ -119,13 +119,16 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { if let Some(unwind) = unwind { let uwbcx = self.bcx(unwind); let unwind = self.make_landing_pad(uwbcx); + let bundle = bcx.lpad().and_then(|b| b.bundle()); bcx.invoke(drop_fn, &[llvalue], self.llblock(target), unwind.llbb(), + bundle, None); } 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)); } } @@ -187,24 +190,28 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let cleanup = self.bcx(cleanup); let landingpad = self.make_landing_pad(cleanup); let unreachable_blk = self.unreachable_block(); + let bundle = bcx.lpad().and_then(|b| b.bundle()); bcx.invoke(callee.immediate(), &llargs[..], unreachable_blk.llbb, landingpad.llbb(), + bundle, Some(attrs)); }, (false, false, &Some(cleanup), &Some((_, success))) => { let cleanup = self.bcx(cleanup); let landingpad = self.make_landing_pad(cleanup); 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 { (self.bcx(success), None) }; + let bundle = bcx.lpad().and_then(|b| b.bundle()); let invokeret = bcx.invoke(callee.immediate(), &llargs[..], target.llbb(), landingpad.llbb(), + bundle, Some(attrs)); if let Some(postinvoketarget) = postinvoke { // We translate the copy into a temporary block. The temporary block is @@ -240,7 +247,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { } }, (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(); } (false, _, _, &Some((_, target))) => { @@ -301,12 +309,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { cleanup: BlockAndBuilder<'bcx, 'tcx>) -> BlockAndBuilder<'bcx, 'tcx> { + let cleanup_llbb = cleanup.llbb(); 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 llpersonality = bcx.fcx().eh_personality(); 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); let slot = self.get_personality_slot(&bcx); bcx.store(llretval, slot); - bcx.br(cleanup.llbb()); + bcx.br(cleanup_llbb); bcx } fn unreachable_block(&mut self) -> Block<'bcx, 'tcx> { 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(); self.unreachable_block = Some(bl); bl diff --git a/src/librustc_trans/trans/mir/mod.rs b/src/librustc_trans/trans/mir/mod.rs index 289faf4c136a..e93c920d9a3b 100644 --- a/src/librustc_trans/trans/mir/mod.rs +++ b/src/librustc_trans/trans/mir/mod.rs @@ -114,12 +114,13 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: BlockAndBuilder<'bcx, 'tcx>) { let block_bcxs: Vec> = mir_blocks.iter() .map(|&bb|{ - let bcx = fcx.new_block(&format!("{:?}", bb), None); // FIXME(#30941) this doesn't handle msvc-style exceptions - if mir.basic_block_data(bb).is_cleanup { - *bcx.lpad.borrow_mut() = Some(LandingPad::gnu()) - } - bcx + let lpad = if mir.basic_block_data(bb).is_cleanup { + Some(LandingPad::gnu()) + } else { + None + }; + fcx.new_block(&format!("{:?}", bb), None, lpad) }) .collect(); diff --git a/src/librustc_trans/trans/mir/rvalue.rs b/src/librustc_trans/trans/mir/rvalue.rs index 6ef5d53ce87b..5debb76aa6c0 100644 --- a/src/librustc_trans/trans/mir/rvalue.rs +++ b/src/librustc_trans/trans/mir/rvalue.rs @@ -497,10 +497,12 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { if input_ty == tcx.types.f32 { let lllhs = bcx.fpext(lhs, 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())) } else { - bcx.call(llfn, &[lhs, rhs], None) + let bundle = bcx.lpad().and_then(|b| b.bundle()); + bcx.call(llfn, &[lhs, rhs], bundle, None) } } else { bcx.frem(lhs, rhs)