blob: 6366c35039075865afeb6cd359b71c6e1cb3e7d8 [file] [log] [blame]
Reid Kleckner65870442015-06-09 17:47:50 +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 Kleckner65870442015-06-09 17:47:50 +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 Kleckner65870442015-06-09 17:47:50 +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 Kleckner65870442015-06-09 17:47:50 +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 Kleckner65870442015-06-09 17:47:50 +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 Kleckner65870442015-06-09 17:47:50 +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 Kleckner65870442015-06-09 17:47:50 +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 Kleckner65870442015-06-09 17:47:50 +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 Kleckner65870442015-06-09 17:47:50 +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 Kleckner65870442015-06-09 17:47:50 +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: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
113// X86: %[[abnormal_i8:[^ ]*]] = call i8* @llvm.framerecover(i8* bitcast (void ()* @use_abnormal_termination to i8*), i8* %[[fp]], i32 0)
114// X86: %[[abnormal:[^ ]*]] = bitcast i8* %[[abnormal_i8]] to i32*
115// X86: %[[abnormal_zext:[^ ]*]] = load i32, i32* %[[abnormal]]
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000116// CHECK: store i32 %[[abnormal_zext]], i32* @crashed
117// CHECK-NEXT: ret void
118
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000119void noreturn_noop_finally() {
120 __try {
121 __noop();
122 } __finally {
123 abort();
124 }
125}
126
127// CHECK-LABEL: define void @noreturn_noop_finally()
Reid Kleckner65870442015-06-09 17:47:50 +0000128// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000129// CHECK: ret void
130
Reid Kleckner65870442015-06-09 17:47:50 +0000131// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000132// CHECK: call void @abort()
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000133// CHECK: unreachable
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000134
135void noreturn_finally() {
136 __try {
137 might_crash();
138 } __finally {
139 abort();
140 }
141}
142
143// CHECK-LABEL: define void @noreturn_finally()
144// CHECK: invoke void @might_crash()
145// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
146//
147// CHECK: [[cont]]
Reid Kleckner65870442015-06-09 17:47:50 +0000148// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000149// CHECK: ret void
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000150//
151// CHECK: [[lpad]]
152// CHECK: landingpad
153// CHECK-NEXT: cleanup
Reid Kleckner65870442015-06-09 17:47:50 +0000154// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000155// CHECK: resume { i8*, i32 }
156
Reid Kleckner65870442015-06-09 17:47:50 +0000157// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000158// CHECK: call void @abort()
159// CHECK: unreachable
Nico Webere68b9f32015-02-25 16:25:00 +0000160
161int finally_with_return() {
162 __try {
163 return 42;
164 } __finally {
165 }
166}
167// CHECK-LABEL: define i32 @finally_with_return()
Reid Kleckner65870442015-06-09 17:47:50 +0000168// CHECK: call void @"\01?fin$0@0@finally_with_return@@"({{.*}})
Nico Webere68b9f32015-02-25 16:25:00 +0000169// CHECK-NEXT: ret i32 42
170
Reid Kleckner65870442015-06-09 17:47:50 +0000171// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000172// CHECK-NOT: br i1
173// CHECK-NOT: br label
174// CHECK: ret void
175
Nico Webere68b9f32015-02-25 16:25:00 +0000176int nested___finally___finally() {
177 __try {
178 __try {
179 } __finally {
180 return 1;
181 }
182 } __finally {
183 // Intentionally no return here.
184 }
185 return 0;
186}
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000187
Nico Webere68b9f32015-02-25 16:25:00 +0000188// CHECK-LABEL: define i32 @nested___finally___finally
Reid Kleckner65870442015-06-09 17:47:50 +0000189// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000190// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
Nico Webere68b9f32015-02-25 16:25:00 +0000191//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000192// CHECK: [[outercont]]
Reid Kleckner65870442015-06-09 17:47:50 +0000193// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000194// CHECK-NEXT: ret i32 0
Nico Weberff62a6a2015-02-26 22:34:33 +0000195//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000196// CHECK: [[lpad]]
197// CHECK-NEXT: landingpad
198// CHECK-NEXT: cleanup
Reid Kleckner65870442015-06-09 17:47:50 +0000199// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000200
Reid Kleckner65870442015-06-09 17:47:50 +0000201// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000202// CHECK: ret void
203
Reid Kleckner65870442015-06-09 17:47:50 +0000204// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000205// CHECK: unreachable
Nico Weberff62a6a2015-02-26 22:34:33 +0000206
207int nested___finally___finally_with_eh_edge() {
208 __try {
209 __try {
210 might_crash();
211 } __finally {
212 return 899;
213 }
214 } __finally {
215 // Intentionally no return here.
216 }
217 return 912;
218}
219// CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000220// CHECK: invoke void @might_crash()
221// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000222//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000223// [[invokecont]]
Reid Kleckner65870442015-06-09 17:47:50 +0000224// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000225// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000226//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000227// CHECK: [[outercont]]
Reid Kleckner65870442015-06-09 17:47:50 +0000228// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000229// CHECK-NEXT: ret i32 912
Nico Weberff62a6a2015-02-26 22:34:33 +0000230//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000231// CHECK: [[lpad1]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000232// CHECK-NEXT: landingpad
233// CHECK-NEXT: cleanup
Reid Kleckner65870442015-06-09 17:47:50 +0000234// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000235// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000236//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000237// CHECK: [[lpad2]]
238// CHECK-NEXT: landingpad
239// CHECK-NEXT: cleanup
Reid Kleckner65870442015-06-09 17:47:50 +0000240// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Nico Weberff62a6a2015-02-26 22:34:33 +0000241// CHECK: resume
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000242
Reid Kleckner65870442015-06-09 17:47:50 +0000243// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000244// CHECK: ret void
245
Reid Kleckner65870442015-06-09 17:47:50 +0000246// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000247// CHECK: unreachable