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