blob: 67a04c4e97de843d41a896cf3f9bd8b6e7c3c418 [file] [log] [blame]
Nico Weber5779f842015-02-12 23:16:11 +00001// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
Reid Kleckner1d59f992015-01-22 01:36:17 +00002
Nico Weber5779f842015-02-12 23:16:11 +00003void g();
Reid Kleckner1d59f992015-01-22 01:36:17 +00004
Nico Weber5779f842015-02-12 23:16:11 +00005//////////////////////////////////////////////////////////////////////////////
6// __leave with __except
7
8// Nothing in the __try block can trap, so __try.cont isn't created.
9int __leave_with___except_simple() {
Reid Kleckner1d59f992015-01-22 01:36:17 +000010 int myres = 0;
11 __try {
Nico Weber5779f842015-02-12 23:16:11 +000012 myres = 15;
Reid Kleckner1d59f992015-01-22 01:36:17 +000013 __leave;
Nico Weber5779f842015-02-12 23:16:11 +000014 myres = 23;
Reid Kleckner1d59f992015-01-22 01:36:17 +000015 } __except (1) {
16 return 0;
17 }
Reid Kleckner1d59f992015-01-22 01:36:17 +000018 return 1;
19}
Nico Weber5779f842015-02-12 23:16:11 +000020// CHECK-LABEL: define i32 @__leave_with___except_simple()
21// CHECK: store i32 15, i32* %myres
Nico Weberd9b8bd62015-02-25 17:44:04 +000022// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +000023// CHECK-NOT: store i32 23
Nico Weberd9b8bd62015-02-25 17:44:04 +000024// CHECK: [[tryleave]]
Nico Weber5779f842015-02-12 23:16:11 +000025// CHECK-NEXT: ret i32 1
26
27
28// The "normal" case.
29int __leave_with___except() {
30 int myres = 0;
31 __try {
32 g();
33 __leave;
34 myres = 23;
35 } __except (1) {
36 return 0;
37 }
38 return 1;
39}
40// CHECK-LABEL: define i32 @__leave_with___except()
41// CHECK: invoke void bitcast (void (...)* @g to void ()*)()
42// CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}}
43// For __excepts, instead of an explicit __try.__leave label, we could use
44// use invoke.cont as __leave jump target instead. However, not doing this
45// keeps the CodeGen code simpler, __leave is very rare, and SimplifyCFG will
46// simplify this anyways.
47// CHECK: [[cont]]
Nico Weberd9b8bd62015-02-25 17:44:04 +000048// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +000049// CHECK-NOT: store i32 23
Nico Weberd9b8bd62015-02-25 17:44:04 +000050// CHECK: [[tryleave]]
51// CHECK-NEXT: br label %
Nico Weber5779f842015-02-12 23:16:11 +000052
53
54//////////////////////////////////////////////////////////////////////////////
55// __leave with __finally
56
57void abort(void) __attribute__((noreturn));
58
59// Nothing in the __try block can trap, so __finally.cont and friends aren't
60// created.
61int __leave_with___finally_simple() {
62 int myres = 0;
63 __try {
64 myres = 15;
65 __leave;
66 myres = 23;
67 } __finally {
68 return 0;
69 }
70 return 1;
71}
72// CHECK-LABEL: define i32 @__leave_with___finally_simple()
73// CHECK: store i32 15, i32* %myres
Nico Weberd9b8bd62015-02-25 17:44:04 +000074// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +000075// CHECK-NOT: store i32 23
Nico Weberd9b8bd62015-02-25 17:44:04 +000076// CHECK: [[tryleave]]
77// CHECK-NEXT: store i8 0, i8* %
78// CHECK-NEXT: br label %
Nico Weber5779f842015-02-12 23:16:11 +000079
80// __finally block doesn't return, __finally.cont doesn't exist.
81int __leave_with___finally_noreturn() {
82 int myres = 0;
83 __try {
84 myres = 15;
85 __leave;
86 myres = 23;
87 } __finally {
88 abort();
89 }
90 return 1;
91}
92// CHECK-LABEL: define i32 @__leave_with___finally_noreturn()
93// CHECK: store i32 15, i32* %myres
Nico Weberd9b8bd62015-02-25 17:44:04 +000094// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +000095// CHECK-NOT: store i32 23
Nico Weberd9b8bd62015-02-25 17:44:04 +000096// CHECK: [[tryleave]]
97// CHECK-NEXT: store i8 0, i8* %
98// CHECK-NEXT: br label %
Nico Weber5779f842015-02-12 23:16:11 +000099
100// The "normal" case.
101int __leave_with___finally() {
102 int myres = 0;
103 __try {
104 g();
105 __leave;
106 myres = 23;
107 } __finally {
108 return 0;
109 }
110 return 1;
111}
112// CHECK-LABEL: define i32 @__leave_with___finally()
113// CHECK: invoke void bitcast (void (...)* @g to void ()*)()
114// CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}}
115// For __finally, there needs to be an explicit __try.__leave, because
116// abnormal.termination.slot needs to be set there.
117// CHECK: [[cont]]
Nico Weberd9b8bd62015-02-25 17:44:04 +0000118// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +0000119// CHECK-NOT: store i32 23
Nico Weberd9b8bd62015-02-25 17:44:04 +0000120// CHECK: [[tryleave]]
121// CHECK-NEXT: store i8 0, i8* %
122// CHECK-NEXT: br label %
Nico Weber5779f842015-02-12 23:16:11 +0000123
124
125//////////////////////////////////////////////////////////////////////////////
126// Mixed, nested cases.
127
Nico Weber5779f842015-02-12 23:16:11 +0000128int nested___except___finally() {
129 int myres = 0;
130 __try {
131 __try {
132 g();
133 } __finally {
134 g();
135 __leave; // Refers to the outer __try, not the __finally!
136 myres = 23;
137 return 0;
138 }
139
140 myres = 51;
141 } __except (1) {
142 }
143 return 1;
144}
145// The order of basic blocks in the below doesn't matter.
146// CHECK-LABEL: define i32 @nested___except___finally()
147
148// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)()
149// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
150
Nico Weberd9b8bd62015-02-25 17:44:04 +0000151// CHECK: [[g1_cont]]
152// CHECK-NEXT: store i8 0, i8* %[[abnormal:[^ ]*]]
153// CHECK-NEXT: br label %[[finally:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +0000154
Nico Weberd9b8bd62015-02-25 17:44:04 +0000155// CHECK: [[finally]]
156// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)()
Nico Weber5779f842015-02-12 23:16:11 +0000157// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
158
Nico Weberd9b8bd62015-02-25 17:44:04 +0000159// CHECK: [[g2_cont]]
160// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +0000161// CHECK-NOT: store i32 23
Nico Weber5779f842015-02-12 23:16:11 +0000162
Nico Weberff62a6a2015-02-26 22:34:33 +0000163// Unused __finally continuation block
164// CHECK: store i32 51, i32* %
165// CHECK-NEXT: br label %[[tryleave]]
166
167// CHECK: [[tryleave]]
168// CHECK-NEXT: br label %[[trycont:[^ ]*]]
169
Nico Weberd9b8bd62015-02-25 17:44:04 +0000170// CHECK: [[g1_lpad]]
171// CHECK: store i8 1, i8* %
172// CHECK-NEXT: br label %[[finally]]
Nico Weber5779f842015-02-12 23:16:11 +0000173
Nico Weberd9b8bd62015-02-25 17:44:04 +0000174// CHECK: [[g2_lpad]]
175// CHECK-NOT: %[[abnormal]]
176// CHECK: br label %[[except:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +0000177
Nico Weberd9b8bd62015-02-25 17:44:04 +0000178// CHECK: [[except]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000179// CHECK-NEXT: br label %[[trycont]]
Nico Weber5779f842015-02-12 23:16:11 +0000180
Nico Weberd9b8bd62015-02-25 17:44:04 +0000181// CHECK: [[trycont]]
182// CHECK-NEXT: ret i32 1
183
Nico Weber5779f842015-02-12 23:16:11 +0000184int nested___except___except() {
185 int myres = 0;
186 __try {
187 __try {
188 g();
189 myres = 16;
190 } __except (1) {
191 g();
192 __leave; // Refers to the outer __try, not the __except we're in!
193 myres = 23;
194 return 0;
195 }
196
197 myres = 51;
198 } __except (1) {
199 }
200 return 1;
201}
202// The order of basic blocks in the below doesn't matter.
203// CHECK-LABEL: define i32 @nested___except___except()
204
205// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)()
206// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
207
Nico Weberd9b8bd62015-02-25 17:44:04 +0000208// CHECK: [[g1_cont]]
Nico Weber5779f842015-02-12 23:16:11 +0000209// CHECK: store i32 16, i32* %myres
Nico Weberd9b8bd62015-02-25 17:44:04 +0000210// CHECK-NEXT: br label %[[trycont:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +0000211
Nico Weberd9b8bd62015-02-25 17:44:04 +0000212// CHECK: [[g1_lpad]]
213// CHECK: br label %[[except:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +0000214
Nico Weberd9b8bd62015-02-25 17:44:04 +0000215// CHECK: [[except]]
Nico Weber5779f842015-02-12 23:16:11 +0000216// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() #3
217// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
218
Nico Weberd9b8bd62015-02-25 17:44:04 +0000219// CHECK: [[g2_cont]]
220// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +0000221// CHECK-NOT: store i32 23
Nico Weber5779f842015-02-12 23:16:11 +0000222
Nico Weberd9b8bd62015-02-25 17:44:04 +0000223// CHECK: [[g2_lpad]]
224// CHECK: br label %[[outerexcept:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +0000225
Nico Weberd9b8bd62015-02-25 17:44:04 +0000226// CHECK: [[outerexcept]]
227// CHECK-NEXT: br label %[[trycont4:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +0000228
Nico Weberd9b8bd62015-02-25 17:44:04 +0000229// CHECK: [[trycont4]]
230// CHECK-NEXT: ret i32 1
231
232// CHECK: [[trycont]]
Nico Weber5779f842015-02-12 23:16:11 +0000233// CHECK-NEXT: store i32 51, i32* %myres
Nico Weberd9b8bd62015-02-25 17:44:04 +0000234// CHECK-NEXT: br label %[[tryleave]]
Nico Weber5779f842015-02-12 23:16:11 +0000235
Nico Weberd9b8bd62015-02-25 17:44:04 +0000236// CHECK: [[tryleave]]
237// CHECK-NEXT: br label %[[trycont4]]
Nico Weber497bf552015-02-27 01:58:08 +0000238
239int nested___finally___except() {
240 int myres = 0;
241 __try {
242 __try {
243 g();
244 } __except (1) {
245 g();
246 __leave; // Refers to the outer __try, not the __except!
247 myres = 23;
248 return 0;
249 }
250
251 myres = 51;
252 } __finally {
253 }
254 return 1;
255}
256// The order of basic blocks in the below doesn't matter.
257// CHECK-LABEL: define i32 @nested___finally___except()
258
259// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)()
260// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
261
262// CHECK: [[g1_cont]]
263// CHECK-NEXT: br label %[[trycont:[^ ]*]]
264
265// CHECK: [[g1_lpad]]
266// CHECK: br label %[[except]]
267
268// CHECK: [[except]]
269// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)()
270// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
271
272// CHECK: [[g2_cont]]
273// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
274// CHECK-NOT: 23
275
276// CHECK: [[g2_lpad]]
277// CHECK: store i8 1, i8* %[[abnormal:[^ ]*]]
278// CHECK-NEXT: br label %[[finally:[^ ]*]]
279
280// CHECK: [[trycont]]
281// CHECK: store i32 51, i32* %
282// CHECK-NEXT: br label %[[tryleave]]
283
284// CHECK: [[tryleave]]
285// CHECK-NEXT: store i8 0, i8* %[[abnormal]]
286// CHECK-NEXT: br label %[[finally:[^ ]*]]
287
288// CHECK: [[finally]]
289// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8* %[[abnormal]]
290// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0
291// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]]
292
293// CHECK: [[finallycont]]
294// CHECK-NEXT: ret i32 1
295
296// CHECK: [[finallyresume]]
297// CHECK-NEXT: br label %[[ehresume:[^ ]*]]
298
299// CHECK: [[ehresume]]
300// CHECK: resume
301
Nico Weber5339a522015-02-27 02:26:14 +0000302int nested___finally___finally() {
303 int myres = 0;
304 __try {
305 __try {
306 g();
307 myres = 16;
308 } __finally {
309 g();
310 __leave; // Refers to the outer __try, not the __finally we're in!
311 myres = 23;
312 return 0;
313 }
314
315 myres = 51;
316 } __finally {
317 }
318 return 1;
319}
320// The order of basic blocks in the below doesn't matter.
321// CHECK-LABEL: define i32 @nested___finally___finally()
322
323// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)()
324// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
325
326// CHECK: [[g1_cont]]
327// CHECK: store i32 16, i32* %[[myres:[^ ]*]],
328// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]]
329// CHECK-NEXT: br label %[[finally:[^ ]*]]
330
331// CHECK: [[finally]]
332// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() #3
333// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
334
335// CHECK: [[g2_cont]]
336// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
337// CHECK-NOT: store i32 23
338
339// There's an unreachable block for the skipped `myres = 51`.
340// CHECK: store i32 51, i32* %[[myres]]
341// CHECK-NEXT: br label %[[tryleave]]
342
343// CHECK: [[tryleave]]
344// CHECK-NEXT: store i8 0, i8* %[[abnormal]]
345// CHECK-NEXT: br label %[[outerfinally:[^ ]*]]
346
347// CHECK: [[outerfinally]]
348// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8* %[[abnormal]]
349// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0
350// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]]
351
352// CHECK: [[finallycont]]
353// CHECK-NEXT: ret i32 1
354
355// CHECK: [[g1_lpad]]
356// CHECK: store i8 1, i8* %[[abnormal]]
357// CHECK-NEXT: br label %[[finally:[^ ]*]]
358
359// CHECK: [[g2_lpad]]
360// CHECK: br label %[[ehcleanup:[^ ]*]]
361
362// CHECK: [[ehcleanup]]
363// CHECK-NEXT: store i8 1, i8* %[[abnormal]]
364// CHECK-NEXT: br label %[[outerfinally]]
365
366// CHECK: [[finallyresume]]
367// CHECK-NEXT: br label %[[ehresume:[^ ]*]]
368
369// CHECK: [[ehresume]]
370// CHECK: resume