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