brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.3 KiB · 873386b Raw
675 lines · plain
1; RUN: llc < %s -asm-verbose=false -wasm-enable-eh -wasm-use-legacy-eh=false -exception-model=wasm -mattr=+exception-handling -verify-machineinstrs | FileCheck --implicit-check-not=ehgcr -allow-deprecated-dag-overlap %s2; RUN: llc < %s -asm-verbose=false -wasm-enable-eh -wasm-use-legacy-eh=false -exception-model=wasm -mattr=+exception-handling -verify-machineinstrs -O03; RUN: llc < %s -wasm-enable-eh -wasm-use-legacy-eh=false -exception-model=wasm -mattr=+exception-handling4; RUN: llc < %s -wasm-enable-eh -wasm-use-legacy-eh=false -exception-model=wasm -mattr=+exception-handling -filetype=obj5; RUN: llc < %s -mtriple=wasm64-unknown-unknown -wasm-enable-eh -wasm-use-legacy-eh=false -exception-model=wasm -mattr=+exception-handling -verify-machineinstrs | FileCheck --implicit-check-not=ehgcr -allow-deprecated-dag-overlap %s --check-prefix=WASM646 7target triple = "wasm32-unknown-unknown"8 9%struct.Temp = type { i8 }10 11@_ZTIi = external dso_local constant ptr12 13; CHECK: .tagtype  __cpp_exception i3214 15; CHECK-LABEL: throw:16; CHECK:     throw __cpp_exception17; CHECK-NOT: unreachable18define void @throw(ptr %p) {19  call void @llvm.wasm.throw(i32 0, ptr %p)20  ret void21}22 23; Simple test with a try-catch24;25; void foo();26; void catch() {27;   try {28;     foo();29;   } catch (int) {30;   }31; }32 33; CHECK-LABEL: catch:34; WASM64-LABEL: catch:35; CHECK: global.get  __stack_pointer36; CHECK: local.set  037; CHECK: block38; CHECK:   block     () -> (i32, exnref)39; CHECK:     try_table    (catch_ref __cpp_exception 0)40; WASM64:  block     () -> (i64, exnref)41; CHECK:       call  foo42; CHECK:       br        243; CHECK:     end_try_table44; CHECK:     unreachable45; CHECK:   end_block46; CHECK:   local.set  247; CHECK:   local.get  048; CHECK:   global.set  __stack_pointer49; CHECK:   i32.store  __wasm_lpad_context50; CHECK:   call  _Unwind_CallPersonality51; CHECK:   block52; CHECK:     br_if     053; CHECK:     call  __cxa_begin_catch54; CHECK:     call  __cxa_end_catch55; CHECK:     br        156; CHECK:   end_block57; CHECK:   local.get  258; CHECK:   throw_ref59; CHECK: end_block60define void @catch() personality ptr @__gxx_wasm_personality_v0 {61entry:62  invoke void @foo()63          to label %try.cont unwind label %catch.dispatch64 65catch.dispatch:                                   ; preds = %entry66  %0 = catchswitch within none [label %catch.start] unwind to caller67 68catch.start:                                      ; preds = %catch.dispatch69  %1 = catchpad within %0 [ptr @_ZTIi]70  %2 = call ptr @llvm.wasm.get.exception(token %1)71  %3 = call i32 @llvm.wasm.get.ehselector(token %1)72  %4 = call i32 @llvm.eh.typeid.for(ptr @_ZTIi)73  %matches = icmp eq i32 %3, %474  br i1 %matches, label %catch, label %rethrow75 76catch:                                            ; preds = %catch.start77  %5 = call ptr @__cxa_begin_catch(ptr %2) [ "funclet"(token %1) ]78  call void @__cxa_end_catch() [ "funclet"(token %1) ]79  catchret from %1 to label %try.cont80 81rethrow:                                          ; preds = %catch.start82  call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]83  unreachable84 85try.cont:                                         ; preds = %catch, %entry86  ret void87}88 89; Destructor (cleanup) test90;91; void foo();92; struct Temp {93;   ~Temp() {}94; };95; void cleanup() {96;   Temp t;97;   foo();98; }99 100; CHECK-LABEL: cleanup:101; CHECK: block102; CHECK:   block     exnref103; CHECK:     try_table    (catch_all_ref 0)104; CHECK:       call  foo105; CHECK:       br        2106; CHECK:     end_try_table107; CHECK:   end_block108; CHECK:   local.set  1109; CHECK:   global.set  __stack_pointer110; CHECK:   call  _ZN4TempD2Ev111; CHECK:   local.get  1112; CHECK:   throw_ref113; CHECK: end_block114; CHECK: call  _ZN4TempD2Ev115define void @cleanup() personality ptr @__gxx_wasm_personality_v0 {116entry:117  %t = alloca %struct.Temp, align 1118  invoke void @foo()119          to label %invoke.cont unwind label %ehcleanup120 121invoke.cont:                                      ; preds = %entry122  %call = call ptr @_ZN4TempD2Ev(ptr %t)123  ret void124 125ehcleanup:                                        ; preds = %entry126  %0 = cleanuppad within none []127  %call1 = call ptr @_ZN4TempD2Ev(ptr %t) [ "funclet"(token %0) ]128  cleanupret from %0 unwind to caller129}130 131; Calling a function that may throw within a 'catch (...)' generates a132; terminatepad, because __cxa_end_catch() also can throw within 'catch (...)'.133;134; void foo();135; void terminatepad() {136;   try {137;     foo();138;   } catch (...) {139;     foo();140;   }141; }142 143; CHECK-LABEL: terminatepad144; WASM64-LABEL: terminatepad145; CHECK: block146; CHECK:   block     i32147; WASM64:  block     i64148; CHECK:     try_table    (catch __cpp_exception 0)149; CHECK:       call  foo150; CHECK:       br        2151; CHECK:     end_try_table152; CHECK:   end_block153; CHECK:   call  __cxa_begin_catch154; CHECK:   block155; CHECK:     block     exnref156; CHECK:       try_table    (catch_all_ref 0)157; CHECK:         call  foo158; CHECK:         br        2159; CHECK:       end_try_table160; CHECK:     end_block161; CHECK:     local.set  2162; CHECK:     block163; CHECK:       block164; CHECK:         try_table    (catch_all 0)165; CHECK:           call  __cxa_end_catch166; CHECK:           br        2167; CHECK:         end_try_table168; CHECK:       end_block169; CHECK:       call  _ZSt9terminatev170; CHECK:       unreachable171; CHECK:     end_block172; CHECK:     local.get  2173; CHECK:     throw_ref174; CHECK:   end_block175; CHECK:   call  __cxa_end_catch176; CHECK: end_block177define void @terminatepad() personality ptr @__gxx_wasm_personality_v0 {178entry:179  invoke void @foo()180          to label %try.cont unwind label %catch.dispatch181 182catch.dispatch:                                   ; preds = %entry183  %0 = catchswitch within none [label %catch.start] unwind to caller184 185catch.start:                                      ; preds = %catch.dispatch186  %1 = catchpad within %0 [ptr null]187  %2 = call ptr @llvm.wasm.get.exception(token %1)188  %3 = call i32 @llvm.wasm.get.ehselector(token %1)189  %4 = call ptr @__cxa_begin_catch(ptr %2) [ "funclet"(token %1) ]190  invoke void @foo() [ "funclet"(token %1) ]191          to label %invoke.cont1 unwind label %ehcleanup192 193invoke.cont1:                                     ; preds = %catch.start194  call void @__cxa_end_catch() [ "funclet"(token %1) ]195  catchret from %1 to label %try.cont196 197try.cont:                                         ; preds = %invoke.cont1, %entry198  ret void199 200ehcleanup:                                        ; preds = %catch.start201  %5 = cleanuppad within %1 []202  invoke void @__cxa_end_catch() [ "funclet"(token %5) ]203          to label %invoke.cont2 unwind label %terminate204 205invoke.cont2:                                     ; preds = %ehcleanup206  cleanupret from %5 unwind to caller207 208terminate:                                        ; preds = %ehcleanup209  %6 = cleanuppad within %5 []210  call void @_ZSt9terminatev() #2 [ "funclet"(token %6) ]211  unreachable212}213 214; Tests prologues and epilogues are not generated within EH scopes.215; They should not be treated as funclets; BBs starting with a catch instruction216; should not have a prologue, and BBs ending with a catchret/cleanupret should217; not have an epilogue. This is separate from __stack_pointer restoring218; instructions after a catch instruction.219;220; void bar(int) noexcept;221; void no_prolog_epilog_in_ehpad() {222;   int stack_var = 0;223;   bar(stack_var);224;   try {225;     foo();226;   } catch (int) {227;     foo();228;   }229; }230 231; CHECK-LABEL: no_prolog_epilog_in_ehpad232; CHECK:   call  bar233; CHECK:   block234; CHECK:     block     () -> (i32, exnref)235; CHECK:       try_table    (catch_ref __cpp_exception 0)236; CHECK:         call  foo237; CHECK:         br        2238; CHECK:       end_try_table239; CHECK:     end_block240; CHECK:     local.set  2241; CHECK-NOT: global.get  __stack_pointer242; CHECK:     global.set  __stack_pointer243; CHECK:     block244; CHECK:       block245; CHECK:         br_if     0246; CHECK:         call  __cxa_begin_catch247; CHECK:         block     exnref248; CHECK:           try_table    (catch_all_ref 0)249; CHECK:             call  foo250; CHECK:             br        3251; CHECK:           end_try_table252; CHECK:         end_block253; CHECK:         local.set  2254; CHECK-NOT:     global.get  __stack_pointer255; CHECK:         global.set  __stack_pointer256; CHECK:         call  __cxa_end_catch257; CHECK:         local.get  2258; CHECK:         throw_ref259; CHECK-NOT:     global.set  __stack_pointer260; CHECK:       end_block261; CHECK:       local.get  2262; CHECK:       throw_ref263; CHECK:     end_block264; CHECK-NOT: global.set  __stack_pointer265; CHECK:     call  __cxa_end_catch266; CHECK:   end_block267define void @no_prolog_epilog_in_ehpad() personality ptr @__gxx_wasm_personality_v0 {268entry:269  %stack_var = alloca i32, align 4270  call void @bar(ptr %stack_var)271  invoke void @foo()272          to label %try.cont unwind label %catch.dispatch273 274catch.dispatch:                                   ; preds = %entry275  %0 = catchswitch within none [label %catch.start] unwind to caller276 277catch.start:                                      ; preds = %catch.dispatch278  %1 = catchpad within %0 [ptr @_ZTIi]279  %2 = call ptr @llvm.wasm.get.exception(token %1)280  %3 = call i32 @llvm.wasm.get.ehselector(token %1)281  %4 = call i32 @llvm.eh.typeid.for(ptr @_ZTIi)282  %matches = icmp eq i32 %3, %4283  br i1 %matches, label %catch, label %rethrow284 285catch:                                            ; preds = %catch.start286  %5 = call ptr @__cxa_begin_catch(ptr %2) [ "funclet"(token %1) ]287  %6 = load float, ptr %5, align 4288  invoke void @foo() [ "funclet"(token %1) ]289          to label %invoke.cont1 unwind label %ehcleanup290 291invoke.cont1:                                     ; preds = %catch292  call void @__cxa_end_catch() [ "funclet"(token %1) ]293  catchret from %1 to label %try.cont294 295rethrow:                                          ; preds = %catch.start296  call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]297  unreachable298 299try.cont:                                         ; preds = %invoke.cont1, %entry300  ret void301 302ehcleanup:                                        ; preds = %catch303  %7 = cleanuppad within %1 []304  call void @__cxa_end_catch() [ "funclet"(token %7) ]305  cleanupret from %7 unwind to caller306}307 308; When a function does not have stack-allocated objects, it does not need to309; store SP back to __stack_pointer global at the epilog.310;311; void foo();312; void no_sp_writeback() {313;   try {314;     foo();315;   } catch (...) {316;   }317; }318 319; CHECK-LABEL: no_sp_writeback320; CHECK:     block321; CHECK:       block     i32322; CHECK:         try_table    (catch __cpp_exception 0)323; CHECK:           call  foo324; CHECK:           br        2325; CHECK:         end_try_table326; CHECK:       end_block327; CHECK:       call  __cxa_begin_catch328; CHECK:       call  __cxa_end_catch329; CHECK:     end_block330; CHECK-NOT: global.set  __stack_pointer331; CHECK:     end_function332define void @no_sp_writeback() personality ptr @__gxx_wasm_personality_v0 {333entry:334  invoke void @foo()335          to label %try.cont unwind label %catch.dispatch336 337catch.dispatch:                                   ; preds = %entry338  %0 = catchswitch within none [label %catch.start] unwind to caller339 340catch.start:                                      ; preds = %catch.dispatch341  %1 = catchpad within %0 [ptr null]342  %2 = call ptr @llvm.wasm.get.exception(token %1)343  %3 = call i32 @llvm.wasm.get.ehselector(token %1)344  %4 = call ptr @__cxa_begin_catch(ptr %2) [ "funclet"(token %1) ]345  call void @__cxa_end_catch() [ "funclet"(token %1) ]346  catchret from %1 to label %try.cont347 348try.cont:                                         ; preds = %catch.start, %entry349  ret void350}351 352; When the result of @llvm.wasm.get.exception is not used. This is created to353; fix a bug in LateEHPrepare and this should not crash.354define void @get_exception_wo_use() personality ptr @__gxx_wasm_personality_v0 {355entry:356  invoke void @foo()357          to label %try.cont unwind label %catch.dispatch358 359catch.dispatch:                                   ; preds = %entry360  %0 = catchswitch within none [label %catch.start] unwind to caller361 362catch.start:                                      ; preds = %catch.dispatch363  %1 = catchpad within %0 [ptr null]364  %2 = call ptr @llvm.wasm.get.exception(token %1)365  %3 = call i32 @llvm.wasm.get.ehselector(token %1)366  catchret from %1 to label %try.cont367 368try.cont:                                         ; preds = %catch.start, %entry369  ret void370}371 372; Tests a case when a cleanup region (cleanuppad ~ clanupret) contains another373; catchpad374define void @complex_cleanup_region() personality ptr @__gxx_wasm_personality_v0 {375entry:376  invoke void @foo()377          to label %invoke.cont unwind label %ehcleanup378 379invoke.cont:                                      ; preds = %entry380  ret void381 382ehcleanup:                                        ; preds = %entry383  %0 = cleanuppad within none []384  invoke void @foo() [ "funclet"(token %0) ]385          to label %ehcleanupret unwind label %catch.dispatch386 387catch.dispatch:                                   ; preds = %ehcleanup388  %1 = catchswitch within %0 [label %catch.start] unwind label %ehcleanup.1389 390catch.start:                                      ; preds = %catch.dispatch391  %2 = catchpad within %1 [ptr null]392  %3 = call ptr @llvm.wasm.get.exception(token %2)393  %4 = call i32 @llvm.wasm.get.ehselector(token %2)394  catchret from %2 to label %ehcleanupret395 396ehcleanup.1:                                      ; preds = %catch.dispatch397  %5 = cleanuppad within %0 []398  unreachable399 400ehcleanupret:                                     ; preds = %catch.start, %ehcleanup401  cleanupret from %0 unwind to caller402}403 404; Regression test for the bug that 'rethrow' was not treated correctly as a405; terminator in isel.406define void @rethrow_terminator() personality ptr @__gxx_wasm_personality_v0 {407entry:408  invoke void @foo()409          to label %try.cont unwind label %catch.dispatch410 411catch.dispatch:                                   ; preds = %entry412  %0 = catchswitch within none [label %catch.start] unwind label %ehcleanup413 414catch.start:                                      ; preds = %catch.dispatch415  %1 = catchpad within %0 [ptr @_ZTIi]416  %2 = call ptr @llvm.wasm.get.exception(token %1)417  %3 = call i32 @llvm.wasm.get.ehselector(token %1)418  %4 = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi)419  %matches = icmp eq i32 %3, %4420  br i1 %matches, label %catch, label %rethrow421 422catch:                                            ; preds = %catch.start423  %5 = call ptr @__cxa_begin_catch(ptr %2) [ "funclet"(token %1) ]424  %6 = load i32, ptr %5, align 4425  call void @__cxa_end_catch() [ "funclet"(token %1) ]426  catchret from %1 to label %try.cont427 428rethrow:                                          ; preds = %catch.start429  invoke void @llvm.wasm.rethrow() #1 [ "funclet"(token %1) ]430          to label %unreachable unwind label %ehcleanup431 432try.cont:                                         ; preds = %entry, %catch433  ret void434 435ehcleanup:                                        ; preds = %rethrow, %catch.dispatch436  ; 'rethrow' BB is this BB's predecessor, and its437  ; 'invoke void @llvm.wasm.rethrow()' is lowered down to a 'RETHROW' in Wasm438  ; MIR. And this 'phi' creates 'CONST_I32' instruction in the predecessor439  ; 'rethrow' BB. If 'RETHROW' is not treated correctly as a terminator, it can440  ; create a BB like441  ; bb.3.rethrow:442  ;   RETHROW 0443  ;   %0 = CONST_I32 20444  ;   BR ...445  %tmp = phi i32 [ 10, %catch.dispatch ], [ 20, %rethrow ]446  %7 = cleanuppad within none []447  call void @take_i32(i32 %tmp) [ "funclet"(token %7) ]448  cleanupret from %7 unwind to caller449 450unreachable:                                      ; preds = %rethrow451  unreachable452}453 454; The bitcode below is generated when the code below is compiled and455; Temp::~Temp() is inlined into inlined_cleanupret():456;457; void inlined_cleanupret() {458; try {459;   Temp t;460;   throw 2;461; } catch (...)462; }463;464; Temp::~Temp() {465;   try {466;     throw 1;467;   } catch (...) {468;   }469; }470;471; ~Temp() generates cleanupret, which is lowered to a 'throw_ref' later. That472; throw_ref's argument should correctly target the top-level cleanuppad473; (catch_all_ref). This is a regression test for the bug where we did not474; compute throw_ref's argument correctly.475 476; CHECK-LABEL: inlined_cleanupret:477; CHECK: block     exnref478; CHECK:   block479; CHECK:     block     exnref480; CHECK:       try_table    (catch_all_ref 0)481; CHECK:         call  __cxa_throw482; CHECK:       end_try_table483; CHECK:     end_block484; try_table (catch_all_ref 0)'s caught exception is stored in local 2485; CHECK:     local.set  2486; CHECK:     block487; CHECK:       try_table    (catch_all 0)488; CHECK:         block489; CHECK:           block     i32490; CHECK:             try_table    (catch __cpp_exception 0)491; CHECK:               call  __cxa_throw492; CHECK:             end_try_table493; CHECK:           end_block494; CHECK:           call  __cxa_end_catch495; CHECK:           block     i32496; CHECK:             try_table    (catch_all_ref 5)497; CHECK:               try_table    (catch __cpp_exception 1)498; Note that the throw_ref below targets the top-level catch_all_ref (local 2)499; CHECK:                 local.get  2500; CHECK:                 throw_ref501; CHECK:               end_try_table502; CHECK:             end_try_table503; CHECK:           end_block504; CHECK:           try_table    (catch_all_ref 4)505; CHECK:             call  __cxa_end_catch506; CHECK:           end_try_table507; CHECK:           return508; CHECK:         end_block509; CHECK:       end_try_table510; CHECK:     end_block511; CHECK:     call  _ZSt9terminatev512; CHECK:   end_block513; CHECK: end_block514; CHECK: throw_ref515define void @inlined_cleanupret() personality ptr @__gxx_wasm_personality_v0 {516entry:517  %exception = tail call ptr @__cxa_allocate_exception(i32 4)518  store i32 2, ptr %exception, align 16519  invoke void @__cxa_throw(ptr nonnull %exception, ptr nonnull @_ZTIi, ptr null)520          to label %unreachable unwind label %ehcleanup521 522ehcleanup:                                        ; preds = %entry523  %0 = cleanuppad within none []524  %exception.i = call ptr @__cxa_allocate_exception(i32 4) [ "funclet"(token %0) ]525  store i32 1, ptr %exception.i, align 16526  invoke void @__cxa_throw(ptr nonnull %exception.i, ptr nonnull @_ZTIi, ptr null) [ "funclet"(token %0) ]527          to label %unreachable unwind label %catch.dispatch.i528 529catch.dispatch.i:                                 ; preds = %ehcleanup530  %1 = catchswitch within %0 [label %catch.start.i] unwind label %terminate.i531 532catch.start.i:                                    ; preds = %catch.dispatch.i533  %2 = catchpad within %1 [ptr null]534  %3 = tail call ptr @llvm.wasm.get.exception(token %2)535  %4 = tail call i32 @llvm.wasm.get.ehselector(token %2)536  %5 = call ptr @__cxa_begin_catch(ptr %3) [ "funclet"(token %2) ]537  invoke void @__cxa_end_catch() [ "funclet"(token %2) ]538          to label %invoke.cont.i unwind label %terminate.i539 540invoke.cont.i:                                    ; preds = %catch.start.i541  catchret from %2 to label %_ZN4TempD2Ev.exit542 543terminate.i:                                      ; preds = %catch.start.i, %catch.dispatch.i544  %6 = cleanuppad within %0 []545  call void @_ZSt9terminatev() #2 [ "funclet"(token %6) ]546  unreachable547 548_ZN4TempD2Ev.exit:                                ; preds = %invoke.cont.i549  cleanupret from %0 unwind label %catch.dispatch550 551catch.dispatch:                                   ; preds = %_ZN4TempD2Ev.exit552  %7 = catchswitch within none [label %catch.start] unwind to caller553 554catch.start:                                      ; preds = %catch.dispatch555  %8 = catchpad within %7 [ptr null]556  %9 = tail call ptr @llvm.wasm.get.exception(token %8)557  %10 = tail call i32 @llvm.wasm.get.ehselector(token %8)558  %11 = call ptr @__cxa_begin_catch(ptr %9) #8 [ "funclet"(token %8) ]559  call void @__cxa_end_catch() [ "funclet"(token %8) ]560  catchret from %8 to label %try.cont561 562try.cont:                                         ; preds = %catch.start563  ret void564 565unreachable:                                      ; preds = %entry566  unreachable567}568 569; This tests whether llvm.wasm.throw intrinsic can invoked and iseled correctly.570 571; CHECK-LABEL: invoke_throw:572; CHECK: try_table    (catch __cpp_exception 0)573; CHECK:   local.get  0574; CHECK:   throw     __cpp_exception575; CHECK: end_try_table576define void @invoke_throw(ptr %p) personality ptr @__gxx_wasm_personality_v0 {577entry:578  invoke void @llvm.wasm.throw(i32 0, ptr %p)579          to label %try.cont unwind label %catch.dispatch580 581catch.dispatch:                                   ; preds = %entry582  %0 = catchswitch within none [label %catch.start] unwind to caller583 584catch.start:                                      ; preds = %catch.dispatch585  %1 = catchpad within %0 [ptr null]586  %2 = call ptr @llvm.wasm.get.exception(token %1)587  %3 = call i32 @llvm.wasm.get.ehselector(token %1)588  %4 = call ptr @__cxa_begin_catch(ptr %2) #4 [ "funclet"(token %1) ]589  call void @__cxa_end_catch() [ "funclet"(token %1) ]590  catchret from %1 to label %try.cont591 592try.cont:                                         ; preds = %catch, %entry593  ret void594}595 596; Regression test for a bug where, when an invoke unwinds to a catchswitch, the597; catchswitch's unwind destination was not included in the invoke's unwind598; destination when there was no direct link from catch.start to there.599 600; CHECK-LABEL: unwind_destinations:601; CHECK: block602; CHECK:   block603; CHECK:     try_table    (catch_all 0)604; CHECK:       block     i32605; CHECK:         try_table    (catch __cpp_exception 0)606; CHECK:           call  foo607; CHECK:         end_try_table608; CHECK:         unreachable609; CHECK:       end_block610; CHECK:       call  _ZSt9terminatev611; CHECK:       unreachable612; CHECK:     end_try_table613; CHECK:     unreachable614; CHECK:   end_block615; Note the below is "terminate" BB and should not be DCE'd616; CHECK:   call  _ZSt9terminatev617; CHECK:   unreachable618; CHECK: end_block619define void @unwind_destinations() personality ptr @__gxx_wasm_personality_v0 {620entry:621  invoke void @foo()622          to label %try.cont unwind label %catch.dispatch623 624catch.dispatch:                                   ; preds = %entry625  %0 = catchswitch within none [label %catch.start] unwind label %terminate626 627catch.start:                                      ; preds = %catch.dispatch628  %1 = catchpad within %0 [ptr null]629  %2 = call ptr @llvm.wasm.get.exception(token %1)630  %3 = call ptr @__cxa_begin_catch(ptr %2) #5 [ "funclet"(token %1) ]631  call void @_ZSt9terminatev() #2 [ "funclet"(token %1) ]632  unreachable633 634; Even if there is no link from catch.start to this terminate BB, when there is635; an exception that catch.start does not catch (e.g. a foreign exception), it636; should end up here, so this BB should NOT be DCE'ed637terminate:                                        ; preds = %catch.dispatch638  %4 = cleanuppad within none []639  call void @_ZSt9terminatev() #2 [ "funclet"(token %4) ]640  unreachable641 642try.cont:                                         ; preds = %entry643  ret void644}645 646declare void @foo()647declare void @bar(ptr)648declare void @take_i32(i32)649declare i32 @__gxx_wasm_personality_v0(...)650; Function Attrs: noreturn651declare void @llvm.wasm.throw(i32, ptr) #1652; Function Attrs: nounwind653declare ptr @llvm.wasm.get.exception(token) #0654; Function Attrs: nounwind655declare i32 @llvm.wasm.get.ehselector(token) #0656; Function Attrs: noreturn657declare void @llvm.wasm.rethrow() #1658; Function Attrs: nounwind659declare i32 @llvm.eh.typeid.for(ptr) #0660; Function Attrs: nounwind661declare ptr @__cxa_allocate_exception(i32) #0662declare ptr @__cxa_begin_catch(ptr)663declare void @__cxa_end_catch()664; Function Attrs: noreturn665declare void @__cxa_throw(ptr, ptr, ptr) #1666declare void @_ZSt9terminatev()667declare ptr @_ZN4TempD2Ev(ptr returned)668 669attributes #0 = { nounwind }670attributes #1 = { noreturn }671attributes #2 = { noreturn nounwind }672 673;; The exception tag should not be defined locally674; CHECK-NOT: __cpp_exception:675