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