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