blob: ad90e4d2b4abf37dcedd2aa68fcea4a37f66ea4f [file] [log] [blame]
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +00001// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - \
2// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X64
3// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - \
4// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X86
Reid Kleckner1d59f992015-01-22 01:36:17 +00005
Reid Kleckner16f9a6b2015-02-05 00:58:46 +00006void abort(void) __attribute__((noreturn));
Reid Kleckner1d59f992015-01-22 01:36:17 +00007void might_crash(void);
8void cleanup(void);
9int check_condition(void);
10void basic_finally(void) {
11 __try {
12 might_crash();
13 } __finally {
14 cleanup();
15 }
16}
17
18// CHECK-LABEL: define void @basic_finally()
19// CHECK: invoke void @might_crash()
Reid Kleckneraca01db2015-02-04 22:37:07 +000020// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
21//
22// CHECK: [[invoke_cont]]
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +000023// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
24// X64: call void @"\01?fin$0@0@basic_finally@@"(i8 0, i8* %[[fp]])
25// X86: call void @"\01?fin$0@0@basic_finally@@"()
Reid Kleckneraca01db2015-02-04 22:37:07 +000026// CHECK-NEXT: ret void
27//
28// CHECK: [[lpad]]
29// CHECK-NEXT: landingpad
Reid Kleckner1d59f992015-01-22 01:36:17 +000030// CHECK-NEXT: cleanup
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +000031// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
32// X64: call void @"\01?fin$0@0@basic_finally@@"(i8 1, i8* %[[fp]])
33// X86: call void @"\01?fin$0@0@basic_finally@@"()
Reid Kleckneraca01db2015-02-04 22:37:07 +000034// CHECK: resume { i8*, i32 }
Reid Kleckner1d59f992015-01-22 01:36:17 +000035
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +000036// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +000037// CHECK: call void @cleanup()
38
Reid Kleckneraca01db2015-02-04 22:37:07 +000039// Mostly check that we don't double emit 'r' which would crash.
40void decl_in_finally(void) {
41 __try {
42 might_crash();
43 } __finally {
44 int r;
45 }
46}
47
48// Ditto, don't crash double emitting 'l'.
49void label_in_finally(void) {
Reid Kleckner1d59f992015-01-22 01:36:17 +000050 __try {
51 might_crash();
52 } __finally {
53l:
54 cleanup();
55 if (check_condition())
56 goto l;
57 }
58}
Reid Kleckneraca01db2015-02-04 22:37:07 +000059
60// CHECK-LABEL: define void @label_in_finally()
61// CHECK: invoke void @might_crash()
62// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
63//
64// CHECK: [[invoke_cont]]
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +000065// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
66// X64: call void @"\01?fin$0@0@label_in_finally@@"(i8 0, i8* %[[fp]])
67// X86: call void @"\01?fin$0@0@label_in_finally@@"()
Reid Klecknerebaf28d2015-04-14 20:59:00 +000068// CHECK: ret void
69
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +000070// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"({{.*}})
Reid Kleckneraca01db2015-02-04 22:37:07 +000071// CHECK: br label %[[l:[^ ]*]]
72//
73// CHECK: [[l]]
74// CHECK: call void @cleanup()
75// CHECK: call i32 @check_condition()
76// CHECK: br i1 {{.*}}, label
77// CHECK: br label %[[l]]
78
79int crashed;
80void use_abnormal_termination(void) {
81 __try {
82 might_crash();
83 } __finally {
84 crashed = __abnormal_termination();
85 }
86}
87
88// CHECK-LABEL: define void @use_abnormal_termination()
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +000089// X86: call void (...) @llvm.frameescape(i32* %[[abnormal_termination:[^ ),]*]])
90// X86: store i32 1, i32* %[[abnormal_termination]]
Reid Kleckneraca01db2015-02-04 22:37:07 +000091// CHECK: invoke void @might_crash()
92// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
93//
94// CHECK: [[invoke_cont]]
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +000095// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
96// X64: call void @"\01?fin$0@0@use_abnormal_termination@@"(i8 0, i8* %[[fp]])
97// X86: store i32 0, i32* %[[abnormal_termination]]
98// X86: call void @"\01?fin$0@0@use_abnormal_termination@@"()
Reid Klecknerebaf28d2015-04-14 20:59:00 +000099// CHECK: ret void
Reid Kleckneraca01db2015-02-04 22:37:07 +0000100//
101// CHECK: [[lpad]]
102// CHECK-NEXT: landingpad
103// CHECK-NEXT: cleanup
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000104// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
105// X64: call void @"\01?fin$0@0@use_abnormal_termination@@"(i8 1, i8* %[[fp]])
106// X86: call void @"\01?fin$0@0@use_abnormal_termination@@"()
Reid Kleckneraca01db2015-02-04 22:37:07 +0000107// CHECK: resume { i8*, i32 }
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000108
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000109// X64: define internal void @"\01?fin$0@0@use_abnormal_termination@@"(i8 %[[abnormal:abnormal_termination]], i8* %frame_pointer)
110// X64: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
111// X86: define internal void @"\01?fin$0@0@use_abnormal_termination@@"()
112// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
113// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @use_abnormal_termination to i8*), i8* %[[ebp]])
114// X86: %[[abnormal_i8:[^ ]*]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @use_abnormal_termination to i8*), i8* %[[fp]], i32 0)
115// X86: %[[abnormal:[^ ]*]] = bitcast i8* %[[abnormal_i8]] to i32*
116// X86: %[[abnormal_zext:[^ ]*]] = load i32, i32* %[[abnormal]]
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000117// CHECK: store i32 %[[abnormal_zext]], i32* @crashed
118// CHECK-NEXT: ret void
119
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000120void noreturn_noop_finally() {
121 __try {
122 __noop();
123 } __finally {
124 abort();
125 }
126}
127
128// CHECK-LABEL: define void @noreturn_noop_finally()
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000129// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000130// CHECK: ret void
131
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000132// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000133// CHECK: call void @abort()
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000134// CHECK: unreachable
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000135
136void noreturn_finally() {
137 __try {
138 might_crash();
139 } __finally {
140 abort();
141 }
142}
143
144// CHECK-LABEL: define void @noreturn_finally()
145// CHECK: invoke void @might_crash()
146// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
147//
148// CHECK: [[cont]]
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000149// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000150// CHECK: ret void
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000151//
152// CHECK: [[lpad]]
153// CHECK: landingpad
154// CHECK-NEXT: cleanup
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000155// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000156// CHECK: resume { i8*, i32 }
157
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000158// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000159// CHECK: call void @abort()
160// CHECK: unreachable
Nico Webere68b9f32015-02-25 16:25:00 +0000161
162int finally_with_return() {
163 __try {
164 return 42;
165 } __finally {
166 }
167}
168// CHECK-LABEL: define i32 @finally_with_return()
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000169// CHECK: call void @"\01?fin$0@0@finally_with_return@@"({{.*}})
Nico Webere68b9f32015-02-25 16:25:00 +0000170// CHECK-NEXT: ret i32 42
171
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000172// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000173// CHECK-NOT: br i1
174// CHECK-NOT: br label
175// CHECK: ret void
176
Nico Webere68b9f32015-02-25 16:25:00 +0000177int nested___finally___finally() {
178 __try {
179 __try {
180 } __finally {
181 return 1;
182 }
183 } __finally {
184 // Intentionally no return here.
185 }
186 return 0;
187}
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000188
Nico Webere68b9f32015-02-25 16:25:00 +0000189// CHECK-LABEL: define i32 @nested___finally___finally
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000190// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000191// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
Nico Webere68b9f32015-02-25 16:25:00 +0000192//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000193// CHECK: [[outercont]]
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000194// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000195// CHECK-NEXT: ret i32 0
Nico Weberff62a6a2015-02-26 22:34:33 +0000196//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000197// CHECK: [[lpad]]
198// CHECK-NEXT: landingpad
199// CHECK-NEXT: cleanup
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000200// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000201
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000202// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000203// CHECK: ret void
204
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000205// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000206// CHECK: unreachable
Nico Weberff62a6a2015-02-26 22:34:33 +0000207
208int nested___finally___finally_with_eh_edge() {
209 __try {
210 __try {
211 might_crash();
212 } __finally {
213 return 899;
214 }
215 } __finally {
216 // Intentionally no return here.
217 }
218 return 912;
219}
220// CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000221// CHECK: invoke void @might_crash()
222// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000223//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000224// [[invokecont]]
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000225// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000226// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000227//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000228// CHECK: [[outercont]]
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000229// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000230// CHECK-NEXT: ret i32 912
Nico Weberff62a6a2015-02-26 22:34:33 +0000231//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000232// CHECK: [[lpad1]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000233// CHECK-NEXT: landingpad
234// CHECK-NEXT: cleanup
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000235// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000236// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000237//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000238// CHECK: [[lpad2]]
239// CHECK-NEXT: landingpad
240// CHECK-NEXT: cleanup
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000241// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Nico Weberff62a6a2015-02-26 22:34:33 +0000242// CHECK: resume
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000243
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000244// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000245// CHECK: ret void
246
Reid Klecknerd0d9a1f2015-07-01 17:10:10 +0000247// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000248// CHECK: unreachable