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() {
18 store i32 0, i32* %retval
19 invoke void @might_crash()
20 to label %return unwind label %lpad
23 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
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() {
51 store i32 0, i32* %retval
52 invoke void @might_crash()
53 to label %return unwind label %lpad
56 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
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() {
78 invoke void @might_crash()
79 to label %return unwind label %lpad
82 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
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 @lpad_phi() {
112 invoke void @might_crash()
113 to label %cont unwind label %lpad
116 invoke void @might_crash()
117 to label %return unwind label %lpad
120 %ncalls.1 = phi i32 [ 0, %entry ], [ 1, %cont ]
121 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
123 %sel = extractvalue { i8*, i32 } %ehvals, 1
124 %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
125 %matches = icmp eq i32 %sel, %filt_sel
126 br i1 %matches, label %return, label %eh.resume
129 %r = phi i32 [2, %cont], [%ncalls.1, %lpad]
133 resume { i8*, i32 } %ehvals
136 ; CHECK-LABEL: define i32 @lpad_phi()
138 ; CHECK: store i32 0, i32*
139 ; CHECK: invoke void @might_crash()
140 ; CHECK: store i32 1, i32*
141 ; CHECK: invoke void @might_crash()
142 ; CHECK: landingpad { i8*, i32 }
143 ; CHECK-NEXT: cleanup
144 ; CHECK-NEXT: catch i32 ()* @filt
145 ; 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))
146 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
148 ; CHECK: lpad.return_crit_edge:
149 ; CHECK: load i32, i32*
150 ; CHECK: br label %return
153 ; CHECK-NEXT: %r = phi i32 [ 2, %cont ], [ %{{.*}}, %lpad.return_crit_edge ]
154 ; CHECK-NEXT: ret i32 %r
156 define i32 @cleanup_and_except() {
158 invoke void @might_crash()
159 to label %return unwind label %lpad
162 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
166 %sel = extractvalue { i8*, i32 } %ehvals, 1
167 %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
168 %matches = icmp eq i32 %sel, %filt_sel
169 br i1 %matches, label %return, label %eh.resume
172 %r = phi i32 [0, %entry], [1, %lpad]
176 resume { i8*, i32 } %ehvals
179 ; CHECK-LABEL: define i32 @cleanup_and_except()
180 ; CHECK: landingpad { i8*, i32 }
181 ; CHECK-NEXT: cleanup
182 ; CHECK-NEXT: catch i32 ()* @filt
183 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(
184 ; CHECK: i32 0, void ({{.*}})* @cleanup_and_except.cleanup,
185 ; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %lpad.return_crit_edge))
186 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
188 ; CHECK: lpad.return_crit_edge:
189 ; CHECK: br label %return
192 ; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
193 ; CHECK-NEXT: ret i32 %r
195 ; FIXME: This cleanup is an artifact of bad demotion.
196 ; X64-LABEL: define internal void @lpad_phi.cleanup(i8*, i8*)
197 ; X86-LABEL: define internal void @lpad_phi.cleanup()
198 ; X86: call i8* @llvm.frameaddress(i32 1)
199 ; CHECK: call i8* @llvm.framerecover({{.*}})
201 ; CHECK: store i32 %{{.*}}, i32*