1; REQUIRES: asserts
2; 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
3; RUN: llc < %s -disable-wasm-fallthrough-return-opt -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
4; 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
5; 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 -stats 2>&1 | FileCheck %s --check-prefix=NOSORT
6; RUN: llc < %s -disable-wasm-fallthrough-return-opt -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-LOCALS
7
8target triple = "wasm32-unknown-unknown"
9
10@_ZTIi = external constant i8*
11@_ZTId = external constant i8*
12
13%class.Object = type { i8 }
14%class.MyClass = type { i32 }
15
16; Simple test case with two catch clauses
17;
18; void foo();
19; void test0() {
20;   try {
21;     foo();
22;   } catch (int) {
23;   } catch (double) {
24;   }
25; }
26
27; CHECK-LABEL: test0
28; CHECK: try
29; CHECK:   call      foo
30; CHECK: catch
31; CHECK:   block
32; CHECK:     br_if     0, {{.*}}                       # 0: down to label[[L0:[0-9]+]]
33; CHECK:     call      $drop=, __cxa_begin_catch
34; CHECK:     call      __cxa_end_catch
35; CHECK:     br        1                               # 1: down to label[[L1:[0-9]+]]
36; CHECK:   end_block                                   # label[[L0]]:
37; CHECK:   block
38; CHECK:     br_if     0, {{.*}}                       # 0: down to label[[L2:[0-9]+]]
39; CHECK:     call      $drop=, __cxa_begin_catch
40; CHECK:     call      __cxa_end_catch
41; CHECK:     br        1                               # 1: down to label[[L1]]
42; CHECK:   end_block                                   # label[[L2]]:
43; CHECK:   rethrow   0                                 # to caller
44; CHECK: end_try                                       # label[[L1]]:
45define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
46entry:
47  invoke void @foo()
48          to label %try.cont unwind label %catch.dispatch
49
50catch.dispatch:                                   ; preds = %entry
51  %0 = catchswitch within none [label %catch.start] unwind to caller
52
53catch.start:                                      ; preds = %catch.dispatch
54  %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)]
55  %2 = call i8* @llvm.wasm.get.exception(token %1)
56  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
57  %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
58  %matches = icmp eq i32 %3, %4
59  br i1 %matches, label %catch2, label %catch.fallthrough
60
61catch2:                                           ; preds = %catch.start
62  %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
63  call void @__cxa_end_catch() [ "funclet"(token %1) ]
64  catchret from %1 to label %try.cont
65
66catch.fallthrough:                                ; preds = %catch.start
67  %6 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*))
68  %matches1 = icmp eq i32 %3, %6
69  br i1 %matches1, label %catch, label %rethrow
70
71catch:                                            ; preds = %catch.fallthrough
72  %7 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
73  call void @__cxa_end_catch() [ "funclet"(token %1) ]
74  catchret from %1 to label %try.cont
75
76rethrow:                                          ; preds = %catch.fallthrough
77  call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]
78  unreachable
79
80try.cont:                                         ; preds = %catch, %catch2, %entry
81  ret void
82}
83
84; Nested try-catches within a catch
85; void test1() {
86;   try {
87;     foo();
88;   } catch (int) {
89;     try {
90;       foo();
91;     } catch (int) {
92;       foo();
93;     }
94;   }
95; }
96
97; CHECK-LABEL: test1
98; CHECK: try
99; CHECK:   call  foo
100; CHECK: catch
101; CHECK:   block
102; CHECK:     block
103; CHECK:       br_if     0, {{.*}}                     # 0: down to label[[L0:[0-9+]]]
104; CHECK:       call  $drop=, __cxa_begin_catch, $0
105; CHECK:       try
106; CHECK:         try
107; CHECK:           call  foo
108; CHECK:           br        3                         # 3: down to label[[L1:[0-9+]]]
109; CHECK:         catch
110; CHECK:           block
111; CHECK:             block
112; CHECK:               br_if     0, {{.*}}             # 0: down to label[[L2:[0-9+]]]
113; CHECK:               call  $drop=, __cxa_begin_catch
114; CHECK:               try
115; CHECK:                 call  foo
116; CHECK:                 br        2                   # 2: down to label[[L3:[0-9+]]]
117; CHECK:               catch_all
118; CHECK:                 call  __cxa_end_catch
119; CHECK:                 rethrow   0                   # down to catch[[L4:[0-9+]]]
120; CHECK:               end_try
121; CHECK:             end_block                         # label[[L2]]:
122; CHECK:             rethrow   1                       # down to catch[[L4]]
123; CHECK:           end_block                           # label[[L3]]:
124; CHECK:           call  __cxa_end_catch
125; CHECK:           br        3                         # 3: down to label[[L1]]
126; CHECK:         end_try
127; CHECK:       catch_all                               # catch[[L4]]:
128; CHECK:         call  __cxa_end_catch
129; CHECK:         rethrow   0                           # to caller
130; CHECK:       end_try
131; CHECK:     end_block                                 # label[[L0]]:
132; CHECK:     rethrow   1                               # to caller
133; CHECK:   end_block                                   # label[[L1]]:
134; CHECK:   call  __cxa_end_catch
135; CHECK: end_try
136define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
137entry:
138  invoke void @foo()
139          to label %try.cont11 unwind label %catch.dispatch
140
141catch.dispatch:                                   ; preds = %entry
142  %0 = catchswitch within none [label %catch.start] unwind to caller
143
144catch.start:                                      ; preds = %catch.dispatch
145  %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
146  %2 = call i8* @llvm.wasm.get.exception(token %1)
147  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
148  %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
149  %matches = icmp eq i32 %3, %4
150  br i1 %matches, label %catch, label %rethrow
151
152catch:                                            ; preds = %catch.start
153  %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
154  %6 = bitcast i8* %5 to i32*
155  %7 = load i32, i32* %6, align 4
156  invoke void @foo() [ "funclet"(token %1) ]
157          to label %try.cont unwind label %catch.dispatch2
158
159catch.dispatch2:                                  ; preds = %catch
160  %8 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup9
161
162catch.start3:                                     ; preds = %catch.dispatch2
163  %9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
164  %10 = call i8* @llvm.wasm.get.exception(token %9)
165  %11 = call i32 @llvm.wasm.get.ehselector(token %9)
166  %12 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
167  %matches4 = icmp eq i32 %11, %12
168  br i1 %matches4, label %catch6, label %rethrow5
169
170catch6:                                           ; preds = %catch.start3
171  %13 = call i8* @__cxa_begin_catch(i8* %10) [ "funclet"(token %9) ]
172  %14 = bitcast i8* %13 to i32*
173  %15 = load i32, i32* %14, align 4
174  invoke void @foo() [ "funclet"(token %9) ]
175          to label %invoke.cont8 unwind label %ehcleanup
176
177invoke.cont8:                                     ; preds = %catch6
178  call void @__cxa_end_catch() [ "funclet"(token %9) ]
179  catchret from %9 to label %try.cont
180
181rethrow5:                                         ; preds = %catch.start3
182  invoke void @llvm.wasm.rethrow() [ "funclet"(token %9) ]
183          to label %unreachable unwind label %ehcleanup9
184
185try.cont:                                         ; preds = %invoke.cont8, %catch
186  call void @__cxa_end_catch() [ "funclet"(token %1) ]
187  catchret from %1 to label %try.cont11
188
189rethrow:                                          ; preds = %catch.start
190  call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]
191  unreachable
192
193try.cont11:                                       ; preds = %try.cont, %entry
194  ret void
195
196ehcleanup:                                        ; preds = %catch6
197  %16 = cleanuppad within %9 []
198  call void @__cxa_end_catch() [ "funclet"(token %16) ]
199  cleanupret from %16 unwind label %ehcleanup9
200
201ehcleanup9:                                       ; preds = %ehcleanup, %rethrow5, %catch.dispatch2
202  %17 = cleanuppad within %1 []
203  call void @__cxa_end_catch() [ "funclet"(token %17) ]
204  cleanupret from %17 unwind to caller
205
206unreachable:                                      ; preds = %rethrow5
207  unreachable
208}
209
210; Nested loop within a catch clause
211; void test2() {
212;   try {
213;     foo();
214;   } catch (...) {
215;     for (int i = 0; i < 50; i++)
216;       foo();
217;   }
218; }
219
220; CHECK-LABEL: test2
221; CHECK: try
222; CHECK:   call      foo
223; CHECK: catch
224; CHECK:   call      $drop=, __cxa_begin_catch
225; CHECK:   loop                                        # label[[L0:[0-9]+]]:
226; CHECK:     block
227; CHECK:       block
228; CHECK:         br_if     0, {{.*}}                   # 0: down to label[[L1:[0-9]+]]
229; CHECK:         try
230; CHECK:           call      foo
231; CHECK:           br        2                         # 2: down to label[[L2:[0-9]+]]
232; CHECK:         catch
233; CHECK:           try
234; CHECK:             call      __cxa_end_catch
235; CHECK:           catch_all
236; CHECK:             call      _ZSt9terminatev
237; CHECK:             unreachable
238; CHECK:           end_try
239; CHECK:           rethrow   0                         # to caller
240; CHECK:         end_try
241; CHECK:       end_block                               # label[[L1]]:
242; CHECK:       call      __cxa_end_catch
243; CHECK:       br        2                             # 2: down to label[[L3:[0-9]+]]
244; CHECK:     end_block                                 # label[[L2]]:
245; CHECK:     br        0                               # 0: up to label[[L0]]
246; CHECK:   end_loop
247; CHECK: end_try                                       # label[[L3]]:
248define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
249entry:
250  invoke void @foo()
251          to label %try.cont unwind label %catch.dispatch
252
253catch.dispatch:                                   ; preds = %entry
254  %0 = catchswitch within none [label %catch.start] unwind to caller
255
256catch.start:                                      ; preds = %catch.dispatch
257  %1 = catchpad within %0 [i8* null]
258  %2 = call i8* @llvm.wasm.get.exception(token %1)
259  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
260  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
261  br label %for.cond
262
263for.cond:                                         ; preds = %for.inc, %catch.start
264  %i.0 = phi i32 [ 0, %catch.start ], [ %inc, %for.inc ]
265  %cmp = icmp slt i32 %i.0, 50
266  br i1 %cmp, label %for.body, label %for.end
267
268for.body:                                         ; preds = %for.cond
269  invoke void @foo() [ "funclet"(token %1) ]
270          to label %for.inc unwind label %ehcleanup
271
272for.inc:                                          ; preds = %for.body
273  %inc = add nsw i32 %i.0, 1
274  br label %for.cond
275
276for.end:                                          ; preds = %for.cond
277  call void @__cxa_end_catch() [ "funclet"(token %1) ]
278  catchret from %1 to label %try.cont
279
280try.cont:                                         ; preds = %for.end, %entry
281  ret void
282
283ehcleanup:                                        ; preds = %for.body
284  %5 = cleanuppad within %1 []
285  invoke void @__cxa_end_catch() [ "funclet"(token %5) ]
286          to label %invoke.cont2 unwind label %terminate
287
288invoke.cont2:                                     ; preds = %ehcleanup
289  cleanupret from %5 unwind to caller
290
291terminate:                                        ; preds = %ehcleanup
292  %6 = cleanuppad within %5 []
293  call void @_ZSt9terminatev() [ "funclet"(token %6) ]
294  unreachable
295}
296
297; Tests if block and try markers are correctly placed. Even if two predecessors
298; of the EH pad are bb2 and bb3 and their nearest common dominator is bb1, the
299; TRY marker should be placed at bb0 because there's a branch from bb0 to bb2,
300; and scopes cannot be interleaved.
301
302; NOOPT-LABEL: test3
303; NOOPT: try
304; NOOPT:   block
305; NOOPT:     block
306; NOOPT:       block
307; NOOPT:       end_block
308; NOOPT:     end_block
309; NOOPT:     call      foo
310; NOOPT:   end_block
311; NOOPT:   call      bar
312; NOOPT: catch     {{.*}}
313; NOOPT: end_try
314define void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
315bb0:
316  br i1 undef, label %bb1, label %bb2
317
318bb1:                                              ; preds = %bb0
319  br i1 undef, label %bb3, label %bb4
320
321bb2:                                              ; preds = %bb0
322  br label %try.cont
323
324bb3:                                              ; preds = %bb1
325  invoke void @foo()
326          to label %try.cont unwind label %catch.dispatch
327
328bb4:                                              ; preds = %bb1
329  invoke void @bar()
330          to label %try.cont unwind label %catch.dispatch
331
332catch.dispatch:                                   ; preds = %bb4, %bb3
333  %0 = catchswitch within none [label %catch.start] unwind to caller
334
335catch.start:                                      ; preds = %catch.dispatch
336  %1 = catchpad within %0 [i8* null]
337  %2 = call i8* @llvm.wasm.get.exception(token %1)
338  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
339  catchret from %1 to label %try.cont
340
341try.cont:                                         ; preds = %catch.start, %bb4, %bb3, %bb2
342  ret void
343}
344
345; Tests if try/end_try markers are placed correctly wrt loop/end_loop markers,
346; when try and loop markers are in the same BB and end_try and end_loop are in
347; another BB.
348; CHECK: loop
349; CHECK:   try
350; CHECK:     call      foo
351; CHECK:   catch
352; CHECK:   end_try
353; CHECK: end_loop
354define void @test4(i32* %p) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
355entry:
356  store volatile i32 0, i32* %p
357  br label %loop
358
359loop:                                             ; preds = %try.cont, %entry
360  store volatile i32 1, i32* %p
361  invoke void @foo()
362          to label %try.cont unwind label %catch.dispatch
363
364catch.dispatch:                                   ; preds = %loop
365  %0 = catchswitch within none [label %catch.start] unwind to caller
366
367catch.start:                                      ; preds = %catch.dispatch
368  %1 = catchpad within %0 [i8* null]
369  %2 = call i8* @llvm.wasm.get.exception(token %1)
370  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
371  catchret from %1 to label %try.cont
372
373try.cont:                                         ; preds = %catch.start, %loop
374  br label %loop
375}
376
377; Some of test cases below are hand-tweaked by deleting some library calls to
378; simplify tests and changing the order of basic blocks to cause unwind
379; destination mismatches. And we use -wasm-disable-ehpad-sort to create maximum
380; number of mismatches in several tests below.
381
382; - Call unwind mismatch
383; 'call bar''s original unwind destination was 'C0', but after control flow
384; linearization, its unwind destination incorrectly becomes 'C1'. We fix this by
385; wrapping the call with a nested try-delegate that targets 'C0'.
386; - Catch unwind mismatch
387; If 'call foo' throws a foreign exception, it will not be caught by C1, and
388; should be rethrown to the caller. But after control flow linearization, it
389; will instead unwind to C0, an incorrect next EH pad. We wrap the whole
390; try-catch with try-delegate that rethrows an exception to the caller to fix
391; this.
392
393; NOSORT-LABEL: test5
394; NOSORT: try
395; --- try-delegate starts (catch unwind mismatch)
396; NOSORT    try
397; NOSORT:     try
398; NOSORT:       call  foo
399; --- try-delegate starts (call unwind mismatch)
400; NOSORT:       try
401; NOSORT:         call  bar
402; NOSORT:       delegate    2     # label/catch{{[0-9]+}}: down to catch[[C0:[0-9]+]]
403; --- try-delegate ends (call unwind mismatch)
404; NOSORT:     catch   {{.*}}      # catch[[C1:[0-9]+]]:
405; NOSORT:     end_try
406; NOSORT:   delegate    1         # label/catch{{[0-9]+}}: to caller
407; --- try-delegate ends (catch unwind mismatch)
408; NOSORT: catch   {{.*}}          # catch[[C0]]:
409; NOSORT: end_try
410; NOSORT: return
411
412define void @test5() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
413bb0:
414  invoke void @foo()
415          to label %bb1 unwind label %catch.dispatch0
416
417bb1:                                              ; preds = %bb0
418  invoke void @bar()
419          to label %try.cont unwind label %catch.dispatch1
420
421catch.dispatch0:                                  ; preds = %bb0
422  %0 = catchswitch within none [label %catch.start0] unwind to caller
423
424catch.start0:                                     ; preds = %catch.dispatch0
425  %1 = catchpad within %0 [i8* null]
426  %2 = call i8* @llvm.wasm.get.exception(token %1)
427  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
428  catchret from %1 to label %try.cont
429
430catch.dispatch1:                                  ; preds = %bb1
431  %4 = catchswitch within none [label %catch.start1] unwind to caller
432
433catch.start1:                                     ; preds = %catch.dispatch1
434  %5 = catchpad within %4 [i8* null]
435  %6 = call i8* @llvm.wasm.get.exception(token %5)
436  %7 = call i32 @llvm.wasm.get.ehselector(token %5)
437  catchret from %5 to label %try.cont
438
439try.cont:                                         ; preds = %catch.start1, %catch.start0, %bb1
440  ret void
441}
442
443; 'call bar' and 'call baz''s original unwind destination was the caller, but
444; after control flow linearization, their unwind destination incorrectly becomes
445; 'C0'. We fix this by wrapping the calls with a nested try-delegate that
446; rethrows exceptions to the caller.
447
448; And the return value of 'baz' should NOT be stackified because the BB is split
449; during fixing unwind mismatches.
450
451; NOSORT-LABEL: test6
452; NOSORT: try
453; NOSORT:   call  foo
454; --- try-delegate starts (call unwind mismatch)
455; NOSORT:   try
456; NOSORT:     call  bar
457; NOSORT:     call  $[[RET:[0-9]+]]=, baz
458; NOSORT-NOT: call  $push{{.*}}=, baz
459; NOSORT:   delegate    1                     # label/catch{{[0-9]+}}: to caller
460; --- try-delegate ends (call unwind mismatch)
461; NOSORT:   call  nothrow, $[[RET]]
462; NOSORT:   return
463; NOSORT: catch   {{.*}}                      # catch[[C0:[0-9]+]]:
464; NOSORT:   return
465; NOSORT: end_try
466
467define void @test6() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
468bb0:
469  invoke void @foo()
470          to label %bb1 unwind label %catch.dispatch0
471
472bb1:                                              ; preds = %bb0
473  call void @bar()
474  %call = call i32 @baz()
475  call void @nothrow(i32 %call) #0
476  ret void
477
478catch.dispatch0:                                  ; preds = %bb0
479  %0 = catchswitch within none [label %catch.start0] unwind to caller
480
481catch.start0:                                     ; preds = %catch.dispatch0
482  %1 = catchpad within %0 [i8* null]
483  %2 = call i8* @llvm.wasm.get.exception(token %1)
484  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
485  catchret from %1 to label %try.cont
486
487try.cont:                                         ; preds = %catch.start0
488  ret void
489}
490
491; The same as test5, but we have one more call 'call @foo' in bb1 which unwinds
492; to the caller. IN this case bb1 has two call unwind mismatches: 'call @foo'
493; unwinds to the caller and 'call @bar' unwinds to catch C0.
494
495; NOSORT-LABEL: test7
496; NOSORT: try
497; --- try-delegate starts (catch unwind mismatch)
498; NOSORT    try
499; NOSORT:     try
500; NOSORT:       call  foo
501; --- try-delegate starts (call unwind mismatch)
502; NOSORT:       try
503; NOSORT:         call  foo
504; NOSORT:       delegate    3     # label/catch{{[0-9]+}}: to caller
505; --- try-delegate ends (call unwind mismatch)
506; --- try-delegate starts (call unwind mismatch)
507; NOSORT:       try
508; NOSORT:         call  bar
509; NOSORT:       delegate    2     # label/catch{{[0-9]+}}: down to catch[[C0:[0-9]+]]
510; --- try-delegate ends (call unwind mismatch)
511; NOSORT:     catch   {{.*}}      # catch[[C1:[0-9]+]]:
512; NOSORT:     end_try
513; NOSORT:   delegate    1         # label/catch{{[0-9]+}}: to caller
514; --- try-delegate ends (catch unwind mismatch)
515; NOSORT: catch   {{.*}}        # catch[[C0]]:
516; NOSORT: end_try
517; NOSORT: return
518
519define void @test7() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
520bb0:
521  invoke void @foo()
522          to label %bb1 unwind label %catch.dispatch0
523
524bb1:                                              ; preds = %bb0
525  call void @foo()
526  invoke void @bar()
527          to label %try.cont unwind label %catch.dispatch1
528
529catch.dispatch0:                                  ; preds = %bb0
530  %0 = catchswitch within none [label %catch.start0] unwind to caller
531
532catch.start0:                                     ; preds = %catch.dispatch0
533  %1 = catchpad within %0 [i8* null]
534  %2 = call i8* @llvm.wasm.get.exception(token %1)
535  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
536  catchret from %1 to label %try.cont
537
538catch.dispatch1:                                  ; preds = %bb1
539  %4 = catchswitch within none [label %catch.start1] unwind to caller
540
541catch.start1:                                     ; preds = %catch.dispatch1
542  %5 = catchpad within %4 [i8* null]
543  %6 = call i8* @llvm.wasm.get.exception(token %5)
544  %7 = call i32 @llvm.wasm.get.ehselector(token %5)
545  catchret from %5 to label %try.cont
546
547try.cont:                                         ; preds = %catch.start1, %catch.start0, %bb1
548  ret void
549}
550
551; Similar situation as @test6. Here 'call @qux''s original unwind destination
552; was the caller, but after control flow linearization, their unwind destination
553; incorrectly becomes 'C0' within the function. We fix this by wrapping the call
554; with a nested try-delegate that rethrows the exception to the caller.
555
556; Because 'call @qux' pops an argument pushed by 'i32.const 5' from stack, the
557; nested 'try' should be placed before `i32.const 5', not between 'i32.const 5'
558; and 'call @qux'.
559
560; NOSORT-LABEL: test8
561; NOSORT: try       i32
562; NOSORT:   call  foo
563; --- try-delegate starts (call unwind mismatch)
564; NOSORT:   try
565; NOSORT:     i32.const  $push{{[0-9]+}}=, 5
566; NOSORT:     call  ${{[0-9]+}}=, qux
567; NOSORT:   delegate    1                     # label/catch{{[0-9]+}}: to caller
568; --- try-delegate ends (call unwind mismatch)
569; NOSORT:   return
570; NOSORT: catch   {{.*}}                      # catch[[C0:[0-9]+]]:
571; NOSORT:   return
572; NOSORT: end_try
573
574define i32 @test8() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
575bb0:
576  invoke void @foo()
577          to label %bb1 unwind label %catch.dispatch0
578
579bb1:                                              ; preds = %bb0
580  %0 = call i32 @qux(i32 5)
581  ret i32 %0
582
583catch.dispatch0:                                  ; preds = %bb0
584  %1 = catchswitch within none [label %catch.start0] unwind to caller
585
586catch.start0:                                     ; preds = %catch.dispatch0
587  %2 = catchpad within %1 [i8* null]
588  %3 = call i8* @llvm.wasm.get.exception(token %2)
589  %j = call i32 @llvm.wasm.get.ehselector(token %2)
590  catchret from %2 to label %try.cont
591
592try.cont:                                         ; preds = %catch.start0
593  ret i32 0
594}
595
596; Tests the case when TEE stackifies a register in RegStackify but it gets
597; unstackified in fixCallUnwindMismatches in CFGStackify.
598
599; NOSORT-LOCALS-LABEL: test9
600define void @test9(i32 %x) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
601bb0:
602  invoke void @foo()
603          to label %bb1 unwind label %catch.dispatch0
604
605bb1:                                              ; preds = %bb0
606  %t = add i32 %x, 4
607  ; This %addr is used in multiple places, so tee is introduced in RegStackify,
608  ; which stackifies the use of %addr in store instruction. A tee has two dest
609  ; registers, the first of which is stackified and the second is not.
610  ; But when we introduce a nested try-delegate in fixCallUnwindMismatches in
611  ; CFGStackify, it is possible that we end up unstackifying the first dest
612  ; register. In that case, we convert that tee into a copy.
613  %addr = inttoptr i32 %t to i32*
614  %load = load i32, i32* %addr
615  %call = call i32 @baz()
616  %add = add i32 %load, %call
617  store i32 %add, i32* %addr
618  ret void
619; NOSORT-LOCALS:       i32.add
620; NOSORT-LOCALS-NOT:   local.tee
621; NOSORT-LOCALS-NEXT:  local.set
622
623catch.dispatch0:                                  ; preds = %bb0
624  %0 = catchswitch within none [label %catch.start0] unwind to caller
625
626catch.start0:                                     ; preds = %catch.dispatch0
627  %1 = catchpad within %0 [i8* null]
628  %2 = call i8* @llvm.wasm.get.exception(token %1)
629  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
630  catchret from %1 to label %try.cont
631
632try.cont:                                         ; preds = %catch.start0
633  ret void
634}
635
636; We have two call unwind unwind mismatches:
637; - A may-throw instruction unwinds to an incorrect EH pad after linearizing the
638;   CFG, when it is supposed to unwind to another EH pad.
639; - A may-throw instruction unwinds to an incorrect EH pad after linearizing the
640;   CFG, when it is supposed to unwind to the caller.
641; We also have a catch unwind mismatch: If an exception is not caught by the
642; first catch because it is a non-C++ exception, it shouldn't unwind to the next
643; catch, but it should unwind to the caller.
644
645; NOSORT-LABEL: test10
646; NOSORT: try
647; --- try-delegate starts (catch unwind mismatch)
648; NOSORT:   try
649; NOSORT:     try
650; NOSORT:       call  foo
651; --- try-delegate starts (call unwind mismatch)
652; NOSORT:       try
653; NOSORT:         call  bar
654; NOSORT:       delegate    2            # label/catch{{[0-9]+}}: down to catch[[C0:[0-9]+]]
655; --- try-delegate ends (call unwind mismatch)
656; NOSORT:     catch
657; NOSORT:       call  {{.*}} __cxa_begin_catch
658; --- try-delegate starts (call unwind mismatch)
659; NOSORT:       try
660; NOSORT:         call  __cxa_end_catch
661; NOSORT:       delegate    3            # label/catch{{[0-9]+}}: to caller
662; --- try-delegate ends (call unwind mismatch)
663; NOSORT:     end_try
664; NOSORT:   delegate    1                # label/catch{{[0-9]+}}: to caller
665; --- try-delegate ends (catch unwind mismatch)
666; NOSORT: catch  {{.*}}                  # catch[[C0]]:
667; NOSORT:   call  {{.*}} __cxa_begin_catch
668; NOSORT:   call  __cxa_end_catch
669; NOSORT: end_try
670; NOSORT: return
671
672define void @test10() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
673bb0:
674  invoke void @foo()
675          to label %bb1 unwind label %catch.dispatch0
676
677bb1:                                              ; preds = %bb0
678  invoke void @bar()
679          to label %try.cont unwind label %catch.dispatch1
680
681catch.dispatch0:                                  ; preds = %bb0
682  %0 = catchswitch within none [label %catch.start0] unwind to caller
683
684catch.start0:                                     ; preds = %catch.dispatch0
685  %1 = catchpad within %0 [i8* null]
686  %2 = call i8* @llvm.wasm.get.exception(token %1)
687  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
688  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
689  call void @__cxa_end_catch() [ "funclet"(token %1) ]
690  catchret from %1 to label %try.cont
691
692catch.dispatch1:                                  ; preds = %bb1
693  %5 = catchswitch within none [label %catch.start1] unwind to caller
694
695catch.start1:                                     ; preds = %catch.dispatch1
696  %6 = catchpad within %5 [i8* null]
697  %7 = call i8* @llvm.wasm.get.exception(token %6)
698  %8 = call i32 @llvm.wasm.get.ehselector(token %6)
699  %9 = call i8* @__cxa_begin_catch(i8* %7) [ "funclet"(token %6) ]
700  call void @__cxa_end_catch() [ "funclet"(token %6) ]
701  catchret from %6 to label %try.cont
702
703try.cont:                                         ; preds = %catch.start1, %catch.start0, %bb1
704  ret void
705}
706
707; In CFGSort, EH pads should be sorted as soon as it is available and
708; 'Preferred' queue and should NOT be entered into 'Ready' queue unless we are
709; in the middle of sorting another region that does not contain the EH pad. In
710; this example, 'catch.start' should be sorted right after 'if.then' is sorted
711; (before 'cont' is sorted) and there should not be any unwind destination
712; mismatches in CFGStackify.
713
714; NOOPT-LABEL: test11
715; NOOPT: block
716; NOOPT:   try
717; NOOPT:     call      foo
718; NOOPT:   catch
719; NOOPT:   end_try
720; NOOPT:   call      foo
721; NOOPT: end_block
722; NOOPT: return
723define void @test11(i32 %arg) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
724entry:
725  %tobool = icmp ne i32 %arg, 0
726  br i1 %tobool, label %if.then, label %if.end
727
728catch.dispatch:                                   ; preds = %if.then
729  %0 = catchswitch within none [label %catch.start] unwind to caller
730
731catch.start:                                      ; preds = %catch.dispatch
732  %1 = catchpad within %0 [i8* null]
733  %2 = call i8* @llvm.wasm.get.exception(token %1)
734  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
735  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
736  call void @__cxa_end_catch() [ "funclet"(token %1) ]
737  catchret from %1 to label %if.end
738
739if.then:                                          ; preds = %entry
740  invoke void @foo()
741          to label %cont unwind label %catch.dispatch
742
743cont:                                             ; preds = %if.then
744  call void @foo()
745  br label %if.end
746
747if.end:                                           ; preds = %cont, %catch.start, %entry
748  ret void
749}
750
751; Intrinsics like memcpy, memmove, and memset don't throw and are lowered into
752; calls to external symbols (not global addresses) in instruction selection,
753; which will be eventually lowered to library function calls.
754; Because this test runs with -wasm-disable-ehpad-sort, these library calls in
755; invoke.cont BB fall within try~end_try, but they shouldn't cause crashes or
756; unwinding destination mismatches in CFGStackify.
757
758; NOSORT-LABEL: test12
759; NOSORT: try
760; NOSORT:   call  foo
761; NOSORT:   call {{.*}} memcpy
762; NOSORT:   call {{.*}} memmove
763; NOSORT:   call {{.*}} memset
764; NOSORT:   return
765; NOSORT: catch_all
766; NOSORT:   rethrow 0
767; NOSORT: end_try
768define void @test12(i8* %a, i8* %b) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
769entry:
770  %o = alloca %class.Object, align 1
771  invoke void @foo()
772          to label %invoke.cont unwind label %ehcleanup
773
774invoke.cont:                                      ; preds = %entry
775  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %b, i32 100, i1 false)
776  call void @llvm.memmove.p0i8.p0i8.i32(i8* %a, i8* %b, i32 100, i1 false)
777  call void @llvm.memset.p0i8.i32(i8* %a, i8 0, i32 100, i1 false)
778  %call = call %class.Object* @_ZN6ObjectD2Ev(%class.Object* %o)
779  ret void
780
781ehcleanup:                                        ; preds = %entry
782  %0 = cleanuppad within none []
783  %call2 = call %class.Object* @_ZN6ObjectD2Ev(%class.Object* %o) [ "funclet"(token %0) ]
784  cleanupret from %0 unwind to caller
785}
786
787; Tests if 'try' marker is placed correctly. In this test, 'try' should be
788; placed before the call to 'nothrow_i32' and not between the call to
789; 'nothrow_i32' and 'fun', because the return value of 'nothrow_i32' is
790; stackified and pushed onto the stack to be consumed by the call to 'fun'.
791
792; CHECK-LABEL: test13
793; CHECK: try
794; CHECK: call      $push{{.*}}=, nothrow_i32
795; CHECK: call      fun, $pop{{.*}}
796define void @test13() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
797entry:
798  %call = call i32 @nothrow_i32()
799  invoke void @fun(i32 %call)
800          to label %invoke.cont unwind label %terminate
801
802invoke.cont:                                      ; preds = %entry
803  ret void
804
805terminate:                                        ; preds = %entry
806  %0 = cleanuppad within none []
807  call void @_ZSt9terminatev() [ "funclet"(token %0) ]
808  unreachable
809}
810
811; This crashed on debug mode (= when NDEBUG is not defined) when the logic for
812; computing the innermost region was not correct, in which a loop region
813; contains an exception region. This should pass CFGSort without crashing.
814define void @test14() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
815entry:
816  %e = alloca %class.MyClass, align 4
817  br label %for.cond
818
819for.cond:                                         ; preds = %for.inc, %entry
820  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
821  %cmp = icmp slt i32 %i.0, 9
822  br i1 %cmp, label %for.body, label %for.end
823
824for.body:                                         ; preds = %for.cond
825  invoke void @quux(i32 %i.0)
826          to label %for.inc unwind label %catch.dispatch
827
828catch.dispatch:                                   ; preds = %for.body
829  %0 = catchswitch within none [label %catch.start] unwind to caller
830
831catch.start:                                      ; preds = %catch.dispatch
832  %1 = catchpad within %0 [i8* bitcast ({ i8*, i8* }* @_ZTI7MyClass to i8*)]
833  %2 = call i8* @llvm.wasm.get.exception(token %1)
834  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
835  %4 = call i32 @llvm.eh.typeid.for(i8* bitcast ({ i8*, i8* }* @_ZTI7MyClass to i8*))
836  %matches = icmp eq i32 %3, %4
837  br i1 %matches, label %catch, label %rethrow
838
839catch:                                            ; preds = %catch.start
840  %5 = call i8* @__cxa_get_exception_ptr(i8* %2) [ "funclet"(token %1) ]
841  %6 = bitcast i8* %5 to %class.MyClass*
842  %call = call %class.MyClass* @_ZN7MyClassC2ERKS_(%class.MyClass* %e, %class.MyClass* dereferenceable(4) %6) [ "funclet"(token %1) ]
843  %7 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
844  %x = getelementptr inbounds %class.MyClass, %class.MyClass* %e, i32 0, i32 0
845  %8 = load i32, i32* %x, align 4
846  invoke void @quux(i32 %8) [ "funclet"(token %1) ]
847          to label %invoke.cont2 unwind label %ehcleanup
848
849invoke.cont2:                                     ; preds = %catch
850  %call3 = call %class.MyClass* @_ZN7MyClassD2Ev(%class.MyClass* %e) [ "funclet"(token %1) ]
851  call void @__cxa_end_catch() [ "funclet"(token %1) ]
852  catchret from %1 to label %for.inc
853
854rethrow:                                          ; preds = %catch.start
855  call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]
856  unreachable
857
858for.inc:                                          ; preds = %invoke.cont2, %for.body
859  %inc = add nsw i32 %i.0, 1
860  br label %for.cond
861
862ehcleanup:                                        ; preds = %catch
863  %9 = cleanuppad within %1 []
864  %call4 = call %class.MyClass* @_ZN7MyClassD2Ev(%class.MyClass* %e) [ "funclet"(token %9) ]
865  invoke void @__cxa_end_catch() [ "funclet"(token %9) ]
866          to label %invoke.cont6 unwind label %terminate7
867
868invoke.cont6:                                     ; preds = %ehcleanup
869  cleanupret from %9 unwind to caller
870
871for.end:                                          ; preds = %for.cond
872  ret void
873
874terminate7:                                       ; preds = %ehcleanup
875  %10 = cleanuppad within %9 []
876  call void @_ZSt9terminatev() [ "funclet"(token %10) ]
877  unreachable
878}
879
880; Tests if CFGStackify's removeUnnecessaryInstrs() removes unnecessary branches
881; correctly. The code is in the form below, where 'br' is unnecessary because
882; after running the 'try' body the control flow will fall through to bb2 anyway.
883
884; bb0:
885;   try
886;     ...
887;     br bb2      <- Not necessary
888; bb1 (ehpad):
889;   catch
890;     ...
891; bb2:            <- Continuation BB
892;   end
893; CHECK-LABEL: test15
894define void @test15(i32 %n) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
895entry:
896  invoke void @foo()
897          to label %for.body unwind label %catch.dispatch
898
899for.body:                                         ; preds = %for.end, %entry
900  %i = phi i32 [ %inc, %for.end ], [ 0, %entry ]
901  invoke void @foo()
902          to label %for.end unwind label %catch.dispatch
903
904; Before going to CFGStackify, this BB will have a conditional branch followed
905; by an unconditional branch. CFGStackify should remove only the unconditional
906; one.
907for.end:                                          ; preds = %for.body
908  %inc = add nuw nsw i32 %i, 1
909  %exitcond = icmp eq i32 %inc, %n
910  br i1 %exitcond, label %try.cont, label %for.body
911; CHECK: br_if
912; CHECK-NOT: br
913; CHECK: end_loop
914; CHECK: catch
915
916catch.dispatch:                                   ; preds = %for.body, %entry
917  %0 = catchswitch within none [label %catch.start] unwind to caller
918
919catch.start:                                      ; preds = %catch.dispatch
920  %1 = catchpad within %0 [i8* null]
921  %2 = call i8* @llvm.wasm.get.exception(token %1)
922  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
923  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
924  call void @__cxa_end_catch() [ "funclet"(token %1) ]
925  catchret from %1 to label %try.cont
926
927try.cont:                                         ; preds = %catch.start, %for.end
928  ret void
929}
930
931; void foo();
932; void test16() {
933;   try {
934;     foo();
935;     try {
936;       foo();
937;     } catch (...) {
938;     }
939;   } catch (...) {
940;   }
941; }
942;
943; This tests whether the 'br' can be removed in code in the form as follows.
944; Here 'br' is inside an inner try, whose 'end' is in another EH pad. In this
945; case, after running an inner try body, the control flow should fall through to
946; bb3, so the 'br' in the code is unnecessary.
947
948; bb0:
949;   try
950;     try
951;       ...
952;       br bb3      <- Not necessary
953; bb1:
954;     catch
955; bb2:
956;     end_try
957;   catch
958;     ...
959; bb3:            <- Continuation BB
960;   end
961;
962; CHECK-LABEL: test16
963define void @test16() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
964; CHECK: call foo
965entry:
966  invoke void @foo()
967          to label %invoke.cont unwind label %catch.dispatch3
968
969; CHECK: call foo
970; CHECK-NOT: br
971invoke.cont:                                      ; preds = %entry
972  invoke void @foo()
973          to label %try.cont8 unwind label %catch.dispatch
974
975catch.dispatch:                                   ; preds = %invoke.cont
976  %0 = catchswitch within none [label %catch.start] unwind label %catch.dispatch3
977
978; CHECK: catch
979catch.start:                                      ; preds = %catch.dispatch
980  %1 = catchpad within %0 [i8* null]
981  %2 = call i8* @llvm.wasm.get.exception(token %1)
982  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
983  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
984  invoke void @__cxa_end_catch() [ "funclet"(token %1) ]
985          to label %invoke.cont2 unwind label %catch.dispatch3
986
987catch.dispatch3:                                  ; preds = %catch.start, %catch.dispatch, %entry
988  %5 = catchswitch within none [label %catch.start4] unwind to caller
989
990catch.start4:                                     ; preds = %catch.dispatch3
991  %6 = catchpad within %5 [i8* null]
992  %7 = call i8* @llvm.wasm.get.exception(token %6)
993  %8 = call i32 @llvm.wasm.get.ehselector(token %6)
994  %9 = call i8* @__cxa_begin_catch(i8* %7) [ "funclet"(token %6) ]
995  call void @__cxa_end_catch() [ "funclet"(token %6) ]
996  catchret from %6 to label %try.cont8
997
998try.cont8:                                        ; preds = %invoke.cont2, %catch.start4, %invoke.cont
999  ret void
1000
1001invoke.cont2:                                     ; preds = %catch.start
1002  catchret from %1 to label %try.cont8
1003}
1004
1005; Here an exception is semantically contained in a loop. 'ehcleanup' BB belongs
1006; to the exception, but does not belong to the loop (because it does not have a
1007; path back to the loop header), and is placed after the loop latch block
1008; 'invoke.cont' intentionally. This tests if 'end_loop' marker is placed
1009; correctly not right after 'invoke.cont' part but after 'ehcleanup' part,
1010; NOSORT-LABEL: test17
1011; NOSORT: loop
1012; NOSORT: try
1013; NOSORT: end_try
1014; NOSORT: end_loop
1015define void @test17(i32 %n) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1016entry:
1017  br label %while.cond
1018
1019while.cond:                                       ; preds = %invoke.cont, %entry
1020  %n.addr.0 = phi i32 [ %n, %entry ], [ %dec, %invoke.cont ]
1021  %tobool = icmp ne i32 %n.addr.0, 0
1022  br i1 %tobool, label %while.body, label %while.end
1023
1024while.body:                                       ; preds = %while.cond
1025  %dec = add nsw i32 %n.addr.0, -1
1026  invoke void @foo()
1027          to label %while.end unwind label %catch.dispatch
1028
1029catch.dispatch:                                   ; preds = %while.body
1030  %0 = catchswitch within none [label %catch.start] unwind to caller
1031
1032catch.start:                                      ; preds = %catch.dispatch
1033  %1 = catchpad within %0 [i8* null]
1034  %2 = call i8* @llvm.wasm.get.exception(token %1)
1035  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
1036  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
1037  invoke void @__cxa_end_catch() [ "funclet"(token %1) ]
1038          to label %invoke.cont unwind label %ehcleanup
1039
1040invoke.cont:                                      ; preds = %catch.start
1041  catchret from %1 to label %while.cond
1042
1043ehcleanup:                                        ; preds = %catch.start
1044  %5 = cleanuppad within %1 []
1045  call void @_ZSt9terminatev() [ "funclet"(token %5) ]
1046  unreachable
1047
1048while.end:                                        ; preds = %while.body, %while.cond
1049  ret void
1050}
1051
1052; When the function return type is non-void and 'end' instructions are at the
1053; very end of a function, CFGStackify's fixEndsAtEndOfFunction function fixes
1054; the corresponding block/loop/try's type to match the function's return type.
1055; But when a `try`'s type is fixed, we should also check `end` instructions
1056; before its corresponding `catch_all`, because both `try` and `catch_all` body
1057; should satisfy the return type requirements.
1058
1059; NOSORT-LABEL: test18
1060; NOSORT: try i32
1061; NOSORT: loop i32
1062; NOSORT: end_loop
1063; NOSORT: catch_all
1064; NOSORT: end_try
1065; NOSORT-NEXT: end_function
1066define i32 @test18(i32 %n) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1067entry:
1068  %t = alloca %class.Object, align 1
1069  br label %for.cond
1070
1071for.cond:                                         ; preds = %for.inc, %entry
1072  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
1073  %cmp = icmp slt i32 %i.0, %n
1074  br label %for.body
1075
1076for.body:                                         ; preds = %for.cond
1077  %div = sdiv i32 %n, 2
1078  %cmp1 = icmp eq i32 %i.0, %div
1079  br i1 %cmp1, label %if.then, label %for.inc
1080
1081if.then:                                          ; preds = %for.body
1082  %call = invoke i32 @baz()
1083          to label %invoke.cont unwind label %ehcleanup
1084
1085invoke.cont:                                      ; preds = %if.then
1086  %call2 = call %class.Object* @_ZN6ObjectD2Ev(%class.Object* %t)
1087  ret i32 %call
1088
1089for.inc:                                          ; preds = %for.body
1090  %inc = add nsw i32 %i.0, 1
1091  br label %for.cond
1092
1093ehcleanup:                                        ; preds = %if.then
1094  %0 = cleanuppad within none []
1095  %call3 = call %class.Object* @_ZN6ObjectD2Ev(%class.Object* %t) [ "funclet"(token %0) ]
1096  cleanupret from %0 unwind to caller
1097}
1098
1099; This crashed when updating EHPadStack within fixCallUniwindMismatch had a bug.
1100; This should not crash and try-delegate has to be created around 'call @baz',
1101; because the initial TRY placement for 'call @quux' was done before 'call @baz'
1102; because 'call @baz''s return value is stackified.
1103
1104; CHECK-LABEL: test19
1105; CHECK: try
1106; CHECK:   try
1107; CHECK:     call $[[RET:[0-9]+]]=, baz
1108; CHECK:   delegate  1
1109; CHECK:    call  quux, $[[RET]]
1110; CHECK: catch_all
1111; CHECK: end_try
1112define void @test19() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1113entry:
1114  %call = call i32 @baz()
1115  invoke void @quux(i32 %call)
1116          to label %invoke.cont unwind label %ehcleanup
1117
1118ehcleanup:                                        ; preds = %entry
1119  %0 = cleanuppad within none []
1120  cleanupret from %0 unwind to caller
1121
1122invoke.cont:                                      ; preds = %entry
1123  unreachable
1124}
1125
1126; This tests if invalidated branch destinations after fixing catch unwind
1127; mismatches are correctly remapped. For example, we have this code and suppose
1128; we need to wrap this try-catch-end in this code with a try-delegate to fix a
1129; catch unwind mismatch:
1130  ; - Before:
1131; block
1132;   br (a)
1133;   try
1134;   catch
1135;   end_try
1136; end_block
1137;           <- (a)
1138;
1139; - After
1140; block
1141;   br (a)
1142;   try
1143;     try
1144;     catch
1145;     end_try
1146;           <- (a)
1147;   delegate
1148; end_block
1149;           <- (b)
1150; After adding a try-delegate, the 'br's destination BB, where (a) points,
1151; becomes invalid because it incorrectly branches into an inner scope. The
1152; destination should change to the BB where (b) points.
1153
1154; NOSORT-LABEL: test20
1155; NOSORT: try
1156; NOSORT:   br_if   0
1157define void @test20(i1 %arg) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1158entry:
1159  br i1 %arg, label %bb0, label %dest
1160
1161bb0:                                              ; preds = %entry
1162  invoke void @foo()
1163          to label %bb1 unwind label %catch.dispatch0
1164
1165bb1:                                              ; preds = %bb0
1166  invoke void @bar()
1167          to label %try.cont unwind label %catch.dispatch1
1168
1169catch.dispatch0:                                  ; preds = %bb0
1170  %0 = catchswitch within none [label %catch.start0] unwind to caller
1171
1172catch.start0:                                     ; preds = %catch.dispatch0
1173  %1 = catchpad within %0 [i8* null]
1174  %2 = call i8* @llvm.wasm.get.exception(token %1)
1175  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
1176  catchret from %1 to label %try.cont
1177
1178dest:                                             ; preds = %entry
1179  ret void
1180
1181catch.dispatch1:                                  ; preds = %bb1
1182  %4 = catchswitch within none [label %catch.start1] unwind to caller
1183
1184catch.start1:                                     ; preds = %catch.dispatch1
1185  %5 = catchpad within %4 [i8* null]
1186  %6 = call i8* @llvm.wasm.get.exception(token %5)
1187  %7 = call i32 @llvm.wasm.get.ehselector(token %5)
1188  catchret from %5 to label %try.cont
1189
1190try.cont:                                         ; preds = %catch.start1, %catch.start0, %bb1
1191  ret void
1192}
1193
1194; The similar case with test20, but multiple consecutive delegates are
1195; generated:
1196; - Before:
1197; block
1198;   br (a)
1199;   try
1200;   catch
1201;   end_try
1202; end_block
1203;           <- (a)
1204;
1205; - After
1206; block
1207;   br (a)
1208;   try
1209;     ...
1210;     try
1211;       try
1212;       catch
1213;       end_try
1214;             <- (a)
1215;     delegate
1216;   delegate
1217; end_block
1218;           <- (b) The br destination should be remapped to here
1219;
1220; The test was reduced by bugpoint and should not crash in CFGStackify.
1221define void @test21() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1222entry:
1223  br i1 undef, label %if.then, label %if.end12
1224
1225if.then:                                          ; preds = %entry
1226  invoke void @__cxa_throw(i8* null, i8* null, i8* null) #1
1227          to label %unreachable unwind label %catch.dispatch
1228
1229catch.dispatch:                                   ; preds = %if.then
1230  %0 = catchswitch within none [label %catch.start] unwind to caller
1231
1232catch.start:                                      ; preds = %catch.dispatch
1233  %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
1234  %2 = call i8* @llvm.wasm.get.exception(token %1)
1235  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
1236  catchret from %1 to label %catchret.dest
1237
1238catchret.dest:                                    ; preds = %catch.start
1239  invoke void @foo()
1240          to label %invoke.cont unwind label %catch.dispatch4
1241
1242invoke.cont:                                      ; preds = %catchret.dest
1243  invoke void @__cxa_throw(i8* null, i8* null, i8* null) #1
1244          to label %unreachable unwind label %catch.dispatch4
1245
1246catch.dispatch4:                                  ; preds = %invoke.cont, %catchret.dest
1247  %4 = catchswitch within none [label %catch.start5] unwind to caller
1248
1249catch.start5:                                     ; preds = %catch.dispatch4
1250  %5 = catchpad within %4 [i8* bitcast (i8** @_ZTIi to i8*)]
1251  %6 = call i8* @llvm.wasm.get.exception(token %5)
1252  %7 = call i32 @llvm.wasm.get.ehselector(token %5)
1253  unreachable
1254
1255if.end12:                                         ; preds = %entry
1256  invoke void @foo()
1257          to label %invoke.cont14 unwind label %catch.dispatch16
1258
1259catch.dispatch16:                                 ; preds = %if.end12
1260  %8 = catchswitch within none [label %catch.start17] unwind label %ehcleanup
1261
1262catch.start17:                                    ; preds = %catch.dispatch16
1263  %9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
1264  %10 = call i8* @llvm.wasm.get.exception(token %9)
1265  %11 = call i32 @llvm.wasm.get.ehselector(token %9)
1266  br i1 undef, label %catch20, label %rethrow19
1267
1268catch20:                                          ; preds = %catch.start17
1269  catchret from %9 to label %catchret.dest22
1270
1271catchret.dest22:                                  ; preds = %catch20
1272  br label %try.cont23
1273
1274rethrow19:                                        ; preds = %catch.start17
1275  invoke void @llvm.wasm.rethrow() #1 [ "funclet"(token %9) ]
1276          to label %unreachable unwind label %ehcleanup
1277
1278try.cont23:                                       ; preds = %invoke.cont14, %catchret.dest22
1279  invoke void @foo()
1280          to label %invoke.cont24 unwind label %ehcleanup
1281
1282invoke.cont24:                                    ; preds = %try.cont23
1283  ret void
1284
1285invoke.cont14:                                    ; preds = %if.end12
1286  br label %try.cont23
1287
1288ehcleanup:                                        ; preds = %try.cont23, %rethrow19, %catch.dispatch16
1289  %12 = cleanuppad within none []
1290  cleanupret from %12 unwind to caller
1291
1292unreachable:                                      ; preds = %rethrow19, %invoke.cont, %if.then
1293  unreachable
1294}
1295
1296; Regression test for WasmEHFuncInfo's reverse mapping bug. 'UnwindDestToSrc'
1297; should return a vector and not a single BB, which was incorrect.
1298; This was reduced by bugpoint and should not crash in CFGStackify.
1299define void @test22() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1300entry:
1301  invoke void @foo()
1302          to label %invoke.cont unwind label %catch.dispatch
1303
1304catch.dispatch:                                   ; preds = %entry
1305  %0 = catchswitch within none [label %catch.start] unwind label %ehcleanup22
1306
1307catch.start:                                      ; preds = %catch.dispatch
1308  %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
1309  %2 = call i8* @llvm.wasm.get.exception(token %1)
1310  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
1311  invoke void @__cxa_throw(i8* null, i8* null, i8* null) #1 [ "funclet"(token %1) ]
1312          to label %unreachable unwind label %catch.dispatch2
1313
1314catch.dispatch2:                                  ; preds = %catch.start
1315  %4 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup
1316
1317catch.start3:                                     ; preds = %catch.dispatch2
1318  %5 = catchpad within %4 [i8* bitcast (i8** @_ZTIi to i8*)]
1319  %6 = call i8* @llvm.wasm.get.exception(token %5)
1320  %7 = call i32 @llvm.wasm.get.ehselector(token %5)
1321  catchret from %5 to label %try.cont
1322
1323try.cont:                                         ; preds = %catch.start3
1324  invoke void @foo() [ "funclet"(token %1) ]
1325          to label %invoke.cont8 unwind label %ehcleanup
1326
1327invoke.cont8:                                     ; preds = %try.cont
1328  invoke void @__cxa_throw(i8* null, i8* null, i8* null) #1 [ "funclet"(token %1) ]
1329          to label %unreachable unwind label %catch.dispatch11
1330
1331catch.dispatch11:                                 ; preds = %invoke.cont8
1332  %8 = catchswitch within %1 [label %catch.start12] unwind label %ehcleanup
1333
1334catch.start12:                                    ; preds = %catch.dispatch11
1335  %9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
1336  %10 = call i8* @llvm.wasm.get.exception(token %9)
1337  %11 = call i32 @llvm.wasm.get.ehselector(token %9)
1338  unreachable
1339
1340invoke.cont:                                      ; preds = %entry
1341  unreachable
1342
1343ehcleanup:                                        ; preds = %catch.dispatch11, %try.cont, %catch.dispatch2
1344  %12 = cleanuppad within %1 []
1345  cleanupret from %12 unwind label %ehcleanup22
1346
1347ehcleanup22:                                      ; preds = %ehcleanup, %catch.dispatch
1348  %13 = cleanuppad within none []
1349  cleanupret from %13 unwind to caller
1350
1351unreachable:                                      ; preds = %invoke.cont8, %catch.start
1352  unreachable
1353}
1354
1355; void test23() {
1356;   try {
1357;     try {
1358;       throw 0;
1359;     } catch (int) {
1360;     }
1361;   } catch (int) {
1362;   }
1363; }
1364;
1365; Regression test for a WebAssemblyException grouping bug. After catchswitches
1366; are removed, EH pad catch.start2 is dominated by catch.start, but because
1367; catch.start2 is the unwind destination of catch.start, it should not be
1368; included in catch.start's exception. Also, after we take catch.start2's
1369; exception out of catch.start's exception, we have to take out try.cont8 out of
1370; catch.start's exception, because it has a predecessor in catch.start2.
1371define void @test23() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1372entry:
1373  %exception = call i8* @__cxa_allocate_exception(i32 4) #0
1374  %0 = bitcast i8* %exception to i32*
1375  store i32 0, i32* %0, align 16
1376  invoke void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #1
1377          to label %unreachable unwind label %catch.dispatch
1378
1379catch.dispatch:                                   ; preds = %entry
1380  %1 = catchswitch within none [label %catch.start] unwind label %catch.dispatch1
1381
1382catch.start:                                      ; preds = %catch.dispatch
1383  %2 = catchpad within %1 [i8* bitcast (i8** @_ZTIi to i8*)]
1384  %3 = call i8* @llvm.wasm.get.exception(token %2)
1385  %4 = call i32 @llvm.wasm.get.ehselector(token %2)
1386  %5 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #0
1387  %matches = icmp eq i32 %4, %5
1388  br i1 %matches, label %catch, label %rethrow
1389
1390catch:                                            ; preds = %catch.start
1391  %6 = call i8* @__cxa_begin_catch(i8* %3) #0 [ "funclet"(token %2) ]
1392  %7 = bitcast i8* %6 to i32*
1393  %8 = load i32, i32* %7, align 4
1394  call void @__cxa_end_catch() #0 [ "funclet"(token %2) ]
1395  catchret from %2 to label %catchret.dest
1396
1397catchret.dest:                                    ; preds = %catch
1398  br label %try.cont
1399
1400rethrow:                                          ; preds = %catch.start
1401  invoke void @llvm.wasm.rethrow() #1 [ "funclet"(token %2) ]
1402          to label %unreachable unwind label %catch.dispatch1
1403
1404catch.dispatch1:                                  ; preds = %rethrow, %catch.dispatch
1405  %9 = catchswitch within none [label %catch.start2] unwind to caller
1406
1407catch.start2:                                     ; preds = %catch.dispatch1
1408  %10 = catchpad within %9 [i8* bitcast (i8** @_ZTIi to i8*)]
1409  %11 = call i8* @llvm.wasm.get.exception(token %10)
1410  %12 = call i32 @llvm.wasm.get.ehselector(token %10)
1411  %13 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #0
1412  %matches3 = icmp eq i32 %12, %13
1413  br i1 %matches3, label %catch5, label %rethrow4
1414
1415catch5:                                           ; preds = %catch.start2
1416  %14 = call i8* @__cxa_begin_catch(i8* %11) #0 [ "funclet"(token %10) ]
1417  %15 = bitcast i8* %14 to i32*
1418  %16 = load i32, i32* %15, align 4
1419  call void @__cxa_end_catch() #0 [ "funclet"(token %10) ]
1420  catchret from %10 to label %catchret.dest7
1421
1422catchret.dest7:                                   ; preds = %catch5
1423  br label %try.cont8
1424
1425rethrow4:                                         ; preds = %catch.start2
1426  call void @llvm.wasm.rethrow() #1 [ "funclet"(token %10) ]
1427  unreachable
1428
1429try.cont8:                                        ; preds = %try.cont, %catchret.dest7
1430  ret void
1431
1432try.cont:                                         ; preds = %catchret.dest
1433  br label %try.cont8
1434
1435unreachable:                                      ; preds = %rethrow, %entry
1436  unreachable
1437}
1438
1439; Test for WebAssemblyException grouping. This test is hand-modified to generate
1440; this structure:
1441; catch.start dominates catch.start4 and catch.start4 dominates catch.start12,
1442; so the after dominator-based grouping, we end up with:
1443; catch.start's exception > catch4.start's exception > catch12.start's exception
1444; (> here represents subexception relationship)
1445;
1446; But the unwind destination chain is catch.start -> catch.start4 ->
1447; catch.start12. So all these subexception relationship should be deconstructed.
1448; We have to make sure to take out catch.start4's exception out of catch.start's
1449; exception first, before taking out catch.start12's exception out of
1450; catch.start4's exception; otherwise we end up with an incorrect relationship
1451; of catch.start's exception > catch.start12's exception.
1452define void @test24() personality i8* bitcast (i32 (...)*
1453@__gxx_wasm_personality_v0 to i8*) {
1454entry:
1455  invoke void @foo()
1456          to label %invoke.cont unwind label %catch.dispatch
1457
1458invoke.cont:                                      ; preds = %entry
1459  invoke void @foo()
1460          to label %invoke.cont1 unwind label %catch.dispatch
1461
1462invoke.cont1:                                     ; preds = %invoke.cont
1463  invoke void @foo()
1464          to label %try.cont18 unwind label %catch.dispatch
1465
1466catch.dispatch11:                                 ; preds = %rethrow6, %catch.dispatch3
1467  %0 = catchswitch within none [label %catch.start12] unwind to caller
1468
1469catch.start12:                                    ; preds = %catch.dispatch11
1470  %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
1471  %2 = call i8* @llvm.wasm.get.exception(token %1)
1472  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
1473  %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #0
1474  %matches13 = icmp eq i32 %3, %4
1475  br i1 %matches13, label %catch15, label %rethrow14
1476
1477catch15:                                          ; preds = %catch.start12
1478  %5 = call i8* @__cxa_begin_catch(i8* %2) #0 [ "funclet"(token %1) ]
1479  %6 = bitcast i8* %5 to i32*
1480  %7 = load i32, i32* %6, align 4
1481  call void @__cxa_end_catch() #0 [ "funclet"(token %1) ]
1482  catchret from %1 to label %try.cont18
1483
1484rethrow14:                                        ; preds = %catch.start12
1485  call void @llvm.wasm.rethrow() #1 [ "funclet"(token %1) ]
1486  unreachable
1487
1488catch.dispatch3:                                  ; preds = %rethrow, %catch.dispatch
1489  %8 = catchswitch within none [label %catch.start4] unwind label %catch.dispatch11
1490
1491catch.start4:                                     ; preds = %catch.dispatch3
1492  %9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
1493  %10 = call i8* @llvm.wasm.get.exception(token %9)
1494  %11 = call i32 @llvm.wasm.get.ehselector(token %9)
1495  %12 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #0
1496  %matches5 = icmp eq i32 %11, %12
1497  br i1 %matches5, label %catch7, label %rethrow6
1498
1499catch7:                                           ; preds = %catch.start4
1500  %13 = call i8* @__cxa_begin_catch(i8* %10) #0 [ "funclet"(token %9) ]
1501  %14 = bitcast i8* %13 to i32*
1502  %15 = load i32, i32* %14, align 4
1503  call void @__cxa_end_catch() #0 [ "funclet"(token %9) ]
1504  catchret from %9 to label %try.cont18
1505
1506rethrow6:                                         ; preds = %catch.start4
1507  invoke void @llvm.wasm.rethrow() #1 [ "funclet"(token %9) ]
1508          to label %unreachable unwind label %catch.dispatch11
1509
1510catch.dispatch:                                   ; preds = %invoke.cont1, %invoke.cont, %entry
1511  %16 = catchswitch within none [label %catch.start] unwind label %catch.dispatch3
1512
1513catch.start:                                      ; preds = %catch.dispatch
1514  %17 = catchpad within %16 [i8* bitcast (i8** @_ZTIi to i8*)]
1515  %18 = call i8* @llvm.wasm.get.exception(token %17)
1516  %19 = call i32 @llvm.wasm.get.ehselector(token %17)
1517  %20 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #0
1518  %matches = icmp eq i32 %19, %20
1519  br i1 %matches, label %catch, label %rethrow
1520
1521catch:                                            ; preds = %catch.start
1522  %21 = call i8* @__cxa_begin_catch(i8* %18) #0 [ "funclet"(token %17) ]
1523  %22 = bitcast i8* %21 to i32*
1524  %23 = load i32, i32* %22, align 4
1525  call void @__cxa_end_catch() #0 [ "funclet"(token %17) ]
1526  catchret from %17 to label %try.cont18
1527
1528rethrow:                                          ; preds = %catch.start
1529  invoke void @llvm.wasm.rethrow() #1 [ "funclet"(token %17) ]
1530          to label %unreachable unwind label %catch.dispatch3
1531
1532try.cont18:                                       ; preds = %catch, %catch7, %catch15, %invoke.cont1
1533  ret void
1534
1535unreachable:                                      ; preds = %rethrow, %rethrow6
1536  unreachable
1537}
1538
1539; void test25() {
1540;   try {
1541;     try {
1542;       throw 0;
1543;     } catch (int) { // (a)
1544;     }
1545;   } catch (int) {   // (b)
1546;   }
1547;   try {
1548;     foo();
1549;   } catch (int) {   // (c)
1550;   }
1551; }
1552;
1553; Regression test for an ExceptionInfo grouping bug. Because the first (inner)
1554; try always throws, both EH pads (b) (catch.start2) and (c) (catch.start10) are
1555; dominated by EH pad (a) (catch.start), even though they are not semantically
1556; contained in (a)'s exception. Because (a)'s unwind destination is (b), (b)'s
1557; exception is taken out of (a)'s. But because (c) is reachable from (b), we
1558; should make sure to take out (c)'s exception out of (a)'s exception too.
1559define void @test25() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1560entry:
1561  %exception = call i8* @__cxa_allocate_exception(i32 4) #1
1562  %0 = bitcast i8* %exception to i32*
1563  store i32 0, i32* %0, align 16
1564  invoke void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #3
1565          to label %unreachable unwind label %catch.dispatch
1566
1567catch.dispatch:                                   ; preds = %entry
1568  %1 = catchswitch within none [label %catch.start] unwind label %catch.dispatch1
1569
1570catch.start:                                      ; preds = %catch.dispatch
1571  %2 = catchpad within %1 [i8* bitcast (i8** @_ZTIi to i8*)]
1572  %3 = call i8* @llvm.wasm.get.exception(token %2)
1573  %4 = call i32 @llvm.wasm.get.ehselector(token %2)
1574  %5 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #1
1575  %matches = icmp eq i32 %4, %5
1576  br i1 %matches, label %catch, label %rethrow
1577
1578catch:                                            ; preds = %catch.start
1579  %6 = call i8* @__cxa_begin_catch(i8* %3) #1 [ "funclet"(token %2) ]
1580  %7 = bitcast i8* %6 to i32*
1581  %8 = load i32, i32* %7, align 4
1582  call void @__cxa_end_catch() #1 [ "funclet"(token %2) ]
1583  catchret from %2 to label %try.cont8
1584
1585rethrow:                                          ; preds = %catch.start
1586  invoke void @llvm.wasm.rethrow() #3 [ "funclet"(token %2) ]
1587          to label %unreachable unwind label %catch.dispatch1
1588
1589catch.dispatch1:                                  ; preds = %rethrow, %catch.dispatch
1590  %9 = catchswitch within none [label %catch.start2] unwind to caller
1591
1592catch.start2:                                     ; preds = %catch.dispatch1
1593  %10 = catchpad within %9 [i8* bitcast (i8** @_ZTIi to i8*)]
1594  %11 = call i8* @llvm.wasm.get.exception(token %10)
1595  %12 = call i32 @llvm.wasm.get.ehselector(token %10)
1596  %13 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #1
1597  %matches3 = icmp eq i32 %12, %13
1598  br i1 %matches3, label %catch5, label %rethrow4
1599
1600catch5:                                           ; preds = %catch.start2
1601  %14 = call i8* @__cxa_begin_catch(i8* %11) #1 [ "funclet"(token %10) ]
1602  %15 = bitcast i8* %14 to i32*
1603  %16 = load i32, i32* %15, align 4
1604  call void @__cxa_end_catch() #1 [ "funclet"(token %10) ]
1605  catchret from %10 to label %try.cont8
1606
1607rethrow4:                                         ; preds = %catch.start2
1608  call void @llvm.wasm.rethrow() #3 [ "funclet"(token %10) ]
1609  unreachable
1610
1611try.cont8:                                        ; preds = %catch, %catch5
1612  invoke void @foo()
1613          to label %try.cont16 unwind label %catch.dispatch9
1614
1615catch.dispatch9:                                  ; preds = %try.cont8
1616  %17 = catchswitch within none [label %catch.start10] unwind to caller
1617
1618catch.start10:                                    ; preds = %catch.dispatch9
1619  %18 = catchpad within %17 [i8* bitcast (i8** @_ZTIi to i8*)]
1620  %19 = call i8* @llvm.wasm.get.exception(token %18)
1621  %20 = call i32 @llvm.wasm.get.ehselector(token %18)
1622  %21 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #1
1623  %matches11 = icmp eq i32 %20, %21
1624  br i1 %matches11, label %catch13, label %rethrow12
1625
1626catch13:                                          ; preds = %catch.start10
1627  %22 = call i8* @__cxa_begin_catch(i8* %19) #1 [ "funclet"(token %18) ]
1628  %23 = bitcast i8* %22 to i32*
1629  %24 = load i32, i32* %23, align 4
1630  call void @__cxa_end_catch() #1 [ "funclet"(token %18) ]
1631  catchret from %18 to label %try.cont16
1632
1633rethrow12:                                        ; preds = %catch.start10
1634  call void @llvm.wasm.rethrow() #3 [ "funclet"(token %18) ]
1635  unreachable
1636
1637try.cont16:                                       ; preds = %try.cont8, %catch13
1638  ret void
1639
1640unreachable:                                      ; preds = %rethrow, %entry
1641  unreachable
1642}
1643
1644; Check if the unwind destination mismatch stats are correct
1645; NOSORT: 23 wasm-cfg-stackify    - Number of call unwind mismatches found
1646; NOSORT:  4 wasm-cfg-stackify    - Number of catch unwind mismatches found
1647
1648declare void @foo()
1649declare void @bar()
1650declare i32 @baz()
1651declare i32 @qux(i32)
1652declare void @quux(i32)
1653declare void @fun(i32)
1654; Function Attrs: nounwind
1655declare void @nothrow(i32) #0
1656; Function Attrs: nounwind
1657declare i32 @nothrow_i32() #0
1658
1659; Function Attrs: nounwind
1660declare %class.Object* @_ZN6ObjectD2Ev(%class.Object* returned) #0
1661@_ZTI7MyClass = external constant { i8*, i8* }, align 4
1662; Function Attrs: nounwind
1663declare %class.MyClass* @_ZN7MyClassD2Ev(%class.MyClass* returned) #0
1664; Function Attrs: nounwind
1665declare %class.MyClass* @_ZN7MyClassC2ERKS_(%class.MyClass* returned, %class.MyClass* dereferenceable(4)) #0
1666
1667declare i32 @__gxx_wasm_personality_v0(...)
1668; Function Attrs: nounwind
1669declare i8* @llvm.wasm.get.exception(token) #0
1670; Function Attrs: nounwind
1671declare i32 @llvm.wasm.get.ehselector(token) #0
1672declare i8* @__cxa_allocate_exception(i32) #0
1673declare void @__cxa_throw(i8*, i8*, i8*)
1674; Function Attrs: noreturn
1675declare void @llvm.wasm.rethrow() #1
1676; Function Attrs: nounwind
1677declare i32 @llvm.eh.typeid.for(i8*) #0
1678
1679declare i8* @__cxa_begin_catch(i8*)
1680declare void @__cxa_end_catch()
1681declare i8* @__cxa_get_exception_ptr(i8*)
1682declare void @_ZSt9terminatev()
1683; Function Attrs: nounwind
1684declare void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i32, i1 immarg) #0
1685; Function Attrs: nounwind
1686declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1 immarg) #0
1687; Function Attrs: nounwind
1688declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1 immarg) #0
1689
1690attributes #0 = { nounwind }
1691attributes #1 = { noreturn }
1692