1 ; RUN: opt -S -winehprepare -mtriple=x86_64-windows-msvc < %s | FileCheck %s
3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4 target triple = "x86_64-pc-windows-msvc"
6 declare void @cleanup()
8 declare void @might_crash()
9 declare i32 @__C_specific_handler(...)
10 declare i32 @llvm.eh.typeid.for(i8*)
12 define i32 @simple_except_store() {
15 store i32 0, i32* %retval
16 invoke void @might_crash()
17 to label %return unwind label %lpad
20 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
22 %sel = extractvalue { i8*, i32 } %ehvals, 1
23 %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
24 %matches = icmp eq i32 %sel, %filt_sel
25 br i1 %matches, label %__except, label %eh.resume
28 store i32 1, i32* %retval
32 %r = load i32, i32* %retval
36 resume { i8*, i32 } %ehvals
39 ; CHECK-LABEL: define i32 @simple_except_store()
40 ; CHECK: landingpad { i8*, i32 }
41 ; CHECK-NEXT: catch i32 ()* @filt
42 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@simple_except_store, %__except))
43 ; CHECK-NEXT: indirectbr {{.*}} [label %__except]
45 define i32 @catch_all() {
48 store i32 0, i32* %retval
49 invoke void @might_crash()
50 to label %return unwind label %lpad
53 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
55 store i32 1, i32* %retval
59 %r = load i32, i32* %retval
63 ; CHECK-LABEL: define i32 @catch_all()
64 ; CHECK: landingpad { i8*, i32 }
65 ; CHECK-NEXT: catch i8* null
66 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@catch_all, %catch.all))
67 ; CHECK-NEXT: indirectbr {{.*}} [label %catch.all]
70 ; CHECK: store i32 1, i32* %retval
73 define i32 @except_phi() {
75 invoke void @might_crash()
76 to label %return unwind label %lpad
79 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
81 %sel = extractvalue { i8*, i32 } %ehvals, 1
82 %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
83 %matches = icmp eq i32 %sel, %filt_sel
84 br i1 %matches, label %return, label %eh.resume
87 %r = phi i32 [0, %entry], [1, %lpad]
91 resume { i8*, i32 } %ehvals
94 ; CHECK-LABEL: define i32 @except_phi()
95 ; CHECK: landingpad { i8*, i32 }
96 ; CHECK-NEXT: catch i32 ()* @filt
97 ; 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))
98 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
100 ; CHECK: lpad.return_crit_edge:
101 ; CHECK: br label %return
104 ; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
105 ; CHECK-NEXT: ret i32 %r
107 define i32 @lpad_phi() {
109 invoke void @might_crash()
110 to label %cont unwind label %lpad
113 invoke void @might_crash()
114 to label %return unwind label %lpad
117 %ncalls.1 = phi i32 [ 0, %entry ], [ 1, %cont ]
118 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
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
126 %r = phi i32 [2, %cont], [%ncalls.1, %lpad]
130 resume { i8*, i32 } %ehvals
133 ; CHECK-LABEL: define i32 @lpad_phi()
135 ; CHECK: store i32 0, i32*
136 ; CHECK: invoke void @might_crash()
137 ; CHECK: store i32 1, i32*
138 ; CHECK: invoke void @might_crash()
139 ; CHECK: landingpad { i8*, i32 }
140 ; CHECK-NEXT: cleanup
141 ; CHECK-NEXT: catch i32 ()* @filt
142 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @lpad_phi.cleanup, i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@lpad_phi, %lpad.return_crit_edge))
143 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
145 ; CHECK: lpad.return_crit_edge:
146 ; CHECK: load i32, i32*
147 ; CHECK: br label %return
150 ; CHECK-NEXT: %r = phi i32 [ 2, %cont ], [ %{{.*}}, %lpad.return_crit_edge ]
151 ; CHECK-NEXT: ret i32 %r
153 define i32 @cleanup_and_except() {
155 invoke void @might_crash()
156 to label %return unwind label %lpad
159 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
163 %sel = extractvalue { i8*, i32 } %ehvals, 1
164 %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
165 %matches = icmp eq i32 %sel, %filt_sel
166 br i1 %matches, label %return, label %eh.resume
169 %r = phi i32 [0, %entry], [1, %lpad]
173 resume { i8*, i32 } %ehvals
176 ; CHECK-LABEL: define i32 @cleanup_and_except()
177 ; CHECK: landingpad { i8*, i32 }
178 ; CHECK-NEXT: cleanup
179 ; CHECK-NEXT: catch i32 ()* @filt
180 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(
181 ; CHECK: i32 0, void (i8*, i8*)* @cleanup_and_except.cleanup,
182 ; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %lpad.return_crit_edge))
183 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
185 ; CHECK: lpad.return_crit_edge:
186 ; CHECK: br label %return
189 ; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
190 ; CHECK-NEXT: ret i32 %r
192 ; FIXME: This cleanup is an artifact of bad demotion.
193 ; CHECK-LABEL: define internal void @lpad_phi.cleanup(i8*, i8*)
195 ; CHECK: store i32 %{{.*}}, i32*