Re-commit "[SEH] Remove the old __C_specific_handler code now that WinEHPrepare works"
[oota-llvm.git] / test / CodeGen / WinEH / seh-simple.ll
1 ; RUN: opt -S -winehprepare -mtriple=x86_64-windows-msvc < %s | FileCheck %s
2
3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4 target triple = "x86_64-pc-windows-msvc"
5
6 declare void @cleanup()
7 declare i32 @filt()
8 declare void @might_crash()
9 declare i32 @__C_specific_handler(...)
10 declare i32 @llvm.eh.typeid.for(i8*)
11
12 define i32 @simple_except_store() {
13 entry:
14   %retval = alloca i32
15   store i32 0, i32* %retval
16   invoke void @might_crash()
17           to label %return unwind label %lpad
18
19 lpad:
20   %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
21           catch i32 ()* @filt
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
26
27 __except:
28   store i32 1, i32* %retval
29   br label %return
30
31 return:
32   %r = load i32, i32* %retval
33   ret i32 %r
34
35 eh.resume:
36   resume { i8*, i32 } %ehvals
37 }
38
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]
44
45 define i32 @catch_all() {
46 entry:
47   %retval = alloca i32
48   store i32 0, i32* %retval
49   invoke void @might_crash()
50           to label %return unwind label %lpad
51
52 lpad:
53   %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
54           catch i8* null
55   store i32 1, i32* %retval
56   br label %return
57
58 return:
59   %r = load i32, i32* %retval
60   ret i32 %r
61 }
62
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]
68 ;
69 ; CHECK: catch.all:
70 ; CHECK: store i32 1, i32* %retval
71
72
73 define i32 @except_phi() {
74 entry:
75   invoke void @might_crash()
76           to label %return unwind label %lpad
77
78 lpad:
79   %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
80           catch i32 ()* @filt
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
85
86 return:
87   %r = phi i32 [0, %entry], [1, %lpad]
88   ret i32 %r
89
90 eh.resume:
91   resume { i8*, i32 } %ehvals
92 }
93
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]
99 ;
100 ; CHECK: lpad.return_crit_edge:
101 ; CHECK: br label %return
102 ;
103 ; CHECK: return:
104 ; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
105 ; CHECK-NEXT: ret i32 %r
106
107 define i32 @lpad_phi() {
108 entry:
109   invoke void @might_crash()
110           to label %cont unwind label %lpad
111
112 cont:
113   invoke void @might_crash()
114           to label %return unwind label %lpad
115
116 lpad:
117   %ncalls.1 = phi i32 [ 0, %entry ], [ 1, %cont ]
118   %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
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   %r = phi i32 [2, %cont], [%ncalls.1, %lpad]
127   ret i32 %r
128
129 eh.resume:
130   resume { i8*, i32 } %ehvals
131 }
132
133 ; CHECK-LABEL: define i32 @lpad_phi()
134 ; CHECK: alloca i32
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]
144 ;
145 ; CHECK: lpad.return_crit_edge:
146 ; CHECK: load i32, i32*
147 ; CHECK: br label %return
148 ;
149 ; CHECK: return:
150 ; CHECK-NEXT: %r = phi i32 [ 2, %cont ], [ %{{.*}}, %lpad.return_crit_edge ]
151 ; CHECK-NEXT: ret i32 %r
152
153 define i32 @cleanup_and_except() {
154 entry:
155   invoke void @might_crash()
156           to label %return unwind label %lpad
157
158 lpad:
159   %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
160           cleanup
161           catch i32 ()* @filt
162   call void @cleanup()
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
167
168 return:
169   %r = phi i32 [0, %entry], [1, %lpad]
170   ret i32 %r
171
172 eh.resume:
173   resume { i8*, i32 } %ehvals
174 }
175
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]
184 ;
185 ; CHECK: lpad.return_crit_edge:
186 ; CHECK: br label %return
187 ;
188 ; CHECK: return:
189 ; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
190 ; CHECK-NEXT: ret i32 %r
191
192 ; FIXME: This cleanup is an artifact of bad demotion.
193 ; CHECK-LABEL: define internal void @lpad_phi.cleanup(i8*, i8*)
194 ; CHECK: load i32
195 ; CHECK: store i32 %{{.*}}, i32*