Home | History | Annotate | Download | only in WebAssembly
      1 ; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s
      2 
      3 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
      4 target triple = "wasm32-unknown-unknown"
      5 
      6 @_ZTIi = external constant i8*
      7 @_ZTIc = external constant i8*
      8 ; CHECK-DAG: __THREW__ = weak_odr global i32 0
      9 ; CHECK-DAG: __threwValue = weak_odr global i32 0
     10 ; CHECK-DAG: __tempRet0 = weak_odr global i32 0
     11 
     12 ; Test invoke instruction with clauses (try-catch block)
     13 define void @clause() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
     14 ; CHECK-LABEL: @clause(
     15 entry:
     16   invoke void @foo(i32 3)
     17           to label %invoke.cont unwind label %lpad
     18 ; CHECK: entry:
     19 ; CHECK-NEXT: store i32 0, i32* @__THREW__
     20 ; CHECK-NEXT: call void @__invoke_void_i32(void (i32)* @foo, i32 3)
     21 ; CHECK-NEXT: %[[__THREW__VAL:.*]] = load i32, i32* @__THREW__
     22 ; CHECK-NEXT: store i32 0, i32* @__THREW__
     23 ; CHECK-NEXT: %cmp = icmp eq i32 %[[__THREW__VAL]], 1
     24 ; CHECK-NEXT: br i1 %cmp, label %lpad, label %invoke.cont
     25 
     26 invoke.cont:                                      ; preds = %entry
     27   br label %try.cont
     28 
     29 lpad:                                             ; preds = %entry
     30   %0 = landingpad { i8*, i32 }
     31           catch i8* bitcast (i8** @_ZTIi to i8*)
     32           catch i8* null
     33   %1 = extractvalue { i8*, i32 } %0, 0
     34   %2 = extractvalue { i8*, i32 } %0, 1
     35   br label %catch.dispatch
     36 ; CHECK: lpad:
     37 ; CHECK-NEXT: %[[FMC:.*]] = call i8* @__cxa_find_matching_catch_4(i8* bitcast (i8** @_ZTIi to i8*), i8* null)
     38 ; CHECK-NEXT: %[[IVI1:.*]] = insertvalue { i8*, i32 } undef, i8* %[[FMC]], 0
     39 ; CHECK-NEXT: %[[TEMPRET0_VAL:.*]] = load i32, i32* @__tempRet0
     40 ; CHECK-NEXT: %[[IVI2:.*]] = insertvalue { i8*, i32 } %[[IVI1]], i32 %[[TEMPRET0_VAL]], 1
     41 ; CHECK-NEXT: extractvalue { i8*, i32 } %[[IVI2]], 0
     42 ; CHECK-NEXT: %[[CDR:.*]] = extractvalue { i8*, i32 } %[[IVI2]], 1
     43 
     44 catch.dispatch:                                   ; preds = %lpad
     45   %3 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
     46   %matches = icmp eq i32 %2, %3
     47   br i1 %matches, label %catch1, label %catch
     48 ; CHECK: catch.dispatch:
     49 ; CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm_eh_typeid_for(i8* bitcast (i8** @_ZTIi to i8*))
     50 ; CHECK-NEXT: %matches = icmp eq i32 %[[CDR]], %[[TYPEID]]
     51 
     52 catch1:                                           ; preds = %catch.dispatch
     53   %4 = call i8* @__cxa_begin_catch(i8* %1)
     54   %5 = bitcast i8* %4 to i32*
     55   %6 = load i32, i32* %5, align 4
     56   call void @__cxa_end_catch()
     57   br label %try.cont
     58 
     59 try.cont:                                         ; preds = %catch, %catch1, %invoke.cont
     60   ret void
     61 
     62 catch:                                            ; preds = %catch.dispatch
     63   %7 = call i8* @__cxa_begin_catch(i8* %1)
     64   call void @__cxa_end_catch()
     65   br label %try.cont
     66 }
     67 
     68 ; Test invoke instruction with filters (functions with throw(...) declaration)
     69 define void @filter() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
     70 ; CHECK-LABEL: @filter(
     71 entry:
     72   invoke void @foo(i32 3)
     73           to label %invoke.cont unwind label %lpad
     74 ; CHECK: entry:
     75 ; CHECK-NEXT: store i32 0, i32* @__THREW__
     76 ; CHECK-NEXT: call void @__invoke_void_i32(void (i32)* @foo, i32 3)
     77 ; CHECK-NEXT: %[[__THREW__VAL:.*]] = load i32, i32* @__THREW__
     78 ; CHECK-NEXT: store i32 0, i32* @__THREW__
     79 ; CHECK-NEXT: %cmp = icmp eq i32 %[[__THREW__VAL]], 1
     80 ; CHECK-NEXT: br i1 %cmp, label %lpad, label %invoke.cont
     81 
     82 invoke.cont:                                      ; preds = %entry
     83   ret void
     84 
     85 lpad:                                             ; preds = %entry
     86   %0 = landingpad { i8*, i32 }
     87           filter [2 x i8*] [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTIc to i8*)]
     88   %1 = extractvalue { i8*, i32 } %0, 0
     89   %2 = extractvalue { i8*, i32 } %0, 1
     90   br label %filter.dispatch
     91 ; CHECK: lpad:
     92 ; CHECK-NEXT: %[[FMC:.*]] = call i8* @__cxa_find_matching_catch_4(i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTIc to i8*))
     93 ; CHECK-NEXT: %[[IVI1:.*]] = insertvalue { i8*, i32 } undef, i8* %[[FMC]], 0
     94 ; CHECK-NEXT: %[[TEMPRET0_VAL:.*]] = load i32, i32* @__tempRet0
     95 ; CHECK-NEXT: %[[IVI2:.*]] = insertvalue { i8*, i32 } %[[IVI1]], i32 %[[TEMPRET0_VAL]], 1
     96 ; CHECK-NEXT: extractvalue { i8*, i32 } %[[IVI2]], 0
     97 ; CHECK-NEXT: extractvalue { i8*, i32 } %[[IVI2]], 1
     98 
     99 filter.dispatch:                                  ; preds = %lpad
    100   %ehspec.fails = icmp slt i32 %2, 0
    101   br i1 %ehspec.fails, label %ehspec.unexpected, label %eh.resume
    102 
    103 ehspec.unexpected:                                ; preds = %filter.dispatch
    104   call void @__cxa_call_unexpected(i8* %1) #4
    105   unreachable
    106 
    107 eh.resume:                                        ; preds = %filter.dispatch
    108   %lpad.val = insertvalue { i8*, i32 } undef, i8* %1, 0
    109   %lpad.val3 = insertvalue { i8*, i32 } %lpad.val, i32 %2, 1
    110   resume { i8*, i32 } %lpad.val3
    111 ; CHECK: eh.resume:
    112 ; CHECK-NEXT: insertvalue
    113 ; CHECK-NEXT: %[[LPAD_VAL:.*]] = insertvalue
    114 ; CHECK-NEXT: %[[LOW:.*]] = extractvalue { i8*, i32 } %[[LPAD_VAL]], 0
    115 ; CHECK-NEXT: call void @__resumeException(i8* %[[LOW]])
    116 ; CHECK-NEXT: unreachable
    117 }
    118 
    119 ; Test if argument attributes indices in newly created call instructions are correct
    120 define void @arg_attributes() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
    121 ; CHECK-LABEL: @arg_attributes(
    122 entry:
    123   %0 = invoke noalias i8* @bar(i8 signext 1, i8 zeroext 2)
    124           to label %invoke.cont unwind label %lpad
    125 ; CHECK: entry:
    126 ; CHECK-NEXT: store i32 0, i32* @__THREW__
    127 ; CHECK-NEXT: %0 = call noalias i8* @"__invoke_i8*_i8_i8"(i8* (i8, i8)* @bar, i8 signext 1, i8 zeroext 2)
    128 
    129 invoke.cont:                                      ; preds = %entry
    130   br label %try.cont
    131 
    132 lpad:                                             ; preds = %entry
    133   %1 = landingpad { i8*, i32 }
    134           catch i8* bitcast (i8** @_ZTIi to i8*)
    135           catch i8* null
    136   %2 = extractvalue { i8*, i32 } %1, 0
    137   %3 = extractvalue { i8*, i32 } %1, 1
    138   br label %catch.dispatch
    139 
    140 catch.dispatch:                                   ; preds = %lpad
    141   %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
    142   %matches = icmp eq i32 %3, %4
    143   br i1 %matches, label %catch1, label %catch
    144 
    145 catch1:                                           ; preds = %catch.dispatch
    146   %5 = call i8* @__cxa_begin_catch(i8* %2)
    147   %6 = bitcast i8* %5 to i32*
    148   %7 = load i32, i32* %6, align 4
    149   call void @__cxa_end_catch()
    150   br label %try.cont
    151 
    152 try.cont:                                         ; preds = %catch, %catch1, %invoke.cont
    153   ret void
    154 
    155 catch:                                            ; preds = %catch.dispatch
    156   %8 = call i8* @__cxa_begin_catch(i8* %2)
    157   call void @__cxa_end_catch()
    158   br label %try.cont
    159 }
    160 
    161 declare void @foo(i32)
    162 declare i8* @bar(i8, i8)
    163 
    164 declare i32 @__gxx_personality_v0(...)
    165 declare i32 @llvm.eh.typeid.for(i8*)
    166 declare i8* @__cxa_begin_catch(i8*)
    167 declare void @__cxa_end_catch()
    168 declare void @__cxa_call_unexpected(i8*)
    169 
    170 ; JS glue functions and invoke wrappers declaration
    171 ; CHECK-DAG: declare void @__resumeException(i8*)
    172 ; CHECK-DAG: declare void @__invoke_void_i32(void (i32)*, i32)
    173 ; CHECK-DAG: declare i8* @__cxa_find_matching_catch_4(i8*, i8*)
    174 
    175 ; setThrew function creation
    176 ; CHECK-LABEL: define weak_odr void @setThrew(i32 %threw, i32 %value) {
    177 ; CHECK: entry:
    178 ; CHECK-NEXT: %__THREW__.val = load i32, i32* @__THREW__
    179 ; CHECK-NEXT: %cmp = icmp eq i32 %__THREW__.val, 0
    180 ; CHECK-NEXT: br i1 %cmp, label %if.then, label %if.end
    181 ; CHECK: if.then:
    182 ; CHECK-NEXT: store i32 %threw, i32* @__THREW__
    183 ; CHECK-NEXT: store i32 %value, i32* @__threwValue
    184 ; CHECK-NEXT: br label %if.end
    185 ; CHECK: if.end:
    186 ; CHECK-NEXT: ret void
    187 ; CHECK: }
    188 
    189 ; setTempRet0 function creation
    190 ; CHECK-LABEL: define weak_odr void @setTempRet0(i32 %value) {
    191 ; CHECK: entry:
    192 ; CHECK-NEXT: store i32 %value, i32* @__tempRet0
    193 ; CHECK-NEXT: ret void
    194 ; CHECK: }
    195