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