kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

insn.c (13996B)


      1 #include "wasm/wasm.h"
      2 #include "wasm/wasm_insn_table.h"
      3 
      4 int wasm_is_num_type(WasmValType vt) {
      5   return vt == WASM_VAL_I32 || vt == WASM_VAL_I64 || vt == WASM_VAL_F32 ||
      6          vt == WASM_VAL_F64;
      7 }
      8 
      9 int wasm_is_ref_type(WasmValType vt) {
     10   return vt == WASM_VAL_FUNCREF || vt == WASM_VAL_EXTERNREF;
     11 }
     12 
     13 int wasm_is_frontend_value_type(WasmValType vt) {
     14   return wasm_is_num_type(vt) || vt == WASM_VAL_FUNCREF;
     15 }
     16 
     17 int wasm_feature_enabled(const WasmModule* m, WasmFeatureSet feature) {
     18   return (m->features & (uint32_t)feature) != 0;
     19 }
     20 
     21 void wasm_require_feature_at(KitCompiler* c, const WasmModule* m,
     22                              WasmFeatureSet feature, const char* feature_name,
     23                              const char* what, KitSrcLoc loc) {
     24   if (!wasm_feature_enabled(m, feature))
     25     wasm_error(c, loc, "wasm: %s requires %s", what, feature_name);
     26 }
     27 
     28 void wasm_require_feature(KitCompiler* c, const WasmModule* m,
     29                           WasmFeatureSet feature, const char* feature_name,
     30                           const char* what) {
     31   wasm_require_feature_at(c, m, feature, feature_name, what, wasm_loc(0, 0));
     32 }
     33 
     34 int wasm_insn_is_load(WasmInsnKind kind) {
     35   return kind == WASM_INSN_I32_LOAD || kind == WASM_INSN_I64_LOAD ||
     36          kind == WASM_INSN_F32_LOAD || kind == WASM_INSN_F64_LOAD ||
     37          kind == WASM_INSN_I32_LOAD8_S || kind == WASM_INSN_I32_LOAD8_U ||
     38          kind == WASM_INSN_I32_LOAD16_S || kind == WASM_INSN_I32_LOAD16_U ||
     39          kind == WASM_INSN_I64_LOAD8_S || kind == WASM_INSN_I64_LOAD8_U ||
     40          kind == WASM_INSN_I64_LOAD16_S || kind == WASM_INSN_I64_LOAD16_U ||
     41          kind == WASM_INSN_I64_LOAD32_S || kind == WASM_INSN_I64_LOAD32_U;
     42 }
     43 
     44 int wasm_insn_is_store(WasmInsnKind kind) {
     45   return kind == WASM_INSN_I32_STORE || kind == WASM_INSN_I64_STORE ||
     46          kind == WASM_INSN_F32_STORE || kind == WASM_INSN_F64_STORE ||
     47          kind == WASM_INSN_I32_STORE8 || kind == WASM_INSN_I32_STORE16 ||
     48          kind == WASM_INSN_I64_STORE8 || kind == WASM_INSN_I64_STORE16 ||
     49          kind == WASM_INSN_I64_STORE32;
     50 }
     51 
     52 int wasm_insn_is_atomic_load(WasmInsnKind kind) {
     53   return kind == WASM_INSN_I32_ATOMIC_LOAD ||
     54          kind == WASM_INSN_I64_ATOMIC_LOAD ||
     55          kind == WASM_INSN_I32_ATOMIC_LOAD8_U ||
     56          kind == WASM_INSN_I32_ATOMIC_LOAD16_U ||
     57          kind == WASM_INSN_I64_ATOMIC_LOAD8_U ||
     58          kind == WASM_INSN_I64_ATOMIC_LOAD16_U ||
     59          kind == WASM_INSN_I64_ATOMIC_LOAD32_U;
     60 }
     61 
     62 int wasm_insn_is_atomic_store(WasmInsnKind kind) {
     63   return kind == WASM_INSN_I32_ATOMIC_STORE ||
     64          kind == WASM_INSN_I64_ATOMIC_STORE ||
     65          kind == WASM_INSN_I32_ATOMIC_STORE8 ||
     66          kind == WASM_INSN_I32_ATOMIC_STORE16 ||
     67          kind == WASM_INSN_I64_ATOMIC_STORE8 ||
     68          kind == WASM_INSN_I64_ATOMIC_STORE16 ||
     69          kind == WASM_INSN_I64_ATOMIC_STORE32;
     70 }
     71 
     72 int wasm_insn_is_atomic_rmw(WasmInsnKind kind) {
     73   return kind == WASM_INSN_I32_ATOMIC_RMW_ADD ||
     74          kind == WASM_INSN_I64_ATOMIC_RMW_ADD ||
     75          kind == WASM_INSN_I32_ATOMIC_RMW_SUB ||
     76          kind == WASM_INSN_I64_ATOMIC_RMW_SUB ||
     77          kind == WASM_INSN_I32_ATOMIC_RMW_AND ||
     78          kind == WASM_INSN_I64_ATOMIC_RMW_AND ||
     79          kind == WASM_INSN_I32_ATOMIC_RMW_OR ||
     80          kind == WASM_INSN_I64_ATOMIC_RMW_OR ||
     81          kind == WASM_INSN_I32_ATOMIC_RMW_XOR ||
     82          kind == WASM_INSN_I64_ATOMIC_RMW_XOR ||
     83          kind == WASM_INSN_I32_ATOMIC_RMW_XCHG ||
     84          kind == WASM_INSN_I64_ATOMIC_RMW_XCHG;
     85 }
     86 
     87 int wasm_insn_is_atomic_cmpxchg(WasmInsnKind kind) {
     88   return kind == WASM_INSN_I32_ATOMIC_RMW_CMPXCHG ||
     89          kind == WASM_INSN_I64_ATOMIC_RMW_CMPXCHG;
     90 }
     91 
     92 int wasm_insn_is_atomic_wait_notify(WasmInsnKind kind) {
     93   return kind == WASM_INSN_I32_ATOMIC_WAIT ||
     94          kind == WASM_INSN_I64_ATOMIC_WAIT ||
     95          kind == WASM_INSN_MEMORY_ATOMIC_NOTIFY;
     96 }
     97 
     98 int wasm_insn_is_atomic_mem(WasmInsnKind kind) {
     99   return wasm_insn_is_atomic_load(kind) || wasm_insn_is_atomic_store(kind) ||
    100          wasm_insn_is_atomic_rmw(kind) || wasm_insn_is_atomic_cmpxchg(kind) ||
    101          wasm_insn_is_atomic_wait_notify(kind);
    102 }
    103 
    104 int wasm_insn_is_mem(WasmInsnKind kind) {
    105   return wasm_insn_is_load(kind) || wasm_insn_is_store(kind) ||
    106          wasm_insn_is_atomic_mem(kind);
    107 }
    108 
    109 WasmValType wasm_func_local_type(const WasmFunc* f, uint32_t index) {
    110   if (index < f->nparams) return f->params[index];
    111   return f->locals[index - f->nparams];
    112 }
    113 
    114 uint32_t wasm_mem_width(uint8_t kind) {
    115   switch (kind) {
    116     case WASM_INSN_I32_LOAD8_S:
    117     case WASM_INSN_I32_LOAD8_U:
    118     case WASM_INSN_I64_LOAD8_S:
    119     case WASM_INSN_I64_LOAD8_U:
    120     case WASM_INSN_I32_STORE8:
    121     case WASM_INSN_I64_STORE8:
    122     case WASM_INSN_I32_ATOMIC_LOAD8_U:
    123     case WASM_INSN_I64_ATOMIC_LOAD8_U:
    124     case WASM_INSN_I32_ATOMIC_STORE8:
    125     case WASM_INSN_I64_ATOMIC_STORE8:
    126       return 1;
    127     case WASM_INSN_I32_LOAD16_S:
    128     case WASM_INSN_I32_LOAD16_U:
    129     case WASM_INSN_I64_LOAD16_S:
    130     case WASM_INSN_I64_LOAD16_U:
    131     case WASM_INSN_I32_STORE16:
    132     case WASM_INSN_I64_STORE16:
    133     case WASM_INSN_I32_ATOMIC_LOAD16_U:
    134     case WASM_INSN_I64_ATOMIC_LOAD16_U:
    135     case WASM_INSN_I32_ATOMIC_STORE16:
    136     case WASM_INSN_I64_ATOMIC_STORE16:
    137       return 2;
    138     case WASM_INSN_I32_LOAD:
    139     case WASM_INSN_F32_LOAD:
    140     case WASM_INSN_I64_LOAD32_S:
    141     case WASM_INSN_I64_LOAD32_U:
    142     case WASM_INSN_I32_STORE:
    143     case WASM_INSN_F32_STORE:
    144     case WASM_INSN_I64_STORE32:
    145     case WASM_INSN_I32_ATOMIC_LOAD:
    146     case WASM_INSN_I64_ATOMIC_LOAD32_U:
    147     case WASM_INSN_I32_ATOMIC_STORE:
    148     case WASM_INSN_I64_ATOMIC_STORE32:
    149     case WASM_INSN_I32_ATOMIC_RMW_ADD:
    150     case WASM_INSN_I32_ATOMIC_RMW_SUB:
    151     case WASM_INSN_I32_ATOMIC_RMW_AND:
    152     case WASM_INSN_I32_ATOMIC_RMW_OR:
    153     case WASM_INSN_I32_ATOMIC_RMW_XOR:
    154     case WASM_INSN_I32_ATOMIC_RMW_XCHG:
    155     case WASM_INSN_I32_ATOMIC_RMW_CMPXCHG:
    156     case WASM_INSN_I32_ATOMIC_WAIT:
    157     case WASM_INSN_MEMORY_ATOMIC_NOTIFY:
    158       return 4;
    159     default:
    160       return 8;
    161   }
    162 }
    163 
    164 int wasm_int_cmp_op(uint8_t kind, KitCgIntCmpOp* out) {
    165   switch (kind) {
    166     case WASM_INSN_I32_EQ:
    167     case WASM_INSN_I64_EQ:
    168       *out = KIT_CG_INT_EQ;
    169       return 1;
    170     case WASM_INSN_I32_NE:
    171     case WASM_INSN_I64_NE:
    172       *out = KIT_CG_INT_NE;
    173       return 1;
    174     case WASM_INSN_I32_LT_S:
    175     case WASM_INSN_I64_LT_S:
    176       *out = KIT_CG_INT_LT_S;
    177       return 1;
    178     case WASM_INSN_I32_LT_U:
    179     case WASM_INSN_I64_LT_U:
    180       *out = KIT_CG_INT_LT_U;
    181       return 1;
    182     case WASM_INSN_I32_GT_S:
    183     case WASM_INSN_I64_GT_S:
    184       *out = KIT_CG_INT_GT_S;
    185       return 1;
    186     case WASM_INSN_I32_GT_U:
    187     case WASM_INSN_I64_GT_U:
    188       *out = KIT_CG_INT_GT_U;
    189       return 1;
    190     case WASM_INSN_I32_LE_S:
    191     case WASM_INSN_I64_LE_S:
    192       *out = KIT_CG_INT_LE_S;
    193       return 1;
    194     case WASM_INSN_I32_LE_U:
    195     case WASM_INSN_I64_LE_U:
    196       *out = KIT_CG_INT_LE_U;
    197       return 1;
    198     case WASM_INSN_I32_GE_S:
    199     case WASM_INSN_I64_GE_S:
    200       *out = KIT_CG_INT_GE_S;
    201       return 1;
    202     case WASM_INSN_I32_GE_U:
    203     case WASM_INSN_I64_GE_U:
    204       *out = KIT_CG_INT_GE_U;
    205       return 1;
    206     default:
    207       return 0;
    208   }
    209 }
    210 
    211 WasmValType wasm_load_result_type(uint8_t kind) {
    212   switch (kind) {
    213     case WASM_INSN_F32_LOAD:
    214       return WASM_VAL_F32;
    215     case WASM_INSN_F64_LOAD:
    216       return WASM_VAL_F64;
    217     case WASM_INSN_I64_LOAD:
    218     case WASM_INSN_I64_LOAD8_S:
    219     case WASM_INSN_I64_LOAD8_U:
    220     case WASM_INSN_I64_LOAD16_S:
    221     case WASM_INSN_I64_LOAD16_U:
    222     case WASM_INSN_I64_LOAD32_S:
    223     case WASM_INSN_I64_LOAD32_U:
    224     case WASM_INSN_I64_ATOMIC_LOAD:
    225     case WASM_INSN_I64_ATOMIC_LOAD8_U:
    226     case WASM_INSN_I64_ATOMIC_LOAD16_U:
    227     case WASM_INSN_I64_ATOMIC_LOAD32_U:
    228       return WASM_VAL_I64;
    229     default:
    230       return WASM_VAL_I32;
    231   }
    232 }
    233 
    234 WasmValType wasm_store_value_type(uint8_t kind) {
    235   switch (kind) {
    236     case WASM_INSN_F32_STORE:
    237       return WASM_VAL_F32;
    238     case WASM_INSN_F64_STORE:
    239       return WASM_VAL_F64;
    240     case WASM_INSN_I64_STORE:
    241     case WASM_INSN_I64_STORE8:
    242     case WASM_INSN_I64_STORE16:
    243     case WASM_INSN_I64_STORE32:
    244     case WASM_INSN_I64_ATOMIC_STORE:
    245     case WASM_INSN_I64_ATOMIC_STORE8:
    246     case WASM_INSN_I64_ATOMIC_STORE16:
    247     case WASM_INSN_I64_ATOMIC_STORE32:
    248       return WASM_VAL_I64;
    249     default:
    250       return WASM_VAL_I32;
    251   }
    252 }
    253 
    254 WasmValType wasm_atomic_value_type(uint8_t kind) {
    255   switch (kind) {
    256     case WASM_INSN_I64_ATOMIC_LOAD:
    257     case WASM_INSN_I64_ATOMIC_LOAD8_U:
    258     case WASM_INSN_I64_ATOMIC_LOAD16_U:
    259     case WASM_INSN_I64_ATOMIC_LOAD32_U:
    260     case WASM_INSN_I64_ATOMIC_STORE:
    261     case WASM_INSN_I64_ATOMIC_STORE8:
    262     case WASM_INSN_I64_ATOMIC_STORE16:
    263     case WASM_INSN_I64_ATOMIC_STORE32:
    264     case WASM_INSN_I64_ATOMIC_RMW_ADD:
    265     case WASM_INSN_I64_ATOMIC_RMW_SUB:
    266     case WASM_INSN_I64_ATOMIC_RMW_AND:
    267     case WASM_INSN_I64_ATOMIC_RMW_OR:
    268     case WASM_INSN_I64_ATOMIC_RMW_XOR:
    269     case WASM_INSN_I64_ATOMIC_RMW_XCHG:
    270     case WASM_INSN_I64_ATOMIC_RMW_CMPXCHG:
    271     case WASM_INSN_I64_ATOMIC_WAIT:
    272       return WASM_VAL_I64;
    273     default:
    274       return WASM_VAL_I32;
    275   }
    276 }
    277 
    278 KitCgAtomicOp wasm_atomic_rmw_op(uint8_t kind) {
    279   switch (kind) {
    280     case WASM_INSN_I32_ATOMIC_RMW_ADD:
    281     case WASM_INSN_I64_ATOMIC_RMW_ADD:
    282       return KIT_CG_ATOMIC_ADD;
    283     case WASM_INSN_I32_ATOMIC_RMW_SUB:
    284     case WASM_INSN_I64_ATOMIC_RMW_SUB:
    285       return KIT_CG_ATOMIC_SUB;
    286     case WASM_INSN_I32_ATOMIC_RMW_AND:
    287     case WASM_INSN_I64_ATOMIC_RMW_AND:
    288       return KIT_CG_ATOMIC_AND;
    289     case WASM_INSN_I32_ATOMIC_RMW_OR:
    290     case WASM_INSN_I64_ATOMIC_RMW_OR:
    291       return KIT_CG_ATOMIC_OR;
    292     case WASM_INSN_I32_ATOMIC_RMW_XOR:
    293     case WASM_INSN_I64_ATOMIC_RMW_XOR:
    294       return KIT_CG_ATOMIC_XOR;
    295     default:
    296       return KIT_CG_ATOMIC_XCHG;
    297   }
    298 }
    299 
    300 int wasm_int_unop_kind(uint8_t kind, WasmValType* vt) {
    301   if (kind == WASM_INSN_I32_CLZ || kind == WASM_INSN_I32_CTZ ||
    302       kind == WASM_INSN_I32_POPCNT || kind == WASM_INSN_I32_EXTEND8_S ||
    303       kind == WASM_INSN_I32_EXTEND16_S) {
    304     *vt = WASM_VAL_I32;
    305     return 1;
    306   }
    307   if (kind == WASM_INSN_I64_CLZ || kind == WASM_INSN_I64_CTZ ||
    308       kind == WASM_INSN_I64_POPCNT || kind == WASM_INSN_I64_EXTEND8_S ||
    309       kind == WASM_INSN_I64_EXTEND16_S || kind == WASM_INSN_I64_EXTEND32_S) {
    310     *vt = WASM_VAL_I64;
    311     return 1;
    312   }
    313   return 0;
    314 }
    315 
    316 int wasm_fp_unop_kind(uint8_t kind, WasmValType* vt) {
    317   if (kind == WASM_INSN_F32_NEG) {
    318     *vt = WASM_VAL_F32;
    319     return 1;
    320   }
    321   if (kind == WASM_INSN_F64_NEG) {
    322     *vt = WASM_VAL_F64;
    323     return 1;
    324   }
    325   return 0;
    326 }
    327 
    328 int wasm_fp_binop_kind(uint8_t kind, WasmValType* vt) {
    329   if (kind == WASM_INSN_F32_ADD || kind == WASM_INSN_F32_SUB ||
    330       kind == WASM_INSN_F32_MUL || kind == WASM_INSN_F32_DIV) {
    331     *vt = WASM_VAL_F32;
    332     return 1;
    333   }
    334   if (kind == WASM_INSN_F64_ADD || kind == WASM_INSN_F64_SUB ||
    335       kind == WASM_INSN_F64_MUL || kind == WASM_INSN_F64_DIV) {
    336     *vt = WASM_VAL_F64;
    337     return 1;
    338   }
    339   return 0;
    340 }
    341 
    342 int wasm_fp_cmp_kind(uint8_t kind, WasmValType* vt) {
    343   if (kind == WASM_INSN_F32_EQ || kind == WASM_INSN_F32_NE ||
    344       kind == WASM_INSN_F32_LT || kind == WASM_INSN_F32_GT ||
    345       kind == WASM_INSN_F32_LE || kind == WASM_INSN_F32_GE) {
    346     *vt = WASM_VAL_F32;
    347     return 1;
    348   }
    349   if (kind == WASM_INSN_F64_EQ || kind == WASM_INSN_F64_NE ||
    350       kind == WASM_INSN_F64_LT || kind == WASM_INSN_F64_GT ||
    351       kind == WASM_INSN_F64_LE || kind == WASM_INSN_F64_GE) {
    352     *vt = WASM_VAL_F64;
    353     return 1;
    354   }
    355   return 0;
    356 }
    357 
    358 int wasm_conversion_kind(uint8_t kind, WasmValType* src, WasmValType* dst) {
    359   switch (kind) {
    360     case WASM_INSN_I32_WRAP_I64:
    361       *src = WASM_VAL_I64;
    362       *dst = WASM_VAL_I32;
    363       return 1;
    364     case WASM_INSN_I64_EXTEND_I32_S:
    365     case WASM_INSN_I64_EXTEND_I32_U:
    366       *src = WASM_VAL_I32;
    367       *dst = WASM_VAL_I64;
    368       return 1;
    369     case WASM_INSN_I32_TRUNC_F32_S:
    370     case WASM_INSN_I32_TRUNC_F32_U:
    371       *src = WASM_VAL_F32;
    372       *dst = WASM_VAL_I32;
    373       return 1;
    374     case WASM_INSN_I32_TRUNC_F64_S:
    375     case WASM_INSN_I32_TRUNC_F64_U:
    376       *src = WASM_VAL_F64;
    377       *dst = WASM_VAL_I32;
    378       return 1;
    379     case WASM_INSN_I64_TRUNC_F32_S:
    380     case WASM_INSN_I64_TRUNC_F32_U:
    381       *src = WASM_VAL_F32;
    382       *dst = WASM_VAL_I64;
    383       return 1;
    384     case WASM_INSN_I64_TRUNC_F64_S:
    385     case WASM_INSN_I64_TRUNC_F64_U:
    386       *src = WASM_VAL_F64;
    387       *dst = WASM_VAL_I64;
    388       return 1;
    389     case WASM_INSN_F32_CONVERT_I32_S:
    390     case WASM_INSN_F32_CONVERT_I32_U:
    391       *src = WASM_VAL_I32;
    392       *dst = WASM_VAL_F32;
    393       return 1;
    394     case WASM_INSN_F32_CONVERT_I64_S:
    395     case WASM_INSN_F32_CONVERT_I64_U:
    396       *src = WASM_VAL_I64;
    397       *dst = WASM_VAL_F32;
    398       return 1;
    399     case WASM_INSN_F64_CONVERT_I32_S:
    400     case WASM_INSN_F64_CONVERT_I32_U:
    401       *src = WASM_VAL_I32;
    402       *dst = WASM_VAL_F64;
    403       return 1;
    404     case WASM_INSN_F64_CONVERT_I64_S:
    405     case WASM_INSN_F64_CONVERT_I64_U:
    406       *src = WASM_VAL_I64;
    407       *dst = WASM_VAL_F64;
    408       return 1;
    409     case WASM_INSN_F32_DEMOTE_F64:
    410       *src = WASM_VAL_F64;
    411       *dst = WASM_VAL_F32;
    412       return 1;
    413     case WASM_INSN_F64_PROMOTE_F32:
    414       *src = WASM_VAL_F32;
    415       *dst = WASM_VAL_F64;
    416       return 1;
    417     case WASM_INSN_I32_REINTERPRET_F32:
    418       *src = WASM_VAL_F32;
    419       *dst = WASM_VAL_I32;
    420       return 1;
    421     case WASM_INSN_I64_REINTERPRET_F64:
    422       *src = WASM_VAL_F64;
    423       *dst = WASM_VAL_I64;
    424       return 1;
    425     case WASM_INSN_F32_REINTERPRET_I32:
    426       *src = WASM_VAL_I32;
    427       *dst = WASM_VAL_F32;
    428       return 1;
    429     case WASM_INSN_F64_REINTERPRET_I64:
    430       *src = WASM_VAL_I64;
    431       *dst = WASM_VAL_F64;
    432       return 1;
    433     default:
    434       return 0;
    435   }
    436 }
    437 
    438 /* WAT mnemonic for an instruction kind. Spellings live in WASM_INSN_TABLE so
    439  * the encoder, disassembler, and WAT parser all agree. Returns ".unknown" for
    440  * any out-of-range kind rather than NULL so callers can print unconditionally. */
    441 const char* wasm_insn_mnemonic(WasmInsnKind kind) {
    442   const WasmInsnInfo* info = wasm_insn_info(kind);
    443   return info ? info->mnemonic : ".unknown";
    444 }