@@ -851,21 +851,21 @@ fn memset_intrinsic(
851
851
852
852
fn try_intrinsic (
853
853
bx : & mut Builder < ' a , ' ll , ' tcx > ,
854
- func : & ' ll Value ,
854
+ try_func : & ' ll Value ,
855
855
data : & ' ll Value ,
856
- local_ptr : & ' ll Value ,
856
+ catch_func : & ' ll Value ,
857
857
dest : & ' ll Value ,
858
858
) {
859
859
if bx. sess ( ) . no_landing_pads ( ) {
860
- bx. call ( func , & [ data] , None ) ;
860
+ bx. call ( try_func , & [ data] , None ) ;
861
861
// Return 0 unconditionally from the intrinsic call;
862
862
// we can never unwind.
863
863
let ret_align = bx. tcx ( ) . data_layout . i32_align . abi ;
864
864
bx. store ( bx. const_i32 ( 0 ) , dest, ret_align) ;
865
865
} else if wants_msvc_seh ( bx. sess ( ) ) {
866
- codegen_msvc_try ( bx, func , data, local_ptr , dest) ;
866
+ codegen_msvc_try ( bx, try_func , data, catch_func , dest) ;
867
867
} else {
868
- codegen_gnu_try ( bx, func , data, local_ptr , dest) ;
868
+ codegen_gnu_try ( bx, try_func , data, catch_func , dest) ;
869
869
}
870
870
}
871
871
@@ -878,9 +878,9 @@ fn try_intrinsic(
878
878
// as the old ones are still more optimized.
879
879
fn codegen_msvc_try (
880
880
bx : & mut Builder < ' a , ' ll , ' tcx > ,
881
- func : & ' ll Value ,
881
+ try_func : & ' ll Value ,
882
882
data : & ' ll Value ,
883
- local_ptr : & ' ll Value ,
883
+ catch_func : & ' ll Value ,
884
884
dest : & ' ll Value ,
885
885
) {
886
886
let llfn = get_rust_try_fn ( bx, & mut |mut bx| {
@@ -892,15 +892,15 @@ fn codegen_msvc_try(
892
892
let mut catchpad = bx. build_sibling_block ( "catchpad" ) ;
893
893
let mut caught = bx. build_sibling_block ( "caught" ) ;
894
894
895
- let func = llvm:: get_param ( bx. llfn ( ) , 0 ) ;
895
+ let try_func = llvm:: get_param ( bx. llfn ( ) , 0 ) ;
896
896
let data = llvm:: get_param ( bx. llfn ( ) , 1 ) ;
897
- let local_ptr = llvm:: get_param ( bx. llfn ( ) , 2 ) ;
897
+ let catch_func = llvm:: get_param ( bx. llfn ( ) , 2 ) ;
898
898
899
899
// We're generating an IR snippet that looks like:
900
900
//
901
- // declare i32 @rust_try(%func , %data, %ptr ) {
902
- // %slot = alloca [2 x i64]
903
- // invoke %func (%data) to label %normal unwind label %catchswitch
901
+ // declare i32 @rust_try(%try_func , %data, %catch_func ) {
902
+ // %slot = alloca u8*
903
+ // invoke %try_func (%data) to label %normal unwind label %catchswitch
904
904
//
905
905
// normal:
906
906
// ret i32 0
@@ -928,26 +928,26 @@ fn codegen_msvc_try(
928
928
// ~rust_panic();
929
929
//
930
930
// uint64_t x[2];
931
- // }
931
+ // };
932
932
//
933
- // int bar(void (*foo)(void), uint64_t *ret) {
933
+ // int __rust_try(
934
+ // void (*try_func)(void*),
935
+ // void *data,
936
+ // void (*catch_func)(void*, void*) noexcept
937
+ // ) {
934
938
// try {
935
- // foo( );
939
+ // try_func(data );
936
940
// return 0;
937
941
// } catch(rust_panic& a) {
938
- // ret[0] = a.x[0];
939
- // ret[1] = a.x[1];
940
- // a.x[0] = 0;
942
+ // catch_func(data, &a);
941
943
// return 1;
942
944
// }
943
945
// }
944
946
//
945
947
// More information can be found in libstd's seh.rs implementation.
946
- let i64_2 = bx. type_array ( bx. type_i64 ( ) , 2 ) ;
947
- let i64_2_ptr = bx. type_ptr_to ( i64_2) ;
948
948
let ptr_align = bx. tcx ( ) . data_layout . pointer_align . abi ;
949
- let slot = bx. alloca ( i64_2_ptr , ptr_align) ;
950
- bx. invoke ( func , & [ data] , normal. llbb ( ) , catchswitch. llbb ( ) , None ) ;
949
+ let slot = bx. alloca ( bx . type_i8p ( ) , ptr_align) ;
950
+ bx. invoke ( try_func , & [ data] , normal. llbb ( ) , catchswitch. llbb ( ) , None ) ;
951
951
952
952
normal. ret ( bx. const_i32 ( 0 ) ) ;
953
953
@@ -987,17 +987,8 @@ fn codegen_msvc_try(
987
987
// Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang
988
988
let flags = bx. const_i32 ( 8 ) ;
989
989
let funclet = catchpad. catch_pad ( cs, & [ tydesc, flags, slot] ) ;
990
- let i64_align = bx. tcx ( ) . data_layout . i64_align . abi ;
991
- let payload_ptr = catchpad. load ( slot, ptr_align) ;
992
- let payload = catchpad. load ( payload_ptr, i64_align) ;
993
- let local_ptr = catchpad. bitcast ( local_ptr, bx. type_ptr_to ( i64_2) ) ;
994
- catchpad. store ( payload, local_ptr, i64_align) ;
995
-
996
- // Clear the first word of the exception so avoid double-dropping it.
997
- // This will be read by the destructor which is implicitly called at the
998
- // end of the catch block by the runtime.
999
- let payload_0_ptr = catchpad. inbounds_gep ( payload_ptr, & [ bx. const_i32 ( 0 ) , bx. const_i32 ( 0 ) ] ) ;
1000
- catchpad. store ( bx. const_u64 ( 0 ) , payload_0_ptr, i64_align) ;
990
+ let ptr = catchpad. load ( slot, ptr_align) ;
991
+ catchpad. call ( catch_func, & [ data, ptr] , Some ( & funclet) ) ;
1001
992
1002
993
catchpad. catch_ret ( & funclet, caught. llbb ( ) ) ;
1003
994
@@ -1006,7 +997,7 @@ fn codegen_msvc_try(
1006
997
1007
998
// Note that no invoke is used here because by definition this function
1008
999
// can't panic (that's what it's catching).
1009
- let ret = bx. call ( llfn, & [ func , data, local_ptr ] , None ) ;
1000
+ let ret = bx. call ( llfn, & [ try_func , data, catch_func ] , None ) ;
1010
1001
let i32_align = bx. tcx ( ) . data_layout . i32_align . abi ;
1011
1002
bx. store ( ret, dest, i32_align) ;
1012
1003
}
@@ -1024,38 +1015,34 @@ fn codegen_msvc_try(
1024
1015
// the right personality function.
1025
1016
fn codegen_gnu_try (
1026
1017
bx : & mut Builder < ' a , ' ll , ' tcx > ,
1027
- func : & ' ll Value ,
1018
+ try_func : & ' ll Value ,
1028
1019
data : & ' ll Value ,
1029
- local_ptr : & ' ll Value ,
1020
+ catch_func : & ' ll Value ,
1030
1021
dest : & ' ll Value ,
1031
1022
) {
1032
1023
let llfn = get_rust_try_fn ( bx, & mut |mut bx| {
1033
1024
// Codegens the shims described above:
1034
1025
//
1035
1026
// bx:
1036
- // invoke %func(%args... ) normal %normal unwind %catch
1027
+ // invoke %func(%data ) normal %normal unwind %catch
1037
1028
//
1038
1029
// normal:
1039
1030
// ret 0
1040
1031
//
1041
1032
// catch:
1042
- // (ptr, _) = landingpad
1043
- // store ptr , %local_ptr
1033
+ // (% ptr, _) = landingpad
1034
+ // call %catch_func(%data , %ptr)
1044
1035
// ret 1
1045
- //
1046
- // Note that the `local_ptr` data passed into the `try` intrinsic is
1047
- // expected to be `*mut *mut u8` for this to actually work, but that's
1048
- // managed by the standard library.
1049
1036
1050
1037
bx. sideeffect ( ) ;
1051
1038
1052
1039
let mut then = bx. build_sibling_block ( "then" ) ;
1053
1040
let mut catch = bx. build_sibling_block ( "catch" ) ;
1054
1041
1055
- let func = llvm:: get_param ( bx. llfn ( ) , 0 ) ;
1042
+ let try_func = llvm:: get_param ( bx. llfn ( ) , 0 ) ;
1056
1043
let data = llvm:: get_param ( bx. llfn ( ) , 1 ) ;
1057
- let local_ptr = llvm:: get_param ( bx. llfn ( ) , 2 ) ;
1058
- bx. invoke ( func , & [ data] , then. llbb ( ) , catch. llbb ( ) , None ) ;
1044
+ let catch_func = llvm:: get_param ( bx. llfn ( ) , 2 ) ;
1045
+ bx. invoke ( try_func , & [ data] , then. llbb ( ) , catch. llbb ( ) , None ) ;
1059
1046
then. ret ( bx. const_i32 ( 0 ) ) ;
1060
1047
1061
1048
// Type indicator for the exception being thrown.
@@ -1075,15 +1062,13 @@ fn codegen_gnu_try(
1075
1062
} ;
1076
1063
catch. add_clause ( vals, tydesc) ;
1077
1064
let ptr = catch. extract_value ( vals, 0 ) ;
1078
- let ptr_align = bx. tcx ( ) . data_layout . pointer_align . abi ;
1079
- let bitcast = catch. bitcast ( local_ptr, bx. type_ptr_to ( bx. type_i8p ( ) ) ) ;
1080
- catch. store ( ptr, bitcast, ptr_align) ;
1065
+ catch. call ( catch_func, & [ data, ptr] , None ) ;
1081
1066
catch. ret ( bx. const_i32 ( 1 ) ) ;
1082
1067
} ) ;
1083
1068
1084
1069
// Note that no invoke is used here because by definition this function
1085
1070
// can't panic (that's what it's catching).
1086
- let ret = bx. call ( llfn, & [ func , data, local_ptr ] , None ) ;
1071
+ let ret = bx. call ( llfn, & [ try_func , data, catch_func ] , None ) ;
1087
1072
let i32_align = bx. tcx ( ) . data_layout . i32_align . abi ;
1088
1073
bx. store ( ret, dest, i32_align) ;
1089
1074
}
@@ -1130,15 +1115,22 @@ fn get_rust_try_fn<'ll, 'tcx>(
1130
1115
// Define the type up front for the signature of the rust_try function.
1131
1116
let tcx = cx. tcx ;
1132
1117
let i8p = tcx. mk_mut_ptr ( tcx. types . i8 ) ;
1133
- let fn_ty = tcx. mk_fn_ptr ( ty:: Binder :: bind ( tcx. mk_fn_sig (
1118
+ let try_fn_ty = tcx. mk_fn_ptr ( ty:: Binder :: bind ( tcx. mk_fn_sig (
1134
1119
iter:: once ( i8p) ,
1135
1120
tcx. mk_unit ( ) ,
1136
1121
false ,
1137
1122
hir:: Unsafety :: Unsafe ,
1138
1123
Abi :: Rust ,
1139
1124
) ) ) ;
1125
+ let catch_fn_ty = tcx. mk_fn_ptr ( ty:: Binder :: bind ( tcx. mk_fn_sig (
1126
+ [ i8p, i8p] . iter ( ) . cloned ( ) ,
1127
+ tcx. mk_unit ( ) ,
1128
+ false ,
1129
+ hir:: Unsafety :: Unsafe ,
1130
+ Abi :: Rust ,
1131
+ ) ) ) ;
1140
1132
let output = tcx. types . i32 ;
1141
- let rust_try = gen_fn ( cx, "__rust_try" , vec ! [ fn_ty , i8p, i8p ] , output, codegen) ;
1133
+ let rust_try = gen_fn ( cx, "__rust_try" , vec ! [ try_fn_ty , i8p, catch_fn_ty ] , output, codegen) ;
1142
1134
cx. rust_try_fn . set ( Some ( rust_try) ) ;
1143
1135
rust_try
1144
1136
}
0 commit comments