1
; RUN: opt -S -winehprepare -mtriple=x86_64-windows-msvc < %s \
2
; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X64
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
9
declare void @cleanup()
11
declare void @might_crash()
12
declare i32 @__C_specific_handler(...)
13
declare i32 @llvm.eh.typeid.for(i8*)
15
define i32 @simple_except_store() personality i32 (...)* @__C_specific_handler {
18
store i32 0, i32* %retval
19
invoke void @might_crash()
20
to label %return unwind label %lpad
23
%ehvals = landingpad { i8*, i32 }
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
31
store i32 1, i32* %retval
35
%r = load i32, i32* %retval
39
resume { i8*, i32 } %ehvals
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]
48
define i32 @catch_all() personality i32 (...)* @__C_specific_handler {
51
store i32 0, i32* %retval
52
invoke void @might_crash()
53
to label %return unwind label %lpad
56
%ehvals = landingpad { i8*, i32 }
58
store i32 1, i32* %retval
62
%r = load i32, i32* %retval
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]
73
; CHECK: store i32 1, i32* %retval
76
define i32 @except_phi() personality i32 (...)* @__C_specific_handler {
78
invoke void @might_crash()
79
to label %return unwind label %lpad
82
%ehvals = landingpad { i8*, i32 }
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
90
%r = phi i32 [0, %entry], [1, %lpad]
94
resume { i8*, i32 } %ehvals
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]
103
; CHECK: lpad.return_crit_edge:
104
; CHECK: br label %return
107
; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
108
; CHECK-NEXT: ret i32 %r
110
define i32 @except_join() personality i32 (...)* @__C_specific_handler {
112
invoke void @might_crash()
113
to label %return unwind label %lpad
116
%ehvals = landingpad { i8*, i32 }
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
127
resume { i8*, i32 } %ehvals
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]
136
; CHECK: lpad.return_crit_edge:
137
; CHECK: br label %return
140
; CHECK-NEXT: ret i32 0
142
define i32 @lpad_phi() personality i32 (...)* @__C_specific_handler {
144
invoke void @might_crash()
145
to label %cont unwind label %lpad
148
invoke void @might_crash()
149
to label %return unwind label %lpad
152
%ncalls.1 = phi i32 [ 0, %entry ], [ 1, %cont ]
153
%ehvals = landingpad { i8*, i32 }
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
161
%r = phi i32 [2, %cont], [%ncalls.1, %lpad]
165
resume { i8*, i32 } %ehvals
168
; CHECK-LABEL: define i32 @lpad_phi()
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]
180
; CHECK: lpad.return_crit_edge:
181
; CHECK: load i32, i32*
182
; CHECK: br label %return
185
; CHECK-NEXT: %r = phi i32 [ 2, %cont ], [ %{{.*}}, %lpad.return_crit_edge ]
186
; CHECK-NEXT: ret i32 %r
188
define i32 @cleanup_and_except() personality i32 (...)* @__C_specific_handler {
190
invoke void @might_crash()
191
to label %return unwind label %lpad
194
%ehvals = landingpad { i8*, i32 }
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
204
%r = phi i32 [0, %entry], [1, %lpad]
208
resume { i8*, i32 } %ehvals
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]
220
; CHECK: lpad.return_crit_edge:
221
; CHECK: br label %return
224
; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
225
; CHECK-NEXT: ret i32 %r
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({{.*}})
233
; CHECK: store i32 %{{.*}}, i32*