module.c (18265B)
1 #include "wasm/wasm.h" 2 3 KitSrcLoc wasm_loc(uint32_t line, uint32_t col) { 4 KitSrcLoc loc; 5 loc.file_id = 0; 6 loc.line = line; 7 loc.col = col; 8 return loc; 9 } 10 11 void wasm_error(KitCompiler* c, KitSrcLoc loc, const char* fmt, ...) { 12 va_list ap; 13 va_start(ap, fmt); 14 kit_frontend_vfatal(c, loc, fmt, ap); 15 } 16 17 void* wasm_realloc(KitHeap* h, void* p, size_t old_n, size_t new_n) { 18 return h->realloc(h, p, old_n ? old_n : 1u, new_n ? new_n : 1u, 19 _Alignof(max_align_t)); 20 } 21 22 char* wasm_strdup(KitHeap* h, const char* s, size_t len) { 23 char* out; 24 if (!h || !s) return NULL; 25 out = (char*)h->alloc(h, len + 1u, 1); 26 if (!out) return NULL; 27 memcpy(out, s, len); 28 out[len] = '\0'; 29 return out; 30 } 31 32 void wasm_free_str(KitHeap* h, char** s) { 33 if (!h || !s || !*s) return; 34 h->free(h, *s, strlen(*s) + 1u); 35 *s = NULL; 36 } 37 38 void wasm_module_init(WasmModule* m, KitHeap* heap) { 39 memset(m, 0, sizeof *m); 40 m->heap = heap; 41 m->features = WASM_FEATURE_THREADS | WASM_FEATURE_TYPED_FUNC_REFS | 42 WASM_FEATURE_TAIL_CALLS | WASM_FEATURE_MULTI_MEMORY | 43 WASM_FEATURE_MEMORY64 | WASM_FEATURE_BULK_MEMORY | 44 WASM_FEATURE_NONTRAPPING_FTOI; 45 } 46 47 void wasm_module_free(WasmModule* m) { 48 uint32_t i; 49 if (!m || !m->heap) return; 50 for (i = 0; i < m->ntypes; ++i) { 51 WasmFuncType* t = &m->types[i]; 52 wasm_free_str(m->heap, &t->name); 53 if (t->params) 54 m->heap->free(m->heap, t->params, sizeof(*t->params) * t->cap_params); 55 if (t->results) 56 m->heap->free(m->heap, t->results, sizeof(*t->results) * t->cap_results); 57 } 58 if (m->types) 59 m->heap->free(m->heap, m->types, sizeof(*m->types) * m->cap_types); 60 for (i = 0; i < m->nfuncs; ++i) { 61 WasmFunc* f = &m->funcs[i]; 62 wasm_free_str(m->heap, &f->name); 63 wasm_free_str(m->heap, &f->import_module); 64 wasm_free_str(m->heap, &f->import_name); 65 wasm_free_str(m->heap, &f->export_name); 66 if (f->local_names) { 67 for (uint32_t j = 0; j < f->cap_local_names; ++j) 68 wasm_free_str(m->heap, &f->local_names[j]); 69 m->heap->free(m->heap, f->local_names, 70 sizeof(*f->local_names) * f->cap_local_names); 71 } 72 if (f->params) 73 m->heap->free(m->heap, f->params, sizeof(*f->params) * f->cap_params); 74 if (f->results) 75 m->heap->free(m->heap, f->results, sizeof(*f->results) * f->cap_results); 76 if (f->locals) 77 m->heap->free(m->heap, f->locals, sizeof(*f->locals) * f->cap_locals); 78 if (f->insns) { 79 for (uint32_t j = 0; j < f->ninsns; ++j) 80 if (f->insns[j].targets) 81 m->heap->free(m->heap, f->insns[j].targets, 82 sizeof(uint32_t) * f->insns[j].ntargets); 83 m->heap->free(m->heap, f->insns, sizeof(*f->insns) * f->cap_insns); 84 } 85 } 86 if (m->funcs) 87 m->heap->free(m->heap, m->funcs, sizeof(*m->funcs) * m->cap_funcs); 88 for (i = 0; i < m->nmemories; ++i) { 89 wasm_free_str(m->heap, &m->memories[i].name); 90 wasm_free_str(m->heap, &m->memories[i].import_module); 91 wasm_free_str(m->heap, &m->memories[i].import_name); 92 wasm_free_str(m->heap, &m->memories[i].export_name); 93 } 94 if (m->memories) 95 m->heap->free(m->heap, m->memories, sizeof(*m->memories) * m->cap_memories); 96 for (i = 0; i < m->ndata; ++i) { 97 wasm_free_str(m->heap, &m->data[i].name); 98 if (m->data[i].bytes) 99 m->heap->free(m->heap, m->data[i].bytes, (size_t)m->data[i].nbytes); 100 } 101 if (m->data) m->heap->free(m->heap, m->data, sizeof(*m->data) * m->cap_data); 102 for (i = 0; i < m->nelems; ++i) { 103 wasm_free_str(m->heap, &m->elems[i].name); 104 if (m->elems[i].funcs) 105 m->heap->free(m->heap, m->elems[i].funcs, 106 sizeof(*m->elems[i].funcs) * m->elems[i].cap_funcs); 107 } 108 for (i = 0; i < m->ntables; ++i) { 109 wasm_free_str(m->heap, &m->tables[i].name); 110 wasm_free_str(m->heap, &m->tables[i].import_module); 111 wasm_free_str(m->heap, &m->tables[i].import_name); 112 wasm_free_str(m->heap, &m->tables[i].export_name); 113 } 114 if (m->tables) 115 m->heap->free(m->heap, m->tables, sizeof(*m->tables) * m->cap_tables); 116 for (i = 0; i < m->nglobals; ++i) { 117 wasm_free_str(m->heap, &m->globals[i].name); 118 wasm_free_str(m->heap, &m->globals[i].import_module); 119 wasm_free_str(m->heap, &m->globals[i].import_name); 120 wasm_free_str(m->heap, &m->globals[i].export_name); 121 } 122 if (m->globals) 123 m->heap->free(m->heap, m->globals, sizeof(*m->globals) * m->cap_globals); 124 if (m->elems) 125 m->heap->free(m->heap, m->elems, sizeof(*m->elems) * m->cap_elems); 126 if (m->exports) 127 m->heap->free(m->heap, m->exports, sizeof(*m->exports) * m->cap_exports); 128 for (i = 0; i < m->ncustoms; ++i) { 129 wasm_free_str(m->heap, &m->customs[i].name); 130 if (m->customs[i].data) 131 m->heap->free(m->heap, m->customs[i].data, m->customs[i].len); 132 } 133 if (m->customs) 134 m->heap->free(m->heap, m->customs, sizeof(*m->customs) * m->cap_customs); 135 memset(m, 0, sizeof *m); 136 } 137 138 WasmMemory* wasm_add_memory(KitCompiler* c, WasmModule* m) { 139 WasmMemory* mem; 140 if (m->nmemories == m->cap_memories) { 141 uint32_t new_cap = m->cap_memories ? m->cap_memories * 2u : 2u; 142 void* p = wasm_realloc(m->heap, m->memories, 143 sizeof(*m->memories) * m->cap_memories, 144 sizeof(*m->memories) * new_cap); 145 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 146 m->memories = (WasmMemory*)p; 147 memset(m->memories + m->cap_memories, 0, 148 sizeof(*m->memories) * (new_cap - m->cap_memories)); 149 m->cap_memories = new_cap; 150 } 151 mem = &m->memories[m->nmemories++]; 152 memset(mem, 0, sizeof *mem); 153 return mem; 154 } 155 156 WasmFunc* wasm_add_func(KitCompiler* c, WasmModule* m) { 157 WasmFunc* f; 158 if (m->nfuncs == m->cap_funcs) { 159 uint32_t new_cap = m->cap_funcs ? m->cap_funcs * 2u : 4u; 160 void* p = wasm_realloc(m->heap, m->funcs, sizeof(*m->funcs) * m->cap_funcs, 161 sizeof(*m->funcs) * new_cap); 162 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 163 m->funcs = (WasmFunc*)p; 164 memset(m->funcs + m->cap_funcs, 0, 165 sizeof(*m->funcs) * (new_cap - m->cap_funcs)); 166 m->cap_funcs = new_cap; 167 } 168 f = &m->funcs[m->nfuncs++]; 169 memset(f, 0, sizeof *f); 170 return f; 171 } 172 173 WasmFuncType* wasm_add_type(KitCompiler* c, WasmModule* m) { 174 WasmFuncType* t; 175 if (m->ntypes == m->cap_types) { 176 uint32_t new_cap = m->cap_types ? m->cap_types * 2u : 8u; 177 void* p = wasm_realloc(m->heap, m->types, sizeof(*m->types) * m->cap_types, 178 sizeof(*m->types) * new_cap); 179 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 180 m->types = (WasmFuncType*)p; 181 memset(m->types + m->cap_types, 0, 182 sizeof(*m->types) * (new_cap - m->cap_types)); 183 m->cap_types = new_cap; 184 } 185 t = &m->types[m->ntypes++]; 186 memset(t, 0, sizeof *t); 187 return t; 188 } 189 190 static void wasm_grow_valtypes(KitCompiler* c, WasmModule* m, WasmValType** arr, 191 uint32_t* cap, uint32_t want) { 192 uint32_t new_cap; 193 void* p; 194 if (want <= *cap) return; 195 new_cap = *cap ? *cap : 4u; 196 while (new_cap < want) new_cap *= 2u; 197 p = wasm_realloc(m->heap, *arr, sizeof(WasmValType) * (*cap), 198 sizeof(WasmValType) * new_cap); 199 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 200 *arr = (WasmValType*)p; 201 *cap = new_cap; 202 } 203 204 uint32_t wasm_func_push_param(KitCompiler* c, WasmModule* m, WasmFunc* f, 205 WasmValType vt) { 206 wasm_grow_valtypes(c, m, &f->params, &f->cap_params, f->nparams + 1u); 207 f->params[f->nparams] = vt; 208 return f->nparams++; 209 } 210 211 uint32_t wasm_func_push_local(KitCompiler* c, WasmModule* m, WasmFunc* f, 212 WasmValType vt) { 213 wasm_grow_valtypes(c, m, &f->locals, &f->cap_locals, f->nlocals + 1u); 214 f->locals[f->nlocals] = vt; 215 return f->nparams + f->nlocals++; 216 } 217 218 void wasm_func_set_params(KitCompiler* c, WasmModule* m, WasmFunc* f, 219 const WasmValType* src, uint32_t n) { 220 wasm_grow_valtypes(c, m, &f->params, &f->cap_params, n); 221 if (n) memcpy(f->params, src, sizeof(WasmValType) * n); 222 f->nparams = n; 223 } 224 225 uint32_t wasm_func_push_result(KitCompiler* c, WasmModule* m, WasmFunc* f, 226 WasmValType vt) { 227 wasm_grow_valtypes(c, m, &f->results, &f->cap_results, f->nresults + 1u); 228 f->results[f->nresults] = vt; 229 return f->nresults++; 230 } 231 232 void wasm_func_set_results(KitCompiler* c, WasmModule* m, WasmFunc* f, 233 const WasmValType* src, uint32_t n) { 234 wasm_grow_valtypes(c, m, &f->results, &f->cap_results, n); 235 if (n) memcpy(f->results, src, sizeof(WasmValType) * n); 236 f->nresults = n; 237 } 238 239 void wasm_func_set_local_name(KitCompiler* c, WasmModule* m, WasmFunc* f, 240 uint32_t idx, const char* name, size_t len) { 241 if (idx >= f->cap_local_names) { 242 uint32_t new_cap = f->cap_local_names ? f->cap_local_names * 2u : 8u; 243 void* p; 244 while (new_cap <= idx) new_cap *= 2u; 245 p = wasm_realloc(m->heap, f->local_names, 246 sizeof(char*) * f->cap_local_names, 247 sizeof(char*) * new_cap); 248 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 249 f->local_names = (char**)p; 250 memset(f->local_names + f->cap_local_names, 0, 251 sizeof(char*) * (new_cap - f->cap_local_names)); 252 f->cap_local_names = new_cap; 253 } 254 wasm_free_str(m->heap, &f->local_names[idx]); 255 f->local_names[idx] = wasm_strdup(m->heap, name, len); 256 if (!f->local_names[idx]) 257 wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 258 } 259 260 uint32_t wasm_type_push_param(KitCompiler* c, WasmModule* m, WasmFuncType* t, 261 WasmValType vt) { 262 wasm_grow_valtypes(c, m, &t->params, &t->cap_params, t->nparams + 1u); 263 t->params[t->nparams] = vt; 264 return t->nparams++; 265 } 266 267 uint32_t wasm_type_push_result(KitCompiler* c, WasmModule* m, WasmFuncType* t, 268 WasmValType vt) { 269 wasm_grow_valtypes(c, m, &t->results, &t->cap_results, t->nresults + 1u); 270 t->results[t->nresults] = vt; 271 return t->nresults++; 272 } 273 274 uint32_t wasm_intern_func_type(KitCompiler* c, WasmModule* m, 275 const WasmFunc* f) { 276 uint32_t i; 277 for (i = 0; i < m->ntypes; ++i) { 278 WasmFuncType* t = &m->types[i]; 279 if (t->nparams == f->nparams && t->nresults == f->nresults && 280 (t->nparams == 0 || memcmp(t->params, f->params, 281 sizeof(t->params[0]) * t->nparams) == 0) && 282 (t->nresults == 0 || 283 memcmp(t->results, f->results, 284 sizeof(t->results[0]) * t->nresults) == 0)) 285 return i; 286 } 287 { 288 WasmFuncType* t = wasm_add_type(c, m); 289 wasm_grow_valtypes(c, m, &t->params, &t->cap_params, f->nparams); 290 t->nparams = f->nparams; 291 if (f->nparams) 292 memcpy(t->params, f->params, sizeof(t->params[0]) * f->nparams); 293 wasm_grow_valtypes(c, m, &t->results, &t->cap_results, f->nresults); 294 t->nresults = f->nresults; 295 if (f->nresults) 296 memcpy(t->results, f->results, sizeof(t->results[0]) * f->nresults); 297 return m->ntypes - 1u; 298 } 299 } 300 301 WasmTable* wasm_add_table(KitCompiler* c, WasmModule* m) { 302 WasmTable* t; 303 if (m->ntables == m->cap_tables) { 304 uint32_t new_cap = m->cap_tables ? m->cap_tables * 2u : 2u; 305 void* p = 306 wasm_realloc(m->heap, m->tables, sizeof(*m->tables) * m->cap_tables, 307 sizeof(*m->tables) * new_cap); 308 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 309 m->tables = (WasmTable*)p; 310 memset(m->tables + m->cap_tables, 0, 311 sizeof(*m->tables) * (new_cap - m->cap_tables)); 312 m->cap_tables = new_cap; 313 } 314 t = &m->tables[m->ntables++]; 315 memset(t, 0, sizeof *t); 316 return t; 317 } 318 319 WasmGlobal* wasm_add_global(KitCompiler* c, WasmModule* m) { 320 WasmGlobal* g; 321 if (m->nglobals == m->cap_globals) { 322 uint32_t new_cap = m->cap_globals ? m->cap_globals * 2u : 4u; 323 void* p = 324 wasm_realloc(m->heap, m->globals, sizeof(*m->globals) * m->cap_globals, 325 sizeof(*m->globals) * new_cap); 326 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 327 m->globals = (WasmGlobal*)p; 328 memset(m->globals + m->cap_globals, 0, 329 sizeof(*m->globals) * (new_cap - m->cap_globals)); 330 m->cap_globals = new_cap; 331 } 332 g = &m->globals[m->nglobals++]; 333 memset(g, 0, sizeof *g); 334 return g; 335 } 336 337 WasmElemSegment* wasm_add_elem(KitCompiler* c, WasmModule* m) { 338 WasmElemSegment* e; 339 if (m->nelems == m->cap_elems) { 340 uint32_t new_cap = m->cap_elems ? m->cap_elems * 2u : 4u; 341 void* p = wasm_realloc(m->heap, m->elems, sizeof(*m->elems) * m->cap_elems, 342 sizeof(*m->elems) * new_cap); 343 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 344 m->elems = (WasmElemSegment*)p; 345 memset(m->elems + m->cap_elems, 0, 346 sizeof(*m->elems) * (new_cap - m->cap_elems)); 347 m->cap_elems = new_cap; 348 } 349 e = &m->elems[m->nelems++]; 350 memset(e, 0, sizeof *e); 351 return e; 352 } 353 354 WasmDataSegment* wasm_add_data(KitCompiler* c, WasmModule* m) { 355 WasmDataSegment* d; 356 if (m->ndata == m->cap_data) { 357 uint32_t new_cap = m->cap_data ? m->cap_data * 2u : 4u; 358 void* p = wasm_realloc(m->heap, m->data, sizeof(*m->data) * m->cap_data, 359 sizeof(*m->data) * new_cap); 360 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 361 m->data = (WasmDataSegment*)p; 362 memset(m->data + m->cap_data, 0, 363 sizeof(*m->data) * (new_cap - m->cap_data)); 364 m->cap_data = new_cap; 365 } 366 d = &m->data[m->ndata++]; 367 memset(d, 0, sizeof *d); 368 return d; 369 } 370 371 void wasm_data_set_bytes(KitCompiler* c, WasmModule* m, WasmDataSegment* d, 372 const uint8_t* src, uint64_t n) { 373 void* p; 374 if (n > SIZE_MAX) 375 wasm_error(c, wasm_loc(0, 0), "wasm: data segment too large"); 376 if (d->bytes && d->nbytes) 377 m->heap->free(m->heap, d->bytes, (size_t)d->nbytes); 378 d->bytes = NULL; 379 d->nbytes = 0; 380 if (!n) return; 381 p = m->heap->alloc(m->heap, (size_t)n, 1); 382 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 383 if (src) 384 memcpy(p, src, (size_t)n); 385 else 386 memset(p, 0, (size_t)n); 387 d->bytes = (uint8_t*)p; 388 d->nbytes = n; 389 } 390 391 void wasm_elem_push_func(KitCompiler* c, WasmModule* m, WasmElemSegment* e, 392 uint32_t funcidx) { 393 if (e->nfuncs == e->cap_funcs) { 394 uint32_t new_cap = e->cap_funcs ? e->cap_funcs * 2u : 8u; 395 void* p = wasm_realloc(m->heap, e->funcs, sizeof(*e->funcs) * e->cap_funcs, 396 sizeof(*e->funcs) * new_cap); 397 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 398 e->funcs = (uint32_t*)p; 399 e->cap_funcs = new_cap; 400 } 401 e->funcs[e->nfuncs++] = funcidx; 402 } 403 404 WasmExport* wasm_add_export(KitCompiler* c, WasmModule* m) { 405 WasmExport* e; 406 if (m->nexports == m->cap_exports) { 407 uint32_t new_cap = m->cap_exports ? m->cap_exports * 2u : 8u; 408 void* p = 409 wasm_realloc(m->heap, m->exports, sizeof(*m->exports) * m->cap_exports, 410 sizeof(*m->exports) * new_cap); 411 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 412 m->exports = (WasmExport*)p; 413 memset(m->exports + m->cap_exports, 0, 414 sizeof(*m->exports) * (new_cap - m->cap_exports)); 415 m->cap_exports = new_cap; 416 } 417 e = &m->exports[m->nexports++]; 418 memset(e, 0, sizeof *e); 419 return e; 420 } 421 422 WasmCustom* wasm_add_custom(KitCompiler* c, WasmModule* m) { 423 WasmCustom* cs; 424 if (m->ncustoms == m->cap_customs) { 425 uint32_t new_cap = m->cap_customs ? m->cap_customs * 2u : 4u; 426 void* p = 427 wasm_realloc(m->heap, m->customs, sizeof(*m->customs) * m->cap_customs, 428 sizeof(*m->customs) * new_cap); 429 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 430 m->customs = (WasmCustom*)p; 431 memset(m->customs + m->cap_customs, 0, 432 sizeof(*m->customs) * (new_cap - m->cap_customs)); 433 m->cap_customs = new_cap; 434 } 435 cs = &m->customs[m->ncustoms++]; 436 memset(cs, 0, sizeof *cs); 437 return cs; 438 } 439 440 void wasm_func_add_insn(KitCompiler* c, WasmModule* m, WasmFunc* f, 441 WasmInsnKind kind, int64_t imm) { 442 if (f->ninsns == f->cap_insns) { 443 uint32_t new_cap = f->cap_insns ? f->cap_insns * 2u : 16u; 444 void* p = wasm_realloc(m->heap, f->insns, sizeof(*f->insns) * f->cap_insns, 445 sizeof(*f->insns) * new_cap); 446 if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); 447 f->insns = (WasmInsn*)p; 448 f->cap_insns = new_cap; 449 } 450 f->insns[f->ninsns].loc = m ? m->current_loc : wasm_loc(0, 0); 451 f->insns[f->ninsns].kind = (uint8_t)kind; 452 f->insns[f->ninsns].type = 0; 453 f->insns[f->ninsns].imm = imm; 454 f->insns[f->ninsns].fp = 0.0; 455 f->insns[f->ninsns].align = 0; 456 f->insns[f->ninsns].memidx = 0; 457 f->insns[f->ninsns].offset64 = imm < 0 ? 0 : (uint64_t)imm; 458 f->insns[f->ninsns].aux_idx = 0; 459 f->insns[f->ninsns].ntargets = 0; 460 f->insns[f->ninsns].targets = NULL; 461 f->ninsns++; 462 } 463 464 void wasm_func_add_mem_insn(KitCompiler* c, WasmModule* m, WasmFunc* f, 465 WasmInsnKind kind, uint32_t align, uint64_t offset, 466 uint32_t memidx) { 467 wasm_func_add_insn(c, m, f, kind, 468 offset > INT64_MAX ? INT64_MAX : (int64_t)offset); 469 f->insns[f->ninsns - 1u].align = align; 470 f->insns[f->ninsns - 1u].offset64 = offset; 471 f->insns[f->ninsns - 1u].memidx = memidx; 472 } 473 474 void wasm_func_add_fp_insn(KitCompiler* c, WasmModule* m, WasmFunc* f, 475 WasmInsnKind kind, double value) { 476 wasm_func_add_insn(c, m, f, kind, 0); 477 f->insns[f->ninsns - 1u].fp = value; 478 } 479 480 void wasm_insn_set_targets(KitCompiler* c, WasmModule* m, WasmInsn* in, 481 const uint32_t* targets, uint32_t ntargets) { 482 if (in->targets) 483 m->heap->free(m->heap, in->targets, sizeof(uint32_t) * in->ntargets); 484 in->targets = NULL; 485 in->ntargets = ntargets; 486 if (!ntargets) return; 487 in->targets = (uint32_t*)m->heap->alloc(m->heap, sizeof(uint32_t) * ntargets, 488 _Alignof(uint32_t)); 489 if (!in->targets) 490 wasm_error(c, wasm_loc(0, 0), "wasm: out of memory for br_table targets"); 491 if (targets) memcpy(in->targets, targets, sizeof(uint32_t) * ntargets); 492 }