[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / WebAssembly / cfg-stackify-eh.ll
blob28ae7be6eda71bf904cc8189a98d906bcaa63e76
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
8 target triple = "wasm32-unknown-unknown"
10 @_ZTIi = external constant i8*
11 @_ZTId = external constant i8*
13 %class.Object = type { i8 }
14 %class.MyClass = type { i32 }
16 ; Simple test case with two catch clauses
18 ; void foo();
19 ; void test0() {
20 ;   try {
21 ;     foo();
22 ;   } catch (int) {
23 ;   } catch (double) {
24 ;   }
25 ; }
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]]:
45 define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
46 entry:
47   invoke void @foo()
48           to label %try.cont unwind label %catch.dispatch
50 catch.dispatch:                                   ; preds = %entry
51   %0 = catchswitch within none [label %catch.start] unwind to caller
53 catch.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
61 catch2:                                           ; 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
66 catch.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
71 catch:                                            ; 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
76 rethrow:                                          ; preds = %catch.fallthrough
77   call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]
78   unreachable
80 try.cont:                                         ; preds = %catch, %catch2, %entry
81   ret void
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 ; }
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
136 define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
137 entry:
138   invoke void @foo()
139           to label %try.cont11 unwind label %catch.dispatch
141 catch.dispatch:                                   ; preds = %entry
142   %0 = catchswitch within none [label %catch.start] unwind to caller
144 catch.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
152 catch:                                            ; 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
159 catch.dispatch2:                                  ; preds = %catch
160   %8 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup9
162 catch.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
170 catch6:                                           ; 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
177 invoke.cont8:                                     ; preds = %catch6
178   call void @__cxa_end_catch() [ "funclet"(token %9) ]
179   catchret from %9 to label %try.cont
181 rethrow5:                                         ; preds = %catch.start3
182   invoke void @llvm.wasm.rethrow() [ "funclet"(token %9) ]
183           to label %unreachable unwind label %ehcleanup9
185 try.cont:                                         ; preds = %invoke.cont8, %catch
186   call void @__cxa_end_catch() [ "funclet"(token %1) ]
187   catchret from %1 to label %try.cont11
189 rethrow:                                          ; preds = %catch.start
190   call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]
191   unreachable
193 try.cont11:                                       ; preds = %try.cont, %entry
194   ret void
196 ehcleanup:                                        ; preds = %catch6
197   %16 = cleanuppad within %9 []
198   call void @__cxa_end_catch() [ "funclet"(token %16) ]
199   cleanupret from %16 unwind label %ehcleanup9
201 ehcleanup9:                                       ; 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
206 unreachable:                                      ; preds = %rethrow5
207   unreachable
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 ; }
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]]:
248 define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
249 entry:
250   invoke void @foo()
251           to label %try.cont unwind label %catch.dispatch
253 catch.dispatch:                                   ; preds = %entry
254   %0 = catchswitch within none [label %catch.start] unwind to caller
256 catch.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
263 for.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
268 for.body:                                         ; preds = %for.cond
269   invoke void @foo() [ "funclet"(token %1) ]
270           to label %for.inc unwind label %ehcleanup
272 for.inc:                                          ; preds = %for.body
273   %inc = add nsw i32 %i.0, 1
274   br label %for.cond
276 for.end:                                          ; preds = %for.cond
277   call void @__cxa_end_catch() [ "funclet"(token %1) ]
278   catchret from %1 to label %try.cont
280 try.cont:                                         ; preds = %for.end, %entry
281   ret void
283 ehcleanup:                                        ; 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
288 invoke.cont2:                                     ; preds = %ehcleanup
289   cleanupret from %5 unwind to caller
291 terminate:                                        ; preds = %ehcleanup
292   %6 = cleanuppad within %5 []
293   call void @_ZSt9terminatev() [ "funclet"(token %6) ]
294   unreachable
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.
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
314 define void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
315 bb0:
316   br i1 undef, label %bb1, label %bb2
318 bb1:                                              ; preds = %bb0
319   br i1 undef, label %bb3, label %bb4
321 bb2:                                              ; preds = %bb0
322   br label %try.cont
324 bb3:                                              ; preds = %bb1
325   invoke void @foo()
326           to label %try.cont unwind label %catch.dispatch
328 bb4:                                              ; preds = %bb1
329   invoke void @bar()
330           to label %try.cont unwind label %catch.dispatch
332 catch.dispatch:                                   ; preds = %bb4, %bb3
333   %0 = catchswitch within none [label %catch.start] unwind to caller
335 catch.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
341 try.cont:                                         ; preds = %catch.start, %bb4, %bb3, %bb2
342   ret void
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
354 define void @test4(i32* %p) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
355 entry:
356   store volatile i32 0, i32* %p
357   br label %loop
359 loop:                                             ; preds = %try.cont, %entry
360   store volatile i32 1, i32* %p
361   invoke void @foo()
362           to label %try.cont unwind label %catch.dispatch
364 catch.dispatch:                                   ; preds = %loop
365   %0 = catchswitch within none [label %catch.start] unwind to caller
367 catch.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
373 try.cont:                                         ; preds = %catch.start, %loop
374   br label %loop
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.
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.
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
412 define void @test5() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
413 bb0:
414   invoke void @foo()
415           to label %bb1 unwind label %catch.dispatch0
417 bb1:                                              ; preds = %bb0
418   invoke void @bar()
419           to label %try.cont unwind label %catch.dispatch1
421 catch.dispatch0:                                  ; preds = %bb0
422   %0 = catchswitch within none [label %catch.start0] unwind to caller
424 catch.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
430 catch.dispatch1:                                  ; preds = %bb1
431   %4 = catchswitch within none [label %catch.start1] unwind to caller
433 catch.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
439 try.cont:                                         ; preds = %catch.start1, %catch.start0, %bb1
440   ret void
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.
448 ; And the return value of 'baz' should NOT be stackified because the BB is split
449 ; during fixing unwind mismatches.
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
467 define void @test6() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
468 bb0:
469   invoke void @foo()
470           to label %bb1 unwind label %catch.dispatch0
472 bb1:                                              ; preds = %bb0
473   call void @bar()
474   %call = call i32 @baz()
475   call void @nothrow(i32 %call) #0
476   ret void
478 catch.dispatch0:                                  ; preds = %bb0
479   %0 = catchswitch within none [label %catch.start0] unwind to caller
481 catch.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
487 try.cont:                                         ; preds = %catch.start0
488   ret void
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.
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
519 define void @test7() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
520 bb0:
521   invoke void @foo()
522           to label %bb1 unwind label %catch.dispatch0
524 bb1:                                              ; preds = %bb0
525   call void @foo()
526   invoke void @bar()
527           to label %try.cont unwind label %catch.dispatch1
529 catch.dispatch0:                                  ; preds = %bb0
530   %0 = catchswitch within none [label %catch.start0] unwind to caller
532 catch.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
538 catch.dispatch1:                                  ; preds = %bb1
539   %4 = catchswitch within none [label %catch.start1] unwind to caller
541 catch.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
547 try.cont:                                         ; preds = %catch.start1, %catch.start0, %bb1
548   ret void
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.
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'.
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
574 define i32 @test8() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
575 bb0:
576   invoke void @foo()
577           to label %bb1 unwind label %catch.dispatch0
579 bb1:                                              ; preds = %bb0
580   %0 = call i32 @qux(i32 5)
581   ret i32 %0
583 catch.dispatch0:                                  ; preds = %bb0
584   %1 = catchswitch within none [label %catch.start0] unwind to caller
586 catch.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
592 try.cont:                                         ; preds = %catch.start0
593   ret i32 0
596 ; Tests the case when TEE stackifies a register in RegStackify but it gets
597 ; unstackified in fixCallUnwindMismatches in CFGStackify.
599 ; NOSORT-LOCALS-LABEL: test9
600 define void @test9(i32 %x) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
601 bb0:
602   invoke void @foo()
603           to label %bb1 unwind label %catch.dispatch0
605 bb1:                                              ; 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
623 catch.dispatch0:                                  ; preds = %bb0
624   %0 = catchswitch within none [label %catch.start0] unwind to caller
626 catch.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
632 try.cont:                                         ; preds = %catch.start0
633   ret void
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.
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
672 define void @test10() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
673 bb0:
674   invoke void @foo()
675           to label %bb1 unwind label %catch.dispatch0
677 bb1:                                              ; preds = %bb0
678   invoke void @bar()
679           to label %try.cont unwind label %catch.dispatch1
681 catch.dispatch0:                                  ; preds = %bb0
682   %0 = catchswitch within none [label %catch.start0] unwind to caller
684 catch.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
692 catch.dispatch1:                                  ; preds = %bb1
693   %5 = catchswitch within none [label %catch.start1] unwind to caller
695 catch.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
703 try.cont:                                         ; preds = %catch.start1, %catch.start0, %bb1
704   ret void
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.
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
723 define void @test11(i32 %arg) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
724 entry:
725   %tobool = icmp ne i32 %arg, 0
726   br i1 %tobool, label %if.then, label %if.end
728 catch.dispatch:                                   ; preds = %if.then
729   %0 = catchswitch within none [label %catch.start] unwind to caller
731 catch.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
739 if.then:                                          ; preds = %entry
740   invoke void @foo()
741           to label %cont unwind label %catch.dispatch
743 cont:                                             ; preds = %if.then
744   call void @foo()
745   br label %if.end
747 if.end:                                           ; preds = %cont, %catch.start, %entry
748   ret void
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.
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
768 define void @test12(i8* %a, i8* %b) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
769 entry:
770   %o = alloca %class.Object, align 1
771   invoke void @foo()
772           to label %invoke.cont unwind label %ehcleanup
774 invoke.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
781 ehcleanup:                                        ; 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
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'.
792 ; CHECK-LABEL: test13
793 ; CHECK: try
794 ; CHECK: call      $push{{.*}}=, nothrow_i32
795 ; CHECK: call      fun, $pop{{.*}}
796 define void @test13() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
797 entry:
798   %call = call i32 @nothrow_i32()
799   invoke void @fun(i32 %call)
800           to label %invoke.cont unwind label %terminate
802 invoke.cont:                                      ; preds = %entry
803   ret void
805 terminate:                                        ; preds = %entry
806   %0 = cleanuppad within none []
807   call void @_ZSt9terminatev() [ "funclet"(token %0) ]
808   unreachable
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.
814 define void @test14() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
815 entry:
816   %e = alloca %class.MyClass, align 4
817   br label %for.cond
819 for.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
824 for.body:                                         ; preds = %for.cond
825   invoke void @quux(i32 %i.0)
826           to label %for.inc unwind label %catch.dispatch
828 catch.dispatch:                                   ; preds = %for.body
829   %0 = catchswitch within none [label %catch.start] unwind to caller
831 catch.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
839 catch:                                            ; 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
849 invoke.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
854 rethrow:                                          ; preds = %catch.start
855   call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]
856   unreachable
858 for.inc:                                          ; preds = %invoke.cont2, %for.body
859   %inc = add nsw i32 %i.0, 1
860   br label %for.cond
862 ehcleanup:                                        ; 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
868 invoke.cont6:                                     ; preds = %ehcleanup
869   cleanupret from %9 unwind to caller
871 for.end:                                          ; preds = %for.cond
872   ret void
874 terminate7:                                       ; preds = %ehcleanup
875   %10 = cleanuppad within %9 []
876   call void @_ZSt9terminatev() [ "funclet"(token %10) ]
877   unreachable
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.
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
894 define void @test15(i32 %n) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
895 entry:
896   invoke void @foo()
897           to label %for.body unwind label %catch.dispatch
899 for.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
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.
907 for.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
916 catch.dispatch:                                   ; preds = %for.body, %entry
917   %0 = catchswitch within none [label %catch.start] unwind to caller
919 catch.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
927 try.cont:                                         ; preds = %catch.start, %for.end
928   ret void
931 ; void foo();
932 ; void test16() {
933 ;   try {
934 ;     foo();
935 ;     try {
936 ;       foo();
937 ;     } catch (...) {
938 ;     }
939 ;   } catch (...) {
940 ;   }
941 ; }
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.
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
962 ; CHECK-LABEL: test16
963 define void @test16() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
964 ; CHECK: call foo
965 entry:
966   invoke void @foo()
967           to label %invoke.cont unwind label %catch.dispatch3
969 ; CHECK: call foo
970 ; CHECK-NOT: br
971 invoke.cont:                                      ; preds = %entry
972   invoke void @foo()
973           to label %try.cont8 unwind label %catch.dispatch
975 catch.dispatch:                                   ; preds = %invoke.cont
976   %0 = catchswitch within none [label %catch.start] unwind label %catch.dispatch3
978 ; CHECK: catch
979 catch.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
987 catch.dispatch3:                                  ; preds = %catch.start, %catch.dispatch, %entry
988   %5 = catchswitch within none [label %catch.start4] unwind to caller
990 catch.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
998 try.cont8:                                        ; preds = %invoke.cont2, %catch.start4, %invoke.cont
999   ret void
1001 invoke.cont2:                                     ; preds = %catch.start
1002   catchret from %1 to label %try.cont8
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
1015 define void @test17(i32 %n) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1016 entry:
1017   br label %while.cond
1019 while.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
1024 while.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
1029 catch.dispatch:                                   ; preds = %while.body
1030   %0 = catchswitch within none [label %catch.start] unwind to caller
1032 catch.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
1040 invoke.cont:                                      ; preds = %catch.start
1041   catchret from %1 to label %while.cond
1043 ehcleanup:                                        ; preds = %catch.start
1044   %5 = cleanuppad within %1 []
1045   call void @_ZSt9terminatev() [ "funclet"(token %5) ]
1046   unreachable
1048 while.end:                                        ; preds = %while.body, %while.cond
1049   ret void
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.
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
1066 define i32 @test18(i32 %n) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1067 entry:
1068   %t = alloca %class.Object, align 1
1069   br label %for.cond
1071 for.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
1076 for.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
1081 if.then:                                          ; preds = %for.body
1082   %call = invoke i32 @baz()
1083           to label %invoke.cont unwind label %ehcleanup
1085 invoke.cont:                                      ; preds = %if.then
1086   %call2 = call %class.Object* @_ZN6ObjectD2Ev(%class.Object* %t)
1087   ret i32 %call
1089 for.inc:                                          ; preds = %for.body
1090   %inc = add nsw i32 %i.0, 1
1091   br label %for.cond
1093 ehcleanup:                                        ; 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
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.
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
1112 define void @test19() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1113 entry:
1114   %call = call i32 @baz()
1115   invoke void @quux(i32 %call)
1116           to label %invoke.cont unwind label %ehcleanup
1118 ehcleanup:                                        ; preds = %entry
1119   %0 = cleanuppad within none []
1120   cleanupret from %0 unwind to caller
1122 invoke.cont:                                      ; preds = %entry
1123   unreachable
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)
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.
1154 ; NOSORT-LABEL: test20
1155 ; NOSORT: try
1156 ; NOSORT:   br_if   0
1157 define void @test20(i1 %arg) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1158 entry:
1159   br i1 %arg, label %bb0, label %dest
1161 bb0:                                              ; preds = %entry
1162   invoke void @foo()
1163           to label %bb1 unwind label %catch.dispatch0
1165 bb1:                                              ; preds = %bb0
1166   invoke void @bar()
1167           to label %try.cont unwind label %catch.dispatch1
1169 catch.dispatch0:                                  ; preds = %bb0
1170   %0 = catchswitch within none [label %catch.start0] unwind to caller
1172 catch.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
1178 dest:                                             ; preds = %entry
1179   ret void
1181 catch.dispatch1:                                  ; preds = %bb1
1182   %4 = catchswitch within none [label %catch.start1] unwind to caller
1184 catch.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
1190 try.cont:                                         ; preds = %catch.start1, %catch.start0, %bb1
1191   ret void
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)
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
1220 ; The test was reduced by bugpoint and should not crash in CFGStackify.
1221 define void @test21() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1222 entry:
1223   br i1 undef, label %if.then, label %if.end12
1225 if.then:                                          ; preds = %entry
1226   invoke void @__cxa_throw(i8* null, i8* null, i8* null) #1
1227           to label %unreachable unwind label %catch.dispatch
1229 catch.dispatch:                                   ; preds = %if.then
1230   %0 = catchswitch within none [label %catch.start] unwind to caller
1232 catch.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
1238 catchret.dest:                                    ; preds = %catch.start
1239   invoke void @foo()
1240           to label %invoke.cont unwind label %catch.dispatch4
1242 invoke.cont:                                      ; preds = %catchret.dest
1243   invoke void @__cxa_throw(i8* null, i8* null, i8* null) #1
1244           to label %unreachable unwind label %catch.dispatch4
1246 catch.dispatch4:                                  ; preds = %invoke.cont, %catchret.dest
1247   %4 = catchswitch within none [label %catch.start5] unwind to caller
1249 catch.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
1255 if.end12:                                         ; preds = %entry
1256   invoke void @foo()
1257           to label %invoke.cont14 unwind label %catch.dispatch16
1259 catch.dispatch16:                                 ; preds = %if.end12
1260   %8 = catchswitch within none [label %catch.start17] unwind label %ehcleanup
1262 catch.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
1268 catch20:                                          ; preds = %catch.start17
1269   catchret from %9 to label %catchret.dest22
1271 catchret.dest22:                                  ; preds = %catch20
1272   br label %try.cont23
1274 rethrow19:                                        ; preds = %catch.start17
1275   invoke void @llvm.wasm.rethrow() #1 [ "funclet"(token %9) ]
1276           to label %unreachable unwind label %ehcleanup
1278 try.cont23:                                       ; preds = %invoke.cont14, %catchret.dest22
1279   invoke void @foo()
1280           to label %invoke.cont24 unwind label %ehcleanup
1282 invoke.cont24:                                    ; preds = %try.cont23
1283   ret void
1285 invoke.cont14:                                    ; preds = %if.end12
1286   br label %try.cont23
1288 ehcleanup:                                        ; preds = %try.cont23, %rethrow19, %catch.dispatch16
1289   %12 = cleanuppad within none []
1290   cleanupret from %12 unwind to caller
1292 unreachable:                                      ; preds = %rethrow19, %invoke.cont, %if.then
1293   unreachable
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.
1299 define void @test22() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1300 entry:
1301   invoke void @foo()
1302           to label %invoke.cont unwind label %catch.dispatch
1304 catch.dispatch:                                   ; preds = %entry
1305   %0 = catchswitch within none [label %catch.start] unwind label %ehcleanup22
1307 catch.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
1314 catch.dispatch2:                                  ; preds = %catch.start
1315   %4 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup
1317 catch.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
1323 try.cont:                                         ; preds = %catch.start3
1324   invoke void @foo() [ "funclet"(token %1) ]
1325           to label %invoke.cont8 unwind label %ehcleanup
1327 invoke.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
1331 catch.dispatch11:                                 ; preds = %invoke.cont8
1332   %8 = catchswitch within %1 [label %catch.start12] unwind label %ehcleanup
1334 catch.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
1340 invoke.cont:                                      ; preds = %entry
1341   unreachable
1343 ehcleanup:                                        ; preds = %catch.dispatch11, %try.cont, %catch.dispatch2
1344   %12 = cleanuppad within %1 []
1345   cleanupret from %12 unwind label %ehcleanup22
1347 ehcleanup22:                                      ; preds = %ehcleanup, %catch.dispatch
1348   %13 = cleanuppad within none []
1349   cleanupret from %13 unwind to caller
1351 unreachable:                                      ; preds = %invoke.cont8, %catch.start
1352   unreachable
1355 ; void test23() {
1356 ;   try {
1357 ;     try {
1358 ;       throw 0;
1359 ;     } catch (int) {
1360 ;     }
1361 ;   } catch (int) {
1362 ;   }
1363 ; }
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.
1371 define void @test23() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1372 entry:
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
1379 catch.dispatch:                                   ; preds = %entry
1380   %1 = catchswitch within none [label %catch.start] unwind label %catch.dispatch1
1382 catch.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
1390 catch:                                            ; 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
1397 catchret.dest:                                    ; preds = %catch
1398   br label %try.cont
1400 rethrow:                                          ; preds = %catch.start
1401   invoke void @llvm.wasm.rethrow() #1 [ "funclet"(token %2) ]
1402           to label %unreachable unwind label %catch.dispatch1
1404 catch.dispatch1:                                  ; preds = %rethrow, %catch.dispatch
1405   %9 = catchswitch within none [label %catch.start2] unwind to caller
1407 catch.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
1415 catch5:                                           ; 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
1422 catchret.dest7:                                   ; preds = %catch5
1423   br label %try.cont8
1425 rethrow4:                                         ; preds = %catch.start2
1426   call void @llvm.wasm.rethrow() #1 [ "funclet"(token %10) ]
1427   unreachable
1429 try.cont8:                                        ; preds = %try.cont, %catchret.dest7
1430   ret void
1432 try.cont:                                         ; preds = %catchret.dest
1433   br label %try.cont8
1435 unreachable:                                      ; preds = %rethrow, %entry
1436   unreachable
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)
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.
1452 define void @test24() personality i8* bitcast (i32 (...)*
1453 @__gxx_wasm_personality_v0 to i8*) {
1454 entry:
1455   invoke void @foo()
1456           to label %invoke.cont unwind label %catch.dispatch
1458 invoke.cont:                                      ; preds = %entry
1459   invoke void @foo()
1460           to label %invoke.cont1 unwind label %catch.dispatch
1462 invoke.cont1:                                     ; preds = %invoke.cont
1463   invoke void @foo()
1464           to label %try.cont18 unwind label %catch.dispatch
1466 catch.dispatch11:                                 ; preds = %rethrow6, %catch.dispatch3
1467   %0 = catchswitch within none [label %catch.start12] unwind to caller
1469 catch.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
1477 catch15:                                          ; 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
1484 rethrow14:                                        ; preds = %catch.start12
1485   call void @llvm.wasm.rethrow() #1 [ "funclet"(token %1) ]
1486   unreachable
1488 catch.dispatch3:                                  ; preds = %rethrow, %catch.dispatch
1489   %8 = catchswitch within none [label %catch.start4] unwind label %catch.dispatch11
1491 catch.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
1499 catch7:                                           ; 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
1506 rethrow6:                                         ; preds = %catch.start4
1507   invoke void @llvm.wasm.rethrow() #1 [ "funclet"(token %9) ]
1508           to label %unreachable unwind label %catch.dispatch11
1510 catch.dispatch:                                   ; preds = %invoke.cont1, %invoke.cont, %entry
1511   %16 = catchswitch within none [label %catch.start] unwind label %catch.dispatch3
1513 catch.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
1521 catch:                                            ; 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
1528 rethrow:                                          ; preds = %catch.start
1529   invoke void @llvm.wasm.rethrow() #1 [ "funclet"(token %17) ]
1530           to label %unreachable unwind label %catch.dispatch3
1532 try.cont18:                                       ; preds = %catch, %catch7, %catch15, %invoke.cont1
1533   ret void
1535 unreachable:                                      ; preds = %rethrow, %rethrow6
1536   unreachable
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 ; }
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.
1559 define void @test25() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1560 entry:
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
1567 catch.dispatch:                                   ; preds = %entry
1568   %1 = catchswitch within none [label %catch.start] unwind label %catch.dispatch1
1570 catch.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
1578 catch:                                            ; 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
1585 rethrow:                                          ; preds = %catch.start
1586   invoke void @llvm.wasm.rethrow() #3 [ "funclet"(token %2) ]
1587           to label %unreachable unwind label %catch.dispatch1
1589 catch.dispatch1:                                  ; preds = %rethrow, %catch.dispatch
1590   %9 = catchswitch within none [label %catch.start2] unwind to caller
1592 catch.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
1600 catch5:                                           ; 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
1607 rethrow4:                                         ; preds = %catch.start2
1608   call void @llvm.wasm.rethrow() #3 [ "funclet"(token %10) ]
1609   unreachable
1611 try.cont8:                                        ; preds = %catch, %catch5
1612   invoke void @foo()
1613           to label %try.cont16 unwind label %catch.dispatch9
1615 catch.dispatch9:                                  ; preds = %try.cont8
1616   %17 = catchswitch within none [label %catch.start10] unwind to caller
1618 catch.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
1626 catch13:                                          ; 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
1633 rethrow12:                                        ; preds = %catch.start10
1634   call void @llvm.wasm.rethrow() #3 [ "funclet"(token %18) ]
1635   unreachable
1637 try.cont16:                                       ; preds = %try.cont8, %catch13
1638   ret void
1640 unreachable:                                      ; preds = %rethrow, %entry
1641   unreachable
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
1648 declare void @foo()
1649 declare void @bar()
1650 declare i32 @baz()
1651 declare i32 @qux(i32)
1652 declare void @quux(i32)
1653 declare void @fun(i32)
1654 ; Function Attrs: nounwind
1655 declare void @nothrow(i32) #0
1656 ; Function Attrs: nounwind
1657 declare i32 @nothrow_i32() #0
1659 ; Function Attrs: nounwind
1660 declare %class.Object* @_ZN6ObjectD2Ev(%class.Object* returned) #0
1661 @_ZTI7MyClass = external constant { i8*, i8* }, align 4
1662 ; Function Attrs: nounwind
1663 declare %class.MyClass* @_ZN7MyClassD2Ev(%class.MyClass* returned) #0
1664 ; Function Attrs: nounwind
1665 declare %class.MyClass* @_ZN7MyClassC2ERKS_(%class.MyClass* returned, %class.MyClass* dereferenceable(4)) #0
1667 declare i32 @__gxx_wasm_personality_v0(...)
1668 ; Function Attrs: nounwind
1669 declare i8* @llvm.wasm.get.exception(token) #0
1670 ; Function Attrs: nounwind
1671 declare i32 @llvm.wasm.get.ehselector(token) #0
1672 declare i8* @__cxa_allocate_exception(i32) #0
1673 declare void @__cxa_throw(i8*, i8*, i8*)
1674 ; Function Attrs: noreturn
1675 declare void @llvm.wasm.rethrow() #1
1676 ; Function Attrs: nounwind
1677 declare i32 @llvm.eh.typeid.for(i8*) #0
1679 declare i8* @__cxa_begin_catch(i8*)
1680 declare void @__cxa_end_catch()
1681 declare i8* @__cxa_get_exception_ptr(i8*)
1682 declare void @_ZSt9terminatev()
1683 ; Function Attrs: nounwind
1684 declare void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i32, i1 immarg) #0
1685 ; Function Attrs: nounwind
1686 declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1 immarg) #0
1687 ; Function Attrs: nounwind
1688 declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1 immarg) #0
1690 attributes #0 = { nounwind }
1691 attributes #1 = { noreturn }