wasm.h (22255B)
1 #ifndef KIT_WASM_WASM_H 2 #define KIT_WASM_WASM_H 3 4 /* Shared Wasm binary/core: in-memory module model, binary decoder, WAT 5 * parser, validator, encoder, and small instruction-kind helpers. This 6 * header is the boundary between the format mechanics (decode/encode/ 7 * validate, all in src/wasm/) and the consumers that lower those modules 8 * into something else (lang/wasm/cg.c lowers to native CG; src/arch/wasm/ 9 * builds modules from the CG backend; src/obj/wasm_emit.c flushes them). 10 * 11 * Types here use the public KitCompiler / KitHeap / KitWriter 12 * aliases on purpose: this layer is callable from every Wasm caller in 13 * the tree without depending on libkit internals beyond the public 14 * frontend/CG headers. */ 15 16 #include <kit/cg.h> 17 #include <kit/compile.h> 18 #include <kit/core.h> 19 #include <kit/frontend.h> 20 #include <stdarg.h> 21 #include <stddef.h> 22 #include <stdint.h> 23 #include <stdlib.h> 24 #include <string.h> 25 26 typedef enum WasmValType { 27 WASM_VAL_I32 = 0x7f, 28 WASM_VAL_I64 = 0x7e, 29 WASM_VAL_F32 = 0x7d, 30 WASM_VAL_F64 = 0x7c, 31 WASM_VAL_FUNCREF = 0x70, 32 WASM_VAL_EXTERNREF = 0x6f, 33 } WasmValType; 34 35 typedef enum WasmFeatureSet { 36 WASM_FEATURE_THREADS = 1u << 0, 37 WASM_FEATURE_TYPED_FUNC_REFS = 1u << 1, 38 WASM_FEATURE_TAIL_CALLS = 1u << 2, 39 WASM_FEATURE_MULTI_MEMORY = 1u << 3, 40 WASM_FEATURE_MEMORY64 = 1u << 4, 41 WASM_FEATURE_BULK_MEMORY = 1u << 5, 42 WASM_FEATURE_NONTRAPPING_FTOI = 1u << 6, 43 } WasmFeatureSet; 44 45 typedef enum WasmInsnKind { 46 WASM_INSN_UNREACHABLE, 47 WASM_INSN_NOP, 48 WASM_INSN_BLOCK, 49 WASM_INSN_LOOP, 50 WASM_INSN_IF, 51 WASM_INSN_ELSE, 52 WASM_INSN_END, 53 WASM_INSN_BR, 54 WASM_INSN_BR_IF, 55 WASM_INSN_BR_TABLE, 56 WASM_INSN_SELECT, 57 WASM_INSN_F32_CONST, 58 WASM_INSN_F64_CONST, 59 WASM_INSN_I32_CONST, 60 WASM_INSN_I64_CONST, 61 WASM_INSN_LOCAL_GET, 62 WASM_INSN_LOCAL_SET, 63 WASM_INSN_LOCAL_TEE, 64 WASM_INSN_CALL, 65 WASM_INSN_CALL_INDIRECT, 66 WASM_INSN_RETURN_CALL, 67 WASM_INSN_RETURN_CALL_INDIRECT, 68 WASM_INSN_REF_NULL, 69 WASM_INSN_REF_FUNC, 70 WASM_INSN_REF_IS_NULL, 71 WASM_INSN_CALL_REF, 72 WASM_INSN_RETURN_CALL_REF, 73 WASM_INSN_GLOBAL_GET, 74 WASM_INSN_GLOBAL_SET, 75 WASM_INSN_RETURN, 76 WASM_INSN_DROP, 77 WASM_INSN_I32_LOAD, 78 WASM_INSN_I64_LOAD, 79 WASM_INSN_F32_LOAD, 80 WASM_INSN_F64_LOAD, 81 WASM_INSN_I32_LOAD8_S, 82 WASM_INSN_I32_LOAD8_U, 83 WASM_INSN_I32_LOAD16_S, 84 WASM_INSN_I32_LOAD16_U, 85 WASM_INSN_I64_LOAD8_S, 86 WASM_INSN_I64_LOAD8_U, 87 WASM_INSN_I64_LOAD16_S, 88 WASM_INSN_I64_LOAD16_U, 89 WASM_INSN_I64_LOAD32_S, 90 WASM_INSN_I64_LOAD32_U, 91 WASM_INSN_I32_STORE, 92 WASM_INSN_I64_STORE, 93 WASM_INSN_F32_STORE, 94 WASM_INSN_F64_STORE, 95 WASM_INSN_I32_STORE8, 96 WASM_INSN_I32_STORE16, 97 WASM_INSN_I64_STORE8, 98 WASM_INSN_I64_STORE16, 99 WASM_INSN_I64_STORE32, 100 WASM_INSN_MEMORY_SIZE, 101 WASM_INSN_MEMORY_GROW, 102 WASM_INSN_ATOMIC_FENCE, 103 WASM_INSN_I32_ATOMIC_LOAD, 104 WASM_INSN_I64_ATOMIC_LOAD, 105 WASM_INSN_I32_ATOMIC_LOAD8_U, 106 WASM_INSN_I32_ATOMIC_LOAD16_U, 107 WASM_INSN_I64_ATOMIC_LOAD8_U, 108 WASM_INSN_I64_ATOMIC_LOAD16_U, 109 WASM_INSN_I64_ATOMIC_LOAD32_U, 110 WASM_INSN_I32_ATOMIC_STORE, 111 WASM_INSN_I64_ATOMIC_STORE, 112 WASM_INSN_I32_ATOMIC_STORE8, 113 WASM_INSN_I32_ATOMIC_STORE16, 114 WASM_INSN_I64_ATOMIC_STORE8, 115 WASM_INSN_I64_ATOMIC_STORE16, 116 WASM_INSN_I64_ATOMIC_STORE32, 117 WASM_INSN_I32_ATOMIC_RMW_ADD, 118 WASM_INSN_I64_ATOMIC_RMW_ADD, 119 WASM_INSN_I32_ATOMIC_RMW_SUB, 120 WASM_INSN_I64_ATOMIC_RMW_SUB, 121 WASM_INSN_I32_ATOMIC_RMW_AND, 122 WASM_INSN_I64_ATOMIC_RMW_AND, 123 WASM_INSN_I32_ATOMIC_RMW_OR, 124 WASM_INSN_I64_ATOMIC_RMW_OR, 125 WASM_INSN_I32_ATOMIC_RMW_XOR, 126 WASM_INSN_I64_ATOMIC_RMW_XOR, 127 WASM_INSN_I32_ATOMIC_RMW_XCHG, 128 WASM_INSN_I64_ATOMIC_RMW_XCHG, 129 WASM_INSN_I32_ATOMIC_RMW_CMPXCHG, 130 WASM_INSN_I64_ATOMIC_RMW_CMPXCHG, 131 WASM_INSN_I32_ATOMIC_WAIT, 132 WASM_INSN_I64_ATOMIC_WAIT, 133 WASM_INSN_MEMORY_ATOMIC_NOTIFY, 134 WASM_INSN_I32_ADD, 135 WASM_INSN_I32_SUB, 136 WASM_INSN_I32_MUL, 137 WASM_INSN_I32_DIV_S, 138 WASM_INSN_I32_DIV_U, 139 WASM_INSN_I32_REM_S, 140 WASM_INSN_I32_REM_U, 141 WASM_INSN_I32_AND, 142 WASM_INSN_I32_OR, 143 WASM_INSN_I32_XOR, 144 WASM_INSN_I32_SHL, 145 WASM_INSN_I32_SHR_S, 146 WASM_INSN_I32_SHR_U, 147 WASM_INSN_I32_ROTL, 148 WASM_INSN_I32_ROTR, 149 WASM_INSN_I32_CLZ, 150 WASM_INSN_I32_CTZ, 151 WASM_INSN_I32_POPCNT, 152 WASM_INSN_I32_EQZ, 153 WASM_INSN_I32_EQ, 154 WASM_INSN_I32_NE, 155 WASM_INSN_I32_LT_S, 156 WASM_INSN_I32_LT_U, 157 WASM_INSN_I32_GT_S, 158 WASM_INSN_I32_GT_U, 159 WASM_INSN_I32_LE_S, 160 WASM_INSN_I32_LE_U, 161 WASM_INSN_I32_GE_S, 162 WASM_INSN_I32_GE_U, 163 WASM_INSN_I64_ADD, 164 WASM_INSN_I64_SUB, 165 WASM_INSN_I64_MUL, 166 WASM_INSN_I64_DIV_S, 167 WASM_INSN_I64_DIV_U, 168 WASM_INSN_I64_REM_S, 169 WASM_INSN_I64_REM_U, 170 WASM_INSN_I64_AND, 171 WASM_INSN_I64_OR, 172 WASM_INSN_I64_XOR, 173 WASM_INSN_I64_SHL, 174 WASM_INSN_I64_SHR_S, 175 WASM_INSN_I64_SHR_U, 176 WASM_INSN_I64_ROTL, 177 WASM_INSN_I64_ROTR, 178 WASM_INSN_I64_CLZ, 179 WASM_INSN_I64_CTZ, 180 WASM_INSN_I64_POPCNT, 181 WASM_INSN_I64_EQZ, 182 WASM_INSN_I64_EQ, 183 WASM_INSN_I64_NE, 184 WASM_INSN_I64_LT_S, 185 WASM_INSN_I64_LT_U, 186 WASM_INSN_I64_GT_S, 187 WASM_INSN_I64_GT_U, 188 WASM_INSN_I64_LE_S, 189 WASM_INSN_I64_LE_U, 190 WASM_INSN_I64_GE_S, 191 WASM_INSN_I64_GE_U, 192 WASM_INSN_F32_ADD, 193 WASM_INSN_F32_SUB, 194 WASM_INSN_F32_MUL, 195 WASM_INSN_F32_DIV, 196 WASM_INSN_F32_EQ, 197 WASM_INSN_F32_NE, 198 WASM_INSN_F32_LT, 199 WASM_INSN_F32_GT, 200 WASM_INSN_F32_LE, 201 WASM_INSN_F32_GE, 202 WASM_INSN_F64_ADD, 203 WASM_INSN_F64_SUB, 204 WASM_INSN_F64_MUL, 205 WASM_INSN_F64_DIV, 206 WASM_INSN_F64_EQ, 207 WASM_INSN_F64_NE, 208 WASM_INSN_F64_LT, 209 WASM_INSN_F64_GT, 210 WASM_INSN_F64_LE, 211 WASM_INSN_F64_GE, 212 WASM_INSN_F32_NEG, 213 WASM_INSN_F64_NEG, 214 WASM_INSN_I32_WRAP_I64, 215 WASM_INSN_I32_TRUNC_F32_S, 216 WASM_INSN_I32_TRUNC_F32_U, 217 WASM_INSN_I32_TRUNC_F64_S, 218 WASM_INSN_I32_TRUNC_F64_U, 219 WASM_INSN_I64_EXTEND_I32_S, 220 WASM_INSN_I64_EXTEND_I32_U, 221 WASM_INSN_I64_TRUNC_F32_S, 222 WASM_INSN_I64_TRUNC_F32_U, 223 WASM_INSN_I64_TRUNC_F64_S, 224 WASM_INSN_I64_TRUNC_F64_U, 225 WASM_INSN_F32_CONVERT_I32_S, 226 WASM_INSN_F32_CONVERT_I32_U, 227 WASM_INSN_F32_CONVERT_I64_S, 228 WASM_INSN_F32_CONVERT_I64_U, 229 WASM_INSN_F32_DEMOTE_F64, 230 WASM_INSN_F64_CONVERT_I32_S, 231 WASM_INSN_F64_CONVERT_I32_U, 232 WASM_INSN_F64_CONVERT_I64_S, 233 WASM_INSN_F64_CONVERT_I64_U, 234 WASM_INSN_F64_PROMOTE_F32, 235 WASM_INSN_I32_REINTERPRET_F32, 236 WASM_INSN_I64_REINTERPRET_F64, 237 WASM_INSN_F32_REINTERPRET_I32, 238 WASM_INSN_F64_REINTERPRET_I64, 239 /* Sign-extension operators (0xc0..0xc4). In-register sign extension from a 240 * narrower width; part of the standard MVP-era instruction set. */ 241 WASM_INSN_I32_EXTEND8_S, 242 WASM_INSN_I32_EXTEND16_S, 243 WASM_INSN_I64_EXTEND8_S, 244 WASM_INSN_I64_EXTEND16_S, 245 WASM_INSN_I64_EXTEND32_S, 246 /* Non-trapping float-to-int truncation (0xfc 0x00..0x07). 247 * Gated by WASM_FEATURE_NONTRAPPING_FTOI. */ 248 WASM_INSN_I32_TRUNC_SAT_F32_S, 249 WASM_INSN_I32_TRUNC_SAT_F32_U, 250 WASM_INSN_I32_TRUNC_SAT_F64_S, 251 WASM_INSN_I32_TRUNC_SAT_F64_U, 252 WASM_INSN_I64_TRUNC_SAT_F32_S, 253 WASM_INSN_I64_TRUNC_SAT_F32_U, 254 WASM_INSN_I64_TRUNC_SAT_F64_S, 255 WASM_INSN_I64_TRUNC_SAT_F64_U, 256 /* Bulk memory ops (0xfc 0x08..0x11). Gated by WASM_FEATURE_BULK_MEMORY. 257 * Immediate slots: 258 * memory.init: imm = dataidx, memidx = memidx 259 * data.drop: imm = dataidx 260 * memory.copy: memidx = dst memidx, aux_idx = src memidx 261 * memory.fill: memidx = memidx 262 * table.init: imm = elemidx, aux_idx = tableidx 263 * elem.drop: imm = elemidx 264 * table.copy: aux_idx = src tableidx, imm = dst tableidx 265 * table.grow: imm = tableidx 266 * table.size: imm = tableidx 267 * table.fill: imm = tableidx 268 */ 269 WASM_INSN_MEMORY_INIT, 270 WASM_INSN_DATA_DROP, 271 WASM_INSN_MEMORY_COPY, 272 WASM_INSN_MEMORY_FILL, 273 WASM_INSN_TABLE_INIT, 274 WASM_INSN_ELEM_DROP, 275 WASM_INSN_TABLE_COPY, 276 WASM_INSN_TABLE_GROW, 277 WASM_INSN_TABLE_SIZE, 278 WASM_INSN_TABLE_FILL, 279 } WasmInsnKind; 280 281 /* Blocktype sentinel stored in WasmInsn.type for a block/loop/if whose 282 * signature is a function-type index (multi-value: block params and/or >1 283 * result). 0 == void, a valtype byte (0x6f..0x7f) == the single-result 284 * shorthand, and this value (0x01, outside the valtype range and != 0) == "the 285 * blocktype is the typeidx held in WasmInsn.imm". See wasm_insn_blocktype_*. */ 286 #define WASM_BLOCKTYPE_TYPEIDX 0x01u 287 288 typedef struct WasmInsn { 289 KitSrcLoc loc; 290 uint8_t kind; 291 uint8_t type; 292 int64_t imm; 293 double fp; 294 uint32_t align; 295 uint32_t memidx; 296 uint64_t offset64; 297 /* Secondary index slot for opcodes with two index immediates: memory.copy 298 * (src memidx), table.init (tableidx), table.copy (src tableidx). */ 299 uint32_t aux_idx; 300 /* br_table branch depths: targets[0..ntargets-1], the last being the 301 * default. Heap-owned (m->heap), sized exactly ntargets, freed with the 302 * function. A pointer rather than an inline array so a switch's jump table 303 * can hold an arbitrary number of cases without bloating every other 304 * instruction. Set via wasm_insn_set_targets. */ 305 uint32_t ntargets; 306 uint32_t* targets; 307 } WasmInsn; 308 309 /* Blocktype accessors for block/loop/if. A typeidx blocktype keeps its 310 * function-type index in `imm` and flags it with the WASM_BLOCKTYPE_TYPEIDX 311 * sentinel in `type`; the shorthand forms keep their valtype (or 0 for void) 312 * directly in `type`. No dedicated struct field — this keeps every instruction 313 * the same small size (mirroring the br_table targets pointer trick). */ 314 static inline int wasm_insn_blocktype_is_typeidx(const WasmInsn* in) { 315 return in->type == WASM_BLOCKTYPE_TYPEIDX; 316 } 317 static inline void wasm_insn_set_blocktype_typeidx(WasmInsn* in, 318 uint32_t typeidx) { 319 in->type = (uint8_t)WASM_BLOCKTYPE_TYPEIDX; 320 in->imm = (int64_t)typeidx; 321 } 322 static inline uint32_t wasm_insn_blocktype_typeidx(const WasmInsn* in) { 323 return (uint32_t)in->imm; 324 } 325 326 typedef struct WasmFunc { 327 KitSrcLoc loc; 328 char* name; 329 uint32_t typeidx; 330 int has_typeidx; 331 int is_import; 332 char* import_module; 333 char* import_name; 334 /* params/locals/local_names are heap-grown — no fixed limit. params holds 335 * one WasmValType per function parameter (size = nparams, capacity = 336 * cap_params); locals holds one WasmValType per declared local (size = 337 * nlocals, capacity = cap_locals); local_names is a sparse array indexed by 338 * wasm-local index (0..nparams+nlocals-1) and capacity-tracked separately. */ 339 WasmValType* params; 340 uint32_t nparams; 341 uint32_t cap_params; 342 WasmValType* locals; 343 uint32_t nlocals; 344 uint32_t cap_locals; 345 char** local_names; 346 uint32_t cap_local_names; 347 /* results mirrors params: a heap-grown vector (size = nresults, capacity = 348 * cap_results). Multi-value blocks reference multi-result function types, so 349 * the type section — and therefore func/import signatures — can carry more 350 * than one result. */ 351 WasmValType* results; 352 uint32_t nresults; 353 uint32_t cap_results; 354 char* export_name; 355 WasmInsn* insns; 356 uint32_t ninsns; 357 uint32_t cap_insns; 358 } WasmFunc; 359 360 typedef struct WasmFuncType { 361 char* name; 362 WasmValType* params; 363 uint32_t nparams; 364 uint32_t cap_params; 365 WasmValType* results; 366 uint32_t nresults; 367 uint32_t cap_results; 368 } WasmFuncType; 369 370 typedef struct WasmMemory { 371 char* name; 372 uint64_t min_pages; 373 uint64_t max_pages; 374 int has_max; 375 int is64; 376 int shared; 377 int is_import; 378 char* import_module; 379 char* import_name; 380 char* export_name; 381 } WasmMemory; 382 383 typedef enum WasmSegmentMode { 384 WASM_SEG_ACTIVE = 0, 385 WASM_SEG_PASSIVE = 1, 386 WASM_SEG_DECLARATIVE = 2, /* element segments only */ 387 } WasmSegmentMode; 388 389 /* A data segment carries an immutable byte buffer plus its placement mode. 390 * Active segments are copied into memory `memidx` at constant offset `offset` 391 * at module instantiation. Passive segments are sources for `memory.init` and 392 * are otherwise inert until `data.drop` permanently zero-lengths them. */ 393 typedef struct WasmDataSegment { 394 uint8_t mode; /* WasmSegmentMode */ 395 uint32_t memidx; /* meaningful when mode == WASM_SEG_ACTIVE */ 396 int64_t offset; /* active offset; signed to allow caller-relative builds */ 397 char* name; /* optional WAT `$name`, NULL otherwise */ 398 uint8_t* bytes; 399 uint64_t nbytes; 400 } WasmDataSegment; 401 402 typedef struct WasmTable { 403 char* name; 404 WasmValType elem_type; 405 uint32_t min; 406 uint32_t max; 407 int has_max; 408 int is_import; 409 char* import_module; 410 char* import_name; 411 char* export_name; 412 } WasmTable; 413 414 typedef struct WasmGlobal { 415 KitSrcLoc loc; 416 char* name; 417 WasmValType type; 418 uint8_t mutable_; 419 WasmInsn init; 420 int is_import; 421 char* import_module; 422 char* import_name; 423 char* export_name; 424 } WasmGlobal; 425 426 typedef struct WasmElemSegment { 427 uint8_t mode; /* WasmSegmentMode */ 428 WasmValType elem_type; /* funcref/externref/typed-funcref */ 429 uint32_t tableidx; /* meaningful when mode == WASM_SEG_ACTIVE */ 430 int64_t offset; /* active offset */ 431 char* name; /* optional WAT `$name`, NULL otherwise */ 432 uint32_t* funcs; /* heap-grown; each slot is a function index */ 433 uint32_t nfuncs; 434 uint32_t cap_funcs; 435 } WasmElemSegment; 436 437 typedef struct WasmExport { 438 char* name; 439 uint8_t kind; 440 uint32_t index; 441 } WasmExport; 442 443 typedef struct WasmCustom { 444 char* name; 445 uint8_t* data; 446 uint32_t len; 447 } WasmCustom; 448 449 typedef struct WasmModule { 450 KitHeap* heap; 451 uint32_t file_id; 452 KitSrcLoc current_loc; 453 KitSrcLoc start_field_loc; 454 WasmFuncType* types; 455 uint32_t ntypes; 456 uint32_t cap_types; 457 WasmFunc* funcs; 458 uint32_t nfuncs; 459 uint32_t cap_funcs; 460 WasmMemory* memories; 461 uint32_t nmemories; 462 uint32_t cap_memories; 463 WasmTable* tables; 464 uint32_t ntables; 465 uint32_t cap_tables; 466 WasmGlobal* globals; 467 uint32_t nglobals; 468 uint32_t cap_globals; 469 WasmElemSegment* elems; 470 uint32_t nelems; 471 uint32_t cap_elems; 472 WasmDataSegment* data; 473 uint32_t ndata; 474 uint32_t cap_data; 475 WasmExport* exports; 476 uint32_t nexports; 477 uint32_t cap_exports; 478 WasmCustom* customs; 479 uint32_t ncustoms; 480 uint32_t cap_customs; 481 uint32_t start_func; 482 int has_start; 483 int has_target_features; 484 uint32_t features; 485 } WasmModule; 486 487 KitSrcLoc wasm_loc(uint32_t line, uint32_t col); 488 void wasm_error(KitCompiler* c, KitSrcLoc loc, const char* fmt, ...); 489 void* wasm_realloc(KitHeap* h, void* p, size_t old_n, size_t new_n); 490 char* wasm_strdup(KitHeap* h, const char* s, size_t len); 491 void wasm_free_str(KitHeap* h, char** s); 492 493 void wasm_module_init(WasmModule* m, KitHeap* heap); 494 void wasm_module_free(WasmModule* m); 495 WasmMemory* wasm_add_memory(KitCompiler* c, WasmModule* m); 496 WasmFunc* wasm_add_func(KitCompiler* c, WasmModule* m); 497 WasmFuncType* wasm_add_type(KitCompiler* c, WasmModule* m); 498 uint32_t wasm_intern_func_type(KitCompiler* c, WasmModule* m, 499 const WasmFunc* f); 500 WasmTable* wasm_add_table(KitCompiler* c, WasmModule* m); 501 WasmGlobal* wasm_add_global(KitCompiler* c, WasmModule* m); 502 WasmElemSegment* wasm_add_elem(KitCompiler* c, WasmModule* m); 503 WasmDataSegment* wasm_add_data(KitCompiler* c, WasmModule* m); 504 /* Append a function index to an element segment, growing as needed. */ 505 void wasm_elem_push_func(KitCompiler* c, WasmModule* m, WasmElemSegment* e, 506 uint32_t funcidx); 507 /* Set/append a data segment's byte buffer. Copies `n` bytes from `src`. */ 508 void wasm_data_set_bytes(KitCompiler* c, WasmModule* m, WasmDataSegment* d, 509 const uint8_t* src, uint64_t n); 510 WasmExport* wasm_add_export(KitCompiler* c, WasmModule* m); 511 WasmCustom* wasm_add_custom(KitCompiler* c, WasmModule* m); 512 /* Push a single parameter type onto a WasmFunc's signature, growing the 513 * underlying array as needed. Returns the new parameter's wasm-local index. */ 514 uint32_t wasm_func_push_param(KitCompiler* c, WasmModule* m, WasmFunc* f, 515 WasmValType vt); 516 /* Push a single declared local onto a WasmFunc. Returns the new local's 517 * wasm-local index (i.e., nparams + (nlocals-1) after the push). */ 518 uint32_t wasm_func_push_local(KitCompiler* c, WasmModule* m, WasmFunc* f, 519 WasmValType vt); 520 /* Bulk-set the params array from a source buffer. Reuses existing capacity 521 * when possible; otherwise grows. */ 522 void wasm_func_set_params(KitCompiler* c, WasmModule* m, WasmFunc* f, 523 const WasmValType* src, uint32_t n); 524 /* Push a single result type onto a WasmFunc's signature, growing as needed. 525 * Returns the new result's index. */ 526 uint32_t wasm_func_push_result(KitCompiler* c, WasmModule* m, WasmFunc* f, 527 WasmValType vt); 528 /* Bulk-set the results array from a source buffer. Reuses existing capacity 529 * when possible; otherwise grows. */ 530 void wasm_func_set_results(KitCompiler* c, WasmModule* m, WasmFunc* f, 531 const WasmValType* src, uint32_t n); 532 /* Assign a name to wasm-local index `idx`, growing local_names as needed. 533 * `idx` may be any value < nparams + nlocals (or any future index the caller 534 * intends to fill before encoding). */ 535 void wasm_func_set_local_name(KitCompiler* c, WasmModule* m, WasmFunc* f, 536 uint32_t idx, const char* name, size_t len); 537 /* Push a single parameter type onto a WasmFuncType, growing as needed. */ 538 uint32_t wasm_type_push_param(KitCompiler* c, WasmModule* m, WasmFuncType* t, 539 WasmValType vt); 540 /* Push a single result type onto a WasmFuncType, growing as needed. */ 541 uint32_t wasm_type_push_result(KitCompiler* c, WasmModule* m, WasmFuncType* t, 542 WasmValType vt); 543 544 void wasm_func_add_insn(KitCompiler* c, WasmModule* m, WasmFunc* f, 545 WasmInsnKind kind, int64_t imm); 546 void wasm_func_add_mem_insn(KitCompiler* c, WasmModule* m, WasmFunc* f, 547 WasmInsnKind kind, uint32_t align, uint64_t offset, 548 uint32_t memidx); 549 void wasm_func_add_fp_insn(KitCompiler* c, WasmModule* m, WasmFunc* f, 550 WasmInsnKind kind, double value); 551 /* Replace `in`'s br_table target vector with a heap-owned copy of 552 * `targets[0..ntargets)` (allocated from m->heap, freed with the function). 553 * Any previous vector is released first. */ 554 void wasm_insn_set_targets(KitCompiler* c, WasmModule* m, WasmInsn* in, 555 const uint32_t* targets, uint32_t ntargets); 556 557 /* The resolved param/result signature of a block/loop/if instruction. For the 558 * shorthand forms the vectors point into a caller-provided scratch buffer; for 559 * the typeidx form they point into m->types[idx]. Lifetime follows whichever 560 * backs them (the scratch or the module). */ 561 typedef struct WasmBlockSig { 562 const WasmValType* params; 563 uint32_t nparams; 564 const WasmValType* results; 565 uint32_t nresults; 566 } WasmBlockSig; 567 /* Resolve a block/loop/if instruction's blocktype into *out. `result_scratch` 568 * is a caller-owned single-WasmValType buffer used to hold the shorthand result 569 * type (so it need not outlive the call beyond *out's use). */ 570 void wasm_block_sig(const WasmModule* m, const WasmInsn* in, 571 WasmValType* result_scratch, WasmBlockSig* out); 572 573 int wasm_is_num_type(WasmValType vt); 574 int wasm_is_ref_type(WasmValType vt); 575 int wasm_is_frontend_value_type(WasmValType vt); 576 int wasm_feature_enabled(const WasmModule* m, WasmFeatureSet feature); 577 void wasm_require_feature(KitCompiler* c, const WasmModule* m, 578 WasmFeatureSet feature, const char* feature_name, 579 const char* what); 580 int wasm_insn_is_load(WasmInsnKind kind); 581 int wasm_insn_is_store(WasmInsnKind kind); 582 int wasm_insn_is_atomic_load(WasmInsnKind kind); 583 int wasm_insn_is_atomic_store(WasmInsnKind kind); 584 int wasm_insn_is_atomic_rmw(WasmInsnKind kind); 585 int wasm_insn_is_atomic_cmpxchg(WasmInsnKind kind); 586 int wasm_insn_is_atomic_wait_notify(WasmInsnKind kind); 587 int wasm_insn_is_atomic_mem(WasmInsnKind kind); 588 int wasm_insn_is_mem(WasmInsnKind kind); 589 /* WAT mnemonic for an instruction kind (e.g. "i32.add"); never NULL. */ 590 const char* wasm_insn_mnemonic(WasmInsnKind kind); 591 WasmValType wasm_func_local_type(const WasmFunc* f, uint32_t index); 592 uint32_t wasm_mem_width(uint8_t kind); 593 int wasm_int_cmp_op(uint8_t kind, KitCgIntCmpOp* out); 594 WasmValType wasm_load_result_type(uint8_t kind); 595 WasmValType wasm_store_value_type(uint8_t kind); 596 WasmValType wasm_atomic_value_type(uint8_t kind); 597 KitCgAtomicOp wasm_atomic_rmw_op(uint8_t kind); 598 int wasm_int_unop_kind(uint8_t kind, WasmValType* vt); 599 int wasm_fp_unop_kind(uint8_t kind, WasmValType* vt); 600 int wasm_fp_binop_kind(uint8_t kind, WasmValType* vt); 601 int wasm_fp_cmp_kind(uint8_t kind, WasmValType* vt); 602 int wasm_conversion_kind(uint8_t kind, WasmValType* src, WasmValType* dst); 603 604 void wasm_parse_wat(KitCompiler* c, KitSlice name, const KitSlice* input, 605 WasmModule* out); 606 /* Parses a sequence of WAT instructions (no (module ...) / (func ...) wrapper) 607 * into the caller-supplied WasmFunc. The function must already have its 608 * params/results/locals filled in. Direct (call $name) references resolve 609 * against m->funcs[].name. Diagnostics are routed through KitCompiler. */ 610 void wasm_parse_wat_body(KitCompiler* c, WasmModule* m, WasmFunc* f, 611 const char* src, size_t len, KitSrcLoc loc); 612 void wasm_decode_binary(KitCompiler* c, const KitSlice* input, WasmModule* out); 613 /* Decode one instruction from data[pos..] into *out; returns bytes consumed (0 614 * if none). `scratch` is a caller-owned reusable module (wasm_module_init) used 615 * as an allocation-free decode buffer. Shares the opcode mapping with 616 * wasm_decode_binary. Used by the disassembler. */ 617 size_t wasm_decode_one_insn(KitCompiler* c, WasmModule* scratch, 618 const uint8_t* data, size_t len, size_t pos, 619 WasmInsn* out); 620 int wasm_is_binary(const KitSlice* input); 621 void wasm_validate(WasmModule* m, KitCompiler* c); 622 /* Validate a single function under the typed operand/control stack rules. 623 * Used by wasm_validate and by callers that synthesize scratch functions 624 * (e.g. the wasm-target inline-asm path). */ 625 void wasm_validate_func(KitCompiler* c, WasmModule* m, WasmFunc* f); 626 void wasm_emit_cg_into(KitCompiler* c, KitCg* cg, const WasmModule* m); 627 void wasm_emit_cg(KitCompiler* c, const KitCodeOptions* code_opts, 628 KitObjBuilder* out, const WasmModule* m); 629 void wasm_encode(KitCompiler* c, const WasmModule* m, KitWriter* out); 630 631 #endif