[SEH] Emit 32-bit SEH tables for the new EH IR
[oota-llvm.git] / test / CodeGen / X86 / win32-seh-catchpad.ll
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   %0 = catchpad [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
15
16 __except.ret:                                     ; preds = %catch.dispatch
17   catchret %0 to label %__except
18
19 __except:                                         ; preds = %__except.ret
20   call void @f(i32 2)
21   br label %__try.cont
22
23 __try.cont:                                       ; preds = %__except, %invoke.cont
24   call void @f(i32 3)
25   ret void
26
27 catchendblock:                                    ; preds = %catch.dispatch
28   catchendpad unwind to caller
29
30 invoke.cont:                                      ; preds = %entry
31   br label %__try.cont
32 }
33
34 ; CHECK-LABEL: _try_except:
35 ;     Store state #0
36 ; CHECK: movl $0, -[[state:[0-9]+]](%ebp)
37 ; CHECK: movl $1, (%esp)
38 ; CHECK: calll _f
39 ; CHECK: movl $-1, -[[state]](%ebp)
40 ; CHECK: movl $3, (%esp)
41 ; CHECK: calll _f
42 ; CHECK: retl
43
44 ;   __except
45 ; CHECK: movl $-1, -[[state]](%ebp)
46 ; CHECK: movl $2, (%esp)
47 ; CHECK: calll _f
48
49 ; CHECK: .section        .xdata,"dr"
50 ; CHECK: L__ehtable$try_except:
51 ; CHECK:         .long   -1
52 ; CHECK:         .long   _try_except_filter_catchall
53 ; CHECK:         .long   LBB0_1
54
55 define internal i32 @try_except_filter_catchall() #0 {
56 entry:
57   %0 = call i8* @llvm.frameaddress(i32 1)
58   %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @try_except to i8*), i8* %0)
59   %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @try_except to i8*), i8* %1, i32 0)
60   %__exception_code = bitcast i8* %2 to i32*
61   %3 = getelementptr inbounds i8, i8* %0, i32 -20
62   %4 = bitcast i8* %3 to i8**
63   %5 = load i8*, i8** %4, align 4
64   %6 = bitcast i8* %5 to { i32*, i8* }*
65   %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0
66   %8 = load i32*, i32** %7, align 4
67   %9 = load i32, i32* %8, align 4
68   store i32 %9, i32* %__exception_code, align 4
69   ret i32 1
70 }
71
72 define void @nested_exceptions() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
73 entry:
74   %__exception_code = alloca i32, align 4
75   call void (...) @llvm.localescape(i32* %__exception_code)
76   invoke void @crash() #3
77           to label %__try.cont unwind label %catch.dispatch
78
79 catch.dispatch:                                   ; preds = %entry
80   %0 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
81
82 __except.ret:                                     ; preds = %catch.dispatch
83   catchret %0 to label %__try.cont
84
85 __try.cont:                                       ; preds = %entry, %__except.ret
86   invoke void @crash() #3
87           to label %__try.cont.9 unwind label %catch.dispatch.5
88
89 catch.dispatch.5:                                 ; preds = %__try.cont
90   %1 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.7 unwind label %catchendblock.6
91
92 __except.ret.7:                                   ; preds = %catch.dispatch.5
93   catchret %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   %2 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.13 unwind label %catchendblock.12
101
102 __except.ret.13:                                  ; preds = %catch.dispatch.11
103   catchret %2 to label %__try.cont.15
104
105 __try.cont.15:                                    ; preds = %__try.cont.9, %__except.ret.13
106   invoke void @crash() #3
107           to label %__try.cont.35 unwind label %catch.dispatch.17
108
109 catch.dispatch.17:                                ; preds = %catchendblock.12, %__try.cont.15
110   %3 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.19 unwind label %catchendblock.18
111
112 __except.ret.19:                                  ; preds = %catch.dispatch.17
113   catchret %3 to label %__except.20
114
115 __except.20:                                      ; preds = %__except.ret.19
116   invoke void @crash() #3
117           to label %__try.cont.27 unwind label %catch.dispatch.23
118
119 catch.dispatch.23:                                ; preds = %__except.20
120   %4 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.25 unwind label %catchendblock.24
121
122 __except.ret.25:                                  ; preds = %catch.dispatch.23
123   catchret %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
129 catch.dispatch.30:                                ; preds = %__try.cont.27
130   %5 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.32 unwind label %catchendblock.31
131
132 __except.ret.32:                                  ; preds = %catch.dispatch.30
133   catchret %5 to label %__try.cont.35
134
135 __try.cont.35:                                    ; preds = %__try.cont.15, %__try.cont.27, %__except.ret.32
136   ret void
137
138 catchendblock.31:                                 ; preds = %catch.dispatch.30
139   catchendpad unwind to caller
140
141 catchendblock.24:                                 ; preds = %catch.dispatch.23
142   catchendpad unwind to caller
143
144 catchendblock.18:                                 ; preds = %catch.dispatch.17
145   catchendpad unwind to caller
146
147 catchendblock.12:                                 ; preds = %catch.dispatch.11
148   catchendpad unwind label %catch.dispatch.17
149
150 catchendblock.6:                                  ; preds = %catch.dispatch.5
151   catchendpad unwind label %catch.dispatch.11
152
153 catchendblock:                                    ; preds = %catch.dispatch
154   catchendpad unwind label %catch.dispatch.11
155 }
156
157 ; This table is equivalent to the one produced by MSVC, even if it isn't in
158 ; quite the same order.
159
160 ; CHECK-LABEL: _nested_exceptions:
161 ; CHECK: L__ehtable$nested_exceptions:
162 ; CHECK:         .long   -1
163 ; CHECK:         .long   _nested_exceptions_filter_catchall
164 ; CHECK:         .long   LBB
165 ; CHECK:         .long   -1
166 ; CHECK:         .long   _nested_exceptions_filter_catchall
167 ; CHECK:         .long   LBB
168 ; CHECK:         .long   -1
169 ; CHECK:         .long   _nested_exceptions_filter_catchall
170 ; CHECK:         .long   LBB
171 ; CHECK:         .long   2
172 ; CHECK:         .long   _nested_exceptions_filter_catchall
173 ; CHECK:         .long   LBB
174 ; CHECK:         .long   3
175 ; CHECK:         .long   _nested_exceptions_filter_catchall
176 ; CHECK:         .long   LBB
177 ; CHECK:         .long   3
178 ; CHECK:         .long   _nested_exceptions_filter_catchall
179 ; CHECK:         .long   LBB
180
181 declare void @crash() #0
182
183 define internal i32 @nested_exceptions_filter_catchall() #0 {
184 entry:
185   %0 = call i8* @llvm.frameaddress(i32 1)
186   %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %0)
187   %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %1, i32 0)
188   %__exception_code3 = bitcast i8* %2 to i32*
189   %3 = getelementptr inbounds i8, i8* %0, i32 -20
190   %4 = bitcast i8* %3 to i8**
191   %5 = load i8*, i8** %4, align 4
192   %6 = bitcast i8* %5 to { i32*, i8* }*
193   %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0
194   %8 = load i32*, i32** %7, align 4
195   %9 = load i32, i32* %8, align 4
196   store i32 %9, i32* %__exception_code3, align 4
197   ret i32 1
198 }
199
200 ; Function Attrs: nounwind readnone
201 declare i8* @llvm.frameaddress(i32) #1
202
203 ; Function Attrs: nounwind readnone
204 declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) #1
205
206 ; Function Attrs: nounwind readnone
207 declare i8* @llvm.localrecover(i8*, i8*, i32) #1
208
209 declare void @f(i32) #0
210
211 declare i32 @_except_handler3(...)
212
213 ; Function Attrs: nounwind
214 declare void @llvm.localescape(...) #2
215
216 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" }
217 attributes #1 = { nounwind readnone }
218 attributes #2 = { nounwind }
219 attributes #3 = { noinline }