// Definition of the standard "try" function for Rust using the GNU-like model
// of exceptions (e.g. the normal semantics of LLVM's landingpad and invoke
// instructions).
//
// This translation is a little surprising because
// we always call a shim function instead of inlining the call to `invoke`
// manually here. This is done because in LLVM we're only allowed to have one
// personality per function definition. The call to the `try` intrinsic is
// being inlined into the function calling it, and that function may already
// have other personality functions in play. By calling a shim we're
// guaranteed that our shim will have the right personality function.
//
Definition of the standard "try" function for Rust using the GNU-like model
of exceptions .

This translation is a little surprising because
we always call a shim function instead of inlining the call to `invoke`
manually here. This is done because in LLVM we're only allowed to have one
personality per function definition. The call to the `try` intrinsic is
being inlined into the function calling it, and that function may already
have other personality functions in play. By calling a shim we're
guaranteed that our shim will have the right personality function.
Definition of the standard " try " function for Rust using the GNU - like model of exceptions . This translation is a little surprising because we always call a shim function instead of inlining the call to ` invoke ` manually here . This is done because in LLVM we ' re only allowed to have one personality per function definition . The call to the ` try ` intrinsic is being inlined into the function calling it and that function may already have other personality functions in play . By calling a shim we ' re guaranteed that our shim will have the right personality function .
fn trans_gnu_try<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                             func: ValueRef,
                             data: ValueRef,
                             dest: ValueRef,
                             dloc: DebugLoc) -> Block<'blk, 'tcx> {
    let llfn = get_rust_try_fn(bcx.fcx, &mut |try_fn_ty, output| {
        let ccx = bcx.ccx();
        let dloc = DebugLoc::None;
        // Translates the shims described above:
        //
        //   bcx:
        //      invoke %func(%args...) normal %normal unwind %catch
        //
        //   normal:
        //      ret null
        //
        //   catch:
        //      (ptr, _) = landingpad
        //      ret ptr
        let rust_try = declare::define_internal_rust_fn(ccx, "__rust_try", try_fn_ty);
        attributes::emit_uwtable(rust_try, true);
        let catch_pers = match bcx.tcx().lang_items.eh_personality_catch() {
            Some(did) => callee::trans_fn_ref(ccx, did, ExprId(0),
                                              bcx.fcx.param_substs).val,
            None => bcx.tcx().sess.bug("eh_personality_catch not defined"),
        };
        let (fcx, block_arena);
        block_arena = TypedArena::new();
        fcx = new_fn_ctxt(ccx, rust_try, ast::DUMMY_NODE_ID, false,
                          output, ccx.tcx().mk_substs(Substs::trans_empty()),
                          None, &block_arena);
        let bcx = init_function(&fcx, true, output);
        let then = bcx.fcx.new_temp_block("then");
        let catch = bcx.fcx.new_temp_block("catch");
        let func = llvm::get_param(rust_try, 0);
        let data = llvm::get_param(rust_try, 1);
        Invoke(bcx, func, &[data], then.llbb, catch.llbb, None, dloc);
        Ret(then, C_null(Type::i8p(ccx)), dloc);
        // Type indicator for the exception being thrown.
        // The first value in this tuple is a pointer to the exception object being thrown.
        // The second value is a "selector" indicating which of the landing pad clauses
        // the exception's type had been matched to.  rust_try ignores the selector.
        let lpad_ty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)],
                                    false);
        let vals = LandingPad(catch, lpad_ty, catch_pers, 1);
        AddClause(catch, vals, C_null(Type::i8p(ccx)));
        let ptr = ExtractValue(catch, vals, 0);
        Ret(catch, ptr, dloc);
        fcx.cleanup();
        return rust_try
    });
    // Note that no invoke is used here because by definition this function
    // can't panic (that's what it's catching).
    let ret = Call(bcx, llfn, &[func, data], None, dloc);
    Store(bcx, ret, dest);
    return bcx;
}
fn trans_gnu_try < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > , func : ValueRef , data : ValueRef , dest : ValueRef , dloc : DebugLoc ) -> Block < ' blk , ' tcx > { let llfn = get_rust_try_fn ( bcx . fcx , & mut | try_fn_ty , output | { let ccx = bcx . ccx ( ) ; let dloc = DebugLoc :: None ; // Translates the shims described above: // //   bcx: //      invoke %func(%args...) normal %normal unwind %catch // //   normal: //      ret null // //   catch: //      (ptr, _) = landingpad //      ret ptr let rust_try = declare :: define_internal_rust_fn ( ccx , " " , try_fn_ty ) ; attributes :: emit_uwtable ( rust_try , true ) ; let catch_pers = match bcx . tcx ( ) . lang_items . eh_personality_catch ( ) { Some ( did ) => callee :: trans_fn_ref ( ccx , did , ExprId ( 0 ) , bcx . fcx . param_substs ) . val , None => bcx . tcx ( ) . sess . bug ( " " ) , } ; let ( fcx , block_arena ) ; block_arena = TypedArena :: new ( ) ; fcx = new_fn_ctxt ( ccx , rust_try , ast :: DUMMY_NODE_ID , false , output , ccx . tcx ( ) . mk_substs ( Substs :: trans_empty ( ) ) , None , & block_arena ) ; let bcx = init_function ( & fcx , true , output ) ; let then = bcx . fcx . new_temp_block ( " " ) ; let catch = bcx . fcx . new_temp_block ( " " ) ; let func = llvm :: get_param ( rust_try , 0 ) ; let data = llvm :: get_param ( rust_try , 1 ) ; Invoke ( bcx , func , & [ data ] , then . llbb , catch . llbb , None , dloc ) ; Ret ( then , C_null ( Type :: i8p ( ccx ) ) , dloc ) ; // Type indicator for the exception being thrown. // The first value in this tuple is a pointer to the exception object being thrown. // The second value is a "selector" indicating which of the landing pad clauses // the exception's type had been matched to.  rust_try ignores the selector. let lpad_ty = Type :: struct_ ( ccx , & [ Type :: i8p ( ccx ) , Type :: i32 ( ccx ) ] , false ) ; let vals = LandingPad ( catch , lpad_ty , catch_pers , 1 ) ; AddClause ( catch , vals , C_null ( Type :: i8p ( ccx ) ) ) ; let ptr = ExtractValue ( catch , vals , 0 ) ; Ret ( catch , ptr , dloc ) ; fcx . cleanup ( ) ; return rust_try } ) ; // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). let ret = Call ( bcx , llfn , & [ func , data ] , None , dloc ) ; Store ( bcx , ret , dest ) ; return bcx ; }
Definition of the standard "try" function for Rust using the GNU-like model
of exceptions (e.g.
Definition of the standard " try " function for Rust using the GNU - like model of exceptions ( e . g .
bcx
Block<'blk, 'tcx>
func
ValueRef
data
ValueRef
dest
ValueRef
dloc
DebugLoc