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 datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
9target triple = "wasm32-unknown-unknown"
10
11@_ZTIi = external constant i8*
12@_ZTId = external constant i8*
13
14%class.Object = type { i8 }
15%class.MyClass = type { i32 }
16
17; Simple test case with two catch clauses
18;
19; void foo();
20; void test0() {
21;   try {
22;     foo();
23;   } catch (int) {
24;   } catch (double) {
25;   }
26; }
27
28; CHECK-LABEL: test0
29; CHECK: try
30; CHECK:   call      foo
31; CHECK: catch
32; CHECK:   block
33; CHECK:     br_if     0, {{.*}}                       # 0: down to label[[L0:[0-9]+]]
34; CHECK:     call      $drop=, __cxa_begin_catch
35; CHECK:     call      __cxa_end_catch
36; CHECK:     br        1                               # 1: down to label[[L1:[0-9]+]]
37; CHECK:   end_block                                   # label[[L0]]:
38; CHECK:   block
39; CHECK:     br_if     0, {{.*}}                       # 0: down to label[[L2:[0-9]+]]
40; CHECK:     call      $drop=, __cxa_begin_catch
41; CHECK:     call      __cxa_end_catch
42; CHECK:     br        1                               # 1: down to label[[L1]]
43; CHECK:   end_block                                   # label[[L2]]:
44; CHECK:   rethrow   0                                 # to caller
45; CHECK: end_try                                       # label[[L1]]:
46define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
47entry:
48  invoke void @foo()
49          to label %try.cont unwind label %catch.dispatch
50
51catch.dispatch:                                   ; preds = %entry
52  %0 = catchswitch within none [label %catch.start] unwind to caller
53
54catch.start:                                      ; preds = %catch.dispatch
55  %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)]
56  %2 = call i8* @llvm.wasm.get.exception(token %1)
57  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
58  %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
59  %matches = icmp eq i32 %3, %4
60  br i1 %matches, label %catch2, label %catch.fallthrough
61
62catch2:                                           ; preds = %catch.start
63  %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
64  call void @__cxa_end_catch() [ "funclet"(token %1) ]
65  catchret from %1 to label %try.cont
66
67catch.fallthrough:                                ; preds = %catch.start
68  %6 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*))
69  %matches1 = icmp eq i32 %3, %6
70  br i1 %matches1, label %catch, label %rethrow
71
72catch:                                            ; preds = %catch.fallthrough
73  %7 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
74  call void @__cxa_end_catch() [ "funclet"(token %1) ]
75  catchret from %1 to label %try.cont
76
77rethrow:                                          ; preds = %catch.fallthrough
78  call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]
79  unreachable
80
81try.cont:                                         ; preds = %catch, %catch2, %entry
82  ret void
83}
84
85; Nested try-catches within a catch
86; void test1() {
87;   try {
88;     foo();
89;   } catch (int) {
90;     try {
91;       foo();
92;     } catch (int) {
93;       foo();
94;     }
95;   }
96; }
97
98; CHECK-LABEL: test1
99; CHECK: try
100; CHECK:   call      foo
101; CHECK: catch
102; CHECK:   block
103; CHECK:     block
104; CHECK:       br_if     0, {{.*}}                     # 0: down to label[[L0:[0-9]+]]
105; CHECK:       call      $drop=, __cxa_begin_catch
106; CHECK:       try
107; CHECK:         call      foo
108; CHECK:         br        2                           # 2: down to label[[L1:[0-9]+]]
109; CHECK:       catch
110; CHECK:         try
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
118; CHECK:               call      __cxa_end_catch
119; CHECK:               rethrow   0                     # down to catch[[C0:[0-9]+]]
120; CHECK:             end_try
121; CHECK:           end_block                           # label[[L2]]:
122; CHECK:           rethrow   1                         # down to catch[[C0]]
123; CHECK:         catch_all                             # catch[[C0]]:
124; CHECK:           call      __cxa_end_catch
125; CHECK:           rethrow   0                         # to caller
126; CHECK:         end_try                               # label[[L3]]:
127; CHECK:         call      __cxa_end_catch
128; CHECK:         br        2                           # 2: down to label[[L1]]
129; CHECK:       end_try
130; CHECK:     end_block                                 # label[[L0]]:
131; CHECK:     rethrow   1                               # to caller
132; CHECK:   end_block                                   # label[[L1]]:
133; CHECK:   call      __cxa_end_catch
134; CHECK: end_try
135define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
136entry:
137  invoke void @foo()
138          to label %try.cont11 unwind label %catch.dispatch
139
140catch.dispatch:                                   ; preds = %entry
141  %0 = catchswitch within none [label %catch.start] unwind to caller
142
143catch.start:                                      ; preds = %catch.dispatch
144  %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
145  %2 = call i8* @llvm.wasm.get.exception(token %1)
146  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
147  %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
148  %matches = icmp eq i32 %3, %4
149  br i1 %matches, label %catch, label %rethrow
150
151catch:                                            ; preds = %catch.start
152  %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
153  %6 = bitcast i8* %5 to i32*
154  %7 = load i32, i32* %6, align 4
155  invoke void @foo() [ "funclet"(token %1) ]
156          to label %try.cont unwind label %catch.dispatch2
157
158catch.dispatch2:                                  ; preds = %catch
159  %8 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup9
160
161catch.start3:                                     ; preds = %catch.dispatch2
162  %9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
163  %10 = call i8* @llvm.wasm.get.exception(token %9)
164  %11 = call i32 @llvm.wasm.get.ehselector(token %9)
165  %12 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
166  %matches4 = icmp eq i32 %11, %12
167  br i1 %matches4, label %catch6, label %rethrow5
168
169catch6:                                           ; preds = %catch.start3
170  %13 = call i8* @__cxa_begin_catch(i8* %10) [ "funclet"(token %9) ]
171  %14 = bitcast i8* %13 to i32*
172  %15 = load i32, i32* %14, align 4
173  invoke void @foo() [ "funclet"(token %9) ]
174          to label %invoke.cont8 unwind label %ehcleanup
175
176invoke.cont8:                                     ; preds = %catch6
177  call void @__cxa_end_catch() [ "funclet"(token %9) ]
178  catchret from %9 to label %try.cont
179
180rethrow5:                                         ; preds = %catch.start3
181  invoke void @llvm.wasm.rethrow() [ "funclet"(token %9) ]
182          to label %unreachable unwind label %ehcleanup9
183
184try.cont:                                         ; preds = %invoke.cont8, %catch
185  call void @__cxa_end_catch() [ "funclet"(token %1) ]
186  catchret from %1 to label %try.cont11
187
188rethrow:                                          ; preds = %catch.start
189  call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]
190  unreachable
191
192try.cont11:                                       ; preds = %try.cont, %entry
193  ret void
194
195ehcleanup:                                        ; preds = %catch6
196  %16 = cleanuppad within %9 []
197  call void @__cxa_end_catch() [ "funclet"(token %16) ]
198  cleanupret from %16 unwind label %ehcleanup9
199
200ehcleanup9:                                       ; preds = %ehcleanup, %rethrow5, %catch.dispatch2
201  %17 = cleanuppad within %1 []
202  call void @__cxa_end_catch() [ "funclet"(token %17) ]
203  cleanupret from %17 unwind to caller
204
205unreachable:                                      ; preds = %rethrow5
206  unreachable
207}
208
209; Nested loop within a catch clause
210; void test2() {
211;   try {
212;     foo();
213;   } catch (...) {
214;     for (int i = 0; i < 50; i++)
215;       foo();
216;   }
217; }
218
219; CHECK-LABEL: test2
220; CHECK: try
221; CHECK:   call      foo
222; CHECK: catch
223; CHECK:   call      $drop=, __cxa_begin_catch
224; CHECK:   loop                                        # label[[L0:[0-9]+]]:
225; CHECK:     block
226; CHECK:       block
227; CHECK:         br_if     0, {{.*}}                   # 0: down to label[[L1:[0-9]+]]
228; CHECK:         try
229; CHECK:           call      foo
230; CHECK:           br        2                         # 2: down to label[[L2:[0-9]+]]
231; CHECK:         catch
232; CHECK:           try
233; CHECK:             call      __cxa_end_catch
234; CHECK:           catch
235; CHECK:             call      __clang_call_terminate
236; CHECK:             unreachable
237; CHECK:           end_try
238; CHECK:           rethrow   0                         # to caller
239; CHECK:         end_try
240; CHECK:       end_block                               # label[[L1]]:
241; CHECK:       call      __cxa_end_catch
242; CHECK:       br        2                             # 2: down to label[[L3:[0-9]+]]
243; CHECK:     end_block                                 # label[[L2]]:
244; CHECK:     br        0                               # 0: up to label[[L0]]
245; CHECK:   end_loop
246; CHECK: end_try                                       # label[[L3]]:
247define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
248entry:
249  invoke void @foo()
250          to label %try.cont unwind label %catch.dispatch
251
252catch.dispatch:                                   ; preds = %entry
253  %0 = catchswitch within none [label %catch.start] unwind to caller
254
255catch.start:                                      ; preds = %catch.dispatch
256  %1 = catchpad within %0 [i8* null]
257  %2 = call i8* @llvm.wasm.get.exception(token %1)
258  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
259  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
260  br label %for.cond
261
262for.cond:                                         ; preds = %for.inc, %catch.start
263  %i.0 = phi i32 [ 0, %catch.start ], [ %inc, %for.inc ]
264  %cmp = icmp slt i32 %i.0, 50
265  br i1 %cmp, label %for.body, label %for.end
266
267for.body:                                         ; preds = %for.cond
268  invoke void @foo() [ "funclet"(token %1) ]
269          to label %for.inc unwind label %ehcleanup
270
271for.inc:                                          ; preds = %for.body
272  %inc = add nsw i32 %i.0, 1
273  br label %for.cond
274
275for.end:                                          ; preds = %for.cond
276  call void @__cxa_end_catch() [ "funclet"(token %1) ]
277  catchret from %1 to label %try.cont
278
279try.cont:                                         ; preds = %for.end, %entry
280  ret void
281
282ehcleanup:                                        ; preds = %for.body
283  %5 = cleanuppad within %1 []
284  invoke void @__cxa_end_catch() [ "funclet"(token %5) ]
285          to label %invoke.cont2 unwind label %terminate
286
287invoke.cont2:                                     ; preds = %ehcleanup
288  cleanupret from %5 unwind to caller
289
290terminate:                                        ; preds = %ehcleanup
291  %6 = cleanuppad within %5 []
292  %7 = call i8* @llvm.wasm.get.exception(token %6)
293  call void @__clang_call_terminate(i8* %7) [ "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  %1 = tail call i8* @llvm.wasm.get.exception(token %0)
808  call void @__clang_call_terminate(i8* %1) [ "funclet"(token %0) ]
809  unreachable
810}
811
812; This crashed on debug mode (= when NDEBUG is not defined) when the logic for
813; computing the innermost region was not correct, in which a loop region
814; contains an exception region. This should pass CFGSort without crashing.
815define void @test14() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
816entry:
817  %e = alloca %class.MyClass, align 4
818  br label %for.cond
819
820for.cond:                                         ; preds = %for.inc, %entry
821  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
822  %cmp = icmp slt i32 %i.0, 9
823  br i1 %cmp, label %for.body, label %for.end
824
825for.body:                                         ; preds = %for.cond
826  invoke void @quux(i32 %i.0)
827          to label %for.inc unwind label %catch.dispatch
828
829catch.dispatch:                                   ; preds = %for.body
830  %0 = catchswitch within none [label %catch.start] unwind to caller
831
832catch.start:                                      ; preds = %catch.dispatch
833  %1 = catchpad within %0 [i8* bitcast ({ i8*, i8* }* @_ZTI7MyClass to i8*)]
834  %2 = call i8* @llvm.wasm.get.exception(token %1)
835  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
836  %4 = call i32 @llvm.eh.typeid.for(i8* bitcast ({ i8*, i8* }* @_ZTI7MyClass to i8*))
837  %matches = icmp eq i32 %3, %4
838  br i1 %matches, label %catch, label %rethrow
839
840catch:                                            ; preds = %catch.start
841  %5 = call i8* @__cxa_get_exception_ptr(i8* %2) [ "funclet"(token %1) ]
842  %6 = bitcast i8* %5 to %class.MyClass*
843  %call = call %class.MyClass* @_ZN7MyClassC2ERKS_(%class.MyClass* %e, %class.MyClass* dereferenceable(4) %6) [ "funclet"(token %1) ]
844  %7 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
845  %x = getelementptr inbounds %class.MyClass, %class.MyClass* %e, i32 0, i32 0
846  %8 = load i32, i32* %x, align 4
847  invoke void @quux(i32 %8) [ "funclet"(token %1) ]
848          to label %invoke.cont2 unwind label %ehcleanup
849
850invoke.cont2:                                     ; preds = %catch
851  %call3 = call %class.MyClass* @_ZN7MyClassD2Ev(%class.MyClass* %e) [ "funclet"(token %1) ]
852  call void @__cxa_end_catch() [ "funclet"(token %1) ]
853  catchret from %1 to label %for.inc
854
855rethrow:                                          ; preds = %catch.start
856  call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]
857  unreachable
858
859for.inc:                                          ; preds = %invoke.cont2, %for.body
860  %inc = add nsw i32 %i.0, 1
861  br label %for.cond
862
863ehcleanup:                                        ; preds = %catch
864  %9 = cleanuppad within %1 []
865  %call4 = call %class.MyClass* @_ZN7MyClassD2Ev(%class.MyClass* %e) [ "funclet"(token %9) ]
866  invoke void @__cxa_end_catch() [ "funclet"(token %9) ]
867          to label %invoke.cont6 unwind label %terminate7
868
869invoke.cont6:                                     ; preds = %ehcleanup
870  cleanupret from %9 unwind to caller
871
872for.end:                                          ; preds = %for.cond
873  ret void
874
875terminate7:                                       ; preds = %ehcleanup
876  %10 = cleanuppad within %9 []
877  %11 = call i8* @llvm.wasm.get.exception(token %10)
878  call void @__clang_call_terminate(i8* %11) [ "funclet"(token %10) ]
879  unreachable
880}
881
882; Tests if CFGStackify's removeUnnecessaryInstrs() removes unnecessary branches
883; correctly. The code is in the form below, where 'br' is unnecessary because
884; after running the 'try' body the control flow will fall through to bb2 anyway.
885
886; bb0:
887;   try
888;     ...
889;     br bb2      <- Not necessary
890; bb1 (ehpad):
891;   catch
892;     ...
893; bb2:            <- Continuation BB
894;   end
895; CHECK-LABEL: test15
896define void @test15(i32 %n) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
897entry:
898  invoke void @foo()
899          to label %for.body unwind label %catch.dispatch
900
901for.body:                                         ; preds = %for.end, %entry
902  %i = phi i32 [ %inc, %for.end ], [ 0, %entry ]
903  invoke void @foo()
904          to label %for.end unwind label %catch.dispatch
905
906; Before going to CFGStackify, this BB will have a conditional branch followed
907; by an unconditional branch. CFGStackify should remove only the unconditional
908; one.
909for.end:                                          ; preds = %for.body
910  %inc = add nuw nsw i32 %i, 1
911  %exitcond = icmp eq i32 %inc, %n
912  br i1 %exitcond, label %try.cont, label %for.body
913; CHECK: br_if
914; CHECK-NOT: br
915; CHECK: end_loop
916; CHECK: catch
917
918catch.dispatch:                                   ; preds = %for.body, %entry
919  %0 = catchswitch within none [label %catch.start] unwind to caller
920
921catch.start:                                      ; preds = %catch.dispatch
922  %1 = catchpad within %0 [i8* null]
923  %2 = call i8* @llvm.wasm.get.exception(token %1)
924  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
925  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
926  call void @__cxa_end_catch() [ "funclet"(token %1) ]
927  catchret from %1 to label %try.cont
928
929try.cont:                                         ; preds = %catch.start, %for.end
930  ret void
931}
932
933; void foo();
934; void test16() {
935;   try {
936;     foo();
937;     try {
938;       foo();
939;     } catch (...) {
940;     }
941;   } catch (...) {
942;   }
943; }
944;
945; This tests whether the 'br' can be removed in code in the form as follows.
946; Here 'br' is inside an inner try, whose 'end' is in another EH pad. In this
947; case, after running an inner try body, the control flow should fall through to
948; bb3, so the 'br' in the code is unnecessary.
949
950; bb0:
951;   try
952;     try
953;       ...
954;       br bb3      <- Not necessary
955; bb1:
956;     catch
957; bb2:
958;     end_try
959;   catch
960;     ...
961; bb3:            <- Continuation BB
962;   end
963;
964; CHECK-LABEL: test16
965define void @test16() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
966; CHECK: call foo
967entry:
968  invoke void @foo()
969          to label %invoke.cont unwind label %catch.dispatch3
970
971; CHECK: call foo
972; CHECK-NOT: br
973invoke.cont:                                      ; preds = %entry
974  invoke void @foo()
975          to label %try.cont8 unwind label %catch.dispatch
976
977catch.dispatch:                                   ; preds = %invoke.cont
978  %0 = catchswitch within none [label %catch.start] unwind label %catch.dispatch3
979
980; CHECK: catch
981catch.start:                                      ; preds = %catch.dispatch
982  %1 = catchpad within %0 [i8* null]
983  %2 = call i8* @llvm.wasm.get.exception(token %1)
984  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
985  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
986  invoke void @__cxa_end_catch() [ "funclet"(token %1) ]
987          to label %invoke.cont2 unwind label %catch.dispatch3
988
989catch.dispatch3:                                  ; preds = %catch.start, %catch.dispatch, %entry
990  %5 = catchswitch within none [label %catch.start4] unwind to caller
991
992catch.start4:                                     ; preds = %catch.dispatch3
993  %6 = catchpad within %5 [i8* null]
994  %7 = call i8* @llvm.wasm.get.exception(token %6)
995  %8 = call i32 @llvm.wasm.get.ehselector(token %6)
996  %9 = call i8* @__cxa_begin_catch(i8* %7) [ "funclet"(token %6) ]
997  call void @__cxa_end_catch() [ "funclet"(token %6) ]
998  catchret from %6 to label %try.cont8
999
1000try.cont8:                                        ; preds = %invoke.cont2, %catch.start4, %invoke.cont
1001  ret void
1002
1003invoke.cont2:                                     ; preds = %catch.start
1004  catchret from %1 to label %try.cont8
1005}
1006
1007; Here an exception is semantically contained in a loop. 'ehcleanup' BB belongs
1008; to the exception, but does not belong to the loop (because it does not have a
1009; path back to the loop header), and is placed after the loop latch block
1010; 'invoke.cont' intentionally. This tests if 'end_loop' marker is placed
1011; correctly not right after 'invoke.cont' part but after 'ehcleanup' part,
1012; NOSORT-LABEL: test17
1013; NOSORT: loop
1014; NOSORT: try
1015; NOSORT: end_try
1016; NOSORT: end_loop
1017define void @test17(i32 %n) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1018entry:
1019  br label %while.cond
1020
1021while.cond:                                       ; preds = %invoke.cont, %entry
1022  %n.addr.0 = phi i32 [ %n, %entry ], [ %dec, %invoke.cont ]
1023  %tobool = icmp ne i32 %n.addr.0, 0
1024  br i1 %tobool, label %while.body, label %while.end
1025
1026while.body:                                       ; preds = %while.cond
1027  %dec = add nsw i32 %n.addr.0, -1
1028  invoke void @foo()
1029          to label %while.end unwind label %catch.dispatch
1030
1031catch.dispatch:                                   ; preds = %while.body
1032  %0 = catchswitch within none [label %catch.start] unwind to caller
1033
1034catch.start:                                      ; preds = %catch.dispatch
1035  %1 = catchpad within %0 [i8* null]
1036  %2 = call i8* @llvm.wasm.get.exception(token %1)
1037  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
1038  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
1039  invoke void @__cxa_end_catch() [ "funclet"(token %1) ]
1040          to label %invoke.cont unwind label %ehcleanup
1041
1042invoke.cont:                                      ; preds = %catch.start
1043  catchret from %1 to label %while.cond
1044
1045ehcleanup:                                        ; preds = %catch.start
1046  %5 = cleanuppad within %1 []
1047  %6 = call i8* @llvm.wasm.get.exception(token %5)
1048  call void @__clang_call_terminate(i8* %6) [ "funclet"(token %5) ]
1049  unreachable
1050
1051while.end:                                        ; preds = %while.body, %while.cond
1052  ret void
1053}
1054
1055; When the function return type is non-void and 'end' instructions are at the
1056; very end of a function, CFGStackify's fixEndsAtEndOfFunction function fixes
1057; the corresponding block/loop/try's type to match the function's return type.
1058; But when a `try`'s type is fixed, we should also check `end` instructions
1059; before its corresponding `catch_all`, because both `try` and `catch_all` body
1060; should satisfy the return type requirements.
1061
1062; NOSORT-LABEL: test18
1063; NOSORT: try i32
1064; NOSORT: loop i32
1065; NOSORT: end_loop
1066; NOSORT: catch_all
1067; NOSORT: end_try
1068; NOSORT-NEXT: end_function
1069define i32 @test18(i32 %n) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1070entry:
1071  %t = alloca %class.Object, align 1
1072  br label %for.cond
1073
1074for.cond:                                         ; preds = %for.inc, %entry
1075  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
1076  %cmp = icmp slt i32 %i.0, %n
1077  br label %for.body
1078
1079for.body:                                         ; preds = %for.cond
1080  %div = sdiv i32 %n, 2
1081  %cmp1 = icmp eq i32 %i.0, %div
1082  br i1 %cmp1, label %if.then, label %for.inc
1083
1084if.then:                                          ; preds = %for.body
1085  %call = invoke i32 @baz()
1086          to label %invoke.cont unwind label %ehcleanup
1087
1088invoke.cont:                                      ; preds = %if.then
1089  %call2 = call %class.Object* @_ZN6ObjectD2Ev(%class.Object* %t)
1090  ret i32 %call
1091
1092for.inc:                                          ; preds = %for.body
1093  %inc = add nsw i32 %i.0, 1
1094  br label %for.cond
1095
1096ehcleanup:                                        ; preds = %if.then
1097  %0 = cleanuppad within none []
1098  %call3 = call %class.Object* @_ZN6ObjectD2Ev(%class.Object* %t) [ "funclet"(token %0) ]
1099  cleanupret from %0 unwind to caller
1100}
1101
1102; This crashed when updating EHPadStack within fixCallUniwindMismatch had a bug.
1103; This should not crash and try-delegate has to be created around 'call @baz',
1104; because the initial TRY placement for 'call @quux' was done before 'call @baz'
1105; because 'call @baz''s return value is stackified.
1106
1107; CHECK-LABEL: test19
1108; CHECK: try
1109; CHECK:   try
1110; CHECK:     call $[[RET:[0-9]+]]=, baz
1111; CHECK:   delegate  1
1112; CHECK:    call  quux, $[[RET]]
1113; CHECK: catch_all
1114; CHECK: end_try
1115define void @test19() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1116entry:
1117  %call = call i32 @baz()
1118  invoke void @quux(i32 %call)
1119          to label %invoke.cont unwind label %ehcleanup
1120
1121ehcleanup:                                        ; preds = %entry
1122  %0 = cleanuppad within none []
1123  cleanupret from %0 unwind to caller
1124
1125invoke.cont:                                      ; preds = %entry
1126  unreachable
1127}
1128
1129; This tests if invalidated branch destinations after fixing catch unwind
1130; mismatches are correctly remapped. For example, we have this code and suppose
1131; we need to wrap this try-catch-end in this code with a try-delegate to fix a
1132; catch unwind mismatch:
1133  ; - Before:
1134; block
1135;   br (a)
1136;   try
1137;   catch
1138;   end_try
1139; end_block
1140;           <- (a)
1141;
1142; - After
1143; block
1144;   br (a)
1145;   try
1146;     try
1147;     catch
1148;     end_try
1149;           <- (a)
1150;   delegate
1151; end_block
1152;           <- (b)
1153; After adding a try-delegate, the 'br's destination BB, where (a) points,
1154; becomes invalid because it incorrectly branches into an inner scope. The
1155; destination should change to the BB where (b) points.
1156
1157; NOSORT-LABEL: test20
1158; NOSORT: try
1159; NOSORT:   br_if   0
1160define void @test20(i1 %arg) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
1161entry:
1162  br i1 %arg, label %bb0, label %dest
1163
1164bb0:                                              ; preds = %entry
1165  invoke void @foo()
1166          to label %bb1 unwind label %catch.dispatch0
1167
1168bb1:                                              ; preds = %bb0
1169  invoke void @bar()
1170          to label %try.cont unwind label %catch.dispatch1
1171
1172catch.dispatch0:                                  ; preds = %bb0
1173  %0 = catchswitch within none [label %catch.start0] unwind to caller
1174
1175catch.start0:                                     ; preds = %catch.dispatch0
1176  %1 = catchpad within %0 [i8* null]
1177  %2 = call i8* @llvm.wasm.get.exception(token %1)
1178  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
1179  catchret from %1 to label %try.cont
1180
1181dest:                                             ; preds = %entry
1182  ret void
1183
1184catch.dispatch1:                                  ; preds = %bb1
1185  %4 = catchswitch within none [label %catch.start1] unwind to caller
1186
1187catch.start1:                                     ; preds = %catch.dispatch1
1188  %5 = catchpad within %4 [i8* null]
1189  %6 = call i8* @llvm.wasm.get.exception(token %5)
1190  %7 = call i32 @llvm.wasm.get.ehselector(token %5)
1191  catchret from %5 to label %try.cont
1192
1193try.cont:                                         ; preds = %catch.start1, %catch.start0, %bb1
1194  ret void
1195}
1196
1197; Check if the unwind destination mismatch stats are correct
1198; NOSORT: 20 wasm-cfg-stackify    - Number of call unwind mismatches found
1199; NOSORT:  4 wasm-cfg-stackify    - Number of catch unwind mismatches found
1200
1201declare void @foo()
1202declare void @bar()
1203declare i32 @baz()
1204declare i32 @qux(i32)
1205declare void @quux(i32)
1206declare void @fun(i32)
1207; Function Attrs: nounwind
1208declare void @nothrow(i32) #0
1209; Function Attrs: nounwind
1210declare i32 @nothrow_i32() #0
1211
1212; Function Attrs: nounwind
1213declare %class.Object* @_ZN6ObjectD2Ev(%class.Object* returned) #0
1214@_ZTI7MyClass = external constant { i8*, i8* }, align 4
1215; Function Attrs: nounwind
1216declare %class.MyClass* @_ZN7MyClassD2Ev(%class.MyClass* returned) #0
1217; Function Attrs: nounwind
1218declare %class.MyClass* @_ZN7MyClassC2ERKS_(%class.MyClass* returned, %class.MyClass* dereferenceable(4)) #0
1219
1220declare i32 @__gxx_wasm_personality_v0(...)
1221; Function Attrs: nounwind
1222declare i8* @llvm.wasm.get.exception(token) #0
1223; Function Attrs: nounwind
1224declare i32 @llvm.wasm.get.ehselector(token) #0
1225; Function Attrs: noreturn
1226declare void @llvm.wasm.rethrow() #1
1227; Function Attrs: nounwind
1228declare i32 @llvm.eh.typeid.for(i8*) #0
1229
1230declare i8* @__cxa_begin_catch(i8*)
1231declare void @__cxa_end_catch()
1232declare i8* @__cxa_get_exception_ptr(i8*)
1233declare void @__clang_call_terminate(i8*)
1234declare void @_ZSt9terminatev()
1235; Function Attrs: nounwind
1236declare void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i32, i1 immarg) #0
1237; Function Attrs: nounwind
1238declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1 immarg) #0
1239; Function Attrs: nounwind
1240declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1 immarg) #0
1241
1242attributes #0 = { nounwind }
1243attributes #1 = { noreturn }
1244