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