kit

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

cg.c (168827B)


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