kit

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

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