blob: 087fadbcd7ab30e2ec7cad4b17efc40651eb4808 [file] [log] [blame]
David Majnemer4ff6f732016-02-20 09:23:41 +00001// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | opt -instnamer -S | FileCheck %s
Reid Kleckner1d59f992015-01-22 01:36:17 +00002
Reid Klecknerebaf28d2015-04-14 20:59:00 +00003void g(void);
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()
Reid Klecknerebaf28d2015-04-14 20:59:00 +000041// CHECK: invoke void @g()
Nico Weber5779f842015-02-12 23:16:11 +000042// 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]]
Reid Kleckner15d152d2015-07-07 23:23:31 +000077// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer2ccba832015-04-17 06:57:25 +000078// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_simple@@"(i8 0, i8* %[[fp]])
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]]
Reid Kleckner15d152d2015-07-07 23:23:31 +000097// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer2ccba832015-04-17 06:57:25 +000098// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_noreturn@@"(i8 0, i8* %[[fp]])
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()
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000113// CHECK: invoke void @g()
Nico Weber5779f842015-02-12 23:16:11 +0000114// 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]]
Reid Kleckner15d152d2015-07-07 23:23:31 +0000121// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer2ccba832015-04-17 06:57:25 +0000122// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally@@"(i8 0, i8* %[[fp]])
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}
Nico Weber5779f842015-02-12 23:16:11 +0000145// CHECK-LABEL: define i32 @nested___except___finally()
146
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000147// CHECK-LABEL: invoke void @g()
148// CHECK-NEXT: to label %[[g1_cont1:.*]] unwind label %[[g1_lpad:.*]]
Nico Weber5779f842015-02-12 23:16:11 +0000149
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000150// CHECK: [[g1_cont1]]
Reid Kleckner15d152d2015-07-07 23:23:31 +0000151// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer2ccba832015-04-17 06:57:25 +0000152// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i8 0, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000153// CHECK-NEXT: to label %[[fin_cont:.*]] unwind label %[[g2_lpad:.*]]
Nico Weber5779f842015-02-12 23:16:11 +0000154
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000155// CHECK: [[fin_cont]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000156// CHECK: store i32 51, i32* %
Nico Weberff62a6a2015-02-26 22:34:33 +0000157// CHECK-NEXT: br label %[[trycont:[^ ]*]]
158
Nico Weberd9b8bd62015-02-25 17:44:04 +0000159// CHECK: [[g1_lpad]]
Reid Kleckner129552b2015-10-08 01:13:52 +0000160// CHECK-NEXT: cleanuppad
161// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer2ccba832015-04-17 06:57:25 +0000162// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i8 1, i8* %[[fp]])
David Majnemer4e52d6f2015-12-12 05:39:21 +0000163// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[g2_lpad]]
Reid Kleckner129552b2015-10-08 01:13:52 +0000164// CHECK: cleanupret {{.*}} unwind label %[[g2_lpad]]
Nico Weber5779f842015-02-12 23:16:11 +0000165
Nico Weberd9b8bd62015-02-25 17:44:04 +0000166// CHECK: [[g2_lpad]]
David Majnemer4e52d6f2015-12-12 05:39:21 +0000167// CHECK: catchpad {{.*}} [i8* null]
Reid Kleckner129552b2015-10-08 01:13:52 +0000168// CHECK: catchret
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000169// CHECK: br label %[[trycont]]
Nico Weber5779f842015-02-12 23:16:11 +0000170
Nico Weberd9b8bd62015-02-25 17:44:04 +0000171// CHECK: [[trycont]]
172// CHECK-NEXT: ret i32 1
173
David Majnemer2ccba832015-04-17 06:57:25 +0000174// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___except___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000175// CHECK: call void @g()
176// CHECK: unreachable
177
Nico Weber5779f842015-02-12 23:16:11 +0000178int nested___except___except() {
179 int myres = 0;
180 __try {
181 __try {
182 g();
183 myres = 16;
184 } __except (1) {
185 g();
186 __leave; // Refers to the outer __try, not the __except we're in!
187 myres = 23;
188 return 0;
189 }
190
191 myres = 51;
192 } __except (1) {
193 }
194 return 1;
195}
196// The order of basic blocks in the below doesn't matter.
197// CHECK-LABEL: define i32 @nested___except___except()
198
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000199// CHECK-LABEL: invoke void @g()
Nico Weber5779f842015-02-12 23:16:11 +0000200// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
201
Nico Weberd9b8bd62015-02-25 17:44:04 +0000202// CHECK: [[g1_lpad]]
David Majnemer4e52d6f2015-12-12 05:39:21 +0000203// CHECK: catchpad {{.*}} [i8* null]
Reid Kleckner129552b2015-10-08 01:13:52 +0000204// CHECK: catchret {{.*}} to label %[[except:[^ ]*]]
Nico Weberd9b8bd62015-02-25 17:44:04 +0000205// CHECK: [[except]]
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000206// CHECK: invoke void @g()
Nico Weber5779f842015-02-12 23:16:11 +0000207// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
208
Reid Kleckner129552b2015-10-08 01:13:52 +0000209// CHECK: [[g2_lpad]]
David Majnemer4e52d6f2015-12-12 05:39:21 +0000210// CHECK: catchpad {{.*}} [i8* null]
Reid Kleckner129552b2015-10-08 01:13:52 +0000211// CHECK: catchret
212// CHECK: br label %[[trycont4:[^ ]*]]
213
214// CHECK: [[trycont4]]
215// CHECK-NEXT: ret i32 1
216
Nico Weberd9b8bd62015-02-25 17:44:04 +0000217// CHECK: [[g2_cont]]
218// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
Nico Weber5779f842015-02-12 23:16:11 +0000219// CHECK-NOT: store i32 23
Nico Weber5779f842015-02-12 23:16:11 +0000220
Reid Kleckner129552b2015-10-08 01:13:52 +0000221// CHECK: [[g1_cont]]
222// CHECK: store i32 16, i32* %myres
223// CHECK-NEXT: br label %[[trycont:[^ ]*]]
Nico Weberd9b8bd62015-02-25 17:44:04 +0000224
225// CHECK: [[trycont]]
Nico Weber5779f842015-02-12 23:16:11 +0000226// CHECK-NEXT: store i32 51, i32* %myres
Nico Weberd9b8bd62015-02-25 17:44:04 +0000227// CHECK-NEXT: br label %[[tryleave]]
Nico Weber5779f842015-02-12 23:16:11 +0000228
Nico Weberd9b8bd62015-02-25 17:44:04 +0000229// CHECK: [[tryleave]]
230// CHECK-NEXT: br label %[[trycont4]]
Nico Weber6bdd9b02015-02-27 16:40:43 +0000231
232int nested___finally___except() {
233 int myres = 0;
234 __try {
235 __try {
236 g();
237 } __except (1) {
238 g();
239 __leave; // Refers to the outer __try, not the __except!
240 myres = 23;
241 return 0;
242 }
243
244 myres = 51;
245 } __finally {
246 }
247 return 1;
248}
249// The order of basic blocks in the below doesn't matter.
250// CHECK-LABEL: define i32 @nested___finally___except()
251
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000252// CHECK-LABEL: invoke void @g()
Nico Weber6bdd9b02015-02-27 16:40:43 +0000253// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
254
Nico Weber6bdd9b02015-02-27 16:40:43 +0000255// CHECK: [[g1_lpad]]
Reid Kleckner129552b2015-10-08 01:13:52 +0000256// CHECK: catchpad
257// CHECK: catchret
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000258// CHECK: invoke void @g()
Nico Weber6bdd9b02015-02-27 16:40:43 +0000259// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
260
261// CHECK: [[g2_cont]]
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000262// CHECK: br label %[[tryleave:[^ ]*]]
Nico Weber6bdd9b02015-02-27 16:40:43 +0000263// CHECK-NOT: 23
264
Reid Kleckner129552b2015-10-08 01:13:52 +0000265// CHECK: [[g1_cont]]
266// CHECK-NEXT: br label %[[trycont:[^ ]*]]
Nico Weber6bdd9b02015-02-27 16:40:43 +0000267
268// CHECK: [[trycont]]
269// CHECK: store i32 51, i32* %
270// CHECK-NEXT: br label %[[tryleave]]
271
272// CHECK: [[tryleave]]
Reid Kleckner15d152d2015-07-07 23:23:31 +0000273// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer2ccba832015-04-17 06:57:25 +0000274// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i8 0, i8* %[[fp]])
Nico Weber6bdd9b02015-02-27 16:40:43 +0000275// CHECK-NEXT: ret i32 1
276
Reid Kleckner129552b2015-10-08 01:13:52 +0000277// CHECK: [[g2_lpad]]
278// CHECK: cleanuppad
279// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer4e52d6f2015-12-12 05:39:21 +0000280// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]])
Reid Kleckner129552b2015-10-08 01:13:52 +0000281// CHECK: cleanupret {{.*}} unwind to caller
Nico Weber6bdd9b02015-02-27 16:40:43 +0000282
David Majnemer2ccba832015-04-17 06:57:25 +0000283// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___except@@"(i8 %abnormal_termination, i8* %frame_pointer)
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000284// CHECK: ret void
285
Nico Weber6bdd9b02015-02-27 16:40:43 +0000286int nested___finally___finally() {
287 int myres = 0;
288 __try {
289 __try {
290 g();
291 myres = 16;
292 } __finally {
293 g();
294 __leave; // Refers to the outer __try, not the __finally we're in!
295 myres = 23;
296 return 0;
297 }
298
299 myres = 51;
300 } __finally {
301 }
302 return 1;
303}
304// The order of basic blocks in the below doesn't matter.
305// CHECK-LABEL: define i32 @nested___finally___finally()
306
Reid Kleckner129552b2015-10-08 01:13:52 +0000307// CHECK: invoke void @g()
Nico Weber6bdd9b02015-02-27 16:40:43 +0000308// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
309
310// CHECK: [[g1_cont]]
311// CHECK: store i32 16, i32* %[[myres:[^ ]*]],
Reid Kleckner15d152d2015-07-07 23:23:31 +0000312// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer2ccba832015-04-17 06:57:25 +0000313// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000314// CHECK-NEXT: to label %[[finally_cont:.*]] unwind label %[[g2_lpad:.*]]
Nico Weber6bdd9b02015-02-27 16:40:43 +0000315
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000316// CHECK: [[finally_cont]]
Nico Weber6bdd9b02015-02-27 16:40:43 +0000317// CHECK: store i32 51, i32* %[[myres]]
Reid Kleckner15d152d2015-07-07 23:23:31 +0000318// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer2ccba832015-04-17 06:57:25 +0000319// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
Nico Weber6bdd9b02015-02-27 16:40:43 +0000320// CHECK-NEXT: ret i32 1
321
322// CHECK: [[g1_lpad]]
David Majnemer4e52d6f2015-12-12 05:39:21 +0000323// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none []
Reid Kleckner129552b2015-10-08 01:13:52 +0000324// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer2ccba832015-04-17 06:57:25 +0000325// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
David Majnemer4e52d6f2015-12-12 05:39:21 +0000326// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[g2_lpad]]
Reid Kleckner129552b2015-10-08 01:13:52 +0000327// CHECK: [[finally_cont2]]
David Majnemer4e52d6f2015-12-12 05:39:21 +0000328// CHECK: cleanupret from %[[padtoken]] unwind label %[[g2_lpad]]
Nico Weber6bdd9b02015-02-27 16:40:43 +0000329
330// CHECK: [[g2_lpad]]
David Majnemer4e52d6f2015-12-12 05:39:21 +0000331// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none []
Reid Kleckner129552b2015-10-08 01:13:52 +0000332// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer4e52d6f2015-12-12 05:39:21 +0000333// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
334// CHECK: cleanupret from %[[padtoken]] unwind to caller
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000335
David Majnemer2ccba832015-04-17 06:57:25 +0000336// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000337// CHECK: ret void
338
David Majnemer2ccba832015-04-17 06:57:25 +0000339// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000340// CHECK: call void @g()
341// CHECK: unreachable