fn trans_msvc_try<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              func: ValueRef,
                              data: ValueRef,
                              local_ptr: ValueRef,
                              dest: ValueRef,
                              dloc: DebugLoc) -> Block<'blk, 'tcx> {
    let llfn = get_rust_try_fn(bcx.fcx, &mut |bcx| {
        let ccx = bcx.ccx();
        let dloc = DebugLoc::None;

        SetPersonalityFn(bcx, bcx.fcx.eh_personality());

        let normal = bcx.fcx.new_block("normal");
        let catchswitch = bcx.fcx.new_block("catchswitch");
        let catchpad = bcx.fcx.new_block("catchpad");
        let caught = bcx.fcx.new_block("caught");

        let func = llvm::get_param(bcx.fcx.llfn, 0);
        let data = llvm::get_param(bcx.fcx.llfn, 1);
        let local_ptr = llvm::get_param(bcx.fcx.llfn, 2);

        // We're generating an IR snippet that looks like:
        //
        //   declare i32 @rust_try(%func, %data, %ptr) {
        //      %slot = alloca i64*
        //      invoke %func(%data) to label %normal unwind label %catchswitch
        //
        //   normal:
        //      ret i32 0
        //
        //   catchswitch:
        //      %cs = catchswitch within none [%catchpad] unwind to caller
        //
        //   catchpad:
        //      %tok = catchpad within %cs [%type_descriptor, 0, %slot]
        //      %ptr[0] = %slot[0]
        //      %ptr[1] = %slot[1]
        //      catchret from %tok to label %caught
        //
        //   caught:
        //      ret i32 1
        //   }
        //
        // This structure follows the basic usage of throw/try/catch in LLVM.
        // For example, compile this C++ snippet to see what LLVM generates:
        //
        //      #include <stdint.h>
        //
        //      int bar(void (*foo)(void), uint64_t *ret) {
        //          try {
        //              foo();
        //              return 0;
        //          } catch(uint64_t a[2]) {
        //              ret[0] = a[0];
        //              ret[1] = a[1];
        //              return 1;
        //          }
        //      }
        //
        // More information can be found in libstd's seh.rs implementation.
        let i64p = Type::i64(ccx).ptr_to();
        let slot = Alloca(bcx, i64p, "slot");
        Invoke(bcx, func, &[data], normal.llbb, catchswitch.llbb, dloc);

        Ret(normal, C_i32(ccx, 0), dloc);

        let cs = CatchSwitch(catchswitch, None, None, 1);
        AddHandler(catchswitch, cs, catchpad.llbb);

        let tcx = ccx.tcx();
        let tydesc = match tcx.lang_items.msvc_try_filter() {
            Some(did) => ::consts::get_static(ccx, did),
            None => bug!("msvc_try_filter not defined"),
        };
        let tok = CatchPad(catchpad, cs, &[tydesc, C_i32(ccx, 0), slot]);
        let addr = Load(catchpad, slot);
        let arg1 = Load(catchpad, addr);
        let val1 = C_i32(ccx, 1);
        let arg2 = Load(catchpad, InBoundsGEP(catchpad, addr, &[val1]));
        let local_ptr = BitCast(catchpad, local_ptr, i64p);
        Store(catchpad, arg1, local_ptr);
        Store(catchpad, arg2, InBoundsGEP(catchpad, local_ptr, &[val1]));
        CatchRet(catchpad, tok, caught.llbb);

        Ret(caught, C_i32(ccx, 1), dloc);
    });

    // 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, local_ptr], dloc);
    Store(bcx, ret, dest);
    return bcx
}
// MSVC's definition of the `rust_try` function.
//
// This implementation uses the new exception handling instructions in LLVM
// which have support in LLVM for SEH on MSVC targets. Although these
// instructions are meant to work for all targets, as of the time of this
// writing, however, LLVM does not recommend the usage of these new instructions
// as the old ones are still more optimized.
MSVC's definition of the `rust_try` function.
This implementation uses the new exception handling instructions in LLVM
which have support in LLVM for SEH on MSVC targets. Although these
instructions are meant to work for all targets, as of the time of this
writing, however, LLVM does not recommend the usage of these new instructions
as the old ones are still more optimized.
MSVC ' s definition of the ` rust_try ` function . This implementation uses the new exception handling instructions in LLVM which have support in LLVM for SEH on MSVC targets . Although these instructions are meant to work for all targets as of the time of this writing however LLVM does not recommend the usage of these new instructions as the old ones are still more optimized .
fn trans_msvc_try<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              func: ValueRef,
                              data: ValueRef,
                              local_ptr: ValueRef,
                              dest: ValueRef,
                              dloc: DebugLoc) -> Block<'blk, 'tcx> {
    let llfn = get_rust_try_fn(bcx.fcx, &mut |bcx| {
        let ccx = bcx.ccx();
        let dloc = DebugLoc::None;
        SetPersonalityFn(bcx, bcx.fcx.eh_personality());
        let normal = bcx.fcx.new_block("normal");
        let catchswitch = bcx.fcx.new_block("catchswitch");
        let catchpad = bcx.fcx.new_block("catchpad");
        let caught = bcx.fcx.new_block("caught");
        let func = llvm::get_param(bcx.fcx.llfn, 0);
        let data = llvm::get_param(bcx.fcx.llfn, 1);
        let local_ptr = llvm::get_param(bcx.fcx.llfn, 2);
        // We're generating an IR snippet that looks like:
        //
        //   declare i32 @rust_try(%func, %data, %ptr) {
        //      %slot = alloca i64*
        //      invoke %func(%data) to label %normal unwind label %catchswitch
        //
        //   normal:
        //      ret i32 0
        //
        //   catchswitch:
        //      %cs = catchswitch within none [%catchpad] unwind to caller
        //
        //   catchpad:
        //      %tok = catchpad within %cs [%type_descriptor, 0, %slot]
        //      %ptr[0] = %slot[0]
        //      %ptr[1] = %slot[1]
        //      catchret from %tok to label %caught
        //
        //   caught:
        //      ret i32 1
        //   }
        //
        // This structure follows the basic usage of throw/try/catch in LLVM.
        // For example, compile this C++ snippet to see what LLVM generates:
        //
        //      #include <stdint.h>
        //
        //      int bar(void (*foo)(void), uint64_t *ret) {
        //          try {
        //              foo();
        //              return 0;
        //          } catch(uint64_t a[2]) {
        //              ret[0] = a[0];
        //              ret[1] = a[1];
        //              return 1;
        //          }
        //      }
        //
        // More information can be found in libstd's seh.rs implementation.
        let i64p = Type::i64(ccx).ptr_to();
        let slot = Alloca(bcx, i64p, "slot");
        Invoke(bcx, func, &[data], normal.llbb, catchswitch.llbb, dloc);
        Ret(normal, C_i32(ccx, 0), dloc);
        let cs = CatchSwitch(catchswitch, None, None, 1);
        AddHandler(catchswitch, cs, catchpad.llbb);
        let tcx = ccx.tcx();
        let tydesc = match tcx.lang_items.msvc_try_filter() {
            Some(did) => ::consts::get_static(ccx, did),
            None => bug!("msvc_try_filter not defined"),
        };
        let tok = CatchPad(catchpad, cs, &[tydesc, C_i32(ccx, 0), slot]);
        let addr = Load(catchpad, slot);
        let arg1 = Load(catchpad, addr);
        let val1 = C_i32(ccx, 1);
        let arg2 = Load(catchpad, InBoundsGEP(catchpad, addr, &[val1]));
        let local_ptr = BitCast(catchpad, local_ptr, i64p);
        Store(catchpad, arg1, local_ptr);
        Store(catchpad, arg2, InBoundsGEP(catchpad, local_ptr, &[val1]));
        CatchRet(catchpad, tok, caught.llbb);
        Ret(caught, C_i32(ccx, 1), dloc);
    });
    // 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, local_ptr], dloc);
    Store(bcx, ret, dest);
    return bcx
}
fn trans_msvc_try < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > , func : ValueRef , data : ValueRef , local_ptr : ValueRef , dest : ValueRef , dloc : DebugLoc ) -> Block < ' blk , ' tcx > { let llfn = get_rust_try_fn ( bcx . fcx , & mut | bcx | { let ccx = bcx . ccx ( ) ; let dloc = DebugLoc :: None ; SetPersonalityFn ( bcx , bcx . fcx . eh_personality ( ) ) ; let normal = bcx . fcx . new_block ( " " ) ; let catchswitch = bcx . fcx . new_block ( " " ) ; let catchpad = bcx . fcx . new_block ( " " ) ; let caught = bcx . fcx . new_block ( " " ) ; let func = llvm :: get_param ( bcx . fcx . llfn , 0 ) ; let data = llvm :: get_param ( bcx . fcx . llfn , 1 ) ; let local_ptr = llvm :: get_param ( bcx . fcx . llfn , 2 ) ; // We're generating an IR snippet that looks like: // //   declare i32 @rust_try(%func, %data, %ptr) { //      %slot = alloca i64* //      invoke %func(%data) to label %normal unwind label %catchswitch // //   normal: //      ret i32 0 // //   catchswitch: //      %cs = catchswitch within none [%catchpad] unwind to caller // //   catchpad: //      %tok = catchpad within %cs [%type_descriptor, 0, %slot] //      %ptr[0] = %slot[0] //      %ptr[1] = %slot[1] //      catchret from %tok to label %caught // //   caught: //      ret i32 1 //   } // // This structure follows the basic usage of throw/try/catch in LLVM. // For example, compile this C++ snippet to see what LLVM generates: // //      #include <stdint.h> // //      int bar(void (*foo)(void), uint64_t *ret) { //          try { //              foo(); //              return 0; //          } catch(uint64_t a[2]) { //              ret[0] = a[0]; //              ret[1] = a[1]; //              return 1; //          } //      } // // More information can be found in libstd's seh.rs implementation. let i64p = Type :: i64 ( ccx ) . ptr_to ( ) ; let slot = Alloca ( bcx , i64p , " " ) ; Invoke ( bcx , func , & [ data ] , normal . llbb , catchswitch . llbb , dloc ) ; Ret ( normal , C_i32 ( ccx , 0 ) , dloc ) ; let cs = CatchSwitch ( catchswitch , None , None , 1 ) ; AddHandler ( catchswitch , cs , catchpad . llbb ) ; let tcx = ccx . tcx ( ) ; let tydesc = match tcx . lang_items . msvc_try_filter ( ) { Some ( did ) => :: consts :: get_static ( ccx , did ) , None => bug ! ( " " ) , } ; let tok = CatchPad ( catchpad , cs , & [ tydesc , C_i32 ( ccx , 0 ) , slot ] ) ; let addr = Load ( catchpad , slot ) ; let arg1 = Load ( catchpad , addr ) ; let val1 = C_i32 ( ccx , 1 ) ; let arg2 = Load ( catchpad , InBoundsGEP ( catchpad , addr , & [ val1 ] ) ) ; let local_ptr = BitCast ( catchpad , local_ptr , i64p ) ; Store ( catchpad , arg1 , local_ptr ) ; Store ( catchpad , arg2 , InBoundsGEP ( catchpad , local_ptr , & [ val1 ] ) ) ; CatchRet ( catchpad , tok , caught . llbb ) ; Ret ( caught , C_i32 ( ccx , 1 ) , dloc ) ; } ) ; // 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 , local_ptr ] , dloc ) ; Store ( bcx , ret , dest ) ; return bcx }
MSVC's definition of the `rust_try` function.
MSVC ' s definition of the ` rust_try ` function .
bcx
Block<'blk, 'tcx>
func
ValueRef
data
ValueRef
local_ptr
ValueRef
dest
ValueRef
dloc
DebugLoc
bcx
Block<'blk, 'tcx>
func
ValueRef
data
ValueRef
local_ptr
ValueRef
dest
ValueRef
dloc
DebugLoc