fn codegen_msvc_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;

        bx.set_personality_fn(bx.cx.eh_personality());

        let normal = bx.build_sibling_block("normal");
        let catchswitch = bx.build_sibling_block("catchswitch");
        let catchpad = bx.build_sibling_block("catchpad");
        let caught = bx.build_sibling_block("caught");

        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);

        // 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(cx).ptr_to();
        let ptr_align = bx.tcx().data_layout.pointer_align;
        let slot = bx.alloca(i64p, "slot", ptr_align);
        bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(),
            None);

        normal.ret(C_i32(cx, 0));

        let cs = catchswitch.catch_switch(None, None, 1);
        catchswitch.add_handler(cs, catchpad.llbb());

        let tcx = cx.tcx;
        let tydesc = match tcx.lang_items().msvc_try_filter() {
            Some(did) => ::consts::get_static(cx, did),
            None => bug!("msvc_try_filter not defined"),
        };
        let tok = catchpad.catch_pad(cs, &[tydesc, C_i32(cx, 0), slot]);
        let addr = catchpad.load(slot, ptr_align);

        let i64_align = bx.tcx().data_layout.i64_align;
        let arg1 = catchpad.load(addr, i64_align);
        let val1 = C_i32(cx, 1);
        let arg2 = catchpad.load(catchpad.inbounds_gep(addr, &[val1]), i64_align);
        let local_ptr = catchpad.bitcast(local_ptr, i64p);
        catchpad.store(arg1, local_ptr, i64_align);
        catchpad.store(arg2, catchpad.inbounds_gep(local_ptr, &[val1]), i64_align);
        catchpad.catch_ret(tok, caught.llbb());

        caught.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);
}
// 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 codegen_msvc_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;
        bx.set_personality_fn(bx.cx.eh_personality());
        let normal = bx.build_sibling_block("normal");
        let catchswitch = bx.build_sibling_block("catchswitch");
        let catchpad = bx.build_sibling_block("catchpad");
        let caught = bx.build_sibling_block("caught");
        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);
        // 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(cx).ptr_to();
        let ptr_align = bx.tcx().data_layout.pointer_align;
        let slot = bx.alloca(i64p, "slot", ptr_align);
        bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(),
            None);
        normal.ret(C_i32(cx, 0));
        let cs = catchswitch.catch_switch(None, None, 1);
        catchswitch.add_handler(cs, catchpad.llbb());
        let tcx = cx.tcx;
        let tydesc = match tcx.lang_items().msvc_try_filter() {
            Some(did) => ::consts::get_static(cx, did),
            None => bug!("msvc_try_filter not defined"),
        };
        let tok = catchpad.catch_pad(cs, &[tydesc, C_i32(cx, 0), slot]);
        let addr = catchpad.load(slot, ptr_align);
        let i64_align = bx.tcx().data_layout.i64_align;
        let arg1 = catchpad.load(addr, i64_align);
        let val1 = C_i32(cx, 1);
        let arg2 = catchpad.load(catchpad.inbounds_gep(addr, &[val1]), i64_align);
        let local_ptr = catchpad.bitcast(local_ptr, i64p);
        catchpad.store(arg1, local_ptr, i64_align);
        catchpad.store(arg2, catchpad.inbounds_gep(local_ptr, &[val1]), i64_align);
        catchpad.catch_ret(tok, caught.llbb());
        caught.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_msvc_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 ; bx . set_personality_fn ( bx . cx . eh_personality ( ) ) ; let normal = bx . build_sibling_block ( " " ) ; let catchswitch = bx . build_sibling_block ( " " ) ; let catchpad = bx . build_sibling_block ( " " ) ; let caught = 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 ) ; // 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 ( cx ) . ptr_to ( ) ; let ptr_align = bx . tcx ( ) . data_layout . pointer_align ; let slot = bx . alloca ( i64p , " " , ptr_align ) ; bx . invoke ( func , & [ data ] , normal . llbb ( ) , catchswitch . llbb ( ) , None ) ; normal . ret ( C_i32 ( cx , 0 ) ) ; let cs = catchswitch . catch_switch ( None , None , 1 ) ; catchswitch . add_handler ( cs , catchpad . llbb ( ) ) ; let tcx = cx . tcx ; let tydesc = match tcx . lang_items ( ) . msvc_try_filter ( ) { Some ( did ) => :: consts :: get_static ( cx , did ) , None => bug ! ( " " ) , } ; let tok = catchpad . catch_pad ( cs , & [ tydesc , C_i32 ( cx , 0 ) , slot ] ) ; let addr = catchpad . load ( slot , ptr_align ) ; let i64_align = bx . tcx ( ) . data_layout . i64_align ; let arg1 = catchpad . load ( addr , i64_align ) ; let val1 = C_i32 ( cx , 1 ) ; let arg2 = catchpad . load ( catchpad . inbounds_gep ( addr , & [ val1 ] ) , i64_align ) ; let local_ptr = catchpad . bitcast ( local_ptr , i64p ) ; catchpad . store ( arg1 , local_ptr , i64_align ) ; catchpad . store ( arg2 , catchpad . inbounds_gep ( local_ptr , & [ val1 ] ) , i64_align ) ; catchpad . catch_ret ( tok , caught . llbb ( ) ) ; caught . 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 ) ; }
MSVC's definition of the `rust_try` function.
MSVC ' s definition of the ` rust_try ` function .
bx
&Builder<'a, 'll, 'tcx>
cx
&CodegenCx<'ll, 'tcx>
func
&'ll Value
data
&'ll Value
local_ptr
&'ll Value
dest
&'ll Value
bx
&Builder<'a, 'll, 'tcx>
cx
&CodegenCx<'ll, 'tcx>
func
&'ll Value
data
&'ll Value
local_ptr
&'ll Value
dest
&'ll Value