1 ; RUN: llc < %s | FileCheck %s 2 3 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" 4 target triple = "i686-pc-windows-msvc" 5 6 define void @try_except() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) { 7 entry: 8 %__exception_code = alloca i32, align 4 9 call void (...) @llvm.localescape(i32* %__exception_code) 10 invoke void @f(i32 1) #3 11 to label %invoke.cont unwind label %catch.dispatch 12 13 catch.dispatch: ; preds = %entry 14 %cs1 = catchswitch within none [label %__except.ret] unwind to caller 15 16 __except.ret: ; preds = %catch.dispatch 17 %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)] 18 catchret from %0 to label %__except 19 20 __except: ; preds = %__except.ret 21 call void @f(i32 2) 22 br label %__try.cont 23 24 __try.cont: ; preds = %__except, %invoke.cont 25 call void @f(i32 3) 26 ret void 27 28 invoke.cont: ; preds = %entry 29 br label %__try.cont 30 } 31 32 ; CHECK-LABEL: _try_except: 33 ; Store state #0 34 ; CHECK: movl $0, -[[state:[0-9]+]](%ebp) 35 ; CHECK: movl $1, (%esp) 36 ; CHECK: calll _f 37 ; CHECK: movl $-1, -[[state]](%ebp) 38 ; CHECK: movl $3, (%esp) 39 ; CHECK: calll _f 40 ; CHECK: retl 41 42 ; __except 43 ; CHECK: movl $-1, -[[state]](%ebp) 44 ; CHECK: movl $2, (%esp) 45 ; CHECK: calll _f 46 47 ; CHECK: .section .xdata,"dr" 48 ; CHECK: L__ehtable$try_except: 49 ; CHECK: .long -1 50 ; CHECK: .long _try_except_filter_catchall 51 ; CHECK: .long LBB0_1 52 53 define internal i32 @try_except_filter_catchall() #0 { 54 entry: 55 %0 = call i8* @llvm.frameaddress(i32 1) 56 %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @try_except to i8*), i8* %0) 57 %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @try_except to i8*), i8* %1, i32 0) 58 %__exception_code = bitcast i8* %2 to i32* 59 %3 = getelementptr inbounds i8, i8* %0, i32 -20 60 %4 = bitcast i8* %3 to i8** 61 %5 = load i8*, i8** %4, align 4 62 %6 = bitcast i8* %5 to { i32*, i8* }* 63 %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0 64 %8 = load i32*, i32** %7, align 4 65 %9 = load i32, i32* %8, align 4 66 store i32 %9, i32* %__exception_code, align 4 67 ret i32 1 68 } 69 70 define void @nested_exceptions() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) { 71 entry: 72 %__exception_code = alloca i32, align 4 73 call void (...) @llvm.localescape(i32* %__exception_code) 74 invoke void @crash() #3 75 to label %__try.cont unwind label %catch.dispatch 76 77 catch.dispatch: ; preds = %entry 78 %cs1 = catchswitch within none [label %__except.ret] unwind label %catch.dispatch.11 79 80 __except.ret: ; preds = %catch.dispatch 81 %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] 82 catchret from %0 to label %__try.cont 83 84 __try.cont: ; preds = %entry, %__except.ret 85 invoke void @crash() #3 86 to label %__try.cont.9 unwind label %catch.dispatch.5 87 88 catch.dispatch.5: ; preds = %__try.cont 89 %cs2 = catchswitch within none [label %__except.ret.7] unwind label %catch.dispatch.11 90 91 __except.ret.7: ; preds = %catch.dispatch.5 92 %1 = catchpad within %cs2 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] 93 catchret from %1 to label %__try.cont.9 94 95 __try.cont.9: ; preds = %__try.cont, %__except.ret.7 96 invoke void @crash() #3 97 to label %__try.cont.15 unwind label %catch.dispatch.11 98 99 catch.dispatch.11: ; preds = %catchendblock, %catchendblock.6, %__try.cont.9 100 %cs3 = catchswitch within none [label %__except.ret.13] unwind label %catch.dispatch.17 101 102 __except.ret.13: ; preds = %catch.dispatch.11 103 %2 = catchpad within %cs3 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] 104 catchret from %2 to label %__try.cont.15 105 106 __try.cont.15: ; preds = %__try.cont.9, %__except.ret.13 107 invoke void @crash() #3 108 to label %__try.cont.35 unwind label %catch.dispatch.17 109 110 catch.dispatch.17: ; preds = %catchendblock.12, %__try.cont.15 111 %cs4 = catchswitch within none [label %__except.ret.19] unwind to caller 112 113 __except.ret.19: ; preds = %catch.dispatch.17 114 %3 = catchpad within %cs4 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] 115 catchret from %3 to label %__except.20 116 117 __except.20: ; preds = %__except.ret.19 118 invoke void @crash() #3 119 to label %__try.cont.27 unwind label %catch.dispatch.23 120 121 catch.dispatch.23: ; preds = %__except.20 122 %cs5 = catchswitch within none [label %__except.ret.25] unwind to caller 123 124 __except.ret.25: ; preds = %catch.dispatch.23 125 %4 = catchpad within %cs5 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] 126 catchret from %4 to label %__try.cont.27 127 128 __try.cont.27: ; preds = %__except.20, %__except.ret.25 129 invoke void @crash() #3 130 to label %__try.cont.35 unwind label %catch.dispatch.30 131 132 catch.dispatch.30: ; preds = %__try.cont.27 133 %cs6 = catchswitch within none [label %__except.ret.32] unwind to caller 134 135 __except.ret.32: ; preds = %catch.dispatch.30 136 %5 = catchpad within %cs6 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] 137 catchret from %5 to label %__try.cont.35 138 139 __try.cont.35: ; preds = %__try.cont.15, %__try.cont.27, %__except.ret.32 140 ret void 141 } 142 143 ; This table is equivalent to the one produced by MSVC, even if it isn't in 144 ; quite the same order. 145 146 ; CHECK-LABEL: _nested_exceptions: 147 ; CHECK: L__ehtable$nested_exceptions: 148 ; CHECK: .long -1 149 ; CHECK: .long _nested_exceptions_filter_catchall 150 ; CHECK: .long LBB 151 ; CHECK: .long 0 152 ; CHECK: .long _nested_exceptions_filter_catchall 153 ; CHECK: .long LBB 154 ; CHECK: .long 1 155 ; CHECK: .long _nested_exceptions_filter_catchall 156 ; CHECK: .long LBB 157 ; CHECK: .long 1 158 ; CHECK: .long _nested_exceptions_filter_catchall 159 ; CHECK: .long LBB 160 ; CHECK: .long -1 161 ; CHECK: .long _nested_exceptions_filter_catchall 162 ; CHECK: .long LBB 163 ; CHECK: .long -1 164 ; CHECK: .long _nested_exceptions_filter_catchall 165 ; CHECK: .long LBB 166 167 declare void @crash() #0 168 169 define internal i32 @nested_exceptions_filter_catchall() #0 { 170 entry: 171 %0 = call i8* @llvm.frameaddress(i32 1) 172 %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %0) 173 %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %1, i32 0) 174 %__exception_code3 = bitcast i8* %2 to i32* 175 %3 = getelementptr inbounds i8, i8* %0, i32 -20 176 %4 = bitcast i8* %3 to i8** 177 %5 = load i8*, i8** %4, align 4 178 %6 = bitcast i8* %5 to { i32*, i8* }* 179 %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0 180 %8 = load i32*, i32** %7, align 4 181 %9 = load i32, i32* %8, align 4 182 store i32 %9, i32* %__exception_code3, align 4 183 ret i32 1 184 } 185 186 define void @code_in_catchpad() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) { 187 entry: 188 invoke void @f(i32 1) #3 189 to label %__except unwind label %catch.dispatch 190 191 catch.dispatch: ; preds = %entry 192 %cs1 = catchswitch within none [label %__except.ret] unwind to caller 193 194 __except.ret: ; preds = %catch.dispatch 195 %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)] 196 call void @f(i32 2) [ "funclet"(token %0) ] 197 catchret from %0 to label %__except 198 199 __except: 200 ret void 201 } 202 203 ; CHECK-LABEL: _code_in_catchpad: 204 ; CHECK: # %__except.ret 205 ; CHECK-NEXT: movl -24(%ebp), %esp 206 ; CHECK-NEXT: addl $12, %ebp 207 ; CHECK-NEXT: movl $-1, -16(%ebp) 208 ; CHECK-NEXT: movl $2, (%esp) 209 ; CHECK-NEXT: calll _f 210 211 212 ; Function Attrs: nounwind readnone 213 declare i8* @llvm.frameaddress(i32) #1 214 215 ; Function Attrs: nounwind readnone 216 declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) #1 217 218 ; Function Attrs: nounwind readnone 219 declare i8* @llvm.localrecover(i8*, i8*, i32) #1 220 221 declare void @f(i32) #0 222 223 declare i32 @_except_handler3(...) 224 225 ; Function Attrs: nounwind 226 declare void @llvm.localescape(...) #2 227 228 attributes #0 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 229 attributes #1 = { nounwind readnone } 230 attributes #2 = { nounwind } 231 attributes #3 = { noinline } 232