kit

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

cg.c (179000B)


      1 #include <kit/support/arena.h>
      2 
      3 #include "runtime_abi.h"
      4 #include "wasm/wasm.h"
      5 
      6 typedef struct WasmCgBuiltinTypes {
      7   KitCgTypeId id[KIT_CG_BUILTIN_COUNT];
      8 } WasmCgBuiltinTypes;
      9 
     10 static WasmCgBuiltinTypes wasm_cg_builtin_types(KitCompiler* c) {
     11   WasmCgBuiltinTypes b;
     12   memset(&b, 0, sizeof b);
     13   for (uint32_t i = 0; i < KIT_CG_BUILTIN_COUNT; ++i)
     14     b.id[i] = kit_cg_type_builtin(c, (KitCgBuiltinType)i);
     15   return b;
     16 }
     17 
     18 static KitCgTypeId wasm_cg_record_type(KitCompiler* c, KitSym tag,
     19                                        const KitCgFieldDesc* fields,
     20                                        uint32_t nfields) {
     21   KitCgRecordDesc desc;
     22   memset(&desc, 0, sizeof desc);
     23   desc.tag = tag;
     24   desc.fields = fields;
     25   desc.nfields = nfields;
     26   return kit_cg_type_record(c, &desc);
     27 }
     28 
     29 static KitCgTypeId wasm_cg_type(KitCompiler* c, WasmCgBuiltinTypes b,
     30                                 WasmValType vt) {
     31   switch (vt) {
     32     case WASM_VAL_I32:
     33       return b.id[KIT_CG_BUILTIN_I32];
     34     case WASM_VAL_I64:
     35       return b.id[KIT_CG_BUILTIN_I64];
     36     case WASM_VAL_F32:
     37       return b.id[KIT_CG_BUILTIN_F32];
     38     case WASM_VAL_F64:
     39       return b.id[KIT_CG_BUILTIN_F64];
     40     case WASM_VAL_FUNCREF:
     41     case WASM_VAL_EXTERNREF:
     42       return kit_cg_type_ptr(c, b.id[KIT_CG_BUILTIN_VOID], 0);
     43   }
     44   wasm_error(c, wasm_loc(0, 0), "wasm: unsupported value type");
     45   return b.id[KIT_CG_BUILTIN_I32];
     46 }
     47 
     48 static KitCgMemAccess wasm_cg_mem(KitCompiler* c, WasmCgBuiltinTypes b,
     49                                   WasmValType vt) {
     50   KitCgMemAccess mem;
     51   memset(&mem, 0, sizeof mem);
     52   mem.type = wasm_cg_type(c, b, vt);
     53   return mem;
     54 }
     55 
     56 static KitCgMemAccess wasm_cg_mem_type(KitCgTypeId ty) {
     57   KitCgMemAccess mem;
     58   memset(&mem, 0, sizeof mem);
     59   mem.type = ty;
     60   return mem;
     61 }
     62 
     63 static void wasm_cg_push_zero(KitCompiler* c, KitCg* cg, WasmCgBuiltinTypes b,
     64                               WasmValType vt) {
     65   KitCgTypeId ty = wasm_cg_type(c, b, vt);
     66   if (wasm_is_ref_type(vt))
     67     kit_cg_push_null(cg, ty);
     68   else if (vt == WASM_VAL_F32 || vt == WASM_VAL_F64)
     69     kit_cg_push_float(cg, 0.0, ty);
     70   else
     71     kit_cg_push_int(cg, 0, ty);
     72 }
     73 
     74 static KitCgTypeId wasm_load_storage_type(WasmCgBuiltinTypes b, uint8_t kind) {
     75   switch (kind) {
     76     case WASM_INSN_I32_LOAD8_S:
     77     case WASM_INSN_I32_LOAD8_U:
     78     case WASM_INSN_I64_LOAD8_S:
     79     case WASM_INSN_I64_LOAD8_U:
     80       return b.id[KIT_CG_BUILTIN_I8];
     81     case WASM_INSN_I32_LOAD16_S:
     82     case WASM_INSN_I32_LOAD16_U:
     83     case WASM_INSN_I64_LOAD16_S:
     84     case WASM_INSN_I64_LOAD16_U:
     85       return b.id[KIT_CG_BUILTIN_I16];
     86     case WASM_INSN_I64_LOAD32_S:
     87     case WASM_INSN_I64_LOAD32_U:
     88     case WASM_INSN_I32_LOAD:
     89       return b.id[KIT_CG_BUILTIN_I32];
     90     case WASM_INSN_F32_LOAD:
     91       return b.id[KIT_CG_BUILTIN_F32];
     92     case WASM_INSN_F64_LOAD:
     93       return b.id[KIT_CG_BUILTIN_F64];
     94     default:
     95       return b.id[KIT_CG_BUILTIN_I64];
     96   }
     97 }
     98 
     99 static KitCgTypeId wasm_store_storage_type(WasmCgBuiltinTypes b, uint8_t kind) {
    100   switch (kind) {
    101     case WASM_INSN_I32_STORE8:
    102     case WASM_INSN_I64_STORE8:
    103       return b.id[KIT_CG_BUILTIN_I8];
    104     case WASM_INSN_I32_STORE16:
    105     case WASM_INSN_I64_STORE16:
    106       return b.id[KIT_CG_BUILTIN_I16];
    107     case WASM_INSN_I64_STORE32:
    108     case WASM_INSN_I32_STORE:
    109       return b.id[KIT_CG_BUILTIN_I32];
    110     case WASM_INSN_F32_STORE:
    111       return b.id[KIT_CG_BUILTIN_F32];
    112     case WASM_INSN_F64_STORE:
    113       return b.id[KIT_CG_BUILTIN_F64];
    114     default:
    115       return b.id[KIT_CG_BUILTIN_I64];
    116   }
    117 }
    118 
    119 typedef enum WasmTrapKind {
    120   WASM_TRAP_UNREACHABLE,
    121   WASM_TRAP_DIVISION,
    122   WASM_TRAP_INVALID_CONVERSION,
    123   WASM_TRAP_BOUNDS,
    124   WASM_TRAP_TABLE,
    125   WASM_TRAP_SIGNATURE,
    126   WASM_TRAP_COUNT,
    127 } WasmTrapKind;
    128 
    129 typedef struct WasmCgRuntime {
    130   KitCgTypeId i8_ptr_ty;
    131   KitCgTypeId void_ptr_ty;
    132   KitCgTypeId memory_ty;
    133   KitCgTypeId func_import_ty;
    134   KitCgTypeId global_import_ty;
    135   KitCgTypeId table_entry_ty;
    136   KitCgTypeId table_entry_ptr_ty;
    137   KitCgTypeId table_ty;
    138   KitCgTypeId instance_ty;
    139   KitCgTypeId instance_ptr_ty;
    140   uint64_t table_entry_size;
    141   /* Byte offsets within the instance struct for each top-level slot. */
    142   uint64_t* memory_offset;
    143   uint64_t* func_import_offset;
    144   uint64_t* func_ref_entry_offset;
    145   uint64_t* global_offset;
    146   uint64_t* table_offset;
    147   uint64_t* table_entries_offset;
    148   /* Byte offsets within their containing record. */
    149   uint64_t memory_data_offset;
    150   uint64_t memory_pages_offset;
    151   uint64_t memory_max_pages_offset;
    152   uint64_t memory_flags_offset;
    153   uint64_t func_import_fn_offset;
    154   uint64_t global_import_addr_offset;
    155   uint64_t table_entries_ptr_offset;
    156   uint64_t table_len_offset;
    157   uint64_t table_max_offset;
    158   uint64_t table_entry_fn_offset;
    159   uint64_t table_entry_typeidx_offset;
    160   /* memory/func/global/table-indexed instance-record field numbers. Sized to
    161    * the actual module counts (m->nmemories, m->nfuncs, m->nglobals,
    162    * m->ntables) and arena-allocated in wasm_cg_build_runtime so there's no
    163    * fixed cap on any of them. */
    164   uint32_t* memory_field;
    165   uint32_t memory_data_field;
    166   uint32_t memory_pages_field;
    167   uint32_t memory_max_pages_field;
    168   uint32_t memory_flags_field;
    169   uint32_t* func_import_field;
    170   uint32_t* func_ref_entry_field;
    171   uint32_t* global_field;
    172   uint32_t global_import_addr_field;
    173   uint32_t* table_field;
    174   uint32_t* table_entries_field;
    175   uint32_t table_entry_fn_field;
    176   uint32_t table_entry_typeidx_field;
    177   uint32_t table_entries_ptr_field;
    178   uint32_t table_len_field;
    179   uint32_t table_max_field;
    180   /* Bulk-memory passive segment storage. Each module data/elem segment with
    181    * mode == WASM_SEG_PASSIVE has a slot in the instance; active segments also
    182    * get a slot for uniform indexing (memory.init/table.init are validated to
    183    * traps on dropped/active segment use; the slot's len is left zero for
    184    * active segments so memory.init traps on non-zero copies). */
    185   KitCgTypeId passive_data_ty;
    186   KitCgTypeId passive_elem_ty;
    187   uint32_t* passive_data_field;
    188   uint32_t passive_data_base_field;
    189   uint32_t passive_data_len_field;
    190   uint32_t* passive_elem_field;
    191   uint32_t* passive_elem_storage_field;
    192   uint32_t passive_elem_entries_field;
    193   uint32_t passive_elem_length_field;
    194   KitCgTypeId void_ty;
    195   KitCgTypeId trap_func_ty;
    196   KitCgSym trap_syms[WASM_TRAP_COUNT];
    197 } WasmCgRuntime;
    198 
    199 static const char* wasm_trap_name(WasmTrapKind kind) {
    200   switch (kind) {
    201     case WASM_TRAP_UNREACHABLE:
    202       return "__kit_wasm_trap_unreachable";
    203     case WASM_TRAP_DIVISION:
    204       return "__kit_wasm_trap_division";
    205     case WASM_TRAP_INVALID_CONVERSION:
    206       return "__kit_wasm_trap_invalid_conversion";
    207     case WASM_TRAP_BOUNDS:
    208       return "__kit_wasm_trap_bounds";
    209     case WASM_TRAP_TABLE:
    210       return "__kit_wasm_trap_table";
    211     case WASM_TRAP_SIGNATURE:
    212       return "__kit_wasm_trap_signature";
    213     default:
    214       return "__kit_wasm_trap";
    215   }
    216 }
    217 
    218 static void wasm_cg_emit_raw_trap(KitCompiler* c, KitCg* cg) {
    219   kit_cg_intrinsic(cg, KIT_CG_INTRIN_TRAP, 0,
    220                    kit_cg_type_builtin(c, KIT_CG_BUILTIN_VOID));
    221   kit_cg_unreachable(cg);
    222 }
    223 
    224 static void wasm_cg_trap(KitCg* cg, const WasmCgRuntime* rt,
    225                          WasmTrapKind kind) {
    226   if (rt && kind < WASM_TRAP_COUNT && rt->trap_syms[kind])
    227     kit_cg_call_symbol(cg, rt->trap_syms[kind], 0,
    228                        (KitCgCallAttrs){.flags = KIT_CG_CALL_COLD});
    229   else if (rt)
    230     kit_cg_intrinsic(cg, KIT_CG_INTRIN_TRAP, 0, rt->void_ty);
    231   kit_cg_unreachable(cg);
    232 }
    233 
    234 static void wasm_cg_trap_unreachable(KitCg* cg, const WasmCgRuntime* rt) {
    235   wasm_cg_trap(cg, rt, WASM_TRAP_UNREACHABLE);
    236 }
    237 static void wasm_cg_trap_division(KitCg* cg, const WasmCgRuntime* rt) {
    238   wasm_cg_trap(cg, rt, WASM_TRAP_DIVISION);
    239 }
    240 static void wasm_cg_trap_invalid_conversion(KitCg* cg,
    241                                             const WasmCgRuntime* rt) {
    242   wasm_cg_trap(cg, rt, WASM_TRAP_INVALID_CONVERSION);
    243 }
    244 static void wasm_cg_trap_bounds(KitCg* cg, const WasmCgRuntime* rt) {
    245   wasm_cg_trap(cg, rt, WASM_TRAP_BOUNDS);
    246 }
    247 static void wasm_cg_trap_table(KitCg* cg, const WasmCgRuntime* rt) {
    248   wasm_cg_trap(cg, rt, WASM_TRAP_TABLE);
    249 }
    250 static void wasm_cg_trap_signature(KitCg* cg, const WasmCgRuntime* rt) {
    251   wasm_cg_trap(cg, rt, WASM_TRAP_SIGNATURE);
    252 }
    253 
    254 static void wasm_indexed_name(char* name, size_t cap, const char* prefix,
    255                               uint32_t index) {
    256   size_t pos = 0;
    257   uint32_t n = index, div = 1000000000u;
    258   while (*prefix && pos + 1u < cap) name[pos++] = *prefix++;
    259   while (div > 1u && n / div == 0) div /= 10u;
    260   while (div && pos + 1u < cap) {
    261     name[pos++] = (char)('0' + (n / div) % 10u);
    262     div /= 10u;
    263   }
    264   name[pos] = '\0';
    265 }
    266 
    267 static uint64_t wasm_cg_field_offset(KitCompiler* c, KitCgTypeId ty,
    268                                      uint32_t index) {
    269   const KitCgRecordLayout* L = kit_cg_type_record_layout(c, ty);
    270   if (!L || index >= L->nfields) {
    271     wasm_error(c, wasm_loc(0, 0), "wasm: failed to query field offset");
    272     return 0;
    273   }
    274   return L->fields[index].offset;
    275 }
    276 
    277 static uint32_t wasm_cg_checked_add_u32(KitCompiler* c, uint32_t a, uint32_t b,
    278                                         KitSrcLoc loc) {
    279   if (UINT32_MAX - a < b)
    280     wasm_error(c, loc, "wasm: module layout is too large");
    281   return a + b;
    282 }
    283 
    284 static void wasm_cg_build_runtime(KitCompiler* c, WasmCgBuiltinTypes b,
    285                                   const WasmModule* m, WasmCgRuntime* rt,
    286                                   KitArena* arena) {
    287   KitCgFieldDesc memory_fields[4];
    288   KitCgFieldDesc func_import_fields[1];
    289   KitCgFieldDesc global_import_fields[1];
    290   KitCgFieldDesc table_entry_fields[2];
    291   KitCgFieldDesc table_fields[3];
    292   KitCgFieldDesc passive_data_fields[2];
    293   KitCgFieldDesc passive_elem_fields[2];
    294   /* Total instance fields = nmemories + (#import funcs) + nfuncs (one
    295    * func_ref entry per func) + nglobals + 2*ntables + ndata + nelems.
    296    * Allocate the upper bound from the arena so nfields can grow with the
    297    * module. */
    298   uint32_t instance_cap = 0;
    299   KitCgFieldDesc* instance_fields =
    300       instance_cap ? kit_arena_zarray(arena, KitCgFieldDesc, instance_cap)
    301                    : NULL;
    302   uint32_t nfields = 0;
    303   uint32_t* memory_field_idx = NULL;
    304   uint32_t* func_import_field_idx = NULL;
    305   uint32_t* func_ref_entry_field_idx = NULL;
    306   uint32_t* global_field_idx = NULL;
    307   uint32_t* table_field_idx = NULL;
    308   uint32_t* table_entries_field_idx = NULL;
    309   memset(rt, 0, sizeof *rt);
    310 
    311   instance_cap =
    312       wasm_cg_checked_add_u32(c, instance_cap, m->nmemories, wasm_loc(0, 0));
    313   instance_cap =
    314       wasm_cg_checked_add_u32(c, instance_cap, m->nfuncs, wasm_loc(0, 0));
    315   instance_cap =
    316       wasm_cg_checked_add_u32(c, instance_cap, m->nfuncs, wasm_loc(0, 0));
    317   instance_cap =
    318       wasm_cg_checked_add_u32(c, instance_cap, m->nglobals, wasm_loc(0, 0));
    319   if (m->ntables > UINT32_MAX / 2u)
    320     wasm_error(c, wasm_loc(0, 0), "wasm: module layout is too large");
    321   instance_cap =
    322       wasm_cg_checked_add_u32(c, instance_cap, 2u * m->ntables, wasm_loc(0, 0));
    323   instance_cap =
    324       wasm_cg_checked_add_u32(c, instance_cap, m->ndata, wasm_loc(0, 0));
    325   if (m->nelems > UINT32_MAX / 2u)
    326     wasm_error(c, wasm_loc(0, 0), "wasm: module layout is too large");
    327   instance_cap =
    328       wasm_cg_checked_add_u32(c, instance_cap, 2u * m->nelems, wasm_loc(0, 0));
    329   instance_fields = instance_cap
    330                         ? kit_arena_zarray(arena, KitCgFieldDesc, instance_cap)
    331                         : NULL;
    332 
    333   rt->memory_field =
    334       m->nmemories ? kit_arena_zarray(arena, uint32_t, m->nmemories) : NULL;
    335   rt->memory_offset =
    336       m->nmemories ? kit_arena_zarray(arena, uint64_t, m->nmemories) : NULL;
    337   rt->func_import_field =
    338       m->nfuncs ? kit_arena_zarray(arena, uint32_t, m->nfuncs) : NULL;
    339   rt->func_import_offset =
    340       m->nfuncs ? kit_arena_zarray(arena, uint64_t, m->nfuncs) : NULL;
    341   rt->func_ref_entry_field =
    342       m->nfuncs ? kit_arena_zarray(arena, uint32_t, m->nfuncs) : NULL;
    343   rt->func_ref_entry_offset =
    344       m->nfuncs ? kit_arena_zarray(arena, uint64_t, m->nfuncs) : NULL;
    345   rt->global_field =
    346       m->nglobals ? kit_arena_zarray(arena, uint32_t, m->nglobals) : NULL;
    347   rt->global_offset =
    348       m->nglobals ? kit_arena_zarray(arena, uint64_t, m->nglobals) : NULL;
    349   rt->table_field =
    350       m->ntables ? kit_arena_zarray(arena, uint32_t, m->ntables) : NULL;
    351   rt->table_offset =
    352       m->ntables ? kit_arena_zarray(arena, uint64_t, m->ntables) : NULL;
    353   rt->table_entries_field =
    354       m->ntables ? kit_arena_zarray(arena, uint32_t, m->ntables) : NULL;
    355   rt->table_entries_offset =
    356       m->ntables ? kit_arena_zarray(arena, uint64_t, m->ntables) : NULL;
    357   rt->passive_data_field =
    358       m->ndata ? kit_arena_zarray(arena, uint32_t, m->ndata) : NULL;
    359   rt->passive_elem_field =
    360       m->nelems ? kit_arena_zarray(arena, uint32_t, m->nelems) : NULL;
    361   rt->passive_elem_storage_field =
    362       m->nelems ? kit_arena_zarray(arena, uint32_t, m->nelems) : NULL;
    363   memory_field_idx =
    364       m->nmemories ? kit_arena_zarray(arena, uint32_t, m->nmemories) : NULL;
    365   func_import_field_idx =
    366       m->nfuncs ? kit_arena_zarray(arena, uint32_t, m->nfuncs) : NULL;
    367   func_ref_entry_field_idx =
    368       m->nfuncs ? kit_arena_zarray(arena, uint32_t, m->nfuncs) : NULL;
    369   global_field_idx =
    370       m->nglobals ? kit_arena_zarray(arena, uint32_t, m->nglobals) : NULL;
    371   table_field_idx =
    372       m->ntables ? kit_arena_zarray(arena, uint32_t, m->ntables) : NULL;
    373   table_entries_field_idx =
    374       m->ntables ? kit_arena_zarray(arena, uint32_t, m->ntables) : NULL;
    375   rt->void_ty = b.id[KIT_CG_BUILTIN_VOID];
    376   rt->i8_ptr_ty = kit_cg_type_ptr(c, b.id[KIT_CG_BUILTIN_I8], 0);
    377   rt->void_ptr_ty = rt->i8_ptr_ty;
    378   memset(memory_fields, 0, sizeof memory_fields);
    379   memory_fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("data"));
    380   memory_fields[0].type = rt->i8_ptr_ty;
    381   memory_fields[1].name = kit_sym_intern(c, KIT_SLICE_LIT("pages"));
    382   memory_fields[1].type = b.id[KIT_CG_BUILTIN_I64];
    383   memory_fields[2].name = kit_sym_intern(c, KIT_SLICE_LIT("max_pages"));
    384   memory_fields[2].type = b.id[KIT_CG_BUILTIN_I64];
    385   memory_fields[3].name = kit_sym_intern(c, KIT_SLICE_LIT("flags"));
    386   memory_fields[3].type = b.id[KIT_CG_BUILTIN_I32];
    387   rt->memory_ty = wasm_cg_record_type(
    388       c, kit_sym_intern(c, KIT_SLICE_LIT("KitWasmMemory")), memory_fields, 4);
    389   rt->memory_data_offset = wasm_cg_field_offset(c, rt->memory_ty, 0);
    390   rt->memory_pages_offset = wasm_cg_field_offset(c, rt->memory_ty, 1);
    391   rt->memory_max_pages_offset = wasm_cg_field_offset(c, rt->memory_ty, 2);
    392   rt->memory_flags_offset = wasm_cg_field_offset(c, rt->memory_ty, 3);
    393   rt->memory_data_field = 0;
    394   rt->memory_pages_field = 1;
    395   rt->memory_max_pages_field = 2;
    396   rt->memory_flags_field = 3;
    397   memset(func_import_fields, 0, sizeof func_import_fields);
    398   func_import_fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("fn"));
    399   func_import_fields[0].type = rt->void_ptr_ty;
    400   rt->func_import_ty = wasm_cg_record_type(
    401       c, kit_sym_intern(c, KIT_SLICE_LIT("KitWasmFuncImport")),
    402       func_import_fields, 1);
    403   rt->func_import_fn_offset = wasm_cg_field_offset(c, rt->func_import_ty, 0);
    404   memset(global_import_fields, 0, sizeof global_import_fields);
    405   global_import_fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("addr"));
    406   global_import_fields[0].type = rt->void_ptr_ty;
    407   rt->global_import_ty = wasm_cg_record_type(
    408       c, kit_sym_intern(c, KIT_SLICE_LIT("KitWasmGlobalImport")),
    409       global_import_fields, 1);
    410   rt->global_import_addr_offset =
    411       wasm_cg_field_offset(c, rt->global_import_ty, 0);
    412   memset(table_entry_fields, 0, sizeof table_entry_fields);
    413   table_entry_fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("fn"));
    414   table_entry_fields[0].type = rt->void_ptr_ty;
    415   table_entry_fields[1].name = kit_sym_intern(c, KIT_SLICE_LIT("typeidx"));
    416   table_entry_fields[1].type = b.id[KIT_CG_BUILTIN_I32];
    417   rt->table_entry_ty = wasm_cg_record_type(
    418       c, kit_sym_intern(c, KIT_SLICE_LIT("KitWasmTableEntry")),
    419       table_entry_fields, 2);
    420   rt->table_entry_ptr_ty = kit_cg_type_ptr(c, rt->table_entry_ty, 0);
    421   rt->table_entry_fn_offset = wasm_cg_field_offset(c, rt->table_entry_ty, 0);
    422   rt->table_entry_typeidx_offset =
    423       wasm_cg_field_offset(c, rt->table_entry_ty, 1);
    424   rt->table_entry_size = kit_cg_type_size(c, rt->table_entry_ty);
    425   rt->table_entry_fn_field = 0;
    426   rt->table_entry_typeidx_field = 1;
    427   memset(table_fields, 0, sizeof table_fields);
    428   table_fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("entries"));
    429   table_fields[0].type = rt->table_entry_ptr_ty;
    430   table_fields[1].name = kit_sym_intern(c, KIT_SLICE_LIT("len"));
    431   table_fields[1].type = b.id[KIT_CG_BUILTIN_I32];
    432   table_fields[2].name = kit_sym_intern(c, KIT_SLICE_LIT("max"));
    433   table_fields[2].type = b.id[KIT_CG_BUILTIN_I32];
    434   rt->table_ty = wasm_cg_record_type(
    435       c, kit_sym_intern(c, KIT_SLICE_LIT("KitWasmTable")), table_fields, 3);
    436   rt->table_entries_ptr_offset = wasm_cg_field_offset(c, rt->table_ty, 0);
    437   rt->table_len_offset = wasm_cg_field_offset(c, rt->table_ty, 1);
    438   rt->table_max_offset = wasm_cg_field_offset(c, rt->table_ty, 2);
    439   rt->table_entries_ptr_field = 0;
    440   rt->table_len_field = 1;
    441   rt->table_max_field = 2;
    442   memset(passive_data_fields, 0, sizeof passive_data_fields);
    443   passive_data_fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("base"));
    444   passive_data_fields[0].type = rt->i8_ptr_ty;
    445   passive_data_fields[1].name = kit_sym_intern(c, KIT_SLICE_LIT("len"));
    446   passive_data_fields[1].type = b.id[KIT_CG_BUILTIN_I64];
    447   rt->passive_data_ty = wasm_cg_record_type(
    448       c, kit_sym_intern(c, KIT_SLICE_LIT("KitWasmPassiveDataSegment")),
    449       passive_data_fields, 2);
    450   rt->passive_data_base_field = 0;
    451   rt->passive_data_len_field = 1;
    452   memset(passive_elem_fields, 0, sizeof passive_elem_fields);
    453   passive_elem_fields[0].name = kit_sym_intern(c, KIT_SLICE_LIT("entries"));
    454   passive_elem_fields[0].type = rt->table_entry_ptr_ty;
    455   passive_elem_fields[1].name = kit_sym_intern(c, KIT_SLICE_LIT("length"));
    456   passive_elem_fields[1].type = b.id[KIT_CG_BUILTIN_I32];
    457   rt->passive_elem_ty = wasm_cg_record_type(
    458       c, kit_sym_intern(c, KIT_SLICE_LIT("KitWasmPassiveElemSegment")),
    459       passive_elem_fields, 2);
    460   rt->passive_elem_entries_field = 0;
    461   rt->passive_elem_length_field = 1;
    462   for (uint32_t i = 0; i < m->nmemories; ++i) {
    463     char name[40];
    464     if (i == 0)
    465       memcpy(name, "memory", sizeof "memory");
    466     else
    467       wasm_indexed_name(name, sizeof name, "memory_", i);
    468     rt->memory_field[i] = nfields;
    469     memory_field_idx[i] = nfields;
    470     instance_fields[nfields].name = kit_sym_intern(c, kit_slice_cstr(name));
    471     instance_fields[nfields].type = rt->memory_ty;
    472     nfields++;
    473   }
    474   for (uint32_t i = 0; i < m->nfuncs; ++i) {
    475     char name[40];
    476     if (!m->funcs[i].is_import) continue;
    477     wasm_indexed_name(name, sizeof name, "import_func_", i);
    478     rt->func_import_field[i] = nfields;
    479     func_import_field_idx[i] = nfields;
    480     instance_fields[nfields].name = kit_sym_intern(c, kit_slice_cstr(name));
    481     instance_fields[nfields].type = rt->func_import_ty;
    482     nfields++;
    483   }
    484   for (uint32_t i = 0; i < m->nfuncs; ++i) {
    485     char name[40];
    486     wasm_indexed_name(name, sizeof name, "func_ref_", i);
    487     rt->func_ref_entry_field[i] = nfields;
    488     func_ref_entry_field_idx[i] = nfields;
    489     instance_fields[nfields].name = kit_sym_intern(c, kit_slice_cstr(name));
    490     instance_fields[nfields].type = rt->table_entry_ty;
    491     nfields++;
    492   }
    493   for (uint32_t i = 0; i < m->nglobals; ++i) {
    494     char name[32];
    495     wasm_indexed_name(name, sizeof name,
    496                       m->globals[i].is_import ? "import_global_" : "global_",
    497                       i);
    498     rt->global_field[i] = nfields;
    499     global_field_idx[i] = nfields;
    500     instance_fields[nfields].name = kit_sym_intern(c, kit_slice_cstr(name));
    501     instance_fields[nfields].type =
    502         m->globals[i].is_import ? rt->global_import_ty
    503                                 : wasm_cg_type(c, b, m->globals[i].type);
    504     nfields++;
    505   }
    506   for (uint32_t i = 0; i < m->ntables; ++i) {
    507     char name[40];
    508     uint32_t max = m->tables[i].has_max ? m->tables[i].max : m->tables[i].min;
    509     wasm_indexed_name(name, sizeof name, "table_", i);
    510     rt->table_field[i] = nfields;
    511     table_field_idx[i] = nfields;
    512     instance_fields[nfields].name = kit_sym_intern(c, kit_slice_cstr(name));
    513     instance_fields[nfields].type = rt->table_ty;
    514     nfields++;
    515     wasm_indexed_name(name, sizeof name, "table_entries_", i);
    516     rt->table_entries_field[i] = nfields;
    517     table_entries_field_idx[i] = nfields;
    518     instance_fields[nfields].name = kit_sym_intern(c, kit_slice_cstr(name));
    519     instance_fields[nfields].type =
    520         kit_cg_type_array(c, rt->table_entry_ty, max ? max : 1u);
    521     nfields++;
    522   }
    523   for (uint32_t i = 0; i < m->ndata; ++i) {
    524     char name[40];
    525     wasm_indexed_name(name, sizeof name, "passive_data_", i);
    526     rt->passive_data_field[i] = nfields;
    527     instance_fields[nfields].name = kit_sym_intern(c, kit_slice_cstr(name));
    528     instance_fields[nfields].type = rt->passive_data_ty;
    529     nfields++;
    530   }
    531   for (uint32_t i = 0; i < m->nelems; ++i) {
    532     char name[40];
    533     uint32_t nfuncs = m->elems[i].nfuncs;
    534     wasm_indexed_name(name, sizeof name, "passive_elem_", i);
    535     rt->passive_elem_field[i] = nfields;
    536     instance_fields[nfields].name = kit_sym_intern(c, kit_slice_cstr(name));
    537     instance_fields[nfields].type = rt->passive_elem_ty;
    538     nfields++;
    539     wasm_indexed_name(name, sizeof name, "passive_elem_storage_", i);
    540     rt->passive_elem_storage_field[i] = nfields;
    541     instance_fields[nfields].name = kit_sym_intern(c, kit_slice_cstr(name));
    542     instance_fields[nfields].type =
    543         kit_cg_type_array(c, rt->table_entry_ty, nfuncs ? nfuncs : 1u);
    544     nfields++;
    545   }
    546   rt->instance_ty = wasm_cg_record_type(
    547       c, kit_sym_intern(c, KIT_SLICE_LIT("KitWasmInstance")), instance_fields,
    548       nfields);
    549   rt->instance_ptr_ty = kit_cg_type_ptr(c, rt->instance_ty, 0);
    550   for (uint32_t i = 0; i < m->nmemories; ++i)
    551     rt->memory_offset[i] =
    552         wasm_cg_field_offset(c, rt->instance_ty, memory_field_idx[i]);
    553   for (uint32_t i = 0; i < m->nfuncs; ++i) {
    554     if (m->funcs[i].is_import)
    555       rt->func_import_offset[i] =
    556           wasm_cg_field_offset(c, rt->instance_ty, func_import_field_idx[i]);
    557     rt->func_ref_entry_offset[i] =
    558         wasm_cg_field_offset(c, rt->instance_ty, func_ref_entry_field_idx[i]);
    559   }
    560   for (uint32_t i = 0; i < m->nglobals; ++i)
    561     rt->global_offset[i] =
    562         wasm_cg_field_offset(c, rt->instance_ty, global_field_idx[i]);
    563   for (uint32_t i = 0; i < m->ntables; ++i) {
    564     rt->table_offset[i] =
    565         wasm_cg_field_offset(c, rt->instance_ty, table_field_idx[i]);
    566     rt->table_entries_offset[i] =
    567         wasm_cg_field_offset(c, rt->instance_ty, table_entries_field_idx[i]);
    568   }
    569 }
    570 
    571 /* Push the instance pointer rvalue (loaded from the instance parameter slot).
    572  * Stack: [] -> [void*]. Callers fold a struct offset into the memop's EA. */
    573 static void wasm_cg_push_instance_ptr(KitCg* cg, const WasmCgRuntime* rt,
    574                                       KitCgLocal instance_local) {
    575   kit_cg_push_local(cg, instance_local);
    576   kit_cg_load(cg, wasm_cg_mem_type(rt->instance_ptr_ty));
    577 }
    578 
    579 /* Push the instance as a record PLACE (the pointee of the instance pointer).
    580  * Stack: [] -> [place]. Callers project struct fields off it with field/elem.
    581  */
    582 static void wasm_cg_push_instance_lvalue(KitCg* cg, const WasmCgRuntime* rt,
    583                                          KitCgLocal instance_local) {
    584   wasm_cg_push_instance_ptr(cg, rt, instance_local);
    585   kit_cg_deref(cg, 0);
    586 }
    587 
    588 /* Add a constant byte offset to the pointer rvalue on TOS, retyping to
    589  * `result_ptr_ty`. No-op when offset == 0 (and the type is not retyped). */
    590 static void wasm_cg_ptr_add_offset(KitCg* cg, WasmCgBuiltinTypes b,
    591                                    uint64_t offset, KitCgTypeId result_ptr_ty) {
    592   KitCgTypeId i64_ty = b.id[KIT_CG_BUILTIN_I64];
    593   if (offset == 0) {
    594     kit_cg_bitcast(cg, result_ptr_ty);
    595     return;
    596   }
    597   kit_cg_ptr_to_int(cg, i64_ty);
    598   kit_cg_push_int(cg, offset, i64_ty);
    599   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    600   kit_cg_int_to_ptr(cg, result_ptr_ty);
    601 }
    602 
    603 /* Load the i8* data pointer from instance->memories[memidx].data. */
    604 static void wasm_cg_push_memory_data_ptr(KitCg* cg, const WasmCgRuntime* rt,
    605                                          KitCgLocal instance_local,
    606                                          uint32_t memidx) {
    607   wasm_cg_push_instance_ptr(cg, rt, instance_local);
    608   kit_cg_deref(cg,
    609                (int64_t)(rt->memory_offset[memidx] + rt->memory_data_offset));
    610   kit_cg_load(cg, wasm_cg_mem_type(rt->i8_ptr_ty));
    611 }
    612 
    613 static void wasm_cg_push_memory_pages_lvalue(KitCg* cg, const WasmCgRuntime* rt,
    614                                              KitCgLocal instance_local,
    615                                              uint32_t memidx) {
    616   wasm_cg_push_instance_lvalue(cg, rt, instance_local);
    617   kit_cg_field(cg, rt->memory_field[memidx]);
    618   kit_cg_field(cg, rt->memory_pages_field);
    619 }
    620 
    621 /* Load instance->import_funcs[func_index].fn as a void*. */
    622 static void wasm_cg_push_import_func_ptr(KitCg* cg, const WasmCgRuntime* rt,
    623                                          KitCgLocal instance_local,
    624                                          uint32_t func_index) {
    625   wasm_cg_push_instance_ptr(cg, rt, instance_local);
    626   kit_cg_deref(cg, (int64_t)(rt->func_import_offset[func_index] +
    627                              rt->func_import_fn_offset));
    628   kit_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
    629 }
    630 
    631 /* Push a pointer rvalue to instance->globals[global_index]'s value cell,
    632  * dereferencing the import indirection if needed. Result type is T* where T is
    633  * the global's value type. */
    634 static void wasm_cg_push_global_value_ptr(
    635     KitCompiler* c, KitCg* cg, WasmCgBuiltinTypes b, const WasmCgRuntime* rt,
    636     KitCgLocal instance_local, const WasmModule* m, uint32_t global_index) {
    637   KitCgTypeId ptr_ty =
    638       kit_cg_type_ptr(c, wasm_cg_type(c, b, m->globals[global_index].type), 0);
    639   if (m->globals[global_index].is_import) {
    640     wasm_cg_push_instance_ptr(cg, rt, instance_local);
    641     kit_cg_deref(cg, (int64_t)(rt->global_offset[global_index] +
    642                                rt->global_import_addr_offset));
    643     kit_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
    644     kit_cg_dup(cg);
    645     kit_cg_push_null(cg, rt->void_ptr_ty);
    646     kit_cg_int_cmp(cg, KIT_CG_INT_NE);
    647     {
    648       KitCgLabel ok = kit_cg_label_new(cg);
    649       kit_cg_branch_true(cg, ok);
    650       wasm_cg_trap_table(cg, rt);
    651       kit_cg_label_place(cg, ok);
    652     }
    653     kit_cg_bitcast(cg, ptr_ty);
    654   } else {
    655     wasm_cg_push_instance_ptr(cg, rt, instance_local);
    656     wasm_cg_ptr_add_offset(cg, b, rt->global_offset[global_index], ptr_ty);
    657   }
    658 }
    659 
    660 static void wasm_cg_push_table_lvalue(KitCg* cg, const WasmCgRuntime* rt,
    661                                       KitCgLocal instance_local,
    662                                       uint32_t table_index) {
    663   wasm_cg_push_instance_lvalue(cg, rt, instance_local);
    664   kit_cg_field(cg, rt->table_field[table_index]);
    665 }
    666 
    667 static void wasm_cg_push_table_entry_lvalue(KitCg* cg, const WasmCgRuntime* rt,
    668                                             KitCgLocal instance_local,
    669                                             uint32_t table_index,
    670                                             KitCgLocal index_local,
    671                                             KitCgMemAccess index_mem) {
    672   wasm_cg_push_table_lvalue(cg, rt, instance_local, table_index);
    673   kit_cg_field(cg, rt->table_entries_ptr_field);
    674   kit_cg_load(cg, wasm_cg_mem_type(rt->table_entry_ptr_ty));
    675   kit_cg_push_local(cg, index_local);
    676   kit_cg_load(cg, index_mem);
    677   kit_cg_elem(cg, 0);
    678 }
    679 
    680 /* Push a pointer rvalue to instance->tables[table_index].entries[index_local].
    681  * The index is loaded from a temp local supplied by the caller (mirrors the
    682  * previous helper's signature). */
    683 static void wasm_cg_push_table_entry_ptr(KitCg* cg, WasmCgBuiltinTypes b,
    684                                          const WasmCgRuntime* rt,
    685                                          KitCgLocal instance_local,
    686                                          uint32_t table_index,
    687                                          KitCgLocal index_local,
    688                                          KitCgMemAccess index_mem) {
    689   KitCgTypeId i64_ty = b.id[KIT_CG_BUILTIN_I64];
    690   /* Load entries pointer from instance->tables[i].entries. */
    691   wasm_cg_push_instance_ptr(cg, rt, instance_local);
    692   kit_cg_deref(cg, (int64_t)(rt->table_offset[table_index] +
    693                              rt->table_entries_ptr_offset));
    694   kit_cg_load(cg, wasm_cg_mem_type(rt->table_entry_ptr_ty));
    695   /* Compute entries + index * sizeof(entry) into a pointer rvalue. */
    696   kit_cg_ptr_to_int(cg, i64_ty);
    697   kit_cg_push_local(cg, index_local);
    698   kit_cg_load(cg, index_mem);
    699   kit_cg_zext(cg, i64_ty);
    700   kit_cg_push_int(cg, rt->table_entry_size, i64_ty);
    701   kit_cg_int_binop(cg, KIT_CG_INT_MUL, 0);
    702   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    703   kit_cg_int_to_ptr(cg, rt->table_entry_ptr_ty);
    704 }
    705 
    706 static void wasm_cg_push_passive_data_lvalue(KitCg* cg, const WasmCgRuntime* rt,
    707                                              KitCgLocal instance_local,
    708                                              uint32_t dataidx) {
    709   wasm_cg_push_instance_lvalue(cg, rt, instance_local);
    710   kit_cg_field(cg, rt->passive_data_field[dataidx]);
    711 }
    712 
    713 static void wasm_cg_push_passive_elem_lvalue(KitCg* cg, const WasmCgRuntime* rt,
    714                                              KitCgLocal instance_local,
    715                                              uint32_t elemidx) {
    716   wasm_cg_push_instance_lvalue(cg, rt, instance_local);
    717   kit_cg_field(cg, rt->passive_elem_field[elemidx]);
    718 }
    719 
    720 static void wasm_cg_push_passive_elem_storage_array_lvalue(
    721     KitCg* cg, const WasmCgRuntime* rt, KitCgLocal instance_local,
    722     uint32_t elemidx) {
    723   wasm_cg_push_instance_lvalue(cg, rt, instance_local);
    724   kit_cg_field(cg, rt->passive_elem_storage_field[elemidx]);
    725 }
    726 
    727 static void wasm_cg_memory_check(KitCompiler* c, KitCg* cg,
    728                                  WasmCgBuiltinTypes b, const WasmModule* m,
    729                                  const WasmCgRuntime* rt,
    730                                  KitCgLocal instance_local,
    731                                  const WasmInsn* in) {
    732   uint32_t width = wasm_mem_width(in->kind);
    733   uint64_t end;
    734   KitCgLabel ok = kit_cg_label_new(cg);
    735   uint64_t max_pages = m->memories[in->memidx].has_max
    736                            ? m->memories[in->memidx].max_pages
    737                            : m->memories[in->memidx].min_pages;
    738   if (in->offset64 > UINT64_MAX - (uint64_t)width) {
    739     wasm_cg_trap_bounds(cg, rt);
    740     return;
    741   }
    742   end = in->offset64 + (uint64_t)width;
    743   if (max_pages > UINT64_MAX / 65536u || end > max_pages * 65536u) {
    744     wasm_cg_trap_bounds(cg, rt);
    745     return;
    746   }
    747   (void)c;
    748   kit_cg_dup(cg);
    749   wasm_cg_push_instance_ptr(cg, rt, instance_local);
    750   kit_cg_deref(
    751       cg, (int64_t)(rt->memory_offset[in->memidx] + rt->memory_pages_offset));
    752   kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
    753   kit_cg_push_int(cg, 65536u, b.id[KIT_CG_BUILTIN_I64]);
    754   kit_cg_int_binop(cg, KIT_CG_INT_MUL, 0);
    755   kit_cg_push_int(cg, end, b.id[KIT_CG_BUILTIN_I64]);
    756   kit_cg_int_binop(cg, KIT_CG_INT_SUB, 0);
    757   if (!m->memories[in->memidx].is64) {
    758     kit_cg_swap(cg);
    759     kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
    760     kit_cg_swap(cg);
    761   }
    762   kit_cg_int_cmp(cg, KIT_CG_INT_LE_U);
    763   kit_cg_branch_true(cg, ok);
    764   wasm_cg_trap_bounds(cg, rt);
    765   kit_cg_label_place(cg, ok);
    766 }
    767 
    768 /* Compute the absolute address (data_ptr + addr_on_tos + offset) as a
    769  * pointer rvalue. Stack: [addr] -> [void*]. */
    770 static void wasm_cg_memory_addr_from_tos(KitCg* cg, WasmCgBuiltinTypes b,
    771                                          const WasmCgRuntime* rt,
    772                                          const WasmModule* m,
    773                                          KitCgLocal instance_local,
    774                                          uint32_t memidx, uint64_t offset) {
    775   KitCgTypeId i64_ty = b.id[KIT_CG_BUILTIN_I64];
    776   /* TOS: [addr]. */
    777   if (!m->memories[memidx].is64) kit_cg_zext(cg, i64_ty);
    778   if (offset) {
    779     kit_cg_push_int(cg, offset, i64_ty);
    780     kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    781   }
    782   /* TOS: [addr + offset]. */
    783   wasm_cg_push_memory_data_ptr(cg, rt, instance_local, memidx);
    784   kit_cg_ptr_to_int(cg, i64_ty);
    785   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    786   kit_cg_int_to_ptr(cg, rt->i8_ptr_ty);
    787 }
    788 
    789 static void wasm_cg_rotate(KitCompiler* c, KitCg* cg, WasmCgBuiltinTypes b,
    790                            WasmValType vt, int right) {
    791   KitCgTypeId ty = wasm_cg_type(c, b, vt);
    792   KitCgMemAccess mem = wasm_cg_mem(c, b, vt);
    793   KitCgLocalAttrs attrs;
    794   KitCgLocal lhs, rhs;
    795   uint32_t mask = vt == WASM_VAL_I32 ? 31u : 63u;
    796   memset(&attrs, 0, sizeof attrs);
    797   attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
    798   rhs = kit_cg_local(cg, ty, attrs);
    799   lhs = kit_cg_local(cg, ty, attrs);
    800   kit_cg_push_local(cg, rhs);
    801   kit_cg_swap(cg);
    802   kit_cg_store(cg, mem);
    803   kit_cg_push_local(cg, lhs);
    804   kit_cg_swap(cg);
    805   kit_cg_store(cg, mem);
    806 
    807   kit_cg_push_local(cg, lhs);
    808   kit_cg_load(cg, mem);
    809   kit_cg_push_local(cg, rhs);
    810   kit_cg_load(cg, mem);
    811   kit_cg_push_int(cg, mask, ty);
    812   kit_cg_int_binop(cg, KIT_CG_INT_AND, 0);
    813   kit_cg_int_binop(cg, right ? KIT_CG_INT_LSHR : KIT_CG_INT_SHL, 0);
    814 
    815   kit_cg_push_local(cg, lhs);
    816   kit_cg_load(cg, mem);
    817   kit_cg_push_int(cg, 0, ty);
    818   kit_cg_push_local(cg, rhs);
    819   kit_cg_load(cg, mem);
    820   kit_cg_int_binop(cg, KIT_CG_INT_SUB, 0);
    821   kit_cg_push_int(cg, mask, ty);
    822   kit_cg_int_binop(cg, KIT_CG_INT_AND, 0);
    823   kit_cg_int_binop(cg, right ? KIT_CG_INT_SHL : KIT_CG_INT_LSHR, 0);
    824   kit_cg_int_binop(cg, KIT_CG_INT_OR, 0);
    825 }
    826 
    827 static void wasm_cg_checked_divrem(KitCompiler* c, KitCg* cg,
    828                                    WasmCgBuiltinTypes b,
    829                                    const WasmCgRuntime* rt, WasmValType vt,
    830                                    KitCgIntBinOp op) {
    831   KitCgTypeId ty = wasm_cg_type(c, b, vt);
    832   KitCgMemAccess mem = wasm_cg_mem(c, b, vt);
    833   KitCgLocalAttrs attrs;
    834   KitCgLocal lhs, rhs;
    835   KitCgLabel ok = kit_cg_label_new(cg);
    836   memset(&attrs, 0, sizeof attrs);
    837   attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
    838   rhs = kit_cg_local(cg, ty, attrs);
    839   lhs = kit_cg_local(cg, ty, attrs);
    840   kit_cg_push_local(cg, rhs);
    841   kit_cg_swap(cg);
    842   kit_cg_store(cg, mem);
    843   kit_cg_push_local(cg, lhs);
    844   kit_cg_swap(cg);
    845   kit_cg_store(cg, mem);
    846   kit_cg_push_local(cg, rhs);
    847   kit_cg_load(cg, mem);
    848   kit_cg_push_int(cg, 0, ty);
    849   kit_cg_int_cmp(cg, KIT_CG_INT_NE);
    850   kit_cg_branch_true(cg, ok);
    851   wasm_cg_trap_division(cg, rt);
    852   kit_cg_label_place(cg, ok);
    853   if (op == KIT_CG_INT_SDIV) {
    854     KitCgLabel no_overflow = kit_cg_label_new(cg);
    855     uint64_t min_val = vt == WASM_VAL_I32 ? UINT64_C(0x80000000)
    856                                           : UINT64_C(0x8000000000000000);
    857     kit_cg_push_local(cg, lhs);
    858     kit_cg_load(cg, mem);
    859     kit_cg_push_int(cg, min_val, ty);
    860     kit_cg_int_cmp(cg, KIT_CG_INT_NE);
    861     kit_cg_branch_true(cg, no_overflow);
    862     kit_cg_push_local(cg, rhs);
    863     kit_cg_load(cg, mem);
    864     kit_cg_push_int(cg, UINT64_MAX, ty);
    865     kit_cg_int_cmp(cg, KIT_CG_INT_NE);
    866     kit_cg_branch_true(cg, no_overflow);
    867     wasm_cg_trap_division(cg, rt);
    868     kit_cg_label_place(cg, no_overflow);
    869   }
    870   kit_cg_push_local(cg, lhs);
    871   kit_cg_load(cg, mem);
    872   kit_cg_push_local(cg, rhs);
    873   kit_cg_load(cg, mem);
    874   kit_cg_int_binop(cg, op, 0);
    875 }
    876 
    877 static void wasm_cg_checked_trunc(KitCompiler* c, KitCg* cg,
    878                                   WasmCgBuiltinTypes b, const WasmCgRuntime* rt,
    879                                   WasmValType src, WasmValType dst,
    880                                   int is_unsigned) {
    881   KitCgTypeId src_ty = wasm_cg_type(c, b, src);
    882   KitCgTypeId dst_ty = wasm_cg_type(c, b, dst);
    883   KitCgTypeId bit_ty =
    884       b.id[src == WASM_VAL_F32 ? KIT_CG_BUILTIN_I32 : KIT_CG_BUILTIN_I64];
    885   KitCgMemAccess src_mem = wasm_cg_mem(c, b, src);
    886   KitCgMemAccess bit_mem = wasm_cg_mem_type(bit_ty);
    887   KitCgLocalAttrs attrs;
    888   KitCgLocal value, bits, abs_bits;
    889   uint64_t abs_mask =
    890       src == WASM_VAL_F32 ? UINT64_C(0x7fffffff) : UINT64_C(0x7fffffffffffffff);
    891   uint64_t sign_mask =
    892       src == WASM_VAL_F32 ? UINT64_C(0x80000000) : UINT64_C(0x8000000000000000);
    893   uint64_t inf_bits =
    894       src == WASM_VAL_F32 ? UINT64_C(0x7f800000) : UINT64_C(0x7ff0000000000000);
    895   uint64_t limit_bits;
    896   memset(&attrs, 0, sizeof attrs);
    897   attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
    898   value = kit_cg_local(cg, src_ty, attrs);
    899   bits = kit_cg_local(cg, bit_ty, attrs);
    900   abs_bits = kit_cg_local(cg, bit_ty, attrs);
    901   kit_cg_push_local(cg, value);
    902   kit_cg_swap(cg);
    903   kit_cg_store(cg, src_mem);
    904 
    905   kit_cg_push_local(cg, bits);
    906   kit_cg_push_local(cg, value);
    907   kit_cg_load(cg, src_mem);
    908   kit_cg_bitcast(cg, bit_ty);
    909   kit_cg_store(cg, bit_mem);
    910 
    911   kit_cg_push_local(cg, abs_bits);
    912   kit_cg_push_local(cg, bits);
    913   kit_cg_load(cg, bit_mem);
    914   kit_cg_push_int(cg, abs_mask, bit_ty);
    915   kit_cg_int_binop(cg, KIT_CG_INT_AND, 0);
    916   kit_cg_store(cg, bit_mem);
    917 
    918   {
    919     KitCgLabel finite = kit_cg_label_new(cg);
    920     kit_cg_push_local(cg, abs_bits);
    921     kit_cg_load(cg, bit_mem);
    922     kit_cg_push_int(cg, inf_bits, bit_ty);
    923     kit_cg_int_cmp(cg, KIT_CG_INT_LE_U);
    924     kit_cg_branch_true(cg, finite);
    925     wasm_cg_trap_invalid_conversion(cg, rt);
    926     kit_cg_label_place(cg, finite);
    927   }
    928 
    929   if (src == WASM_VAL_F32) {
    930     if (dst == WASM_VAL_I32)
    931       limit_bits = is_unsigned ? UINT64_C(0x4f800000) : UINT64_C(0x4f000000);
    932     else
    933       limit_bits = is_unsigned ? UINT64_C(0x5f800000) : UINT64_C(0x5f000000);
    934   } else {
    935     if (dst == WASM_VAL_I32)
    936       limit_bits = is_unsigned ? UINT64_C(0x41f0000000000000)
    937                                : UINT64_C(0x41e0000000000000);
    938     else
    939       limit_bits = is_unsigned ? UINT64_C(0x43f0000000000000)
    940                                : UINT64_C(0x43e0000000000000);
    941   }
    942 
    943   if (is_unsigned) {
    944     KitCgLabel nonnegative = kit_cg_label_new(cg);
    945     kit_cg_push_local(cg, abs_bits);
    946     kit_cg_load(cg, bit_mem);
    947     kit_cg_push_int(cg, 0, bit_ty);
    948     kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
    949     kit_cg_branch_true(cg, nonnegative);
    950     kit_cg_push_local(cg, bits);
    951     kit_cg_load(cg, bit_mem);
    952     kit_cg_push_int(cg, sign_mask, bit_ty);
    953     kit_cg_int_cmp(cg, KIT_CG_INT_LT_U);
    954     kit_cg_branch_true(cg, nonnegative);
    955     wasm_cg_trap_invalid_conversion(cg, rt);
    956     kit_cg_label_place(cg, nonnegative);
    957 
    958     {
    959       KitCgLabel in_range = kit_cg_label_new(cg);
    960       kit_cg_push_local(cg, abs_bits);
    961       kit_cg_load(cg, bit_mem);
    962       kit_cg_push_int(cg, limit_bits, bit_ty);
    963       kit_cg_int_cmp(cg, KIT_CG_INT_LT_U);
    964       kit_cg_branch_true(cg, in_range);
    965       wasm_cg_trap_invalid_conversion(cg, rt);
    966       kit_cg_label_place(cg, in_range);
    967     }
    968   } else {
    969     KitCgLabel negative = kit_cg_label_new(cg);
    970     KitCgLabel in_range = kit_cg_label_new(cg);
    971     kit_cg_push_local(cg, bits);
    972     kit_cg_load(cg, bit_mem);
    973     kit_cg_push_int(cg, sign_mask, bit_ty);
    974     kit_cg_int_cmp(cg, KIT_CG_INT_GE_U);
    975     kit_cg_branch_true(cg, negative);
    976     kit_cg_push_local(cg, abs_bits);
    977     kit_cg_load(cg, bit_mem);
    978     kit_cg_push_int(cg, limit_bits, bit_ty);
    979     kit_cg_int_cmp(cg, KIT_CG_INT_LT_U);
    980     kit_cg_branch_true(cg, in_range);
    981     wasm_cg_trap_invalid_conversion(cg, rt);
    982     kit_cg_label_place(cg, negative);
    983     kit_cg_push_local(cg, abs_bits);
    984     kit_cg_load(cg, bit_mem);
    985     kit_cg_push_int(cg, limit_bits, bit_ty);
    986     kit_cg_int_cmp(cg, KIT_CG_INT_LE_U);
    987     kit_cg_branch_true(cg, in_range);
    988     wasm_cg_trap_invalid_conversion(cg, rt);
    989     kit_cg_label_place(cg, in_range);
    990   }
    991 
    992   kit_cg_push_local(cg, value);
    993   kit_cg_load(cg, src_mem);
    994   if (is_unsigned)
    995     kit_cg_float_to_uint(cg, dst_ty, KIT_CG_ROUND_TOWARD_ZERO);
    996   else
    997     kit_cg_float_to_sint(cg, dst_ty, KIT_CG_ROUND_TOWARD_ZERO);
    998 }
    999 
   1000 static int wasm_fp_binop(uint8_t kind, KitCgFpBinOp* out) {
   1001   switch (kind) {
   1002     case WASM_INSN_F32_ADD:
   1003     case WASM_INSN_F64_ADD:
   1004       *out = KIT_CG_FP_ADD;
   1005       return 1;
   1006     case WASM_INSN_F32_SUB:
   1007     case WASM_INSN_F64_SUB:
   1008       *out = KIT_CG_FP_SUB;
   1009       return 1;
   1010     case WASM_INSN_F32_MUL:
   1011     case WASM_INSN_F64_MUL:
   1012       *out = KIT_CG_FP_MUL;
   1013       return 1;
   1014     case WASM_INSN_F32_DIV:
   1015     case WASM_INSN_F64_DIV:
   1016       *out = KIT_CG_FP_DIV;
   1017       return 1;
   1018     default:
   1019       return 0;
   1020   }
   1021 }
   1022 
   1023 static int wasm_fp_cmp_op(uint8_t kind, KitCgFpCmpOp* out) {
   1024   switch (kind) {
   1025     case WASM_INSN_F32_EQ:
   1026     case WASM_INSN_F64_EQ:
   1027       *out = KIT_CG_FP_OEQ;
   1028       return 1;
   1029     case WASM_INSN_F32_NE:
   1030     case WASM_INSN_F64_NE:
   1031       /* wasm f.ne is the UNORDERED not-equal: true when a != b OR either
   1032        * operand is NaN. Map to UNE, not ONE (ordered, false on NaN). */
   1033       *out = KIT_CG_FP_UNE;
   1034       return 1;
   1035     case WASM_INSN_F32_LT:
   1036     case WASM_INSN_F64_LT:
   1037       *out = KIT_CG_FP_OLT;
   1038       return 1;
   1039     case WASM_INSN_F32_GT:
   1040     case WASM_INSN_F64_GT:
   1041       *out = KIT_CG_FP_OGT;
   1042       return 1;
   1043     case WASM_INSN_F32_LE:
   1044     case WASM_INSN_F64_LE:
   1045       *out = KIT_CG_FP_OLE;
   1046       return 1;
   1047     case WASM_INSN_F32_GE:
   1048     case WASM_INSN_F64_GE:
   1049       *out = KIT_CG_FP_OGE;
   1050       return 1;
   1051     default:
   1052       return 0;
   1053   }
   1054 }
   1055 
   1056 static void wasm_cg_call_func(KitCompiler* c, KitCg* cg, WasmCgBuiltinTypes b,
   1057                               const WasmFunc* f, const WasmCgRuntime* rt,
   1058                               KitCgSym sym, KitCgTypeId func_type,
   1059                               KitCgLocal instance_local, uint32_t func_index,
   1060                               int must_tail, KitSrcLoc loc, KitArena* arena) {
   1061   KitCgLocalAttrs attrs;
   1062   KitCgLocal* args =
   1063       f->nparams ? kit_arena_array(arena, KitCgLocal, f->nparams) : NULL;
   1064   KitCgLocal callee = KIT_CG_LOCAL_NONE;
   1065   (void)loc;
   1066   memset(&attrs, 0, sizeof attrs);
   1067   attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   1068   for (uint32_t p = 0; p < f->nparams; ++p) {
   1069     uint32_t param = f->nparams - 1u - p;
   1070     args[param] = kit_cg_local(cg, wasm_cg_type(c, b, f->params[param]), attrs);
   1071     kit_cg_push_local(cg, args[param]);
   1072     kit_cg_swap(cg);
   1073     kit_cg_store(cg, wasm_cg_mem(c, b, f->params[param]));
   1074   }
   1075   if (f->is_import) {
   1076     KitCgLabel ok = kit_cg_label_new(cg);
   1077     callee = kit_cg_local(cg, rt->void_ptr_ty, attrs);
   1078     kit_cg_push_local(cg, callee);
   1079     wasm_cg_push_import_func_ptr(cg, rt, instance_local, func_index);
   1080     kit_cg_store(cg, wasm_cg_mem_type(rt->void_ptr_ty));
   1081     kit_cg_push_local(cg, callee);
   1082     kit_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
   1083     kit_cg_push_null(cg, rt->void_ptr_ty);
   1084     kit_cg_int_cmp(cg, KIT_CG_INT_NE);
   1085     kit_cg_branch_true(cg, ok);
   1086     wasm_cg_trap_table(cg, rt);
   1087     kit_cg_label_place(cg, ok);
   1088     kit_cg_push_local(cg, callee);
   1089     kit_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
   1090     kit_cg_bitcast(cg, kit_cg_type_ptr(c, func_type, 0));
   1091   }
   1092   kit_cg_push_local(cg, instance_local);
   1093   kit_cg_load(cg, wasm_cg_mem_type(rt->instance_ptr_ty));
   1094   for (uint32_t p = 0; p < f->nparams; ++p) {
   1095     kit_cg_push_local(cg, args[p]);
   1096     kit_cg_load(cg, wasm_cg_mem(c, b, f->params[p]));
   1097   }
   1098   if (f->is_import)
   1099     kit_cg_call(cg, f->nparams + 1u, func_type,
   1100                 (KitCgCallAttrs){.tail = must_tail ? KIT_CG_TAIL_MUST
   1101                                                    : KIT_CG_TAIL_DEFAULT});
   1102   else
   1103     kit_cg_call_symbol(
   1104         cg, sym, f->nparams + 1u,
   1105         (KitCgCallAttrs){.tail = must_tail ? KIT_CG_TAIL_MUST
   1106                                            : KIT_CG_TAIL_DEFAULT});
   1107   if (must_tail) {
   1108     if (f->nresults) wasm_cg_push_zero(c, cg, b, f->results[0]);
   1109     kit_cg_unreachable(cg);
   1110   }
   1111 }
   1112 
   1113 /* Intern a NUL-terminated string as readonly const data and return its
   1114  * symbol. Each call mints a fresh symbol; the caller is responsible for
   1115  * deduplication if that matters. */
   1116 static KitCgSym wasm_cg_intern_cstr(KitCg* cg, WasmCgBuiltinTypes b,
   1117                                     const char* s) {
   1118   size_t len = 0;
   1119   while (s && s[len]) ++len;
   1120   return kit_cg_const_data(cg, (const uint8_t*)(s ? s : ""), len + 1u, 1,
   1121                            b.id[KIT_CG_BUILTIN_I8]);
   1122 }
   1123 
   1124 /* Emit the host-import metadata symbols read by kit_wasm_bind_host_imports.
   1125  * Layout matches runtime_abi.h. When the module has no imports, only the
   1126  * count (=0) is emitted; descriptor/type arrays are omitted so the binder can
   1127  * no-op early via kit_jit_lookup returning NULL. */
   1128 static void wasm_cg_emit_host_import_metadata(KitCompiler* c, KitCg* cg,
   1129                                               WasmCgBuiltinTypes b,
   1130                                               const WasmModule* m,
   1131                                               const WasmCgRuntime* rt,
   1132                                               KitArena* arena) {
   1133   KitCgTypeId u32_ty = b.id[KIT_CG_BUILTIN_I32];
   1134   KitCgTypeId u8_ty = b.id[KIT_CG_BUILTIN_I8];
   1135   KitCgTypeId ptr_ty = rt->void_ptr_ty;
   1136   uint32_t ptr_size = (uint32_t)kit_cg_type_size(c, ptr_ty);
   1137   uint32_t ptr_align = ptr_size ? ptr_size : 8u;
   1138   uint32_t nimports = 0;
   1139   uint32_t nfunc_imports = 0;
   1140   uint32_t nmemory_imports = 0;
   1141   uint32_t ntable_imports = 0;
   1142   uint32_t nglobal_imports = 0;
   1143   uint32_t desc_size = 2u * ptr_size + 16u;
   1144   uint32_t type_desc_size =
   1145       2u * ptr_size + 8u + (ptr_align > 4u ? 2u * (ptr_align - 4u) : 0u);
   1146   KitCgSym nimports_sym, imports_sym;
   1147   KitCgDecl decl;
   1148   KitCgDataDefAttrs data_attrs;
   1149   uint32_t i;
   1150 
   1151   for (i = 0; i < m->nfuncs; ++i) {
   1152     if (!m->funcs[i].is_import) continue;
   1153     nimports++;
   1154     nfunc_imports++;
   1155   }
   1156   for (i = 0; i < m->nmemories; ++i) {
   1157     if (!m->memories[i].is_import) continue;
   1158     nimports++;
   1159     nmemory_imports++;
   1160   }
   1161   for (i = 0; i < m->ntables; ++i) {
   1162     if (!m->tables[i].is_import) continue;
   1163     nimports++;
   1164     ntable_imports++;
   1165   }
   1166   for (i = 0; i < m->nglobals; ++i) {
   1167     if (!m->globals[i].is_import) continue;
   1168     nimports++;
   1169     nglobal_imports++;
   1170   }
   1171 
   1172   /* Always emit the count symbol so the binder can read it unconditionally.
   1173    * If zero, the descriptor/type arrays are omitted. */
   1174   memset(&decl, 0, sizeof decl);
   1175   decl.kind = KIT_CG_DECL_OBJECT;
   1176   decl.linkage_name = kit_cg_c_linkage_name(
   1177       c, kit_sym_intern(c, KIT_SLICE_LIT("__kit_wasm_nimports")));
   1178   decl.display_name = decl.linkage_name;
   1179   decl.type = u32_ty;
   1180   decl.sym.bind = KIT_SB_GLOBAL;
   1181   decl.as.object.flags = KIT_CG_OBJ_READONLY;
   1182   nimports_sym = kit_cg_decl(cg, decl);
   1183   if (!nimports_sym)
   1184     wasm_error(c, wasm_loc(0, 0),
   1185                "wasm: failed to declare __kit_wasm_nimports");
   1186 
   1187   memset(&data_attrs, 0, sizeof data_attrs);
   1188   data_attrs.flags = KIT_CG_DATADEF_READONLY;
   1189   data_attrs.align = 4;
   1190   kit_cg_data_begin(cg, nimports_sym, data_attrs);
   1191   kit_cg_data_int(cg, (uint64_t)nimports, u32_ty);
   1192   kit_cg_data_end(cg);
   1193 
   1194   if (!nimports) return;
   1195 
   1196   /* Walk imports once, build sym handles for module/field strings, capture
   1197    * each import's kind-specific descriptor index and slot offset. Function
   1198    * import signatures are deduplicated into __kit_wasm_types; the emitted
   1199    * __kit_wasm_nfunc_import_types count lets the binder validate the compact
   1200    * descriptor indexes before reading that table. */
   1201   typedef struct WasmImportEmit {
   1202     KitCgSym module_sym;
   1203     KitCgSym field_sym;
   1204     uint32_t kind;
   1205     uint32_t desc_index;
   1206     uint32_t slot_offset;
   1207   } WasmImportEmit;
   1208   WasmImportEmit* descs = kit_arena_zarray(arena, WasmImportEmit, nimports);
   1209   KitWasmMemoryImportDesc* memory_descs =
   1210       nmemory_imports
   1211           ? kit_arena_zarray(arena, KitWasmMemoryImportDesc, nmemory_imports)
   1212           : NULL;
   1213   KitWasmTableImportDesc* table_descs =
   1214       ntable_imports
   1215           ? kit_arena_zarray(arena, KitWasmTableImportDesc, ntable_imports)
   1216           : NULL;
   1217   KitWasmGlobalImportDesc* global_descs =
   1218       nglobal_imports
   1219           ? kit_arena_zarray(arena, KitWasmGlobalImportDesc, nglobal_imports)
   1220           : NULL;
   1221   uint32_t* type_remap =
   1222       nfunc_imports
   1223           ? kit_arena_zarray(arena, uint32_t, m->ntypes ? m->ntypes : 1u)
   1224           : NULL;
   1225   uint32_t* local_to_module =
   1226       nfunc_imports ? kit_arena_zarray(arena, uint32_t, nfunc_imports) : NULL;
   1227   uint32_t ntypes = 0;
   1228   uint32_t d = 0;
   1229   uint32_t mem_d = 0;
   1230   uint32_t table_d = 0;
   1231   uint32_t global_d = 0;
   1232   for (i = 0; type_remap && i < m->ntypes; ++i) type_remap[i] = UINT32_MAX;
   1233   for (i = 0; i < m->nfuncs; ++i) {
   1234     const WasmFunc* f = &m->funcs[i];
   1235     uint64_t slot_off;
   1236     uint32_t module_typeidx;
   1237     if (!f->is_import) continue;
   1238     module_typeidx = f->typeidx;
   1239     if (module_typeidx >= m->ntypes) {
   1240       wasm_error(c, f->loc, "wasm: import typeidx out of range");
   1241       return;
   1242     }
   1243     if (type_remap[module_typeidx] == UINT32_MAX) {
   1244       type_remap[module_typeidx] = ntypes;
   1245       local_to_module[ntypes] = module_typeidx;
   1246       ntypes++;
   1247     }
   1248     descs[d].module_sym =
   1249         wasm_cg_intern_cstr(cg, b, f->import_module ? f->import_module : "");
   1250     descs[d].field_sym =
   1251         wasm_cg_intern_cstr(cg, b, f->import_name ? f->import_name : "");
   1252     descs[d].kind = KIT_WASM_IMPORT_FUNC;
   1253     descs[d].desc_index = type_remap[module_typeidx];
   1254     slot_off = rt->func_import_offset[i];
   1255     if (slot_off > UINT32_MAX) {
   1256       wasm_error(c, f->loc, "wasm: import slot offset exceeds u32");
   1257       return;
   1258     }
   1259     descs[d].slot_offset = (uint32_t)slot_off;
   1260     d++;
   1261   }
   1262   for (i = 0; i < m->nmemories; ++i) {
   1263     const WasmMemory* mem = &m->memories[i];
   1264     uint64_t max_pages;
   1265     uint32_t flags;
   1266     if (!mem->is_import) continue;
   1267     max_pages = mem->has_max ? mem->max_pages : mem->min_pages;
   1268     flags = (mem->shared ? KIT_WASM_MEMORY_SHARED : 0u) |
   1269             (mem->is64 ? KIT_WASM_MEMORY_64 : 0u);
   1270     descs[d].module_sym = wasm_cg_intern_cstr(
   1271         cg, b, mem->import_module ? mem->import_module : "");
   1272     descs[d].field_sym =
   1273         wasm_cg_intern_cstr(cg, b, mem->import_name ? mem->import_name : "");
   1274     descs[d].kind = KIT_WASM_IMPORT_MEMORY;
   1275     descs[d].desc_index = mem_d;
   1276     if (rt->memory_offset[i] > UINT32_MAX) {
   1277       wasm_error(c, wasm_loc(0, 0), "wasm: memory import slot exceeds u32");
   1278       return;
   1279     }
   1280     descs[d].slot_offset = (uint32_t)rt->memory_offset[i];
   1281     memory_descs[mem_d].min_pages = mem->min_pages;
   1282     memory_descs[mem_d].max_pages = max_pages;
   1283     memory_descs[mem_d].flags = flags;
   1284     memory_descs[mem_d].has_max = mem->has_max ? 1u : 0u;
   1285     mem_d++;
   1286     d++;
   1287   }
   1288   for (i = 0; i < m->ntables; ++i) {
   1289     const WasmTable* t = &m->tables[i];
   1290     uint32_t max;
   1291     if (!t->is_import) continue;
   1292     max = t->has_max ? t->max : t->min;
   1293     descs[d].module_sym =
   1294         wasm_cg_intern_cstr(cg, b, t->import_module ? t->import_module : "");
   1295     descs[d].field_sym =
   1296         wasm_cg_intern_cstr(cg, b, t->import_name ? t->import_name : "");
   1297     descs[d].kind = KIT_WASM_IMPORT_TABLE;
   1298     descs[d].desc_index = table_d;
   1299     if (rt->table_offset[i] > UINT32_MAX) {
   1300       wasm_error(c, wasm_loc(0, 0), "wasm: table import slot exceeds u32");
   1301       return;
   1302     }
   1303     descs[d].slot_offset = (uint32_t)rt->table_offset[i];
   1304     table_descs[table_d].elem_type = (uint32_t)t->elem_type;
   1305     table_descs[table_d].min = t->min;
   1306     table_descs[table_d].max = max;
   1307     table_descs[table_d].has_max = t->has_max ? 1u : 0u;
   1308     table_d++;
   1309     d++;
   1310   }
   1311   for (i = 0; i < m->nglobals; ++i) {
   1312     const WasmGlobal* g = &m->globals[i];
   1313     if (!g->is_import) continue;
   1314     descs[d].module_sym =
   1315         wasm_cg_intern_cstr(cg, b, g->import_module ? g->import_module : "");
   1316     descs[d].field_sym =
   1317         wasm_cg_intern_cstr(cg, b, g->import_name ? g->import_name : "");
   1318     descs[d].kind = KIT_WASM_IMPORT_GLOBAL;
   1319     descs[d].desc_index = global_d;
   1320     if (rt->global_offset[i] > UINT32_MAX) {
   1321       wasm_error(c, g->loc, "wasm: global import slot exceeds u32");
   1322       return;
   1323     }
   1324     descs[d].slot_offset = (uint32_t)rt->global_offset[i];
   1325     global_descs[global_d].type = (uint32_t)g->type;
   1326     global_descs[global_d].mutable_ = g->mutable_ ? 1u : 0u;
   1327     global_d++;
   1328     d++;
   1329   }
   1330 
   1331   /* __kit_wasm_types: array of KitWasmTypeDesc.
   1332    *   { const u8* params; u32 nparams; const u8* results; u32 nresults; }
   1333    * Each distinct imported function signature gets one entry. Param/result
   1334    * bytes are emitted as interned const u8 arrays using raw WasmValType
   1335    * bytes. */
   1336   if (ntypes) {
   1337     KitCgSym nfunc_import_types_sym;
   1338     KitCgSym types_sym;
   1339     KitCgSym* param_syms = kit_arena_zarray(arena, KitCgSym, ntypes);
   1340     KitCgSym* result_syms = kit_arena_zarray(arena, KitCgSym, ntypes);
   1341     KitCgTypeId types_array_ty =
   1342         kit_cg_type_array(c, u8_ty, (uint64_t)type_desc_size * ntypes);
   1343     for (uint32_t k = 0; k < ntypes; ++k) {
   1344       const WasmFuncType* t = &m->types[local_to_module[k]];
   1345       uint8_t* pbuf =
   1346           t->nparams ? kit_arena_array(arena, uint8_t, t->nparams) : NULL;
   1347       uint8_t* rbuf =
   1348           t->nresults ? kit_arena_array(arena, uint8_t, t->nresults) : NULL;
   1349       for (uint32_t p = 0; p < t->nparams; ++p) pbuf[p] = (uint8_t)t->params[p];
   1350       for (uint32_t r = 0; r < t->nresults; ++r)
   1351         rbuf[r] = (uint8_t)t->results[r];
   1352       param_syms[k] = t->nparams
   1353                           ? kit_cg_const_data(cg, pbuf, t->nparams, 1, u8_ty)
   1354                           : (KitCgSym)0;
   1355       result_syms[k] = t->nresults
   1356                            ? kit_cg_const_data(cg, rbuf, t->nresults, 1, u8_ty)
   1357                            : (KitCgSym)0;
   1358     }
   1359     memset(&decl, 0, sizeof decl);
   1360     decl.kind = KIT_CG_DECL_OBJECT;
   1361     decl.linkage_name = kit_cg_c_linkage_name(
   1362         c, kit_sym_intern(c, KIT_SLICE_LIT("__kit_wasm_nfunc_import_types")));
   1363     decl.display_name = decl.linkage_name;
   1364     decl.type = u32_ty;
   1365     decl.sym.bind = KIT_SB_GLOBAL;
   1366     decl.as.object.flags = KIT_CG_OBJ_READONLY;
   1367     nfunc_import_types_sym = kit_cg_decl(cg, decl);
   1368     if (!nfunc_import_types_sym)
   1369       wasm_error(c, wasm_loc(0, 0),
   1370                  "wasm: failed to declare __kit_wasm_nfunc_import_types");
   1371     memset(&data_attrs, 0, sizeof data_attrs);
   1372     data_attrs.flags = KIT_CG_DATADEF_READONLY;
   1373     data_attrs.align = 4;
   1374     kit_cg_data_begin(cg, nfunc_import_types_sym, data_attrs);
   1375     kit_cg_data_int(cg, (uint64_t)ntypes, u32_ty);
   1376     kit_cg_data_end(cg);
   1377 
   1378     memset(&decl, 0, sizeof decl);
   1379     decl.kind = KIT_CG_DECL_OBJECT;
   1380     decl.linkage_name = kit_cg_c_linkage_name(
   1381         c, kit_sym_intern(c, KIT_SLICE_LIT("__kit_wasm_types")));
   1382     decl.display_name = decl.linkage_name;
   1383     decl.type = types_array_ty;
   1384     decl.sym.bind = KIT_SB_GLOBAL;
   1385     decl.as.object.flags = KIT_CG_OBJ_READONLY;
   1386     types_sym = kit_cg_decl(cg, decl);
   1387     if (!types_sym)
   1388       wasm_error(c, wasm_loc(0, 0), "wasm: failed to declare __kit_wasm_types");
   1389     memset(&data_attrs, 0, sizeof data_attrs);
   1390     data_attrs.flags = KIT_CG_DATADEF_READONLY;
   1391     data_attrs.align = ptr_align;
   1392     kit_cg_data_begin(cg, types_sym, data_attrs);
   1393     for (uint32_t k = 0; k < ntypes; ++k) {
   1394       const WasmFuncType* t = &m->types[local_to_module[k]];
   1395       kit_cg_data_align(cg, ptr_align);
   1396       if (param_syms[k])
   1397         kit_cg_data_addr(cg, param_syms[k], 0, ptr_size, 0);
   1398       else
   1399         kit_cg_data_pad(cg, ptr_size, 0);
   1400       kit_cg_data_int(cg, (uint64_t)t->nparams, u32_ty);
   1401       /* Pad up to ptr alignment before next pointer field. */
   1402       if (ptr_align > 4) kit_cg_data_align(cg, ptr_align);
   1403       if (result_syms[k])
   1404         kit_cg_data_addr(cg, result_syms[k], 0, ptr_size, 0);
   1405       else
   1406         kit_cg_data_pad(cg, ptr_size, 0);
   1407       kit_cg_data_int(cg, (uint64_t)t->nresults, u32_ty);
   1408       if (ptr_align > 4) kit_cg_data_align(cg, ptr_align);
   1409     }
   1410     kit_cg_data_end(cg);
   1411   }
   1412 
   1413   if (nmemory_imports) {
   1414     KitCgSym memory_types_sym;
   1415     KitCgTypeId memory_array_ty = kit_cg_type_array(
   1416         c, u8_ty, (uint64_t)sizeof(KitWasmMemoryImportDesc) * nmemory_imports);
   1417     memset(&decl, 0, sizeof decl);
   1418     decl.kind = KIT_CG_DECL_OBJECT;
   1419     decl.linkage_name = kit_cg_c_linkage_name(
   1420         c, kit_sym_intern(c, KIT_SLICE_LIT("__kit_wasm_memory_import_types")));
   1421     decl.display_name = decl.linkage_name;
   1422     decl.type = memory_array_ty;
   1423     decl.sym.bind = KIT_SB_GLOBAL;
   1424     decl.as.object.flags = KIT_CG_OBJ_READONLY;
   1425     memory_types_sym = kit_cg_decl(cg, decl);
   1426     if (!memory_types_sym)
   1427       wasm_error(c, wasm_loc(0, 0),
   1428                  "wasm: failed to declare __kit_wasm_memory_import_types");
   1429     memset(&data_attrs, 0, sizeof data_attrs);
   1430     data_attrs.flags = KIT_CG_DATADEF_READONLY;
   1431     data_attrs.align = 8;
   1432     kit_cg_data_begin(cg, memory_types_sym, data_attrs);
   1433     for (uint32_t k = 0; k < nmemory_imports; ++k) {
   1434       kit_cg_data_align(cg, 8);
   1435       kit_cg_data_int(cg, memory_descs[k].min_pages, b.id[KIT_CG_BUILTIN_I64]);
   1436       kit_cg_data_int(cg, memory_descs[k].max_pages, b.id[KIT_CG_BUILTIN_I64]);
   1437       kit_cg_data_int(cg, memory_descs[k].flags, u32_ty);
   1438       kit_cg_data_int(cg, memory_descs[k].has_max, u32_ty);
   1439     }
   1440     kit_cg_data_end(cg);
   1441   }
   1442 
   1443   if (ntable_imports) {
   1444     KitCgSym table_types_sym;
   1445     KitCgTypeId table_array_ty = kit_cg_type_array(
   1446         c, u8_ty, (uint64_t)sizeof(KitWasmTableImportDesc) * ntable_imports);
   1447     memset(&decl, 0, sizeof decl);
   1448     decl.kind = KIT_CG_DECL_OBJECT;
   1449     decl.linkage_name = kit_cg_c_linkage_name(
   1450         c, kit_sym_intern(c, KIT_SLICE_LIT("__kit_wasm_table_import_types")));
   1451     decl.display_name = decl.linkage_name;
   1452     decl.type = table_array_ty;
   1453     decl.sym.bind = KIT_SB_GLOBAL;
   1454     decl.as.object.flags = KIT_CG_OBJ_READONLY;
   1455     table_types_sym = kit_cg_decl(cg, decl);
   1456     if (!table_types_sym)
   1457       wasm_error(c, wasm_loc(0, 0),
   1458                  "wasm: failed to declare __kit_wasm_table_import_types");
   1459     memset(&data_attrs, 0, sizeof data_attrs);
   1460     data_attrs.flags = KIT_CG_DATADEF_READONLY;
   1461     data_attrs.align = 4;
   1462     kit_cg_data_begin(cg, table_types_sym, data_attrs);
   1463     for (uint32_t k = 0; k < ntable_imports; ++k) {
   1464       kit_cg_data_int(cg, table_descs[k].elem_type, u32_ty);
   1465       kit_cg_data_int(cg, table_descs[k].min, u32_ty);
   1466       kit_cg_data_int(cg, table_descs[k].max, u32_ty);
   1467       kit_cg_data_int(cg, table_descs[k].has_max, u32_ty);
   1468     }
   1469     kit_cg_data_end(cg);
   1470   }
   1471 
   1472   if (nglobal_imports) {
   1473     KitCgSym global_types_sym;
   1474     KitCgTypeId global_array_ty = kit_cg_type_array(
   1475         c, u8_ty, (uint64_t)sizeof(KitWasmGlobalImportDesc) * nglobal_imports);
   1476     memset(&decl, 0, sizeof decl);
   1477     decl.kind = KIT_CG_DECL_OBJECT;
   1478     decl.linkage_name = kit_cg_c_linkage_name(
   1479         c, kit_sym_intern(c, KIT_SLICE_LIT("__kit_wasm_global_import_types")));
   1480     decl.display_name = decl.linkage_name;
   1481     decl.type = global_array_ty;
   1482     decl.sym.bind = KIT_SB_GLOBAL;
   1483     decl.as.object.flags = KIT_CG_OBJ_READONLY;
   1484     global_types_sym = kit_cg_decl(cg, decl);
   1485     if (!global_types_sym)
   1486       wasm_error(c, wasm_loc(0, 0),
   1487                  "wasm: failed to declare __kit_wasm_global_import_types");
   1488     memset(&data_attrs, 0, sizeof data_attrs);
   1489     data_attrs.flags = KIT_CG_DATADEF_READONLY;
   1490     data_attrs.align = 4;
   1491     kit_cg_data_begin(cg, global_types_sym, data_attrs);
   1492     for (uint32_t k = 0; k < nglobal_imports; ++k) {
   1493       kit_cg_data_int(cg, global_descs[k].type, u32_ty);
   1494       kit_cg_data_int(cg, global_descs[k].mutable_, u32_ty);
   1495     }
   1496     kit_cg_data_end(cg);
   1497   }
   1498 
   1499   /* __kit_wasm_imports: array of KitWasmImportDesc. */
   1500   {
   1501     KitCgTypeId imports_array_ty =
   1502         kit_cg_type_array(c, u8_ty, (uint64_t)desc_size * nimports);
   1503     memset(&decl, 0, sizeof decl);
   1504     decl.kind = KIT_CG_DECL_OBJECT;
   1505     decl.linkage_name = kit_cg_c_linkage_name(
   1506         c, kit_sym_intern(c, KIT_SLICE_LIT("__kit_wasm_imports")));
   1507     decl.display_name = decl.linkage_name;
   1508     decl.type = imports_array_ty;
   1509     decl.sym.bind = KIT_SB_GLOBAL;
   1510     decl.as.object.flags = KIT_CG_OBJ_READONLY;
   1511     imports_sym = kit_cg_decl(cg, decl);
   1512     if (!imports_sym)
   1513       wasm_error(c, wasm_loc(0, 0),
   1514                  "wasm: failed to declare __kit_wasm_imports");
   1515     memset(&data_attrs, 0, sizeof data_attrs);
   1516     data_attrs.flags = KIT_CG_DATADEF_READONLY;
   1517     data_attrs.align = ptr_align;
   1518     kit_cg_data_begin(cg, imports_sym, data_attrs);
   1519     for (uint32_t k = 0; k < nimports; ++k) {
   1520       kit_cg_data_align(cg, ptr_align);
   1521       kit_cg_data_addr(cg, descs[k].module_sym, 0, ptr_size, 0);
   1522       kit_cg_data_addr(cg, descs[k].field_sym, 0, ptr_size, 0);
   1523       kit_cg_data_int(cg, (uint64_t)descs[k].kind, u32_ty);
   1524       kit_cg_data_int(cg, (uint64_t)descs[k].desc_index, u32_ty);
   1525       kit_cg_data_int(cg, (uint64_t)descs[k].slot_offset, u32_ty);
   1526       kit_cg_data_int(cg, 0, u32_ty);
   1527       if (ptr_align > 4) kit_cg_data_align(cg, ptr_align);
   1528     }
   1529     kit_cg_data_end(cg);
   1530   }
   1531 }
   1532 
   1533 /* Emit the runtime layout symbols read by kit_wasm_get_runtime_layout:
   1534  *
   1535  *   __kit_wasm_instance_size    uint64
   1536  *   __kit_wasm_nmemories        uint32
   1537  *   __kit_wasm_memory_layouts   KitWasmMemoryLayout[]
   1538  *
   1539  * The memory-layout array intentionally contains only fixed-width integers, so
   1540  * the host reader can consume it without target pointer-size ambiguity. */
   1541 static void wasm_cg_emit_runtime_layout_metadata(KitCompiler* c, KitCg* cg,
   1542                                                  WasmCgBuiltinTypes b,
   1543                                                  const WasmModule* m,
   1544                                                  const WasmCgRuntime* rt) {
   1545   KitCgTypeId u8_ty = b.id[KIT_CG_BUILTIN_I8];
   1546   KitCgTypeId u32_ty = b.id[KIT_CG_BUILTIN_I32];
   1547   KitCgTypeId u64_ty = b.id[KIT_CG_BUILTIN_I64];
   1548   KitCgDecl decl;
   1549   KitCgDataDefAttrs data_attrs;
   1550   KitCgSym instance_size_sym;
   1551   KitCgSym nmemories_sym;
   1552   uint64_t instance_size = kit_cg_type_size(c, rt->instance_ty);
   1553 
   1554   memset(&decl, 0, sizeof decl);
   1555   decl.kind = KIT_CG_DECL_OBJECT;
   1556   decl.linkage_name = kit_cg_c_linkage_name(
   1557       c, kit_sym_intern(c, KIT_SLICE_LIT("__kit_wasm_instance_size")));
   1558   decl.display_name = decl.linkage_name;
   1559   decl.type = u64_ty;
   1560   decl.sym.bind = KIT_SB_GLOBAL;
   1561   decl.as.object.flags = KIT_CG_OBJ_READONLY;
   1562   instance_size_sym = kit_cg_decl(cg, decl);
   1563   if (!instance_size_sym)
   1564     wasm_error(c, wasm_loc(0, 0),
   1565                "wasm: failed to declare __kit_wasm_instance_size");
   1566   memset(&data_attrs, 0, sizeof data_attrs);
   1567   data_attrs.flags = KIT_CG_DATADEF_READONLY;
   1568   data_attrs.align = 8;
   1569   kit_cg_data_begin(cg, instance_size_sym, data_attrs);
   1570   kit_cg_data_int(cg, instance_size, u64_ty);
   1571   kit_cg_data_end(cg);
   1572 
   1573   memset(&decl, 0, sizeof decl);
   1574   decl.kind = KIT_CG_DECL_OBJECT;
   1575   decl.linkage_name = kit_cg_c_linkage_name(
   1576       c, kit_sym_intern(c, KIT_SLICE_LIT("__kit_wasm_nmemories")));
   1577   decl.display_name = decl.linkage_name;
   1578   decl.type = u32_ty;
   1579   decl.sym.bind = KIT_SB_GLOBAL;
   1580   decl.as.object.flags = KIT_CG_OBJ_READONLY;
   1581   nmemories_sym = kit_cg_decl(cg, decl);
   1582   if (!nmemories_sym)
   1583     wasm_error(c, wasm_loc(0, 0),
   1584                "wasm: failed to declare __kit_wasm_nmemories");
   1585   memset(&data_attrs, 0, sizeof data_attrs);
   1586   data_attrs.flags = KIT_CG_DATADEF_READONLY;
   1587   data_attrs.align = 4;
   1588   kit_cg_data_begin(cg, nmemories_sym, data_attrs);
   1589   kit_cg_data_int(cg, (uint64_t)m->nmemories, u32_ty);
   1590   kit_cg_data_end(cg);
   1591 
   1592   if (m->nmemories) {
   1593     const uint64_t layout_size = sizeof(KitWasmMemoryLayout);
   1594     KitCgTypeId layouts_array_ty =
   1595         kit_cg_type_array(c, u8_ty, layout_size * m->nmemories);
   1596     KitCgSym layouts_sym;
   1597     memset(&decl, 0, sizeof decl);
   1598     decl.kind = KIT_CG_DECL_OBJECT;
   1599     decl.linkage_name = kit_cg_c_linkage_name(
   1600         c, kit_sym_intern(c, KIT_SLICE_LIT("__kit_wasm_memory_layouts")));
   1601     decl.display_name = decl.linkage_name;
   1602     decl.type = layouts_array_ty;
   1603     decl.sym.bind = KIT_SB_GLOBAL;
   1604     decl.as.object.flags = KIT_CG_OBJ_READONLY;
   1605     layouts_sym = kit_cg_decl(cg, decl);
   1606     if (!layouts_sym)
   1607       wasm_error(c, wasm_loc(0, 0),
   1608                  "wasm: failed to declare __kit_wasm_memory_layouts");
   1609     memset(&data_attrs, 0, sizeof data_attrs);
   1610     data_attrs.flags = KIT_CG_DATADEF_READONLY;
   1611     data_attrs.align = 8;
   1612     kit_cg_data_begin(cg, layouts_sym, data_attrs);
   1613     for (uint32_t i = 0; i < m->nmemories; ++i) {
   1614       const WasmMemory* mem = &m->memories[i];
   1615       uint64_t max_pages = mem->has_max ? mem->max_pages : mem->min_pages;
   1616       uint32_t flags = (mem->shared ? KIT_WASM_MEMORY_SHARED : 0u) |
   1617                        (mem->is64 ? KIT_WASM_MEMORY_64 : 0u);
   1618       kit_cg_data_align(cg, 8);
   1619       kit_cg_data_int(cg, rt->memory_offset[i], u64_ty);
   1620       kit_cg_data_int(cg, mem->min_pages, u64_ty);
   1621       kit_cg_data_int(cg, max_pages, u64_ty);
   1622       kit_cg_data_int(cg, flags, u32_ty);
   1623       kit_cg_data_int(cg, 0, u32_ty);
   1624     }
   1625     kit_cg_data_end(cg);
   1626   }
   1627 }
   1628 
   1629 /* Bounds-check that addr + n <= size. addr/n/size are all treated as i64
   1630  * (caller zero-extends i32 inputs first). Traps on overflow or out-of-range
   1631  * via the rt bounds trap; falls through on success. */
   1632 static void wasm_cg_bulk_bounds_check(KitCg* cg, WasmCgBuiltinTypes b,
   1633                                       const WasmCgRuntime* rt,
   1634                                       KitCgLocal addr_local, KitCgLocal n_local,
   1635                                       KitCgLocal size_local) {
   1636   KitCgMemAccess i64_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I64]);
   1637   KitCgLabel ok = kit_cg_label_new(cg);
   1638   /* size - addr >= n  (unsigned), equivalently addr + n <= size with no
   1639    * overflow. First check size >= addr. */
   1640   KitCgLabel addr_ok = kit_cg_label_new(cg);
   1641   kit_cg_push_local(cg, size_local);
   1642   kit_cg_load(cg, i64_mem);
   1643   kit_cg_push_local(cg, addr_local);
   1644   kit_cg_load(cg, i64_mem);
   1645   kit_cg_int_cmp(cg, KIT_CG_INT_GE_U);
   1646   kit_cg_branch_true(cg, addr_ok);
   1647   wasm_cg_trap_bounds(cg, rt);
   1648   kit_cg_label_place(cg, addr_ok);
   1649   kit_cg_push_local(cg, size_local);
   1650   kit_cg_load(cg, i64_mem);
   1651   kit_cg_push_local(cg, addr_local);
   1652   kit_cg_load(cg, i64_mem);
   1653   kit_cg_int_binop(cg, KIT_CG_INT_SUB, 0);
   1654   kit_cg_push_local(cg, n_local);
   1655   kit_cg_load(cg, i64_mem);
   1656   kit_cg_int_cmp(cg, KIT_CG_INT_GE_U);
   1657   kit_cg_branch_true(cg, ok);
   1658   wasm_cg_trap_bounds(cg, rt);
   1659   kit_cg_label_place(cg, ok);
   1660 }
   1661 
   1662 /* Emit a byte-wise copy loop: copies n_local bytes from src_base+src_addr
   1663  * to dst_base+dst_addr. Handles overlap by choosing direction based on
   1664  * pointer comparison. Locals are pre-stored i64 values; src_base and
   1665  * dst_base are i8* values pre-stored in locals. */
   1666 static void wasm_cg_emit_byte_copy_loop(
   1667     KitCg* cg, WasmCgBuiltinTypes b, const WasmCgRuntime* rt,
   1668     KitCgLocal dst_base_local, KitCgLocal src_base_local,
   1669     KitCgLocal dst_addr_local, KitCgLocal src_addr_local, KitCgLocal n_local) {
   1670   KitCgMemAccess i64_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I64]);
   1671   KitCgMemAccess i8_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I8]);
   1672   KitCgMemAccess ptr_mem = wasm_cg_mem_type(rt->i8_ptr_ty);
   1673   KitCgLocalAttrs attrs;
   1674   KitCgLocal idx, dir;
   1675   KitCgLabel done = kit_cg_label_new(cg);
   1676   KitCgLabel loop_start = kit_cg_label_new(cg);
   1677   KitCgLabel forward = kit_cg_label_new(cg);
   1678   memset(&attrs, 0, sizeof attrs);
   1679   attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   1680   idx = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   1681   dir = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   1682   /* If n == 0, nothing to do. */
   1683   kit_cg_push_local(cg, n_local);
   1684   kit_cg_load(cg, i64_mem);
   1685   kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I64]);
   1686   kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   1687   kit_cg_branch_true(cg, done);
   1688 
   1689   /* Choose direction: forward if dst_addr <= src_addr OR if base pointers
   1690    * differ. Same-base + dst > src needs backward copy to handle overlap.
   1691    * We approximate with: dir = (dst_base == src_base && dst_addr > src_addr)
   1692    *                            ? backward : forward. */
   1693   kit_cg_push_local(cg, dir);
   1694   kit_cg_push_local(cg, dst_base_local);
   1695   kit_cg_load(cg, ptr_mem);
   1696   kit_cg_push_local(cg, src_base_local);
   1697   kit_cg_load(cg, ptr_mem);
   1698   kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   1699   kit_cg_store(cg, wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I32]));
   1700   kit_cg_push_local(cg, dir);
   1701   kit_cg_load(cg, wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I32]));
   1702   kit_cg_branch_false(cg, forward);
   1703   kit_cg_push_local(cg, dst_addr_local);
   1704   kit_cg_load(cg, i64_mem);
   1705   kit_cg_push_local(cg, src_addr_local);
   1706   kit_cg_load(cg, i64_mem);
   1707   kit_cg_int_cmp(cg, KIT_CG_INT_GT_U);
   1708   kit_cg_branch_false(cg, forward);
   1709   /* Backward loop: idx = n - 1, while idx >= 0 then idx-- (stop at 0). */
   1710   kit_cg_push_local(cg, idx);
   1711   kit_cg_push_local(cg, n_local);
   1712   kit_cg_load(cg, i64_mem);
   1713   kit_cg_store(cg, i64_mem);
   1714   {
   1715     KitCgLabel back_loop = kit_cg_label_new(cg);
   1716     kit_cg_label_place(cg, back_loop);
   1717     kit_cg_push_local(cg, idx);
   1718     kit_cg_load(cg, i64_mem);
   1719     kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I64]);
   1720     kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   1721     kit_cg_branch_true(cg, done);
   1722     /* idx-- */
   1723     kit_cg_push_local(cg, idx);
   1724     kit_cg_push_local(cg, idx);
   1725     kit_cg_load(cg, i64_mem);
   1726     kit_cg_push_int(cg, 1, b.id[KIT_CG_BUILTIN_I64]);
   1727     kit_cg_int_binop(cg, KIT_CG_INT_SUB, 0);
   1728     kit_cg_store(cg, i64_mem);
   1729     /* dst_base[dst_addr + idx] = src_base[src_addr + idx] */
   1730     kit_cg_push_local(cg, dst_base_local);
   1731     kit_cg_load(cg, ptr_mem);
   1732     kit_cg_push_local(cg, dst_addr_local);
   1733     kit_cg_load(cg, i64_mem);
   1734     kit_cg_push_local(cg, idx);
   1735     kit_cg_load(cg, i64_mem);
   1736     kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1737     kit_cg_elem(cg, 0);
   1738     kit_cg_push_local(cg, src_base_local);
   1739     kit_cg_load(cg, ptr_mem);
   1740     kit_cg_push_local(cg, src_addr_local);
   1741     kit_cg_load(cg, i64_mem);
   1742     kit_cg_push_local(cg, idx);
   1743     kit_cg_load(cg, i64_mem);
   1744     kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1745     kit_cg_elem(cg, 0);
   1746     kit_cg_load(cg, i8_mem);
   1747     kit_cg_store(cg, i8_mem);
   1748     kit_cg_jump(cg, back_loop);
   1749   }
   1750   kit_cg_label_place(cg, forward);
   1751   /* Forward loop: idx = 0; while idx < n then dst[idx]=src[idx]; idx++. */
   1752   kit_cg_push_local(cg, idx);
   1753   kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I64]);
   1754   kit_cg_store(cg, i64_mem);
   1755   kit_cg_label_place(cg, loop_start);
   1756   kit_cg_push_local(cg, idx);
   1757   kit_cg_load(cg, i64_mem);
   1758   kit_cg_push_local(cg, n_local);
   1759   kit_cg_load(cg, i64_mem);
   1760   kit_cg_int_cmp(cg, KIT_CG_INT_GE_U);
   1761   kit_cg_branch_true(cg, done);
   1762   kit_cg_push_local(cg, dst_base_local);
   1763   kit_cg_load(cg, ptr_mem);
   1764   kit_cg_push_local(cg, dst_addr_local);
   1765   kit_cg_load(cg, i64_mem);
   1766   kit_cg_push_local(cg, idx);
   1767   kit_cg_load(cg, i64_mem);
   1768   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1769   kit_cg_elem(cg, 0);
   1770   kit_cg_push_local(cg, src_base_local);
   1771   kit_cg_load(cg, ptr_mem);
   1772   kit_cg_push_local(cg, src_addr_local);
   1773   kit_cg_load(cg, i64_mem);
   1774   kit_cg_push_local(cg, idx);
   1775   kit_cg_load(cg, i64_mem);
   1776   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1777   kit_cg_elem(cg, 0);
   1778   kit_cg_load(cg, i8_mem);
   1779   kit_cg_store(cg, i8_mem);
   1780   kit_cg_push_local(cg, idx);
   1781   kit_cg_push_local(cg, idx);
   1782   kit_cg_load(cg, i64_mem);
   1783   kit_cg_push_int(cg, 1, b.id[KIT_CG_BUILTIN_I64]);
   1784   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1785   kit_cg_store(cg, i64_mem);
   1786   kit_cg_jump(cg, loop_start);
   1787   kit_cg_label_place(cg, done);
   1788 }
   1789 
   1790 /* Emit a byte-fill loop: writes (val & 0xff) into dst_base+dst_addr..+n. */
   1791 static void wasm_cg_emit_byte_fill_loop(KitCg* cg, WasmCgBuiltinTypes b,
   1792                                         const WasmCgRuntime* rt,
   1793                                         KitCgLocal dst_base_local,
   1794                                         KitCgLocal dst_addr_local,
   1795                                         KitCgLocal val_local,
   1796                                         KitCgLocal n_local) {
   1797   KitCgMemAccess i64_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I64]);
   1798   KitCgMemAccess i32_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I32]);
   1799   KitCgMemAccess i8_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I8]);
   1800   KitCgMemAccess ptr_mem = wasm_cg_mem_type(rt->i8_ptr_ty);
   1801   KitCgLocalAttrs attrs;
   1802   KitCgLocal idx;
   1803   KitCgLabel done = kit_cg_label_new(cg);
   1804   KitCgLabel loop_start = kit_cg_label_new(cg);
   1805   memset(&attrs, 0, sizeof attrs);
   1806   attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   1807   idx = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   1808   kit_cg_push_local(cg, idx);
   1809   kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I64]);
   1810   kit_cg_store(cg, i64_mem);
   1811   kit_cg_label_place(cg, loop_start);
   1812   kit_cg_push_local(cg, idx);
   1813   kit_cg_load(cg, i64_mem);
   1814   kit_cg_push_local(cg, n_local);
   1815   kit_cg_load(cg, i64_mem);
   1816   kit_cg_int_cmp(cg, KIT_CG_INT_GE_U);
   1817   kit_cg_branch_true(cg, done);
   1818   kit_cg_push_local(cg, dst_base_local);
   1819   kit_cg_load(cg, ptr_mem);
   1820   kit_cg_push_local(cg, dst_addr_local);
   1821   kit_cg_load(cg, i64_mem);
   1822   kit_cg_push_local(cg, idx);
   1823   kit_cg_load(cg, i64_mem);
   1824   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1825   kit_cg_elem(cg, 0);
   1826   kit_cg_push_local(cg, val_local);
   1827   kit_cg_load(cg, i32_mem);
   1828   kit_cg_trunc(cg, b.id[KIT_CG_BUILTIN_I8]);
   1829   kit_cg_store(cg, i8_mem);
   1830   kit_cg_push_local(cg, idx);
   1831   kit_cg_push_local(cg, idx);
   1832   kit_cg_load(cg, i64_mem);
   1833   kit_cg_push_int(cg, 1, b.id[KIT_CG_BUILTIN_I64]);
   1834   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1835   kit_cg_store(cg, i64_mem);
   1836   kit_cg_jump(cg, loop_start);
   1837   kit_cg_label_place(cg, done);
   1838 }
   1839 
   1840 /* Like wasm_cg_emit_byte_copy_loop but for table entries (struct-sized). */
   1841 static void wasm_cg_emit_table_copy_loop(
   1842     KitCompiler* c, KitCg* cg, WasmCgBuiltinTypes b, const WasmCgRuntime* rt,
   1843     KitCgLocal dst_base_local, KitCgLocal src_base_local,
   1844     KitCgLocal dst_idx_local, KitCgLocal src_idx_local, KitCgLocal n_local) {
   1845   KitCgMemAccess i64_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I64]);
   1846   KitCgMemAccess ptr_mem = wasm_cg_mem_type(rt->table_entry_ptr_ty);
   1847   KitCgMemAccess fn_mem = wasm_cg_mem_type(rt->void_ptr_ty);
   1848   KitCgMemAccess i32_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I32]);
   1849   KitCgLocalAttrs attrs;
   1850   KitCgLocal idx, dir;
   1851   KitCgLabel done = kit_cg_label_new(cg);
   1852   KitCgLabel forward = kit_cg_label_new(cg);
   1853   KitCgLabel loop_start = kit_cg_label_new(cg);
   1854   (void)c;
   1855   memset(&attrs, 0, sizeof attrs);
   1856   attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   1857   idx = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   1858   dir = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   1859   kit_cg_push_local(cg, n_local);
   1860   kit_cg_load(cg, i64_mem);
   1861   kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I64]);
   1862   kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   1863   kit_cg_branch_true(cg, done);
   1864   /* dir = (dst_base == src_base) ? (dst_idx > src_idx) : 0 */
   1865   kit_cg_push_local(cg, dir);
   1866   kit_cg_push_local(cg, dst_base_local);
   1867   kit_cg_load(cg, ptr_mem);
   1868   kit_cg_push_local(cg, src_base_local);
   1869   kit_cg_load(cg, ptr_mem);
   1870   kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   1871   kit_cg_store(cg, i32_mem);
   1872   kit_cg_push_local(cg, dir);
   1873   kit_cg_load(cg, i32_mem);
   1874   kit_cg_branch_false(cg, forward);
   1875   kit_cg_push_local(cg, dst_idx_local);
   1876   kit_cg_load(cg, i64_mem);
   1877   kit_cg_push_local(cg, src_idx_local);
   1878   kit_cg_load(cg, i64_mem);
   1879   kit_cg_int_cmp(cg, KIT_CG_INT_GT_U);
   1880   kit_cg_branch_false(cg, forward);
   1881   {
   1882     KitCgLabel back_loop = kit_cg_label_new(cg);
   1883     kit_cg_push_local(cg, idx);
   1884     kit_cg_push_local(cg, n_local);
   1885     kit_cg_load(cg, i64_mem);
   1886     kit_cg_store(cg, i64_mem);
   1887     kit_cg_label_place(cg, back_loop);
   1888     kit_cg_push_local(cg, idx);
   1889     kit_cg_load(cg, i64_mem);
   1890     kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I64]);
   1891     kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   1892     kit_cg_branch_true(cg, done);
   1893     kit_cg_push_local(cg, idx);
   1894     kit_cg_push_local(cg, idx);
   1895     kit_cg_load(cg, i64_mem);
   1896     kit_cg_push_int(cg, 1, b.id[KIT_CG_BUILTIN_I64]);
   1897     kit_cg_int_binop(cg, KIT_CG_INT_SUB, 0);
   1898     kit_cg_store(cg, i64_mem);
   1899     /* copy fn and typeidx fields */
   1900     kit_cg_push_local(cg, dst_base_local);
   1901     kit_cg_load(cg, ptr_mem);
   1902     kit_cg_push_local(cg, dst_idx_local);
   1903     kit_cg_load(cg, i64_mem);
   1904     kit_cg_push_local(cg, idx);
   1905     kit_cg_load(cg, i64_mem);
   1906     kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1907     kit_cg_elem(cg, 0);
   1908     kit_cg_field(cg, rt->table_entry_fn_field);
   1909     kit_cg_push_local(cg, src_base_local);
   1910     kit_cg_load(cg, ptr_mem);
   1911     kit_cg_push_local(cg, src_idx_local);
   1912     kit_cg_load(cg, i64_mem);
   1913     kit_cg_push_local(cg, idx);
   1914     kit_cg_load(cg, i64_mem);
   1915     kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1916     kit_cg_elem(cg, 0);
   1917     kit_cg_field(cg, rt->table_entry_fn_field);
   1918     kit_cg_load(cg, fn_mem);
   1919     kit_cg_store(cg, fn_mem);
   1920     kit_cg_push_local(cg, dst_base_local);
   1921     kit_cg_load(cg, ptr_mem);
   1922     kit_cg_push_local(cg, dst_idx_local);
   1923     kit_cg_load(cg, i64_mem);
   1924     kit_cg_push_local(cg, idx);
   1925     kit_cg_load(cg, i64_mem);
   1926     kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1927     kit_cg_elem(cg, 0);
   1928     kit_cg_field(cg, rt->table_entry_typeidx_field);
   1929     kit_cg_push_local(cg, src_base_local);
   1930     kit_cg_load(cg, ptr_mem);
   1931     kit_cg_push_local(cg, src_idx_local);
   1932     kit_cg_load(cg, i64_mem);
   1933     kit_cg_push_local(cg, idx);
   1934     kit_cg_load(cg, i64_mem);
   1935     kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1936     kit_cg_elem(cg, 0);
   1937     kit_cg_field(cg, rt->table_entry_typeidx_field);
   1938     kit_cg_load(cg, i32_mem);
   1939     kit_cg_store(cg, i32_mem);
   1940     kit_cg_jump(cg, back_loop);
   1941   }
   1942   kit_cg_label_place(cg, forward);
   1943   kit_cg_push_local(cg, idx);
   1944   kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I64]);
   1945   kit_cg_store(cg, i64_mem);
   1946   kit_cg_label_place(cg, loop_start);
   1947   kit_cg_push_local(cg, idx);
   1948   kit_cg_load(cg, i64_mem);
   1949   kit_cg_push_local(cg, n_local);
   1950   kit_cg_load(cg, i64_mem);
   1951   kit_cg_int_cmp(cg, KIT_CG_INT_GE_U);
   1952   kit_cg_branch_true(cg, done);
   1953   kit_cg_push_local(cg, dst_base_local);
   1954   kit_cg_load(cg, ptr_mem);
   1955   kit_cg_push_local(cg, dst_idx_local);
   1956   kit_cg_load(cg, i64_mem);
   1957   kit_cg_push_local(cg, idx);
   1958   kit_cg_load(cg, i64_mem);
   1959   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1960   kit_cg_elem(cg, 0);
   1961   kit_cg_field(cg, rt->table_entry_fn_field);
   1962   kit_cg_push_local(cg, src_base_local);
   1963   kit_cg_load(cg, ptr_mem);
   1964   kit_cg_push_local(cg, src_idx_local);
   1965   kit_cg_load(cg, i64_mem);
   1966   kit_cg_push_local(cg, idx);
   1967   kit_cg_load(cg, i64_mem);
   1968   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1969   kit_cg_elem(cg, 0);
   1970   kit_cg_field(cg, rt->table_entry_fn_field);
   1971   kit_cg_load(cg, fn_mem);
   1972   kit_cg_store(cg, fn_mem);
   1973   kit_cg_push_local(cg, dst_base_local);
   1974   kit_cg_load(cg, ptr_mem);
   1975   kit_cg_push_local(cg, dst_idx_local);
   1976   kit_cg_load(cg, i64_mem);
   1977   kit_cg_push_local(cg, idx);
   1978   kit_cg_load(cg, i64_mem);
   1979   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1980   kit_cg_elem(cg, 0);
   1981   kit_cg_field(cg, rt->table_entry_typeidx_field);
   1982   kit_cg_push_local(cg, src_base_local);
   1983   kit_cg_load(cg, ptr_mem);
   1984   kit_cg_push_local(cg, src_idx_local);
   1985   kit_cg_load(cg, i64_mem);
   1986   kit_cg_push_local(cg, idx);
   1987   kit_cg_load(cg, i64_mem);
   1988   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1989   kit_cg_elem(cg, 0);
   1990   kit_cg_field(cg, rt->table_entry_typeidx_field);
   1991   kit_cg_load(cg, i32_mem);
   1992   kit_cg_store(cg, i32_mem);
   1993   kit_cg_push_local(cg, idx);
   1994   kit_cg_push_local(cg, idx);
   1995   kit_cg_load(cg, i64_mem);
   1996   kit_cg_push_int(cg, 1, b.id[KIT_CG_BUILTIN_I64]);
   1997   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   1998   kit_cg_store(cg, i64_mem);
   1999   kit_cg_jump(cg, loop_start);
   2000   kit_cg_label_place(cg, done);
   2001 }
   2002 
   2003 static void wasm_cg_cache_funcref_entry(
   2004     KitCompiler* c, KitCg* cg, WasmCgBuiltinTypes b, const WasmCgRuntime* rt,
   2005     KitCgLocal ref_local, KitCgLocal fn_local, KitCgLocal typeidx_local,
   2006     KitCgMemAccess ref_mem, KitCgMemAccess i32_mem) {
   2007   KitCgLabel is_null = kit_cg_label_new(cg);
   2008   KitCgLabel done = kit_cg_label_new(cg);
   2009   kit_cg_push_local(cg, ref_local);
   2010   kit_cg_load(cg, ref_mem);
   2011   kit_cg_push_null(cg, rt->void_ptr_ty);
   2012   kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   2013   kit_cg_branch_true(cg, is_null);
   2014 
   2015   kit_cg_push_local(cg, fn_local);
   2016   kit_cg_push_local(cg, ref_local);
   2017   kit_cg_load(cg, ref_mem);
   2018   kit_cg_bitcast(cg, kit_cg_type_ptr(c, rt->table_entry_ty, 0));
   2019   kit_cg_deref(cg, 0);
   2020   kit_cg_field(cg, rt->table_entry_fn_field);
   2021   kit_cg_load(cg, ref_mem);
   2022   kit_cg_store(cg, ref_mem);
   2023 
   2024   kit_cg_push_local(cg, typeidx_local);
   2025   kit_cg_push_local(cg, ref_local);
   2026   kit_cg_load(cg, ref_mem);
   2027   kit_cg_bitcast(cg, kit_cg_type_ptr(c, rt->table_entry_ty, 0));
   2028   kit_cg_deref(cg, 0);
   2029   kit_cg_field(cg, rt->table_entry_typeidx_field);
   2030   kit_cg_load(cg, i32_mem);
   2031   kit_cg_store(cg, i32_mem);
   2032   kit_cg_jump(cg, done);
   2033 
   2034   kit_cg_label_place(cg, is_null);
   2035   kit_cg_push_local(cg, fn_local);
   2036   kit_cg_push_null(cg, rt->void_ptr_ty);
   2037   kit_cg_store(cg, ref_mem);
   2038   kit_cg_push_local(cg, typeidx_local);
   2039   kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I32]);
   2040   kit_cg_store(cg, i32_mem);
   2041   kit_cg_label_place(cg, done);
   2042 }
   2043 
   2044 /* Per-function control-stack entry for the opcode walk in wasm_emit_cg_into:
   2045  * one frame per structured block/loop/if. Each live frame owns a structured CG
   2046  * scope (kit_cg_block_begin_sig / kit_cg_scope_begin_sig); the wasm operand
   2047  * stack maps onto the CG value stack, and the scope's carry locals move the
   2048  * block's results (and a loop's params) across the structured-control edges.
   2049  *
   2050  * A frame opened in dead code (after a branch terminator, before the matching
   2051  * else/end) is marked `entry_dead` and owns no CG scope — it only tracks
   2052  * nesting so the matching end pops the right depth. `base` is the CG
   2053  * value-stack depth just below the block's result region, used to discard the
   2054  * operands a Wasm polymorphic/unreachable region leaves behind. */
   2055 typedef struct WasmCgControl {
   2056   uint8_t kind;       /* WASM_INSN_BLOCK / LOOP / IF */
   2057   uint8_t seen_else;  /* an else has been processed (if frames) */
   2058   uint8_t entry_dead; /* opened in dead code => no CG scope */
   2059   uint8_t pad;
   2060   KitCgScope scope;    /* valid iff !entry_dead */
   2061   uint32_t base;       /* CG value-stack depth below the block's results */
   2062   KitCgTypeId* params; /* CG types, arena-owned; valid iff !entry_dead */
   2063   uint32_t nparams;
   2064   KitCgTypeId* results;
   2065   uint32_t nresults;
   2066   KitCgLabel else_label;  /* if frames: the false-arm landing pad */
   2067   KitCgLocal* param_tmps; /* if frames: nparams snapshot locals for the else */
   2068 } WasmCgControl;
   2069 
   2070 /* Resolve a block/loop/if instruction's signature into CG-type arrays stored on
   2071  * `fr` (arena-owned). */
   2072 static void wasm_cg_resolve_sig(KitCompiler* c, WasmCgBuiltinTypes b,
   2073                                 const WasmModule* m, KitArena* arena,
   2074                                 const WasmInsn* in, WasmCgControl* fr) {
   2075   WasmValType scratch;
   2076   WasmBlockSig sig;
   2077   uint32_t k;
   2078   wasm_block_sig(m, in, &scratch, &sig);
   2079   fr->nparams = sig.nparams;
   2080   fr->nresults = sig.nresults;
   2081   fr->params =
   2082       sig.nparams ? kit_arena_array(arena, KitCgTypeId, sig.nparams) : NULL;
   2083   fr->results =
   2084       sig.nresults ? kit_arena_array(arena, KitCgTypeId, sig.nresults) : NULL;
   2085   for (k = 0; k < sig.nparams; ++k)
   2086     fr->params[k] = wasm_cg_type(c, b, sig.params[k]);
   2087   for (k = 0; k < sig.nresults; ++k)
   2088     fr->results[k] = wasm_cg_type(c, b, sig.results[k]);
   2089 }
   2090 
   2091 /* Discard value-stack operands down to `base`. */
   2092 static void wasm_cg_drop_to(KitCg* cg, uint32_t base) {
   2093   while (kit_cg_stack_depth(cg) > base) kit_cg_drop(cg);
   2094 }
   2095 
   2096 /* Re-push `n` snapshot temps onto the stack (bottom->top). */
   2097 static void wasm_cg_push_temps(KitCg* cg, const KitCgTypeId* types,
   2098                                const KitCgLocal* tmps, uint32_t n) {
   2099   uint32_t k;
   2100   for (k = 0; k < n; ++k)
   2101     kit_cg_local_read(cg, tmps[k], wasm_cg_mem_type(types[k]));
   2102 }
   2103 
   2104 /* Pop `n` values (bottom->top types[]) into fresh temp locals; with `restore`,
   2105  * re-push them so the originals stay on the stack (a duplicate snapshot).
   2106  * Returns the temp locals (arena-owned). */
   2107 static KitCgLocal* wasm_cg_save_values(KitCg* cg, KitArena* arena,
   2108                                        const KitCgTypeId* types, uint32_t n,
   2109                                        int restore) {
   2110   KitCgLocal* tmps;
   2111   KitCgLocalAttrs attrs;
   2112   uint32_t k;
   2113   if (!n) return NULL;
   2114   tmps = kit_arena_array(arena, KitCgLocal, n);
   2115   memset(&attrs, 0, sizeof attrs);
   2116   attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   2117   for (k = 0; k < n; ++k) tmps[k] = kit_cg_local(cg, types[k], attrs);
   2118   for (k = 0; k < n; ++k)
   2119     kit_cg_local_write(cg, tmps[n - 1u - k],
   2120                        wasm_cg_mem_type(types[n - 1u - k]));
   2121   if (restore) wasm_cg_push_temps(cg, types, tmps, n);
   2122   return tmps;
   2123 }
   2124 
   2125 /* Branch to a live control frame carrying its label values (already on the
   2126  * stack): a loop takes its params (store + jump continue), a block/if takes its
   2127  * results (break). Consumes the label values. */
   2128 static void wasm_cg_branch_to(KitCg* cg, WasmCgControl* fr) {
   2129   if (fr->kind == WASM_INSN_LOOP) {
   2130     kit_cg_scope_store_params(cg, fr->scope);
   2131     kit_cg_jump(cg, kit_cg_scope_continue_label(cg, fr->scope));
   2132   } else {
   2133     kit_cg_break(cg, fr->scope);
   2134   }
   2135 }
   2136 
   2137 /* The label values a branch to `fr` transfers (loop -> params, else results).
   2138  */
   2139 static const KitCgTypeId* wasm_cg_label_types(const WasmCgControl* fr,
   2140                                               uint32_t* n) {
   2141   if (fr->kind == WASM_INSN_LOOP) {
   2142     *n = fr->nparams;
   2143     return fr->params;
   2144   }
   2145   *n = fr->nresults;
   2146   return fr->results;
   2147 }
   2148 
   2149 /* Exit an if's then-arm and enter its else arm: carry then-results to the block
   2150  * break (or discard them if the then-arm terminated), place the else label, and
   2151  * re-push the snapshotted params for the else arm. */
   2152 static void wasm_cg_enter_else(KitCg* cg, WasmCgControl* fr, int then_dead) {
   2153   if (then_dead)
   2154     wasm_cg_drop_to(cg, fr->base);
   2155   else
   2156     kit_cg_break(cg, fr->scope);
   2157   kit_cg_label_place(cg, fr->else_label);
   2158   wasm_cg_push_temps(cg, fr->params, fr->param_tmps, fr->nparams);
   2159 }
   2160 
   2161 /* Open a block/loop/if frame into `fr`. In dead code the frame owns no CG scope
   2162  * (just nesting); otherwise it opens the structured scope, and an `if` also
   2163  * lifts the condition, snapshots its params for the else arm, and branches the
   2164  * false arm to a fresh else label. */
   2165 static void wasm_cg_open_frame(KitCompiler* c, KitCg* cg, WasmCgBuiltinTypes b,
   2166                                const WasmModule* m, KitArena* arena,
   2167                                WasmCgControl* fr, const WasmInsn* in,
   2168                                int dead) {
   2169   KitCgScopeSig sig;
   2170   memset(fr, 0, sizeof *fr);
   2171   fr->kind = in->kind;
   2172   fr->entry_dead = dead ? 1u : 0u;
   2173   if (dead) return;
   2174   wasm_cg_resolve_sig(c, b, m, arena, in, fr);
   2175   memset(&sig, 0, sizeof sig);
   2176   sig.params = fr->params;
   2177   sig.nparams = fr->nparams;
   2178   sig.results = fr->results;
   2179   sig.nresults = fr->nresults;
   2180   if (in->kind == WASM_INSN_IF) {
   2181     fr->else_label = kit_cg_label_new(cg);
   2182     if (fr->nparams == 0) {
   2183       fr->scope = kit_cg_block_begin_sig(cg, &sig);
   2184       kit_cg_branch_false(cg, fr->else_label); /* pop cond */
   2185     } else {
   2186       KitCgLocalAttrs attrs;
   2187       KitCgLocal cond_tmp;
   2188       KitCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
   2189       memset(&attrs, 0, sizeof attrs);
   2190       attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   2191       cond_tmp = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   2192       /* Lift the condition above the params, snapshot the params for the else
   2193        * arm, then re-test the condition once the block scope is open. */
   2194       kit_cg_local_write(cg, cond_tmp, i32_mem);
   2195       fr->param_tmps =
   2196           wasm_cg_save_values(cg, arena, fr->params, fr->nparams, 1);
   2197       fr->scope = kit_cg_block_begin_sig(cg, &sig);
   2198       kit_cg_local_read(cg, cond_tmp, i32_mem);
   2199       kit_cg_branch_false(cg, fr->else_label);
   2200     }
   2201   } else if (in->kind == WASM_INSN_LOOP) {
   2202     fr->scope = kit_cg_scope_begin_sig(cg, &sig);
   2203   } else {
   2204     fr->scope = kit_cg_block_begin_sig(cg, &sig);
   2205   }
   2206   fr->base = kit_cg_stack_depth(cg) - fr->nparams;
   2207 }
   2208 
   2209 /* Process an `else`: returns the new dead state (the else arm's reachability).
   2210  */
   2211 static int wasm_cg_handle_else(KitCg* cg, WasmCgControl* fr, int dead) {
   2212   if (fr->entry_dead) return dead; /* else of a dead if; stays dead */
   2213   wasm_cg_enter_else(cg, fr, dead);
   2214   fr->seen_else = 1u;
   2215   return 0;
   2216 }
   2217 
   2218 /* Process an `end`: closes the frame's scope and returns the post-end dead
   2219  * state. The caller pops the frame afterwards. */
   2220 static int wasm_cg_handle_end(KitCg* cg, WasmCgControl* fr, int dead) {
   2221   if (fr->entry_dead) return dead; /* dead frame; nothing to close */
   2222   if (fr->kind == WASM_INSN_IF && !fr->seen_else) {
   2223     /* No else arm: the implicit empty else passes the params through as the
   2224      * results (the validator guarantees params == results). */
   2225     wasm_cg_enter_else(cg, fr, dead);
   2226     kit_cg_scope_end(cg, fr->scope);
   2227     return 0;
   2228   }
   2229   if (dead)
   2230     kit_cg_scope_end_unreachable(cg, fr->scope);
   2231   else
   2232     kit_cg_scope_end(cg, fr->scope);
   2233   return 0;
   2234 }
   2235 
   2236 void wasm_emit_cg_into(KitCompiler* c, KitCg* cg, const WasmModule* m) {
   2237   WasmCgBuiltinTypes b = wasm_cg_builtin_types(c);
   2238   WasmCgRuntime rt;
   2239   /* A KitArena owns transient frontend-side codegen state — sym tables, func
   2240    * types, per-function local arrays, instance-record field tables, call
   2241    * argument arrays. Lives for the duration of wasm_emit_cg_into; no fixed cap
   2242    * on functions, params, locals, or instance fields. */
   2243   KitArena* arena = NULL;
   2244   KitCgSym init_sym = KIT_CG_SYM_NONE;
   2245   uint32_t i, j;
   2246   if (kit_arena_new(kit_compiler_context(c)->heap, 8192, &arena) != KIT_OK)
   2247     wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
   2248   if (!cg) wasm_error(c, wasm_loc(0, 0), "wasm: failed to initialize codegen");
   2249   KitCgSym* syms =
   2250       m->nfuncs ? kit_arena_zarray(arena, KitCgSym, m->nfuncs) : NULL;
   2251   KitCgTypeId* func_types =
   2252       m->nfuncs ? kit_arena_zarray(arena, KitCgTypeId, m->nfuncs) : NULL;
   2253   wasm_cg_build_runtime(c, b, m, &rt, arena);
   2254   {
   2255     KitCgFuncSig sig;
   2256     KitCgDecl decl;
   2257     memset(&sig, 0, sizeof sig);
   2258     sig.result.type = b.id[KIT_CG_BUILTIN_VOID];
   2259     sig.call_conv = KIT_CG_CC_TARGET_C;
   2260     rt.trap_func_ty = kit_cg_type_func(c, sig);
   2261     if (!rt.trap_func_ty)
   2262       wasm_error(c, wasm_loc(0, 0), "wasm: failed to create trap type");
   2263     for (uint32_t k = 0; k < WASM_TRAP_COUNT; ++k) {
   2264       KitSym source_name = kit_sym_intern(c, kit_slice_cstr(wasm_trap_name(k)));
   2265       memset(&decl, 0, sizeof decl);
   2266       decl.kind = KIT_CG_DECL_FUNC;
   2267       decl.linkage_name = kit_cg_c_linkage_name(c, source_name);
   2268       decl.display_name = source_name;
   2269       decl.type = rt.trap_func_ty;
   2270       decl.sym.bind = KIT_SB_LOCAL;
   2271       decl.as.func.flags = KIT_CG_FUNC_NORETURN | KIT_CG_FUNC_COLD;
   2272       rt.trap_syms[k] = kit_cg_decl(cg, decl);
   2273       if (!rt.trap_syms[k])
   2274         wasm_error(c, wasm_loc(0, 0), "wasm: failed to declare trap helper");
   2275     }
   2276   }
   2277   {
   2278     KitCgDecl decl;
   2279     KitCgFuncParam init_param;
   2280     KitCgFuncSig sig;
   2281     memset(&init_param, 0, sizeof init_param);
   2282     init_param.type = rt.instance_ptr_ty;
   2283     memset(&sig, 0, sizeof sig);
   2284     sig.result.type = b.id[KIT_CG_BUILTIN_VOID];
   2285     sig.params = &init_param;
   2286     sig.nparams = 1;
   2287     sig.call_conv = KIT_CG_CC_TARGET_C;
   2288     memset(&decl, 0, sizeof decl);
   2289     decl.kind = KIT_CG_DECL_FUNC;
   2290     decl.linkage_name = kit_cg_c_linkage_name(
   2291         c, kit_sym_intern(c, KIT_SLICE_LIT("__kit_wasm_init")));
   2292     decl.display_name = decl.linkage_name;
   2293     decl.type = kit_cg_type_func(c, sig);
   2294     decl.sym.bind = KIT_SB_GLOBAL;
   2295     init_sym = kit_cg_decl(cg, decl);
   2296   }
   2297   for (i = 0; i < m->nfuncs; ++i) {
   2298     const WasmFunc* f = &m->funcs[i];
   2299     KitCgFuncParam* cg_params =
   2300         kit_arena_zarray(arena, KitCgFuncParam, f->nparams + 1u);
   2301     KitCgFuncSig sig;
   2302     KitCgDecl decl;
   2303     char local_name[40];
   2304     KitSym source_name;
   2305     kit_cg_set_loc(cg, f->loc);
   2306     cg_params[0].type = rt.instance_ptr_ty;
   2307     for (j = 0; j < f->nparams; ++j) {
   2308       cg_params[j + 1u].type = wasm_cg_type(c, b, f->params[j]);
   2309     }
   2310     memset(&sig, 0, sizeof sig);
   2311     sig.result.type = b.id[KIT_CG_BUILTIN_VOID];
   2312     if (f->nresults) sig.result.type = wasm_cg_type(c, b, f->results[0]);
   2313     sig.params = cg_params;
   2314     sig.nparams = f->nparams + 1u;
   2315     sig.call_conv = KIT_CG_CC_TARGET_C;
   2316     func_types[i] = kit_cg_type_func(c, sig);
   2317     if (!func_types[i])
   2318       wasm_error(c, f->loc, "wasm: failed to create function type");
   2319     if (f->is_import) {
   2320       syms[i] = KIT_CG_SYM_NONE;
   2321       continue;
   2322     }
   2323     if (f->export_name) {
   2324       source_name = kit_sym_intern(c, kit_slice_cstr(f->export_name));
   2325     } else {
   2326       wasm_indexed_name(local_name, sizeof local_name, "__kit_wasm_func_", i);
   2327       source_name = kit_sym_intern(c, kit_slice_cstr(local_name));
   2328     }
   2329     memset(&decl, 0, sizeof decl);
   2330     decl.kind = KIT_CG_DECL_FUNC;
   2331     decl.linkage_name = kit_cg_c_linkage_name(c, source_name);
   2332     decl.display_name = source_name;
   2333     decl.type = func_types[i];
   2334     decl.sym.bind = f->export_name ? KIT_SB_GLOBAL : KIT_SB_LOCAL;
   2335     syms[i] = kit_cg_decl(cg, decl);
   2336     if (!syms[i]) wasm_error(c, f->loc, "wasm: failed to declare function");
   2337   }
   2338   for (uint32_t k = 0; k < WASM_TRAP_COUNT; ++k) {
   2339     kit_cg_func_begin(cg, rt.trap_syms[k]);
   2340     wasm_cg_emit_raw_trap(c, cg);
   2341     kit_cg_func_end(cg);
   2342   }
   2343   if (init_sym) {
   2344     KitCgLocalAttrs attrs;
   2345     KitCgLocal instance_local;
   2346     memset(&attrs, 0, sizeof attrs);
   2347     kit_cg_func_begin(cg, init_sym);
   2348     instance_local = kit_cg_param(cg, 0, rt.instance_ptr_ty, attrs);
   2349     for (i = 0; i < m->nmemories; ++i) {
   2350       const WasmMemory* mem = &m->memories[i];
   2351       uint64_t max_pages = mem->has_max ? mem->max_pages : mem->min_pages;
   2352       uint32_t flags = (mem->shared ? 1u : 0u) | (mem->is64 ? 2u : 0u);
   2353       wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2354       kit_cg_deref(cg, (int64_t)(rt.memory_offset[i] + rt.memory_pages_offset));
   2355       kit_cg_push_int(cg, mem->min_pages, b.id[KIT_CG_BUILTIN_I64]);
   2356       kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   2357       wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2358       kit_cg_deref(cg,
   2359                    (int64_t)(rt.memory_offset[i] + rt.memory_max_pages_offset));
   2360       kit_cg_push_int(cg, max_pages, b.id[KIT_CG_BUILTIN_I64]);
   2361       kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   2362       wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2363       kit_cg_deref(cg, (int64_t)(rt.memory_offset[i] + rt.memory_flags_offset));
   2364       kit_cg_push_int(cg, flags, b.id[KIT_CG_BUILTIN_I32]);
   2365       kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   2366       /* For each active data segment targeting this memory, memcpy its
   2367        * bytes into the linear memory at the segment's offset. Passive
   2368        * segments are not initialized here — they're consumed by an
   2369        * explicit `memory.init` instruction at runtime. */
   2370       for (uint32_t di = 0; di < m->ndata; ++di) {
   2371         const WasmDataSegment* d = &m->data[di];
   2372         if (d->mode != WASM_SEG_ACTIVE) continue;
   2373         if (d->memidx != i) continue;
   2374         if (!d->nbytes) continue;
   2375         {
   2376           KitCgSym data_sym = kit_cg_const_data(cg, d->bytes, d->nbytes, 16,
   2377                                                 b.id[KIT_CG_BUILTIN_I8]);
   2378           KitCgMemAccess byte_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I8]);
   2379           wasm_cg_push_memory_data_ptr(cg, &rt, instance_local, i);
   2380           if (d->offset) wasm_cg_ptr_add_offset(cg, b, d->offset, rt.i8_ptr_ty);
   2381           kit_cg_push_symbol_addr(cg, data_sym, 0);
   2382           kit_cg_memcpy(cg, d->nbytes, byte_mem, byte_mem);
   2383         }
   2384       }
   2385     }
   2386     /* Populate per-module passive data segment slots. Passive segments
   2387      * intern their bytes as a const data symbol and store {base, len}
   2388      * into the instance slot; memory.init/data.drop read/clear this slot.
   2389      * Active segments leave their slot at zero-len (they're effectively
   2390      * dropped after init), which makes memory.init on an active index
   2391      * trap on any non-zero copy length. */
   2392     for (uint32_t di = 0; di < m->ndata; ++di) {
   2393       const WasmDataSegment* d = &m->data[di];
   2394       wasm_cg_push_passive_data_lvalue(cg, &rt, instance_local, di);
   2395       kit_cg_field(cg, rt.passive_data_base_field);
   2396       if (d->mode == WASM_SEG_PASSIVE && d->nbytes) {
   2397         KitCgSym data_sym = kit_cg_const_data(cg, d->bytes, d->nbytes, 16,
   2398                                               b.id[KIT_CG_BUILTIN_I8]);
   2399         kit_cg_push_symbol_addr(cg, data_sym, 0);
   2400       } else {
   2401         kit_cg_push_null(cg, rt.i8_ptr_ty);
   2402       }
   2403       kit_cg_store(cg, wasm_cg_mem_type(rt.i8_ptr_ty));
   2404       wasm_cg_push_passive_data_lvalue(cg, &rt, instance_local, di);
   2405       kit_cg_field(cg, rt.passive_data_len_field);
   2406       kit_cg_push_int(cg, (d->mode == WASM_SEG_PASSIVE) ? d->nbytes : 0u,
   2407                       b.id[KIT_CG_BUILTIN_I64]);
   2408       kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   2409     }
   2410     for (i = 0; i < m->nfuncs; ++i) {
   2411       wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2412       kit_cg_deref(cg, (int64_t)(rt.func_ref_entry_offset[i] +
   2413                                  rt.table_entry_fn_offset));
   2414       if (m->funcs[i].is_import) {
   2415         wasm_cg_push_import_func_ptr(cg, &rt, instance_local, i);
   2416       } else {
   2417         kit_cg_push_symbol_addr(cg, syms[i], 0);
   2418         kit_cg_bitcast(cg, rt.void_ptr_ty);
   2419       }
   2420       kit_cg_store(cg, wasm_cg_mem_type(rt.void_ptr_ty));
   2421       wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2422       kit_cg_deref(cg, (int64_t)(rt.func_ref_entry_offset[i] +
   2423                                  rt.table_entry_typeidx_offset));
   2424       kit_cg_push_int(cg, m->funcs[i].typeidx, b.id[KIT_CG_BUILTIN_I32]);
   2425       kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   2426     }
   2427     for (i = 0; i < m->ntables; ++i) {
   2428       const WasmTable* t = &m->tables[i];
   2429       uint32_t max = t->has_max ? t->max : t->min;
   2430       /* tables[i].entries = &instance->table_entries_arr[i][0]. The address
   2431        * of the entries array is instance + table_entries_offset[i]. */
   2432       wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2433       kit_cg_deref(cg,
   2434                    (int64_t)(rt.table_offset[i] + rt.table_entries_ptr_offset));
   2435       wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2436       wasm_cg_ptr_add_offset(cg, b, rt.table_entries_offset[i],
   2437                              rt.table_entry_ptr_ty);
   2438       kit_cg_store(cg, wasm_cg_mem_type(rt.table_entry_ptr_ty));
   2439       wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2440       kit_cg_deref(cg, (int64_t)(rt.table_offset[i] + rt.table_len_offset));
   2441       kit_cg_push_int(cg, t->min, b.id[KIT_CG_BUILTIN_I32]);
   2442       kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   2443       wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2444       kit_cg_deref(cg, (int64_t)(rt.table_offset[i] + rt.table_max_offset));
   2445       kit_cg_push_int(cg, max, b.id[KIT_CG_BUILTIN_I32]);
   2446       kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   2447     }
   2448     for (i = 0; i < m->nelems; ++i) {
   2449       const WasmElemSegment* seg = &m->elems[i];
   2450       int is_passive = (seg->mode == WASM_SEG_PASSIVE);
   2451       for (j = 0; j < seg->nfuncs; ++j) {
   2452         uint32_t funcidx = seg->funcs[j];
   2453         KitCgLocalAttrs tmp_attrs;
   2454         KitCgLocal slot_local;
   2455         memset(&tmp_attrs, 0, sizeof tmp_attrs);
   2456         tmp_attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   2457         slot_local = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], tmp_attrs);
   2458         kit_cg_push_local(cg, slot_local);
   2459         if (is_passive) {
   2460           kit_cg_push_int(cg, j, b.id[KIT_CG_BUILTIN_I32]);
   2461         } else {
   2462           kit_cg_push_int(cg, (uint32_t)(seg->offset + j),
   2463                           b.id[KIT_CG_BUILTIN_I32]);
   2464         }
   2465         kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   2466         /* Resolve the target table-entry lvalue: active segments write into
   2467          * the module's table; passive segments write into the per-segment
   2468          * inline storage array so the bytes survive instantiation for
   2469          * later table.init. */
   2470         if (is_passive) {
   2471           wasm_cg_push_passive_elem_storage_array_lvalue(cg, &rt,
   2472                                                          instance_local, i);
   2473           kit_cg_addr(cg);
   2474           kit_cg_bitcast(cg, rt.table_entry_ptr_ty);
   2475           kit_cg_push_local(cg, slot_local);
   2476           kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   2477           kit_cg_elem(cg, 0);
   2478         } else {
   2479           wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local,
   2480                                           seg->tableidx, slot_local,
   2481                                           wasm_cg_mem(c, b, WASM_VAL_I32));
   2482         }
   2483         kit_cg_field(cg, rt.table_entry_fn_field);
   2484         if (m->funcs[funcidx].is_import) {
   2485           wasm_cg_push_import_func_ptr(cg, &rt, instance_local, funcidx);
   2486         } else {
   2487           kit_cg_push_symbol_addr(cg, syms[funcidx], 0);
   2488           kit_cg_bitcast(cg, rt.void_ptr_ty);
   2489         }
   2490         kit_cg_store(cg, wasm_cg_mem_type(rt.void_ptr_ty));
   2491         if (is_passive) {
   2492           wasm_cg_push_passive_elem_storage_array_lvalue(cg, &rt,
   2493                                                          instance_local, i);
   2494           kit_cg_addr(cg);
   2495           kit_cg_bitcast(cg, rt.table_entry_ptr_ty);
   2496           kit_cg_push_local(cg, slot_local);
   2497           kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   2498           kit_cg_elem(cg, 0);
   2499         } else {
   2500           wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local,
   2501                                           seg->tableidx, slot_local,
   2502                                           wasm_cg_mem(c, b, WASM_VAL_I32));
   2503         }
   2504         kit_cg_field(cg, rt.table_entry_typeidx_field);
   2505         kit_cg_push_int(cg, m->funcs[funcidx].typeidx,
   2506                         b.id[KIT_CG_BUILTIN_I32]);
   2507         kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   2508       }
   2509       /* Initialize the passive_elem descriptor (entries pointer + length).
   2510        * Active segments get a zero-length descriptor so table.init on an
   2511        * active index traps on any non-zero copy. */
   2512       wasm_cg_push_passive_elem_lvalue(cg, &rt, instance_local, i);
   2513       kit_cg_field(cg, rt.passive_elem_entries_field);
   2514       if (is_passive && seg->nfuncs) {
   2515         wasm_cg_push_passive_elem_storage_array_lvalue(cg, &rt, instance_local,
   2516                                                        i);
   2517         kit_cg_addr(cg);
   2518         kit_cg_bitcast(cg, rt.table_entry_ptr_ty);
   2519         kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I32]);
   2520         kit_cg_elem(cg, 0);
   2521         kit_cg_addr(cg);
   2522       } else {
   2523         kit_cg_push_null(cg, rt.table_entry_ptr_ty);
   2524       }
   2525       kit_cg_store(cg, wasm_cg_mem_type(rt.table_entry_ptr_ty));
   2526       wasm_cg_push_passive_elem_lvalue(cg, &rt, instance_local, i);
   2527       kit_cg_field(cg, rt.passive_elem_length_field);
   2528       kit_cg_push_int(cg, is_passive ? seg->nfuncs : 0u,
   2529                       b.id[KIT_CG_BUILTIN_I32]);
   2530       kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   2531     }
   2532     for (i = 0; i < m->nglobals; ++i) {
   2533       const WasmGlobal* g = &m->globals[i];
   2534       if (g->is_import) continue;
   2535       wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2536       kit_cg_deref(cg, (int64_t)rt.global_offset[i]);
   2537       if (g->type == WASM_VAL_F32 || g->type == WASM_VAL_F64)
   2538         kit_cg_push_float(cg, g->init.fp, wasm_cg_type(c, b, g->type));
   2539       else
   2540         kit_cg_push_int(cg, (uint64_t)g->init.imm, wasm_cg_type(c, b, g->type));
   2541       kit_cg_store(cg, wasm_cg_mem(c, b, g->type));
   2542     }
   2543     if (m->has_start)
   2544       wasm_cg_call_func(c, cg, b, &m->funcs[m->start_func], &rt,
   2545                         syms[m->start_func], func_types[m->start_func],
   2546                         instance_local, m->start_func, 0, m->start_field_loc,
   2547                         arena);
   2548     kit_cg_ret(cg);
   2549     kit_cg_func_end(cg);
   2550   }
   2551   /* Host-import resolution metadata: emit __kit_wasm_nimports always, plus
   2552    * import descriptors and kind-specific type arrays when the module declares
   2553    * imports. Function import signatures are deduplicated in __kit_wasm_types.
   2554    * Read by kit_wasm_bind_host_imports. */
   2555   wasm_cg_emit_host_import_metadata(c, cg, b, m, &rt, arena);
   2556   wasm_cg_emit_runtime_layout_metadata(c, cg, b, m, &rt);
   2557   for (i = 0; i < m->nfuncs; ++i) {
   2558     const WasmFunc* f = &m->funcs[i];
   2559     /* Per-function arena-allocated locals and control stack. locals is
   2560      * sized to nparams + nlocals; the control stack starts at 16 entries
   2561      * and doubles in-place on overflow (arena pointers are stable, so
   2562      * we use a side heap realloc instead). */
   2563     KitCgLocal* locals =
   2564         (f->nparams + f->nlocals)
   2565             ? kit_arena_array(arena, KitCgLocal, f->nparams + f->nlocals)
   2566             : NULL;
   2567     KitHeap* heap = kit_compiler_context(c)->heap;
   2568     uint32_t control_cap = 16u;
   2569     WasmCgControl* control = (WasmCgControl*)heap->alloc(
   2570         heap, sizeof(WasmCgControl) * control_cap, _Alignof(WasmCgControl));
   2571     uint32_t ncontrol = 0;
   2572     KitCgLocal instance_local;
   2573     if (!control) wasm_error(c, f->loc, "wasm: out of memory");
   2574     if (f->is_import) {
   2575       heap->free(heap, control, sizeof(WasmCgControl) * control_cap);
   2576       continue;
   2577     }
   2578     kit_cg_set_loc(cg, f->loc);
   2579     kit_cg_func_begin(cg, syms[i]);
   2580     {
   2581       KitCgLocalAttrs attrs;
   2582       memset(&attrs, 0, sizeof attrs);
   2583       instance_local = kit_cg_param(cg, 0, rt.instance_ptr_ty, attrs);
   2584     }
   2585     for (j = 0; j < f->nparams; ++j) {
   2586       KitCgLocalAttrs attrs;
   2587       memset(&attrs, 0, sizeof attrs);
   2588       locals[j] =
   2589           kit_cg_param(cg, j + 1u, wasm_cg_type(c, b, f->params[j]), attrs);
   2590     }
   2591     for (j = 0; j < f->nlocals; ++j) {
   2592       KitCgLocalAttrs attrs;
   2593       memset(&attrs, 0, sizeof attrs);
   2594       attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   2595       locals[f->nparams + j] =
   2596           kit_cg_local(cg, wasm_cg_type(c, b, f->locals[j]), attrs);
   2597       kit_cg_push_local(cg, locals[f->nparams + j]);
   2598       wasm_cg_push_zero(c, cg, b, f->locals[j]);
   2599       kit_cg_store(cg, wasm_cg_mem(c, b, f->locals[j]));
   2600     }
   2601     /* The CG value-stack depth at the function's statement level (operands
   2602      * empty), and whether the current position is unreachable (after a branch
   2603      * terminator). Dead non-control ops are skipped; the structured scope ops
   2604      * still track nesting so the matching end pops the right depth. */
   2605     uint32_t func_base = kit_cg_stack_depth(cg);
   2606     int dead = 0;
   2607     for (j = 0; j < f->ninsns; ++j) {
   2608       WasmInsn in = f->insns[j];
   2609       uint32_t cur_base;
   2610       kit_cg_set_loc(cg, in.loc);
   2611       /* Skip dead value ops; only block/loop/if/else/end keep their bookkeeping
   2612        * so nesting (and the eventual scope close) stays balanced. */
   2613       if (dead && in.kind != WASM_INSN_BLOCK && in.kind != WASM_INSN_LOOP &&
   2614           in.kind != WASM_INSN_IF && in.kind != WASM_INSN_ELSE &&
   2615           in.kind != WASM_INSN_END)
   2616         continue;
   2617       cur_base = ncontrol ? control[ncontrol - 1u].base : func_base;
   2618       switch (in.kind) {
   2619         case WASM_INSN_UNREACHABLE:
   2620           wasm_cg_trap_unreachable(cg, &rt);
   2621           wasm_cg_drop_to(cg, cur_base);
   2622           dead = 1;
   2623           break;
   2624         case WASM_INSN_NOP:
   2625           break;
   2626         case WASM_INSN_BLOCK:
   2627         case WASM_INSN_LOOP:
   2628         case WASM_INSN_IF:
   2629           if (ncontrol == control_cap) {
   2630             uint32_t new_cap = control_cap * 2u;
   2631             void* p = heap->realloc(
   2632                 heap, control, sizeof(WasmCgControl) * control_cap,
   2633                 sizeof(WasmCgControl) * new_cap, _Alignof(WasmCgControl));
   2634             if (!p) wasm_error(c, in.loc, "wasm: out of memory");
   2635             control = (WasmCgControl*)p;
   2636             control_cap = new_cap;
   2637           }
   2638           wasm_cg_open_frame(c, cg, b, m, arena, &control[ncontrol], &in, dead);
   2639           ncontrol++;
   2640           break;
   2641         case WASM_INSN_ELSE:
   2642           if (!ncontrol || control[ncontrol - 1u].kind != WASM_INSN_IF)
   2643             wasm_error(c, in.loc, "wasm: else without if");
   2644           dead = wasm_cg_handle_else(cg, &control[ncontrol - 1u], dead);
   2645           break;
   2646         case WASM_INSN_END:
   2647           if (!ncontrol) wasm_error(c, in.loc, "wasm: end without block");
   2648           dead = wasm_cg_handle_end(cg, &control[ncontrol - 1u], dead);
   2649           ncontrol--;
   2650           break;
   2651         case WASM_INSN_BR: {
   2652           uint32_t depth = (uint32_t)in.imm;
   2653           if (depth >= ncontrol)
   2654             wasm_error(c, in.loc, "wasm: branch depth out of range");
   2655           wasm_cg_branch_to(cg, &control[ncontrol - 1u - depth]);
   2656           wasm_cg_drop_to(cg, cur_base);
   2657           dead = 1;
   2658           break;
   2659         }
   2660         case WASM_INSN_BR_IF: {
   2661           uint32_t depth = (uint32_t)in.imm;
   2662           uint32_t idx;
   2663           WasmCgControl* tgt;
   2664           const KitCgTypeId* lt;
   2665           uint32_t nlt;
   2666           KitCgLocal cond_tmp;
   2667           KitCgLocal* carry_tmps;
   2668           KitCgLabel skip;
   2669           KitCgLocalAttrs attrs;
   2670           KitCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
   2671           if (depth >= ncontrol)
   2672             wasm_error(c, in.loc, "wasm: branch depth out of range");
   2673           idx = ncontrol - 1u - depth;
   2674           tgt = &control[idx];
   2675           lt = wasm_cg_label_types(tgt, &nlt);
   2676           /* Branch-around: lift the condition, snapshot the carried label
   2677            * values (so they survive on the fall-through), and on the taken arm
   2678            * re-push the copies and branch — consuming them — to the target. */
   2679           memset(&attrs, 0, sizeof attrs);
   2680           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   2681           cond_tmp = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   2682           kit_cg_local_write(cg, cond_tmp, i32_mem); /* pop cond */
   2683           carry_tmps = wasm_cg_save_values(cg, arena, lt, nlt, 1);
   2684           skip = kit_cg_label_new(cg);
   2685           kit_cg_local_read(cg, cond_tmp, i32_mem);
   2686           kit_cg_branch_false(cg, skip);
   2687           wasm_cg_push_temps(cg, lt, carry_tmps, nlt);
   2688           wasm_cg_branch_to(cg, tgt);
   2689           kit_cg_label_place(cg, skip);
   2690           break;
   2691         }
   2692         case WASM_INSN_BR_TABLE: {
   2693           KitCgSwitch sw;
   2694           KitCgSwitchCase* cases;
   2695           WasmCgControl* dflt;
   2696           const KitCgTypeId* lt;
   2697           uint32_t nlt;
   2698           KitCgLocal sel_tmp;
   2699           KitCgLocal* carry_tmps;
   2700           KitCgLabel* distinct_tramp;
   2701           uint32_t* distinct_ctrl;
   2702           KitCgLabel* per_target;
   2703           uint32_t ndistinct = 0;
   2704           uint32_t k, q;
   2705           KitCgLocalAttrs attrs;
   2706           KitCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
   2707           if (in.ntargets == 0)
   2708             wasm_error(c, in.loc, "wasm: bad br_table target count");
   2709           for (k = 0; k < in.ntargets; ++k)
   2710             if (in.targets[k] >= ncontrol)
   2711               wasm_error(c, in.loc, "wasm: branch depth out of range");
   2712           dflt = &control[ncontrol - 1u - in.targets[in.ntargets - 1u]];
   2713           lt = wasm_cg_label_types(dflt, &nlt);
   2714           /* Lift the selector, then save the carried label values once so each
   2715            * per-target trampoline can re-push and branch with them. */
   2716           memset(&attrs, 0, sizeof attrs);
   2717           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   2718           sel_tmp = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   2719           kit_cg_local_write(cg, sel_tmp, i32_mem); /* pop selector */
   2720           carry_tmps = wasm_cg_save_values(cg, arena, lt, nlt, 0);
   2721           /* One trampoline per distinct target control frame. */
   2722           distinct_tramp = kit_arena_array(arena, KitCgLabel, in.ntargets);
   2723           distinct_ctrl = kit_arena_array(arena, uint32_t, in.ntargets);
   2724           per_target = kit_arena_array(arena, KitCgLabel, in.ntargets);
   2725           for (k = 0; k < in.ntargets; ++k) {
   2726             uint32_t ci = ncontrol - 1u - in.targets[k];
   2727             int found = -1;
   2728             for (q = 0; q < ndistinct; ++q)
   2729               if (distinct_ctrl[q] == ci) {
   2730                 found = (int)q;
   2731                 break;
   2732               }
   2733             if (found < 0) {
   2734               distinct_ctrl[ndistinct] = ci;
   2735               distinct_tramp[ndistinct] = kit_cg_label_new(cg);
   2736               found = (int)ndistinct++;
   2737             }
   2738             per_target[k] = distinct_tramp[found];
   2739           }
   2740           cases = kit_arena_zarray(arena, KitCgSwitchCase, in.ntargets);
   2741           for (k = 0; k + 1u < in.ntargets; ++k) {
   2742             cases[k].value = k;
   2743             cases[k].label = per_target[k];
   2744           }
   2745           kit_cg_local_read(cg, sel_tmp, i32_mem);
   2746           memset(&sw, 0, sizeof sw);
   2747           sw.selector_type = b.id[KIT_CG_BUILTIN_I32];
   2748           sw.cases = cases;
   2749           sw.ncases = in.ntargets - 1u;
   2750           sw.default_label = per_target[in.ntargets - 1u];
   2751           /* br_table is dense-by-construction (case values 0..N-1); hint a
   2752            * jump table. Targets that ignore the hint fall back to a cmp chain.
   2753            */
   2754           sw.hint = KIT_CG_SWITCH_JUMP_TABLE;
   2755           kit_cg_switch(cg, sw);
   2756           for (q = 0; q < ndistinct; ++q) {
   2757             kit_cg_label_place(cg, distinct_tramp[q]);
   2758             wasm_cg_push_temps(cg, lt, carry_tmps, nlt);
   2759             wasm_cg_branch_to(cg, &control[distinct_ctrl[q]]);
   2760           }
   2761           wasm_cg_drop_to(cg, cur_base);
   2762           dead = 1;
   2763           break;
   2764         }
   2765         case WASM_INSN_SELECT: {
   2766           KitCgTypeId ty = wasm_cg_type(c, b, (WasmValType)in.type);
   2767           KitCgMemAccess mem = wasm_cg_mem(c, b, (WasmValType)in.type);
   2768           KitCgLocalAttrs attrs;
   2769           KitCgLocal lhs, rhs, cond, result;
   2770           KitCgLabel else_label = kit_cg_label_new(cg);
   2771           KitCgLabel end_label = kit_cg_label_new(cg);
   2772           memset(&attrs, 0, sizeof attrs);
   2773           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   2774           lhs = kit_cg_local(cg, ty, attrs);
   2775           rhs = kit_cg_local(cg, ty, attrs);
   2776           result = kit_cg_local(cg, ty, attrs);
   2777           cond = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   2778 
   2779           kit_cg_push_local(cg, cond);
   2780           kit_cg_swap(cg);
   2781           kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   2782           kit_cg_push_local(cg, rhs);
   2783           kit_cg_swap(cg);
   2784           kit_cg_store(cg, mem);
   2785           kit_cg_push_local(cg, lhs);
   2786           kit_cg_swap(cg);
   2787           kit_cg_store(cg, mem);
   2788 
   2789           kit_cg_push_local(cg, cond);
   2790           kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   2791           kit_cg_branch_false(cg, else_label);
   2792           kit_cg_push_local(cg, result);
   2793           kit_cg_push_local(cg, lhs);
   2794           kit_cg_load(cg, mem);
   2795           kit_cg_store(cg, mem);
   2796           kit_cg_jump(cg, end_label);
   2797           kit_cg_label_place(cg, else_label);
   2798           kit_cg_push_local(cg, result);
   2799           kit_cg_push_local(cg, rhs);
   2800           kit_cg_load(cg, mem);
   2801           kit_cg_store(cg, mem);
   2802           kit_cg_label_place(cg, end_label);
   2803           kit_cg_push_local(cg, result);
   2804           kit_cg_load(cg, mem);
   2805         } break;
   2806         case WASM_INSN_I32_CONST:
   2807           kit_cg_push_int(cg, (uint64_t)(uint32_t)in.imm,
   2808                           b.id[KIT_CG_BUILTIN_I32]);
   2809           break;
   2810         case WASM_INSN_I64_CONST:
   2811           kit_cg_push_int(cg, (uint64_t)in.imm, b.id[KIT_CG_BUILTIN_I64]);
   2812           break;
   2813         case WASM_INSN_F32_CONST:
   2814           kit_cg_push_float(cg, in.fp, b.id[KIT_CG_BUILTIN_F32]);
   2815           break;
   2816         case WASM_INSN_F64_CONST:
   2817           kit_cg_push_float(cg, in.fp, b.id[KIT_CG_BUILTIN_F64]);
   2818           break;
   2819         case WASM_INSN_LOCAL_GET: {
   2820           uint32_t index = (uint32_t)in.imm;
   2821           kit_cg_push_local(cg, locals[index]);
   2822           kit_cg_load(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
   2823           break;
   2824         }
   2825         case WASM_INSN_LOCAL_SET: {
   2826           uint32_t index = (uint32_t)in.imm;
   2827           kit_cg_push_local(cg, locals[index]);
   2828           kit_cg_swap(cg);
   2829           kit_cg_store(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
   2830           break;
   2831         }
   2832         case WASM_INSN_LOCAL_TEE: {
   2833           uint32_t index = (uint32_t)in.imm;
   2834           kit_cg_dup(cg);
   2835           kit_cg_push_local(cg, locals[index]);
   2836           kit_cg_swap(cg);
   2837           kit_cg_store(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
   2838           break;
   2839         }
   2840         case WASM_INSN_CALL:
   2841         case WASM_INSN_RETURN_CALL:
   2842           wasm_cg_call_func(c, cg, b, &m->funcs[in.imm], &rt, syms[in.imm],
   2843                             func_types[in.imm], instance_local,
   2844                             (uint32_t)in.imm, in.kind == WASM_INSN_RETURN_CALL,
   2845                             in.loc, arena);
   2846           break;
   2847         case WASM_INSN_CALL_INDIRECT:
   2848         case WASM_INSN_RETURN_CALL_INDIRECT: {
   2849           const WasmFuncType* t = &m->types[in.imm];
   2850           KitCgLocalAttrs attrs;
   2851           KitCgLocal selector, callee, result = KIT_CG_LOCAL_NONE;
   2852           KitCgLocal* args =
   2853               t->nparams ? kit_arena_array(arena, KitCgLocal, t->nparams)
   2854                          : NULL;
   2855           KitCgLabel ok;
   2856           KitCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
   2857           KitCgFuncParam* indirect_params =
   2858               kit_arena_zarray(arena, KitCgFuncParam, t->nparams + 1u);
   2859           KitCgFuncSig indirect_sig;
   2860           KitCgTypeId indirect_func_type;
   2861           memset(&attrs, 0, sizeof attrs);
   2862           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   2863           indirect_params[0].type = rt.instance_ptr_ty;
   2864           for (uint32_t p = 0; p < t->nparams; ++p)
   2865             indirect_params[p + 1u].type = wasm_cg_type(c, b, t->params[p]);
   2866           memset(&indirect_sig, 0, sizeof indirect_sig);
   2867           indirect_sig.result.type = b.id[KIT_CG_BUILTIN_VOID];
   2868           if (t->nresults)
   2869             indirect_sig.result.type = wasm_cg_type(c, b, t->results[0]);
   2870           indirect_sig.params = indirect_params;
   2871           indirect_sig.nparams = t->nparams + 1u;
   2872           indirect_sig.call_conv = KIT_CG_CC_TARGET_C;
   2873           indirect_func_type = kit_cg_type_func(c, indirect_sig);
   2874           selector = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   2875           callee = kit_cg_local(cg, rt.void_ptr_ty, attrs);
   2876           if (t->nresults)
   2877             result = kit_cg_local(cg, wasm_cg_type(c, b, t->results[0]), attrs);
   2878           kit_cg_push_local(cg, selector);
   2879           kit_cg_swap(cg);
   2880           kit_cg_store(cg, i32_mem);
   2881           for (uint32_t p = 0; p < t->nparams; ++p) {
   2882             uint32_t param = t->nparams - 1u - p;
   2883             args[param] =
   2884                 kit_cg_local(cg, wasm_cg_type(c, b, t->params[param]), attrs);
   2885             kit_cg_push_local(cg, args[param]);
   2886             kit_cg_swap(cg);
   2887             kit_cg_store(cg, wasm_cg_mem(c, b, t->params[param]));
   2888           }
   2889 
   2890           ok = kit_cg_label_new(cg);
   2891           kit_cg_push_local(cg, selector);
   2892           kit_cg_load(cg, i32_mem);
   2893           {
   2894             wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2895             kit_cg_deref(
   2896                 cg, (int64_t)(rt.table_offset[in.align] + rt.table_len_offset));
   2897             kit_cg_load(cg, i32_mem);
   2898           }
   2899           kit_cg_int_cmp(cg, KIT_CG_INT_LT_U);
   2900           kit_cg_branch_true(cg, ok);
   2901           wasm_cg_trap_table(cg, &rt);
   2902           kit_cg_label_place(cg, ok);
   2903 
   2904           ok = kit_cg_label_new(cg);
   2905           kit_cg_push_local(cg, callee);
   2906           wasm_cg_push_table_entry_ptr(cg, b, &rt, instance_local, in.align,
   2907                                        selector, i32_mem);
   2908           {
   2909             kit_cg_deref(cg, (int64_t)rt.table_entry_fn_offset);
   2910             kit_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty));
   2911           }
   2912           kit_cg_store(cg, wasm_cg_mem_type(rt.void_ptr_ty));
   2913           kit_cg_push_local(cg, callee);
   2914           kit_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty));
   2915           kit_cg_push_null(cg, rt.void_ptr_ty);
   2916           kit_cg_int_cmp(cg, KIT_CG_INT_NE);
   2917           kit_cg_branch_true(cg, ok);
   2918           wasm_cg_trap_table(cg, &rt);
   2919           kit_cg_label_place(cg, ok);
   2920 
   2921           ok = kit_cg_label_new(cg);
   2922           wasm_cg_push_table_entry_ptr(cg, b, &rt, instance_local, in.align,
   2923                                        selector, i32_mem);
   2924           {
   2925             kit_cg_deref(cg, (int64_t)rt.table_entry_typeidx_offset);
   2926             kit_cg_load(cg, i32_mem);
   2927           }
   2928           kit_cg_push_int(cg, (uint32_t)in.imm, b.id[KIT_CG_BUILTIN_I32]);
   2929           kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   2930           kit_cg_branch_true(cg, ok);
   2931           wasm_cg_trap_signature(cg, &rt);
   2932           kit_cg_label_place(cg, ok);
   2933 
   2934           kit_cg_push_local(cg, callee);
   2935           kit_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty));
   2936           kit_cg_bitcast(cg, kit_cg_type_ptr(c, indirect_func_type, 0));
   2937           kit_cg_push_local(cg, instance_local);
   2938           kit_cg_load(cg, wasm_cg_mem_type(rt.instance_ptr_ty));
   2939           for (uint32_t p = 0; p < t->nparams; ++p) {
   2940             kit_cg_push_local(cg, args[p]);
   2941             kit_cg_load(cg, wasm_cg_mem(c, b, t->params[p]));
   2942           }
   2943           kit_cg_call(
   2944               cg, t->nparams + 1u, indirect_func_type,
   2945               (KitCgCallAttrs){.tail = in.kind == WASM_INSN_RETURN_CALL_INDIRECT
   2946                                            ? KIT_CG_TAIL_MUST
   2947                                            : KIT_CG_TAIL_DEFAULT});
   2948           if (in.kind == WASM_INSN_RETURN_CALL_INDIRECT) {
   2949             if (t->nresults) wasm_cg_push_zero(c, cg, b, t->results[0]);
   2950             kit_cg_unreachable(cg);
   2951           } else if (t->nresults) {
   2952             kit_cg_push_local(cg, result);
   2953             kit_cg_swap(cg);
   2954             kit_cg_store(cg, wasm_cg_mem(c, b, t->results[0]));
   2955             kit_cg_push_local(cg, result);
   2956             kit_cg_load(cg, wasm_cg_mem(c, b, t->results[0]));
   2957           }
   2958           break;
   2959         }
   2960         case WASM_INSN_REF_NULL:
   2961           kit_cg_push_null(cg, rt.void_ptr_ty);
   2962           break;
   2963         case WASM_INSN_REF_FUNC:
   2964           wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   2965           wasm_cg_ptr_add_offset(cg, b,
   2966                                  rt.func_ref_entry_offset[(uint32_t)in.imm],
   2967                                  rt.void_ptr_ty);
   2968           break;
   2969         case WASM_INSN_REF_IS_NULL:
   2970           kit_cg_push_null(cg, rt.void_ptr_ty);
   2971           kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   2972           break;
   2973         case WASM_INSN_CALL_REF:
   2974         case WASM_INSN_RETURN_CALL_REF: {
   2975           const WasmFuncType* t = &m->types[in.imm];
   2976           KitCgLocalAttrs attrs;
   2977           KitCgLocal callee_ref, callee, result = KIT_CG_LOCAL_NONE;
   2978           KitCgLocal* args =
   2979               t->nparams ? kit_arena_array(arena, KitCgLocal, t->nparams)
   2980                          : NULL;
   2981           KitCgLabel ok;
   2982           KitCgMemAccess ref_mem = wasm_cg_mem_type(rt.void_ptr_ty);
   2983           KitCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
   2984           KitCgFuncParam* ref_params =
   2985               kit_arena_zarray(arena, KitCgFuncParam, t->nparams + 1u);
   2986           KitCgFuncSig ref_sig;
   2987           KitCgTypeId ref_func_type;
   2988           memset(&attrs, 0, sizeof attrs);
   2989           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   2990           callee_ref = kit_cg_local(cg, rt.void_ptr_ty, attrs);
   2991           callee = kit_cg_local(cg, rt.void_ptr_ty, attrs);
   2992           kit_cg_push_local(cg, callee_ref);
   2993           kit_cg_swap(cg);
   2994           kit_cg_store(cg, ref_mem);
   2995           for (uint32_t p = 0; p < t->nparams; ++p) {
   2996             uint32_t param = t->nparams - 1u - p;
   2997             args[param] =
   2998                 kit_cg_local(cg, wasm_cg_type(c, b, t->params[param]), attrs);
   2999             kit_cg_push_local(cg, args[param]);
   3000             kit_cg_swap(cg);
   3001             kit_cg_store(cg, wasm_cg_mem(c, b, t->params[param]));
   3002           }
   3003           ok = kit_cg_label_new(cg);
   3004           kit_cg_push_local(cg, callee_ref);
   3005           kit_cg_load(cg, ref_mem);
   3006           kit_cg_push_null(cg, rt.void_ptr_ty);
   3007           kit_cg_int_cmp(cg, KIT_CG_INT_NE);
   3008           kit_cg_branch_true(cg, ok);
   3009           wasm_cg_trap_table(cg, &rt);
   3010           kit_cg_label_place(cg, ok);
   3011 
   3012           ok = kit_cg_label_new(cg);
   3013           kit_cg_push_local(cg, callee_ref);
   3014           kit_cg_load(cg, ref_mem);
   3015           kit_cg_bitcast(cg, rt.table_entry_ptr_ty);
   3016           {
   3017             kit_cg_deref(cg, (int64_t)rt.table_entry_typeidx_offset);
   3018             kit_cg_load(cg, i32_mem);
   3019           }
   3020           kit_cg_push_int(cg, (uint32_t)in.imm, b.id[KIT_CG_BUILTIN_I32]);
   3021           kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   3022           kit_cg_branch_true(cg, ok);
   3023           wasm_cg_trap_signature(cg, &rt);
   3024           kit_cg_label_place(cg, ok);
   3025 
   3026           kit_cg_push_local(cg, callee);
   3027           kit_cg_push_local(cg, callee_ref);
   3028           kit_cg_load(cg, ref_mem);
   3029           kit_cg_bitcast(cg, rt.table_entry_ptr_ty);
   3030           {
   3031             kit_cg_deref(cg, (int64_t)rt.table_entry_fn_offset);
   3032             kit_cg_load(cg, ref_mem);
   3033           }
   3034           kit_cg_store(cg, ref_mem);
   3035 
   3036           ref_params[0].type = rt.instance_ptr_ty;
   3037           for (uint32_t p = 0; p < t->nparams; ++p)
   3038             ref_params[p + 1u].type = wasm_cg_type(c, b, t->params[p]);
   3039           memset(&ref_sig, 0, sizeof ref_sig);
   3040           ref_sig.result.type = b.id[KIT_CG_BUILTIN_VOID];
   3041           if (t->nresults)
   3042             ref_sig.result.type = wasm_cg_type(c, b, t->results[0]);
   3043           ref_sig.params = ref_params;
   3044           ref_sig.nparams = t->nparams + 1u;
   3045           ref_sig.call_conv = KIT_CG_CC_TARGET_C;
   3046           ref_func_type = kit_cg_type_func(c, ref_sig);
   3047           if (t->nresults)
   3048             result = kit_cg_local(cg, wasm_cg_type(c, b, t->results[0]), attrs);
   3049           kit_cg_push_local(cg, callee);
   3050           kit_cg_load(cg, ref_mem);
   3051           kit_cg_bitcast(cg, kit_cg_type_ptr(c, ref_func_type, 0));
   3052           kit_cg_push_local(cg, instance_local);
   3053           kit_cg_load(cg, wasm_cg_mem_type(rt.instance_ptr_ty));
   3054           for (uint32_t p = 0; p < t->nparams; ++p) {
   3055             kit_cg_push_local(cg, args[p]);
   3056             kit_cg_load(cg, wasm_cg_mem(c, b, t->params[p]));
   3057           }
   3058           kit_cg_call(
   3059               cg, t->nparams + 1u, ref_func_type,
   3060               (KitCgCallAttrs){.tail = in.kind == WASM_INSN_RETURN_CALL_REF
   3061                                            ? KIT_CG_TAIL_MUST
   3062                                            : KIT_CG_TAIL_DEFAULT});
   3063           if (in.kind == WASM_INSN_RETURN_CALL_REF) {
   3064             if (t->nresults) wasm_cg_push_zero(c, cg, b, t->results[0]);
   3065             kit_cg_unreachable(cg);
   3066           } else if (t->nresults) {
   3067             kit_cg_push_local(cg, result);
   3068             kit_cg_swap(cg);
   3069             kit_cg_store(cg, wasm_cg_mem(c, b, t->results[0]));
   3070             kit_cg_push_local(cg, result);
   3071             kit_cg_load(cg, wasm_cg_mem(c, b, t->results[0]));
   3072           }
   3073           break;
   3074         }
   3075         case WASM_INSN_GLOBAL_GET: {
   3076           uint32_t index = (uint32_t)in.imm;
   3077           wasm_cg_push_global_value_ptr(c, cg, b, &rt, instance_local, m,
   3078                                         index);
   3079           kit_cg_deref(cg, 0);
   3080           kit_cg_load(cg, wasm_cg_mem(c, b, m->globals[index].type));
   3081           break;
   3082         }
   3083         case WASM_INSN_GLOBAL_SET: {
   3084           uint32_t index = (uint32_t)in.imm;
   3085           wasm_cg_push_global_value_ptr(c, cg, b, &rt, instance_local, m,
   3086                                         index);
   3087           kit_cg_deref(cg, 0);
   3088           kit_cg_swap(cg);
   3089           kit_cg_store(cg, wasm_cg_mem(c, b, m->globals[index].type));
   3090           break;
   3091         }
   3092         case WASM_INSN_RETURN:
   3093           kit_cg_ret(cg);
   3094           wasm_cg_drop_to(cg, cur_base);
   3095           dead = 1;
   3096           break;
   3097         case WASM_INSN_DROP:
   3098           kit_cg_drop(cg);
   3099           break;
   3100         case WASM_INSN_MEMORY_SIZE: {
   3101           wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   3102           kit_cg_deref(cg, (int64_t)(rt.memory_offset[in.memidx] +
   3103                                      rt.memory_pages_offset));
   3104           kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   3105           if (!m->memories[in.memidx].is64)
   3106             kit_cg_trunc(cg, b.id[KIT_CG_BUILTIN_I32]);
   3107           break;
   3108         }
   3109         case WASM_INSN_MEMORY_GROW: {
   3110           KitCgLocalAttrs attrs;
   3111           KitCgLocal delta, old_pages, grow_result;
   3112           KitCgLabel fail = kit_cg_label_new(cg);
   3113           KitCgLabel done = kit_cg_label_new(cg);
   3114           WasmValType page_vt =
   3115               m->memories[in.memidx].is64 ? WASM_VAL_I64 : WASM_VAL_I32;
   3116           KitCgTypeId page_ty = wasm_cg_type(c, b, page_vt);
   3117           memset(&attrs, 0, sizeof attrs);
   3118           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3119           delta = kit_cg_local(cg, page_ty, attrs);
   3120           old_pages = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3121           grow_result = kit_cg_local(cg, page_ty, attrs);
   3122           kit_cg_push_local(cg, delta);
   3123           kit_cg_swap(cg);
   3124           kit_cg_store(cg, wasm_cg_mem(c, b, page_vt));
   3125           kit_cg_push_local(cg, old_pages);
   3126           wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   3127           kit_cg_deref(cg, (int64_t)(rt.memory_offset[in.memidx] +
   3128                                      rt.memory_pages_offset));
   3129           kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   3130           kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   3131 
   3132           kit_cg_push_local(cg, delta);
   3133           kit_cg_load(cg, wasm_cg_mem(c, b, page_vt));
   3134           if (!m->memories[in.memidx].is64)
   3135             kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3136           wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   3137           kit_cg_deref(cg, (int64_t)(rt.memory_offset[in.memidx] +
   3138                                      rt.memory_max_pages_offset));
   3139           kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   3140           kit_cg_push_local(cg, old_pages);
   3141           kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   3142           kit_cg_int_binop(cg, KIT_CG_INT_SUB, 0);
   3143           kit_cg_int_cmp(cg, KIT_CG_INT_LE_U);
   3144           kit_cg_branch_false(cg, fail);
   3145 
   3146           wasm_cg_push_instance_ptr(cg, &rt, instance_local);
   3147           kit_cg_deref(cg, (int64_t)(rt.memory_offset[in.memidx] +
   3148                                      rt.memory_pages_offset));
   3149           kit_cg_push_local(cg, old_pages);
   3150           kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   3151           kit_cg_push_local(cg, delta);
   3152           kit_cg_load(cg, wasm_cg_mem(c, b, page_vt));
   3153           if (!m->memories[in.memidx].is64)
   3154             kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3155           kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   3156           kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   3157           kit_cg_push_local(cg, grow_result);
   3158           kit_cg_push_local(cg, old_pages);
   3159           kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   3160           if (!m->memories[in.memidx].is64)
   3161             kit_cg_trunc(cg, b.id[KIT_CG_BUILTIN_I32]);
   3162           kit_cg_store(cg, wasm_cg_mem(c, b, page_vt));
   3163           kit_cg_jump(cg, done);
   3164           kit_cg_label_place(cg, fail);
   3165           kit_cg_push_local(cg, grow_result);
   3166           kit_cg_push_int(cg, UINT64_MAX, page_ty);
   3167           kit_cg_store(cg, wasm_cg_mem(c, b, page_vt));
   3168           kit_cg_label_place(cg, done);
   3169           kit_cg_push_local(cg, grow_result);
   3170           kit_cg_load(cg, wasm_cg_mem(c, b, page_vt));
   3171           break;
   3172         }
   3173         case WASM_INSN_MEMORY_COPY: {
   3174           /* Stack on entry: [dst_addr, src_addr, n] (n at TOS). */
   3175           uint32_t dst_memidx = in.memidx;
   3176           uint32_t src_memidx = in.aux_idx;
   3177           int dst_is64 = m->memories[dst_memidx].is64;
   3178           int src_is64 = m->memories[src_memidx].is64;
   3179           KitCgLocalAttrs attrs;
   3180           KitCgLocal n_l, src_addr_l, dst_addr_l, src_base_l, dst_base_l;
   3181           KitCgLocal src_size_l, dst_size_l;
   3182           KitCgMemAccess i64_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I64]);
   3183           KitCgMemAccess ptr_mem = wasm_cg_mem_type(rt.i8_ptr_ty);
   3184           memset(&attrs, 0, sizeof attrs);
   3185           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3186           n_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3187           src_addr_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3188           dst_addr_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3189           src_base_l = kit_cg_local(cg, rt.i8_ptr_ty, attrs);
   3190           dst_base_l = kit_cg_local(cg, rt.i8_ptr_ty, attrs);
   3191           src_size_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3192           dst_size_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3193           /* Pop n, src_addr, dst_addr into locals (zext if not memory64). */
   3194           kit_cg_push_local(cg, n_l);
   3195           kit_cg_swap(cg);
   3196           if (!dst_is64) kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3197           kit_cg_store(cg, i64_mem);
   3198           kit_cg_push_local(cg, src_addr_l);
   3199           kit_cg_swap(cg);
   3200           if (!src_is64) kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3201           kit_cg_store(cg, i64_mem);
   3202           kit_cg_push_local(cg, dst_addr_l);
   3203           kit_cg_swap(cg);
   3204           if (!dst_is64) kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3205           kit_cg_store(cg, i64_mem);
   3206           /* Cache base and size for src and dst memories. */
   3207           kit_cg_push_local(cg, src_base_l);
   3208           wasm_cg_push_memory_data_ptr(cg, &rt, instance_local, src_memidx);
   3209           kit_cg_store(cg, ptr_mem);
   3210           kit_cg_push_local(cg, dst_base_l);
   3211           wasm_cg_push_memory_data_ptr(cg, &rt, instance_local, dst_memidx);
   3212           kit_cg_store(cg, ptr_mem);
   3213           kit_cg_push_local(cg, src_size_l);
   3214           wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local, src_memidx);
   3215           kit_cg_load(cg, i64_mem);
   3216           kit_cg_push_int(cg, 65536u, b.id[KIT_CG_BUILTIN_I64]);
   3217           kit_cg_int_binop(cg, KIT_CG_INT_MUL, 0);
   3218           kit_cg_store(cg, i64_mem);
   3219           kit_cg_push_local(cg, dst_size_l);
   3220           wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local, dst_memidx);
   3221           kit_cg_load(cg, i64_mem);
   3222           kit_cg_push_int(cg, 65536u, b.id[KIT_CG_BUILTIN_I64]);
   3223           kit_cg_int_binop(cg, KIT_CG_INT_MUL, 0);
   3224           kit_cg_store(cg, i64_mem);
   3225           wasm_cg_bulk_bounds_check(cg, b, &rt, src_addr_l, n_l, src_size_l);
   3226           wasm_cg_bulk_bounds_check(cg, b, &rt, dst_addr_l, n_l, dst_size_l);
   3227           wasm_cg_emit_byte_copy_loop(cg, b, &rt, dst_base_l, src_base_l,
   3228                                       dst_addr_l, src_addr_l, n_l);
   3229           break;
   3230         }
   3231         case WASM_INSN_MEMORY_FILL: {
   3232           /* Stack: [dst_addr, val, n] (n at TOS). */
   3233           uint32_t memidx = in.memidx;
   3234           int is64 = m->memories[memidx].is64;
   3235           KitCgLocalAttrs attrs;
   3236           KitCgLocal n_l, val_l, dst_addr_l, dst_base_l, dst_size_l;
   3237           KitCgMemAccess i64_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I64]);
   3238           KitCgMemAccess i32_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I32]);
   3239           KitCgMemAccess ptr_mem = wasm_cg_mem_type(rt.i8_ptr_ty);
   3240           memset(&attrs, 0, sizeof attrs);
   3241           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3242           n_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3243           val_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3244           dst_addr_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3245           dst_base_l = kit_cg_local(cg, rt.i8_ptr_ty, attrs);
   3246           dst_size_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3247           kit_cg_push_local(cg, n_l);
   3248           kit_cg_swap(cg);
   3249           if (!is64) kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3250           kit_cg_store(cg, i64_mem);
   3251           kit_cg_push_local(cg, val_l);
   3252           kit_cg_swap(cg);
   3253           kit_cg_store(cg, i32_mem);
   3254           kit_cg_push_local(cg, dst_addr_l);
   3255           kit_cg_swap(cg);
   3256           if (!is64) kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3257           kit_cg_store(cg, i64_mem);
   3258           kit_cg_push_local(cg, dst_base_l);
   3259           wasm_cg_push_memory_data_ptr(cg, &rt, instance_local, memidx);
   3260           kit_cg_store(cg, ptr_mem);
   3261           kit_cg_push_local(cg, dst_size_l);
   3262           wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local, memidx);
   3263           kit_cg_load(cg, i64_mem);
   3264           kit_cg_push_int(cg, 65536u, b.id[KIT_CG_BUILTIN_I64]);
   3265           kit_cg_int_binop(cg, KIT_CG_INT_MUL, 0);
   3266           kit_cg_store(cg, i64_mem);
   3267           wasm_cg_bulk_bounds_check(cg, b, &rt, dst_addr_l, n_l, dst_size_l);
   3268           wasm_cg_emit_byte_fill_loop(cg, b, &rt, dst_base_l, dst_addr_l, val_l,
   3269                                       n_l);
   3270           break;
   3271         }
   3272         case WASM_INSN_MEMORY_INIT: {
   3273           /* Stack: [dst_addr, src_addr, n]; in.imm = dataidx; in.memidx =
   3274            * memidx */
   3275           uint32_t dataidx = (uint32_t)in.imm;
   3276           uint32_t memidx = in.memidx;
   3277           int is64 = m->memories[memidx].is64;
   3278           KitCgLocalAttrs attrs;
   3279           KitCgLocal n_l, src_addr_l, dst_addr_l, src_base_l, dst_base_l;
   3280           KitCgLocal src_size_l, dst_size_l;
   3281           KitCgMemAccess i64_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I64]);
   3282           KitCgMemAccess ptr_mem = wasm_cg_mem_type(rt.i8_ptr_ty);
   3283           memset(&attrs, 0, sizeof attrs);
   3284           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3285           n_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3286           src_addr_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3287           dst_addr_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3288           src_base_l = kit_cg_local(cg, rt.i8_ptr_ty, attrs);
   3289           dst_base_l = kit_cg_local(cg, rt.i8_ptr_ty, attrs);
   3290           src_size_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3291           dst_size_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3292           kit_cg_push_local(cg, n_l);
   3293           kit_cg_swap(cg);
   3294           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3295           kit_cg_store(cg, i64_mem);
   3296           kit_cg_push_local(cg, src_addr_l);
   3297           kit_cg_swap(cg);
   3298           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3299           kit_cg_store(cg, i64_mem);
   3300           kit_cg_push_local(cg, dst_addr_l);
   3301           kit_cg_swap(cg);
   3302           if (!is64) kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3303           kit_cg_store(cg, i64_mem);
   3304           /* src_base = inst->passive_data[dataidx].base */
   3305           kit_cg_push_local(cg, src_base_l);
   3306           wasm_cg_push_passive_data_lvalue(cg, &rt, instance_local, dataidx);
   3307           kit_cg_field(cg, rt.passive_data_base_field);
   3308           kit_cg_load(cg, ptr_mem);
   3309           kit_cg_store(cg, ptr_mem);
   3310           /* src_size = inst->passive_data[dataidx].len */
   3311           kit_cg_push_local(cg, src_size_l);
   3312           wasm_cg_push_passive_data_lvalue(cg, &rt, instance_local, dataidx);
   3313           kit_cg_field(cg, rt.passive_data_len_field);
   3314           kit_cg_load(cg, i64_mem);
   3315           kit_cg_store(cg, i64_mem);
   3316           kit_cg_push_local(cg, dst_base_l);
   3317           wasm_cg_push_memory_data_ptr(cg, &rt, instance_local, memidx);
   3318           kit_cg_store(cg, ptr_mem);
   3319           kit_cg_push_local(cg, dst_size_l);
   3320           wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local, memidx);
   3321           kit_cg_load(cg, i64_mem);
   3322           kit_cg_push_int(cg, 65536u, b.id[KIT_CG_BUILTIN_I64]);
   3323           kit_cg_int_binop(cg, KIT_CG_INT_MUL, 0);
   3324           kit_cg_store(cg, i64_mem);
   3325           wasm_cg_bulk_bounds_check(cg, b, &rt, src_addr_l, n_l, src_size_l);
   3326           wasm_cg_bulk_bounds_check(cg, b, &rt, dst_addr_l, n_l, dst_size_l);
   3327           wasm_cg_emit_byte_copy_loop(cg, b, &rt, dst_base_l, src_base_l,
   3328                                       dst_addr_l, src_addr_l, n_l);
   3329           break;
   3330         }
   3331         case WASM_INSN_DATA_DROP: {
   3332           uint32_t dataidx = (uint32_t)in.imm;
   3333           wasm_cg_push_passive_data_lvalue(cg, &rt, instance_local, dataidx);
   3334           kit_cg_field(cg, rt.passive_data_len_field);
   3335           kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I64]);
   3336           kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   3337           break;
   3338         }
   3339         case WASM_INSN_ELEM_DROP: {
   3340           uint32_t elemidx = (uint32_t)in.imm;
   3341           wasm_cg_push_passive_elem_lvalue(cg, &rt, instance_local, elemidx);
   3342           kit_cg_field(cg, rt.passive_elem_length_field);
   3343           kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I32]);
   3344           kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   3345           break;
   3346         }
   3347         case WASM_INSN_TABLE_SIZE: {
   3348           uint32_t tableidx = (uint32_t)in.imm;
   3349           wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
   3350           kit_cg_field(cg, rt.table_len_field);
   3351           kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   3352           break;
   3353         }
   3354         case WASM_INSN_TABLE_GROW: {
   3355           /* Stack: [val, delta] -> [prev_size or -1 on failure].
   3356            * Implementation: if current_len + delta <= max, write zeros into
   3357            * new slots (we ignore val for funcref since slots are owned), then
   3358            * bump len. We do honor val for funcref by writing the supplied
   3359            * funcref into each new slot. */
   3360           uint32_t tableidx = (uint32_t)in.imm;
   3361           KitCgLocalAttrs attrs;
   3362           KitCgLocal val_l, delta_l, old_len_l, result_l, idx_l;
   3363           KitCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
   3364           KitCgMemAccess fn_mem = wasm_cg_mem_type(rt.void_ptr_ty);
   3365           KitCgLabel fail = kit_cg_label_new(cg);
   3366           KitCgLabel done = kit_cg_label_new(cg);
   3367           KitCgLabel fill_loop = kit_cg_label_new(cg);
   3368           memset(&attrs, 0, sizeof attrs);
   3369           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3370           delta_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3371           val_l = kit_cg_local(cg, rt.void_ptr_ty, attrs);
   3372           old_len_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3373           result_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3374           idx_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3375           kit_cg_push_local(cg, delta_l);
   3376           kit_cg_swap(cg);
   3377           kit_cg_store(cg, i32_mem);
   3378           kit_cg_push_local(cg, val_l);
   3379           kit_cg_swap(cg);
   3380           kit_cg_store(cg, fn_mem);
   3381           /* Cache val into fn/typeidx locals so the fill loop writes the
   3382            * correct pair into each new slot. A null ref grows with null slots.
   3383            */
   3384           KitCgLocal val_fn_l = kit_cg_local(cg, rt.void_ptr_ty, attrs);
   3385           KitCgLocal val_typeidx_l =
   3386               kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3387           wasm_cg_cache_funcref_entry(c, cg, b, &rt, val_l, val_fn_l,
   3388                                       val_typeidx_l, fn_mem, i32_mem);
   3389           kit_cg_push_local(cg, old_len_l);
   3390           wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
   3391           kit_cg_field(cg, rt.table_len_field);
   3392           kit_cg_load(cg, i32_mem);
   3393           kit_cg_store(cg, i32_mem);
   3394           /* Check old_len + delta <= max. */
   3395           wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
   3396           kit_cg_field(cg, rt.table_max_field);
   3397           kit_cg_load(cg, i32_mem);
   3398           kit_cg_push_local(cg, old_len_l);
   3399           kit_cg_load(cg, i32_mem);
   3400           kit_cg_int_cmp(cg, KIT_CG_INT_LT_U);
   3401           kit_cg_branch_true(cg, fail);
   3402           /* max - old_len >= delta */
   3403           wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
   3404           kit_cg_field(cg, rt.table_max_field);
   3405           kit_cg_load(cg, i32_mem);
   3406           kit_cg_push_local(cg, old_len_l);
   3407           kit_cg_load(cg, i32_mem);
   3408           kit_cg_int_binop(cg, KIT_CG_INT_SUB, 0);
   3409           kit_cg_push_local(cg, delta_l);
   3410           kit_cg_load(cg, i32_mem);
   3411           kit_cg_int_cmp(cg, KIT_CG_INT_LT_U);
   3412           kit_cg_branch_true(cg, fail);
   3413           /* Update length first. */
   3414           wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
   3415           kit_cg_field(cg, rt.table_len_field);
   3416           kit_cg_push_local(cg, old_len_l);
   3417           kit_cg_load(cg, i32_mem);
   3418           kit_cg_push_local(cg, delta_l);
   3419           kit_cg_load(cg, i32_mem);
   3420           kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   3421           kit_cg_store(cg, i32_mem);
   3422           /* Initialize new slots [old_len, old_len+delta) to val. */
   3423           kit_cg_push_local(cg, idx_l);
   3424           kit_cg_push_local(cg, old_len_l);
   3425           kit_cg_load(cg, i32_mem);
   3426           kit_cg_store(cg, i32_mem);
   3427           kit_cg_label_place(cg, fill_loop);
   3428           kit_cg_push_local(cg, idx_l);
   3429           kit_cg_load(cg, i32_mem);
   3430           kit_cg_push_local(cg, old_len_l);
   3431           kit_cg_load(cg, i32_mem);
   3432           kit_cg_push_local(cg, delta_l);
   3433           kit_cg_load(cg, i32_mem);
   3434           kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   3435           kit_cg_int_cmp(cg, KIT_CG_INT_GE_U);
   3436           {
   3437             KitCgLabel fill_end = kit_cg_label_new(cg);
   3438             kit_cg_branch_true(cg, fill_end);
   3439             wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local, tableidx,
   3440                                             idx_l, i32_mem);
   3441             kit_cg_field(cg, rt.table_entry_fn_field);
   3442             kit_cg_push_local(cg, val_fn_l);
   3443             kit_cg_load(cg, fn_mem);
   3444             kit_cg_store(cg, fn_mem);
   3445             wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local, tableidx,
   3446                                             idx_l, i32_mem);
   3447             kit_cg_field(cg, rt.table_entry_typeidx_field);
   3448             kit_cg_push_local(cg, val_typeidx_l);
   3449             kit_cg_load(cg, i32_mem);
   3450             kit_cg_store(cg, i32_mem);
   3451             kit_cg_push_local(cg, idx_l);
   3452             kit_cg_push_local(cg, idx_l);
   3453             kit_cg_load(cg, i32_mem);
   3454             kit_cg_push_int(cg, 1, b.id[KIT_CG_BUILTIN_I32]);
   3455             kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   3456             kit_cg_store(cg, i32_mem);
   3457             kit_cg_jump(cg, fill_loop);
   3458             kit_cg_label_place(cg, fill_end);
   3459           }
   3460           kit_cg_push_local(cg, result_l);
   3461           kit_cg_push_local(cg, old_len_l);
   3462           kit_cg_load(cg, i32_mem);
   3463           kit_cg_store(cg, i32_mem);
   3464           kit_cg_jump(cg, done);
   3465           kit_cg_label_place(cg, fail);
   3466           kit_cg_push_local(cg, result_l);
   3467           kit_cg_push_int(cg, UINT32_C(0xffffffff), b.id[KIT_CG_BUILTIN_I32]);
   3468           kit_cg_store(cg, i32_mem);
   3469           kit_cg_label_place(cg, done);
   3470           kit_cg_push_local(cg, result_l);
   3471           kit_cg_load(cg, i32_mem);
   3472           break;
   3473         }
   3474         case WASM_INSN_TABLE_FILL: {
   3475           /* Stack: [dst_idx, val, n]. `val` is a `KitWasmTableEntry*`
   3476            * pointing at an instance-resident funcref slot (produced by
   3477            * ref.func). To populate table slots correctly, we dereference
   3478            * `val` once outside the loop into local fn/typeidx pairs and
   3479            * then copy those into each slot. */
   3480           uint32_t tableidx = (uint32_t)in.imm;
   3481           KitCgLocalAttrs attrs;
   3482           KitCgLocal n_l, val_l, dst_idx_l, len_l, idx_l;
   3483           KitCgLocal val_fn_l, val_typeidx_l;
   3484           KitCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
   3485           KitCgMemAccess fn_mem = wasm_cg_mem_type(rt.void_ptr_ty);
   3486           KitCgLabel loop = kit_cg_label_new(cg);
   3487           KitCgLabel done = kit_cg_label_new(cg);
   3488           KitCgLabel ok = kit_cg_label_new(cg);
   3489           memset(&attrs, 0, sizeof attrs);
   3490           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3491           n_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3492           val_l = kit_cg_local(cg, rt.void_ptr_ty, attrs);
   3493           dst_idx_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3494           len_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3495           idx_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3496           val_fn_l = kit_cg_local(cg, rt.void_ptr_ty, attrs);
   3497           val_typeidx_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3498           kit_cg_push_local(cg, n_l);
   3499           kit_cg_swap(cg);
   3500           kit_cg_store(cg, i32_mem);
   3501           kit_cg_push_local(cg, val_l);
   3502           kit_cg_swap(cg);
   3503           kit_cg_store(cg, fn_mem);
   3504           kit_cg_push_local(cg, dst_idx_l);
   3505           kit_cg_swap(cg);
   3506           kit_cg_store(cg, i32_mem);
   3507           /* Cache val into (val_fn, val_typeidx). Null refs fill with null
   3508            * entries and are checked later by call_indirect/call_ref. */
   3509           wasm_cg_cache_funcref_entry(c, cg, b, &rt, val_l, val_fn_l,
   3510                                       val_typeidx_l, fn_mem, i32_mem);
   3511           /* Bounds check: dst_idx + n <= len. */
   3512           kit_cg_push_local(cg, len_l);
   3513           wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
   3514           kit_cg_field(cg, rt.table_len_field);
   3515           kit_cg_load(cg, i32_mem);
   3516           kit_cg_store(cg, i32_mem);
   3517           kit_cg_push_local(cg, len_l);
   3518           kit_cg_load(cg, i32_mem);
   3519           kit_cg_push_local(cg, dst_idx_l);
   3520           kit_cg_load(cg, i32_mem);
   3521           kit_cg_int_cmp(cg, KIT_CG_INT_GE_U);
   3522           kit_cg_branch_true(cg, ok);
   3523           wasm_cg_trap_bounds(cg, &rt);
   3524           kit_cg_label_place(cg, ok);
   3525           {
   3526             KitCgLabel ok2 = kit_cg_label_new(cg);
   3527             kit_cg_push_local(cg, len_l);
   3528             kit_cg_load(cg, i32_mem);
   3529             kit_cg_push_local(cg, dst_idx_l);
   3530             kit_cg_load(cg, i32_mem);
   3531             kit_cg_int_binop(cg, KIT_CG_INT_SUB, 0);
   3532             kit_cg_push_local(cg, n_l);
   3533             kit_cg_load(cg, i32_mem);
   3534             kit_cg_int_cmp(cg, KIT_CG_INT_GE_U);
   3535             kit_cg_branch_true(cg, ok2);
   3536             wasm_cg_trap_bounds(cg, &rt);
   3537             kit_cg_label_place(cg, ok2);
   3538           }
   3539           /* idx = 0; while idx < n: table[dst_idx+idx] = val; idx++ */
   3540           kit_cg_push_local(cg, idx_l);
   3541           kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I32]);
   3542           kit_cg_store(cg, i32_mem);
   3543           kit_cg_label_place(cg, loop);
   3544           kit_cg_push_local(cg, idx_l);
   3545           kit_cg_load(cg, i32_mem);
   3546           kit_cg_push_local(cg, n_l);
   3547           kit_cg_load(cg, i32_mem);
   3548           kit_cg_int_cmp(cg, KIT_CG_INT_GE_U);
   3549           kit_cg_branch_true(cg, done);
   3550           {
   3551             /* Compute slot = dst_idx + idx, store into a temp local for
   3552              * indexing. */
   3553             KitCgLocal slot_l =
   3554                 kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3555             kit_cg_push_local(cg, slot_l);
   3556             kit_cg_push_local(cg, dst_idx_l);
   3557             kit_cg_load(cg, i32_mem);
   3558             kit_cg_push_local(cg, idx_l);
   3559             kit_cg_load(cg, i32_mem);
   3560             kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   3561             kit_cg_store(cg, i32_mem);
   3562             wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local, tableidx,
   3563                                             slot_l, i32_mem);
   3564             kit_cg_field(cg, rt.table_entry_fn_field);
   3565             kit_cg_push_local(cg, val_fn_l);
   3566             kit_cg_load(cg, fn_mem);
   3567             kit_cg_store(cg, fn_mem);
   3568             wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local, tableidx,
   3569                                             slot_l, i32_mem);
   3570             kit_cg_field(cg, rt.table_entry_typeidx_field);
   3571             kit_cg_push_local(cg, val_typeidx_l);
   3572             kit_cg_load(cg, i32_mem);
   3573             kit_cg_store(cg, i32_mem);
   3574           }
   3575           kit_cg_push_local(cg, idx_l);
   3576           kit_cg_push_local(cg, idx_l);
   3577           kit_cg_load(cg, i32_mem);
   3578           kit_cg_push_int(cg, 1, b.id[KIT_CG_BUILTIN_I32]);
   3579           kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   3580           kit_cg_store(cg, i32_mem);
   3581           kit_cg_jump(cg, loop);
   3582           kit_cg_label_place(cg, done);
   3583           break;
   3584         }
   3585         case WASM_INSN_TABLE_COPY: {
   3586           /* Stack: [dst_idx, src_idx, n]; in.imm = dst_tableidx; in.aux_idx =
   3587            * src */
   3588           uint32_t dst_tbl = (uint32_t)in.imm;
   3589           uint32_t src_tbl = in.aux_idx;
   3590           KitCgLocalAttrs attrs;
   3591           KitCgLocal n_l, src_idx_l, dst_idx_l, src_base_l, dst_base_l;
   3592           KitCgLocal src_len_l, dst_len_l;
   3593           KitCgMemAccess i64_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I64]);
   3594           KitCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
   3595           KitCgMemAccess ptr_mem = wasm_cg_mem_type(rt.table_entry_ptr_ty);
   3596           memset(&attrs, 0, sizeof attrs);
   3597           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3598           n_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3599           src_idx_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3600           dst_idx_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3601           src_base_l = kit_cg_local(cg, rt.table_entry_ptr_ty, attrs);
   3602           dst_base_l = kit_cg_local(cg, rt.table_entry_ptr_ty, attrs);
   3603           src_len_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3604           dst_len_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3605           kit_cg_push_local(cg, n_l);
   3606           kit_cg_swap(cg);
   3607           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3608           kit_cg_store(cg, i64_mem);
   3609           kit_cg_push_local(cg, src_idx_l);
   3610           kit_cg_swap(cg);
   3611           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3612           kit_cg_store(cg, i64_mem);
   3613           kit_cg_push_local(cg, dst_idx_l);
   3614           kit_cg_swap(cg);
   3615           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3616           kit_cg_store(cg, i64_mem);
   3617           kit_cg_push_local(cg, src_base_l);
   3618           wasm_cg_push_table_lvalue(cg, &rt, instance_local, src_tbl);
   3619           kit_cg_field(cg, rt.table_entries_ptr_field);
   3620           kit_cg_load(cg, ptr_mem);
   3621           kit_cg_store(cg, ptr_mem);
   3622           kit_cg_push_local(cg, dst_base_l);
   3623           wasm_cg_push_table_lvalue(cg, &rt, instance_local, dst_tbl);
   3624           kit_cg_field(cg, rt.table_entries_ptr_field);
   3625           kit_cg_load(cg, ptr_mem);
   3626           kit_cg_store(cg, ptr_mem);
   3627           kit_cg_push_local(cg, src_len_l);
   3628           wasm_cg_push_table_lvalue(cg, &rt, instance_local, src_tbl);
   3629           kit_cg_field(cg, rt.table_len_field);
   3630           kit_cg_load(cg, i32_mem);
   3631           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3632           kit_cg_store(cg, i64_mem);
   3633           kit_cg_push_local(cg, dst_len_l);
   3634           wasm_cg_push_table_lvalue(cg, &rt, instance_local, dst_tbl);
   3635           kit_cg_field(cg, rt.table_len_field);
   3636           kit_cg_load(cg, i32_mem);
   3637           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3638           kit_cg_store(cg, i64_mem);
   3639           wasm_cg_bulk_bounds_check(cg, b, &rt, src_idx_l, n_l, src_len_l);
   3640           wasm_cg_bulk_bounds_check(cg, b, &rt, dst_idx_l, n_l, dst_len_l);
   3641           wasm_cg_emit_table_copy_loop(c, cg, b, &rt, dst_base_l, src_base_l,
   3642                                        dst_idx_l, src_idx_l, n_l);
   3643           break;
   3644         }
   3645         case WASM_INSN_TABLE_INIT: {
   3646           /* Stack: [dst_idx, src_idx, n]; in.imm = elemidx; in.aux_idx =
   3647            * tableidx */
   3648           uint32_t elemidx = (uint32_t)in.imm;
   3649           uint32_t tableidx = in.aux_idx;
   3650           KitCgLocalAttrs attrs;
   3651           KitCgLocal n_l, src_idx_l, dst_idx_l, src_base_l, dst_base_l;
   3652           KitCgLocal src_len_l, dst_len_l;
   3653           KitCgMemAccess i64_mem = wasm_cg_mem_type(b.id[KIT_CG_BUILTIN_I64]);
   3654           KitCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
   3655           KitCgMemAccess ptr_mem = wasm_cg_mem_type(rt.table_entry_ptr_ty);
   3656           memset(&attrs, 0, sizeof attrs);
   3657           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3658           n_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3659           src_idx_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3660           dst_idx_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3661           src_base_l = kit_cg_local(cg, rt.table_entry_ptr_ty, attrs);
   3662           dst_base_l = kit_cg_local(cg, rt.table_entry_ptr_ty, attrs);
   3663           src_len_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3664           dst_len_l = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3665           kit_cg_push_local(cg, n_l);
   3666           kit_cg_swap(cg);
   3667           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3668           kit_cg_store(cg, i64_mem);
   3669           kit_cg_push_local(cg, src_idx_l);
   3670           kit_cg_swap(cg);
   3671           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3672           kit_cg_store(cg, i64_mem);
   3673           kit_cg_push_local(cg, dst_idx_l);
   3674           kit_cg_swap(cg);
   3675           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3676           kit_cg_store(cg, i64_mem);
   3677           kit_cg_push_local(cg, src_base_l);
   3678           wasm_cg_push_passive_elem_lvalue(cg, &rt, instance_local, elemidx);
   3679           kit_cg_field(cg, rt.passive_elem_entries_field);
   3680           kit_cg_load(cg, ptr_mem);
   3681           kit_cg_store(cg, ptr_mem);
   3682           kit_cg_push_local(cg, dst_base_l);
   3683           wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
   3684           kit_cg_field(cg, rt.table_entries_ptr_field);
   3685           kit_cg_load(cg, ptr_mem);
   3686           kit_cg_store(cg, ptr_mem);
   3687           kit_cg_push_local(cg, src_len_l);
   3688           wasm_cg_push_passive_elem_lvalue(cg, &rt, instance_local, elemidx);
   3689           kit_cg_field(cg, rt.passive_elem_length_field);
   3690           kit_cg_load(cg, i32_mem);
   3691           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3692           kit_cg_store(cg, i64_mem);
   3693           kit_cg_push_local(cg, dst_len_l);
   3694           wasm_cg_push_table_lvalue(cg, &rt, instance_local, tableidx);
   3695           kit_cg_field(cg, rt.table_len_field);
   3696           kit_cg_load(cg, i32_mem);
   3697           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   3698           kit_cg_store(cg, i64_mem);
   3699           wasm_cg_bulk_bounds_check(cg, b, &rt, src_idx_l, n_l, src_len_l);
   3700           wasm_cg_bulk_bounds_check(cg, b, &rt, dst_idx_l, n_l, dst_len_l);
   3701           wasm_cg_emit_table_copy_loop(c, cg, b, &rt, dst_base_l, src_base_l,
   3702                                        dst_idx_l, src_idx_l, n_l);
   3703           break;
   3704         }
   3705         case WASM_INSN_I32_TRUNC_SAT_F32_S:
   3706         case WASM_INSN_I32_TRUNC_SAT_F64_S:
   3707           kit_cg_float_to_sint(cg, b.id[KIT_CG_BUILTIN_I32],
   3708                                KIT_CG_ROUND_TOWARD_ZERO);
   3709           break;
   3710         case WASM_INSN_I32_TRUNC_SAT_F32_U:
   3711         case WASM_INSN_I32_TRUNC_SAT_F64_U:
   3712           kit_cg_float_to_uint(cg, b.id[KIT_CG_BUILTIN_I32],
   3713                                KIT_CG_ROUND_TOWARD_ZERO);
   3714           break;
   3715         case WASM_INSN_I64_TRUNC_SAT_F32_S:
   3716         case WASM_INSN_I64_TRUNC_SAT_F64_S:
   3717           kit_cg_float_to_sint(cg, b.id[KIT_CG_BUILTIN_I64],
   3718                                KIT_CG_ROUND_TOWARD_ZERO);
   3719           break;
   3720         case WASM_INSN_I64_TRUNC_SAT_F32_U:
   3721         case WASM_INSN_I64_TRUNC_SAT_F64_U:
   3722           kit_cg_float_to_uint(cg, b.id[KIT_CG_BUILTIN_I64],
   3723                                KIT_CG_ROUND_TOWARD_ZERO);
   3724           break;
   3725         case WASM_INSN_ATOMIC_FENCE:
   3726           kit_cg_atomic_fence(cg, KIT_CG_MO_SEQ_CST);
   3727           break;
   3728         case WASM_INSN_I32_ATOMIC_LOAD:
   3729         case WASM_INSN_I64_ATOMIC_LOAD:
   3730         case WASM_INSN_I32_ATOMIC_LOAD8_U:
   3731         case WASM_INSN_I32_ATOMIC_LOAD16_U:
   3732         case WASM_INSN_I64_ATOMIC_LOAD8_U:
   3733         case WASM_INSN_I64_ATOMIC_LOAD16_U:
   3734         case WASM_INSN_I64_ATOMIC_LOAD32_U: {
   3735           KitCgTypeId ty = wasm_cg_type(c, b, wasm_atomic_value_type(in.kind));
   3736           KitCgMemAccess mem = wasm_cg_mem_type(ty);
   3737           mem.align = in.align;
   3738           wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
   3739           wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
   3740                                        in.offset64);
   3741           kit_cg_atomic_load(cg, mem, KIT_CG_MO_SEQ_CST);
   3742           break;
   3743         }
   3744         case WASM_INSN_I32_ATOMIC_STORE:
   3745         case WASM_INSN_I64_ATOMIC_STORE:
   3746         case WASM_INSN_I32_ATOMIC_STORE8:
   3747         case WASM_INSN_I32_ATOMIC_STORE16:
   3748         case WASM_INSN_I64_ATOMIC_STORE8:
   3749         case WASM_INSN_I64_ATOMIC_STORE16:
   3750         case WASM_INSN_I64_ATOMIC_STORE32: {
   3751           WasmValType vt = wasm_atomic_value_type(in.kind);
   3752           KitCgTypeId ty = wasm_cg_type(c, b, vt);
   3753           KitCgMemAccess mem = wasm_cg_mem_type(ty);
   3754           KitCgLocalAttrs attrs;
   3755           KitCgLocal value_tmp;
   3756           memset(&attrs, 0, sizeof attrs);
   3757           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3758           mem.align = in.align;
   3759           value_tmp = kit_cg_local(cg, ty, attrs);
   3760           kit_cg_push_local(cg, value_tmp);
   3761           kit_cg_swap(cg);
   3762           kit_cg_store(cg, mem);
   3763           wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
   3764           wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
   3765                                        in.offset64);
   3766           kit_cg_push_local(cg, value_tmp);
   3767           kit_cg_load(cg, mem);
   3768           kit_cg_atomic_store(cg, mem, KIT_CG_MO_SEQ_CST);
   3769           break;
   3770         }
   3771         case WASM_INSN_I32_ATOMIC_RMW_ADD:
   3772         case WASM_INSN_I64_ATOMIC_RMW_ADD:
   3773         case WASM_INSN_I32_ATOMIC_RMW_SUB:
   3774         case WASM_INSN_I64_ATOMIC_RMW_SUB:
   3775         case WASM_INSN_I32_ATOMIC_RMW_AND:
   3776         case WASM_INSN_I64_ATOMIC_RMW_AND:
   3777         case WASM_INSN_I32_ATOMIC_RMW_OR:
   3778         case WASM_INSN_I64_ATOMIC_RMW_OR:
   3779         case WASM_INSN_I32_ATOMIC_RMW_XOR:
   3780         case WASM_INSN_I64_ATOMIC_RMW_XOR:
   3781         case WASM_INSN_I32_ATOMIC_RMW_XCHG:
   3782         case WASM_INSN_I64_ATOMIC_RMW_XCHG: {
   3783           WasmValType vt = wasm_atomic_value_type(in.kind);
   3784           KitCgTypeId ty = wasm_cg_type(c, b, vt);
   3785           KitCgMemAccess mem = wasm_cg_mem_type(ty);
   3786           KitCgLocalAttrs attrs;
   3787           KitCgLocal value_tmp;
   3788           memset(&attrs, 0, sizeof attrs);
   3789           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3790           mem.align = in.align;
   3791           value_tmp = kit_cg_local(cg, ty, attrs);
   3792           kit_cg_push_local(cg, value_tmp);
   3793           kit_cg_swap(cg);
   3794           kit_cg_store(cg, mem);
   3795           wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
   3796           wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
   3797                                        in.offset64);
   3798           kit_cg_push_local(cg, value_tmp);
   3799           kit_cg_load(cg, mem);
   3800           kit_cg_atomic_rmw(cg, mem, wasm_atomic_rmw_op(in.kind),
   3801                             KIT_CG_MO_SEQ_CST);
   3802           break;
   3803         }
   3804         case WASM_INSN_I32_ATOMIC_RMW_CMPXCHG:
   3805         case WASM_INSN_I64_ATOMIC_RMW_CMPXCHG: {
   3806           WasmValType vt = wasm_atomic_value_type(in.kind);
   3807           KitCgTypeId ty = wasm_cg_type(c, b, vt);
   3808           KitCgMemAccess mem = wasm_cg_mem_type(ty);
   3809           KitCgLocalAttrs attrs;
   3810           KitCgLocal expected_tmp, desired_tmp;
   3811           memset(&attrs, 0, sizeof attrs);
   3812           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3813           mem.align = in.align;
   3814           desired_tmp = kit_cg_local(cg, ty, attrs);
   3815           expected_tmp = kit_cg_local(cg, ty, attrs);
   3816           kit_cg_push_local(cg, desired_tmp);
   3817           kit_cg_swap(cg);
   3818           kit_cg_store(cg, mem);
   3819           kit_cg_push_local(cg, expected_tmp);
   3820           kit_cg_swap(cg);
   3821           kit_cg_store(cg, mem);
   3822           wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
   3823           wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
   3824                                        in.offset64);
   3825           kit_cg_push_local(cg, expected_tmp);
   3826           kit_cg_load(cg, mem);
   3827           kit_cg_push_local(cg, desired_tmp);
   3828           kit_cg_load(cg, mem);
   3829           kit_cg_atomic_cmpxchg(cg, mem, KIT_CG_MO_SEQ_CST, KIT_CG_MO_SEQ_CST,
   3830                                 0);
   3831           kit_cg_drop(cg);
   3832           break;
   3833         }
   3834         case WASM_INSN_I32_ATOMIC_WAIT:
   3835         case WASM_INSN_I64_ATOMIC_WAIT: {
   3836           WasmValType vt = wasm_atomic_value_type(in.kind);
   3837           KitCgTypeId ty = wasm_cg_type(c, b, vt);
   3838           KitCgMemAccess mem = wasm_cg_mem_type(ty);
   3839           KitCgLocalAttrs attrs;
   3840           KitCgLocal timeout_tmp, expected_tmp, result_tmp;
   3841           KitCgLabel equal = kit_cg_label_new(cg);
   3842           KitCgLabel done = kit_cg_label_new(cg);
   3843           memset(&attrs, 0, sizeof attrs);
   3844           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3845           mem.align = in.align;
   3846           timeout_tmp = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I64], attrs);
   3847           expected_tmp = kit_cg_local(cg, ty, attrs);
   3848           result_tmp = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3849           kit_cg_push_local(cg, timeout_tmp);
   3850           kit_cg_swap(cg);
   3851           kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I64));
   3852           kit_cg_push_local(cg, expected_tmp);
   3853           kit_cg_swap(cg);
   3854           kit_cg_store(cg, mem);
   3855           wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
   3856           wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
   3857                                        in.offset64);
   3858           kit_cg_atomic_load(cg, mem, KIT_CG_MO_SEQ_CST);
   3859           kit_cg_push_local(cg, expected_tmp);
   3860           kit_cg_load(cg, mem);
   3861           kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   3862           kit_cg_branch_true(cg, equal);
   3863           kit_cg_push_local(cg, result_tmp);
   3864           kit_cg_push_int(cg, 1, b.id[KIT_CG_BUILTIN_I32]);
   3865           kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   3866           kit_cg_jump(cg, done);
   3867           kit_cg_label_place(cg, equal);
   3868           (void)timeout_tmp;
   3869           kit_cg_push_local(cg, result_tmp);
   3870           kit_cg_push_int(cg, 2, b.id[KIT_CG_BUILTIN_I32]);
   3871           kit_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   3872           kit_cg_label_place(cg, done);
   3873           kit_cg_push_local(cg, result_tmp);
   3874           kit_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
   3875           break;
   3876         }
   3877         case WASM_INSN_MEMORY_ATOMIC_NOTIFY: {
   3878           KitCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
   3879           KitCgLocalAttrs attrs;
   3880           KitCgLocal count_tmp;
   3881           memset(&attrs, 0, sizeof attrs);
   3882           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3883           count_tmp = kit_cg_local(cg, b.id[KIT_CG_BUILTIN_I32], attrs);
   3884           kit_cg_push_local(cg, count_tmp);
   3885           kit_cg_swap(cg);
   3886           kit_cg_store(cg, i32_mem);
   3887           wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
   3888           kit_cg_drop(cg);
   3889           kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I32]);
   3890           break;
   3891         }
   3892         case WASM_INSN_I32_LOAD:
   3893         case WASM_INSN_I64_LOAD:
   3894         case WASM_INSN_I32_LOAD8_S:
   3895         case WASM_INSN_I32_LOAD8_U:
   3896         case WASM_INSN_I32_LOAD16_S:
   3897         case WASM_INSN_I32_LOAD16_U:
   3898         case WASM_INSN_I64_LOAD8_S:
   3899         case WASM_INSN_I64_LOAD8_U:
   3900         case WASM_INSN_I64_LOAD16_S:
   3901         case WASM_INSN_I64_LOAD16_U:
   3902         case WASM_INSN_I64_LOAD32_S:
   3903         case WASM_INSN_I64_LOAD32_U:
   3904         case WASM_INSN_F32_LOAD:
   3905         case WASM_INSN_F64_LOAD: {
   3906           KitCgTypeId storage = wasm_load_storage_type(b, in.kind);
   3907           KitCgTypeId result =
   3908               wasm_cg_type(c, b, wasm_load_result_type(in.kind));
   3909           KitCgMemAccess mem;
   3910           memset(&mem, 0, sizeof mem);
   3911           mem.type = storage;
   3912           mem.align = in.align;
   3913           wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
   3914           wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
   3915                                        in.offset64);
   3916           kit_cg_deref(cg, 0);
   3917           kit_cg_load(cg, mem);
   3918           if (storage != result) {
   3919             if (in.kind == WASM_INSN_I32_LOAD8_S ||
   3920                 in.kind == WASM_INSN_I32_LOAD16_S ||
   3921                 in.kind == WASM_INSN_I64_LOAD8_S ||
   3922                 in.kind == WASM_INSN_I64_LOAD16_S ||
   3923                 in.kind == WASM_INSN_I64_LOAD32_S)
   3924               kit_cg_sext(cg, result);
   3925             else
   3926               kit_cg_zext(cg, result);
   3927           }
   3928           break;
   3929         }
   3930         case WASM_INSN_I32_STORE:
   3931         case WASM_INSN_I64_STORE:
   3932         case WASM_INSN_I32_STORE8:
   3933         case WASM_INSN_I32_STORE16:
   3934         case WASM_INSN_I64_STORE8:
   3935         case WASM_INSN_I64_STORE16:
   3936         case WASM_INSN_I64_STORE32:
   3937         case WASM_INSN_F32_STORE:
   3938         case WASM_INSN_F64_STORE: {
   3939           KitCgTypeId storage = wasm_store_storage_type(b, in.kind);
   3940           KitCgTypeId value_type =
   3941               wasm_cg_type(c, b, wasm_store_value_type(in.kind));
   3942           KitCgMemAccess mem;
   3943           KitCgLocalAttrs attrs;
   3944           KitCgLocal addr_tmp, value_tmp;
   3945           WasmValType addr_vt =
   3946               m->memories[in.memidx].is64 ? WASM_VAL_I64 : WASM_VAL_I32;
   3947           memset(&mem, 0, sizeof mem);
   3948           mem.type = storage;
   3949           mem.align = in.align;
   3950           if (storage != value_type) kit_cg_trunc(cg, storage);
   3951           memset(&attrs, 0, sizeof attrs);
   3952           attrs.flags = KIT_CG_LOCAL_COMPILER_TEMP;
   3953           value_tmp = kit_cg_local(cg, storage, attrs);
   3954           addr_tmp = kit_cg_local(cg, wasm_cg_type(c, b, addr_vt), attrs);
   3955           kit_cg_push_local(cg, value_tmp);
   3956           kit_cg_swap(cg);
   3957           kit_cg_store(cg, mem);
   3958           wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
   3959           kit_cg_push_local(cg, addr_tmp);
   3960           kit_cg_swap(cg);
   3961           kit_cg_store(cg, wasm_cg_mem(c, b, addr_vt));
   3962           kit_cg_push_local(cg, addr_tmp);
   3963           kit_cg_load(cg, wasm_cg_mem(c, b, addr_vt));
   3964           wasm_cg_memory_addr_from_tos(cg, b, &rt, m, instance_local, in.memidx,
   3965                                        in.offset64);
   3966           kit_cg_deref(cg, 0);
   3967           kit_cg_push_local(cg, value_tmp);
   3968           kit_cg_load(cg, mem);
   3969           kit_cg_store(cg, mem);
   3970           break;
   3971         }
   3972         case WASM_INSN_I32_ADD:
   3973         case WASM_INSN_I64_ADD:
   3974           kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
   3975           break;
   3976         case WASM_INSN_I32_SUB:
   3977         case WASM_INSN_I64_SUB:
   3978           kit_cg_int_binop(cg, KIT_CG_INT_SUB, 0);
   3979           break;
   3980         case WASM_INSN_I32_MUL:
   3981         case WASM_INSN_I64_MUL:
   3982           kit_cg_int_binop(cg, KIT_CG_INT_MUL, 0);
   3983           break;
   3984         case WASM_INSN_I32_DIV_S:
   3985           wasm_cg_checked_divrem(c, cg, b, &rt, WASM_VAL_I32, KIT_CG_INT_SDIV);
   3986           break;
   3987         case WASM_INSN_I32_DIV_U:
   3988           wasm_cg_checked_divrem(c, cg, b, &rt, WASM_VAL_I32, KIT_CG_INT_UDIV);
   3989           break;
   3990         case WASM_INSN_I32_REM_S:
   3991           wasm_cg_checked_divrem(c, cg, b, &rt, WASM_VAL_I32, KIT_CG_INT_SREM);
   3992           break;
   3993         case WASM_INSN_I32_REM_U:
   3994           wasm_cg_checked_divrem(c, cg, b, &rt, WASM_VAL_I32, KIT_CG_INT_UREM);
   3995           break;
   3996         case WASM_INSN_I64_DIV_S:
   3997           wasm_cg_checked_divrem(c, cg, b, &rt, WASM_VAL_I64, KIT_CG_INT_SDIV);
   3998           break;
   3999         case WASM_INSN_I64_DIV_U:
   4000           wasm_cg_checked_divrem(c, cg, b, &rt, WASM_VAL_I64, KIT_CG_INT_UDIV);
   4001           break;
   4002         case WASM_INSN_I64_REM_S:
   4003           wasm_cg_checked_divrem(c, cg, b, &rt, WASM_VAL_I64, KIT_CG_INT_SREM);
   4004           break;
   4005         case WASM_INSN_I64_REM_U:
   4006           wasm_cg_checked_divrem(c, cg, b, &rt, WASM_VAL_I64, KIT_CG_INT_UREM);
   4007           break;
   4008         case WASM_INSN_I32_AND:
   4009         case WASM_INSN_I64_AND:
   4010           kit_cg_int_binop(cg, KIT_CG_INT_AND, 0);
   4011           break;
   4012         case WASM_INSN_I32_OR:
   4013         case WASM_INSN_I64_OR:
   4014           kit_cg_int_binop(cg, KIT_CG_INT_OR, 0);
   4015           break;
   4016         case WASM_INSN_I32_XOR:
   4017         case WASM_INSN_I64_XOR:
   4018           kit_cg_int_binop(cg, KIT_CG_INT_XOR, 0);
   4019           break;
   4020         case WASM_INSN_I32_SHL:
   4021         case WASM_INSN_I64_SHL:
   4022           kit_cg_int_binop(cg, KIT_CG_INT_SHL, 0);
   4023           break;
   4024         case WASM_INSN_I32_SHR_S:
   4025         case WASM_INSN_I64_SHR_S:
   4026           kit_cg_int_binop(cg, KIT_CG_INT_ASHR, 0);
   4027           break;
   4028         case WASM_INSN_I32_SHR_U:
   4029         case WASM_INSN_I64_SHR_U:
   4030           kit_cg_int_binop(cg, KIT_CG_INT_LSHR, 0);
   4031           break;
   4032         case WASM_INSN_I32_ROTL:
   4033           wasm_cg_rotate(c, cg, b, WASM_VAL_I32, 0);
   4034           break;
   4035         case WASM_INSN_I32_ROTR:
   4036           wasm_cg_rotate(c, cg, b, WASM_VAL_I32, 1);
   4037           break;
   4038         case WASM_INSN_I64_ROTL:
   4039           wasm_cg_rotate(c, cg, b, WASM_VAL_I64, 0);
   4040           break;
   4041         case WASM_INSN_I64_ROTR:
   4042           wasm_cg_rotate(c, cg, b, WASM_VAL_I64, 1);
   4043           break;
   4044         case WASM_INSN_I32_CLZ:
   4045         case WASM_INSN_I64_CLZ:
   4046           kit_cg_intrinsic(cg, KIT_CG_INTRIN_CLZ, 1,
   4047                            in.kind == WASM_INSN_I32_CLZ
   4048                                ? b.id[KIT_CG_BUILTIN_I32]
   4049                                : b.id[KIT_CG_BUILTIN_I64]);
   4050           break;
   4051         case WASM_INSN_I32_CTZ:
   4052         case WASM_INSN_I64_CTZ:
   4053           kit_cg_intrinsic(cg, KIT_CG_INTRIN_CTZ, 1,
   4054                            in.kind == WASM_INSN_I32_CTZ
   4055                                ? b.id[KIT_CG_BUILTIN_I32]
   4056                                : b.id[KIT_CG_BUILTIN_I64]);
   4057           break;
   4058         case WASM_INSN_I32_POPCNT:
   4059         case WASM_INSN_I64_POPCNT:
   4060           kit_cg_intrinsic(cg, KIT_CG_INTRIN_POPCOUNT, 1,
   4061                            in.kind == WASM_INSN_I32_POPCNT
   4062                                ? b.id[KIT_CG_BUILTIN_I32]
   4063                                : b.id[KIT_CG_BUILTIN_I64]);
   4064           break;
   4065         case WASM_INSN_I32_EQZ:
   4066           kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I32]);
   4067           kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   4068           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I32]);
   4069           break;
   4070         case WASM_INSN_I64_EQZ:
   4071           kit_cg_push_int(cg, 0, b.id[KIT_CG_BUILTIN_I64]);
   4072           kit_cg_int_cmp(cg, KIT_CG_INT_EQ);
   4073           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I32]);
   4074           break;
   4075         case WASM_INSN_I32_WRAP_I64:
   4076           kit_cg_trunc(cg, b.id[KIT_CG_BUILTIN_I32]);
   4077           break;
   4078         case WASM_INSN_I64_EXTEND_I32_S:
   4079           kit_cg_sext(cg, b.id[KIT_CG_BUILTIN_I64]);
   4080           break;
   4081         case WASM_INSN_I64_EXTEND_I32_U:
   4082           kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I64]);
   4083           break;
   4084         /* In-register sign-extension operators: narrow the value to the source
   4085          * width, then sign-extend back to the result width. */
   4086         case WASM_INSN_I32_EXTEND8_S:
   4087           kit_cg_trunc(cg, b.id[KIT_CG_BUILTIN_I8]);
   4088           kit_cg_sext(cg, b.id[KIT_CG_BUILTIN_I32]);
   4089           break;
   4090         case WASM_INSN_I32_EXTEND16_S:
   4091           kit_cg_trunc(cg, b.id[KIT_CG_BUILTIN_I16]);
   4092           kit_cg_sext(cg, b.id[KIT_CG_BUILTIN_I32]);
   4093           break;
   4094         case WASM_INSN_I64_EXTEND8_S:
   4095           kit_cg_trunc(cg, b.id[KIT_CG_BUILTIN_I8]);
   4096           kit_cg_sext(cg, b.id[KIT_CG_BUILTIN_I64]);
   4097           break;
   4098         case WASM_INSN_I64_EXTEND16_S:
   4099           kit_cg_trunc(cg, b.id[KIT_CG_BUILTIN_I16]);
   4100           kit_cg_sext(cg, b.id[KIT_CG_BUILTIN_I64]);
   4101           break;
   4102         case WASM_INSN_I64_EXTEND32_S:
   4103           kit_cg_trunc(cg, b.id[KIT_CG_BUILTIN_I32]);
   4104           kit_cg_sext(cg, b.id[KIT_CG_BUILTIN_I64]);
   4105           break;
   4106         case WASM_INSN_I32_TRUNC_F32_S:
   4107         case WASM_INSN_I32_TRUNC_F64_S:
   4108           wasm_cg_checked_trunc(c, cg, b, &rt,
   4109                                 in.kind == WASM_INSN_I32_TRUNC_F32_S
   4110                                     ? WASM_VAL_F32
   4111                                     : WASM_VAL_F64,
   4112                                 WASM_VAL_I32, 0);
   4113           break;
   4114         case WASM_INSN_I32_TRUNC_F32_U:
   4115         case WASM_INSN_I32_TRUNC_F64_U:
   4116           wasm_cg_checked_trunc(c, cg, b, &rt,
   4117                                 in.kind == WASM_INSN_I32_TRUNC_F32_U
   4118                                     ? WASM_VAL_F32
   4119                                     : WASM_VAL_F64,
   4120                                 WASM_VAL_I32, 1);
   4121           break;
   4122         case WASM_INSN_I64_TRUNC_F32_S:
   4123         case WASM_INSN_I64_TRUNC_F64_S:
   4124           wasm_cg_checked_trunc(c, cg, b, &rt,
   4125                                 in.kind == WASM_INSN_I64_TRUNC_F32_S
   4126                                     ? WASM_VAL_F32
   4127                                     : WASM_VAL_F64,
   4128                                 WASM_VAL_I64, 0);
   4129           break;
   4130         case WASM_INSN_I64_TRUNC_F32_U:
   4131         case WASM_INSN_I64_TRUNC_F64_U:
   4132           wasm_cg_checked_trunc(c, cg, b, &rt,
   4133                                 in.kind == WASM_INSN_I64_TRUNC_F32_U
   4134                                     ? WASM_VAL_F32
   4135                                     : WASM_VAL_F64,
   4136                                 WASM_VAL_I64, 1);
   4137           break;
   4138         case WASM_INSN_F32_CONVERT_I32_S:
   4139         case WASM_INSN_F32_CONVERT_I64_S:
   4140           kit_cg_sint_to_float(cg, b.id[KIT_CG_BUILTIN_F32],
   4141                                KIT_CG_ROUND_DEFAULT);
   4142           break;
   4143         case WASM_INSN_F32_CONVERT_I32_U:
   4144         case WASM_INSN_F32_CONVERT_I64_U:
   4145           kit_cg_uint_to_float(cg, b.id[KIT_CG_BUILTIN_F32],
   4146                                KIT_CG_ROUND_DEFAULT);
   4147           break;
   4148         case WASM_INSN_F64_CONVERT_I32_S:
   4149         case WASM_INSN_F64_CONVERT_I64_S:
   4150           kit_cg_sint_to_float(cg, b.id[KIT_CG_BUILTIN_F64],
   4151                                KIT_CG_ROUND_DEFAULT);
   4152           break;
   4153         case WASM_INSN_F64_CONVERT_I32_U:
   4154         case WASM_INSN_F64_CONVERT_I64_U:
   4155           kit_cg_uint_to_float(cg, b.id[KIT_CG_BUILTIN_F64],
   4156                                KIT_CG_ROUND_DEFAULT);
   4157           break;
   4158         case WASM_INSN_F32_DEMOTE_F64:
   4159           kit_cg_fptrunc(cg, b.id[KIT_CG_BUILTIN_F32]);
   4160           break;
   4161         case WASM_INSN_F64_PROMOTE_F32:
   4162           kit_cg_fpext(cg, b.id[KIT_CG_BUILTIN_F64]);
   4163           break;
   4164         case WASM_INSN_I32_REINTERPRET_F32:
   4165           kit_cg_bitcast(cg, b.id[KIT_CG_BUILTIN_I32]);
   4166           break;
   4167         case WASM_INSN_I64_REINTERPRET_F64:
   4168           kit_cg_bitcast(cg, b.id[KIT_CG_BUILTIN_I64]);
   4169           break;
   4170         case WASM_INSN_F32_REINTERPRET_I32:
   4171           kit_cg_bitcast(cg, b.id[KIT_CG_BUILTIN_F32]);
   4172           break;
   4173         case WASM_INSN_F64_REINTERPRET_I64:
   4174           kit_cg_bitcast(cg, b.id[KIT_CG_BUILTIN_F64]);
   4175           break;
   4176         default: {
   4177           KitCgIntCmpOp cmp;
   4178           KitCgFpBinOp fp_bin;
   4179           KitCgFpCmpOp fp_cmp;
   4180           if (wasm_int_cmp_op(in.kind, &cmp)) {
   4181             kit_cg_int_cmp(cg, cmp);
   4182             kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I32]);
   4183           } else if (in.kind == WASM_INSN_F32_NEG ||
   4184                      in.kind == WASM_INSN_F64_NEG) {
   4185             kit_cg_fp_unop(cg, KIT_CG_FP_NEG, KIT_CG_FP_NONE);
   4186           } else if (wasm_fp_binop(in.kind, &fp_bin)) {
   4187             kit_cg_fp_binop(cg, fp_bin, KIT_CG_FP_NONE);
   4188           } else if (wasm_fp_cmp_op(in.kind, &fp_cmp)) {
   4189             kit_cg_fp_cmp(cg, fp_cmp);
   4190             kit_cg_zext(cg, b.id[KIT_CG_BUILTIN_I32]);
   4191           } else {
   4192             wasm_error(c, in.loc, "wasm: unsupported instruction");
   4193           }
   4194           break;
   4195         }
   4196       }
   4197     }
   4198     /* If the body's final reachable position is unreachable (it ended in a
   4199      * branch/return/unreachable), the SValue stack is already balanced and the
   4200      * function's epilogue is closed — emitting another ret here would
   4201      * underflow. `dead` tracks exactly this; the textual-terminator check is a
   4202      * belt-and-suspenders fallback. */
   4203     {
   4204       uint32_t last = f->ninsns;
   4205       int body_terminates;
   4206       while (last > 0 && f->insns[last - 1u].kind == WASM_INSN_END) last--;
   4207       body_terminates =
   4208           last > 0 &&
   4209           (f->insns[last - 1u].kind == WASM_INSN_RETURN ||
   4210            f->insns[last - 1u].kind == WASM_INSN_RETURN_CALL ||
   4211            f->insns[last - 1u].kind == WASM_INSN_RETURN_CALL_INDIRECT ||
   4212            f->insns[last - 1u].kind == WASM_INSN_RETURN_CALL_REF ||
   4213            f->insns[last - 1u].kind == WASM_INSN_UNREACHABLE);
   4214       if (!dead && !body_terminates) kit_cg_ret(cg);
   4215     }
   4216     kit_cg_func_end(cg);
   4217     heap->free(heap, control, sizeof(WasmCgControl) * control_cap);
   4218   }
   4219   kit_arena_free(arena);
   4220 }
   4221 
   4222 void wasm_emit_cg(KitCompiler* c, const KitCodeOptions* code_opts,
   4223                   KitObjBuilder* out, const WasmModule* m) {
   4224   KitCg* cg = NULL;
   4225   KitCgUnitOptions unit_opts;
   4226   KitStatus cg_st = kit_cg_new(c, &cg);
   4227   if (cg_st == KIT_OK) cg_st = kit_cg_begin(cg, out, code_opts);
   4228   memset(&unit_opts, 0, sizeof unit_opts);
   4229   if (cg_st == KIT_OK) cg_st = kit_cg_begin_unit(cg, &unit_opts);
   4230   if (cg_st != KIT_OK || !cg)
   4231     wasm_error(c, wasm_loc(0, 0), "wasm: failed to initialize codegen");
   4232   wasm_emit_cg_into(c, cg, m);
   4233   if (kit_cg_end_unit(cg) != KIT_OK || kit_cg_finish(cg, NULL) != KIT_OK ||
   4234       kit_cg_detach(cg) != KIT_OK)
   4235     wasm_error(c, wasm_loc(0, 0), "wasm: failed to finalize codegen");
   4236   kit_cg_free(cg);
   4237 }