blob: 9cb5a057ef14f7f1312f9a42b71d8a3d147c763c [file] [log] [blame]
Heejin Ahn78297632019-02-26 03:29:59 +00001; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling | FileCheck %s
Heejin Ahn44a5a4b2019-03-26 17:15:55 +00002; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs -exception-model=wasm -mattr=+exception-handling | FileCheck %s --check-prefix=NOOPT
Heejin Ahnc4ac74f2019-03-30 11:04:48 +00003; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling -wasm-disable-ehpad-sort | FileCheck %s --check-prefix=NOSORT
Heejin Ahn7fb68d22018-08-07 20:19:23 +00004
5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
6target triple = "wasm32-unknown-unknown"
7
8@_ZTIi = external constant i8*
9@_ZTId = external constant i8*
10
11; Simple test case with two catch clauses
Heejin Ahn78297632019-02-26 03:29:59 +000012;
13; void foo();
Heejin Ahnd6f48782019-01-30 03:21:57 +000014; void test0() {
15; try {
16; foo();
Heejin Ahn78297632019-02-26 03:29:59 +000017; } catch (int) {
18; } catch (double) {
Heejin Ahnd6f48782019-01-30 03:21:57 +000019; }
20; }
Heejin Ahn7fb68d22018-08-07 20:19:23 +000021
22; CHECK-LABEL: test0
Heejin Ahncf699b42019-02-27 00:50:53 +000023; CHECK: try
24; CHECK: call foo
25; CHECK: catch
26; CHECK: block
27; CHECK: br_if 0, {{.*}} # 0: down to label2
28; CHECK: i32.call $drop=, __cxa_begin_catch
29; CHECK: call __cxa_end_catch
30; CHECK: br 1 # 1: down to label0
31; CHECK: end_block # label2:
32; CHECK: block
33; CHECK: br_if 0, {{.*}} # 0: down to label3
34; CHECK: i32.call $drop=, __cxa_begin_catch
35; CHECK: call __cxa_end_catch
36; CHECK: br 1 # 1: down to label0
37; CHECK: end_block # label3:
Heejin Ahn66ce4192019-03-16 05:38:57 +000038; CHECK: rethrow {{.*}} # to caller
Heejin Ahncf699b42019-02-27 00:50:53 +000039; CHECK: end_try # label0:
Heejin Ahn7fb68d22018-08-07 20:19:23 +000040define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
41entry:
42 invoke void @foo()
43 to label %try.cont unwind label %catch.dispatch
44
45catch.dispatch: ; preds = %entry
46 %0 = catchswitch within none [label %catch.start] unwind to caller
47
48catch.start: ; preds = %catch.dispatch
49 %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)]
50 %2 = call i8* @llvm.wasm.get.exception(token %1)
51 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
52 %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
53 %matches = icmp eq i32 %3, %4
54 br i1 %matches, label %catch2, label %catch.fallthrough
55
56catch2: ; preds = %catch.start
57 %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
Heejin Ahn7fb68d22018-08-07 20:19:23 +000058 call void @__cxa_end_catch() [ "funclet"(token %1) ]
59 catchret from %1 to label %try.cont
60
61catch.fallthrough: ; preds = %catch.start
Heejin Ahn78297632019-02-26 03:29:59 +000062 %6 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*))
63 %matches1 = icmp eq i32 %3, %6
Heejin Ahn7fb68d22018-08-07 20:19:23 +000064 br i1 %matches1, label %catch, label %rethrow
65
66catch: ; preds = %catch.fallthrough
Heejin Ahn78297632019-02-26 03:29:59 +000067 %7 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
Heejin Ahn7fb68d22018-08-07 20:19:23 +000068 call void @__cxa_end_catch() [ "funclet"(token %1) ]
69 catchret from %1 to label %try.cont
70
71rethrow: ; preds = %catch.fallthrough
Heejin Ahn66ce4192019-03-16 05:38:57 +000072 call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %1) ]
Heejin Ahn7fb68d22018-08-07 20:19:23 +000073 unreachable
74
Heejin Ahn44a5a4b2019-03-26 17:15:55 +000075try.cont: ; preds = %catch, %catch2, %entry
Heejin Ahn7fb68d22018-08-07 20:19:23 +000076 ret void
77}
78
79; Nested try-catches within a catch
Heejin Ahnd6f48782019-01-30 03:21:57 +000080; void test1() {
81; try {
82; foo();
Heejin Ahn78297632019-02-26 03:29:59 +000083; } catch (int) {
Heejin Ahnd6f48782019-01-30 03:21:57 +000084; try {
85; foo();
Heejin Ahn78297632019-02-26 03:29:59 +000086; } catch (int) {
Heejin Ahnd6f48782019-01-30 03:21:57 +000087; foo();
88; }
89; }
90; }
Heejin Ahn7fb68d22018-08-07 20:19:23 +000091
92; CHECK-LABEL: test1
Heejin Ahn82da1ff2019-02-27 01:35:14 +000093; CHECK: try
94; CHECK: call foo
95; CHECK: catch
96; CHECK: block
97; CHECK: block
98; CHECK: br_if 0, {{.*}} # 0: down to label7
99; CHECK: i32.call $drop=, __cxa_begin_catch
100; CHECK: try
101; CHECK: call foo
102; CHECK: br 2 # 2: down to label6
103; CHECK: catch
104; CHECK: try
105; CHECK: block
106; CHECK: br_if 0, {{.*}} # 0: down to label11
107; CHECK: i32.call $drop=, __cxa_begin_catch
108; CHECK: try
109; CHECK: call foo
Heejin Ahn195a62e2019-03-03 22:35:56 +0000110; CHECK: br 2 # 2: down to label9
Heejin Ahn82da1ff2019-02-27 01:35:14 +0000111; CHECK: catch
112; CHECK: call __cxa_end_catch
Heejin Ahn66ce4192019-03-16 05:38:57 +0000113; CHECK: rethrow {{.*}} # down to catch3
Heejin Ahn82da1ff2019-02-27 01:35:14 +0000114; CHECK: end_try
115; CHECK: end_block # label11:
Heejin Ahn66ce4192019-03-16 05:38:57 +0000116; CHECK: rethrow {{.*}} # down to catch3
Heejin Ahn82da1ff2019-02-27 01:35:14 +0000117; CHECK: catch {{.*}} # catch3:
118; CHECK: call __cxa_end_catch
Heejin Ahn66ce4192019-03-16 05:38:57 +0000119; CHECK: rethrow {{.*}} # to caller
Heejin Ahn195a62e2019-03-03 22:35:56 +0000120; CHECK: end_try # label9:
Heejin Ahn82da1ff2019-02-27 01:35:14 +0000121; CHECK: call __cxa_end_catch
122; CHECK: br 2 # 2: down to label6
123; CHECK: end_try
124; CHECK: end_block # label7:
Heejin Ahn66ce4192019-03-16 05:38:57 +0000125; CHECK: rethrow {{.*}} # to caller
Heejin Ahn82da1ff2019-02-27 01:35:14 +0000126; CHECK: end_block # label6:
127; CHECK: call __cxa_end_catch
128; CHECK: end_try
Heejin Ahnd6f48782019-01-30 03:21:57 +0000129define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000130entry:
131 invoke void @foo()
132 to label %try.cont11 unwind label %catch.dispatch
133
134catch.dispatch: ; preds = %entry
135 %0 = catchswitch within none [label %catch.start] unwind to caller
136
137catch.start: ; preds = %catch.dispatch
138 %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
139 %2 = call i8* @llvm.wasm.get.exception(token %1)
140 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
141 %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
142 %matches = icmp eq i32 %3, %4
143 br i1 %matches, label %catch, label %rethrow
144
145catch: ; preds = %catch.start
146 %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
147 %6 = bitcast i8* %5 to i32*
148 %7 = load i32, i32* %6, align 4
149 invoke void @foo() [ "funclet"(token %1) ]
150 to label %try.cont unwind label %catch.dispatch2
151
152catch.dispatch2: ; preds = %catch
153 %8 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup9
154
155catch.start3: ; preds = %catch.dispatch2
156 %9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
157 %10 = call i8* @llvm.wasm.get.exception(token %9)
158 %11 = call i32 @llvm.wasm.get.ehselector(token %9)
159 %12 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
160 %matches4 = icmp eq i32 %11, %12
161 br i1 %matches4, label %catch6, label %rethrow5
162
163catch6: ; preds = %catch.start3
164 %13 = call i8* @__cxa_begin_catch(i8* %10) [ "funclet"(token %9) ]
165 %14 = bitcast i8* %13 to i32*
166 %15 = load i32, i32* %14, align 4
167 invoke void @foo() [ "funclet"(token %9) ]
168 to label %invoke.cont8 unwind label %ehcleanup
169
170invoke.cont8: ; preds = %catch6
171 call void @__cxa_end_catch() [ "funclet"(token %9) ]
172 catchret from %9 to label %try.cont
173
174rethrow5: ; preds = %catch.start3
Heejin Ahn66ce4192019-03-16 05:38:57 +0000175 invoke void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %9) ]
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000176 to label %unreachable unwind label %ehcleanup9
177
Heejin Ahn44a5a4b2019-03-26 17:15:55 +0000178try.cont: ; preds = %invoke.cont8, %catch
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000179 call void @__cxa_end_catch() [ "funclet"(token %1) ]
180 catchret from %1 to label %try.cont11
181
182rethrow: ; preds = %catch.start
Heejin Ahn66ce4192019-03-16 05:38:57 +0000183 call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %1) ]
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000184 unreachable
185
Heejin Ahn44a5a4b2019-03-26 17:15:55 +0000186try.cont11: ; preds = %try.cont, %entry
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000187 ret void
188
189ehcleanup: ; preds = %catch6
190 %16 = cleanuppad within %9 []
191 call void @__cxa_end_catch() [ "funclet"(token %16) ]
192 cleanupret from %16 unwind label %ehcleanup9
193
194ehcleanup9: ; preds = %ehcleanup, %rethrow5, %catch.dispatch2
195 %17 = cleanuppad within %1 []
196 call void @__cxa_end_catch() [ "funclet"(token %17) ]
197 cleanupret from %17 unwind to caller
198
199unreachable: ; preds = %rethrow5
200 unreachable
201}
202
203; Nested loop within a catch clause
Heejin Ahnd6f48782019-01-30 03:21:57 +0000204; void test2() {
205; try {
206; foo();
207; } catch (...) {
208; for (int i = 0; i < 50; i++)
209; foo();
210; }
211; }
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000212
213; CHECK-LABEL: test2
Heejin Ahncf699b42019-02-27 00:50:53 +0000214; CHECK: try
215; CHECK: call foo
216; CHECK: catch
217; CHECK: i32.call $drop=, __cxa_begin_catch
218; CHECK: loop # label15:
219; CHECK: block
Heejin Ahn78297632019-02-26 03:29:59 +0000220; CHECK: block
Heejin Ahncf699b42019-02-27 00:50:53 +0000221; CHECK: br_if 0, {{.*}} # 0: down to label17
222; CHECK: try
223; CHECK: call foo
224; CHECK: br 2 # 2: down to label16
225; CHECK: catch
Heejin Ahn78297632019-02-26 03:29:59 +0000226; CHECK: try
Heejin Ahncf699b42019-02-27 00:50:53 +0000227; CHECK: call __cxa_end_catch
Heejin Ahn78297632019-02-26 03:29:59 +0000228; CHECK: catch
Heejin Ahncf699b42019-02-27 00:50:53 +0000229; CHECK: call __clang_call_terminate
230; CHECK: unreachable
Heejin Ahn78297632019-02-26 03:29:59 +0000231; CHECK: end_try
Heejin Ahn66ce4192019-03-16 05:38:57 +0000232; CHECK: rethrow {{.*}} # to caller
Heejin Ahncf699b42019-02-27 00:50:53 +0000233; CHECK: end_try
234; CHECK: end_block # label17:
235; CHECK: call __cxa_end_catch
236; CHECK: br 2 # 2: down to label13
237; CHECK: end_block # label16:
238; CHECK: br 0 # 0: up to label15
239; CHECK: end_loop
240; CHECK: end_try # label13:
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000241define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
242entry:
243 invoke void @foo()
244 to label %try.cont unwind label %catch.dispatch
245
246catch.dispatch: ; preds = %entry
247 %0 = catchswitch within none [label %catch.start] unwind to caller
248
249catch.start: ; preds = %catch.dispatch
250 %1 = catchpad within %0 [i8* null]
251 %2 = call i8* @llvm.wasm.get.exception(token %1)
252 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
253 %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
254 br label %for.cond
255
256for.cond: ; preds = %for.inc, %catch.start
257 %i.0 = phi i32 [ 0, %catch.start ], [ %inc, %for.inc ]
258 %cmp = icmp slt i32 %i.0, 50
259 br i1 %cmp, label %for.body, label %for.end
260
261for.body: ; preds = %for.cond
262 invoke void @foo() [ "funclet"(token %1) ]
263 to label %for.inc unwind label %ehcleanup
264
265for.inc: ; preds = %for.body
266 %inc = add nsw i32 %i.0, 1
267 br label %for.cond
268
269for.end: ; preds = %for.cond
270 call void @__cxa_end_catch() [ "funclet"(token %1) ]
271 catchret from %1 to label %try.cont
272
273try.cont: ; preds = %for.end, %entry
274 ret void
275
276ehcleanup: ; preds = %for.body
277 %5 = cleanuppad within %1 []
278 invoke void @__cxa_end_catch() [ "funclet"(token %5) ]
279 to label %invoke.cont2 unwind label %terminate
280
281invoke.cont2: ; preds = %ehcleanup
282 cleanupret from %5 unwind to caller
283
284terminate: ; preds = %ehcleanup
285 %6 = cleanuppad within %5 []
286 %7 = call i8* @llvm.wasm.get.exception(token %6)
287 call void @__clang_call_terminate(i8* %7) [ "funclet"(token %6) ]
288 unreachable
289}
290
Heejin Ahn44a5a4b2019-03-26 17:15:55 +0000291; Tests if block and try markers are correctly placed. Even if two predecessors
292; of the EH pad are bb2 and bb3 and their nearest common dominator is bb1, the
293; TRY marker should be placed at bb0 because there's a branch from bb0 to bb2,
294; and scopes cannot be interleaved.
295
296; NOOPT-LABEL: test3
297; NOOPT: try
298; NOOPT: block
299; NOOPT: block
300; NOOPT: block
301; NOOPT: end_block
302; NOOPT: end_block
303; NOOPT: call foo
304; NOOPT: end_block
305; NOOPT: call bar
306; NOOPT: catch {{.*}}
307; NOOPT: end_try
308define void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
309bb0:
310 br i1 undef, label %bb1, label %bb2
311
312bb1: ; preds = %bb0
313 br i1 undef, label %bb3, label %bb4
314
315bb2: ; preds = %bb0
316 br label %try.cont
317
318bb3: ; preds = %bb1
319 invoke void @foo()
320 to label %try.cont unwind label %catch.dispatch
321
322bb4: ; preds = %bb1
323 invoke void @bar()
324 to label %try.cont unwind label %catch.dispatch
325
326catch.dispatch: ; preds = %bb4, %bb3
327 %0 = catchswitch within none [label %catch.start] unwind to caller
328
329catch.start: ; preds = %catch.dispatch
330 %1 = catchpad within %0 [i8* null]
331 %2 = call i8* @llvm.wasm.get.exception(token %1)
332 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
333 catchret from %1 to label %try.cont
334
335try.cont: ; preds = %catch.start, %bb4, %bb3, %bb2
336 ret void
337}
338
Heejin Ahn222718f2019-03-26 17:29:55 +0000339; Tests if try/end_try markers are placed correctly wrt loop/end_loop markers,
340; when try and loop markers are in the same BB and end_try and end_loop are in
341; another BB.
342; CHECK: loop
343; CHECK: try
344; CHECK: call foo
345; CHECK: catch
346; CHECK: end_try
347; CHECK: end_loop
348define void @test4(i32* %p) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
349entry:
350 store volatile i32 0, i32* %p
351 br label %loop
352
353loop: ; preds = %try.cont, %entry
354 store volatile i32 1, i32* %p
355 invoke void @foo()
356 to label %try.cont unwind label %catch.dispatch
357
358catch.dispatch: ; preds = %loop
359 %0 = catchswitch within none [label %catch.start] unwind to caller
360
361catch.start: ; preds = %catch.dispatch
362 %1 = catchpad within %0 [i8* null]
363 %2 = call i8* @llvm.wasm.get.exception(token %1)
364 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
365 catchret from %1 to label %try.cont
366
367try.cont: ; preds = %catch.start, %loop
368 br label %loop
369}
370
Heejin Ahnc4ac74f2019-03-30 11:04:48 +0000371; Some of test cases below are hand-tweaked by deleting some library calls to
372; simplify tests and changing the order of basic blocks to cause unwind
373; destination mismatches. And we use -wasm-disable-ehpad-sort to create maximum
374; number of mismatches in several tests below.
375
376; 'call bar''s original unwind destination was 'catch14', but after control flow
377; linearization, its unwind destination incorrectly becomes 'catch15'. We fix
378; this by wrapping the call with a nested try/catch/end_try and branching to the
379; right destination (label32).
380
381; NOSORT-LABEL: test5
382; NOSORT: block
383; NOSORT: try
384; NOSORT: try
385; NOSORT: call foo
386; --- Nested try/catch/end_try starts
387; NOSORT: try
388; NOSORT: call bar
389; NOSORT: catch $drop=
390; NOSORT: br 2 # 2: down to label32
391; NOSORT: end_try
392; --- Nested try/catch/end_try ends
393; NOSORT: br 2 # 2: down to label31
394; NOSORT: catch $drop= # catch15:
395; NOSORT: br 2 # 2: down to label31
396; NOSORT: end_try
397; NOSORT: catch $drop= # catch14:
398; NOSORT: end_try # label32:
399; NOSORT: end_block # label31:
400; NOSORT: return
401
402define void @test5() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
403bb0:
404 invoke void @foo()
405 to label %bb1 unwind label %catch.dispatch0
406
407bb1: ; preds = %bb0
408 invoke void @bar()
409 to label %try.cont unwind label %catch.dispatch1
410
411catch.dispatch0: ; preds = %bb0
412 %0 = catchswitch within none [label %catch.start0] unwind to caller
413
414catch.start0: ; preds = %catch.dispatch0
415 %1 = catchpad within %0 [i8* null]
416 %2 = call i8* @llvm.wasm.get.exception(token %1)
417 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
418 catchret from %1 to label %try.cont
419
420catch.dispatch1: ; preds = %bb1
421 %4 = catchswitch within none [label %catch.start1] unwind to caller
422
423catch.start1: ; preds = %catch.dispatch1
424 %5 = catchpad within %4 [i8* null]
425 %6 = call i8* @llvm.wasm.get.exception(token %5)
426 %7 = call i32 @llvm.wasm.get.ehselector(token %5)
427 catchret from %5 to label %try.cont
428
429try.cont: ; preds = %catch.start1, %catch.start0, %bb1
430 ret void
431}
432
433; Two 'call bar''s original unwind destination was the caller, but after control
434; flow linearization, their unwind destination incorrectly becomes 'catch17'. We
435; fix this by wrapping the call with a nested try/catch/end_try and branching to
436; the right destination (label4), from which we rethrow the exception to the
437; caller.
438
439; NOSORT-LABEL: test6
440; NOSORT: try
441; NOSORT: call foo
442; --- Nested try/catch/end_try starts
443; NOSORT: try
444; NOSORT: call bar
445; NOSORT: call bar
446; NOSORT: catch $[[REG:[0-9]+]]=
447; NOSORT: br 1 # 1: down to label35
448; NOSORT: end_try
449; --- Nested try/catch/end_try ends
450; NOSORT: return
451; NOSORT: catch $drop= # catch17:
452; NOSORT: return
453; NOSORT: end_try # label35:
454; NOSORT: rethrow $[[REG]] # to caller
455
456define void @test6() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
457bb0:
458 invoke void @foo()
459 to label %bb1 unwind label %catch.dispatch0
460
461bb1: ; preds = %bb0
462 call void @bar()
463 call void @bar()
464 ret void
465
466catch.dispatch0: ; preds = %bb0
467 %0 = catchswitch within none [label %catch.start0] unwind to caller
468
469catch.start0: ; preds = %catch.dispatch0
470 %1 = catchpad within %0 [i8* null]
471 %2 = call i8* @llvm.wasm.get.exception(token %1)
472 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
473 catchret from %1 to label %try.cont
474
475try.cont: ; preds = %catch.start0
476 ret void
477}
478
479; If not for the unwind destination mismatch, the LOOP marker here would have an
480; i32 signature. But because we add a rethrow instruction at the end of the
481; appendix block, now the LOOP marker does not have a signature (= has a void
482; signature). Here the two calls two 'bar' are supposed to throw up to the
483; caller, but incorrectly unwind to 'catch19' after linearizing the CFG.
484
485; NOSORT-LABEL: test7
486; NOSORT: block
487; NOSORT-NOT: loop i32
488; NOSORT: loop # label38:
489; NOSORT: try
490; NOSORT: call foo
491; --- Nested try/catch/end_try starts
492; NOSORT: try
493; NOSORT: call bar
494; NOSORT: call bar
495; NOSORT: catch $[[REG:[0-9]+]]=
496; NOSORT: br 1 # 1: down to label39
497; NOSORT: end_try
498; --- Nested try/catch/end_try ends
499; NOSORT: return {{.*}}
500; NOSORT: catch $drop= # catch19:
501; NOSORT: br 1 # 1: up to label38
502; NOSORT: end_try # label39:
503; NOSORT: end_loop
504; NOSORT: end_block
505; NOSORT: rethrow $[[REG]] # to caller
506
507define i32 @test7(i32* %p) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
508entry:
509 store volatile i32 0, i32* %p
510 br label %loop
511
512loop: ; preds = %try.cont, %entry
513 store volatile i32 1, i32* %p
514 invoke void @foo()
515 to label %bb unwind label %catch.dispatch
516
517bb: ; preds = %loop
518 call void @bar()
519 call void @bar()
520 ret i32 0
521
522catch.dispatch: ; preds = %loop
523 %0 = catchswitch within none [label %catch.start] unwind to caller
524
525catch.start: ; preds = %catch.dispatch
526 %1 = catchpad within %0 [i8* null]
527 %2 = call i8* @llvm.wasm.get.exception(token %1)
528 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
529 catchret from %1 to label %try.cont
530
531try.cont: ; preds = %catch.start
532 br label %loop
533}
534
535; When we have both kinds of EH pad unwind mismatches:
536; - A may-throw instruction unwinds to an incorrect EH pad after linearizing the
537; CFG, when it is supposed to unwind to another EH pad.
538; - A may-throw instruction unwinds to an incorrect EH pad after linearizing the
539; CFG, when it is supposed to unwind to the caller.
540
541; NOSORT-LABEL: test8
542; NOSORT: block
543; NOSORT: block
544; NOSORT: try
545; NOSORT: try
546; NOSORT: call foo
547; --- Nested try/catch/end_try starts
548; NOSORT: try
549; NOSORT: call bar
550; NOSORT: catch $[[REG0:[0-9]+]]=
551; NOSORT: br 2 # 2: down to label43
552; NOSORT: end_try
553; --- Nested try/catch/end_try ends
554; NOSORT: br 2 # 2: down to label42
555; NOSORT: catch {{.*}}
556; NOSORT: block i32
557; NOSORT: br_on_exn 0, {{.*}} # 0: down to label46
558; --- Nested try/catch/end_try starts
559; NOSORT: try
560; NOSORT: rethrow {{.*}} # down to catch24
561; NOSORT: catch $[[REG1:[0-9]+]]= # catch24:
562; NOSORT: br 5 # 5: down to label41
563; NOSORT: end_try
564; --- Nested try/catch/end_try ends
565; NOSORT: end_block # label46:
566; NOSORT: i32.call $drop=, __cxa_begin_catch
567; --- Nested try/catch/end_try starts
568; NOSORT: try
569; NOSORT: call __cxa_end_catch
570; NOSORT: catch $[[REG1]]=
571; NOSORT: br 4 # 4: down to label41
572; NOSORT: end_try
573; --- Nested try/catch/end_try ends
574; NOSORT: br 2 # 2: down to label42
575; NOSORT: end_try
576; NOSORT: catch $[[REG0]]=
577; NOSORT: end_try # label43:
578; NOSORT: i32.call $drop=, __cxa_begin_catch
579; NOSORT: call __cxa_end_catch
580; NOSORT: end_block # label42:
581; NOSORT: return
582; NOSORT: end_block # label41:
583; NOSORT: rethrow $[[REG1]] # to caller
584define void @test8() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
585bb0:
586 invoke void @foo()
587 to label %bb1 unwind label %catch.dispatch0
588
589bb1: ; preds = %bb0
590 invoke void @bar()
591 to label %try.cont unwind label %catch.dispatch1
592
593catch.dispatch0: ; preds = %bb0
594 %0 = catchswitch within none [label %catch.start0] unwind to caller
595
596catch.start0: ; preds = %catch.dispatch0
597 %1 = catchpad within %0 [i8* null]
598 %2 = call i8* @llvm.wasm.get.exception(token %1)
599 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
600 %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
601 call void @__cxa_end_catch() [ "funclet"(token %1) ]
602 catchret from %1 to label %try.cont
603
604catch.dispatch1: ; preds = %bb1
605 %5 = catchswitch within none [label %catch.start1] unwind to caller
606
607catch.start1: ; preds = %catch.dispatch1
608 %6 = catchpad within %5 [i8* null]
609 %7 = call i8* @llvm.wasm.get.exception(token %6)
610 %8 = call i32 @llvm.wasm.get.ehselector(token %6)
611 %9 = call i8* @__cxa_begin_catch(i8* %7) [ "funclet"(token %6) ]
612 call void @__cxa_end_catch() [ "funclet"(token %6) ]
613 catchret from %6 to label %try.cont
614
615try.cont: ; preds = %catch.start1, %catch.start0, %bb1
616 ret void
617}
618
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000619declare void @foo()
620declare void @bar()
621declare i32 @__gxx_wasm_personality_v0(...)
622declare i8* @llvm.wasm.get.exception(token)
623declare i32 @llvm.wasm.get.ehselector(token)
Heejin Ahn66ce4192019-03-16 05:38:57 +0000624declare void @llvm.wasm.rethrow.in.catch()
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000625declare i32 @llvm.eh.typeid.for(i8*)
626declare i8* @__cxa_begin_catch(i8*)
627declare void @__cxa_end_catch()
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000628declare void @__clang_call_terminate(i8*)
629declare void @_ZSt9terminatev()