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