kit

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

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 }