1
Fork 0

[eddyb/rebase cleanup] abstracted Funclet

This commit is contained in:
Eduard-Mihai Burtescu 2018-11-13 12:51:42 +02:00
parent 566fa4d003
commit 35b40f51fb
9 changed files with 59 additions and 86 deletions

View file

@ -9,10 +9,10 @@
// except according to those terms. // except according to those terms.
use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect}; use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
use llvm::{self, False, OperandBundleDef, BasicBlock}; use llvm::{self, False, BasicBlock};
use common;
use rustc_codegen_utils::common::{IntPredicate, TypeKind, RealPredicate}; use rustc_codegen_utils::common::{IntPredicate, TypeKind, RealPredicate};
use rustc_codegen_utils; use rustc_codegen_utils;
use common::Funclet;
use context::CodegenCx; use context::CodegenCx;
use type_::Type; use type_::Type;
use type_of::LayoutLlvmExt; use type_of::LayoutLlvmExt;
@ -66,6 +66,7 @@ impl BackendTypes for Builder<'_, 'll, 'tcx> {
type BasicBlock = <CodegenCx<'ll, 'tcx> as BackendTypes>::BasicBlock; type BasicBlock = <CodegenCx<'ll, 'tcx> as BackendTypes>::BasicBlock;
type Type = <CodegenCx<'ll, 'tcx> as BackendTypes>::Type; type Type = <CodegenCx<'ll, 'tcx> as BackendTypes>::Type;
type Context = <CodegenCx<'ll, 'tcx> as BackendTypes>::Context; type Context = <CodegenCx<'ll, 'tcx> as BackendTypes>::Context;
type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet;
type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope; type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope;
} }
@ -218,12 +219,14 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
} }
fn invoke(&self, fn invoke(
llfn: &'ll Value, &self,
args: &[&'ll Value], llfn: &'ll Value,
then: &'ll BasicBlock, args: &[&'ll Value],
catch: &'ll BasicBlock, then: &'ll BasicBlock,
funclet: Option<&common::Funclet<&'ll Value>>) -> &'ll Value { catch: &'ll BasicBlock,
funclet: Option<&Funclet<'ll>>,
) -> &'ll Value {
self.count_insn("invoke"); self.count_insn("invoke");
debug!("Invoke {:?} with args ({:?})", debug!("Invoke {:?} with args ({:?})",
@ -232,7 +235,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
let args = self.check_call("invoke", llfn, args); let args = self.check_call("invoke", llfn, args);
let bundle = funclet.map(|funclet| funclet.bundle()); let bundle = funclet.map(|funclet| funclet.bundle());
let bundle = bundle.map(OperandBundleDef::from_generic);
let bundle = bundle.as_ref().map(|b| &*b.raw); let bundle = bundle.as_ref().map(|b| &*b.raw);
unsafe { unsafe {
@ -1123,7 +1125,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn cleanup_pad(&self, fn cleanup_pad(&self,
parent: Option<&'ll Value>, parent: Option<&'ll Value>,
args: &[&'ll Value]) -> &'ll Value { args: &[&'ll Value]) -> Funclet<'ll> {
self.count_insn("cleanuppad"); self.count_insn("cleanuppad");
let name = const_cstr!("cleanuppad"); let name = const_cstr!("cleanuppad");
let ret = unsafe { let ret = unsafe {
@ -1133,23 +1135,23 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
args.as_ptr(), args.as_ptr(),
name.as_ptr()) name.as_ptr())
}; };
ret.expect("LLVM does not have support for cleanuppad") Funclet::new(ret.expect("LLVM does not have support for cleanuppad"))
} }
fn cleanup_ret( fn cleanup_ret(
&self, cleanup: &'ll Value, &self, funclet: &Funclet<'ll>,
unwind: Option<&'ll BasicBlock>, unwind: Option<&'ll BasicBlock>,
) -> &'ll Value { ) -> &'ll Value {
self.count_insn("cleanupret"); self.count_insn("cleanupret");
let ret = unsafe { let ret = unsafe {
llvm::LLVMRustBuildCleanupRet(self.llbuilder, cleanup, unwind) llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind)
}; };
ret.expect("LLVM does not have support for cleanupret") ret.expect("LLVM does not have support for cleanupret")
} }
fn catch_pad(&self, fn catch_pad(&self,
parent: &'ll Value, parent: &'ll Value,
args: &[&'ll Value]) -> &'ll Value { args: &[&'ll Value]) -> Funclet<'ll> {
self.count_insn("catchpad"); self.count_insn("catchpad");
let name = const_cstr!("catchpad"); let name = const_cstr!("catchpad");
let ret = unsafe { let ret = unsafe {
@ -1157,13 +1159,13 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
args.len() as c_uint, args.as_ptr(), args.len() as c_uint, args.as_ptr(),
name.as_ptr()) name.as_ptr())
}; };
ret.expect("LLVM does not have support for catchpad") Funclet::new(ret.expect("LLVM does not have support for catchpad"))
} }
fn catch_ret(&self, pad: &'ll Value, unwind: &'ll BasicBlock) -> &'ll Value { fn catch_ret(&self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value {
self.count_insn("catchret"); self.count_insn("catchret");
let ret = unsafe { let ret = unsafe {
llvm::LLVMRustBuildCatchRet(self.llbuilder, pad, unwind) llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind)
}; };
ret.expect("LLVM does not have support for catchret") ret.expect("LLVM does not have support for catchret")
} }
@ -1356,8 +1358,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None); self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None);
} }
fn call(&self, llfn: &'ll Value, args: &[&'ll Value], fn call(
funclet: Option<&common::Funclet<&'ll Value>>) -> &'ll Value { &self,
llfn: &'ll Value,
args: &[&'ll Value],
funclet: Option<&Funclet<'ll>>,
) -> &'ll Value {
self.count_insn("call"); self.count_insn("call");
debug!("Call {:?} with args ({:?})", debug!("Call {:?} with args ({:?})",
@ -1366,7 +1372,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
let args = self.check_call("call", llfn, args); let args = self.check_call("call", llfn, args);
let bundle = funclet.map(|funclet| funclet.bundle()); let bundle = funclet.map(|funclet| funclet.bundle());
let bundle = bundle.map(OperandBundleDef::from_generic);
let bundle = bundle.as_ref().map(|b| &*b.raw); let bundle = bundle.as_ref().map(|b| &*b.raw);
unsafe { unsafe {

View file

@ -12,7 +12,7 @@
//! Code that is useful in various codegen modules. //! Code that is useful in various codegen modules.
use llvm::{self, True, False, Bool, BasicBlock}; use llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef};
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::middle::lang_items::LangItem; use rustc::middle::lang_items::LangItem;
use abi; use abi;
@ -23,7 +23,7 @@ use type_of::LayoutLlvmExt;
use value::Value; use value::Value;
use interfaces::*; use interfaces::*;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{Ty, TyCtxt};
use rustc::ty::layout::{HasDataLayout, LayoutOf, self, TyLayout, Size}; use rustc::ty::layout::{HasDataLayout, LayoutOf, self, TyLayout, Size};
use rustc::mir::interpret::{Scalar, AllocType, Allocation}; use rustc::mir::interpret::{Scalar, AllocType, Allocation};
use rustc::hir; use rustc::hir;
@ -35,36 +35,10 @@ use libc::{c_uint, c_char};
use syntax::symbol::LocalInternedString; use syntax::symbol::LocalInternedString;
use syntax::ast::Mutability; use syntax::ast::Mutability;
use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::Span;
pub use context::CodegenCx; pub use context::CodegenCx;
pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
ty.needs_drop(tcx, ty::ParamEnv::reveal_all())
}
pub fn type_is_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::reveal_all())
}
pub fn type_is_freeze<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
ty.is_freeze(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP)
}
pub struct OperandBundleDef<'a, V> {
pub name: &'a str,
pub val: V
}
impl<'a, V> OperandBundleDef<'a, V> {
pub fn new(name: &'a str, val: V) -> Self {
OperandBundleDef {
name,
val
}
}
}
/* /*
* A note on nomenclature of linking: "extern", "foreign", and "upcall". * A note on nomenclature of linking: "extern", "foreign", and "upcall".
* *
@ -105,24 +79,24 @@ impl<'a, V> OperandBundleDef<'a, V> {
/// When inside of a landing pad, each function call in LLVM IR needs to be /// When inside of a landing pad, each function call in LLVM IR needs to be
/// annotated with which landing pad it's a part of. This is accomplished via /// annotated with which landing pad it's a part of. This is accomplished via
/// the `OperandBundleDef` value created for MSVC landing pads. /// the `OperandBundleDef` value created for MSVC landing pads.
pub struct Funclet<'a, V> { pub struct Funclet<'ll> {
cleanuppad: V, cleanuppad: &'ll Value,
operand: OperandBundleDef<'a, V>, operand: OperandBundleDef<'ll>,
} }
impl<'a, V: CodegenObject> Funclet<'a, V> { impl Funclet<'ll> {
pub fn new(cleanuppad: V) -> Self { pub fn new(cleanuppad: &'ll Value) -> Self {
Funclet { Funclet {
cleanuppad, cleanuppad,
operand: OperandBundleDef::new("funclet", cleanuppad), operand: OperandBundleDef::new("funclet", &[cleanuppad]),
} }
} }
pub fn cleanuppad(&self) -> V { pub fn cleanuppad(&self) -> &'ll Value {
self.cleanuppad self.cleanuppad
} }
pub fn bundle(&self) -> &OperandBundleDef<'a, V> { pub fn bundle(&self) -> &OperandBundleDef<'ll> {
&self.operand &self.operand
} }
} }
@ -132,6 +106,7 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> {
type BasicBlock = &'ll BasicBlock; type BasicBlock = &'ll BasicBlock;
type Type = &'ll Type; type Type = &'ll Type;
type Context = &'ll llvm::Context; type Context = &'ll llvm::Context;
type Funclet = Funclet<'ll>;
type DIScope = &'ll llvm::debuginfo::DIScope; type DIScope = &'ll llvm::debuginfo::DIScope;
} }

View file

@ -28,6 +28,7 @@ pub trait BackendTypes {
type BasicBlock: Copy; type BasicBlock: Copy;
type Type: CodegenObject; type Type: CodegenObject;
type Context; type Context;
type Funclet;
type DIScope: Copy; type DIScope: Copy;
} }

View file

@ -15,7 +15,6 @@ use super::intrinsic::IntrinsicCallMethods;
use super::type_::ArgTypeMethods; use super::type_::ArgTypeMethods;
use super::HasCodegen; use super::HasCodegen;
use builder::MemFlags; use builder::MemFlags;
use common::*;
use libc::c_char; use libc::c_char;
use mir::operand::OperandRef; use mir::operand::OperandRef;
use mir::place::PlaceRef; use mir::place::PlaceRef;
@ -58,7 +57,7 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
args: &[Self::Value], args: &[Self::Value],
then: Self::BasicBlock, then: Self::BasicBlock,
catch: Self::BasicBlock, catch: Self::BasicBlock,
funclet: Option<&Funclet<Self::Value>>, funclet: Option<&Self::Funclet>,
) -> Self::Value; ) -> Self::Value;
fn unreachable(&self); fn unreachable(&self);
fn add(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn add(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
@ -213,10 +212,10 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
fn add_clause(&self, landing_pad: Self::Value, clause: Self::Value); fn add_clause(&self, landing_pad: Self::Value, clause: Self::Value);
fn set_cleanup(&self, landing_pad: Self::Value); fn set_cleanup(&self, landing_pad: Self::Value);
fn resume(&self, exn: Self::Value) -> Self::Value; fn resume(&self, exn: Self::Value) -> Self::Value;
fn cleanup_pad(&self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Value; fn cleanup_pad(&self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet;
fn cleanup_ret(&self, cleanup: Self::Value, unwind: Option<Self::BasicBlock>) -> Self::Value; fn cleanup_ret(&self, funclet: &Self::Funclet, unwind: Option<Self::BasicBlock>) -> Self::Value;
fn catch_pad(&self, parent: Self::Value, args: &[Self::Value]) -> Self::Value; fn catch_pad(&self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet;
fn catch_ret(&self, pad: Self::Value, unwind: Self::BasicBlock) -> Self::Value; fn catch_ret(&self, funclet: &Self::Funclet, unwind: Self::BasicBlock) -> Self::Value;
fn catch_switch( fn catch_switch(
&self, &self,
parent: Option<Self::Value>, parent: Option<Self::Value>,
@ -276,7 +275,7 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
&self, &self,
llfn: Self::Value, llfn: Self::Value,
args: &[Self::Value], args: &[Self::Value],
funclet: Option<&Funclet<Self::Value>>, funclet: Option<&Self::Funclet>,
) -> Self::Value; ) -> Self::Value;
fn zext(&self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn zext(&self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;

View file

@ -72,6 +72,7 @@ pub trait HasCodegen<'tcx>: Backend<'tcx> {
BasicBlock = Self::BasicBlock, BasicBlock = Self::BasicBlock,
Type = Self::Type, Type = Self::Type,
Context = Self::Context, Context = Self::Context,
Funclet = Self::Funclet,
DIScope = Self::DIScope, DIScope = Self::DIScope,
>; >;
} }

View file

@ -894,7 +894,7 @@ fn codegen_msvc_try(
Some(did) => cx.get_static(did), Some(did) => cx.get_static(did),
None => bug!("msvc_try_filter not defined"), None => bug!("msvc_try_filter not defined"),
}; };
let tok = catchpad.catch_pad(cs, &[tydesc, cx.const_i32(0), slot]); let funclet = catchpad.catch_pad(cs, &[tydesc, cx.const_i32(0), slot]);
let addr = catchpad.load(slot, ptr_align); let addr = catchpad.load(slot, ptr_align);
let i64_align = bx.tcx().data_layout.i64_align; let i64_align = bx.tcx().data_layout.i64_align;
@ -904,7 +904,7 @@ fn codegen_msvc_try(
let local_ptr = catchpad.bitcast(local_ptr, i64p); let local_ptr = catchpad.bitcast(local_ptr, i64p);
catchpad.store(arg1, local_ptr, i64_align); catchpad.store(arg1, local_ptr, i64_align);
catchpad.store(arg2, catchpad.inbounds_gep(local_ptr, &[val1]), i64_align); catchpad.store(arg2, catchpad.inbounds_gep(local_ptr, &[val1]), i64_align);
catchpad.catch_ret(tok, caught.llbb()); catchpad.catch_ret(&funclet, caught.llbb());
caught.ret(cx.const_i32(1)); caught.ret(cx.const_i32(1));
}); });

View file

@ -28,7 +28,6 @@ use std::ffi::CStr;
use std::cell::RefCell; use std::cell::RefCell;
use libc::{self, c_uint, c_char, size_t}; use libc::{self, c_uint, c_char, size_t};
use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::small_c_str::SmallCStr;
use common;
pub mod archive_ro; pub mod archive_ro;
pub mod diagnostic; pub mod diagnostic;
@ -272,10 +271,6 @@ impl OperandBundleDef<'a> {
}; };
OperandBundleDef { raw: def } OperandBundleDef { raw: def }
} }
pub fn from_generic(bundle: &common::OperandBundleDef<'a, &'a Value>) -> Self {
Self::new(bundle.name, &[bundle.val])
}
} }
impl Drop for OperandBundleDef<'a> { impl Drop for OperandBundleDef<'a> {

View file

@ -17,7 +17,7 @@ use abi::{Abi, FnType, PassMode};
use rustc_target::abi::call::ArgType; use rustc_target::abi::call::ArgType;
use base; use base;
use builder::MemFlags; use builder::MemFlags;
use common::{self, Funclet}; use common;
use rustc_codegen_utils::common::IntPredicate; use rustc_codegen_utils::common::IntPredicate;
use meth; use meth;
use monomorphize; use monomorphize;
@ -67,7 +67,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
funclet_bb: Option<mir::BasicBlock> funclet_bb: Option<mir::BasicBlock>
) -> impl for<'b> Fn( ) -> impl for<'b> Fn(
&'b FunctionCx<'a, 'tcx, Bx>, &'b FunctionCx<'a, 'tcx, Bx>,
) -> Option<&'b Funclet<'static, Bx::Value>> { ) -> Option<&'b Bx::Funclet> {
move |this| { move |this| {
match funclet_bb { match funclet_bb {
Some(funclet_bb) => this.funclets[funclet_bb].as_ref(), Some(funclet_bb) => this.funclets[funclet_bb].as_ref(),
@ -77,8 +77,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
let funclet = funclet_closure_factory(funclet_bb); let funclet = funclet_closure_factory(funclet_bb);
let cleanup_pad = |this: &Self| funclet(this).map(|lp| lp.cleanuppad());
let lltarget = |this: &mut Self, target: mir::BasicBlock| { let lltarget = |this: &mut Self, target: mir::BasicBlock| {
let lltarget = this.blocks[target]; let lltarget = this.blocks[target];
let target_funclet = this.cleanup_kinds[target].funclet_bb(target); let target_funclet = this.cleanup_kinds[target].funclet_bb(target);
@ -106,7 +104,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
debug!("llblock: creating cleanup trampoline for {:?}", target); debug!("llblock: creating cleanup trampoline for {:?}", target);
let name = &format!("{:?}_cleanup_trampoline_{:?}", bb, target); let name = &format!("{:?}_cleanup_trampoline_{:?}", bb, target);
let trampoline = this.new_block(name); let trampoline = this.new_block(name);
trampoline.cleanup_ret(cleanup_pad(this).unwrap(), Some(lltarget)); trampoline.cleanup_ret(funclet(this).unwrap(), Some(lltarget));
trampoline.llbb() trampoline.llbb()
} else { } else {
lltarget lltarget
@ -119,7 +117,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if is_cleanupret { if is_cleanupret {
// micro-optimization: generate a `ret` rather than a jump // micro-optimization: generate a `ret` rather than a jump
// to a trampoline. // to a trampoline.
bx.cleanup_ret(cleanup_pad(this).unwrap(), Some(lltarget)); bx.cleanup_ret(funclet(this).unwrap(), Some(lltarget));
} else { } else {
bx.br(lltarget); bx.br(lltarget);
} }
@ -175,8 +173,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.set_debug_loc(&bx, terminator.source_info); self.set_debug_loc(&bx, terminator.source_info);
match terminator.kind { match terminator.kind {
mir::TerminatorKind::Resume => { mir::TerminatorKind::Resume => {
if let Some(cleanup_pad) = cleanup_pad(self) { if let Some(funclet) = funclet(self) {
bx.cleanup_ret(cleanup_pad, None); bx.cleanup_ret(funclet, None);
} else { } else {
let slot = self.get_personality_slot(&bx); let slot = self.get_personality_slot(&bx);
let lp0 = bx.load_operand(slot.project_field(&bx, 0)).immediate(); let lp0 = bx.load_operand(slot.project_field(&bx, 0)).immediate();

View file

@ -18,7 +18,6 @@ use rustc::ty::subst::Substs;
use rustc::session::config::DebugInfo; use rustc::session::config::DebugInfo;
use base; use base;
use debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext}; use debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext};
use common::Funclet;
use monomorphize::Instance; use monomorphize::Instance;
use abi::{FnType, PassMode}; use abi::{FnType, PassMode};
use interfaces::*; use interfaces::*;
@ -70,7 +69,7 @@ pub struct FunctionCx<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> {
/// When targeting MSVC, this stores the cleanup info for each funclet /// When targeting MSVC, this stores the cleanup info for each funclet
/// BB. This is initialized as we compute the funclets' head block in RPO. /// BB. This is initialized as we compute the funclets' head block in RPO.
funclets: IndexVec<mir::BasicBlock, Option<Funclet<'static, Bx::Value>>>, funclets: IndexVec<mir::BasicBlock, Option<Bx::Funclet>>,
/// This stores the landing-pad block for a given BB, computed lazily on GNU /// This stores the landing-pad block for a given BB, computed lazily on GNU
/// and eagerly on MSVC. /// and eagerly on MSVC.
@ -372,7 +371,7 @@ fn create_funclets<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>, cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
block_bxs: &IndexVec<mir::BasicBlock, Bx::BasicBlock>) block_bxs: &IndexVec<mir::BasicBlock, Bx::BasicBlock>)
-> (IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>, -> (IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>,
IndexVec<mir::BasicBlock, Option<Funclet<'static, Bx::Value>>>) IndexVec<mir::BasicBlock, Option<Bx::Funclet>>)
{ {
block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| { block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| {
match *cleanup_kind { match *cleanup_kind {
@ -380,7 +379,7 @@ fn create_funclets<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
_ => return (None, None) _ => return (None, None)
} }
let cleanup; let funclet;
let ret_llbb; let ret_llbb;
match mir[bb].terminator.as_ref().map(|t| &t.kind) { match mir[bb].terminator.as_ref().map(|t| &t.kind) {
// This is a basic block that we're aborting the program for, // This is a basic block that we're aborting the program for,
@ -417,18 +416,18 @@ fn create_funclets<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
// represents that this is a catch-all block. // represents that this is a catch-all block.
let null = bx.cx().const_null(bx.cx().type_i8p()); let null = bx.cx().const_null(bx.cx().type_i8p());
let sixty_four = bx.cx().const_i32(64); let sixty_four = bx.cx().const_i32(64);
cleanup = cp_bx.catch_pad(cs, &[null, sixty_four, null]); funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
cp_bx.br(llbb); cp_bx.br(llbb);
} }
_ => { _ => {
let cleanup_bx = bx.build_sibling_block(&format!("funclet_{:?}", bb)); let cleanup_bx = bx.build_sibling_block(&format!("funclet_{:?}", bb));
ret_llbb = cleanup_bx.llbb(); ret_llbb = cleanup_bx.llbb();
cleanup = cleanup_bx.cleanup_pad(None, &[]); funclet = cleanup_bx.cleanup_pad(None, &[]);
cleanup_bx.br(llbb); cleanup_bx.br(llbb);
} }
}; };
(Some(ret_llbb), Some(Funclet::new(cleanup))) (Some(ret_llbb), Some(funclet))
}).unzip() }).unzip()
} }