// 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 codegen 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 codegen 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 codegen 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 codegen_gnu_try(
    bx: &Builder<'a, 'll, 'tcx>,
    cx: &CodegenCx<'ll, 'tcx>,
    func: &'ll Value,
    data: &'ll Value,
    local_ptr: &'ll Value,
    dest: &'ll Value,
) {
    let llfn = get_rust_try_fn(cx, &mut |bx| {
        let cx = bx.cx;
        // Codegens the shims described above:
        //
        //   bx:
        //      invoke %func(%args...) normal %normal unwind %catch
        //
        //   normal:
        //      ret 0
        //
        //   catch:
        //      (ptr, _) = landingpad
        //      store ptr, %local_ptr
        //      ret 1
        //
        // Note that the `local_ptr` data passed into the `try` intrinsic is
        // expected to be `*mut *mut u8` for this to actually work, but that's
        // managed by the standard library.
        let then = bx.build_sibling_block("then");
        let catch = bx.build_sibling_block("catch");
        let func = llvm::get_param(bx.llfn(), 0);
        let data = llvm::get_param(bx.llfn(), 1);
        let local_ptr = llvm::get_param(bx.llfn(), 2);
        bx.invoke(func, &[data], then.llbb(), catch.llbb(), None);
        then.ret(C_i32(cx, 0));
        // 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_(cx, &[Type::i8p(cx), Type::i32(cx)],
                                    false);
        let vals = catch.landing_pad(lpad_ty, bx.cx.eh_personality(), 1);
        catch.add_clause(vals, C_null(Type::i8p(cx)));
        let ptr = catch.extract_value(vals, 0);
        let ptr_align = bx.tcx().data_layout.pointer_align;
        catch.store(ptr, catch.bitcast(local_ptr, Type::i8p(cx).ptr_to()), ptr_align);
        catch.ret(C_i32(cx, 1));
    });
    // Note that no invoke is used here because by definition this function
    // can't panic (that's what it's catching).
    let ret = bx.call(llfn, &[func, data, local_ptr], None);
    let i32_align = bx.tcx().data_layout.i32_align;
    bx.store(ret, dest, i32_align);
}
fn codegen_gnu_try ( bx : & Builder < ' a , ' ll , ' tcx > , cx : & CodegenCx < ' ll , ' tcx > , func : & ' ll Value , data : & ' ll Value , local_ptr : & ' ll Value , dest : & ' ll Value , ) { let llfn = get_rust_try_fn ( cx , & mut | bx | { let cx = bx . cx ; // Codegens the shims described above: // //   bx: //      invoke %func(%args...) normal %normal unwind %catch // //   normal: //      ret 0 // //   catch: //      (ptr, _) = landingpad //      store ptr, %local_ptr //      ret 1 // // Note that the `local_ptr` data passed into the `try` intrinsic is // expected to be `*mut *mut u8` for this to actually work, but that's // managed by the standard library. let then = bx . build_sibling_block ( " " ) ; let catch = bx . build_sibling_block ( " " ) ; let func = llvm :: get_param ( bx . llfn ( ) , 0 ) ; let data = llvm :: get_param ( bx . llfn ( ) , 1 ) ; let local_ptr = llvm :: get_param ( bx . llfn ( ) , 2 ) ; bx . invoke ( func , & [ data ] , then . llbb ( ) , catch . llbb ( ) , None ) ; then . ret ( C_i32 ( cx , 0 ) ) ; // 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_ ( cx , & [ Type :: i8p ( cx ) , Type :: i32 ( cx ) ] , false ) ; let vals = catch . landing_pad ( lpad_ty , bx . cx . eh_personality ( ) , 1 ) ; catch . add_clause ( vals , C_null ( Type :: i8p ( cx ) ) ) ; let ptr = catch . extract_value ( vals , 0 ) ; let ptr_align = bx . tcx ( ) . data_layout . pointer_align ; catch . store ( ptr , catch . bitcast ( local_ptr , Type :: i8p ( cx ) . ptr_to ( ) ) , ptr_align ) ; catch . ret ( C_i32 ( cx , 1 ) ) ; } ) ; // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). let ret = bx . call ( llfn , & [ func , data , local_ptr ] , None ) ; let i32_align = bx . tcx ( ) . data_layout . i32_align ; bx . store ( ret , dest , i32_align ) ; }
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 .
bx
&Builder<'a, 'll, 'tcx>
cx
&CodegenCx<'ll, 'tcx>
func
&'ll Value
data
&'ll Value
local_ptr
&'ll Value
dest
&'ll Value