[SEH] Update SEH codegen tests to use the new IR
[oota-llvm.git] / test / CodeGen / WinEH / seh-simple.ll
1 ; RUN: opt -S -winehprepare -mtriple=x86_64-windows-msvc < %s \
2 ; RUN:          | FileCheck %s --check-prefix=CHECK --check-prefix=X64
3 ; RUN: opt -S -winehprepare -mtriple=x86_64-windows-coreclr < %s \
4 ; RUN:          | FileCheck %s --check-prefix=CHECK --check-prefix=X64
5
6 ; This test should also pass in 32-bit using _except_handler3.
7 ; RUN: sed -e 's/__C_specific_handler/_except_handler3/' %s \
8 ; RUN:          | opt -S -winehprepare -mtriple=i686-windows-msvc \
9 ; RUN:          | FileCheck %s --check-prefix=CHECK --check-prefix=X86
10
11 declare void @cleanup()
12 declare i32 @filt()
13 declare void @might_crash()
14 declare i32 @__C_specific_handler(...)
15 declare i32 @llvm.eh.typeid.for(i8*)
16
17 define i32 @simple_except_store() personality i32 (...)* @__C_specific_handler {
18 entry:
19   %retval = alloca i32
20   store i32 0, i32* %retval
21   invoke void @might_crash()
22           to label %return unwind label %lpad
23
24 lpad:
25   %ehvals = landingpad { i8*, i32 }
26           catch i32 ()* @filt
27   %sel = extractvalue { i8*, i32 } %ehvals, 1
28   %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
29   %matches = icmp eq i32 %sel, %filt_sel
30   br i1 %matches, label %__except, label %eh.resume
31
32 __except:
33   store i32 1, i32* %retval
34   br label %return
35
36 return:
37   %r = load i32, i32* %retval
38   ret i32 %r
39
40 eh.resume:
41   resume { i8*, i32 } %ehvals
42 }
43
44 ; CHECK-LABEL: define i32 @simple_except_store()
45 ; CHECK: landingpad { i8*, i32 }
46 ; CHECK-NEXT: catch i32 ()* @filt
47 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@simple_except_store, %__except))
48 ; CHECK-NEXT: indirectbr {{.*}} [label %__except]
49
50 define i32 @catch_all() personality i32 (...)* @__C_specific_handler {
51 entry:
52   %retval = alloca i32
53   store i32 0, i32* %retval
54   invoke void @might_crash()
55           to label %return unwind label %lpad
56
57 lpad:
58   %ehvals = landingpad { i8*, i32 }
59           catch i8* null
60   store i32 1, i32* %retval
61   br label %return
62
63 return:
64   %r = load i32, i32* %retval
65   ret i32 %r
66 }
67
68 ; CHECK-LABEL: define i32 @catch_all()
69 ; CHECK: landingpad { i8*, i32 }
70 ; CHECK-NEXT: catch i8* null
71 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@catch_all, %lpad.split))
72 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.split]
73 ;
74 ; CHECK: lpad.split:
75 ; CHECK: store i32 1, i32* %retval
76
77
78 define i32 @except_phi() personality i32 (...)* @__C_specific_handler {
79 entry:
80   invoke void @might_crash()
81           to label %return unwind label %lpad
82
83 lpad:
84   %ehvals = landingpad { i8*, i32 }
85           catch i32 ()* @filt
86   %sel = extractvalue { i8*, i32 } %ehvals, 1
87   %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
88   %matches = icmp eq i32 %sel, %filt_sel
89   br i1 %matches, label %return, label %eh.resume
90
91 return:
92   %r = phi i32 [0, %entry], [1, %lpad]
93   ret i32 %r
94
95 eh.resume:
96   resume { i8*, i32 } %ehvals
97 }
98
99 ; CHECK-LABEL: define i32 @except_phi()
100 ; CHECK: landingpad { i8*, i32 }
101 ; CHECK-NEXT: catch i32 ()* @filt
102 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_phi, %lpad.return_crit_edge))
103 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
104 ;
105 ; CHECK: lpad.return_crit_edge:
106 ; CHECK: br label %return
107 ;
108 ; CHECK: return:
109 ; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
110 ; CHECK-NEXT: ret i32 %r
111
112 define i32 @except_join() personality i32 (...)* @__C_specific_handler {
113 entry:
114   invoke void @might_crash()
115           to label %return unwind label %lpad
116
117 lpad:
118   %ehvals = landingpad { i8*, i32 }
119           catch i32 ()* @filt
120   %sel = extractvalue { i8*, i32 } %ehvals, 1
121   %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
122   %matches = icmp eq i32 %sel, %filt_sel
123   br i1 %matches, label %return, label %eh.resume
124
125 return:
126   ret i32 0
127
128 eh.resume:
129   resume { i8*, i32 } %ehvals
130 }
131
132 ; CHECK-LABEL: define i32 @except_join()
133 ; CHECK: landingpad { i8*, i32 }
134 ; CHECK-NEXT: catch i32 ()* @filt
135 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_join, %lpad.return_crit_edge))
136 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
137 ;
138 ; CHECK: lpad.return_crit_edge:
139 ; CHECK: br label %return
140 ;
141 ; CHECK: return:
142 ; CHECK-NEXT: ret i32 0
143
144 define i32 @lpad_phi() personality i32 (...)* @__C_specific_handler {
145 entry:
146   invoke void @might_crash()
147           to label %cont unwind label %lpad
148
149 cont:
150   invoke void @might_crash()
151           to label %return unwind label %lpad
152
153 lpad:
154   %ncalls.1 = phi i32 [ 0, %entry ], [ 1, %cont ]
155   %ehvals = landingpad { i8*, i32 }
156           catch i32 ()* @filt
157   %sel = extractvalue { i8*, i32 } %ehvals, 1
158   %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
159   %matches = icmp eq i32 %sel, %filt_sel
160   br i1 %matches, label %return, label %eh.resume
161
162 return:
163   %r = phi i32 [2, %cont], [%ncalls.1, %lpad]
164   ret i32 %r
165
166 eh.resume:
167   resume { i8*, i32 } %ehvals
168 }
169
170 ; CHECK-LABEL: define i32 @lpad_phi()
171 ; CHECK: alloca i32
172 ; CHECK: store i32 0, i32*
173 ; CHECK: invoke void @might_crash()
174 ; CHECK: store i32 1, i32*
175 ; CHECK: invoke void @might_crash()
176 ; CHECK: landingpad { i8*, i32 }
177 ; CHECK-NEXT: cleanup
178 ; CHECK-NEXT: catch i32 ()* @filt
179 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void ({{.*}})* @lpad_phi.cleanup, i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@lpad_phi, %lpad.return_crit_edge))
180 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
181 ;
182 ; CHECK: lpad.return_crit_edge:
183 ; CHECK: load i32, i32*
184 ; CHECK: br label %return
185 ;
186 ; CHECK: return:
187 ; CHECK-NEXT: %r = phi i32 [ 2, %cont ], [ %{{.*}}, %lpad.return_crit_edge ]
188 ; CHECK-NEXT: ret i32 %r
189
190 define i32 @cleanup_and_except() personality i32 (...)* @__C_specific_handler {
191 entry:
192   invoke void @might_crash()
193           to label %return unwind label %lpad
194
195 lpad:
196   %ehvals = landingpad { i8*, i32 }
197           cleanup
198           catch i32 ()* @filt
199   call void @cleanup()
200   %sel = extractvalue { i8*, i32 } %ehvals, 1
201   %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
202   %matches = icmp eq i32 %sel, %filt_sel
203   br i1 %matches, label %return, label %eh.resume
204
205 return:
206   %r = phi i32 [0, %entry], [1, %lpad]
207   ret i32 %r
208
209 eh.resume:
210   resume { i8*, i32 } %ehvals
211 }
212
213 ; CHECK-LABEL: define i32 @cleanup_and_except()
214 ; CHECK: landingpad { i8*, i32 }
215 ; CHECK-NEXT: cleanup
216 ; CHECK-NEXT: catch i32 ()* @filt
217 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(
218 ; CHECK: i32 0, void ({{.*}})* @cleanup_and_except.cleanup,
219 ; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %lpad.return_crit_edge))
220 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
221 ;
222 ; CHECK: lpad.return_crit_edge:
223 ; CHECK: br label %return
224 ;
225 ; CHECK: return:
226 ; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
227 ; CHECK-NEXT: ret i32 %r
228
229 ; FIXME: This cleanup is an artifact of bad demotion.
230 ; X64-LABEL: define internal void @lpad_phi.cleanup(i8*, i8*)
231 ; X86-LABEL: define internal void @lpad_phi.cleanup()
232 ; X86: call i8* @llvm.frameaddress(i32 1)
233 ; CHECK: call i8* @llvm.localrecover({{.*}})
234 ; CHECK: load i32
235 ; CHECK: store i32 %{{.*}}, i32*