[WinEH] Add some test cases I forgot to add to previous commits
[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 @lpad_phi() personality i32 (...)* @__C_specific_handler {
111 entry:
112   invoke void @might_crash()
113           to label %cont unwind label %lpad
114
115 cont:
116   invoke void @might_crash()
117           to label %return unwind label %lpad
118
119 lpad:
120   %ncalls.1 = phi i32 [ 0, %entry ], [ 1, %cont ]
121   %ehvals = landingpad { i8*, i32 }
122           catch i32 ()* @filt
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
127
128 return:
129   %r = phi i32 [2, %cont], [%ncalls.1, %lpad]
130   ret i32 %r
131
132 eh.resume:
133   resume { i8*, i32 } %ehvals
134 }
135
136 ; CHECK-LABEL: define i32 @lpad_phi()
137 ; CHECK: alloca i32
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]
147 ;
148 ; CHECK: lpad.return_crit_edge:
149 ; CHECK: load i32, i32*
150 ; CHECK: br label %return
151 ;
152 ; CHECK: return:
153 ; CHECK-NEXT: %r = phi i32 [ 2, %cont ], [ %{{.*}}, %lpad.return_crit_edge ]
154 ; CHECK-NEXT: ret i32 %r
155
156 define i32 @cleanup_and_except() personality i32 (...)* @__C_specific_handler {
157 entry:
158   invoke void @might_crash()
159           to label %return unwind label %lpad
160
161 lpad:
162   %ehvals = landingpad { i8*, i32 }
163           cleanup
164           catch i32 ()* @filt
165   call void @cleanup()
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
170
171 return:
172   %r = phi i32 [0, %entry], [1, %lpad]
173   ret i32 %r
174
175 eh.resume:
176   resume { i8*, i32 } %ehvals
177 }
178
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]
187 ;
188 ; CHECK: lpad.return_crit_edge:
189 ; CHECK: br label %return
190 ;
191 ; CHECK: return:
192 ; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
193 ; CHECK-NEXT: ret i32 %r
194
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({{.*}})
200 ; CHECK: load i32
201 ; CHECK: store i32 %{{.*}}, i32*