decode.c (48694B)
1 #include "wasm/wasm.h" 2 3 typedef struct BinReader { 4 KitCompiler* c; 5 const uint8_t* data; 6 size_t len; 7 size_t pos; 8 WasmModule* module; 9 } BinReader; 10 11 static uint8_t bin_u8(BinReader* r) { 12 if (r->pos >= r->len) 13 wasm_error(r->c, wasm_loc(0, 0), "wasm: unexpected end of file"); 14 return r->data[r->pos++]; 15 } 16 17 static uint32_t bin_uleb(BinReader* r) { 18 uint32_t result = 0, shift = 0; 19 uint32_t nbytes = 0; 20 for (;;) { 21 uint8_t b = bin_u8(r); 22 if (nbytes++ >= 5u || (shift == 28u && (b & 0xf0u))) 23 wasm_error(r->c, wasm_loc(0, 0), "wasm: invalid uleb128"); 24 result |= (uint32_t)(b & 0x7fu) << shift; 25 if (!(b & 0x80u)) return result; 26 shift += 7u; 27 } 28 } 29 30 static uint64_t bin_uleb64(BinReader* r) { 31 uint64_t result = 0; 32 uint32_t shift = 0; 33 uint32_t nbytes = 0; 34 for (;;) { 35 uint8_t b = bin_u8(r); 36 if (nbytes++ >= 10u || (shift == 63u && (b & 0xfeu))) 37 wasm_error(r->c, wasm_loc(0, 0), "wasm: invalid uleb128"); 38 result |= (uint64_t)(b & 0x7fu) << shift; 39 if (!(b & 0x80u)) return result; 40 shift += 7u; 41 } 42 } 43 44 static int64_t bin_sleb(BinReader* r, uint32_t bits) { 45 /* Accumulate in the unsigned domain: a 7-bit group can land in bit 63 46 (shift == 63 for a 10-byte i64), where a signed left shift is UB. */ 47 uint64_t result = 0; 48 uint32_t shift = 0; 49 uint32_t max_bytes = (bits + 6u) / 7u; 50 uint32_t nbytes = 0; 51 uint8_t b; 52 do { 53 if (nbytes++ >= max_bytes) 54 wasm_error(r->c, wasm_loc(0, 0), "wasm: invalid sleb128"); 55 b = bin_u8(r); 56 result |= (uint64_t)(b & 0x7fu) << shift; 57 shift += 7u; 58 } while (b & 0x80u); 59 if (shift < bits && (b & 0x40u)) result |= ~(uint64_t)0 << shift; 60 return (int64_t)result; 61 } 62 63 static double bin_f32(BinReader* r) { 64 uint32_t bits = 0; 65 float f; 66 for (uint32_t i = 0; i < 4u; ++i) bits |= (uint32_t)bin_u8(r) << (i * 8u); 67 memcpy(&f, &bits, sizeof f); 68 return (double)f; 69 } 70 71 static double bin_f64(BinReader* r) { 72 uint64_t bits = 0; 73 double d; 74 for (uint32_t i = 0; i < 8u; ++i) bits |= (uint64_t)bin_u8(r) << (i * 8u); 75 memcpy(&d, &bits, sizeof d); 76 return d; 77 } 78 79 static void bin_memarg(BinReader* r, uint32_t* align, uint64_t* offset, 80 uint32_t* memidx) { 81 uint32_t a = bin_uleb(r); 82 *memidx = 0; 83 if (a >= 64u && a < 128u) { 84 *align = a - 64u; 85 *memidx = bin_uleb(r); 86 } else if (a < 64u) { 87 *align = a; 88 } else { 89 wasm_error(r->c, wasm_loc(0, 0), "wasm: bad memory alignment"); 90 } 91 *offset = bin_uleb64(r); 92 } 93 94 static void bin_need(BinReader* r, size_t n) { 95 if (n > r->len || r->pos > r->len - n) 96 wasm_error(r->c, wasm_loc(0, 0), "wasm: section length out of bounds"); 97 } 98 99 static char* bin_name(BinReader* r, uint32_t* len_out) { 100 uint32_t n = bin_uleb(r); 101 char* name; 102 bin_need(r, n); 103 name = wasm_strdup(r->module->heap, (const char*)(r->data + r->pos), n); 104 if (!name) wasm_error(r->c, wasm_loc(0, 0), "wasm: out of memory"); 105 r->pos += n; 106 if (len_out) *len_out = n; 107 return name; 108 } 109 110 static WasmValType bin_val_type(BinReader* r, int refs_ok) { 111 uint8_t b = bin_u8(r); 112 switch (b) { 113 case WASM_VAL_I32: 114 case WASM_VAL_I64: 115 case WASM_VAL_F32: 116 case WASM_VAL_F64: 117 return (WasmValType)b; 118 case WASM_VAL_FUNCREF: 119 case WASM_VAL_EXTERNREF: 120 if (refs_ok) return (WasmValType)b; 121 break; 122 default: 123 break; 124 } 125 wasm_error(r->c, wasm_loc(0, 0), "wasm: unsupported value type 0x%02x", b); 126 return WASM_VAL_I32; 127 } 128 129 /* Decode one instruction opcode body (everything except the body-terminating 130 * 0x0b end) into f's instruction list, advancing *rp. Shared verbatim with the 131 * function-body decode loop so the opcode mapping has a single source of truth; 132 * reused by wasm_decode_one_insn for the disassembler. */ 133 static void decode_body_insn(BinReader* rp, WasmModule* out, WasmFunc* f, 134 uint8_t op, uint32_t* pcontrol_depth) { 135 BinReader r = *rp; 136 KitCompiler* c = r.c; 137 uint32_t control_depth = *pcontrol_depth; 138 switch (op) { 139 case 0x00: 140 wasm_func_add_insn(c, out, f, WASM_INSN_UNREACHABLE, 0); 141 break; 142 case 0x01: 143 wasm_func_add_insn(c, out, f, WASM_INSN_NOP, 0); 144 break; 145 case 0x02: 146 if (bin_u8(&r) != 0x40u) 147 wasm_error(c, wasm_loc(0, 0), "wasm: block results are unsupported"); 148 control_depth++; 149 wasm_func_add_insn(c, out, f, WASM_INSN_BLOCK, 0); 150 break; 151 case 0x03: 152 if (bin_u8(&r) != 0x40u) 153 wasm_error(c, wasm_loc(0, 0), "wasm: loop results are unsupported"); 154 control_depth++; 155 wasm_func_add_insn(c, out, f, WASM_INSN_LOOP, 0); 156 break; 157 case 0x04: 158 if (bin_u8(&r) != 0x40u) 159 wasm_error(c, wasm_loc(0, 0), "wasm: if results are unsupported"); 160 control_depth++; 161 wasm_func_add_insn(c, out, f, WASM_INSN_IF, 0); 162 break; 163 case 0x05: 164 wasm_func_add_insn(c, out, f, WASM_INSN_ELSE, 0); 165 break; 166 case 0x0c: 167 wasm_func_add_insn(c, out, f, WASM_INSN_BR, bin_uleb(&r)); 168 break; 169 case 0x0d: 170 wasm_func_add_insn(c, out, f, WASM_INSN_BR_IF, bin_uleb(&r)); 171 break; 172 case 0x0e: { 173 WasmInsn* in; 174 uint32_t n = bin_uleb(&r); 175 /* Each target is at least one byte, so a count exceeding the 176 * remaining input is malformed — reject before allocating. */ 177 if ((uint64_t)n >= r.len - r.pos) 178 wasm_error(c, wasm_loc(0, 0), 179 "wasm: br_table target count exceeds input"); 180 wasm_func_add_insn(c, out, f, WASM_INSN_BR_TABLE, 0); 181 in = &f->insns[f->ninsns - 1u]; 182 wasm_insn_set_targets(c, out, in, NULL, n + 1u); 183 for (uint32_t k = 0; k < n; ++k) in->targets[k] = bin_uleb(&r); 184 in->targets[n] = bin_uleb(&r); 185 break; 186 } 187 case 0x0f: 188 wasm_func_add_insn(c, out, f, WASM_INSN_RETURN, 0); 189 break; 190 case 0x1a: 191 wasm_func_add_insn(c, out, f, WASM_INSN_DROP, 0); 192 break; 193 case 0x1b: 194 wasm_func_add_insn(c, out, f, WASM_INSN_SELECT, 0); 195 break; 196 case 0x28: { 197 uint32_t ma, mi; 198 uint64_t mo; 199 bin_memarg(&r, &ma, &mo, &mi); 200 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD, ma, mo, mi); 201 } break; 202 case 0x29: { 203 uint32_t ma, mi; 204 uint64_t mo; 205 bin_memarg(&r, &ma, &mo, &mi); 206 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD, ma, mo, mi); 207 } break; 208 case 0x2a: { 209 uint32_t ma, mi; 210 uint64_t mo; 211 bin_memarg(&r, &ma, &mo, &mi); 212 wasm_func_add_mem_insn(c, out, f, WASM_INSN_F32_LOAD, ma, mo, mi); 213 } break; 214 case 0x2b: { 215 uint32_t ma, mi; 216 uint64_t mo; 217 bin_memarg(&r, &ma, &mo, &mi); 218 wasm_func_add_mem_insn(c, out, f, WASM_INSN_F64_LOAD, ma, mo, mi); 219 } break; 220 case 0x2c: { 221 uint32_t ma, mi; 222 uint64_t mo; 223 bin_memarg(&r, &ma, &mo, &mi); 224 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD8_S, ma, mo, mi); 225 } break; 226 case 0x2d: { 227 uint32_t ma, mi; 228 uint64_t mo; 229 bin_memarg(&r, &ma, &mo, &mi); 230 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD8_U, ma, mo, mi); 231 } break; 232 case 0x2e: { 233 uint32_t ma, mi; 234 uint64_t mo; 235 bin_memarg(&r, &ma, &mo, &mi); 236 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD16_S, ma, mo, mi); 237 } break; 238 case 0x2f: { 239 uint32_t ma, mi; 240 uint64_t mo; 241 bin_memarg(&r, &ma, &mo, &mi); 242 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD16_U, ma, mo, mi); 243 } break; 244 case 0x30: { 245 uint32_t ma, mi; 246 uint64_t mo; 247 bin_memarg(&r, &ma, &mo, &mi); 248 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD8_S, ma, mo, mi); 249 } break; 250 case 0x31: { 251 uint32_t ma, mi; 252 uint64_t mo; 253 bin_memarg(&r, &ma, &mo, &mi); 254 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD8_U, ma, mo, mi); 255 } break; 256 case 0x32: { 257 uint32_t ma, mi; 258 uint64_t mo; 259 bin_memarg(&r, &ma, &mo, &mi); 260 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD16_S, ma, mo, mi); 261 } break; 262 case 0x33: { 263 uint32_t ma, mi; 264 uint64_t mo; 265 bin_memarg(&r, &ma, &mo, &mi); 266 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD16_U, ma, mo, mi); 267 } break; 268 case 0x34: { 269 uint32_t ma, mi; 270 uint64_t mo; 271 bin_memarg(&r, &ma, &mo, &mi); 272 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD32_S, ma, mo, mi); 273 } break; 274 case 0x35: { 275 uint32_t ma, mi; 276 uint64_t mo; 277 bin_memarg(&r, &ma, &mo, &mi); 278 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD32_U, ma, mo, mi); 279 } break; 280 case 0x36: { 281 uint32_t ma, mi; 282 uint64_t mo; 283 bin_memarg(&r, &ma, &mo, &mi); 284 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_STORE, ma, mo, mi); 285 } break; 286 case 0x37: { 287 uint32_t ma, mi; 288 uint64_t mo; 289 bin_memarg(&r, &ma, &mo, &mi); 290 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE, ma, mo, mi); 291 } break; 292 case 0x38: { 293 uint32_t ma, mi; 294 uint64_t mo; 295 bin_memarg(&r, &ma, &mo, &mi); 296 wasm_func_add_mem_insn(c, out, f, WASM_INSN_F32_STORE, ma, mo, mi); 297 } break; 298 case 0x39: { 299 uint32_t ma, mi; 300 uint64_t mo; 301 bin_memarg(&r, &ma, &mo, &mi); 302 wasm_func_add_mem_insn(c, out, f, WASM_INSN_F64_STORE, ma, mo, mi); 303 } break; 304 case 0x3a: { 305 uint32_t ma, mi; 306 uint64_t mo; 307 bin_memarg(&r, &ma, &mo, &mi); 308 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_STORE8, ma, mo, mi); 309 } break; 310 case 0x3b: { 311 uint32_t ma, mi; 312 uint64_t mo; 313 bin_memarg(&r, &ma, &mo, &mi); 314 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_STORE16, ma, mo, mi); 315 } break; 316 case 0x3c: { 317 uint32_t ma, mi; 318 uint64_t mo; 319 bin_memarg(&r, &ma, &mo, &mi); 320 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE8, ma, mo, mi); 321 } break; 322 case 0x3d: { 323 uint32_t ma, mi; 324 uint64_t mo; 325 bin_memarg(&r, &ma, &mo, &mi); 326 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE16, ma, mo, mi); 327 } break; 328 case 0x3e: { 329 uint32_t ma, mi; 330 uint64_t mo; 331 bin_memarg(&r, &ma, &mo, &mi); 332 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE32, ma, mo, mi); 333 } break; 334 case 0x3f: 335 wasm_func_add_insn(c, out, f, WASM_INSN_MEMORY_SIZE, 0); 336 f->insns[f->ninsns - 1u].memidx = bin_uleb(&r); 337 break; 338 case 0x40: 339 wasm_func_add_insn(c, out, f, WASM_INSN_MEMORY_GROW, 0); 340 f->insns[f->ninsns - 1u].memidx = bin_uleb(&r); 341 break; 342 case 0x10: 343 wasm_func_add_insn(c, out, f, WASM_INSN_CALL, bin_uleb(&r)); 344 break; 345 case 0x11: { 346 WasmInsn* in; 347 wasm_func_add_insn(c, out, f, WASM_INSN_CALL_INDIRECT, bin_uleb(&r)); 348 in = &f->insns[f->ninsns - 1u]; 349 in->align = bin_uleb(&r); 350 break; 351 } 352 case 0x12: 353 wasm_func_add_insn(c, out, f, WASM_INSN_RETURN_CALL, bin_uleb(&r)); 354 break; 355 case 0x13: { 356 WasmInsn* in; 357 wasm_func_add_insn(c, out, f, WASM_INSN_RETURN_CALL_INDIRECT, 358 bin_uleb(&r)); 359 in = &f->insns[f->ninsns - 1u]; 360 in->align = bin_uleb(&r); 361 break; 362 } 363 case 0x14: 364 wasm_func_add_insn(c, out, f, WASM_INSN_CALL_REF, bin_uleb(&r)); 365 break; 366 case 0x15: 367 wasm_func_add_insn(c, out, f, WASM_INSN_RETURN_CALL_REF, bin_uleb(&r)); 368 break; 369 case 0x20: 370 wasm_func_add_insn(c, out, f, WASM_INSN_LOCAL_GET, bin_uleb(&r)); 371 break; 372 case 0x21: 373 wasm_func_add_insn(c, out, f, WASM_INSN_LOCAL_SET, bin_uleb(&r)); 374 break; 375 case 0x22: 376 wasm_func_add_insn(c, out, f, WASM_INSN_LOCAL_TEE, bin_uleb(&r)); 377 break; 378 case 0x23: 379 wasm_func_add_insn(c, out, f, WASM_INSN_GLOBAL_GET, bin_uleb(&r)); 380 break; 381 case 0x24: 382 wasm_func_add_insn(c, out, f, WASM_INSN_GLOBAL_SET, bin_uleb(&r)); 383 break; 384 case 0x41: 385 wasm_func_add_insn(c, out, f, WASM_INSN_I32_CONST, bin_sleb(&r, 32)); 386 break; 387 case 0x42: 388 wasm_func_add_insn(c, out, f, WASM_INSN_I64_CONST, bin_sleb(&r, 64)); 389 break; 390 case 0x43: 391 wasm_func_add_fp_insn(c, out, f, WASM_INSN_F32_CONST, bin_f32(&r)); 392 break; 393 case 0x44: 394 wasm_func_add_fp_insn(c, out, f, WASM_INSN_F64_CONST, bin_f64(&r)); 395 break; 396 case 0xd0: 397 wasm_func_add_insn(c, out, f, WASM_INSN_REF_NULL, bin_val_type(&r, 1)); 398 break; 399 case 0xd1: 400 wasm_func_add_insn(c, out, f, WASM_INSN_REF_IS_NULL, 0); 401 break; 402 case 0xd2: 403 wasm_func_add_insn(c, out, f, WASM_INSN_REF_FUNC, bin_uleb(&r)); 404 break; 405 case 0x45: 406 wasm_func_add_insn(c, out, f, WASM_INSN_I32_EQZ, 0); 407 break; 408 case 0x46: 409 wasm_func_add_insn(c, out, f, WASM_INSN_I32_EQ, 0); 410 break; 411 case 0x47: 412 wasm_func_add_insn(c, out, f, WASM_INSN_I32_NE, 0); 413 break; 414 case 0x48: 415 wasm_func_add_insn(c, out, f, WASM_INSN_I32_LT_S, 0); 416 break; 417 case 0x49: 418 wasm_func_add_insn(c, out, f, WASM_INSN_I32_LT_U, 0); 419 break; 420 case 0x4a: 421 wasm_func_add_insn(c, out, f, WASM_INSN_I32_GT_S, 0); 422 break; 423 case 0x4b: 424 wasm_func_add_insn(c, out, f, WASM_INSN_I32_GT_U, 0); 425 break; 426 case 0x4c: 427 wasm_func_add_insn(c, out, f, WASM_INSN_I32_LE_S, 0); 428 break; 429 case 0x4d: 430 wasm_func_add_insn(c, out, f, WASM_INSN_I32_LE_U, 0); 431 break; 432 case 0x4e: 433 wasm_func_add_insn(c, out, f, WASM_INSN_I32_GE_S, 0); 434 break; 435 case 0x4f: 436 wasm_func_add_insn(c, out, f, WASM_INSN_I32_GE_U, 0); 437 break; 438 case 0x50: 439 wasm_func_add_insn(c, out, f, WASM_INSN_I64_EQZ, 0); 440 break; 441 case 0x51: 442 wasm_func_add_insn(c, out, f, WASM_INSN_I64_EQ, 0); 443 break; 444 case 0x52: 445 wasm_func_add_insn(c, out, f, WASM_INSN_I64_NE, 0); 446 break; 447 case 0x53: 448 wasm_func_add_insn(c, out, f, WASM_INSN_I64_LT_S, 0); 449 break; 450 case 0x54: 451 wasm_func_add_insn(c, out, f, WASM_INSN_I64_LT_U, 0); 452 break; 453 case 0x55: 454 wasm_func_add_insn(c, out, f, WASM_INSN_I64_GT_S, 0); 455 break; 456 case 0x56: 457 wasm_func_add_insn(c, out, f, WASM_INSN_I64_GT_U, 0); 458 break; 459 case 0x57: 460 wasm_func_add_insn(c, out, f, WASM_INSN_I64_LE_S, 0); 461 break; 462 case 0x58: 463 wasm_func_add_insn(c, out, f, WASM_INSN_I64_LE_U, 0); 464 break; 465 case 0x59: 466 wasm_func_add_insn(c, out, f, WASM_INSN_I64_GE_S, 0); 467 break; 468 case 0x5a: 469 wasm_func_add_insn(c, out, f, WASM_INSN_I64_GE_U, 0); 470 break; 471 case 0x6a: 472 wasm_func_add_insn(c, out, f, WASM_INSN_I32_ADD, 0); 473 break; 474 case 0x6b: 475 wasm_func_add_insn(c, out, f, WASM_INSN_I32_SUB, 0); 476 break; 477 case 0x6c: 478 wasm_func_add_insn(c, out, f, WASM_INSN_I32_MUL, 0); 479 break; 480 case 0x6d: 481 wasm_func_add_insn(c, out, f, WASM_INSN_I32_DIV_S, 0); 482 break; 483 case 0x6e: 484 wasm_func_add_insn(c, out, f, WASM_INSN_I32_DIV_U, 0); 485 break; 486 case 0x6f: 487 wasm_func_add_insn(c, out, f, WASM_INSN_I32_REM_S, 0); 488 break; 489 case 0x70: 490 wasm_func_add_insn(c, out, f, WASM_INSN_I32_REM_U, 0); 491 break; 492 case 0x71: 493 wasm_func_add_insn(c, out, f, WASM_INSN_I32_AND, 0); 494 break; 495 case 0x72: 496 wasm_func_add_insn(c, out, f, WASM_INSN_I32_OR, 0); 497 break; 498 case 0x73: 499 wasm_func_add_insn(c, out, f, WASM_INSN_I32_XOR, 0); 500 break; 501 case 0x74: 502 wasm_func_add_insn(c, out, f, WASM_INSN_I32_SHL, 0); 503 break; 504 case 0x75: 505 wasm_func_add_insn(c, out, f, WASM_INSN_I32_SHR_S, 0); 506 break; 507 case 0x76: 508 wasm_func_add_insn(c, out, f, WASM_INSN_I32_SHR_U, 0); 509 break; 510 case 0x67: 511 wasm_func_add_insn(c, out, f, WASM_INSN_I32_CLZ, 0); 512 break; 513 case 0x68: 514 wasm_func_add_insn(c, out, f, WASM_INSN_I32_CTZ, 0); 515 break; 516 case 0x69: 517 wasm_func_add_insn(c, out, f, WASM_INSN_I32_POPCNT, 0); 518 break; 519 case 0x77: 520 wasm_func_add_insn(c, out, f, WASM_INSN_I32_ROTL, 0); 521 break; 522 case 0x78: 523 wasm_func_add_insn(c, out, f, WASM_INSN_I32_ROTR, 0); 524 break; 525 case 0x79: 526 wasm_func_add_insn(c, out, f, WASM_INSN_I64_CLZ, 0); 527 break; 528 case 0x7a: 529 wasm_func_add_insn(c, out, f, WASM_INSN_I64_CTZ, 0); 530 break; 531 case 0x7b: 532 wasm_func_add_insn(c, out, f, WASM_INSN_I64_POPCNT, 0); 533 break; 534 case 0x7c: 535 wasm_func_add_insn(c, out, f, WASM_INSN_I64_ADD, 0); 536 break; 537 case 0x7d: 538 wasm_func_add_insn(c, out, f, WASM_INSN_I64_SUB, 0); 539 break; 540 case 0x7e: 541 wasm_func_add_insn(c, out, f, WASM_INSN_I64_MUL, 0); 542 break; 543 case 0x7f: 544 wasm_func_add_insn(c, out, f, WASM_INSN_I64_DIV_S, 0); 545 break; 546 case 0x80: 547 wasm_func_add_insn(c, out, f, WASM_INSN_I64_DIV_U, 0); 548 break; 549 case 0x81: 550 wasm_func_add_insn(c, out, f, WASM_INSN_I64_REM_S, 0); 551 break; 552 case 0x82: 553 wasm_func_add_insn(c, out, f, WASM_INSN_I64_REM_U, 0); 554 break; 555 case 0x83: 556 wasm_func_add_insn(c, out, f, WASM_INSN_I64_AND, 0); 557 break; 558 case 0x84: 559 wasm_func_add_insn(c, out, f, WASM_INSN_I64_OR, 0); 560 break; 561 case 0x85: 562 wasm_func_add_insn(c, out, f, WASM_INSN_I64_XOR, 0); 563 break; 564 case 0x86: 565 wasm_func_add_insn(c, out, f, WASM_INSN_I64_SHL, 0); 566 break; 567 case 0x87: 568 wasm_func_add_insn(c, out, f, WASM_INSN_I64_SHR_S, 0); 569 break; 570 case 0x88: 571 wasm_func_add_insn(c, out, f, WASM_INSN_I64_SHR_U, 0); 572 break; 573 case 0x89: 574 wasm_func_add_insn(c, out, f, WASM_INSN_I64_ROTL, 0); 575 break; 576 case 0x8a: 577 wasm_func_add_insn(c, out, f, WASM_INSN_I64_ROTR, 0); 578 break; 579 case 0x92: 580 wasm_func_add_insn(c, out, f, WASM_INSN_F32_ADD, 0); 581 break; 582 case 0x93: 583 wasm_func_add_insn(c, out, f, WASM_INSN_F32_SUB, 0); 584 break; 585 case 0x94: 586 wasm_func_add_insn(c, out, f, WASM_INSN_F32_MUL, 0); 587 break; 588 case 0x95: 589 wasm_func_add_insn(c, out, f, WASM_INSN_F32_DIV, 0); 590 break; 591 case 0xa0: 592 wasm_func_add_insn(c, out, f, WASM_INSN_F64_ADD, 0); 593 break; 594 case 0xa1: 595 wasm_func_add_insn(c, out, f, WASM_INSN_F64_SUB, 0); 596 break; 597 case 0xa2: 598 wasm_func_add_insn(c, out, f, WASM_INSN_F64_MUL, 0); 599 break; 600 case 0xa3: 601 wasm_func_add_insn(c, out, f, WASM_INSN_F64_DIV, 0); 602 break; 603 case 0x5b: 604 wasm_func_add_insn(c, out, f, WASM_INSN_F32_EQ, 0); 605 break; 606 case 0x5c: 607 wasm_func_add_insn(c, out, f, WASM_INSN_F32_NE, 0); 608 break; 609 case 0x5d: 610 wasm_func_add_insn(c, out, f, WASM_INSN_F32_LT, 0); 611 break; 612 case 0x5e: 613 wasm_func_add_insn(c, out, f, WASM_INSN_F32_GT, 0); 614 break; 615 case 0x5f: 616 wasm_func_add_insn(c, out, f, WASM_INSN_F32_LE, 0); 617 break; 618 case 0x60: 619 wasm_func_add_insn(c, out, f, WASM_INSN_F32_GE, 0); 620 break; 621 case 0x61: 622 wasm_func_add_insn(c, out, f, WASM_INSN_F64_EQ, 0); 623 break; 624 case 0x62: 625 wasm_func_add_insn(c, out, f, WASM_INSN_F64_NE, 0); 626 break; 627 case 0x63: 628 wasm_func_add_insn(c, out, f, WASM_INSN_F64_LT, 0); 629 break; 630 case 0x64: 631 wasm_func_add_insn(c, out, f, WASM_INSN_F64_GT, 0); 632 break; 633 case 0x65: 634 wasm_func_add_insn(c, out, f, WASM_INSN_F64_LE, 0); 635 break; 636 case 0x66: 637 wasm_func_add_insn(c, out, f, WASM_INSN_F64_GE, 0); 638 break; 639 case 0x8c: 640 wasm_func_add_insn(c, out, f, WASM_INSN_F32_NEG, 0); 641 break; 642 case 0x9a: 643 wasm_func_add_insn(c, out, f, WASM_INSN_F64_NEG, 0); 644 break; 645 case 0xa7: 646 wasm_func_add_insn(c, out, f, WASM_INSN_I32_WRAP_I64, 0); 647 break; 648 case 0xa8: 649 wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F32_S, 0); 650 break; 651 case 0xa9: 652 wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F32_U, 0); 653 break; 654 case 0xaa: 655 wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F64_S, 0); 656 break; 657 case 0xab: 658 wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F64_U, 0); 659 break; 660 case 0xac: 661 wasm_func_add_insn(c, out, f, WASM_INSN_I64_EXTEND_I32_S, 0); 662 break; 663 case 0xad: 664 wasm_func_add_insn(c, out, f, WASM_INSN_I64_EXTEND_I32_U, 0); 665 break; 666 case 0xae: 667 wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F32_S, 0); 668 break; 669 case 0xaf: 670 wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F32_U, 0); 671 break; 672 case 0xb0: 673 wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F64_S, 0); 674 break; 675 case 0xb1: 676 wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F64_U, 0); 677 break; 678 case 0xb2: 679 wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I32_S, 0); 680 break; 681 case 0xb3: 682 wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I32_U, 0); 683 break; 684 case 0xb4: 685 wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I64_S, 0); 686 break; 687 case 0xb5: 688 wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I64_U, 0); 689 break; 690 case 0xb6: 691 wasm_func_add_insn(c, out, f, WASM_INSN_F32_DEMOTE_F64, 0); 692 break; 693 case 0xb7: 694 wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I32_S, 0); 695 break; 696 case 0xb8: 697 wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I32_U, 0); 698 break; 699 case 0xb9: 700 wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I64_S, 0); 701 break; 702 case 0xba: 703 wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I64_U, 0); 704 break; 705 case 0xbb: 706 wasm_func_add_insn(c, out, f, WASM_INSN_F64_PROMOTE_F32, 0); 707 break; 708 case 0xbc: 709 wasm_func_add_insn(c, out, f, WASM_INSN_I32_REINTERPRET_F32, 0); 710 break; 711 case 0xbd: 712 wasm_func_add_insn(c, out, f, WASM_INSN_I64_REINTERPRET_F64, 0); 713 break; 714 case 0xbe: 715 wasm_func_add_insn(c, out, f, WASM_INSN_F32_REINTERPRET_I32, 0); 716 break; 717 case 0xbf: 718 wasm_func_add_insn(c, out, f, WASM_INSN_F64_REINTERPRET_I64, 0); 719 break; 720 case 0xc0: 721 wasm_func_add_insn(c, out, f, WASM_INSN_I32_EXTEND8_S, 0); 722 break; 723 case 0xc1: 724 wasm_func_add_insn(c, out, f, WASM_INSN_I32_EXTEND16_S, 0); 725 break; 726 case 0xc2: 727 wasm_func_add_insn(c, out, f, WASM_INSN_I64_EXTEND8_S, 0); 728 break; 729 case 0xc3: 730 wasm_func_add_insn(c, out, f, WASM_INSN_I64_EXTEND16_S, 0); 731 break; 732 case 0xc4: 733 wasm_func_add_insn(c, out, f, WASM_INSN_I64_EXTEND32_S, 0); 734 break; 735 case 0xfc: { 736 uint32_t sub = bin_uleb(&r); 737 switch (sub) { 738 case 0x00: 739 wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_SAT_F32_S, 0); 740 break; 741 case 0x01: 742 wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_SAT_F32_U, 0); 743 break; 744 case 0x02: 745 wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_SAT_F64_S, 0); 746 break; 747 case 0x03: 748 wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_SAT_F64_U, 0); 749 break; 750 case 0x04: 751 wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_SAT_F32_S, 0); 752 break; 753 case 0x05: 754 wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_SAT_F32_U, 0); 755 break; 756 case 0x06: 757 wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_SAT_F64_S, 0); 758 break; 759 case 0x07: 760 wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_SAT_F64_U, 0); 761 break; 762 case 0x08: { /* memory.init dataidx memidx */ 763 uint32_t dataidx = bin_uleb(&r); 764 uint32_t mi = bin_uleb(&r); 765 wasm_func_add_insn(c, out, f, WASM_INSN_MEMORY_INIT, 766 (int64_t)dataidx); 767 f->insns[f->ninsns - 1u].memidx = mi; 768 break; 769 } 770 case 0x09: { /* data.drop dataidx */ 771 uint32_t dataidx = bin_uleb(&r); 772 wasm_func_add_insn(c, out, f, WASM_INSN_DATA_DROP, (int64_t)dataidx); 773 break; 774 } 775 case 0x0a: { /* memory.copy dst_memidx src_memidx */ 776 uint32_t dst = bin_uleb(&r); 777 uint32_t src = bin_uleb(&r); 778 wasm_func_add_insn(c, out, f, WASM_INSN_MEMORY_COPY, 0); 779 f->insns[f->ninsns - 1u].memidx = dst; 780 f->insns[f->ninsns - 1u].aux_idx = src; 781 break; 782 } 783 case 0x0b: { /* memory.fill memidx */ 784 uint32_t mi = bin_uleb(&r); 785 wasm_func_add_insn(c, out, f, WASM_INSN_MEMORY_FILL, 0); 786 f->insns[f->ninsns - 1u].memidx = mi; 787 break; 788 } 789 case 0x0c: { /* table.init elemidx tableidx */ 790 uint32_t elemidx = bin_uleb(&r); 791 uint32_t ti = bin_uleb(&r); 792 wasm_func_add_insn(c, out, f, WASM_INSN_TABLE_INIT, (int64_t)elemidx); 793 f->insns[f->ninsns - 1u].aux_idx = ti; 794 break; 795 } 796 case 0x0d: { /* elem.drop elemidx */ 797 uint32_t elemidx = bin_uleb(&r); 798 wasm_func_add_insn(c, out, f, WASM_INSN_ELEM_DROP, (int64_t)elemidx); 799 break; 800 } 801 case 0x0e: { /* table.copy dst_tableidx src_tableidx */ 802 uint32_t dst = bin_uleb(&r); 803 uint32_t src = bin_uleb(&r); 804 wasm_func_add_insn(c, out, f, WASM_INSN_TABLE_COPY, (int64_t)dst); 805 f->insns[f->ninsns - 1u].aux_idx = src; 806 break; 807 } 808 case 0x0f: { /* table.grow tableidx */ 809 uint32_t ti = bin_uleb(&r); 810 wasm_func_add_insn(c, out, f, WASM_INSN_TABLE_GROW, (int64_t)ti); 811 break; 812 } 813 case 0x10: { /* table.size tableidx */ 814 uint32_t ti = bin_uleb(&r); 815 wasm_func_add_insn(c, out, f, WASM_INSN_TABLE_SIZE, (int64_t)ti); 816 break; 817 } 818 case 0x11: { /* table.fill tableidx */ 819 uint32_t ti = bin_uleb(&r); 820 wasm_func_add_insn(c, out, f, WASM_INSN_TABLE_FILL, (int64_t)ti); 821 break; 822 } 823 default: 824 wasm_error(c, wasm_loc(0, 0), "wasm: unsupported 0xfc opcode 0x%x", 825 sub); 826 } 827 break; 828 } 829 case 0xfe: { 830 uint32_t sub = bin_uleb(&r); 831 uint32_t ma, mi; 832 uint64_t mo; 833 switch (sub) { 834 case 0x00: 835 bin_memarg(&r, &ma, &mo, &mi); 836 wasm_func_add_mem_insn(c, out, f, WASM_INSN_MEMORY_ATOMIC_NOTIFY, ma, 837 mo, mi); 838 break; 839 case 0x01: 840 bin_memarg(&r, &ma, &mo, &mi); 841 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_WAIT, ma, mo, 842 mi); 843 break; 844 case 0x02: 845 bin_memarg(&r, &ma, &mo, &mi); 846 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_WAIT, ma, mo, 847 mi); 848 break; 849 case 0x03: 850 if (bin_u8(&r) != 0) 851 wasm_error(c, wasm_loc(0, 0), "wasm: bad atomic.fence"); 852 wasm_func_add_insn(c, out, f, WASM_INSN_ATOMIC_FENCE, 0); 853 break; 854 case 0x10: 855 bin_memarg(&r, &ma, &mo, &mi); 856 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_LOAD, ma, mo, 857 mi); 858 break; 859 case 0x11: 860 bin_memarg(&r, &ma, &mo, &mi); 861 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_LOAD, ma, mo, 862 mi); 863 break; 864 case 0x12: 865 bin_memarg(&r, &ma, &mo, &mi); 866 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_LOAD8_U, ma, 867 mo, mi); 868 break; 869 case 0x13: 870 bin_memarg(&r, &ma, &mo, &mi); 871 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_LOAD16_U, ma, 872 mo, mi); 873 break; 874 case 0x14: 875 bin_memarg(&r, &ma, &mo, &mi); 876 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_LOAD8_U, ma, 877 mo, mi); 878 break; 879 case 0x15: 880 bin_memarg(&r, &ma, &mo, &mi); 881 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_LOAD16_U, ma, 882 mo, mi); 883 break; 884 case 0x16: 885 bin_memarg(&r, &ma, &mo, &mi); 886 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_LOAD32_U, ma, 887 mo, mi); 888 break; 889 case 0x17: 890 bin_memarg(&r, &ma, &mo, &mi); 891 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_STORE, ma, mo, 892 mi); 893 break; 894 case 0x18: 895 bin_memarg(&r, &ma, &mo, &mi); 896 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_STORE, ma, mo, 897 mi); 898 break; 899 case 0x19: 900 bin_memarg(&r, &ma, &mo, &mi); 901 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_STORE8, ma, mo, 902 mi); 903 break; 904 case 0x1a: 905 bin_memarg(&r, &ma, &mo, &mi); 906 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_STORE16, ma, 907 mo, mi); 908 break; 909 case 0x1b: 910 bin_memarg(&r, &ma, &mo, &mi); 911 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_STORE8, ma, mo, 912 mi); 913 break; 914 case 0x1c: 915 bin_memarg(&r, &ma, &mo, &mi); 916 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_STORE16, ma, 917 mo, mi); 918 break; 919 case 0x1d: 920 bin_memarg(&r, &ma, &mo, &mi); 921 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_STORE32, ma, 922 mo, mi); 923 break; 924 case 0x1e: 925 bin_memarg(&r, &ma, &mo, &mi); 926 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_RMW_ADD, ma, 927 mo, mi); 928 break; 929 case 0x1f: 930 bin_memarg(&r, &ma, &mo, &mi); 931 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_RMW_ADD, ma, 932 mo, mi); 933 break; 934 case 0x25: 935 bin_memarg(&r, &ma, &mo, &mi); 936 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_RMW_SUB, ma, 937 mo, mi); 938 break; 939 case 0x26: 940 bin_memarg(&r, &ma, &mo, &mi); 941 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_RMW_SUB, ma, 942 mo, mi); 943 break; 944 case 0x2c: 945 bin_memarg(&r, &ma, &mo, &mi); 946 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_RMW_AND, ma, 947 mo, mi); 948 break; 949 case 0x2d: 950 bin_memarg(&r, &ma, &mo, &mi); 951 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_RMW_AND, ma, 952 mo, mi); 953 break; 954 case 0x33: 955 bin_memarg(&r, &ma, &mo, &mi); 956 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_RMW_OR, ma, mo, 957 mi); 958 break; 959 case 0x34: 960 bin_memarg(&r, &ma, &mo, &mi); 961 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_RMW_OR, ma, mo, 962 mi); 963 break; 964 case 0x3a: 965 bin_memarg(&r, &ma, &mo, &mi); 966 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_RMW_XOR, ma, 967 mo, mi); 968 break; 969 case 0x3b: 970 bin_memarg(&r, &ma, &mo, &mi); 971 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_RMW_XOR, ma, 972 mo, mi); 973 break; 974 case 0x41: 975 bin_memarg(&r, &ma, &mo, &mi); 976 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_RMW_XCHG, ma, 977 mo, mi); 978 break; 979 case 0x42: 980 bin_memarg(&r, &ma, &mo, &mi); 981 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_RMW_XCHG, ma, 982 mo, mi); 983 break; 984 case 0x48: 985 bin_memarg(&r, &ma, &mo, &mi); 986 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_ATOMIC_RMW_CMPXCHG, 987 ma, mo, mi); 988 break; 989 case 0x49: 990 bin_memarg(&r, &ma, &mo, &mi); 991 wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_ATOMIC_RMW_CMPXCHG, 992 ma, mo, mi); 993 break; 994 default: 995 wasm_error(c, wasm_loc(0, 0), "wasm: unsupported threads opcode 0x%x", 996 sub); 997 } 998 break; 999 } 1000 default: 1001 wasm_error(c, wasm_loc(0, 0), "wasm: unsupported opcode 0x%02x", op); 1002 } 1003 1004 *pcontrol_depth = control_depth; 1005 *rp = r; 1006 } 1007 1008 void wasm_decode_binary(KitCompiler* c, const KitSlice* input, 1009 WasmModule* out) { 1010 BinReader r; 1011 uint32_t nfunc_types = 0; 1012 uint8_t last_id = 0; 1013 memset(&r, 0, sizeof r); 1014 r.c = c; 1015 r.data = input->data; 1016 r.len = input->len; 1017 r.module = out; 1018 if (r.len < 8 || memcmp(r.data, "\0asm\1\0\0\0", 8) != 0) 1019 wasm_error(c, wasm_loc(0, 0), "wasm: bad magic or version"); 1020 r.pos = 8; 1021 while (r.pos < r.len) { 1022 uint8_t id = bin_u8(&r); 1023 uint32_t size = bin_uleb(&r); 1024 size_t end; 1025 bin_need(&r, size); 1026 end = r.pos + size; 1027 if (id != 0 && id <= last_id) 1028 wasm_error(c, wasm_loc(0, 0), "wasm: sections out of order"); 1029 if (id != 0) last_id = id; 1030 if (id == 0) { 1031 uint32_t name_len = bin_uleb(&r); 1032 bin_need(&r, name_len); 1033 if (name_len == 7u && memcmp(r.data + r.pos, "linking", 7) == 0) 1034 wasm_error(c, wasm_loc(0, 0), 1035 "wasm: relocatable object metadata is not frontend input"); 1036 { 1037 WasmCustom* cs = wasm_add_custom(c, out); 1038 cs->name = 1039 wasm_strdup(out->heap, (const char*)(r.data + r.pos), name_len); 1040 if (!cs->name) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 1041 r.pos += name_len; 1042 if (kit_slice_eq_cstr(kit_slice_cstr(cs->name), "target_features") || 1043 kit_slice_eq_cstr(kit_slice_cstr(cs->name), "target-feature")) 1044 out->has_target_features = 1; 1045 cs->len = (uint32_t)(end - r.pos); 1046 if (cs->len) { 1047 cs->data = (uint8_t*)out->heap->alloc(out->heap, cs->len, 1); 1048 if (!cs->data) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 1049 memcpy(cs->data, r.data + r.pos, cs->len); 1050 } 1051 } 1052 r.pos = end; 1053 continue; 1054 } 1055 if (id == 1) { 1056 uint32_t i, count = bin_uleb(&r); 1057 for (i = 0; i < count; ++i) { 1058 WasmFuncType* t = wasm_add_type(c, out); 1059 uint32_t j, nparam, nresult; 1060 if (bin_u8(&r) != 0x60u) 1061 wasm_error(c, wasm_loc(0, 0), "wasm: expected function type"); 1062 nparam = bin_uleb(&r); 1063 for (j = 0; j < nparam; ++j) 1064 wasm_type_push_param(c, out, t, bin_val_type(&r, 1)); 1065 nresult = bin_uleb(&r); 1066 if (nresult > 1u) 1067 wasm_error(c, wasm_loc(0, 0), "wasm: multi-result unsupported"); 1068 t->nresults = nresult; 1069 for (j = 0; j < nresult; ++j) t->results[j] = bin_val_type(&r, 1); 1070 } 1071 } else if (id == 2) { 1072 uint32_t i, count = bin_uleb(&r); 1073 for (i = 0; i < count; ++i) { 1074 char* mod = bin_name(&r, NULL); 1075 char* name = bin_name(&r, NULL); 1076 uint8_t kind = bin_u8(&r); 1077 if (kind == 0) { 1078 uint32_t typeidx = bin_uleb(&r); 1079 WasmFunc* f; 1080 if (typeidx >= out->ntypes) 1081 wasm_error(c, wasm_loc(0, 0), "wasm: bad import type index"); 1082 f = wasm_add_func(c, out); 1083 f->is_import = 1; 1084 f->import_module = mod; 1085 f->import_name = name; 1086 f->typeidx = typeidx; 1087 f->has_typeidx = 1; 1088 wasm_func_set_params(c, out, f, out->types[typeidx].params, 1089 out->types[typeidx].nparams); 1090 f->nresults = out->types[typeidx].nresults; 1091 memcpy(f->results, out->types[typeidx].results, 1092 sizeof(f->results[0]) * f->nresults); 1093 } else if (kind == 1) { 1094 WasmTable* t = wasm_add_table(c, out); 1095 t->is_import = 1; 1096 t->import_module = mod; 1097 t->import_name = name; 1098 t->elem_type = bin_val_type(&r, 1); 1099 { 1100 uint32_t flags = bin_uleb(&r); 1101 if (flags & ~1u) 1102 wasm_error(c, wasm_loc(0, 0), "wasm: unsupported table limits"); 1103 t->has_max = (flags & 1u) != 0; 1104 t->min = bin_uleb(&r); 1105 if (t->has_max) t->max = bin_uleb(&r); 1106 } 1107 } else if (kind == 2) { 1108 uint32_t flags; 1109 WasmMemory* mem = wasm_add_memory(c, out); 1110 mem->is_import = 1; 1111 mem->import_module = mod; 1112 mem->import_name = name; 1113 flags = bin_uleb(&r); 1114 if (flags & ~7u) 1115 wasm_error(c, wasm_loc(0, 0), "wasm: unsupported memory limits"); 1116 mem->has_max = (flags & 1u) != 0; 1117 mem->shared = (flags & 2u) != 0; 1118 mem->is64 = (flags & 4u) != 0; 1119 mem->min_pages = mem->is64 ? bin_uleb64(&r) : bin_uleb(&r); 1120 if (mem->has_max) 1121 mem->max_pages = mem->is64 ? bin_uleb64(&r) : bin_uleb(&r); 1122 } else if (kind == 3) { 1123 WasmGlobal* g = wasm_add_global(c, out); 1124 g->is_import = 1; 1125 g->import_module = mod; 1126 g->import_name = name; 1127 g->type = bin_val_type(&r, 0); 1128 g->mutable_ = bin_u8(&r); 1129 if (g->mutable_ > 1u) 1130 wasm_error(c, wasm_loc(0, 0), "wasm: bad global mutability"); 1131 } else { 1132 wasm_error(c, wasm_loc(0, 0), "wasm: unsupported import kind"); 1133 } 1134 } 1135 } else if (id == 3) { 1136 uint32_t i, count = bin_uleb(&r); 1137 for (i = 0; i < count; ++i) { 1138 uint32_t typeidx = bin_uleb(&r); 1139 WasmFunc* f; 1140 if (typeidx >= out->ntypes) 1141 wasm_error(c, wasm_loc(0, 0), "wasm: bad function type index"); 1142 f = wasm_add_func(c, out); 1143 f->typeidx = typeidx; 1144 f->has_typeidx = 1; 1145 wasm_func_set_params(c, out, f, out->types[typeidx].params, 1146 out->types[typeidx].nparams); 1147 f->nresults = out->types[typeidx].nresults; 1148 memcpy(f->results, out->types[typeidx].results, 1149 sizeof(f->results[0]) * f->nresults); 1150 nfunc_types++; 1151 } 1152 } else if (id == 5) { 1153 uint32_t count = bin_uleb(&r); 1154 for (uint32_t mi = 0; mi < count; ++mi) { 1155 uint32_t flags = bin_uleb(&r); 1156 WasmMemory* mem = wasm_add_memory(c, out); 1157 if (flags & ~7u) 1158 wasm_error(c, wasm_loc(0, 0), "wasm: unsupported memory limits"); 1159 mem->has_max = (flags & 1u) != 0; 1160 mem->shared = (flags & 2u) != 0; 1161 mem->is64 = (flags & 4u) != 0; 1162 mem->min_pages = mem->is64 ? bin_uleb64(&r) : bin_uleb(&r); 1163 if (mem->has_max) 1164 mem->max_pages = mem->is64 ? bin_uleb64(&r) : bin_uleb(&r); 1165 } 1166 } else if (id == 4) { 1167 uint32_t i, count = bin_uleb(&r); 1168 for (i = 0; i < count; ++i) { 1169 WasmTable* t = wasm_add_table(c, out); 1170 uint32_t flags; 1171 t->elem_type = bin_val_type(&r, 1); 1172 flags = bin_uleb(&r); 1173 if (flags & ~1u) 1174 wasm_error(c, wasm_loc(0, 0), "wasm: unsupported table limits"); 1175 t->has_max = (flags & 1u) != 0; 1176 t->min = bin_uleb(&r); 1177 if (t->has_max) t->max = bin_uleb(&r); 1178 } 1179 } else if (id == 6) { 1180 uint32_t i, count = bin_uleb(&r); 1181 for (i = 0; i < count; ++i) { 1182 WasmGlobal* g = wasm_add_global(c, out); 1183 uint8_t op; 1184 g->type = bin_val_type(&r, 0); 1185 g->mutable_ = bin_u8(&r); 1186 if (g->mutable_ > 1u) 1187 wasm_error(c, wasm_loc(0, 0), "wasm: bad global mutability"); 1188 op = bin_u8(&r); 1189 switch (op) { 1190 case 0x41: 1191 g->init.kind = WASM_INSN_I32_CONST; 1192 g->init.imm = bin_sleb(&r, 32); 1193 break; 1194 case 0x42: 1195 g->init.kind = WASM_INSN_I64_CONST; 1196 g->init.imm = bin_sleb(&r, 64); 1197 break; 1198 case 0x43: 1199 g->init.kind = WASM_INSN_F32_CONST; 1200 g->init.fp = bin_f32(&r); 1201 break; 1202 case 0x44: 1203 g->init.kind = WASM_INSN_F64_CONST; 1204 g->init.fp = bin_f64(&r); 1205 break; 1206 default: 1207 wasm_error(c, wasm_loc(0, 0), 1208 "wasm: unsupported global initializer"); 1209 } 1210 if (bin_u8(&r) != 0x0bu) 1211 wasm_error(c, wasm_loc(0, 0), "wasm: malformed global initializer"); 1212 } 1213 } else if (id == 7) { 1214 uint32_t i, count = bin_uleb(&r); 1215 for (i = 0; i < count; ++i) { 1216 char* name; 1217 uint8_t kind; 1218 uint32_t idx; 1219 WasmExport* ex; 1220 name = bin_name(&r, NULL); 1221 kind = bin_u8(&r); 1222 idx = bin_uleb(&r); 1223 if (kind > 3u) wasm_error(c, wasm_loc(0, 0), "wasm: bad export kind"); 1224 ex = wasm_add_export(c, out); 1225 ex->name = name; 1226 ex->kind = kind; 1227 ex->index = idx; 1228 if (kind == 0 && idx < out->nfuncs) { 1229 out->funcs[idx].export_name = 1230 wasm_strdup(out->heap, name, kit_slice_cstr(name).len); 1231 } else if (kind == 1 && idx < out->ntables) { 1232 out->tables[idx].export_name = 1233 wasm_strdup(out->heap, name, kit_slice_cstr(name).len); 1234 } else if (kind == 2 && idx < out->nmemories) { 1235 out->memories[idx].export_name = 1236 wasm_strdup(out->heap, name, kit_slice_cstr(name).len); 1237 } else if (kind == 3 && idx < out->nglobals) { 1238 out->globals[idx].export_name = 1239 wasm_strdup(out->heap, name, kit_slice_cstr(name).len); 1240 } 1241 } 1242 } else if (id == 8) { 1243 out->has_start = 1; 1244 out->start_func = bin_uleb(&r); 1245 } else if (id == 9) { 1246 uint32_t i, count = bin_uleb(&r); 1247 for (i = 0; i < count; ++i) { 1248 WasmElemSegment* e = wasm_add_elem(c, out); 1249 uint32_t flags = bin_uleb(&r); 1250 uint32_t n; 1251 e->elem_type = WASM_VAL_FUNCREF; 1252 if (flags == 0u) { 1253 e->mode = WASM_SEG_ACTIVE; 1254 e->tableidx = 0; 1255 if (bin_u8(&r) != 0x41) 1256 wasm_error(c, wasm_loc(0, 0), 1257 "wasm: expected i32.const element offset"); 1258 e->offset = bin_sleb(&r, 32); 1259 if (bin_u8(&r) != 0x0b || e->offset < 0) 1260 wasm_error(c, wasm_loc(0, 0), "wasm: bad element offset"); 1261 } else if (flags == 1u) { 1262 e->mode = WASM_SEG_PASSIVE; 1263 if (bin_u8(&r) != 0x00) 1264 wasm_error(c, wasm_loc(0, 0), 1265 "wasm: unsupported passive element kind"); 1266 } else if (flags == 2u) { 1267 e->mode = WASM_SEG_ACTIVE; 1268 e->tableidx = bin_uleb(&r); 1269 if (bin_u8(&r) != 0x41) 1270 wasm_error(c, wasm_loc(0, 0), 1271 "wasm: expected i32.const element offset"); 1272 e->offset = bin_sleb(&r, 32); 1273 if (bin_u8(&r) != 0x0b || e->offset < 0) 1274 wasm_error(c, wasm_loc(0, 0), "wasm: bad element offset"); 1275 if (bin_u8(&r) != 0x00) 1276 wasm_error(c, wasm_loc(0, 0), "wasm: unsupported element kind"); 1277 } else if (flags == 3u) { 1278 e->mode = WASM_SEG_DECLARATIVE; 1279 if (bin_u8(&r) != 0x00) 1280 wasm_error(c, wasm_loc(0, 0), 1281 "wasm: unsupported declarative element kind"); 1282 } else { 1283 wasm_error(c, wasm_loc(0, 0), 1284 "wasm: unsupported element segment flags 0x%x", flags); 1285 } 1286 n = bin_uleb(&r); 1287 for (uint32_t k = 0; k < n; ++k) 1288 wasm_elem_push_func(c, out, e, bin_uleb(&r)); 1289 } 1290 } else if (id == 10) { 1291 uint32_t i, count = bin_uleb(&r); 1292 uint32_t func_index = 0; 1293 if (count != nfunc_types) 1294 wasm_error(c, wasm_loc(0, 0), "wasm: function/code count mismatch"); 1295 for (i = 0; i < count; ++i) { 1296 uint32_t body_size = bin_uleb(&r); 1297 size_t body_end; 1298 uint32_t local_groups, j; 1299 uint32_t control_depth = 0; 1300 int saw_body_end = 0; 1301 WasmFunc* f; 1302 while (func_index < out->nfuncs && out->funcs[func_index].is_import) 1303 func_index++; 1304 if (func_index >= out->nfuncs) 1305 wasm_error(c, wasm_loc(0, 0), "wasm: code body without function"); 1306 f = &out->funcs[func_index++]; 1307 bin_need(&r, body_size); 1308 body_end = r.pos + body_size; 1309 local_groups = bin_uleb(&r); 1310 for (j = 0; j < local_groups; ++j) { 1311 uint32_t k, nlocals = bin_uleb(&r); 1312 WasmValType vt = bin_val_type(&r, 1); 1313 for (k = 0; k < nlocals; ++k) wasm_func_push_local(c, out, f, vt); 1314 } 1315 while (r.pos < body_end) { 1316 uint8_t op = bin_u8(&r); 1317 if (op == 0x0bu) { 1318 if (!control_depth) { 1319 saw_body_end = 1; 1320 break; 1321 } 1322 control_depth--; 1323 wasm_func_add_insn(c, out, f, WASM_INSN_END, 0); 1324 continue; 1325 } 1326 decode_body_insn(&r, out, f, op, &control_depth); 1327 } 1328 if (!saw_body_end) 1329 wasm_error(c, wasm_loc(0, 0), "wasm: function body missing end"); 1330 r.pos = body_end; 1331 } 1332 } else if (id == 11) { 1333 uint32_t i, count = bin_uleb(&r); 1334 for (i = 0; i < count; ++i) { 1335 WasmDataSegment* d = wasm_add_data(c, out); 1336 uint32_t flags = bin_uleb(&r); 1337 uint32_t n; 1338 if (flags == 0u) { 1339 d->mode = WASM_SEG_ACTIVE; 1340 d->memidx = 0; 1341 { 1342 uint8_t op = bin_u8(&r); 1343 if (op == 0x41) 1344 d->offset = bin_sleb(&r, 32); 1345 else if (op == 0x42) 1346 d->offset = bin_sleb(&r, 64); 1347 else 1348 wasm_error(c, wasm_loc(0, 0), "wasm: expected const data offset"); 1349 } 1350 if (bin_u8(&r) != 0x0b || d->offset < 0) 1351 wasm_error(c, wasm_loc(0, 0), "wasm: bad data offset"); 1352 } else if (flags == 1u) { 1353 d->mode = WASM_SEG_PASSIVE; 1354 } else if (flags == 2u) { 1355 d->mode = WASM_SEG_ACTIVE; 1356 d->memidx = bin_uleb(&r); 1357 { 1358 uint8_t op = bin_u8(&r); 1359 if (op == 0x41) 1360 d->offset = bin_sleb(&r, 32); 1361 else if (op == 0x42) 1362 d->offset = bin_sleb(&r, 64); 1363 else 1364 wasm_error(c, wasm_loc(0, 0), "wasm: expected const data offset"); 1365 } 1366 if (bin_u8(&r) != 0x0b || d->offset < 0) 1367 wasm_error(c, wasm_loc(0, 0), "wasm: bad data offset"); 1368 } else { 1369 wasm_error(c, wasm_loc(0, 0), 1370 "wasm: unsupported data segment flags 0x%x", flags); 1371 } 1372 n = bin_uleb(&r); 1373 bin_need(&r, n); 1374 wasm_data_set_bytes(c, out, d, r.data + r.pos, (uint64_t)n); 1375 r.pos += n; 1376 } 1377 } else if (id == 12) { 1378 /* Data count section. Conservatively accept and discard; bulk-memory 1379 * validation only needs it for forward-references during streaming 1380 * validation, which we don't do here. */ 1381 (void)bin_uleb(&r); 1382 } else { 1383 r.pos = end; 1384 } 1385 if (r.pos != end) 1386 wasm_error(c, wasm_loc(0, 0), "wasm: malformed section length"); 1387 } 1388 } 1389 1390 int wasm_is_binary(const KitSlice* input) { 1391 return input->len >= 4u && input->data[0] == 0x00 && input->data[1] == 0x61 && 1392 input->data[2] == 0x73 && input->data[3] == 0x6d; 1393 } 1394 1395 /* Decode exactly one instruction at data[pos..] into *out, returning the number 1396 * of bytes consumed (0 if none). The control-flow opcodes block/loop/if/end are 1397 * returned as plain instructions; callers that care about nesting track depth 1398 * themselves. `scratch` is a caller-owned reusable module (init via 1399 * wasm_module_init); its first function is reused as a decode buffer so this is 1400 * allocation-free after the first call. Malformed input is fatal, matching 1401 * wasm_decode_binary. */ 1402 size_t wasm_decode_one_insn(KitCompiler* c, WasmModule* scratch, 1403 const uint8_t* data, size_t len, size_t pos, 1404 WasmInsn* out) { 1405 BinReader r; 1406 WasmFunc* f; 1407 uint8_t op; 1408 uint32_t control_depth = 0; 1409 if (pos >= len) return 0; 1410 if (scratch->nfuncs == 0) (void)wasm_add_func(c, scratch); 1411 f = &scratch->funcs[0]; 1412 f->ninsns = 0; 1413 memset(&r, 0, sizeof r); 1414 r.c = c; 1415 r.data = data; 1416 r.len = len; 1417 r.pos = pos; 1418 r.module = scratch; 1419 op = bin_u8(&r); 1420 if (op == 0x0bu) { 1421 memset(out, 0, sizeof *out); 1422 out->kind = WASM_INSN_END; 1423 return r.pos - pos; 1424 } 1425 decode_body_insn(&r, scratch, f, op, &control_depth); 1426 if (f->ninsns == 0) return 0; 1427 *out = f->insns[f->ninsns - 1u]; 1428 return r.pos - pos; 1429 }