[AMDGPU][True16][CodeGen] true16 codegen pattern for v_med3_u/i16 (#121850)
[llvm-project.git] / clang / test / CodeGenCXX / wasm-eh.cpp
blob9dc15633bfed949a865836d12300f8c74e798808
1 // REQUIRES: webassembly-registered-target
3 // RUN: %clang -E -dM %s -target wasm32-unknown-unknown -fwasm-exceptions | FileCheck %s -check-prefix PREPROCESSOR
4 // PREPROCESSOR: #define __WASM_EXCEPTIONS__ 1
6 // RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -mllvm -wasm-enable-eh -exception-model=wasm -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s
7 // RUN: %clang_cc1 %s -triple wasm64-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -mllvm -wasm-enable-eh -exception-model=wasm -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s
9 void may_throw();
10 void dont_throw() noexcept;
12 struct Cleanup {
13 ~Cleanup() { dont_throw(); }
16 // Multiple catch clauses w/o catch-all
17 void test0() {
18 try {
19 may_throw();
20 } catch (int) {
21 dont_throw();
22 } catch (double) {
23 dont_throw();
27 // CHECK-LABEL: define void @_Z5test0v() {{.*}} personality ptr @__gxx_wasm_personality_v0
29 // CHECK: %[[INT_ALLOCA:.*]] = alloca i32
30 // CHECK: invoke void @_Z9may_throwv()
31 // CHECK-NEXT: to label %[[NORMAL_BB:.*]] unwind label %[[CATCHDISPATCH_BB:.*]]
33 // CHECK: [[CATCHDISPATCH_BB]]:
34 // CHECK-NEXT: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller
36 // CHECK: [[CATCHSTART_BB]]:
37 // CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [ptr @_ZTIi, ptr @_ZTId]
38 // CHECK-NEXT: %[[EXN:.*]] = call ptr @llvm.wasm.get.exception(token %[[CATCHPAD]])
39 // CHECK-NEXT: store ptr %[[EXN]], ptr %exn.slot
40 // CHECK-NEXT: %[[SELECTOR:.*]] = call i32 @llvm.wasm.get.ehselector(token %[[CATCHPAD]])
41 // CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #7
42 // CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]]
43 // CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_INT_BB:.*]], label %[[CATCH_FALLTHROUGH_BB:.*]]
45 // CHECK: [[CATCH_INT_BB]]:
46 // CHECK-NEXT: %[[EXN:.*]] = load ptr, ptr %exn.slot
47 // CHECK-NEXT: %[[ADDR:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN]]) {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
48 // CHECK-NEXT: %[[INT_VAL:.*]] = load i32, ptr %[[ADDR]]
49 // CHECK-NEXT: store i32 %[[INT_VAL]], ptr %[[INT_ALLOCA]]
50 // CHECK-NEXT: call void @_Z10dont_throwv() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
51 // CHECK-NEXT: call void @__cxa_end_catch() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
52 // CHECK-NEXT: catchret from %[[CATCHPAD]] to label %[[CATCHRET_DEST_BB0:.*]]
54 // CHECK: [[CATCHRET_DEST_BB0]]:
55 // CHECK-NEXT: br label %[[TRY_CONT_BB:.*]]
57 // CHECK: [[CATCH_FALLTHROUGH_BB]]
58 // CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTId) #7
59 // CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]]
60 // CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_FLOAT_BB:.*]], label %[[RETHROW_BB:.*]]
62 // CHECK: [[CATCH_FLOAT_BB]]:
63 // CHECK: catchret from %[[CATCHPAD]] to label %[[CATCHRET_DEST_BB1:.*]]
65 // CHECK: [[CATCHRET_DEST_BB1]]:
66 // CHECK-NEXT: br label %[[TRY_CONT_BB]]
68 // CHECK: [[RETHROW_BB]]:
69 // CHECK-NEXT: call void @llvm.wasm.rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
70 // CHECK-NEXT: unreachable
72 // Single catch-all
73 void test1() {
74 try {
75 may_throw();
76 } catch (...) {
77 dont_throw();
81 // CATCH-LABEL: @_Z5test1v()
83 // CHECK: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller
85 // CHECK: [[CATCHSTART_BB]]:
86 // CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [ptr null]
87 // CHECK: br label %[[CATCH_ALL_BB:.*]]
89 // CHECK: [[CATCH_ALL_BB]]:
90 // CHECK: catchret from %[[CATCHPAD]] to label
92 // Multiple catch clauses w/ catch-all
93 void test2() {
94 try {
95 may_throw();
96 } catch (int) {
97 dont_throw();
98 } catch (...) {
99 dont_throw();
103 // CHECK-LABEL: @_Z5test2v()
105 // CHECK: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller
107 // CHECK: [[CATCHSTART_BB]]:
108 // CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [ptr @_ZTIi, ptr null]
109 // CHECK: br i1 %{{.*}}, label %[[CATCH_INT_BB:.*]], label %[[CATCH_ALL_BB:.*]]
111 // CHECK: [[CATCH_INT_BB]]:
112 // CHECK: catchret from %[[CATCHPAD]] to label
114 // CHECK: [[CATCH_ALL_BB]]:
115 // CHECK: catchret from %[[CATCHPAD]] to label
117 // Cleanup
118 void test3() {
119 Cleanup c;
120 may_throw();
123 // CHECK-LABEL: @_Z5test3v()
125 // CHECK: invoke void @_Z9may_throwv()
126 // CHECK-NEXT: to label {{.*}} unwind label %[[EHCLEANUP_BB:.*]]
128 // CHECK: [[EHCLEANUP_BB]]:
129 // CHECK-NEXT: %[[CLEANUPPAD:.*]] = cleanuppad within none []
130 // CHECK-NEXT: call noundef ptr @_ZN7CleanupD1Ev(ptr {{[^,]*}} %{{.*}}) {{.*}} [ "funclet"(token %[[CLEANUPPAD]]) ]
131 // CHECK-NEXT: cleanupret from %[[CLEANUPPAD]] unwind to caller
133 // Possibly throwing function call within a catch
134 void test4() {
135 try {
136 may_throw();
137 } catch (int) {
138 may_throw();
142 // CHECK-LABEL: @_Z5test4v()
144 // CHECK: %[[CATCHSWITCH]] = catchswitch within none [label %[[CATCHSTART_BB]]] unwind to caller
146 // CHECK: [[CATCHSTART_BB]]:
147 // CHECK: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [ptr @_ZTIi]
149 // CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD]]) ]
150 // CHECK-NEXT: to label %[[INVOKE_CONT_BB:.*]] unwind label %[[EHCLEANUP_BB:.*]]
152 // CHECK: [[INVOKE_CONT_BB]]:
153 // CHECK-NEXT: call void @__cxa_end_catch() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
154 // CHECK-NEXT: catchret from %[[CATCHPAD]] to label
156 // CHECK: [[EHCLEANUP_BB]]:
157 // CHECK-NEXT: %[[CLEANUPPAD:.*]] = cleanuppad within %[[CATCHPAD]] []
158 // CHECK-NEXT: call void @__cxa_end_catch() {{.*}} [ "funclet"(token %[[CLEANUPPAD]]) ]
159 // CHECK-NEXT: cleanupret from %[[CLEANUPPAD]] unwind to caller
161 // Possibly throwing function call within a catch-all
162 void test5() {
163 try {
164 may_throw();
165 } catch (...) {
166 may_throw();
170 // CHECK-LABEL: @_Z5test5v()
172 // CHECK: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB]]] unwind to caller
174 // CHECK: [[CATCHSTART_BB]]:
175 // CHECK: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [ptr null]
177 // CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD]]) ]
178 // CHECK-NEXT: to label %[[INVOKE_CONT_BB0:.*]] unwind label %[[EHCLEANUP_BB:.*]]
180 // CHECK: [[INVOKE_CONT_BB0]]:
181 // CHECK-NEXT: call void @__cxa_end_catch() [ "funclet"(token %[[CATCHPAD]]) ]
182 // CHECK-NEXT: catchret from %[[CATCHPAD]] to label
184 // CHECK: [[EHCLEANUP_BB]]:
185 // CHECK-NEXT: %[[CLEANUPPAD0:.*]] = cleanuppad within %[[CATCHPAD]] []
186 // CHECK-NEXT: invoke void @__cxa_end_catch() [ "funclet"(token %[[CLEANUPPAD0]]) ]
187 // CHECK-NEXT: to label %[[INVOKE_CONT_BB1:.*]] unwind label %[[TERMINATE_BB:.*]]
189 // CHECK: [[INVOKE_CONT_BB1]]:
190 // CHECK-NEXT: cleanupret from %[[CLEANUPPAD0]] unwind to caller
192 // CHECK: [[TERMINATE_BB]]:
193 // CHECK-NEXT: %[[CLEANUPPAD1:.*]] = cleanuppad within %[[CLEANUPPAD0]] []
194 // CHECK-NEXT: call void @_ZSt9terminatev() {{.*}} [ "funclet"(token %[[CLEANUPPAD1]]) ]
195 // CHECK-NEXT: unreachable
197 // Try-catch with cleanups
198 void test6() {
199 Cleanup c1;
200 try {
201 Cleanup c2;
202 may_throw();
203 } catch (int) {
204 Cleanup c3;
205 may_throw();
209 // CHECK-LABEL: @_Z5test6v()
210 // CHECK: invoke void @_Z9may_throwv()
211 // CHECK-NEXT: to label %{{.*}} unwind label %[[EHCLEANUP_BB0:.*]]
213 // CHECK: [[EHCLEANUP_BB0]]:
214 // CHECK-NEXT: %[[CLEANUPPAD0:.*]] = cleanuppad within none []
215 // CHECK-NEXT: call noundef ptr @_ZN7CleanupD1Ev(ptr {{.*}}) {{.*}} [ "funclet"(token %[[CLEANUPPAD0]]) ]
216 // CHECK-NEXT: cleanupret from %[[CLEANUPPAD0]] unwind label %[[CATCH_DISPATCH_BB:.*]]
218 // CHECK: [[CATCH_DISPATCH_BB]]:
219 // CHECK-NEXT: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind label %[[EHCLEANUP_BB1:.*]]
221 // CHECK: [[CATCHSTART_BB]]:
222 // CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [ptr @_ZTIi]
223 // CHECK: br i1 %{{.*}}, label %[[CATCH_INT_BB:.*]], label %[[RETHROW_BB:.*]]
225 // CHECK: [[CATCH_INT_BB]]:
226 // CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD]]) ]
227 // CHECK-NEXT: to label %[[INVOKE_CONT_BB:.*]] unwind label %[[EHCLEANUP_BB2:.*]]
229 // CHECK: [[INVOKE_CONT_BB]]:
230 // CHECK: catchret from %[[CATCHPAD]] to label %{{.*}}
232 // CHECK: [[RETHROW_BB]]:
233 // CHECK-NEXT: invoke void @llvm.wasm.rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
234 // CHECK-NEXT: to label %[[UNREACHABLE_BB:.*]] unwind label %[[EHCLEANUP_BB1:.*]]
236 // CHECK: [[EHCLEANUP_BB2]]:
237 // CHECK-NEXT: %[[CLEANUPPAD2:.*]] = cleanuppad within %[[CATCHPAD]] []
238 // CHECK-NEXT: call noundef ptr @_ZN7CleanupD1Ev(ptr {{[^,]*}} %{{.*}}) {{.*}} [ "funclet"(token %[[CLEANUPPAD2]]) ]
239 // CHECK-NEXT: cleanupret from %[[CLEANUPPAD2]] unwind label %[[EHCLEANUP_BB3:.*]]
241 // CHECK: [[EHCLEANUP_BB3]]:
242 // CHECK-NEXT: %[[CLEANUPPAD3:.*]] = cleanuppad within %[[CATCHPAD]] []
243 // CHECK: cleanupret from %[[CLEANUPPAD3]] unwind label %[[EHCLEANUP_BB1:.*]]
245 // CHECK: [[EHCLEANUP_BB1]]:
246 // CHECK-NEXT: %[[CLEANUPPAD1:.*]] = cleanuppad within none []
247 // CHECK-NEXT: call noundef ptr @_ZN7CleanupD1Ev(ptr {{[^,]*}} %{{.*}}) {{.*}} [ "funclet"(token %[[CLEANUPPAD1]]) ]
248 // CHECK-NEXT: cleanupret from %[[CLEANUPPAD1]] unwind to caller
250 // CHECK: [[UNREACHABLE_BB]]:
251 // CHECK-NEXT: unreachable
253 // Nested try-catches within a try with cleanups
254 void test7() {
255 Cleanup c1;
256 may_throw();
257 try {
258 Cleanup c2;
259 may_throw();
260 try {
261 Cleanup c3;
262 may_throw();
263 } catch (int) {
264 may_throw();
265 } catch (double) {
266 may_throw();
268 } catch (int) {
269 may_throw();
270 } catch (...) {
271 may_throw();
275 // CHECK-LABEL: @_Z5test7v()
276 // CHECK: invoke void @_Z9may_throwv()
278 // CHECK: invoke void @_Z9may_throwv()
280 // CHECK: invoke void @_Z9may_throwv()
282 // CHECK: %[[CLEANUPPAD0:.*]] = cleanuppad within none []
283 // CHECK: cleanupret from %[[CLEANUPPAD0]] unwind label
285 // CHECK: %[[CATCHSWITCH0:.*]] = catchswitch within none
287 // CHECK: %[[CATCHPAD0:.*]] = catchpad within %[[CATCHSWITCH0]] [ptr @_ZTIi, ptr @_ZTId]
289 // CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD0]]) ]
291 // CHECK: catchret from %[[CATCHPAD0]] to label
293 // CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD0]]) ]
295 // CHECK: catchret from %[[CATCHPAD0]] to label
297 // CHECK: invoke void @llvm.wasm.rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD0]]) ]
299 // CHECK: %[[CLEANUPPAD1:.*]] = cleanuppad within %[[CATCHPAD0]] []
300 // CHECK: cleanupret from %[[CLEANUPPAD1]] unwind label
302 // CHECK: %[[CLEANUPPAD2:.*]] = cleanuppad within %[[CATCHPAD0]] []
303 // CHECK: cleanupret from %[[CLEANUPPAD2]] unwind label
305 // CHECK: %[[CLEANUPPAD3:.*]] = cleanuppad within none []
306 // CHECK: cleanupret from %[[CLEANUPPAD3]] unwind label
308 // CHECK: %[[CATCHSWITCH1:.*]] = catchswitch within none
310 // CHECK: %[[CATCHPAD1:.*]] = catchpad within %[[CATCHSWITCH1]] [ptr @_ZTIi, ptr null]
312 // CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD1]]) ]
314 // CHECK: catchret from %[[CATCHPAD1]] to label
316 // CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD1]]) ]
318 // CHECK: invoke void @__cxa_end_catch() [ "funclet"(token %[[CATCHPAD1]]) ]
320 // CHECK: catchret from %[[CATCHPAD1]] to label
322 // CHECK: %[[CLEANUPPAD4:.*]] = cleanuppad within %[[CATCHPAD1]] []
323 // CHECK: invoke void @__cxa_end_catch() [ "funclet"(token %[[CLEANUPPAD4]]) ]
325 // CHECK: cleanupret from %[[CLEANUPPAD4]] unwind label
327 // CHECK: %[[CLEANUPPAD5:.*]] = cleanuppad within %[[CATCHPAD1]] []
328 // CHECK: cleanupret from %[[CLEANUPPAD5]] unwind label
330 // CHECK: %[[CLEANUPPAD6:.*]] = cleanuppad within none []
331 // CHECK: cleanupret from %[[CLEANUPPAD6]] unwind to caller
333 // CHECK: unreachable
335 // CHECK: %[[CLEANUPPAD7:.*]] = cleanuppad within %[[CLEANUPPAD4]] []
336 // CHECK: call void @_ZSt9terminatev() {{.*}} [ "funclet"(token %[[CLEANUPPAD7]]) ]
337 // CHECK: unreachable
339 // Nested try-catches within a catch
340 void test8() {
341 try {
342 may_throw();
343 } catch (int) {
344 try {
345 may_throw();
346 } catch (int) {
347 may_throw();
352 // CHECK-LABEL: @_Z5test8v()
353 // CHECK: invoke void @_Z9may_throwv()
355 // CHECK: %[[CATCHSWITCH0:.*]] = catchswitch within none
357 // CHECK: %[[CATCHPAD0:.*]] = catchpad within %[[CATCHSWITCH0]] [ptr @_ZTIi]
359 // CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD0]]) ]
361 // CHECK: %[[CATCHSWITCH1:.*]] = catchswitch within %[[CATCHPAD0]]
363 // CHECK: %[[CATCHPAD1:.*]] = catchpad within %[[CATCHSWITCH1]] [ptr @_ZTIi]
365 // CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD1]]) ]
367 // CHECK: catchret from %[[CATCHPAD1]] to label
369 // CHECK: invoke void @llvm.wasm.rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD1]]) ]
371 // CHECK: catchret from %[[CATCHPAD0]] to label
373 // CHECK: call void @llvm.wasm.rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD0]]) ]
374 // CHECK: unreachable
376 // CHECK: %[[CLEANUPPAD0:.*]] = cleanuppad within %[[CATCHPAD1]] []
377 // CHECK: cleanupret from %[[CLEANUPPAD0]] unwind label
379 // CHECK: %[[CLEANUPPAD1:.*]] = cleanuppad within %[[CATCHPAD0]] []
380 // CHECK: cleanupret from %[[CLEANUPPAD1]] unwind to caller
382 // CHECK: unreachable
384 // RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -exception-model=wasm -target-feature +exception-handling -emit-llvm -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=WARNING-DEFAULT
385 // RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -exception-model=wasm -target-feature +exception-handling -Wwasm-exception-spec -emit-llvm -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=WARNING-ON
386 // RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -exception-model=wasm -target-feature +exception-handling -Wno-wasm-exception-spec -emit-llvm -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=WARNING-OFF
387 // RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fexceptions -fcxx-exceptions -emit-llvm -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=EM-EH-WARNING
389 // Wasm EH ignores dynamic exception specifications with types at the moment.
390 // This is controlled by -Wwasm-exception-spec, which is on by default. This
391 // warning can be suppressed with -Wno-wasm-exception-spec. Checks if a warning
392 // message is correctly printed or not printed depending on the options.
393 void test9() throw(int) {
395 // WARNING-DEFAULT: warning: dynamic exception specifications with types are currently ignored in wasm
396 // WARNING-ON: warning: dynamic exception specifications with types are currently ignored in wasm
397 // WARNING-OFF-NOT: warning: dynamic exception specifications with types are currently ignored in wasm
398 // EM-EH-WARNING: warning: dynamic exception specifications with types are currently ignored in wasm
400 // Wasm curremtly treats 'throw()' in the same way as 'noexept'. Check if the
401 // same warning message is printed as if when a 'noexcept' function throws.
402 void test10() throw() {
403 throw 3;
405 // WARNING-DEFAULT: warning: 'test10' has a non-throwing exception specification but can still throw
406 // WARNING-DEFAULT: function declared non-throwing here
408 // Here we only check if the command enables wasm exception handling in the
409 // backend so that exception handling instructions can be generated in .s file.
411 // RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -mllvm -wasm-enable-eh -exception-model=wasm -target-feature +exception-handling -S -o - -std=c++11 | FileCheck %s --check-prefix=ASSEMBLY
413 // ASSEMBLY: try
414 // ASSEMBLY: catch
415 // ASSEMBLY: rethrow
416 // ASSEMBLY: end_try