xref: /llvm-project/llvm/test/CodeGen/X86/win32-seh-catchpad.ll (revision 2f448bf509432c1a19ec46ab8cbc7353c03c6280)
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