blob: 224e96f8b8f0bc402d253e3815fd79903ce4742a [file] [log] [blame]
Reid Kleckner94b704c2015-09-09 21:10:03 +00001; 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 i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
7entry:
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
13catch.dispatch: ; preds = %entry
David Majnemer8a1c45d2015-12-12 05:38:55 +000014 %cs1 = catchswitch within none [label %__except.ret] unwind to caller
Reid Kleckner94b704c2015-09-09 21:10:03 +000015
16__except.ret: ; preds = %catch.dispatch
David Majnemer8a1c45d2015-12-12 05:38:55 +000017 %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
18 catchret from %0 to label %__except
Reid Kleckner94b704c2015-09-09 21:10:03 +000019
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
Reid Kleckner94b704c2015-09-09 21:10:03 +000028invoke.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:
David Majnemer081e8fe2015-12-27 06:07:12 +000049; CHECK: .long -1 # ToState
50; CHECK: .long _try_except_filter_catchall # Filter
Reid Kleckner94b704c2015-09-09 21:10:03 +000051; CHECK: .long LBB0_1
52
53define internal i32 @try_except_filter_catchall() #0 {
54entry:
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
70define void @nested_exceptions() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
71entry:
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
77catch.dispatch: ; preds = %entry
David Majnemer8a1c45d2015-12-12 05:38:55 +000078 %cs1 = catchswitch within none [label %__except.ret] unwind label %catch.dispatch.11
Reid Kleckner94b704c2015-09-09 21:10:03 +000079
80__except.ret: ; preds = %catch.dispatch
David Majnemer8a1c45d2015-12-12 05:38:55 +000081 %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
82 catchret from %0 to label %__try.cont
Reid Kleckner94b704c2015-09-09 21:10:03 +000083
84__try.cont: ; preds = %entry, %__except.ret
85 invoke void @crash() #3
86 to label %__try.cont.9 unwind label %catch.dispatch.5
87
88catch.dispatch.5: ; preds = %__try.cont
David Majnemer8a1c45d2015-12-12 05:38:55 +000089 %cs2 = catchswitch within none [label %__except.ret.7] unwind label %catch.dispatch.11
Reid Kleckner94b704c2015-09-09 21:10:03 +000090
91__except.ret.7: ; preds = %catch.dispatch.5
David Majnemer8a1c45d2015-12-12 05:38:55 +000092 %1 = catchpad within %cs2 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
93 catchret from %1 to label %__try.cont.9
Reid Kleckner94b704c2015-09-09 21:10:03 +000094
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
99catch.dispatch.11: ; preds = %catchendblock, %catchendblock.6, %__try.cont.9
David Majnemer8a1c45d2015-12-12 05:38:55 +0000100 %cs3 = catchswitch within none [label %__except.ret.13] unwind label %catch.dispatch.17
Reid Kleckner94b704c2015-09-09 21:10:03 +0000101
102__except.ret.13: ; preds = %catch.dispatch.11
David Majnemer8a1c45d2015-12-12 05:38:55 +0000103 %2 = catchpad within %cs3 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
104 catchret from %2 to label %__try.cont.15
Reid Kleckner94b704c2015-09-09 21:10:03 +0000105
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
110catch.dispatch.17: ; preds = %catchendblock.12, %__try.cont.15
David Majnemer8a1c45d2015-12-12 05:38:55 +0000111 %cs4 = catchswitch within none [label %__except.ret.19] unwind to caller
Reid Kleckner94b704c2015-09-09 21:10:03 +0000112
113__except.ret.19: ; preds = %catch.dispatch.17
David Majnemer8a1c45d2015-12-12 05:38:55 +0000114 %3 = catchpad within %cs4 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
115 catchret from %3 to label %__except.20
Reid Kleckner94b704c2015-09-09 21:10:03 +0000116
117__except.20: ; preds = %__except.ret.19
118 invoke void @crash() #3
119 to label %__try.cont.27 unwind label %catch.dispatch.23
120
121catch.dispatch.23: ; preds = %__except.20
David Majnemer8a1c45d2015-12-12 05:38:55 +0000122 %cs5 = catchswitch within none [label %__except.ret.25] unwind to caller
Reid Kleckner94b704c2015-09-09 21:10:03 +0000123
124__except.ret.25: ; preds = %catch.dispatch.23
David Majnemer8a1c45d2015-12-12 05:38:55 +0000125 %4 = catchpad within %cs5 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
126 catchret from %4 to label %__try.cont.27
Reid Kleckner94b704c2015-09-09 21:10:03 +0000127
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
132catch.dispatch.30: ; preds = %__try.cont.27
David Majnemer8a1c45d2015-12-12 05:38:55 +0000133 %cs6 = catchswitch within none [label %__except.ret.32] unwind to caller
Reid Kleckner94b704c2015-09-09 21:10:03 +0000134
135__except.ret.32: ; preds = %catch.dispatch.30
David Majnemer8a1c45d2015-12-12 05:38:55 +0000136 %5 = catchpad within %cs6 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
137 catchret from %5 to label %__try.cont.35
Reid Kleckner94b704c2015-09-09 21:10:03 +0000138
139__try.cont.35: ; preds = %__try.cont.15, %__try.cont.27, %__except.ret.32
140 ret void
Reid Kleckner94b704c2015-09-09 21:10:03 +0000141}
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
David Majnemer8a1c45d2015-12-12 05:38:55 +0000151; 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
Reid Kleckner94b704c2015-09-09 21:10:03 +0000158; 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
David Majnemer8a1c45d2015-12-12 05:38:55 +0000163; CHECK: .long -1
Reid Kleckner94b704c2015-09-09 21:10:03 +0000164; CHECK: .long _nested_exceptions_filter_catchall
165; CHECK: .long LBB
166
167declare void @crash() #0
168
169define internal i32 @nested_exceptions_filter_catchall() #0 {
170entry:
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
David Majnemer7735a6d2015-10-06 23:31:59 +0000186define void @code_in_catchpad() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
187entry:
188 invoke void @f(i32 1) #3
189 to label %__except unwind label %catch.dispatch
190
191catch.dispatch: ; preds = %entry
David Majnemer8a1c45d2015-12-12 05:38:55 +0000192 %cs1 = catchswitch within none [label %__except.ret] unwind to caller
David Majnemer7735a6d2015-10-06 23:31:59 +0000193
194__except.ret: ; preds = %catch.dispatch
David Majnemer8a1c45d2015-12-12 05:38:55 +0000195 %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
David Majnemer3bb88c02015-12-15 21:27:27 +0000196 call void @f(i32 2) [ "funclet"(token %0) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000197 catchret from %0 to label %__except
David Majnemer7735a6d2015-10-06 23:31:59 +0000198
199__except:
200 ret void
David Majnemer7735a6d2015-10-06 23:31:59 +0000201}
202
203; CHECK-LABEL: _code_in_catchpad:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000204; CHECK: # %__except.ret
David Majnemer7735a6d2015-10-06 23:31:59 +0000205; CHECK-NEXT: movl -24(%ebp), %esp
206; CHECK-NEXT: addl $12, %ebp
David Majnemer7735a6d2015-10-06 23:31:59 +0000207; CHECK-NEXT: movl $-1, -16(%ebp)
208; CHECK-NEXT: movl $2, (%esp)
209; CHECK-NEXT: calll _f
210
211
Reid Kleckner94b704c2015-09-09 21:10:03 +0000212; Function Attrs: nounwind readnone
213declare i8* @llvm.frameaddress(i32) #1
214
215; Function Attrs: nounwind readnone
216declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) #1
217
218; Function Attrs: nounwind readnone
219declare i8* @llvm.localrecover(i8*, i8*, i32) #1
220
221declare void @f(i32) #0
222
223declare i32 @_except_handler3(...)
224
225; Function Attrs: nounwind
226declare void @llvm.localescape(...) #2
227
228attributes #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" }
229attributes #1 = { nounwind readnone }
230attributes #2 = { nounwind }
231attributes #3 = { noinline }