commit 2e3bc93c4d520c5d535c59d1e6a0a972017921b8
parent de7b25ff43c391fe820d41f84e1b0bca8ba9d360
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Mon, 18 May 2026 00:02:24 -0700
Implement Wasm runtime instance slots
Diffstat:
7 files changed, 2695 insertions(+), 2524 deletions(-)
diff --git a/doc/WASM.md b/doc/WASM.md
@@ -762,7 +762,11 @@ Current checked reader/encoder and validation items describe the
re-encode the listed module metadata. Native lowering now covers mutable
numeric globals, imported function declarations, active tables/elements for
`call_indirect`, start functions, and growable single-memory state for the
-accepted frontend subset.
+accepted frontend subset. The native runner path now uses an explicit
+`CfreeWasmInstance*` ABI: lowered functions, direct calls, `call_indirect`
+arms, start dispatch, and `__cfree_wasm_init` all receive the instance;
+single-memory metadata and numeric globals live under that instance. Import
+slots and runtime table storage remain open work.
### Frontend Source and Driver
@@ -843,28 +847,44 @@ accepted frontend subset.
and MVP conversions.
- [x] Lower f32/f64 arithmetic, comparisons, constants, conversions, and
reinterpret ops.
+- [ ] Add checked traps for `i32/i64.trunc_f32/f64_{s,u}` NaN/out-of-range
+ cases; current lowering relies on target float-to-int conversion behavior.
- [x] Lower single linear memory load/store operations, `memory.size`, and
active data initialization.
- [x] Implement checked single-memory loads/stores and growable storage.
- [x] Implement numeric globals for native lowering.
- [x] Implement imported function declarations for native lowering.
- [x] Implement tables, active elements, and `call_indirect`.
-- [ ] Move lowered memory/global/import/table state behind the explicit
- `CfreeWasmInstance` ABI instead of generated module-local storage/direct
- external declarations.
+- [x] Pass an explicit `CfreeWasmInstance*` through lowered functions, direct
+ calls, `call_indirect` arms, start dispatch, and module initialization.
+- [x] Move lowered single-memory metadata and numeric global state behind the
+ explicit `CfreeWasmInstance` ABI instead of generated module-local storage.
+- [x] Move imported functions, imported globals, imported memories, and tables
+ behind instance import/table slots instead of direct external declarations
+ and compile-time active-element dispatch.
- [ ] Define and implement the C-facing exported wrapper ABI that keeps the
instance parameter explicit.
### Runtime and Instance Model
-- [ ] Add internal `CfreeWasmInstance`, memory, table, global, and import-slot
- structs under `lang/wasm` or `rt`.
+- [x] Add an internal runtime ABI header under `lang/wasm` with
+ `CfreeWasmMemory`, opaque `CfreeWasmInstance`, and `CfreeWasmInitFn`.
+- [x] Allocate runner-owned instances and linear memories in `cfree run`,
+ `jit-runner`, and the Wasm executable start harness without process-global
+ Wasm instance or memory storage.
+- [x] Define initialization for single memories, active data, numeric globals,
+ and start functions in `__cfree_wasm_init(instance)`.
+- [x] Add internal `CfreeWasmTable` and import-slot structs under `lang/wasm`
+ or `rt`, and use them for imported functions/globals/memories and active
+ element initialization.
- [ ] Add trap helpers for unreachable, division traps, invalid conversion,
bounds checks, table checks, and indirect-call signature checks.
-- [ ] Define ownership and initialization for memories, tables, active data,
- elements, mutable globals, and start functions.
-- [ ] Add tests that instantiate modules with memory/import/global state
- without process-global state.
+- [x] Define ownership and initialization for runtime tables, active elements,
+ and imported state.
+- [x] Add frontend runner tests that instantiate memory/global/start modules
+ without process-global Wasm state.
+- [x] Add frontend runner tests for instance-owned import slots and runtime
+ table state once those slots exist.
### Wasm Target Backend
diff --git a/lang/wasm/runtime_abi.h b/lang/wasm/runtime_abi.h
@@ -4,16 +4,36 @@
#include <stdint.h>
typedef struct CfreeWasmMemory {
- uint8_t *data;
+ uint8_t* data;
uint32_t pages;
uint32_t max_pages;
} CfreeWasmMemory;
+typedef struct CfreeWasmFuncImport {
+ void* fn;
+} CfreeWasmFuncImport;
+
+typedef struct CfreeWasmGlobalImport {
+ void* addr;
+} CfreeWasmGlobalImport;
+
+typedef struct CfreeWasmTableEntry {
+ void* fn;
+ uint32_t typeidx;
+} CfreeWasmTableEntry;
+
+typedef struct CfreeWasmTable {
+ CfreeWasmTableEntry* entries;
+ uint32_t len;
+ uint32_t max;
+} CfreeWasmTable;
+
/* Opaque to C callers for now. The compiler emits a module-specific instance
- * layout with CfreeWasmMemory first when the module has linear memory, followed
- * by lowered global slots. */
+ * layout with CfreeWasmMemory first, followed by import slots, runtime tables,
+ * and lowered global slots. Table entry storage is instance-owned for
+ * defined tables; embedders fill import slots before calling the init hook. */
typedef struct CfreeWasmInstance CfreeWasmInstance;
-typedef void (*CfreeWasmInitFn)(CfreeWasmInstance *);
+typedef void (*CfreeWasmInitFn)(CfreeWasmInstance*);
#endif
diff --git a/lang/wasm/wasm.c b/lang/wasm/wasm.c
@@ -179,27 +179,27 @@ typedef struct WasmInsn {
} WasmInsn;
typedef struct WasmFunc {
- char *name;
+ char* name;
uint32_t typeidx;
int has_typeidx;
int is_import;
- char *import_module;
- char *import_name;
+ char* import_module;
+ char* import_name;
WasmValType params[16];
uint32_t nparams;
WasmValType locals[32];
uint32_t nlocals;
- char *local_names[48];
+ char* local_names[48];
WasmValType results[1];
uint32_t nresults;
- char *export_name;
- WasmInsn *insns;
+ char* export_name;
+ WasmInsn* insns;
uint32_t ninsns;
uint32_t cap_insns;
} WasmFunc;
typedef struct WasmFuncType {
- char *name;
+ char* name;
WasmValType params[16];
uint32_t nparams;
WasmValType results[1];
@@ -207,40 +207,40 @@ typedef struct WasmFuncType {
} WasmFuncType;
typedef struct WasmMemory {
- char *name;
+ char* name;
uint32_t min_pages;
uint32_t max_pages;
int has_max;
int is_import;
- char *import_module;
- char *import_name;
- char *export_name;
- uint8_t *data;
+ char* import_module;
+ char* import_name;
+ char* export_name;
+ uint8_t* data;
uint32_t data_len;
uint32_t data_init_len;
} WasmMemory;
typedef struct WasmTable {
- char *name;
+ char* name;
WasmValType elem_type;
uint32_t min;
uint32_t max;
int has_max;
int is_import;
- char *import_module;
- char *import_name;
- char *export_name;
+ char* import_module;
+ char* import_name;
+ char* export_name;
} WasmTable;
typedef struct WasmGlobal {
- char *name;
+ char* name;
WasmValType type;
uint8_t mutable_;
WasmInsn init;
int is_import;
- char *import_module;
- char *import_name;
- char *export_name;
+ char* import_module;
+ char* import_name;
+ char* export_name;
} WasmGlobal;
typedef struct WasmElemSegment {
@@ -251,40 +251,40 @@ typedef struct WasmElemSegment {
} WasmElemSegment;
typedef struct WasmExport {
- char *name;
+ char* name;
uint8_t kind;
uint32_t index;
} WasmExport;
typedef struct WasmCustom {
- char *name;
- uint8_t *data;
+ char* name;
+ uint8_t* data;
uint32_t len;
} WasmCustom;
typedef struct WasmModule {
- CfreeHeap *heap;
- WasmFuncType *types;
+ CfreeHeap* heap;
+ WasmFuncType* types;
uint32_t ntypes;
uint32_t cap_types;
- WasmFunc *funcs;
+ WasmFunc* funcs;
uint32_t nfuncs;
uint32_t cap_funcs;
WasmMemory memory;
int has_memory;
- WasmTable *tables;
+ WasmTable* tables;
uint32_t ntables;
uint32_t cap_tables;
- WasmGlobal *globals;
+ WasmGlobal* globals;
uint32_t nglobals;
uint32_t cap_globals;
- WasmElemSegment *elems;
+ WasmElemSegment* elems;
uint32_t nelems;
uint32_t cap_elems;
- WasmExport *exports;
+ WasmExport* exports;
uint32_t nexports;
uint32_t cap_exports;
- WasmCustom *customs;
+ WasmCustom* customs;
uint32_t ncustoms;
uint32_t cap_customs;
uint32_t start_func;
@@ -293,7 +293,7 @@ typedef struct WasmModule {
} WasmModule;
typedef struct WasmTok {
- const char *p;
+ const char* p;
size_t len;
uint32_t line;
uint32_t col;
@@ -309,23 +309,23 @@ enum {
};
typedef struct WatParser {
- CfreeCompiler *c;
- const char *name;
- const char *src;
+ CfreeCompiler* c;
+ const char* name;
+ const char* src;
size_t len;
size_t pos;
uint32_t line;
uint32_t col;
WasmTok tok;
- WasmModule *module;
+ WasmModule* module;
} WatParser;
typedef struct BinReader {
- CfreeCompiler *c;
- const uint8_t *data;
+ CfreeCompiler* c;
+ const uint8_t* data;
size_t len;
size_t pos;
- WasmModule *module;
+ WasmModule* module;
} BinReader;
static CfreeSrcLoc wasm_loc(uint32_t line, uint32_t col) {
@@ -336,50 +336,46 @@ static CfreeSrcLoc wasm_loc(uint32_t line, uint32_t col) {
return loc;
}
-static void wasm_error(CfreeCompiler *c, CfreeSrcLoc loc, const char *fmt,
+static void wasm_error(CfreeCompiler* c, CfreeSrcLoc loc, const char* fmt,
...) {
va_list ap;
va_start(ap, fmt);
cfree_frontend_vfatal(c, loc, fmt, ap);
}
-static void *wasm_realloc(CfreeHeap *h, void *p, size_t old_n, size_t new_n) {
+static void* wasm_realloc(CfreeHeap* h, void* p, size_t old_n, size_t new_n) {
return h->realloc(h, p, old_n ? old_n : 1u, new_n ? new_n : 1u,
_Alignof(max_align_t));
}
-static char *wasm_strdup(CfreeHeap *h, const char *s, size_t len) {
- char *out = (char *)h->alloc(h, len + 1u, 1);
- if (!out)
- return NULL;
- if (len)
- memcpy(out, s, len);
+static char* wasm_strdup(CfreeHeap* h, const char* s, size_t len) {
+ char* out = (char*)h->alloc(h, len + 1u, 1);
+ if (!out) return NULL;
+ if (len) memcpy(out, s, len);
out[len] = '\0';
return out;
}
-static void wasm_free_str(CfreeHeap *h, char **s) {
+static void wasm_free_str(CfreeHeap* h, char** s) {
if (*s) {
h->free(h, *s, strlen(*s) + 1u);
*s = NULL;
}
}
-static void wasm_module_init(WasmModule *m, CfreeHeap *heap) {
+static void wasm_module_init(WasmModule* m, CfreeHeap* heap) {
memset(m, 0, sizeof *m);
m->heap = heap;
}
-static void wasm_module_free(WasmModule *m) {
+static void wasm_module_free(WasmModule* m) {
uint32_t i;
- if (!m || !m->heap)
- return;
- for (i = 0; i < m->ntypes; ++i)
- wasm_free_str(m->heap, &m->types[i].name);
+ if (!m || !m->heap) return;
+ for (i = 0; i < m->ntypes; ++i) wasm_free_str(m->heap, &m->types[i].name);
if (m->types)
m->heap->free(m->heap, m->types, sizeof(*m->types) * m->cap_types);
for (i = 0; i < m->nfuncs; ++i) {
- WasmFunc *f = &m->funcs[i];
+ WasmFunc* f = &m->funcs[i];
wasm_free_str(m->heap, &f->name);
wasm_free_str(m->heap, &f->import_module);
wasm_free_str(m->heap, &f->import_name);
@@ -415,8 +411,7 @@ static void wasm_module_free(WasmModule *m) {
m->heap->free(m->heap, m->globals, sizeof(*m->globals) * m->cap_globals);
if (m->elems)
m->heap->free(m->heap, m->elems, sizeof(*m->elems) * m->cap_elems);
- for (i = 0; i < m->nexports; ++i)
- wasm_free_str(m->heap, &m->exports[i].name);
+ for (i = 0; i < m->nexports; ++i) wasm_free_str(m->heap, &m->exports[i].name);
if (m->exports)
m->heap->free(m->heap, m->exports, sizeof(*m->exports) * m->cap_exports);
for (i = 0; i < m->ncustoms; ++i) {
@@ -429,37 +424,33 @@ static void wasm_module_free(WasmModule *m) {
memset(m, 0, sizeof *m);
}
-static void wasm_memory_ensure(CfreeCompiler *c, WasmModule *m,
+static void wasm_memory_ensure(CfreeCompiler* c, WasmModule* m,
uint32_t min_len) {
uint32_t old_len, new_len;
- void *p;
+ void* p;
if (!m->has_memory)
wasm_error(c, wasm_loc(0, 0), "wasm: data segment without memory");
old_len = m->memory.data_len;
new_len = old_len;
- if (new_len < min_len)
- new_len = min_len;
+ if (new_len < min_len) new_len = min_len;
if (m->memory.min_pages && new_len < m->memory.min_pages * 65536u)
new_len = m->memory.min_pages * 65536u;
- if (new_len == old_len)
- return;
+ if (new_len == old_len) return;
p = wasm_realloc(m->heap, m->memory.data, old_len, new_len);
- if (!p)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
- m->memory.data = (uint8_t *)p;
+ if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ m->memory.data = (uint8_t*)p;
memset(m->memory.data + old_len, 0, new_len - old_len);
m->memory.data_len = new_len;
}
-static WasmFunc *wasm_add_func(CfreeCompiler *c, WasmModule *m) {
- WasmFunc *f;
+static WasmFunc* wasm_add_func(CfreeCompiler* c, WasmModule* m) {
+ WasmFunc* f;
if (m->nfuncs == m->cap_funcs) {
uint32_t new_cap = m->cap_funcs ? m->cap_funcs * 2u : 4u;
- void *p = wasm_realloc(m->heap, m->funcs, sizeof(*m->funcs) * m->cap_funcs,
+ void* p = wasm_realloc(m->heap, m->funcs, sizeof(*m->funcs) * m->cap_funcs,
sizeof(*m->funcs) * new_cap);
- if (!p)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
- m->funcs = (WasmFunc *)p;
+ if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ m->funcs = (WasmFunc*)p;
memset(m->funcs + m->cap_funcs, 0,
sizeof(*m->funcs) * (new_cap - m->cap_funcs));
m->cap_funcs = new_cap;
@@ -469,15 +460,14 @@ static WasmFunc *wasm_add_func(CfreeCompiler *c, WasmModule *m) {
return f;
}
-static WasmFuncType *wasm_add_type(CfreeCompiler *c, WasmModule *m) {
- WasmFuncType *t;
+static WasmFuncType* wasm_add_type(CfreeCompiler* c, WasmModule* m) {
+ WasmFuncType* t;
if (m->ntypes == m->cap_types) {
uint32_t new_cap = m->cap_types ? m->cap_types * 2u : 8u;
- void *p = wasm_realloc(m->heap, m->types, sizeof(*m->types) * m->cap_types,
+ void* p = wasm_realloc(m->heap, m->types, sizeof(*m->types) * m->cap_types,
sizeof(*m->types) * new_cap);
- if (!p)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
- m->types = (WasmFuncType *)p;
+ if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ m->types = (WasmFuncType*)p;
memset(m->types + m->cap_types, 0,
sizeof(*m->types) * (new_cap - m->cap_types));
m->cap_types = new_cap;
@@ -487,11 +477,11 @@ static WasmFuncType *wasm_add_type(CfreeCompiler *c, WasmModule *m) {
return t;
}
-static uint32_t wasm_intern_func_type(CfreeCompiler *c, WasmModule *m,
- const WasmFunc *f) {
+static uint32_t wasm_intern_func_type(CfreeCompiler* c, WasmModule* m,
+ const WasmFunc* f) {
uint32_t i;
for (i = 0; i < m->ntypes; ++i) {
- WasmFuncType *t = &m->types[i];
+ WasmFuncType* t = &m->types[i];
if (t->nparams == f->nparams && t->nresults == f->nresults &&
memcmp(t->params, f->params, sizeof(t->params[0]) * t->nparams) == 0 &&
memcmp(t->results, f->results, sizeof(t->results[0]) * t->nresults) ==
@@ -499,7 +489,7 @@ static uint32_t wasm_intern_func_type(CfreeCompiler *c, WasmModule *m,
return i;
}
{
- WasmFuncType *t = wasm_add_type(c, m);
+ WasmFuncType* t = wasm_add_type(c, m);
t->nparams = f->nparams;
memcpy(t->params, f->params, sizeof(t->params[0]) * f->nparams);
t->nresults = f->nresults;
@@ -508,16 +498,15 @@ static uint32_t wasm_intern_func_type(CfreeCompiler *c, WasmModule *m,
}
}
-static WasmTable *wasm_add_table(CfreeCompiler *c, WasmModule *m) {
- WasmTable *t;
+static WasmTable* wasm_add_table(CfreeCompiler* c, WasmModule* m) {
+ WasmTable* t;
if (m->ntables == m->cap_tables) {
uint32_t new_cap = m->cap_tables ? m->cap_tables * 2u : 2u;
- void *p =
+ void* p =
wasm_realloc(m->heap, m->tables, sizeof(*m->tables) * m->cap_tables,
sizeof(*m->tables) * new_cap);
- if (!p)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
- m->tables = (WasmTable *)p;
+ if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ m->tables = (WasmTable*)p;
memset(m->tables + m->cap_tables, 0,
sizeof(*m->tables) * (new_cap - m->cap_tables));
m->cap_tables = new_cap;
@@ -527,16 +516,15 @@ static WasmTable *wasm_add_table(CfreeCompiler *c, WasmModule *m) {
return t;
}
-static WasmGlobal *wasm_add_global(CfreeCompiler *c, WasmModule *m) {
- WasmGlobal *g;
+static WasmGlobal* wasm_add_global(CfreeCompiler* c, WasmModule* m) {
+ WasmGlobal* g;
if (m->nglobals == m->cap_globals) {
uint32_t new_cap = m->cap_globals ? m->cap_globals * 2u : 4u;
- void *p =
+ void* p =
wasm_realloc(m->heap, m->globals, sizeof(*m->globals) * m->cap_globals,
sizeof(*m->globals) * new_cap);
- if (!p)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
- m->globals = (WasmGlobal *)p;
+ if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ m->globals = (WasmGlobal*)p;
memset(m->globals + m->cap_globals, 0,
sizeof(*m->globals) * (new_cap - m->cap_globals));
m->cap_globals = new_cap;
@@ -546,15 +534,14 @@ static WasmGlobal *wasm_add_global(CfreeCompiler *c, WasmModule *m) {
return g;
}
-static WasmElemSegment *wasm_add_elem(CfreeCompiler *c, WasmModule *m) {
- WasmElemSegment *e;
+static WasmElemSegment* wasm_add_elem(CfreeCompiler* c, WasmModule* m) {
+ WasmElemSegment* e;
if (m->nelems == m->cap_elems) {
uint32_t new_cap = m->cap_elems ? m->cap_elems * 2u : 4u;
- void *p = wasm_realloc(m->heap, m->elems, sizeof(*m->elems) * m->cap_elems,
+ void* p = wasm_realloc(m->heap, m->elems, sizeof(*m->elems) * m->cap_elems,
sizeof(*m->elems) * new_cap);
- if (!p)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
- m->elems = (WasmElemSegment *)p;
+ if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ m->elems = (WasmElemSegment*)p;
memset(m->elems + m->cap_elems, 0,
sizeof(*m->elems) * (new_cap - m->cap_elems));
m->cap_elems = new_cap;
@@ -564,16 +551,15 @@ static WasmElemSegment *wasm_add_elem(CfreeCompiler *c, WasmModule *m) {
return e;
}
-static WasmExport *wasm_add_export(CfreeCompiler *c, WasmModule *m) {
- WasmExport *e;
+static WasmExport* wasm_add_export(CfreeCompiler* c, WasmModule* m) {
+ WasmExport* e;
if (m->nexports == m->cap_exports) {
uint32_t new_cap = m->cap_exports ? m->cap_exports * 2u : 8u;
- void *p =
+ void* p =
wasm_realloc(m->heap, m->exports, sizeof(*m->exports) * m->cap_exports,
sizeof(*m->exports) * new_cap);
- if (!p)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
- m->exports = (WasmExport *)p;
+ if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ m->exports = (WasmExport*)p;
memset(m->exports + m->cap_exports, 0,
sizeof(*m->exports) * (new_cap - m->cap_exports));
m->cap_exports = new_cap;
@@ -583,16 +569,15 @@ static WasmExport *wasm_add_export(CfreeCompiler *c, WasmModule *m) {
return e;
}
-static WasmCustom *wasm_add_custom(CfreeCompiler *c, WasmModule *m) {
- WasmCustom *cs;
+static WasmCustom* wasm_add_custom(CfreeCompiler* c, WasmModule* m) {
+ WasmCustom* cs;
if (m->ncustoms == m->cap_customs) {
uint32_t new_cap = m->cap_customs ? m->cap_customs * 2u : 4u;
- void *p =
+ void* p =
wasm_realloc(m->heap, m->customs, sizeof(*m->customs) * m->cap_customs,
sizeof(*m->customs) * new_cap);
- if (!p)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
- m->customs = (WasmCustom *)p;
+ if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ m->customs = (WasmCustom*)p;
memset(m->customs + m->cap_customs, 0,
sizeof(*m->customs) * (new_cap - m->cap_customs));
m->cap_customs = new_cap;
@@ -602,15 +587,14 @@ static WasmCustom *wasm_add_custom(CfreeCompiler *c, WasmModule *m) {
return cs;
}
-static void wasm_func_add_insn(CfreeCompiler *c, WasmModule *m, WasmFunc *f,
+static void wasm_func_add_insn(CfreeCompiler* c, WasmModule* m, WasmFunc* f,
WasmInsnKind kind, int64_t imm) {
if (f->ninsns == f->cap_insns) {
uint32_t new_cap = f->cap_insns ? f->cap_insns * 2u : 16u;
- void *p = wasm_realloc(m->heap, f->insns, sizeof(*f->insns) * f->cap_insns,
+ void* p = wasm_realloc(m->heap, f->insns, sizeof(*f->insns) * f->cap_insns,
sizeof(*f->insns) * new_cap);
- if (!p)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
- f->insns = (WasmInsn *)p;
+ if (!p) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ f->insns = (WasmInsn*)p;
f->cap_insns = new_cap;
}
f->insns[f->ninsns].kind = (uint8_t)kind;
@@ -622,50 +606,45 @@ static void wasm_func_add_insn(CfreeCompiler *c, WasmModule *m, WasmFunc *f,
f->ninsns++;
}
-static void wasm_func_add_mem_insn(CfreeCompiler *c, WasmModule *m, WasmFunc *f,
+static void wasm_func_add_mem_insn(CfreeCompiler* c, WasmModule* m, WasmFunc* f,
WasmInsnKind kind, uint32_t align,
uint32_t offset) {
wasm_func_add_insn(c, m, f, kind, (int64_t)offset);
f->insns[f->ninsns - 1u].align = align;
}
-static void wasm_func_add_fp_insn(CfreeCompiler *c, WasmModule *m, WasmFunc *f,
+static void wasm_func_add_fp_insn(CfreeCompiler* c, WasmModule* m, WasmFunc* f,
WasmInsnKind kind, double value) {
wasm_func_add_insn(c, m, f, kind, 0);
f->insns[f->ninsns - 1u].fp = value;
}
-static int tok_is(WasmTok t, const char *s) {
+static int tok_is(WasmTok t, const char* s) {
size_t n = strlen(s);
return t.kind == WT_ATOM && t.len == n && memcmp(t.p, s, n) == 0;
}
-static int wasm_name_eq(const char *name, WasmTok t) {
+static int wasm_name_eq(const char* name, WasmTok t) {
size_t n;
- if (!name || t.kind != WT_ATOM)
- return 0;
+ if (!name || t.kind != WT_ATOM) return 0;
n = strlen(name);
return t.len == n && memcmp(name, t.p, n) == 0;
}
static int wat_hex(char ch) {
- if (ch >= '0' && ch <= '9')
- return ch - '0';
- if (ch >= 'a' && ch <= 'f')
- return ch - 'a' + 10;
- if (ch >= 'A' && ch <= 'F')
- return ch - 'A' + 10;
+ if (ch >= '0' && ch <= '9') return ch - '0';
+ if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
+ if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
return -1;
}
-static char *wat_dup_string(WatParser *p, WasmTok t, size_t *len_out) {
- char *out;
+static char* wat_dup_string(WatParser* p, WasmTok t, size_t* len_out) {
+ char* out;
size_t i, n = 0;
if (t.kind != WT_STRING)
wasm_error(p->c, wasm_loc(t.line, t.col), "wasm wat: expected string");
- out = (char *)p->module->heap->alloc(p->module->heap, t.len + 1u, 1);
- if (!out)
- wasm_error(p->c, wasm_loc(t.line, t.col), "wasm: out of memory");
+ out = (char*)p->module->heap->alloc(p->module->heap, t.len + 1u, 1);
+ if (!out) wasm_error(p->c, wasm_loc(t.line, t.col), "wasm: out of memory");
for (i = 0; i < t.len; ++i) {
char ch = t.p[i];
if (ch != '\\') {
@@ -677,40 +656,39 @@ static char *wat_dup_string(WatParser *p, WasmTok t, size_t *len_out) {
"wasm wat: unterminated string escape");
ch = t.p[i];
switch (ch) {
- case 'n':
- out[n++] = '\n';
- break;
- case 'r':
- out[n++] = '\r';
- break;
- case 't':
- out[n++] = '\t';
- break;
- case '"':
- case '\'':
- case '\\':
- out[n++] = ch;
- break;
- default: {
- int hi = wat_hex(ch);
- int lo = (i + 1u < t.len) ? wat_hex(t.p[i + 1u]) : -1;
- if (hi < 0 || lo < 0)
- wasm_error(p->c, wasm_loc(t.line, t.col),
- "wasm wat: unsupported string escape");
- out[n++] = (char)((hi << 4) | lo);
- i++;
- break;
- }
+ case 'n':
+ out[n++] = '\n';
+ break;
+ case 'r':
+ out[n++] = '\r';
+ break;
+ case 't':
+ out[n++] = '\t';
+ break;
+ case '"':
+ case '\'':
+ case '\\':
+ out[n++] = ch;
+ break;
+ default: {
+ int hi = wat_hex(ch);
+ int lo = (i + 1u < t.len) ? wat_hex(t.p[i + 1u]) : -1;
+ if (hi < 0 || lo < 0)
+ wasm_error(p->c, wasm_loc(t.line, t.col),
+ "wasm wat: unsupported string escape");
+ out[n++] = (char)((hi << 4) | lo);
+ i++;
+ break;
+ }
}
}
out[n] = '\0';
- if (len_out)
- *len_out = n;
+ if (len_out) *len_out = n;
return out;
}
-static void wat_next(WatParser *p) {
- const char *s = p->src;
+static void wat_next(WatParser* p) {
+ const char* s = p->src;
while (p->pos < p->len) {
char ch = s[p->pos];
if (ch == '\n') {
@@ -767,8 +745,7 @@ static void wat_next(WatParser *p) {
p->tok.line = p->line;
p->tok.col = p->col;
p->tok.kind = WT_EOF;
- if (p->pos >= p->len)
- return;
+ if (p->pos >= p->len) return;
if (s[p->pos] == '(') {
p->tok.kind = WT_LPAREN;
p->tok.len = 1;
@@ -792,8 +769,7 @@ static void wat_next(WatParser *p) {
if (s[p->pos] == '\\') {
p->pos++;
p->col++;
- if (p->pos >= p->len)
- break;
+ if (p->pos >= p->len) break;
} else if ((unsigned char)s[p->pos] < 0x20) {
wasm_error(p->c, wasm_loc(p->line, p->col),
"wasm wat: unsupported string escape/control character");
@@ -821,21 +797,20 @@ static void wat_next(WatParser *p) {
p->tok.len = (size_t)(s + p->pos - p->tok.p);
}
-static void wat_expect(WatParser *p, uint8_t kind, const char *what) {
+static void wat_expect(WatParser* p, uint8_t kind, const char* what) {
if (p->tok.kind != kind)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col), "wasm wat: expected %s",
what);
wat_next(p);
}
-static int wat_parse_i64(WatParser *p, int64_t *out) {
- const char *s = p->tok.p;
+static int wat_parse_i64(WatParser* p, int64_t* out) {
+ const char* s = p->tok.p;
size_t n = p->tok.len, i = 0;
uint64_t v = 0;
int neg = 0;
unsigned base = 10;
- if (p->tok.kind != WT_ATOM || n == 0)
- return 0;
+ if (p->tok.kind != WT_ATOM || n == 0) return 0;
if (s[0] == '-' || s[0] == '+') {
neg = s[0] == '-';
i = 1;
@@ -844,28 +819,24 @@ static int wat_parse_i64(WatParser *p, int64_t *out) {
base = 16;
i += 2u;
}
- if (i == n)
- return 0;
+ if (i == n) return 0;
for (; i < n; ++i) {
int hd;
unsigned d;
- if (s[i] == '_')
- continue;
+ if (s[i] == '_') continue;
hd = wat_hex(s[i]);
- if (hd < 0 || (unsigned)hd >= base)
- return 0;
+ if (hd < 0 || (unsigned)hd >= base) return 0;
d = (unsigned)hd;
- if (v > (UINT64_MAX - d) / base)
- return 0;
+ if (v > (UINT64_MAX - d) / base) return 0;
v = v * base + d;
}
*out = neg ? -(int64_t)v : (int64_t)v;
return 1;
}
-static int wat_parse_f64(WatParser *p, double *out) {
+static int wat_parse_f64(WatParser* p, double* out) {
char buf[128];
- char *end = NULL;
+ char* end = NULL;
if (p->tok.kind != WT_ATOM || p->tok.len == 0 || p->tok.len >= sizeof buf)
return 0;
memcpy(buf, p->tok.p, p->tok.len);
@@ -874,7 +845,7 @@ static int wat_parse_f64(WatParser *p, double *out) {
return end && *end == '\0';
}
-static int wat_val_type(WasmTok t, WasmValType *out) {
+static int wat_val_type(WasmTok t, WasmValType* out) {
if (tok_is(t, "i32")) {
*out = WASM_VAL_I32;
return 1;
@@ -908,18 +879,14 @@ static int wasm_is_num_type(WasmValType vt) {
}
static uint8_t wasm_export_kind_from_tok(WasmTok t) {
- if (tok_is(t, "func"))
- return 0;
- if (tok_is(t, "table"))
- return 1;
- if (tok_is(t, "memory"))
- return 2;
- if (tok_is(t, "global"))
- return 3;
+ if (tok_is(t, "func")) return 0;
+ if (tok_is(t, "table")) return 1;
+ if (tok_is(t, "memory")) return 2;
+ if (tok_is(t, "global")) return 3;
return 0xffu;
}
-static void wat_skip_list(WatParser *p) {
+static void wat_skip_list(WatParser* p) {
uint32_t depth = 1;
while (depth && p->tok.kind != WT_EOF) {
if (p->tok.kind == WT_LPAREN)
@@ -930,7 +897,7 @@ static void wat_skip_list(WatParser *p) {
}
}
-static int wat_instr_kind(WasmTok t, WasmInsnKind *out, int *has_imm) {
+static int wat_instr_kind(WasmTok t, WasmInsnKind* out, int* has_imm) {
*has_imm = 0;
if (tok_is(t, "unreachable")) {
*out = WASM_INSN_UNREACHABLE;
@@ -1539,7 +1506,7 @@ static int wat_instr_kind(WasmTok t, WasmInsnKind *out, int *has_imm) {
return 0;
}
-static void wat_parse_func_index(WatParser *p, int64_t *out) {
+static void wat_parse_func_index(WatParser* p, int64_t* out) {
uint32_t i;
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
for (i = 0; i < p->module->nfuncs; ++i) {
@@ -1556,7 +1523,7 @@ static void wat_parse_func_index(WatParser *p, int64_t *out) {
"wasm wat: expected instruction immediate");
}
-static void wat_parse_type_index(WatParser *p, int64_t *out) {
+static void wat_parse_type_index(WatParser* p, int64_t* out) {
uint32_t i;
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
for (i = 0; i < p->module->ntypes; ++i) {
@@ -1573,7 +1540,7 @@ static void wat_parse_type_index(WatParser *p, int64_t *out) {
"wasm wat: expected type index");
}
-static void wat_parse_local_index(WatParser *p, WasmFunc *f, int64_t *out) {
+static void wat_parse_local_index(WatParser* p, WasmFunc* f, int64_t* out) {
uint32_t i, nlocals = f->nparams + f->nlocals;
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
for (i = 0; i < nlocals; ++i) {
@@ -1590,7 +1557,7 @@ static void wat_parse_local_index(WatParser *p, WasmFunc *f, int64_t *out) {
"wasm wat: expected instruction immediate");
}
-static void wat_parse_global_index(WatParser *p, int64_t *out) {
+static void wat_parse_global_index(WatParser* p, int64_t* out) {
uint32_t i;
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
for (i = 0; i < p->module->nglobals; ++i) {
@@ -1607,26 +1574,26 @@ static void wat_parse_global_index(WatParser *p, int64_t *out) {
"wasm wat: expected global index");
}
-static void wat_parse_instr_imm(WatParser *p, WasmFunc *f, WasmInsnKind kind,
- int64_t *out) {
+static void wat_parse_instr_imm(WatParser* p, WasmFunc* f, WasmInsnKind kind,
+ int64_t* out) {
switch (kind) {
- case WASM_INSN_CALL:
- wat_parse_func_index(p, out);
- break;
- case WASM_INSN_GLOBAL_GET:
- case WASM_INSN_GLOBAL_SET:
- wat_parse_global_index(p, out);
- break;
- case WASM_INSN_LOCAL_GET:
- case WASM_INSN_LOCAL_SET:
- case WASM_INSN_LOCAL_TEE:
- wat_parse_local_index(p, f, out);
- break;
- default:
- if (!wat_parse_i64(p, out))
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm wat: expected instruction immediate");
- break;
+ case WASM_INSN_CALL:
+ wat_parse_func_index(p, out);
+ break;
+ case WASM_INSN_GLOBAL_GET:
+ case WASM_INSN_GLOBAL_SET:
+ wat_parse_global_index(p, out);
+ break;
+ case WASM_INSN_LOCAL_GET:
+ case WASM_INSN_LOCAL_SET:
+ case WASM_INSN_LOCAL_TEE:
+ wat_parse_local_index(p, f, out);
+ break;
+ default:
+ if (!wat_parse_i64(p, out))
+ wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
+ "wasm wat: expected instruction immediate");
+ break;
}
}
@@ -1650,41 +1617,36 @@ static int wasm_insn_is_mem(WasmInsnKind kind) {
return wasm_insn_is_load(kind) || wasm_insn_is_store(kind);
}
-static int wat_atom_prefix(WasmTok t, const char *prefix) {
+static int wat_atom_prefix(WasmTok t, const char* prefix) {
size_t n = strlen(prefix);
return t.kind == WT_ATOM && t.len >= n && memcmp(t.p, prefix, n) == 0;
}
-static int wat_parse_u32_atom(WasmTok t, uint32_t *out) {
+static int wat_parse_u32_atom(WasmTok t, uint32_t* out) {
uint64_t v = 0;
size_t i = 0;
unsigned base = 10;
- if (t.kind != WT_ATOM || t.len == 0)
- return 0;
+ if (t.kind != WT_ATOM || t.len == 0) return 0;
if (i + 2u <= t.len && t.p[i] == '0' &&
(t.p[i + 1u] == 'x' || t.p[i + 1u] == 'X')) {
base = 16;
i += 2u;
}
- if (i == t.len)
- return 0;
+ if (i == t.len) return 0;
for (; i < t.len; ++i) {
int hd;
- if (t.p[i] == '_')
- continue;
+ if (t.p[i] == '_') continue;
hd = wat_hex(t.p[i]);
- if (hd < 0 || (unsigned)hd >= base)
- return 0;
- if (v > (UINT32_MAX - (uint32_t)hd) / base)
- return 0;
+ if (hd < 0 || (unsigned)hd >= base) return 0;
+ if (v > (UINT32_MAX - (uint32_t)hd) / base) return 0;
v = v * base + (uint32_t)hd;
}
*out = (uint32_t)v;
return 1;
}
-static void wat_parse_mem_attrs(WatParser *p, uint32_t *align,
- uint32_t *offset) {
+static void wat_parse_mem_attrs(WatParser* p, uint32_t* align,
+ uint32_t* offset) {
while (p->tok.kind == WT_ATOM) {
WasmTok val;
if (wat_atom_prefix(p->tok, "align=")) {
@@ -1709,9 +1671,8 @@ static void wat_parse_mem_attrs(WatParser *p, uint32_t *align,
}
}
-static void wat_reject_inline_result(WatParser *p, const char *what) {
- if (p->tok.kind != WT_LPAREN)
- return;
+static void wat_reject_inline_result(WatParser* p, const char* what) {
+ if (p->tok.kind != WT_LPAREN) return;
wat_next(p);
if (!tok_is(p->tok, "result")) {
p->pos = (size_t)(p->tok.p - p->src);
@@ -1728,9 +1689,9 @@ static void wat_reject_inline_result(WatParser *p, const char *what) {
"wasm wat: %s results are unsupported", what);
}
-static void wat_parse_instr(WatParser *p, WasmFunc *f);
+static void wat_parse_instr(WatParser* p, WasmFunc* f);
-static uint32_t wat_parse_call_indirect_type(WatParser *p) {
+static uint32_t wat_parse_call_indirect_type(WatParser* p) {
int64_t typeidx;
wat_expect(p, WT_LPAREN, "'('");
if (!tok_is(p->tok, "type"))
@@ -1746,7 +1707,7 @@ static uint32_t wat_parse_call_indirect_type(WatParser *p) {
return (uint32_t)typeidx;
}
-static void wat_parse_instr_list(WatParser *p, WasmFunc *f) {
+static void wat_parse_instr_list(WatParser* p, WasmFunc* f) {
WasmInsnKind kind;
int has_imm;
int64_t imm = 0;
@@ -1798,8 +1759,7 @@ static void wat_parse_instr_list(WatParser *p, WasmFunc *f) {
p->tok.len = 1;
p->tok.line = save_line;
p->tok.col = save_col - 1u;
- if (tok_is(save_head, "then") || tok_is(save_head, "else"))
- break;
+ if (tok_is(save_head, "then") || tok_is(save_head, "else")) break;
if (tok_is(save_head, "result"))
wasm_error(p->c, wasm_loc(save_head.line, save_head.col),
"wasm wat: if results are unsupported");
@@ -1838,14 +1798,13 @@ static void wat_parse_instr_list(WatParser *p, WasmFunc *f) {
if (wasm_insn_is_mem(kind)) {
uint32_t align = 0, offset = 0;
wat_parse_mem_attrs(p, &align, &offset);
- while (p->tok.kind == WT_LPAREN)
- wat_parse_instr(p, f);
+ while (p->tok.kind == WT_LPAREN) wat_parse_instr(p, f);
wasm_func_add_mem_insn(p->c, p->module, f, kind, align, offset);
wat_expect(p, WT_RPAREN, "')'");
return;
}
if (kind == WASM_INSN_BR_TABLE) {
- WasmInsn *in;
+ WasmInsn* in;
uint32_t n = 0;
while (p->tok.kind != WT_RPAREN && p->tok.kind != WT_EOF) {
int64_t target;
@@ -1868,8 +1827,7 @@ static void wat_parse_instr_list(WatParser *p, WasmFunc *f) {
}
if (kind == WASM_INSN_CALL_INDIRECT) {
uint32_t typeidx = wat_parse_call_indirect_type(p);
- while (p->tok.kind == WT_LPAREN)
- wat_parse_instr(p, f);
+ while (p->tok.kind == WT_LPAREN) wat_parse_instr(p, f);
wasm_func_add_insn(p->c, p->module, f, kind, typeidx);
wat_expect(p, WT_RPAREN, "')'");
return;
@@ -1881,8 +1839,7 @@ static void wat_parse_instr_list(WatParser *p, WasmFunc *f) {
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: expected float immediate");
wat_next(p);
- while (p->tok.kind == WT_LPAREN)
- wat_parse_instr(p, f);
+ while (p->tok.kind == WT_LPAREN) wat_parse_instr(p, f);
wasm_func_add_fp_insn(p->c, p->module, f, kind, fv);
wat_expect(p, WT_RPAREN, "')'");
return;
@@ -1891,13 +1848,12 @@ static void wat_parse_instr_list(WatParser *p, WasmFunc *f) {
wat_next(p);
}
}
- while (p->tok.kind == WT_LPAREN)
- wat_parse_instr(p, f);
+ while (p->tok.kind == WT_LPAREN) wat_parse_instr(p, f);
wasm_func_add_insn(p->c, p->module, f, kind, imm);
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_instr(WatParser *p, WasmFunc *f) {
+static void wat_parse_instr(WatParser* p, WasmFunc* f) {
WasmInsnKind kind;
int has_imm;
if (p->tok.kind == WT_LPAREN) {
@@ -1919,7 +1875,7 @@ static void wat_parse_instr(WatParser *p, WasmFunc *f) {
return;
}
if (kind == WASM_INSN_BR_TABLE) {
- WasmInsn *in;
+ WasmInsn* in;
uint32_t n = 0;
wasm_func_add_insn(p->c, p->module, f, WASM_INSN_BR_TABLE, 0);
in = &f->insns[f->ninsns - 1u];
@@ -1927,8 +1883,7 @@ static void wat_parse_instr(WatParser *p, WasmFunc *f) {
WasmInsnKind next_kind;
int next_has_imm;
int64_t target;
- if (wat_instr_kind(p->tok, &next_kind, &next_has_imm))
- break;
+ if (wat_instr_kind(p->tok, &next_kind, &next_has_imm)) break;
if (n >= 16u)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: too many br_table targets");
@@ -1965,8 +1920,8 @@ static void wat_parse_instr(WatParser *p, WasmFunc *f) {
}
}
-static void wat_parse_func(WatParser *p) {
- WasmFunc *f = wasm_add_func(p->c, p->module);
+static void wat_parse_func(WatParser* p) {
+ WasmFunc* f = wasm_add_func(p->c, p->module);
uint32_t checked_params = 0;
uint32_t checked_results = 0;
wat_expect(p, WT_LPAREN, "'('");
@@ -1991,7 +1946,7 @@ static void wat_parse_func(WatParser *p) {
"wasm wat: expected export string");
f->export_name = wat_dup_string(p, p->tok, NULL);
{
- WasmExport *ex = wasm_add_export(p->c, p->module);
+ WasmExport* ex = wasm_add_export(p->c, p->module);
ex->name = wasm_strdup(p->module->heap, f->export_name,
strlen(f->export_name));
if (!ex->name)
@@ -2145,8 +2100,8 @@ static void wat_parse_func(WatParser *p) {
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_type_field(WatParser *p) {
- WasmFuncType *t = wasm_add_type(p->c, p->module);
+static void wat_parse_type_field(WatParser* p) {
+ WasmFuncType* t = wasm_add_type(p->c, p->module);
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
t->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
if (!t->name)
@@ -2201,8 +2156,8 @@ static void wat_parse_type_field(WatParser *p) {
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_export_field(WatParser *p) {
- char *name;
+static void wat_parse_export_field(WatParser* p) {
+ char* name;
int64_t idx = 0;
uint8_t kind;
if (p->tok.kind != WT_STRING)
@@ -2225,7 +2180,7 @@ static void wat_parse_export_field(WatParser *p) {
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: export index out of range");
{
- WasmExport *ex = wasm_add_export(p->c, p->module);
+ WasmExport* ex = wasm_add_export(p->c, p->module);
ex->name = name;
ex->kind = kind;
ex->index = (uint32_t)idx;
@@ -2264,13 +2219,12 @@ static void wat_parse_export_field(WatParser *p) {
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_memory_field(WatParser *p) {
+static void wat_parse_memory_field(WatParser* p) {
int64_t min_pages, max_pages;
if (p->module->has_memory)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: multiple memories are unsupported");
- if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$')
- wat_next(p);
+ if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') wat_next(p);
if (!wat_parse_i64(p, &min_pages) || min_pages < 0 || min_pages > UINT16_MAX)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: expected memory minimum");
@@ -2290,8 +2244,8 @@ static void wat_parse_memory_field(WatParser *p) {
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_limits(WatParser *p, uint32_t *min, uint32_t *max,
- int *has_max, const char *what) {
+static void wat_parse_limits(WatParser* p, uint32_t* min, uint32_t* max,
+ int* has_max, const char* what) {
int64_t lo, hi;
if (!wat_parse_i64(p, &lo) || lo < 0 || lo > UINT32_MAX)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
@@ -2308,7 +2262,7 @@ static void wat_parse_limits(WatParser *p, uint32_t *min, uint32_t *max,
}
}
-static void wat_parse_table_limits_and_type(WatParser *p, WasmTable *t) {
+static void wat_parse_table_limits_and_type(WatParser* p, WasmTable* t) {
int64_t lo, hi;
if (!wat_parse_i64(p, &lo) || lo < 0 || lo > UINT32_MAX)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
@@ -2332,7 +2286,7 @@ static void wat_parse_table_limits_and_type(WatParser *p, WasmTable *t) {
wat_next(p);
}
-static void wat_parse_import_field(WatParser *p) {
+static void wat_parse_import_field(WatParser* p) {
char *mod, *name;
if (p->tok.kind != WT_STRING)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
@@ -2346,7 +2300,7 @@ static void wat_parse_import_field(WatParser *p) {
wat_next(p);
wat_expect(p, WT_LPAREN, "'('");
if (tok_is(p->tok, "func")) {
- WasmFunc *f = wasm_add_func(p->c, p->module);
+ WasmFunc* f = wasm_add_func(p->c, p->module);
f->is_import = 1;
f->import_module = mod;
f->import_name = name;
@@ -2412,8 +2366,7 @@ static void wat_parse_import_field(WatParser *p) {
}
wat_expect(p, WT_RPAREN, "')'");
}
- if (!f->has_typeidx)
- f->typeidx = wasm_intern_func_type(p->c, p->module, f);
+ if (!f->has_typeidx) f->typeidx = wasm_intern_func_type(p->c, p->module, f);
} else if (tok_is(p->tok, "memory")) {
if (p->module->has_memory)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
@@ -2435,7 +2388,7 @@ static void wat_parse_import_field(WatParser *p) {
&p->module->memory.max_pages, &p->module->memory.has_max,
"memory");
} else if (tok_is(p->tok, "table")) {
- WasmTable *t = wasm_add_table(p->c, p->module);
+ WasmTable* t = wasm_add_table(p->c, p->module);
t->is_import = 1;
t->import_module = mod;
t->import_name = name;
@@ -2449,7 +2402,7 @@ static void wat_parse_import_field(WatParser *p) {
}
wat_parse_table_limits_and_type(p, t);
} else if (tok_is(p->tok, "global")) {
- WasmGlobal *g = wasm_add_global(p->c, p->module);
+ WasmGlobal* g = wasm_add_global(p->c, p->module);
g->is_import = 1;
g->import_module = mod;
g->import_name = name;
@@ -2487,8 +2440,8 @@ static void wat_parse_import_field(WatParser *p) {
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_table_field(WatParser *p) {
- WasmTable *t = wasm_add_table(p->c, p->module);
+static void wat_parse_table_field(WatParser* p) {
+ WasmTable* t = wasm_add_table(p->c, p->module);
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
t->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
if (!t->name)
@@ -2500,7 +2453,7 @@ static void wat_parse_table_field(WatParser *p) {
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_const_expr(WatParser *p, WasmInsn *out) {
+static void wat_parse_const_expr(WatParser* p, WasmInsn* out) {
WasmInsnKind kind;
int has_imm;
memset(out, 0, sizeof *out);
@@ -2524,8 +2477,8 @@ static void wat_parse_const_expr(WatParser *p, WasmInsn *out) {
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_global_field(WatParser *p) {
- WasmGlobal *g = wasm_add_global(p->c, p->module);
+static void wat_parse_global_field(WatParser* p) {
+ WasmGlobal* g = wasm_add_global(p->c, p->module);
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
g->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
if (!g->name)
@@ -2542,7 +2495,7 @@ static void wat_parse_global_field(WatParser *p) {
"wasm wat: expected export string");
g->export_name = wat_dup_string(p, p->tok, NULL);
{
- WasmExport *ex = wasm_add_export(p->c, p->module);
+ WasmExport* ex = wasm_add_export(p->c, p->module);
ex->name = wasm_strdup(p->module->heap, g->export_name,
strlen(g->export_name));
if (!ex->name)
@@ -2578,8 +2531,8 @@ static void wat_parse_global_field(WatParser *p) {
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_elem_field(WatParser *p) {
- WasmElemSegment *e = wasm_add_elem(p->c, p->module);
+static void wat_parse_elem_field(WatParser* p) {
+ WasmElemSegment* e = wasm_add_elem(p->c, p->module);
e->tableidx = 0;
if (p->tok.kind == WT_ATOM) {
int64_t tableidx;
@@ -2599,8 +2552,7 @@ static void wat_parse_elem_field(WatParser *p) {
"wasm wat: element offset must be i32.const");
e->offset = off.imm;
}
- if (tok_is(p->tok, "func"))
- wat_next(p);
+ if (tok_is(p->tok, "func")) wat_next(p);
while (p->tok.kind != WT_RPAREN && p->tok.kind != WT_EOF) {
int64_t idx;
if (e->nfuncs >= 64u)
@@ -2616,7 +2568,7 @@ static void wat_parse_elem_field(WatParser *p) {
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_start_field(WatParser *p) {
+static void wat_parse_start_field(WatParser* p) {
int64_t idx;
wat_parse_func_index(p, &idx);
if (idx < 0 || idx > UINT32_MAX)
@@ -2628,10 +2580,10 @@ static void wat_parse_start_field(WatParser *p) {
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_custom_field(WatParser *p) {
- WasmCustom *cs;
+static void wat_parse_custom_field(WatParser* p) {
+ WasmCustom* cs;
size_t n = 0;
- char *bytes;
+ char* bytes;
if (p->tok.kind != WT_STRING)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: expected custom section name");
@@ -2643,8 +2595,7 @@ static void wat_parse_custom_field(WatParser *p) {
wat_next(p);
if (p->tok.kind == WT_STRING) {
bytes = wat_dup_string(p, p->tok, &n);
- cs->data =
- (uint8_t *)p->module->heap->alloc(p->module->heap, n ? n : 1u, 1);
+ cs->data = (uint8_t*)p->module->heap->alloc(p->module->heap, n ? n : 1u, 1);
if (!cs->data)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm: out of memory");
@@ -2656,13 +2607,12 @@ static void wat_parse_custom_field(WatParser *p) {
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_data_field(WatParser *p) {
+static void wat_parse_data_field(WatParser* p) {
int64_t offset = 0;
- char *bytes;
+ char* bytes;
size_t nbytes;
size_t alloc_len;
- if (p->tok.kind == WT_ATOM)
- wat_next(p);
+ if (p->tok.kind == WT_ATOM) wat_next(p);
wat_expect(p, WT_LPAREN, "'('");
if (!tok_is(p->tok, "i32.const"))
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
@@ -2684,20 +2634,19 @@ static void wat_parse_data_field(WatParser *p) {
wasm_memory_ensure(p->c, p->module, (uint32_t)offset + (uint32_t)nbytes);
memcpy(p->module->memory.data + (uint32_t)offset, bytes, nbytes);
if ((uint64_t)offset + nbytes > p->module->memory.data_init_len)
- p->module->memory.data_init_len =
- (uint32_t)((uint64_t)offset + nbytes);
+ p->module->memory.data_init_len = (uint32_t)((uint64_t)offset + nbytes);
p->module->heap->free(p->module->heap, bytes, alloc_len);
wat_next(p);
wat_expect(p, WT_RPAREN, "')'");
}
-static void wat_parse_module(CfreeCompiler *c, const CfreeBytesInput *input,
- WasmModule *out) {
+static void wat_parse_module(CfreeCompiler* c, const CfreeBytesInput* input,
+ WasmModule* out) {
WatParser p;
memset(&p, 0, sizeof p);
p.c = c;
p.name = input->name;
- p.src = (const char *)input->data;
+ p.src = (const char*)input->data;
p.len = input->len;
p.line = 1;
p.col = 1;
@@ -2762,13 +2711,13 @@ static void wat_parse_module(CfreeCompiler *c, const CfreeBytesInput *input,
"wasm wat: trailing tokens after module");
}
-static uint8_t bin_u8(BinReader *r) {
+static uint8_t bin_u8(BinReader* r) {
if (r->pos >= r->len)
wasm_error(r->c, wasm_loc(0, 0), "wasm: unexpected end of file");
return r->data[r->pos++];
}
-static uint32_t bin_uleb(BinReader *r) {
+static uint32_t bin_uleb(BinReader* r) {
uint32_t result = 0, shift = 0;
uint32_t nbytes = 0;
for (;;) {
@@ -2776,13 +2725,12 @@ static uint32_t bin_uleb(BinReader *r) {
if (nbytes++ >= 5u || (shift == 28u && (b & 0xf0u)))
wasm_error(r->c, wasm_loc(0, 0), "wasm: invalid uleb128");
result |= (uint32_t)(b & 0x7fu) << shift;
- if (!(b & 0x80u))
- return result;
+ if (!(b & 0x80u)) return result;
shift += 7u;
}
}
-static int64_t bin_sleb(BinReader *r, uint32_t bits) {
+static int64_t bin_sleb(BinReader* r, uint32_t bits) {
int64_t result = 0;
uint32_t shift = 0;
uint32_t max_bytes = (bits + 6u) / 7u;
@@ -2795,69 +2743,63 @@ static int64_t bin_sleb(BinReader *r, uint32_t bits) {
result |= (int64_t)(b & 0x7fu) << shift;
shift += 7u;
} while (b & 0x80u);
- if (shift < bits && (b & 0x40u))
- result |= -((int64_t)1 << shift);
+ if (shift < bits && (b & 0x40u)) result |= -((int64_t)1 << shift);
return result;
}
-static double bin_f32(BinReader *r) {
+static double bin_f32(BinReader* r) {
uint32_t bits = 0;
float f;
- for (uint32_t i = 0; i < 4u; ++i)
- bits |= (uint32_t)bin_u8(r) << (i * 8u);
+ for (uint32_t i = 0; i < 4u; ++i) bits |= (uint32_t)bin_u8(r) << (i * 8u);
memcpy(&f, &bits, sizeof f);
return (double)f;
}
-static double bin_f64(BinReader *r) {
+static double bin_f64(BinReader* r) {
uint64_t bits = 0;
double d;
- for (uint32_t i = 0; i < 8u; ++i)
- bits |= (uint64_t)bin_u8(r) << (i * 8u);
+ for (uint32_t i = 0; i < 8u; ++i) bits |= (uint64_t)bin_u8(r) << (i * 8u);
memcpy(&d, &bits, sizeof d);
return d;
}
-static void bin_need(BinReader *r, size_t n) {
+static void bin_need(BinReader* r, size_t n) {
if (n > r->len || r->pos > r->len - n)
wasm_error(r->c, wasm_loc(0, 0), "wasm: section length out of bounds");
}
-static char *bin_name(BinReader *r, CfreeHeap *h, uint32_t *len_out) {
+static char* bin_name(BinReader* r, CfreeHeap* h, uint32_t* len_out) {
uint32_t n = bin_uleb(r);
- char *s;
+ char* s;
bin_need(r, n);
- s = wasm_strdup(h, (const char *)(r->data + r->pos), n);
- if (!s)
- wasm_error(r->c, wasm_loc(0, 0), "wasm: out of memory");
+ s = wasm_strdup(h, (const char*)(r->data + r->pos), n);
+ if (!s) wasm_error(r->c, wasm_loc(0, 0), "wasm: out of memory");
r->pos += n;
- if (len_out)
- *len_out = n;
+ if (len_out) *len_out = n;
return s;
}
-static WasmValType bin_val_type(BinReader *r, int refs_ok) {
+static WasmValType bin_val_type(BinReader* r, int refs_ok) {
uint8_t b = bin_u8(r);
switch (b) {
- case WASM_VAL_I32:
- case WASM_VAL_I64:
- case WASM_VAL_F32:
- case WASM_VAL_F64:
- return (WasmValType)b;
- case WASM_VAL_FUNCREF:
- case WASM_VAL_EXTERNREF:
- if (refs_ok)
+ case WASM_VAL_I32:
+ case WASM_VAL_I64:
+ case WASM_VAL_F32:
+ case WASM_VAL_F64:
return (WasmValType)b;
- break;
- default:
- break;
+ case WASM_VAL_FUNCREF:
+ case WASM_VAL_EXTERNREF:
+ if (refs_ok) return (WasmValType)b;
+ break;
+ default:
+ break;
}
wasm_error(r->c, wasm_loc(0, 0), "wasm: unsupported value type 0x%02x", b);
return WASM_VAL_I32;
}
-static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
- WasmModule *out) {
+static void wasm_decode_binary(CfreeCompiler* c, const CfreeBytesInput* input,
+ WasmModule* out) {
BinReader r;
uint32_t nfunc_types = 0;
uint8_t last_id = 0;
@@ -2877,8 +2819,7 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
end = r.pos + size;
if (id != 0 && id <= last_id)
wasm_error(c, wasm_loc(0, 0), "wasm: sections out of order");
- if (id != 0)
- last_id = id;
+ if (id != 0) last_id = id;
if (id == 0) {
uint32_t name_len = bin_uleb(&r);
bin_need(&r, name_len);
@@ -2886,20 +2827,18 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
wasm_error(c, wasm_loc(0, 0),
"wasm: relocatable object metadata is not frontend input");
{
- WasmCustom *cs = wasm_add_custom(c, out);
+ WasmCustom* cs = wasm_add_custom(c, out);
cs->name =
- wasm_strdup(out->heap, (const char *)(r.data + r.pos), name_len);
- if (!cs->name)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ wasm_strdup(out->heap, (const char*)(r.data + r.pos), name_len);
+ if (!cs->name) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
r.pos += name_len;
if (strcmp(cs->name, "target_features") == 0 ||
strcmp(cs->name, "target-feature") == 0)
out->has_target_features = 1;
cs->len = (uint32_t)(end - r.pos);
if (cs->len) {
- cs->data = (uint8_t *)out->heap->alloc(out->heap, cs->len, 1);
- if (!cs->data)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ cs->data = (uint8_t*)out->heap->alloc(out->heap, cs->len, 1);
+ if (!cs->data) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
memcpy(cs->data, r.data + r.pos, cs->len);
}
}
@@ -2908,10 +2847,9 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
}
if (id == 1) {
uint32_t i, count = bin_uleb(&r);
- if (count > 64u)
- wasm_error(c, wasm_loc(0, 0), "wasm: too many types");
+ if (count > 64u) wasm_error(c, wasm_loc(0, 0), "wasm: too many types");
for (i = 0; i < count; ++i) {
- WasmFuncType *t = wasm_add_type(c, out);
+ WasmFuncType* t = wasm_add_type(c, out);
uint32_t j, nparam, nresult;
if (bin_u8(&r) != 0x60u)
wasm_error(c, wasm_loc(0, 0), "wasm: expected function type");
@@ -2919,24 +2857,22 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
if (nparam > 16u)
wasm_error(c, wasm_loc(0, 0), "wasm: too many parameters");
t->nparams = nparam;
- for (j = 0; j < nparam; ++j)
- t->params[j] = bin_val_type(&r, 0);
+ for (j = 0; j < nparam; ++j) t->params[j] = bin_val_type(&r, 0);
nresult = bin_uleb(&r);
if (nresult > 1u)
wasm_error(c, wasm_loc(0, 0), "wasm: multi-result unsupported");
t->nresults = nresult;
- for (j = 0; j < nresult; ++j)
- t->results[j] = bin_val_type(&r, 0);
+ for (j = 0; j < nresult; ++j) t->results[j] = bin_val_type(&r, 0);
}
} else if (id == 2) {
uint32_t i, count = bin_uleb(&r);
for (i = 0; i < count; ++i) {
- char *mod = bin_name(&r, out->heap, NULL);
- char *name = bin_name(&r, out->heap, NULL);
+ char* mod = bin_name(&r, out->heap, NULL);
+ char* name = bin_name(&r, out->heap, NULL);
uint8_t kind = bin_u8(&r);
if (kind == 0) {
uint32_t typeidx = bin_uleb(&r);
- WasmFunc *f;
+ WasmFunc* f;
if (typeidx >= out->ntypes)
wasm_error(c, wasm_loc(0, 0), "wasm: bad import type index");
f = wasm_add_func(c, out);
@@ -2952,7 +2888,7 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
memcpy(f->results, out->types[typeidx].results,
sizeof(f->results[0]) * f->nresults);
} else if (kind == 1) {
- WasmTable *t = wasm_add_table(c, out);
+ WasmTable* t = wasm_add_table(c, out);
t->is_import = 1;
t->import_module = mod;
t->import_name = name;
@@ -2963,8 +2899,7 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
wasm_error(c, wasm_loc(0, 0), "wasm: unsupported table limits");
t->has_max = (flags & 1u) != 0;
t->min = bin_uleb(&r);
- if (t->has_max)
- t->max = bin_uleb(&r);
+ if (t->has_max) t->max = bin_uleb(&r);
}
} else if (kind == 2) {
uint32_t flags;
@@ -2980,10 +2915,9 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
wasm_error(c, wasm_loc(0, 0), "wasm: unsupported memory limits");
out->memory.has_max = (flags & 1u) != 0;
out->memory.min_pages = bin_uleb(&r);
- if (out->memory.has_max)
- out->memory.max_pages = bin_uleb(&r);
+ if (out->memory.has_max) out->memory.max_pages = bin_uleb(&r);
} else if (kind == 3) {
- WasmGlobal *g = wasm_add_global(c, out);
+ WasmGlobal* g = wasm_add_global(c, out);
g->is_import = 1;
g->import_module = mod;
g->import_name = name;
@@ -3001,7 +2935,7 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
wasm_error(c, wasm_loc(0, 0), "wasm: too many functions");
for (i = 0; i < count; ++i) {
uint32_t typeidx = bin_uleb(&r);
- WasmFunc *f;
+ WasmFunc* f;
if (typeidx >= out->ntypes)
wasm_error(c, wasm_loc(0, 0), "wasm: bad function type index");
f = wasm_add_func(c, out);
@@ -3037,7 +2971,7 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
} else if (id == 4) {
uint32_t i, count = bin_uleb(&r);
for (i = 0; i < count; ++i) {
- WasmTable *t = wasm_add_table(c, out);
+ WasmTable* t = wasm_add_table(c, out);
uint32_t flags;
t->elem_type = bin_val_type(&r, 1);
flags = bin_uleb(&r);
@@ -3045,13 +2979,12 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
wasm_error(c, wasm_loc(0, 0), "wasm: unsupported table limits");
t->has_max = (flags & 1u) != 0;
t->min = bin_uleb(&r);
- if (t->has_max)
- t->max = bin_uleb(&r);
+ if (t->has_max) t->max = bin_uleb(&r);
}
} else if (id == 6) {
uint32_t i, count = bin_uleb(&r);
for (i = 0; i < count; ++i) {
- WasmGlobal *g = wasm_add_global(c, out);
+ WasmGlobal* g = wasm_add_global(c, out);
uint8_t op;
g->type = bin_val_type(&r, 0);
g->mutable_ = bin_u8(&r);
@@ -3059,25 +2992,25 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
wasm_error(c, wasm_loc(0, 0), "wasm: bad global mutability");
op = bin_u8(&r);
switch (op) {
- case 0x41:
- g->init.kind = WASM_INSN_I32_CONST;
- g->init.imm = bin_sleb(&r, 32);
- break;
- case 0x42:
- g->init.kind = WASM_INSN_I64_CONST;
- g->init.imm = bin_sleb(&r, 64);
- break;
- case 0x43:
- g->init.kind = WASM_INSN_F32_CONST;
- g->init.fp = bin_f32(&r);
- break;
- case 0x44:
- g->init.kind = WASM_INSN_F64_CONST;
- g->init.fp = bin_f64(&r);
- break;
- default:
- wasm_error(c, wasm_loc(0, 0),
- "wasm: unsupported global initializer");
+ case 0x41:
+ g->init.kind = WASM_INSN_I32_CONST;
+ g->init.imm = bin_sleb(&r, 32);
+ break;
+ case 0x42:
+ g->init.kind = WASM_INSN_I64_CONST;
+ g->init.imm = bin_sleb(&r, 64);
+ break;
+ case 0x43:
+ g->init.kind = WASM_INSN_F32_CONST;
+ g->init.fp = bin_f32(&r);
+ break;
+ case 0x44:
+ g->init.kind = WASM_INSN_F64_CONST;
+ g->init.fp = bin_f64(&r);
+ break;
+ default:
+ wasm_error(c, wasm_loc(0, 0),
+ "wasm: unsupported global initializer");
}
if (bin_u8(&r) != 0x0bu)
wasm_error(c, wasm_loc(0, 0), "wasm: malformed global initializer");
@@ -3085,21 +3018,20 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
} else if (id == 7) {
uint32_t i, count = bin_uleb(&r);
for (i = 0; i < count; ++i) {
- char *name;
+ char* name;
uint8_t kind;
uint32_t idx;
- WasmExport *ex;
+ WasmExport* ex;
name = bin_name(&r, out->heap, NULL);
kind = bin_u8(&r);
idx = bin_uleb(&r);
- if (kind > 3u)
- wasm_error(c, wasm_loc(0, 0), "wasm: bad export kind");
+ if (kind > 3u) wasm_error(c, wasm_loc(0, 0), "wasm: bad export kind");
ex = wasm_add_export(c, out);
ex->name = name;
ex->kind = kind;
ex->index = idx;
if (kind == 0 && idx < out->nfuncs) {
- WasmFunc *f = &out->funcs[idx];
+ WasmFunc* f = &out->funcs[idx];
wasm_free_str(out->heap, &f->export_name);
f->export_name = wasm_strdup(out->heap, name, strlen(name));
if (!f->export_name)
@@ -3123,7 +3055,7 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
} else if (id == 9) {
uint32_t i, count = bin_uleb(&r);
for (i = 0; i < count; ++i) {
- WasmElemSegment *e = wasm_add_elem(c, out);
+ WasmElemSegment* e = wasm_add_elem(c, out);
uint32_t flags = bin_uleb(&r);
uint32_t n;
if (flags != 0)
@@ -3139,8 +3071,7 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
n = bin_uleb(&r);
if (n > 64u)
wasm_error(c, wasm_loc(0, 0), "wasm: too many element functions");
- for (uint32_t k = 0; k < n; ++k)
- e->funcs[e->nfuncs++] = bin_uleb(&r);
+ for (uint32_t k = 0; k < n; ++k) e->funcs[e->nfuncs++] = bin_uleb(&r);
}
} else if (id == 10) {
uint32_t i, count = bin_uleb(&r);
@@ -3153,7 +3084,7 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
uint32_t local_groups, j;
uint32_t control_depth = 0;
int saw_body_end = 0;
- WasmFunc *f;
+ WasmFunc* f;
while (func_index < out->nfuncs && out->funcs[func_index].is_import)
func_index++;
if (func_index >= out->nfuncs)
@@ -3167,8 +3098,7 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
WasmValType vt = (WasmValType)bin_u8(&r);
if (nlocals > 32u || f->nlocals > 32u - nlocals)
wasm_error(c, wasm_loc(0, 0), "wasm: too many locals");
- for (k = 0; k < nlocals; ++k)
- f->locals[f->nlocals++] = vt;
+ for (k = 0; k < nlocals; ++k) f->locals[f->nlocals++] = vt;
}
while (r.pos < body_end) {
uint8_t op = bin_u8(&r);
@@ -3182,505 +3112,504 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
continue;
}
switch (op) {
- case 0x00:
- wasm_func_add_insn(c, out, f, WASM_INSN_UNREACHABLE, 0);
- break;
- case 0x01:
- wasm_func_add_insn(c, out, f, WASM_INSN_NOP, 0);
- break;
- case 0x02:
- if (bin_u8(&r) != 0x40u)
- wasm_error(c, wasm_loc(0, 0),
- "wasm: block results are unsupported");
- control_depth++;
- wasm_func_add_insn(c, out, f, WASM_INSN_BLOCK, 0);
- break;
- case 0x03:
- if (bin_u8(&r) != 0x40u)
- wasm_error(c, wasm_loc(0, 0),
- "wasm: loop results are unsupported");
- control_depth++;
- wasm_func_add_insn(c, out, f, WASM_INSN_LOOP, 0);
- break;
- case 0x04:
- if (bin_u8(&r) != 0x40u)
- wasm_error(c, wasm_loc(0, 0),
- "wasm: if results are unsupported");
- control_depth++;
- wasm_func_add_insn(c, out, f, WASM_INSN_IF, 0);
- break;
- case 0x05:
- wasm_func_add_insn(c, out, f, WASM_INSN_ELSE, 0);
- break;
- case 0x0c:
- wasm_func_add_insn(c, out, f, WASM_INSN_BR, bin_uleb(&r));
- break;
- case 0x0d:
- wasm_func_add_insn(c, out, f, WASM_INSN_BR_IF, bin_uleb(&r));
- break;
- case 0x0e: {
- WasmInsn *in;
- uint32_t n = bin_uleb(&r);
- if (n >= 16u)
- wasm_error(c, wasm_loc(0, 0),
- "wasm: too many br_table targets");
- wasm_func_add_insn(c, out, f, WASM_INSN_BR_TABLE, 0);
- in = &f->insns[f->ninsns - 1u];
- for (uint32_t k = 0; k < n; ++k)
- in->targets[k] = bin_uleb(&r);
- in->targets[n] = bin_uleb(&r);
- in->ntargets = n + 1u;
- break;
- }
- case 0x0f:
- wasm_func_add_insn(c, out, f, WASM_INSN_RETURN, 0);
- break;
- case 0x1a:
- wasm_func_add_insn(c, out, f, WASM_INSN_DROP, 0);
- break;
- case 0x1b:
- wasm_func_add_insn(c, out, f, WASM_INSN_SELECT, 0);
- break;
- case 0x28:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x29:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x2c:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD8_S,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x2d:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD8_U,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x2e:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD16_S,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x2f:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD16_U,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x30:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD8_S,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x31:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD8_U,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x32:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD16_S,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x33:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD16_U,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x34:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD32_S,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x35:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD32_U,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x36:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_STORE,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x37:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x3a:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_STORE8,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x3b:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_STORE16,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x3c:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE8,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x3d:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE16,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x3e:
- wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE32,
- bin_uleb(&r), bin_uleb(&r));
- break;
- case 0x3f:
- if (bin_u8(&r) != 0)
- wasm_error(c, wasm_loc(0, 0), "wasm: bad memory.size index");
- wasm_func_add_insn(c, out, f, WASM_INSN_MEMORY_SIZE, 0);
- break;
- case 0x40:
- if (bin_u8(&r) != 0)
- wasm_error(c, wasm_loc(0, 0), "wasm: bad memory.grow index");
- wasm_func_add_insn(c, out, f, WASM_INSN_MEMORY_GROW, 0);
- break;
- case 0x10:
- wasm_func_add_insn(c, out, f, WASM_INSN_CALL, bin_uleb(&r));
- break;
- case 0x11: {
- WasmInsn *in;
- wasm_func_add_insn(c, out, f, WASM_INSN_CALL_INDIRECT,
- bin_uleb(&r));
- in = &f->insns[f->ninsns - 1u];
- in->align = bin_uleb(&r);
- break;
- }
- case 0x20:
- wasm_func_add_insn(c, out, f, WASM_INSN_LOCAL_GET, bin_uleb(&r));
- break;
- case 0x21:
- wasm_func_add_insn(c, out, f, WASM_INSN_LOCAL_SET, bin_uleb(&r));
- break;
- case 0x22:
- wasm_func_add_insn(c, out, f, WASM_INSN_LOCAL_TEE, bin_uleb(&r));
- break;
- case 0x23:
- wasm_func_add_insn(c, out, f, WASM_INSN_GLOBAL_GET, bin_uleb(&r));
- break;
- case 0x24:
- wasm_func_add_insn(c, out, f, WASM_INSN_GLOBAL_SET, bin_uleb(&r));
- break;
- case 0x41:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_CONST,
- bin_sleb(&r, 32));
- break;
- case 0x42:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_CONST,
- bin_sleb(&r, 64));
- break;
- case 0x43:
- wasm_func_add_fp_insn(c, out, f, WASM_INSN_F32_CONST,
- bin_f32(&r));
- break;
- case 0x44:
- wasm_func_add_fp_insn(c, out, f, WASM_INSN_F64_CONST,
- bin_f64(&r));
- break;
- case 0x45:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_EQZ, 0);
- break;
- case 0x46:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_EQ, 0);
- break;
- case 0x47:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_NE, 0);
- break;
- case 0x48:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_LT_S, 0);
- break;
- case 0x49:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_LT_U, 0);
- break;
- case 0x4a:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_GT_S, 0);
- break;
- case 0x4b:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_GT_U, 0);
- break;
- case 0x4c:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_LE_S, 0);
- break;
- case 0x4d:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_LE_U, 0);
- break;
- case 0x4e:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_GE_S, 0);
- break;
- case 0x4f:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_GE_U, 0);
- break;
- case 0x50:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_EQZ, 0);
- break;
- case 0x51:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_EQ, 0);
- break;
- case 0x52:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_NE, 0);
- break;
- case 0x53:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_LT_S, 0);
- break;
- case 0x54:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_LT_U, 0);
- break;
- case 0x55:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_GT_S, 0);
- break;
- case 0x56:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_GT_U, 0);
- break;
- case 0x57:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_LE_S, 0);
- break;
- case 0x58:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_LE_U, 0);
- break;
- case 0x59:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_GE_S, 0);
- break;
- case 0x5a:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_GE_U, 0);
- break;
- case 0x6a:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_ADD, 0);
- break;
- case 0x6b:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_SUB, 0);
- break;
- case 0x6c:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_MUL, 0);
- break;
- case 0x6d:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_DIV_S, 0);
- break;
- case 0x6e:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_DIV_U, 0);
- break;
- case 0x6f:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_REM_S, 0);
- break;
- case 0x70:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_REM_U, 0);
- break;
- case 0x71:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_AND, 0);
- break;
- case 0x72:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_OR, 0);
- break;
- case 0x73:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_XOR, 0);
- break;
- case 0x74:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_SHL, 0);
- break;
- case 0x75:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_SHR_S, 0);
- break;
- case 0x76:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_SHR_U, 0);
- break;
- case 0x67:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_CLZ, 0);
- break;
- case 0x68:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_CTZ, 0);
- break;
- case 0x69:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_POPCNT, 0);
- break;
- case 0x77:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_ROTL, 0);
- break;
- case 0x78:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_ROTR, 0);
- break;
- case 0x79:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_CLZ, 0);
- break;
- case 0x7a:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_CTZ, 0);
- break;
- case 0x7b:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_POPCNT, 0);
- break;
- case 0x7c:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_ADD, 0);
- break;
- case 0x7d:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_SUB, 0);
- break;
- case 0x7e:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_MUL, 0);
- break;
- case 0x7f:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_DIV_S, 0);
- break;
- case 0x80:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_DIV_U, 0);
- break;
- case 0x81:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_REM_S, 0);
- break;
- case 0x82:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_REM_U, 0);
- break;
- case 0x83:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_AND, 0);
- break;
- case 0x84:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_OR, 0);
- break;
- case 0x85:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_XOR, 0);
- break;
- case 0x86:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_SHL, 0);
- break;
- case 0x87:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_SHR_S, 0);
- break;
- case 0x88:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_SHR_U, 0);
- break;
- case 0x89:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_ROTL, 0);
- break;
- case 0x8a:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_ROTR, 0);
- break;
- case 0x92:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_ADD, 0);
- break;
- case 0x93:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_SUB, 0);
- break;
- case 0x94:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_MUL, 0);
- break;
- case 0x95:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_DIV, 0);
- break;
- case 0xa0:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_ADD, 0);
- break;
- case 0xa1:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_SUB, 0);
- break;
- case 0xa2:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_MUL, 0);
- break;
- case 0xa3:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_DIV, 0);
- break;
- case 0x5b:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_EQ, 0);
- break;
- case 0x5c:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_NE, 0);
- break;
- case 0x5d:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_LT, 0);
- break;
- case 0x5e:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_GT, 0);
- break;
- case 0x5f:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_LE, 0);
- break;
- case 0x60:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_GE, 0);
- break;
- case 0x61:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_EQ, 0);
- break;
- case 0x62:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_NE, 0);
- break;
- case 0x63:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_LT, 0);
- break;
- case 0x64:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_GT, 0);
- break;
- case 0x65:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_LE, 0);
- break;
- case 0x66:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_GE, 0);
- break;
- case 0xa7:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_WRAP_I64, 0);
- break;
- case 0xa8:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F32_S, 0);
- break;
- case 0xa9:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F32_U, 0);
- break;
- case 0xaa:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F64_S, 0);
- break;
- case 0xab:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F64_U, 0);
- break;
- case 0xac:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_EXTEND_I32_S, 0);
- break;
- case 0xad:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_EXTEND_I32_U, 0);
- break;
- case 0xae:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F32_S, 0);
- break;
- case 0xaf:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F32_U, 0);
- break;
- case 0xb0:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F64_S, 0);
- break;
- case 0xb1:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F64_U, 0);
- break;
- case 0xb2:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I32_S, 0);
- break;
- case 0xb3:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I32_U, 0);
- break;
- case 0xb4:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I64_S, 0);
- break;
- case 0xb5:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I64_U, 0);
- break;
- case 0xb6:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_DEMOTE_F64, 0);
- break;
- case 0xb7:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I32_S, 0);
- break;
- case 0xb8:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I32_U, 0);
- break;
- case 0xb9:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I64_S, 0);
- break;
- case 0xba:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I64_U, 0);
- break;
- case 0xbb:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_PROMOTE_F32, 0);
- break;
- case 0xbc:
- wasm_func_add_insn(c, out, f, WASM_INSN_I32_REINTERPRET_F32, 0);
- break;
- case 0xbd:
- wasm_func_add_insn(c, out, f, WASM_INSN_I64_REINTERPRET_F64, 0);
- break;
- case 0xbe:
- wasm_func_add_insn(c, out, f, WASM_INSN_F32_REINTERPRET_I32, 0);
- break;
- case 0xbf:
- wasm_func_add_insn(c, out, f, WASM_INSN_F64_REINTERPRET_I64, 0);
- break;
- default:
- wasm_error(c, wasm_loc(0, 0), "wasm: unsupported opcode 0x%02x",
- op);
+ case 0x00:
+ wasm_func_add_insn(c, out, f, WASM_INSN_UNREACHABLE, 0);
+ break;
+ case 0x01:
+ wasm_func_add_insn(c, out, f, WASM_INSN_NOP, 0);
+ break;
+ case 0x02:
+ if (bin_u8(&r) != 0x40u)
+ wasm_error(c, wasm_loc(0, 0),
+ "wasm: block results are unsupported");
+ control_depth++;
+ wasm_func_add_insn(c, out, f, WASM_INSN_BLOCK, 0);
+ break;
+ case 0x03:
+ if (bin_u8(&r) != 0x40u)
+ wasm_error(c, wasm_loc(0, 0),
+ "wasm: loop results are unsupported");
+ control_depth++;
+ wasm_func_add_insn(c, out, f, WASM_INSN_LOOP, 0);
+ break;
+ case 0x04:
+ if (bin_u8(&r) != 0x40u)
+ wasm_error(c, wasm_loc(0, 0),
+ "wasm: if results are unsupported");
+ control_depth++;
+ wasm_func_add_insn(c, out, f, WASM_INSN_IF, 0);
+ break;
+ case 0x05:
+ wasm_func_add_insn(c, out, f, WASM_INSN_ELSE, 0);
+ break;
+ case 0x0c:
+ wasm_func_add_insn(c, out, f, WASM_INSN_BR, bin_uleb(&r));
+ break;
+ case 0x0d:
+ wasm_func_add_insn(c, out, f, WASM_INSN_BR_IF, bin_uleb(&r));
+ break;
+ case 0x0e: {
+ WasmInsn* in;
+ uint32_t n = bin_uleb(&r);
+ if (n >= 16u)
+ wasm_error(c, wasm_loc(0, 0),
+ "wasm: too many br_table targets");
+ wasm_func_add_insn(c, out, f, WASM_INSN_BR_TABLE, 0);
+ in = &f->insns[f->ninsns - 1u];
+ for (uint32_t k = 0; k < n; ++k) in->targets[k] = bin_uleb(&r);
+ in->targets[n] = bin_uleb(&r);
+ in->ntargets = n + 1u;
+ break;
+ }
+ case 0x0f:
+ wasm_func_add_insn(c, out, f, WASM_INSN_RETURN, 0);
+ break;
+ case 0x1a:
+ wasm_func_add_insn(c, out, f, WASM_INSN_DROP, 0);
+ break;
+ case 0x1b:
+ wasm_func_add_insn(c, out, f, WASM_INSN_SELECT, 0);
+ break;
+ case 0x28:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x29:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x2c:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD8_S,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x2d:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD8_U,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x2e:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD16_S,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x2f:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_LOAD16_U,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x30:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD8_S,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x31:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD8_U,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x32:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD16_S,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x33:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD16_U,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x34:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD32_S,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x35:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_LOAD32_U,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x36:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_STORE,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x37:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x3a:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_STORE8,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x3b:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I32_STORE16,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x3c:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE8,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x3d:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE16,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x3e:
+ wasm_func_add_mem_insn(c, out, f, WASM_INSN_I64_STORE32,
+ bin_uleb(&r), bin_uleb(&r));
+ break;
+ case 0x3f:
+ if (bin_u8(&r) != 0)
+ wasm_error(c, wasm_loc(0, 0), "wasm: bad memory.size index");
+ wasm_func_add_insn(c, out, f, WASM_INSN_MEMORY_SIZE, 0);
+ break;
+ case 0x40:
+ if (bin_u8(&r) != 0)
+ wasm_error(c, wasm_loc(0, 0), "wasm: bad memory.grow index");
+ wasm_func_add_insn(c, out, f, WASM_INSN_MEMORY_GROW, 0);
+ break;
+ case 0x10:
+ wasm_func_add_insn(c, out, f, WASM_INSN_CALL, bin_uleb(&r));
+ break;
+ case 0x11: {
+ WasmInsn* in;
+ wasm_func_add_insn(c, out, f, WASM_INSN_CALL_INDIRECT,
+ bin_uleb(&r));
+ in = &f->insns[f->ninsns - 1u];
+ in->align = bin_uleb(&r);
+ break;
+ }
+ case 0x20:
+ wasm_func_add_insn(c, out, f, WASM_INSN_LOCAL_GET, bin_uleb(&r));
+ break;
+ case 0x21:
+ wasm_func_add_insn(c, out, f, WASM_INSN_LOCAL_SET, bin_uleb(&r));
+ break;
+ case 0x22:
+ wasm_func_add_insn(c, out, f, WASM_INSN_LOCAL_TEE, bin_uleb(&r));
+ break;
+ case 0x23:
+ wasm_func_add_insn(c, out, f, WASM_INSN_GLOBAL_GET, bin_uleb(&r));
+ break;
+ case 0x24:
+ wasm_func_add_insn(c, out, f, WASM_INSN_GLOBAL_SET, bin_uleb(&r));
+ break;
+ case 0x41:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_CONST,
+ bin_sleb(&r, 32));
+ break;
+ case 0x42:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_CONST,
+ bin_sleb(&r, 64));
+ break;
+ case 0x43:
+ wasm_func_add_fp_insn(c, out, f, WASM_INSN_F32_CONST,
+ bin_f32(&r));
+ break;
+ case 0x44:
+ wasm_func_add_fp_insn(c, out, f, WASM_INSN_F64_CONST,
+ bin_f64(&r));
+ break;
+ case 0x45:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_EQZ, 0);
+ break;
+ case 0x46:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_EQ, 0);
+ break;
+ case 0x47:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_NE, 0);
+ break;
+ case 0x48:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_LT_S, 0);
+ break;
+ case 0x49:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_LT_U, 0);
+ break;
+ case 0x4a:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_GT_S, 0);
+ break;
+ case 0x4b:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_GT_U, 0);
+ break;
+ case 0x4c:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_LE_S, 0);
+ break;
+ case 0x4d:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_LE_U, 0);
+ break;
+ case 0x4e:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_GE_S, 0);
+ break;
+ case 0x4f:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_GE_U, 0);
+ break;
+ case 0x50:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_EQZ, 0);
+ break;
+ case 0x51:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_EQ, 0);
+ break;
+ case 0x52:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_NE, 0);
+ break;
+ case 0x53:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_LT_S, 0);
+ break;
+ case 0x54:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_LT_U, 0);
+ break;
+ case 0x55:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_GT_S, 0);
+ break;
+ case 0x56:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_GT_U, 0);
+ break;
+ case 0x57:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_LE_S, 0);
+ break;
+ case 0x58:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_LE_U, 0);
+ break;
+ case 0x59:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_GE_S, 0);
+ break;
+ case 0x5a:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_GE_U, 0);
+ break;
+ case 0x6a:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_ADD, 0);
+ break;
+ case 0x6b:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_SUB, 0);
+ break;
+ case 0x6c:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_MUL, 0);
+ break;
+ case 0x6d:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_DIV_S, 0);
+ break;
+ case 0x6e:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_DIV_U, 0);
+ break;
+ case 0x6f:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_REM_S, 0);
+ break;
+ case 0x70:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_REM_U, 0);
+ break;
+ case 0x71:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_AND, 0);
+ break;
+ case 0x72:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_OR, 0);
+ break;
+ case 0x73:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_XOR, 0);
+ break;
+ case 0x74:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_SHL, 0);
+ break;
+ case 0x75:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_SHR_S, 0);
+ break;
+ case 0x76:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_SHR_U, 0);
+ break;
+ case 0x67:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_CLZ, 0);
+ break;
+ case 0x68:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_CTZ, 0);
+ break;
+ case 0x69:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_POPCNT, 0);
+ break;
+ case 0x77:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_ROTL, 0);
+ break;
+ case 0x78:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_ROTR, 0);
+ break;
+ case 0x79:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_CLZ, 0);
+ break;
+ case 0x7a:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_CTZ, 0);
+ break;
+ case 0x7b:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_POPCNT, 0);
+ break;
+ case 0x7c:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_ADD, 0);
+ break;
+ case 0x7d:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_SUB, 0);
+ break;
+ case 0x7e:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_MUL, 0);
+ break;
+ case 0x7f:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_DIV_S, 0);
+ break;
+ case 0x80:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_DIV_U, 0);
+ break;
+ case 0x81:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_REM_S, 0);
+ break;
+ case 0x82:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_REM_U, 0);
+ break;
+ case 0x83:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_AND, 0);
+ break;
+ case 0x84:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_OR, 0);
+ break;
+ case 0x85:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_XOR, 0);
+ break;
+ case 0x86:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_SHL, 0);
+ break;
+ case 0x87:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_SHR_S, 0);
+ break;
+ case 0x88:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_SHR_U, 0);
+ break;
+ case 0x89:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_ROTL, 0);
+ break;
+ case 0x8a:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_ROTR, 0);
+ break;
+ case 0x92:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_ADD, 0);
+ break;
+ case 0x93:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_SUB, 0);
+ break;
+ case 0x94:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_MUL, 0);
+ break;
+ case 0x95:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_DIV, 0);
+ break;
+ case 0xa0:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_ADD, 0);
+ break;
+ case 0xa1:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_SUB, 0);
+ break;
+ case 0xa2:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_MUL, 0);
+ break;
+ case 0xa3:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_DIV, 0);
+ break;
+ case 0x5b:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_EQ, 0);
+ break;
+ case 0x5c:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_NE, 0);
+ break;
+ case 0x5d:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_LT, 0);
+ break;
+ case 0x5e:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_GT, 0);
+ break;
+ case 0x5f:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_LE, 0);
+ break;
+ case 0x60:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_GE, 0);
+ break;
+ case 0x61:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_EQ, 0);
+ break;
+ case 0x62:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_NE, 0);
+ break;
+ case 0x63:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_LT, 0);
+ break;
+ case 0x64:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_GT, 0);
+ break;
+ case 0x65:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_LE, 0);
+ break;
+ case 0x66:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_GE, 0);
+ break;
+ case 0xa7:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_WRAP_I64, 0);
+ break;
+ case 0xa8:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F32_S, 0);
+ break;
+ case 0xa9:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F32_U, 0);
+ break;
+ case 0xaa:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F64_S, 0);
+ break;
+ case 0xab:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_TRUNC_F64_U, 0);
+ break;
+ case 0xac:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_EXTEND_I32_S, 0);
+ break;
+ case 0xad:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_EXTEND_I32_U, 0);
+ break;
+ case 0xae:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F32_S, 0);
+ break;
+ case 0xaf:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F32_U, 0);
+ break;
+ case 0xb0:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F64_S, 0);
+ break;
+ case 0xb1:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_TRUNC_F64_U, 0);
+ break;
+ case 0xb2:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I32_S, 0);
+ break;
+ case 0xb3:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I32_U, 0);
+ break;
+ case 0xb4:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I64_S, 0);
+ break;
+ case 0xb5:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_CONVERT_I64_U, 0);
+ break;
+ case 0xb6:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_DEMOTE_F64, 0);
+ break;
+ case 0xb7:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I32_S, 0);
+ break;
+ case 0xb8:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I32_U, 0);
+ break;
+ case 0xb9:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I64_S, 0);
+ break;
+ case 0xba:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_CONVERT_I64_U, 0);
+ break;
+ case 0xbb:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_PROMOTE_F32, 0);
+ break;
+ case 0xbc:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I32_REINTERPRET_F32, 0);
+ break;
+ case 0xbd:
+ wasm_func_add_insn(c, out, f, WASM_INSN_I64_REINTERPRET_F64, 0);
+ break;
+ case 0xbe:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F32_REINTERPRET_I32, 0);
+ break;
+ case 0xbf:
+ wasm_func_add_insn(c, out, f, WASM_INSN_F64_REINTERPRET_I64, 0);
+ break;
+ default:
+ wasm_error(c, wasm_loc(0, 0), "wasm: unsupported opcode 0x%02x",
+ op);
}
}
if (!saw_body_end)
@@ -3719,37 +3648,36 @@ static void wasm_decode_binary(CfreeCompiler *c, const CfreeBytesInput *input,
}
}
-static int wasm_is_binary(const CfreeBytesInput *input) {
+static int wasm_is_binary(const CfreeBytesInput* input) {
return input->len >= 4u && input->data[0] == 0x00 && input->data[1] == 0x61 &&
input->data[2] == 0x73 && input->data[3] == 0x6d;
}
-static CfreeCgTypeId wasm_cg_type(CfreeCompiler *c, CfreeCgBuiltinTypes b,
+static CfreeCgTypeId wasm_cg_type(CfreeCompiler* c, CfreeCgBuiltinTypes b,
WasmValType vt) {
switch (vt) {
- case WASM_VAL_I32:
- return b.id[CFREE_CG_BUILTIN_I32];
- case WASM_VAL_I64:
- return b.id[CFREE_CG_BUILTIN_I64];
- case WASM_VAL_F32:
- return b.id[CFREE_CG_BUILTIN_F32];
- case WASM_VAL_F64:
- return b.id[CFREE_CG_BUILTIN_F64];
- case WASM_VAL_FUNCREF:
- case WASM_VAL_EXTERNREF:
- break;
+ case WASM_VAL_I32:
+ return b.id[CFREE_CG_BUILTIN_I32];
+ case WASM_VAL_I64:
+ return b.id[CFREE_CG_BUILTIN_I64];
+ case WASM_VAL_F32:
+ return b.id[CFREE_CG_BUILTIN_F32];
+ case WASM_VAL_F64:
+ return b.id[CFREE_CG_BUILTIN_F64];
+ case WASM_VAL_FUNCREF:
+ case WASM_VAL_EXTERNREF:
+ break;
}
wasm_error(c, wasm_loc(0, 0), "wasm: unsupported value type");
return b.id[CFREE_CG_BUILTIN_I32];
}
-static WasmValType wasm_func_local_type(const WasmFunc *f, uint32_t index) {
- if (index < f->nparams)
- return f->params[index];
+static WasmValType wasm_func_local_type(const WasmFunc* f, uint32_t index) {
+ if (index < f->nparams) return f->params[index];
return f->locals[index - f->nparams];
}
-static CfreeCgMemAccess wasm_cg_mem(CfreeCompiler *c, CfreeCgBuiltinTypes b,
+static CfreeCgMemAccess wasm_cg_mem(CfreeCompiler* c, CfreeCgBuiltinTypes b,
WasmValType vt) {
CfreeCgMemAccess mem;
memset(&mem, 0, sizeof mem);
@@ -3764,7 +3692,7 @@ static CfreeCgMemAccess wasm_cg_mem_type(CfreeCgTypeId ty) {
return mem;
}
-static void wasm_cg_push_zero(CfreeCompiler *c, CfreeCg *cg,
+static void wasm_cg_push_zero(CfreeCompiler* c, CfreeCg* cg,
CfreeCgBuiltinTypes b, WasmValType vt) {
CfreeCgTypeId ty = wasm_cg_type(c, b, vt);
if (vt == WASM_VAL_F32 || vt == WASM_VAL_F64)
@@ -3776,93 +3704,132 @@ static void wasm_cg_push_zero(CfreeCompiler *c, CfreeCg *cg,
static CfreeCgTypeId wasm_load_storage_type(CfreeCgBuiltinTypes b,
uint8_t kind) {
switch (kind) {
- case WASM_INSN_I32_LOAD8_S:
- case WASM_INSN_I32_LOAD8_U:
- case WASM_INSN_I64_LOAD8_S:
- case WASM_INSN_I64_LOAD8_U:
- return b.id[CFREE_CG_BUILTIN_I8];
- case WASM_INSN_I32_LOAD16_S:
- case WASM_INSN_I32_LOAD16_U:
- case WASM_INSN_I64_LOAD16_S:
- case WASM_INSN_I64_LOAD16_U:
- return b.id[CFREE_CG_BUILTIN_I16];
- case WASM_INSN_I64_LOAD32_S:
- case WASM_INSN_I64_LOAD32_U:
- case WASM_INSN_I32_LOAD:
- return b.id[CFREE_CG_BUILTIN_I32];
- default:
- return b.id[CFREE_CG_BUILTIN_I64];
+ case WASM_INSN_I32_LOAD8_S:
+ case WASM_INSN_I32_LOAD8_U:
+ case WASM_INSN_I64_LOAD8_S:
+ case WASM_INSN_I64_LOAD8_U:
+ return b.id[CFREE_CG_BUILTIN_I8];
+ case WASM_INSN_I32_LOAD16_S:
+ case WASM_INSN_I32_LOAD16_U:
+ case WASM_INSN_I64_LOAD16_S:
+ case WASM_INSN_I64_LOAD16_U:
+ return b.id[CFREE_CG_BUILTIN_I16];
+ case WASM_INSN_I64_LOAD32_S:
+ case WASM_INSN_I64_LOAD32_U:
+ case WASM_INSN_I32_LOAD:
+ return b.id[CFREE_CG_BUILTIN_I32];
+ default:
+ return b.id[CFREE_CG_BUILTIN_I64];
}
}
static CfreeCgTypeId wasm_store_storage_type(CfreeCgBuiltinTypes b,
uint8_t kind) {
switch (kind) {
- case WASM_INSN_I32_STORE8:
- case WASM_INSN_I64_STORE8:
- return b.id[CFREE_CG_BUILTIN_I8];
- case WASM_INSN_I32_STORE16:
- case WASM_INSN_I64_STORE16:
- return b.id[CFREE_CG_BUILTIN_I16];
- case WASM_INSN_I64_STORE32:
- case WASM_INSN_I32_STORE:
- return b.id[CFREE_CG_BUILTIN_I32];
- default:
- return b.id[CFREE_CG_BUILTIN_I64];
+ case WASM_INSN_I32_STORE8:
+ case WASM_INSN_I64_STORE8:
+ return b.id[CFREE_CG_BUILTIN_I8];
+ case WASM_INSN_I32_STORE16:
+ case WASM_INSN_I64_STORE16:
+ return b.id[CFREE_CG_BUILTIN_I16];
+ case WASM_INSN_I64_STORE32:
+ case WASM_INSN_I32_STORE:
+ return b.id[CFREE_CG_BUILTIN_I32];
+ default:
+ return b.id[CFREE_CG_BUILTIN_I64];
}
}
static uint32_t wasm_mem_width(uint8_t kind) {
switch (kind) {
- case WASM_INSN_I32_LOAD8_S:
- case WASM_INSN_I32_LOAD8_U:
- case WASM_INSN_I64_LOAD8_S:
- case WASM_INSN_I64_LOAD8_U:
- case WASM_INSN_I32_STORE8:
- case WASM_INSN_I64_STORE8:
- return 1;
- case WASM_INSN_I32_LOAD16_S:
- case WASM_INSN_I32_LOAD16_U:
- case WASM_INSN_I64_LOAD16_S:
- case WASM_INSN_I64_LOAD16_U:
- case WASM_INSN_I32_STORE16:
- case WASM_INSN_I64_STORE16:
- return 2;
- case WASM_INSN_I32_LOAD:
- case WASM_INSN_I64_LOAD32_S:
- case WASM_INSN_I64_LOAD32_U:
- case WASM_INSN_I32_STORE:
- case WASM_INSN_I64_STORE32:
- return 4;
- default:
- return 8;
- }
-}
-
-static void wasm_cg_trap(CfreeCg *cg) {
+ case WASM_INSN_I32_LOAD8_S:
+ case WASM_INSN_I32_LOAD8_U:
+ case WASM_INSN_I64_LOAD8_S:
+ case WASM_INSN_I64_LOAD8_U:
+ case WASM_INSN_I32_STORE8:
+ case WASM_INSN_I64_STORE8:
+ return 1;
+ case WASM_INSN_I32_LOAD16_S:
+ case WASM_INSN_I32_LOAD16_U:
+ case WASM_INSN_I64_LOAD16_S:
+ case WASM_INSN_I64_LOAD16_U:
+ case WASM_INSN_I32_STORE16:
+ case WASM_INSN_I64_STORE16:
+ return 2;
+ case WASM_INSN_I32_LOAD:
+ case WASM_INSN_I64_LOAD32_S:
+ case WASM_INSN_I64_LOAD32_U:
+ case WASM_INSN_I32_STORE:
+ case WASM_INSN_I64_STORE32:
+ return 4;
+ default:
+ return 8;
+ }
+}
+
+static void wasm_cg_trap(CfreeCg* cg) {
cfree_cg_intrinsic(cg, CFREE_CG_INTRIN_TRAP, 0, CFREE_CG_TYPE_NONE);
cfree_cg_unreachable(cg);
}
+static void wasm_cg_trap_unreachable(CfreeCg* cg) { wasm_cg_trap(cg); }
+static void wasm_cg_trap_division(CfreeCg* cg) { wasm_cg_trap(cg); }
+static void wasm_cg_trap_bounds(CfreeCg* cg) { wasm_cg_trap(cg); }
+static void wasm_cg_trap_table(CfreeCg* cg) { wasm_cg_trap(cg); }
+static void wasm_cg_trap_signature(CfreeCg* cg) { wasm_cg_trap(cg); }
+
typedef struct WasmCgRuntime {
CfreeCgTypeId i8_ptr_ty;
+ CfreeCgTypeId void_ptr_ty;
CfreeCgTypeId memory_ty;
+ CfreeCgTypeId func_import_ty;
+ CfreeCgTypeId global_import_ty;
+ CfreeCgTypeId table_entry_ty;
+ CfreeCgTypeId table_entry_ptr_ty;
+ CfreeCgTypeId table_ty;
CfreeCgTypeId instance_ty;
CfreeCgTypeId instance_ptr_ty;
uint32_t memory_field;
uint32_t memory_data_field;
uint32_t memory_pages_field;
uint32_t memory_max_pages_field;
- uint32_t globals_field0;
+ uint32_t func_import_field[64];
+ uint32_t global_field[64];
+ uint32_t global_import_addr_field;
+ uint32_t table_field[64];
+ uint32_t table_entries_field[64];
+ uint32_t table_entry_fn_field;
+ uint32_t table_entry_typeidx_field;
+ uint32_t table_entries_ptr_field;
+ uint32_t table_len_field;
+ uint32_t table_max_field;
} WasmCgRuntime;
-static void wasm_cg_build_runtime(CfreeCompiler *c, CfreeCgBuiltinTypes b,
- const WasmModule *m, WasmCgRuntime *rt) {
+static void wasm_indexed_name(char* name, size_t cap, const char* prefix,
+ uint32_t index) {
+ size_t pos = 0;
+ uint32_t n = index, div = 1000000000u;
+ while (*prefix && pos + 1u < cap) name[pos++] = *prefix++;
+ while (div > 1u && n / div == 0) div /= 10u;
+ while (div && pos + 1u < cap) {
+ name[pos++] = (char)('0' + (n / div) % 10u);
+ div /= 10u;
+ }
+ name[pos] = '\0';
+}
+
+static void wasm_cg_build_runtime(CfreeCompiler* c, CfreeCgBuiltinTypes b,
+ const WasmModule* m, WasmCgRuntime* rt) {
CfreeCgField memory_fields[3];
- CfreeCgField instance_fields[65];
+ CfreeCgField func_import_fields[1];
+ CfreeCgField global_import_fields[1];
+ CfreeCgField table_entry_fields[2];
+ CfreeCgField table_fields[3];
+ CfreeCgField instance_fields[256];
uint32_t nfields = 0;
memset(rt, 0, sizeof *rt);
rt->i8_ptr_ty = cfree_cg_type_ptr(c, b.id[CFREE_CG_BUILTIN_I8], 0);
+ rt->void_ptr_ty = rt->i8_ptr_ty;
memset(memory_fields, 0, sizeof memory_fields);
memory_fields[0].name = cfree_sym_intern(c, "data");
memory_fields[0].type = rt->i8_ptr_ty;
@@ -3876,29 +3843,83 @@ static void wasm_cg_build_runtime(CfreeCompiler *c, CfreeCgBuiltinTypes b,
rt->memory_data_field = 0;
rt->memory_pages_field = 1;
rt->memory_max_pages_field = 2;
+ memset(func_import_fields, 0, sizeof func_import_fields);
+ func_import_fields[0].name = cfree_sym_intern(c, "fn");
+ func_import_fields[0].type = rt->void_ptr_ty;
+ rt->func_import_ty = cfree_cg_type_record(
+ c, cfree_sym_intern(c, "CfreeWasmFuncImport"), func_import_fields, 1);
+ memset(global_import_fields, 0, sizeof global_import_fields);
+ global_import_fields[0].name = cfree_sym_intern(c, "addr");
+ global_import_fields[0].type = rt->void_ptr_ty;
+ rt->global_import_ty = cfree_cg_type_record(
+ c, cfree_sym_intern(c, "CfreeWasmGlobalImport"), global_import_fields, 1);
+ memset(table_entry_fields, 0, sizeof table_entry_fields);
+ table_entry_fields[0].name = cfree_sym_intern(c, "fn");
+ table_entry_fields[0].type = rt->void_ptr_ty;
+ table_entry_fields[1].name = cfree_sym_intern(c, "typeidx");
+ table_entry_fields[1].type = b.id[CFREE_CG_BUILTIN_I32];
+ rt->table_entry_ty = cfree_cg_type_record(
+ c, cfree_sym_intern(c, "CfreeWasmTableEntry"), table_entry_fields, 2);
+ rt->table_entry_ptr_ty = cfree_cg_type_ptr(c, rt->table_entry_ty, 0);
+ rt->table_entry_fn_field = 0;
+ rt->table_entry_typeidx_field = 1;
+ memset(table_fields, 0, sizeof table_fields);
+ table_fields[0].name = cfree_sym_intern(c, "entries");
+ table_fields[0].type = rt->table_entry_ptr_ty;
+ table_fields[1].name = cfree_sym_intern(c, "len");
+ table_fields[1].type = b.id[CFREE_CG_BUILTIN_I32];
+ table_fields[2].name = cfree_sym_intern(c, "max");
+ table_fields[2].type = b.id[CFREE_CG_BUILTIN_I32];
+ rt->table_ty = cfree_cg_type_record(c, cfree_sym_intern(c, "CfreeWasmTable"),
+ table_fields, 3);
+ rt->table_entries_ptr_field = 0;
+ rt->table_len_field = 1;
+ rt->table_max_field = 2;
memset(instance_fields, 0, sizeof instance_fields);
- if (m->has_memory) {
- instance_fields[nfields].name = cfree_sym_intern(c, "memory");
- instance_fields[nfields].type = rt->memory_ty;
+ instance_fields[nfields].name = cfree_sym_intern(c, "memory");
+ instance_fields[nfields].type = rt->memory_ty;
+ nfields++;
+ for (uint32_t i = 0; i < m->nfuncs; ++i) {
+ char name[40];
+ if (!m->funcs[i].is_import) continue;
+ if (nfields >= 256u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: instance layout too large");
+ wasm_indexed_name(name, sizeof name, "import_func_", i);
+ rt->func_import_field[i] = nfields;
+ instance_fields[nfields].name = cfree_sym_intern(c, name);
+ instance_fields[nfields].type = rt->func_import_ty;
nfields++;
}
- rt->globals_field0 = nfields;
for (uint32_t i = 0; i < m->nglobals; ++i) {
char name[32];
- size_t pos = 0;
- uint32_t n = i, div = 1000000000u;
- const char prefix[] = "global_";
- memcpy(name, prefix, sizeof(prefix) - 1u);
- pos = sizeof(prefix) - 1u;
- while (div > 1u && n / div == 0)
- div /= 10u;
- while (div) {
- name[pos++] = (char)('0' + (n / div) % 10u);
- div /= 10u;
- }
- name[pos] = '\0';
+ if (nfields >= 256u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: instance layout too large");
+ wasm_indexed_name(name, sizeof name,
+ m->globals[i].is_import ? "import_global_" : "global_",
+ i);
+ rt->global_field[i] = nfields;
instance_fields[nfields].name = cfree_sym_intern(c, name);
- instance_fields[nfields].type = wasm_cg_type(c, b, m->globals[i].type);
+ instance_fields[nfields].type =
+ m->globals[i].is_import ? rt->global_import_ty
+ : wasm_cg_type(c, b, m->globals[i].type);
+ nfields++;
+ }
+ rt->global_import_addr_field = 0;
+ for (uint32_t i = 0; i < m->ntables; ++i) {
+ char name[40];
+ uint32_t max = m->tables[i].has_max ? m->tables[i].max : m->tables[i].min;
+ if (nfields + 2u > 256u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: instance layout too large");
+ wasm_indexed_name(name, sizeof name, "table_", i);
+ rt->table_field[i] = nfields;
+ instance_fields[nfields].name = cfree_sym_intern(c, name);
+ instance_fields[nfields].type = rt->table_ty;
+ nfields++;
+ wasm_indexed_name(name, sizeof name, "table_entries_", i);
+ rt->table_entries_field[i] = nfields;
+ instance_fields[nfields].name = cfree_sym_intern(c, name);
+ instance_fields[nfields].type =
+ cfree_cg_type_array(c, rt->table_entry_ty, max ? max : 1u);
nfields++;
}
rt->instance_ty = cfree_cg_type_record(
@@ -3906,58 +3927,129 @@ static void wasm_cg_build_runtime(CfreeCompiler *c, CfreeCgBuiltinTypes b,
rt->instance_ptr_ty = cfree_cg_type_ptr(c, rt->instance_ty, 0);
}
-static void wasm_cg_push_instance_lvalue(CfreeCg *cg, const WasmCgRuntime *rt,
+static void wasm_cg_push_instance_lvalue(CfreeCg* cg, const WasmCgRuntime* rt,
CfreeCgLocal instance_local) {
cfree_cg_push_local(cg, instance_local);
cfree_cg_load(cg, wasm_cg_mem_type(rt->instance_ptr_ty));
cfree_cg_indirect(cg);
}
-static void wasm_cg_push_memory_lvalue(CfreeCg *cg, const WasmCgRuntime *rt,
+static void wasm_cg_push_memory_lvalue(CfreeCg* cg, const WasmCgRuntime* rt,
CfreeCgLocal instance_local) {
wasm_cg_push_instance_lvalue(cg, rt, instance_local);
cfree_cg_field(cg, rt->memory_field);
}
-static void wasm_cg_push_memory_data_ptr(CfreeCg *cg, const WasmCgRuntime *rt,
+static void wasm_cg_push_memory_data_ptr(CfreeCg* cg, const WasmCgRuntime* rt,
CfreeCgLocal instance_local) {
wasm_cg_push_memory_lvalue(cg, rt, instance_local);
cfree_cg_field(cg, rt->memory_data_field);
cfree_cg_load(cg, wasm_cg_mem_type(rt->i8_ptr_ty));
}
-static void wasm_cg_push_memory_pages_lvalue(CfreeCg *cg,
- const WasmCgRuntime *rt,
+static void wasm_cg_push_memory_pages_lvalue(CfreeCg* cg,
+ const WasmCgRuntime* rt,
CfreeCgLocal instance_local) {
wasm_cg_push_memory_lvalue(cg, rt, instance_local);
cfree_cg_field(cg, rt->memory_pages_field);
}
-static void wasm_cg_push_memory_max_lvalue(CfreeCg *cg, const WasmCgRuntime *rt,
+static void wasm_cg_push_memory_max_lvalue(CfreeCg* cg, const WasmCgRuntime* rt,
CfreeCgLocal instance_local) {
wasm_cg_push_memory_lvalue(cg, rt, instance_local);
cfree_cg_field(cg, rt->memory_max_pages_field);
}
-static void wasm_cg_push_global_lvalue(CfreeCg *cg, const WasmCgRuntime *rt,
+static void wasm_cg_push_global_lvalue(CfreeCg* cg, const WasmCgRuntime* rt,
CfreeCgLocal instance_local,
uint32_t global_index) {
wasm_cg_push_instance_lvalue(cg, rt, instance_local);
- cfree_cg_field(cg, rt->globals_field0 + global_index);
+ cfree_cg_field(cg, rt->global_field[global_index]);
+}
+
+static void wasm_cg_push_import_func_lvalue(CfreeCg* cg,
+ const WasmCgRuntime* rt,
+ CfreeCgLocal instance_local,
+ uint32_t func_index) {
+ wasm_cg_push_instance_lvalue(cg, rt, instance_local);
+ cfree_cg_field(cg, rt->func_import_field[func_index]);
+}
+
+static void wasm_cg_push_import_func_ptr(CfreeCg* cg, const WasmCgRuntime* rt,
+ CfreeCgLocal instance_local,
+ uint32_t func_index) {
+ wasm_cg_push_import_func_lvalue(cg, rt, instance_local, func_index);
+ cfree_cg_field(cg, 0);
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
+}
+
+static void wasm_cg_push_global_value_lvalue(CfreeCompiler* c, CfreeCg* cg,
+ CfreeCgBuiltinTypes b,
+ const WasmCgRuntime* rt,
+ CfreeCgLocal instance_local,
+ const WasmModule* m,
+ uint32_t global_index) {
+ wasm_cg_push_global_lvalue(cg, rt, instance_local, global_index);
+ if (m->globals[global_index].is_import) {
+ CfreeCgTypeId ptr_ty = cfree_cg_type_ptr(
+ c, wasm_cg_type(c, b, m->globals[global_index].type), 0);
+ cfree_cg_field(cg, rt->global_import_addr_field);
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
+ cfree_cg_dup(cg);
+ cfree_cg_push_null(cg, rt->void_ptr_ty);
+ cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
+ {
+ CfreeCgLabel ok = cfree_cg_label_new(cg);
+ cfree_cg_branch_true(cg, ok);
+ wasm_cg_trap_table(cg);
+ cfree_cg_label_place(cg, ok);
+ }
+ cfree_cg_bitcast(cg, ptr_ty);
+ cfree_cg_indirect(cg);
+ }
+}
+
+static void wasm_cg_push_table_lvalue(CfreeCg* cg, const WasmCgRuntime* rt,
+ CfreeCgLocal instance_local,
+ uint32_t table_index) {
+ wasm_cg_push_instance_lvalue(cg, rt, instance_local);
+ cfree_cg_field(cg, rt->table_field[table_index]);
}
-static void wasm_cg_memory_check(CfreeCompiler *c, CfreeCg *cg,
- CfreeCgBuiltinTypes b, const WasmModule *m,
- const WasmCgRuntime *rt,
+static void wasm_cg_push_table_entries_array_lvalue(CfreeCg* cg,
+ const WasmCgRuntime* rt,
+ CfreeCgLocal instance_local,
+ uint32_t table_index) {
+ wasm_cg_push_instance_lvalue(cg, rt, instance_local);
+ cfree_cg_field(cg, rt->table_entries_field[table_index]);
+}
+
+static void wasm_cg_push_table_entry_lvalue(CfreeCg* cg,
+ const WasmCgRuntime* rt,
+ CfreeCgLocal instance_local,
+ uint32_t table_index,
+ CfreeCgLocal index_local,
+ CfreeCgMemAccess index_mem) {
+ wasm_cg_push_table_lvalue(cg, rt, instance_local, table_index);
+ cfree_cg_field(cg, rt->table_entries_ptr_field);
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->table_entry_ptr_ty));
+ cfree_cg_push_local(cg, index_local);
+ cfree_cg_load(cg, index_mem);
+ cfree_cg_index(cg, 0);
+}
+
+static void wasm_cg_memory_check(CfreeCompiler* c, CfreeCg* cg,
+ CfreeCgBuiltinTypes b, const WasmModule* m,
+ const WasmCgRuntime* rt,
CfreeCgLocal instance_local,
- const WasmInsn *in) {
+ const WasmInsn* in) {
uint32_t width = wasm_mem_width(in->kind);
uint64_t end = (uint64_t)(uint32_t)in->imm + width;
CfreeCgLabel ok = cfree_cg_label_new(cg);
uint32_t max_pages =
m->memory.has_max ? m->memory.max_pages : m->memory.min_pages;
if (end > (uint64_t)max_pages * 65536u) {
- wasm_cg_trap(cg);
+ wasm_cg_trap_bounds(cg);
return;
}
(void)c;
@@ -3970,11 +4062,11 @@ static void wasm_cg_memory_check(CfreeCompiler *c, CfreeCg *cg,
cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
cfree_cg_int_cmp(cg, CFREE_CG_INT_LE_U);
cfree_cg_branch_true(cg, ok);
- wasm_cg_trap(cg);
+ wasm_cg_trap_bounds(cg);
cfree_cg_label_place(cg, ok);
}
-static void wasm_cg_memory_lvalue(CfreeCg *cg, const WasmCgRuntime *rt,
+static void wasm_cg_memory_lvalue(CfreeCg* cg, const WasmCgRuntime* rt,
CfreeCgLocal instance_local,
uint32_t offset) {
wasm_cg_push_memory_data_ptr(cg, rt, instance_local);
@@ -3982,7 +4074,7 @@ static void wasm_cg_memory_lvalue(CfreeCg *cg, const WasmCgRuntime *rt,
cfree_cg_index(cg, offset);
}
-static void wasm_cg_rotate(CfreeCompiler *c, CfreeCg *cg, CfreeCgBuiltinTypes b,
+static void wasm_cg_rotate(CfreeCompiler* c, CfreeCg* cg, CfreeCgBuiltinTypes b,
WasmValType vt, int right) {
CfreeCgTypeId ty = wasm_cg_type(c, b, vt);
CfreeCgMemAccess mem = wasm_cg_mem(c, b, vt);
@@ -4020,7 +4112,7 @@ static void wasm_cg_rotate(CfreeCompiler *c, CfreeCg *cg, CfreeCgBuiltinTypes b,
cfree_cg_int_binop(cg, CFREE_CG_INT_OR, 0);
}
-static void wasm_cg_checked_divrem(CfreeCompiler *c, CfreeCg *cg,
+static void wasm_cg_checked_divrem(CfreeCompiler* c, CfreeCg* cg,
CfreeCgBuiltinTypes b, WasmValType vt,
CfreeCgIntBinOp op) {
CfreeCgTypeId ty = wasm_cg_type(c, b, vt);
@@ -4043,7 +4135,7 @@ static void wasm_cg_checked_divrem(CfreeCompiler *c, CfreeCg *cg,
cfree_cg_push_int(cg, 0, ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
cfree_cg_branch_true(cg, ok);
- wasm_cg_trap(cg);
+ wasm_cg_trap_division(cg);
cfree_cg_label_place(cg, ok);
if (op == CFREE_CG_INT_SDIV) {
CfreeCgLabel no_overflow = cfree_cg_label_new(cg);
@@ -4059,7 +4151,7 @@ static void wasm_cg_checked_divrem(CfreeCompiler *c, CfreeCg *cg,
cfree_cg_push_int(cg, UINT64_MAX, ty);
cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
cfree_cg_branch_true(cg, no_overflow);
- wasm_cg_trap(cg);
+ wasm_cg_trap_division(cg);
cfree_cg_label_place(cg, no_overflow);
}
cfree_cg_push_local(cg, lhs);
@@ -4069,135 +4161,135 @@ static void wasm_cg_checked_divrem(CfreeCompiler *c, CfreeCg *cg,
cfree_cg_int_binop(cg, op, 0);
}
-static int wasm_int_cmp_op(uint8_t kind, CfreeCgIntCmpOp *out) {
+static int wasm_int_cmp_op(uint8_t kind, CfreeCgIntCmpOp* out) {
switch (kind) {
- case WASM_INSN_I32_EQ:
- case WASM_INSN_I64_EQ:
- *out = CFREE_CG_INT_EQ;
- return 1;
- case WASM_INSN_I32_NE:
- case WASM_INSN_I64_NE:
- *out = CFREE_CG_INT_NE;
- return 1;
- case WASM_INSN_I32_LT_S:
- case WASM_INSN_I64_LT_S:
- *out = CFREE_CG_INT_LT_S;
- return 1;
- case WASM_INSN_I32_LT_U:
- case WASM_INSN_I64_LT_U:
- *out = CFREE_CG_INT_LT_U;
- return 1;
- case WASM_INSN_I32_GT_S:
- case WASM_INSN_I64_GT_S:
- *out = CFREE_CG_INT_GT_S;
- return 1;
- case WASM_INSN_I32_GT_U:
- case WASM_INSN_I64_GT_U:
- *out = CFREE_CG_INT_GT_U;
- return 1;
- case WASM_INSN_I32_LE_S:
- case WASM_INSN_I64_LE_S:
- *out = CFREE_CG_INT_LE_S;
- return 1;
- case WASM_INSN_I32_LE_U:
- case WASM_INSN_I64_LE_U:
- *out = CFREE_CG_INT_LE_U;
- return 1;
- case WASM_INSN_I32_GE_S:
- case WASM_INSN_I64_GE_S:
- *out = CFREE_CG_INT_GE_S;
- return 1;
- case WASM_INSN_I32_GE_U:
- case WASM_INSN_I64_GE_U:
- *out = CFREE_CG_INT_GE_U;
- return 1;
- default:
- return 0;
+ case WASM_INSN_I32_EQ:
+ case WASM_INSN_I64_EQ:
+ *out = CFREE_CG_INT_EQ;
+ return 1;
+ case WASM_INSN_I32_NE:
+ case WASM_INSN_I64_NE:
+ *out = CFREE_CG_INT_NE;
+ return 1;
+ case WASM_INSN_I32_LT_S:
+ case WASM_INSN_I64_LT_S:
+ *out = CFREE_CG_INT_LT_S;
+ return 1;
+ case WASM_INSN_I32_LT_U:
+ case WASM_INSN_I64_LT_U:
+ *out = CFREE_CG_INT_LT_U;
+ return 1;
+ case WASM_INSN_I32_GT_S:
+ case WASM_INSN_I64_GT_S:
+ *out = CFREE_CG_INT_GT_S;
+ return 1;
+ case WASM_INSN_I32_GT_U:
+ case WASM_INSN_I64_GT_U:
+ *out = CFREE_CG_INT_GT_U;
+ return 1;
+ case WASM_INSN_I32_LE_S:
+ case WASM_INSN_I64_LE_S:
+ *out = CFREE_CG_INT_LE_S;
+ return 1;
+ case WASM_INSN_I32_LE_U:
+ case WASM_INSN_I64_LE_U:
+ *out = CFREE_CG_INT_LE_U;
+ return 1;
+ case WASM_INSN_I32_GE_S:
+ case WASM_INSN_I64_GE_S:
+ *out = CFREE_CG_INT_GE_S;
+ return 1;
+ case WASM_INSN_I32_GE_U:
+ case WASM_INSN_I64_GE_U:
+ *out = CFREE_CG_INT_GE_U;
+ return 1;
+ default:
+ return 0;
}
}
-static int wasm_fp_binop(uint8_t kind, CfreeCgFpBinOp *out) {
+static int wasm_fp_binop(uint8_t kind, CfreeCgFpBinOp* out) {
switch (kind) {
- case WASM_INSN_F32_ADD:
- case WASM_INSN_F64_ADD:
- *out = CFREE_CG_FP_ADD;
- return 1;
- case WASM_INSN_F32_SUB:
- case WASM_INSN_F64_SUB:
- *out = CFREE_CG_FP_SUB;
- return 1;
- case WASM_INSN_F32_MUL:
- case WASM_INSN_F64_MUL:
- *out = CFREE_CG_FP_MUL;
- return 1;
- case WASM_INSN_F32_DIV:
- case WASM_INSN_F64_DIV:
- *out = CFREE_CG_FP_DIV;
- return 1;
- default:
- return 0;
+ case WASM_INSN_F32_ADD:
+ case WASM_INSN_F64_ADD:
+ *out = CFREE_CG_FP_ADD;
+ return 1;
+ case WASM_INSN_F32_SUB:
+ case WASM_INSN_F64_SUB:
+ *out = CFREE_CG_FP_SUB;
+ return 1;
+ case WASM_INSN_F32_MUL:
+ case WASM_INSN_F64_MUL:
+ *out = CFREE_CG_FP_MUL;
+ return 1;
+ case WASM_INSN_F32_DIV:
+ case WASM_INSN_F64_DIV:
+ *out = CFREE_CG_FP_DIV;
+ return 1;
+ default:
+ return 0;
}
}
-static int wasm_fp_cmp_op(uint8_t kind, CfreeCgFpCmpOp *out) {
+static int wasm_fp_cmp_op(uint8_t kind, CfreeCgFpCmpOp* out) {
switch (kind) {
- case WASM_INSN_F32_EQ:
- case WASM_INSN_F64_EQ:
- *out = CFREE_CG_FP_OEQ;
- return 1;
- case WASM_INSN_F32_NE:
- case WASM_INSN_F64_NE:
- *out = CFREE_CG_FP_ONE;
- return 1;
- case WASM_INSN_F32_LT:
- case WASM_INSN_F64_LT:
- *out = CFREE_CG_FP_OLT;
- return 1;
- case WASM_INSN_F32_GT:
- case WASM_INSN_F64_GT:
- *out = CFREE_CG_FP_OGT;
- return 1;
- case WASM_INSN_F32_LE:
- case WASM_INSN_F64_LE:
- *out = CFREE_CG_FP_OLE;
- return 1;
- case WASM_INSN_F32_GE:
- case WASM_INSN_F64_GE:
- *out = CFREE_CG_FP_OGE;
- return 1;
- default:
- return 0;
+ case WASM_INSN_F32_EQ:
+ case WASM_INSN_F64_EQ:
+ *out = CFREE_CG_FP_OEQ;
+ return 1;
+ case WASM_INSN_F32_NE:
+ case WASM_INSN_F64_NE:
+ *out = CFREE_CG_FP_ONE;
+ return 1;
+ case WASM_INSN_F32_LT:
+ case WASM_INSN_F64_LT:
+ *out = CFREE_CG_FP_OLT;
+ return 1;
+ case WASM_INSN_F32_GT:
+ case WASM_INSN_F64_GT:
+ *out = CFREE_CG_FP_OGT;
+ return 1;
+ case WASM_INSN_F32_LE:
+ case WASM_INSN_F64_LE:
+ *out = CFREE_CG_FP_OLE;
+ return 1;
+ case WASM_INSN_F32_GE:
+ case WASM_INSN_F64_GE:
+ *out = CFREE_CG_FP_OGE;
+ return 1;
+ default:
+ return 0;
}
}
static WasmValType wasm_load_result_type(uint8_t kind) {
switch (kind) {
- case WASM_INSN_I64_LOAD:
- case WASM_INSN_I64_LOAD8_S:
- case WASM_INSN_I64_LOAD8_U:
- case WASM_INSN_I64_LOAD16_S:
- case WASM_INSN_I64_LOAD16_U:
- case WASM_INSN_I64_LOAD32_S:
- case WASM_INSN_I64_LOAD32_U:
- return WASM_VAL_I64;
- default:
- return WASM_VAL_I32;
+ case WASM_INSN_I64_LOAD:
+ case WASM_INSN_I64_LOAD8_S:
+ case WASM_INSN_I64_LOAD8_U:
+ case WASM_INSN_I64_LOAD16_S:
+ case WASM_INSN_I64_LOAD16_U:
+ case WASM_INSN_I64_LOAD32_S:
+ case WASM_INSN_I64_LOAD32_U:
+ return WASM_VAL_I64;
+ default:
+ return WASM_VAL_I32;
}
}
static WasmValType wasm_store_value_type(uint8_t kind) {
switch (kind) {
- case WASM_INSN_I64_STORE:
- case WASM_INSN_I64_STORE8:
- case WASM_INSN_I64_STORE16:
- case WASM_INSN_I64_STORE32:
- return WASM_VAL_I64;
- default:
- return WASM_VAL_I32;
+ case WASM_INSN_I64_STORE:
+ case WASM_INSN_I64_STORE8:
+ case WASM_INSN_I64_STORE16:
+ case WASM_INSN_I64_STORE32:
+ return WASM_VAL_I64;
+ default:
+ return WASM_VAL_I32;
}
}
-static int wasm_int_unop_kind(uint8_t kind, WasmValType *vt) {
+static int wasm_int_unop_kind(uint8_t kind, WasmValType* vt) {
if (kind == WASM_INSN_I32_CLZ || kind == WASM_INSN_I32_CTZ ||
kind == WASM_INSN_I32_POPCNT) {
*vt = WASM_VAL_I32;
@@ -4211,7 +4303,7 @@ static int wasm_int_unop_kind(uint8_t kind, WasmValType *vt) {
return 0;
}
-static int wasm_fp_binop_kind(uint8_t kind, WasmValType *vt) {
+static int wasm_fp_binop_kind(uint8_t kind, WasmValType* vt) {
if (kind == WASM_INSN_F32_ADD || kind == WASM_INSN_F32_SUB ||
kind == WASM_INSN_F32_MUL || kind == WASM_INSN_F32_DIV) {
*vt = WASM_VAL_F32;
@@ -4225,7 +4317,7 @@ static int wasm_fp_binop_kind(uint8_t kind, WasmValType *vt) {
return 0;
}
-static int wasm_fp_cmp_kind(uint8_t kind, WasmValType *vt) {
+static int wasm_fp_cmp_kind(uint8_t kind, WasmValType* vt) {
if (kind == WASM_INSN_F32_EQ || kind == WASM_INSN_F32_NE ||
kind == WASM_INSN_F32_LT || kind == WASM_INSN_F32_GT ||
kind == WASM_INSN_F32_LE || kind == WASM_INSN_F32_GE) {
@@ -4241,84 +4333,84 @@ static int wasm_fp_cmp_kind(uint8_t kind, WasmValType *vt) {
return 0;
}
-static int wasm_conversion_kind(uint8_t kind, WasmValType *src,
- WasmValType *dst) {
+static int wasm_conversion_kind(uint8_t kind, WasmValType* src,
+ WasmValType* dst) {
switch (kind) {
- case WASM_INSN_I32_WRAP_I64:
- *src = WASM_VAL_I64;
- *dst = WASM_VAL_I32;
- return 1;
- case WASM_INSN_I64_EXTEND_I32_S:
- case WASM_INSN_I64_EXTEND_I32_U:
- *src = WASM_VAL_I32;
- *dst = WASM_VAL_I64;
- return 1;
- case WASM_INSN_I32_TRUNC_F32_S:
- case WASM_INSN_I32_TRUNC_F32_U:
- *src = WASM_VAL_F32;
- *dst = WASM_VAL_I32;
- return 1;
- case WASM_INSN_I32_TRUNC_F64_S:
- case WASM_INSN_I32_TRUNC_F64_U:
- *src = WASM_VAL_F64;
- *dst = WASM_VAL_I32;
- return 1;
- case WASM_INSN_I64_TRUNC_F32_S:
- case WASM_INSN_I64_TRUNC_F32_U:
- *src = WASM_VAL_F32;
- *dst = WASM_VAL_I64;
- return 1;
- case WASM_INSN_I64_TRUNC_F64_S:
- case WASM_INSN_I64_TRUNC_F64_U:
- *src = WASM_VAL_F64;
- *dst = WASM_VAL_I64;
- return 1;
- case WASM_INSN_F32_CONVERT_I32_S:
- case WASM_INSN_F32_CONVERT_I32_U:
- *src = WASM_VAL_I32;
- *dst = WASM_VAL_F32;
- return 1;
- case WASM_INSN_F32_CONVERT_I64_S:
- case WASM_INSN_F32_CONVERT_I64_U:
- *src = WASM_VAL_I64;
- *dst = WASM_VAL_F32;
- return 1;
- case WASM_INSN_F64_CONVERT_I32_S:
- case WASM_INSN_F64_CONVERT_I32_U:
- *src = WASM_VAL_I32;
- *dst = WASM_VAL_F64;
- return 1;
- case WASM_INSN_F64_CONVERT_I64_S:
- case WASM_INSN_F64_CONVERT_I64_U:
- *src = WASM_VAL_I64;
- *dst = WASM_VAL_F64;
- return 1;
- case WASM_INSN_F32_DEMOTE_F64:
- *src = WASM_VAL_F64;
- *dst = WASM_VAL_F32;
- return 1;
- case WASM_INSN_F64_PROMOTE_F32:
- *src = WASM_VAL_F32;
- *dst = WASM_VAL_F64;
- return 1;
- case WASM_INSN_I32_REINTERPRET_F32:
- *src = WASM_VAL_F32;
- *dst = WASM_VAL_I32;
- return 1;
- case WASM_INSN_I64_REINTERPRET_F64:
- *src = WASM_VAL_F64;
- *dst = WASM_VAL_I64;
- return 1;
- case WASM_INSN_F32_REINTERPRET_I32:
- *src = WASM_VAL_I32;
- *dst = WASM_VAL_F32;
- return 1;
- case WASM_INSN_F64_REINTERPRET_I64:
- *src = WASM_VAL_I64;
- *dst = WASM_VAL_F64;
- return 1;
- default:
- return 0;
+ case WASM_INSN_I32_WRAP_I64:
+ *src = WASM_VAL_I64;
+ *dst = WASM_VAL_I32;
+ return 1;
+ case WASM_INSN_I64_EXTEND_I32_S:
+ case WASM_INSN_I64_EXTEND_I32_U:
+ *src = WASM_VAL_I32;
+ *dst = WASM_VAL_I64;
+ return 1;
+ case WASM_INSN_I32_TRUNC_F32_S:
+ case WASM_INSN_I32_TRUNC_F32_U:
+ *src = WASM_VAL_F32;
+ *dst = WASM_VAL_I32;
+ return 1;
+ case WASM_INSN_I32_TRUNC_F64_S:
+ case WASM_INSN_I32_TRUNC_F64_U:
+ *src = WASM_VAL_F64;
+ *dst = WASM_VAL_I32;
+ return 1;
+ case WASM_INSN_I64_TRUNC_F32_S:
+ case WASM_INSN_I64_TRUNC_F32_U:
+ *src = WASM_VAL_F32;
+ *dst = WASM_VAL_I64;
+ return 1;
+ case WASM_INSN_I64_TRUNC_F64_S:
+ case WASM_INSN_I64_TRUNC_F64_U:
+ *src = WASM_VAL_F64;
+ *dst = WASM_VAL_I64;
+ return 1;
+ case WASM_INSN_F32_CONVERT_I32_S:
+ case WASM_INSN_F32_CONVERT_I32_U:
+ *src = WASM_VAL_I32;
+ *dst = WASM_VAL_F32;
+ return 1;
+ case WASM_INSN_F32_CONVERT_I64_S:
+ case WASM_INSN_F32_CONVERT_I64_U:
+ *src = WASM_VAL_I64;
+ *dst = WASM_VAL_F32;
+ return 1;
+ case WASM_INSN_F64_CONVERT_I32_S:
+ case WASM_INSN_F64_CONVERT_I32_U:
+ *src = WASM_VAL_I32;
+ *dst = WASM_VAL_F64;
+ return 1;
+ case WASM_INSN_F64_CONVERT_I64_S:
+ case WASM_INSN_F64_CONVERT_I64_U:
+ *src = WASM_VAL_I64;
+ *dst = WASM_VAL_F64;
+ return 1;
+ case WASM_INSN_F32_DEMOTE_F64:
+ *src = WASM_VAL_F64;
+ *dst = WASM_VAL_F32;
+ return 1;
+ case WASM_INSN_F64_PROMOTE_F32:
+ *src = WASM_VAL_F32;
+ *dst = WASM_VAL_F64;
+ return 1;
+ case WASM_INSN_I32_REINTERPRET_F32:
+ *src = WASM_VAL_F32;
+ *dst = WASM_VAL_I32;
+ return 1;
+ case WASM_INSN_I64_REINTERPRET_F64:
+ *src = WASM_VAL_F64;
+ *dst = WASM_VAL_I64;
+ return 1;
+ case WASM_INSN_F32_REINTERPRET_I32:
+ *src = WASM_VAL_I32;
+ *dst = WASM_VAL_F32;
+ return 1;
+ case WASM_INSN_F64_REINTERPRET_I64:
+ *src = WASM_VAL_I64;
+ *dst = WASM_VAL_F64;
+ return 1;
+ default:
+ return 0;
}
}
@@ -4334,34 +4426,33 @@ typedef struct WasmControlFrame {
int unreachable;
} WasmControlFrame;
-static WasmValType wasm_global_init_type(const WasmInsn *in) {
+static WasmValType wasm_global_init_type(const WasmInsn* in) {
switch (in->kind) {
- case WASM_INSN_I32_CONST:
- return WASM_VAL_I32;
- case WASM_INSN_I64_CONST:
- return WASM_VAL_I64;
- case WASM_INSN_F32_CONST:
- return WASM_VAL_F32;
- case WASM_INSN_F64_CONST:
- return WASM_VAL_F64;
- default:
- return 0;
+ case WASM_INSN_I32_CONST:
+ return WASM_VAL_I32;
+ case WASM_INSN_I64_CONST:
+ return WASM_VAL_I64;
+ case WASM_INSN_F32_CONST:
+ return WASM_VAL_F32;
+ case WASM_INSN_F64_CONST:
+ return WASM_VAL_F64;
+ default:
+ return 0;
}
}
-static void wasm_stack_push(CfreeCompiler *c, WasmValStack *s, WasmValType vt) {
+static void wasm_stack_push(CfreeCompiler* c, WasmValStack* s, WasmValType vt) {
if (s->depth >= 256u)
wasm_error(c, wasm_loc(0, 0), "wasm: operand stack too deep");
s->vals[s->depth++] = vt;
}
-static int wasm_stack_pop(CfreeCompiler *c, WasmValStack *s,
- WasmControlFrame *frames, uint32_t nframes,
- WasmValType expected, const char *what) {
- WasmControlFrame *top = &frames[nframes - 1u];
+static int wasm_stack_pop(CfreeCompiler* c, WasmValStack* s,
+ WasmControlFrame* frames, uint32_t nframes,
+ WasmValType expected, const char* what) {
+ WasmControlFrame* top = &frames[nframes - 1u];
if (s->depth <= top->height) {
- if (top->unreachable)
- return 1;
+ if (top->unreachable) return 1;
wasm_error(c, wasm_loc(0, 0), "wasm: operand stack underflow");
}
if (expected && s->vals[s->depth - 1u] != expected)
@@ -4370,14 +4461,14 @@ static int wasm_stack_pop(CfreeCompiler *c, WasmValStack *s,
return 1;
}
-static void wasm_mark_unreachable(WasmValStack *s, WasmControlFrame *frames,
+static void wasm_mark_unreachable(WasmValStack* s, WasmControlFrame* frames,
uint32_t nframes) {
- WasmControlFrame *top = &frames[nframes - 1u];
+ WasmControlFrame* top = &frames[nframes - 1u];
s->depth = top->height;
top->unreachable = 1;
}
-static void wasm_validate(WasmModule *m, CfreeCompiler *c) {
+static void wasm_validate(WasmModule* m, CfreeCompiler* c) {
uint32_t i, j;
for (i = 0; i < m->ntypes; ++i) {
for (j = 0; j < m->types[i].nparams; ++j)
@@ -4398,14 +4489,14 @@ static void wasm_validate(WasmModule *m, CfreeCompiler *c) {
wasm_error(c, wasm_loc(0, 0), "wasm: table maximum below minimum");
}
for (i = 0; i < m->nglobals; ++i) {
- WasmGlobal *g = &m->globals[i];
+ WasmGlobal* g = &m->globals[i];
if (!wasm_is_num_type(g->type))
wasm_error(c, wasm_loc(0, 0), "wasm: unsupported global type");
if (!g->is_import && wasm_global_init_type(&g->init) != g->type)
wasm_error(c, wasm_loc(0, 0), "wasm: global initializer type mismatch");
}
for (i = 0; i < m->nexports; ++i) {
- WasmExport *ex = &m->exports[i];
+ WasmExport* ex = &m->exports[i];
if ((ex->kind == 0 && ex->index >= m->nfuncs) ||
(ex->kind == 1 && ex->index >= m->ntables) ||
(ex->kind == 2 && (!m->has_memory || ex->index != 0)) ||
@@ -4420,15 +4511,20 @@ static void wasm_validate(WasmModule *m, CfreeCompiler *c) {
"wasm: start function must have no params or results");
}
for (i = 0; i < m->nelems; ++i) {
+ uint32_t table_min;
if (m->elems[i].tableidx >= m->ntables)
wasm_error(c, wasm_loc(0, 0), "wasm: element table index out of range");
+ table_min = m->tables[m->elems[i].tableidx].min;
+ if (m->elems[i].offset < 0 ||
+ (uint64_t)m->elems[i].offset + m->elems[i].nfuncs > table_min)
+ wasm_error(c, wasm_loc(0, 0), "wasm: element segment out of range");
for (j = 0; j < m->elems[i].nfuncs; ++j)
if (m->elems[i].funcs[j] >= m->nfuncs)
wasm_error(c, wasm_loc(0, 0),
"wasm: element function index out of range");
}
for (i = 0; i < m->nfuncs; ++i) {
- WasmFunc *f = &m->funcs[i];
+ WasmFunc* f = &m->funcs[i];
WasmValStack stack;
WasmControlFrame control[65];
uint32_t ncontrol = 1;
@@ -4444,266 +4540,265 @@ static void wasm_validate(WasmModule *m, CfreeCompiler *c) {
if (f->nresults > 1u)
wasm_error(c, wasm_loc(0, 0), "wasm: multi-result unsupported");
for (j = 0; j < f->ninsns; ++j) {
- WasmInsn *in = &f->insns[j];
+ WasmInsn* in = &f->insns[j];
WasmValType vt, src, dst;
switch (in->kind) {
- case WASM_INSN_F32_CONST:
- wasm_stack_push(c, &stack, WASM_VAL_F32);
- break;
- case WASM_INSN_F64_CONST:
- wasm_stack_push(c, &stack, WASM_VAL_F64);
- break;
- case WASM_INSN_I32_CONST:
- wasm_stack_push(c, &stack, WASM_VAL_I32);
- break;
- case WASM_INSN_I64_CONST:
- wasm_stack_push(c, &stack, WASM_VAL_I64);
- break;
- case WASM_INSN_LOCAL_GET:
- if (in->imm < 0 ||
- (uint64_t)in->imm >= (uint64_t)f->nparams + f->nlocals)
- wasm_error(c, wasm_loc(0, 0), "wasm: local index out of range");
- wasm_stack_push(c, &stack,
- wasm_func_local_type(f, (uint32_t)in->imm));
- break;
- case WASM_INSN_LOCAL_SET:
- case WASM_INSN_LOCAL_TEE:
- if (in->imm < 0 ||
- (uint64_t)in->imm >= (uint64_t)f->nparams + f->nlocals)
- wasm_error(c, wasm_loc(0, 0), "wasm: local index out of range");
- wasm_stack_pop(c, &stack, control, ncontrol,
- wasm_func_local_type(f, (uint32_t)in->imm), "local");
- if (in->kind == WASM_INSN_LOCAL_TEE)
+ case WASM_INSN_F32_CONST:
+ wasm_stack_push(c, &stack, WASM_VAL_F32);
+ break;
+ case WASM_INSN_F64_CONST:
+ wasm_stack_push(c, &stack, WASM_VAL_F64);
+ break;
+ case WASM_INSN_I32_CONST:
+ wasm_stack_push(c, &stack, WASM_VAL_I32);
+ break;
+ case WASM_INSN_I64_CONST:
+ wasm_stack_push(c, &stack, WASM_VAL_I64);
+ break;
+ case WASM_INSN_LOCAL_GET:
+ if (in->imm < 0 ||
+ (uint64_t)in->imm >= (uint64_t)f->nparams + f->nlocals)
+ wasm_error(c, wasm_loc(0, 0), "wasm: local index out of range");
wasm_stack_push(c, &stack,
wasm_func_local_type(f, (uint32_t)in->imm));
- break;
- case WASM_INSN_CALL:
- if (in->imm < 0 || (uint64_t)in->imm >= m->nfuncs)
- wasm_error(c, wasm_loc(0, 0), "wasm: call index out of range");
- for (uint32_t k = 0; k < m->funcs[in->imm].nparams; ++k) {
- uint32_t param = m->funcs[in->imm].nparams - 1u - k;
+ break;
+ case WASM_INSN_LOCAL_SET:
+ case WASM_INSN_LOCAL_TEE:
+ if (in->imm < 0 ||
+ (uint64_t)in->imm >= (uint64_t)f->nparams + f->nlocals)
+ wasm_error(c, wasm_loc(0, 0), "wasm: local index out of range");
wasm_stack_pop(c, &stack, control, ncontrol,
- m->funcs[in->imm].params[param], "call argument");
- }
- if (m->funcs[in->imm].nresults)
- wasm_stack_push(c, &stack, m->funcs[in->imm].results[0]);
- break;
- case WASM_INSN_CALL_INDIRECT: {
- WasmFuncType *t;
- if (in->imm < 0 || (uint64_t)in->imm >= m->ntypes)
- wasm_error(c, wasm_loc(0, 0),
- "wasm: call_indirect type index out of range");
- if (in->align >= m->ntables)
- wasm_error(c, wasm_loc(0, 0),
- "wasm: call_indirect table index out of range");
- t = &m->types[in->imm];
- wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32,
- "call_indirect index");
- for (uint32_t k = 0; k < t->nparams; ++k) {
- uint32_t param = t->nparams - 1u - k;
- wasm_stack_pop(c, &stack, control, ncontrol, t->params[param],
- "call_indirect argument");
- }
- if (t->nresults)
- wasm_stack_push(c, &stack, t->results[0]);
- break;
- }
- case WASM_INSN_GLOBAL_GET:
- if (in->imm < 0 || (uint64_t)in->imm >= m->nglobals)
- wasm_error(c, wasm_loc(0, 0), "wasm: global index out of range");
- wasm_stack_push(c, &stack, m->globals[in->imm].type);
- break;
- case WASM_INSN_GLOBAL_SET:
- if (in->imm < 0 || (uint64_t)in->imm >= m->nglobals)
- wasm_error(c, wasm_loc(0, 0), "wasm: global index out of range");
- if (!m->globals[in->imm].mutable_)
- wasm_error(c, wasm_loc(0, 0), "wasm: global is immutable");
- wasm_stack_pop(c, &stack, control, ncontrol, m->globals[in->imm].type,
- "global");
- break;
- case WASM_INSN_RETURN:
- if (f->nresults)
- wasm_stack_pop(c, &stack, control, ncontrol, f->results[0],
- "return");
- wasm_mark_unreachable(&stack, control, ncontrol);
- break;
- case WASM_INSN_DROP:
- wasm_stack_pop(c, &stack, control, ncontrol, 0, "drop");
- break;
- case WASM_INSN_I32_EQZ:
- wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "eqz");
- wasm_stack_push(c, &stack, WASM_VAL_I32);
- break;
- case WASM_INSN_I64_EQZ:
- wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I64, "eqz");
- wasm_stack_push(c, &stack, WASM_VAL_I32);
- break;
- case WASM_INSN_BLOCK:
- case WASM_INSN_LOOP:
- if (ncontrol >= 65u)
- wasm_error(c, wasm_loc(0, 0), "wasm: control stack too deep");
- control[ncontrol].kind = in->kind;
- control[ncontrol].height = stack.depth;
- control[ncontrol].seen_else = 0;
- control[ncontrol].unreachable = 0;
- ncontrol++;
- break;
- case WASM_INSN_IF:
- wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "if");
- if (ncontrol >= 65u)
- wasm_error(c, wasm_loc(0, 0), "wasm: control stack too deep");
- control[ncontrol].kind = in->kind;
- control[ncontrol].height = stack.depth;
- control[ncontrol].seen_else = 0;
- control[ncontrol].unreachable = 0;
- ncontrol++;
- break;
- case WASM_INSN_ELSE:
- if (ncontrol <= 1u || control[ncontrol - 1u].kind != WASM_INSN_IF)
- wasm_error(c, wasm_loc(0, 0), "wasm: else without if");
- if (!control[ncontrol - 1u].unreachable &&
- stack.depth != control[ncontrol - 1u].height)
- wasm_error(c, wasm_loc(0, 0), "wasm: if branch result mismatch");
- stack.depth = control[ncontrol - 1u].height;
- control[ncontrol - 1u].seen_else = 1;
- control[ncontrol - 1u].unreachable = 0;
- break;
- case WASM_INSN_END:
- if (ncontrol <= 1u)
- wasm_error(c, wasm_loc(0, 0), "wasm: end without block");
- if (!control[ncontrol - 1u].unreachable &&
- stack.depth != control[ncontrol - 1u].height)
- wasm_error(c, wasm_loc(0, 0), "wasm: block result mismatch");
- stack.depth = control[ncontrol - 1u].height;
- ncontrol--;
- break;
- case WASM_INSN_BR:
- if (in->imm < 0 || (uint64_t)in->imm >= ncontrol - 1u)
- wasm_error(c, wasm_loc(0, 0), "wasm: branch depth out of range");
- wasm_mark_unreachable(&stack, control, ncontrol);
- break;
- case WASM_INSN_BR_IF:
- if (in->imm < 0 || (uint64_t)in->imm >= ncontrol - 1u)
- wasm_error(c, wasm_loc(0, 0), "wasm: branch depth out of range");
- wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "br_if");
- break;
- case WASM_INSN_BR_TABLE:
- if (in->ntargets == 0)
- wasm_error(c, wasm_loc(0, 0), "wasm: br_table without targets");
- wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32,
- "br_table selector");
- for (uint32_t k = 0; k < in->ntargets; ++k)
- if (in->targets[k] >= ncontrol - 1u)
+ wasm_func_local_type(f, (uint32_t)in->imm), "local");
+ if (in->kind == WASM_INSN_LOCAL_TEE)
+ wasm_stack_push(c, &stack,
+ wasm_func_local_type(f, (uint32_t)in->imm));
+ break;
+ case WASM_INSN_CALL:
+ if (in->imm < 0 || (uint64_t)in->imm >= m->nfuncs)
+ wasm_error(c, wasm_loc(0, 0), "wasm: call index out of range");
+ for (uint32_t k = 0; k < m->funcs[in->imm].nparams; ++k) {
+ uint32_t param = m->funcs[in->imm].nparams - 1u - k;
+ wasm_stack_pop(c, &stack, control, ncontrol,
+ m->funcs[in->imm].params[param], "call argument");
+ }
+ if (m->funcs[in->imm].nresults)
+ wasm_stack_push(c, &stack, m->funcs[in->imm].results[0]);
+ break;
+ case WASM_INSN_CALL_INDIRECT: {
+ WasmFuncType* t;
+ if (in->imm < 0 || (uint64_t)in->imm >= m->ntypes)
wasm_error(c, wasm_loc(0, 0),
- "wasm: br_table depth out of range");
- wasm_mark_unreachable(&stack, control, ncontrol);
- break;
- case WASM_INSN_SELECT: {
- WasmValType rhs, lhs;
- wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "select");
- if (stack.depth <= control[ncontrol - 1u].height &&
- control[ncontrol - 1u].unreachable) {
- in->type = WASM_VAL_I32;
+ "wasm: call_indirect type index out of range");
+ if (in->align >= m->ntables)
+ wasm_error(c, wasm_loc(0, 0),
+ "wasm: call_indirect table index out of range");
+ t = &m->types[in->imm];
+ wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32,
+ "call_indirect index");
+ for (uint32_t k = 0; k < t->nparams; ++k) {
+ uint32_t param = t->nparams - 1u - k;
+ wasm_stack_pop(c, &stack, control, ncontrol, t->params[param],
+ "call_indirect argument");
+ }
+ if (t->nresults) wasm_stack_push(c, &stack, t->results[0]);
break;
}
- if (stack.depth < control[ncontrol - 1u].height + 2u)
- wasm_error(c, wasm_loc(0, 0), "wasm: operand stack underflow");
- rhs = stack.vals[--stack.depth];
- lhs = stack.vals[--stack.depth];
- if (lhs != rhs)
- wasm_error(c, wasm_loc(0, 0), "wasm: select type mismatch");
- in->type = (uint8_t)lhs;
- wasm_stack_push(c, &stack, lhs);
- break;
- }
- case WASM_INSN_MEMORY_SIZE:
- if (!m->has_memory)
- wasm_error(c, wasm_loc(0, 0), "wasm: memory.size without memory");
- wasm_stack_push(c, &stack, WASM_VAL_I32);
- break;
- case WASM_INSN_MEMORY_GROW:
- if (!m->has_memory)
- wasm_error(c, wasm_loc(0, 0), "wasm: memory.grow without memory");
- wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32,
- "memory.grow");
- wasm_stack_push(c, &stack, WASM_VAL_I32);
- break;
- case WASM_INSN_I32_LOAD:
- case WASM_INSN_I64_LOAD:
- case WASM_INSN_I32_LOAD8_S:
- case WASM_INSN_I32_LOAD8_U:
- case WASM_INSN_I32_LOAD16_S:
- case WASM_INSN_I32_LOAD16_U:
- case WASM_INSN_I64_LOAD8_S:
- case WASM_INSN_I64_LOAD8_U:
- case WASM_INSN_I64_LOAD16_S:
- case WASM_INSN_I64_LOAD16_U:
- case WASM_INSN_I64_LOAD32_S:
- case WASM_INSN_I64_LOAD32_U:
- if (!m->has_memory)
- wasm_error(c, wasm_loc(0, 0), "wasm: load without memory");
- wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "load");
- wasm_stack_push(c, &stack, wasm_load_result_type(in->kind));
- break;
- case WASM_INSN_I32_STORE:
- case WASM_INSN_I64_STORE:
- case WASM_INSN_I32_STORE8:
- case WASM_INSN_I32_STORE16:
- case WASM_INSN_I64_STORE8:
- case WASM_INSN_I64_STORE16:
- case WASM_INSN_I64_STORE32:
- if (!m->has_memory)
- wasm_error(c, wasm_loc(0, 0), "wasm: store without memory");
- wasm_stack_pop(c, &stack, control, ncontrol,
- wasm_store_value_type(in->kind), "store");
- wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "store");
- break;
- case WASM_INSN_UNREACHABLE:
- wasm_mark_unreachable(&stack, control, ncontrol);
- break;
- case WASM_INSN_NOP:
- break;
- default:
- if (wasm_int_unop_kind(in->kind, &vt)) {
- wasm_stack_pop(c, &stack, control, ncontrol, vt, "unary operand");
- wasm_stack_push(c, &stack, vt);
+ case WASM_INSN_GLOBAL_GET:
+ if (in->imm < 0 || (uint64_t)in->imm >= m->nglobals)
+ wasm_error(c, wasm_loc(0, 0), "wasm: global index out of range");
+ wasm_stack_push(c, &stack, m->globals[in->imm].type);
break;
- }
- if (wasm_fp_binop_kind(in->kind, &vt)) {
- wasm_stack_pop(c, &stack, control, ncontrol, vt, "fp operand");
- wasm_stack_pop(c, &stack, control, ncontrol, vt, "fp operand");
- wasm_stack_push(c, &stack, vt);
+ case WASM_INSN_GLOBAL_SET:
+ if (in->imm < 0 || (uint64_t)in->imm >= m->nglobals)
+ wasm_error(c, wasm_loc(0, 0), "wasm: global index out of range");
+ if (!m->globals[in->imm].mutable_)
+ wasm_error(c, wasm_loc(0, 0), "wasm: global is immutable");
+ wasm_stack_pop(c, &stack, control, ncontrol, m->globals[in->imm].type,
+ "global");
+ break;
+ case WASM_INSN_RETURN:
+ if (f->nresults)
+ wasm_stack_pop(c, &stack, control, ncontrol, f->results[0],
+ "return");
+ wasm_mark_unreachable(&stack, control, ncontrol);
+ break;
+ case WASM_INSN_DROP:
+ wasm_stack_pop(c, &stack, control, ncontrol, 0, "drop");
+ break;
+ case WASM_INSN_I32_EQZ:
+ wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "eqz");
+ wasm_stack_push(c, &stack, WASM_VAL_I32);
+ break;
+ case WASM_INSN_I64_EQZ:
+ wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I64, "eqz");
+ wasm_stack_push(c, &stack, WASM_VAL_I32);
+ break;
+ case WASM_INSN_BLOCK:
+ case WASM_INSN_LOOP:
+ if (ncontrol >= 65u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: control stack too deep");
+ control[ncontrol].kind = in->kind;
+ control[ncontrol].height = stack.depth;
+ control[ncontrol].seen_else = 0;
+ control[ncontrol].unreachable = 0;
+ ncontrol++;
+ break;
+ case WASM_INSN_IF:
+ wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "if");
+ if (ncontrol >= 65u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: control stack too deep");
+ control[ncontrol].kind = in->kind;
+ control[ncontrol].height = stack.depth;
+ control[ncontrol].seen_else = 0;
+ control[ncontrol].unreachable = 0;
+ ncontrol++;
+ break;
+ case WASM_INSN_ELSE:
+ if (ncontrol <= 1u || control[ncontrol - 1u].kind != WASM_INSN_IF)
+ wasm_error(c, wasm_loc(0, 0), "wasm: else without if");
+ if (!control[ncontrol - 1u].unreachable &&
+ stack.depth != control[ncontrol - 1u].height)
+ wasm_error(c, wasm_loc(0, 0), "wasm: if branch result mismatch");
+ stack.depth = control[ncontrol - 1u].height;
+ control[ncontrol - 1u].seen_else = 1;
+ control[ncontrol - 1u].unreachable = 0;
+ break;
+ case WASM_INSN_END:
+ if (ncontrol <= 1u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: end without block");
+ if (!control[ncontrol - 1u].unreachable &&
+ stack.depth != control[ncontrol - 1u].height)
+ wasm_error(c, wasm_loc(0, 0), "wasm: block result mismatch");
+ stack.depth = control[ncontrol - 1u].height;
+ ncontrol--;
+ break;
+ case WASM_INSN_BR:
+ if (in->imm < 0 || (uint64_t)in->imm >= ncontrol - 1u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: branch depth out of range");
+ wasm_mark_unreachable(&stack, control, ncontrol);
+ break;
+ case WASM_INSN_BR_IF:
+ if (in->imm < 0 || (uint64_t)in->imm >= ncontrol - 1u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: branch depth out of range");
+ wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "br_if");
+ break;
+ case WASM_INSN_BR_TABLE:
+ if (in->ntargets == 0)
+ wasm_error(c, wasm_loc(0, 0), "wasm: br_table without targets");
+ wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32,
+ "br_table selector");
+ for (uint32_t k = 0; k < in->ntargets; ++k)
+ if (in->targets[k] >= ncontrol - 1u)
+ wasm_error(c, wasm_loc(0, 0),
+ "wasm: br_table depth out of range");
+ wasm_mark_unreachable(&stack, control, ncontrol);
+ break;
+ case WASM_INSN_SELECT: {
+ WasmValType rhs, lhs;
+ wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "select");
+ if (stack.depth <= control[ncontrol - 1u].height &&
+ control[ncontrol - 1u].unreachable) {
+ in->type = WASM_VAL_I32;
+ break;
+ }
+ if (stack.depth < control[ncontrol - 1u].height + 2u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: operand stack underflow");
+ rhs = stack.vals[--stack.depth];
+ lhs = stack.vals[--stack.depth];
+ if (lhs != rhs)
+ wasm_error(c, wasm_loc(0, 0), "wasm: select type mismatch");
+ in->type = (uint8_t)lhs;
+ wasm_stack_push(c, &stack, lhs);
break;
}
- if (wasm_fp_cmp_kind(in->kind, &vt)) {
- wasm_stack_pop(c, &stack, control, ncontrol, vt, "fp compare");
- wasm_stack_pop(c, &stack, control, ncontrol, vt, "fp compare");
+ case WASM_INSN_MEMORY_SIZE:
+ if (!m->has_memory)
+ wasm_error(c, wasm_loc(0, 0), "wasm: memory.size without memory");
wasm_stack_push(c, &stack, WASM_VAL_I32);
break;
- }
- if (wasm_conversion_kind(in->kind, &src, &dst)) {
- wasm_stack_pop(c, &stack, control, ncontrol, src, "conversion");
- wasm_stack_push(c, &stack, dst);
+ case WASM_INSN_MEMORY_GROW:
+ if (!m->has_memory)
+ wasm_error(c, wasm_loc(0, 0), "wasm: memory.grow without memory");
+ wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32,
+ "memory.grow");
+ wasm_stack_push(c, &stack, WASM_VAL_I32);
+ break;
+ case WASM_INSN_I32_LOAD:
+ case WASM_INSN_I64_LOAD:
+ case WASM_INSN_I32_LOAD8_S:
+ case WASM_INSN_I32_LOAD8_U:
+ case WASM_INSN_I32_LOAD16_S:
+ case WASM_INSN_I32_LOAD16_U:
+ case WASM_INSN_I64_LOAD8_S:
+ case WASM_INSN_I64_LOAD8_U:
+ case WASM_INSN_I64_LOAD16_S:
+ case WASM_INSN_I64_LOAD16_U:
+ case WASM_INSN_I64_LOAD32_S:
+ case WASM_INSN_I64_LOAD32_U:
+ if (!m->has_memory)
+ wasm_error(c, wasm_loc(0, 0), "wasm: load without memory");
+ wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "load");
+ wasm_stack_push(c, &stack, wasm_load_result_type(in->kind));
+ break;
+ case WASM_INSN_I32_STORE:
+ case WASM_INSN_I64_STORE:
+ case WASM_INSN_I32_STORE8:
+ case WASM_INSN_I32_STORE16:
+ case WASM_INSN_I64_STORE8:
+ case WASM_INSN_I64_STORE16:
+ case WASM_INSN_I64_STORE32:
+ if (!m->has_memory)
+ wasm_error(c, wasm_loc(0, 0), "wasm: store without memory");
+ wasm_stack_pop(c, &stack, control, ncontrol,
+ wasm_store_value_type(in->kind), "store");
+ wasm_stack_pop(c, &stack, control, ncontrol, WASM_VAL_I32, "store");
+ break;
+ case WASM_INSN_UNREACHABLE:
+ wasm_mark_unreachable(&stack, control, ncontrol);
break;
- }
- {
- CfreeCgIntCmpOp cmp;
- WasmValType rhs, lhs;
- rhs = stack.depth > control[ncontrol - 1u].height
- ? stack.vals[stack.depth - 1u]
- : WASM_VAL_I32;
- wasm_stack_pop(c, &stack, control, ncontrol, 0, "operand");
- lhs = stack.depth > control[ncontrol - 1u].height
- ? stack.vals[stack.depth - 1u]
- : rhs;
- wasm_stack_pop(c, &stack, control, ncontrol, rhs, "operand");
- if (lhs != rhs)
- wasm_error(c, wasm_loc(0, 0), "wasm: operand type mismatch");
- wasm_stack_push(
- c, &stack,
- wasm_int_cmp_op(in->kind, &cmp) ? WASM_VAL_I32 : lhs);
+ case WASM_INSN_NOP:
break;
- }
+ default:
+ if (wasm_int_unop_kind(in->kind, &vt)) {
+ wasm_stack_pop(c, &stack, control, ncontrol, vt, "unary operand");
+ wasm_stack_push(c, &stack, vt);
+ break;
+ }
+ if (wasm_fp_binop_kind(in->kind, &vt)) {
+ wasm_stack_pop(c, &stack, control, ncontrol, vt, "fp operand");
+ wasm_stack_pop(c, &stack, control, ncontrol, vt, "fp operand");
+ wasm_stack_push(c, &stack, vt);
+ break;
+ }
+ if (wasm_fp_cmp_kind(in->kind, &vt)) {
+ wasm_stack_pop(c, &stack, control, ncontrol, vt, "fp compare");
+ wasm_stack_pop(c, &stack, control, ncontrol, vt, "fp compare");
+ wasm_stack_push(c, &stack, WASM_VAL_I32);
+ break;
+ }
+ if (wasm_conversion_kind(in->kind, &src, &dst)) {
+ wasm_stack_pop(c, &stack, control, ncontrol, src, "conversion");
+ wasm_stack_push(c, &stack, dst);
+ break;
+ }
+ {
+ CfreeCgIntCmpOp cmp;
+ WasmValType rhs, lhs;
+ rhs = stack.depth > control[ncontrol - 1u].height
+ ? stack.vals[stack.depth - 1u]
+ : WASM_VAL_I32;
+ wasm_stack_pop(c, &stack, control, ncontrol, 0, "operand");
+ lhs = stack.depth > control[ncontrol - 1u].height
+ ? stack.vals[stack.depth - 1u]
+ : rhs;
+ wasm_stack_pop(c, &stack, control, ncontrol, rhs, "operand");
+ if (lhs != rhs)
+ wasm_error(c, wasm_loc(0, 0), "wasm: operand type mismatch");
+ wasm_stack_push(
+ c, &stack,
+ wasm_int_cmp_op(in->kind, &cmp) ? WASM_VAL_I32 : lhs);
+ break;
+ }
}
}
if (ncontrol != 1u)
@@ -4719,12 +4814,15 @@ static void wasm_validate(WasmModule *m, CfreeCompiler *c) {
}
}
-static void wasm_cg_call_func(CfreeCompiler *c, CfreeCg *cg,
- CfreeCgBuiltinTypes b, const WasmFunc *f,
- const WasmCgRuntime *rt, CfreeCgSym sym,
- CfreeCgLocal instance_local) {
+static void wasm_cg_call_func(CfreeCompiler* c, CfreeCg* cg,
+ CfreeCgBuiltinTypes b, const WasmFunc* f,
+ const WasmCgRuntime* rt, CfreeCgSym sym,
+ CfreeCgTypeId func_type,
+ CfreeCgLocal instance_local,
+ uint32_t func_index) {
CfreeCgLocalAttrs attrs;
CfreeCgLocal args[16];
+ CfreeCgLocal callee = CFREE_CG_LOCAL_NONE;
memset(&attrs, 0, sizeof attrs);
attrs.flags = CFREE_CG_LOCAL_COMPILER_TEMP;
if (f->nparams > 16u)
@@ -4737,18 +4835,38 @@ static void wasm_cg_call_func(CfreeCompiler *c, CfreeCg *cg,
cfree_cg_swap(cg);
cfree_cg_store(cg, wasm_cg_mem(c, b, f->params[param]));
}
+ if (f->is_import) {
+ CfreeCgLabel ok = cfree_cg_label_new(cg);
+ callee = cfree_cg_local(cg, rt->void_ptr_ty, attrs);
+ cfree_cg_push_local(cg, callee);
+ wasm_cg_push_import_func_ptr(cg, rt, instance_local, func_index);
+ cfree_cg_store(cg, wasm_cg_mem_type(rt->void_ptr_ty));
+ cfree_cg_push_local(cg, callee);
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
+ cfree_cg_push_null(cg, rt->void_ptr_ty);
+ cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
+ cfree_cg_branch_true(cg, ok);
+ wasm_cg_trap_table(cg);
+ cfree_cg_label_place(cg, ok);
+ cfree_cg_push_local(cg, callee);
+ cfree_cg_load(cg, wasm_cg_mem_type(rt->void_ptr_ty));
+ cfree_cg_bitcast(cg, cfree_cg_type_ptr(c, func_type, 0));
+ }
cfree_cg_push_local(cg, instance_local);
cfree_cg_load(cg, wasm_cg_mem_type(rt->instance_ptr_ty));
for (uint32_t p = 0; p < f->nparams; ++p) {
cfree_cg_push_local(cg, args[p]);
cfree_cg_load(cg, wasm_cg_mem(c, b, f->params[p]));
}
- cfree_cg_call_symbol(cg, sym, f->nparams + 1u, (CfreeCgCallAttrs){0});
+ if (f->is_import)
+ cfree_cg_call(cg, f->nparams + 1u, func_type, (CfreeCgCallAttrs){0});
+ else
+ cfree_cg_call_symbol(cg, sym, f->nparams + 1u, (CfreeCgCallAttrs){0});
}
-static void wasm_emit_cg(CfreeCompiler *c, const CfreeCompileOptions *opts,
- CfreeObjBuilder *out, const WasmModule *m) {
- CfreeCg *cg = cfree_cg_new(c, out, opts);
+static void wasm_emit_cg(CfreeCompiler* c, const CfreeCompileOptions* opts,
+ CfreeObjBuilder* out, const WasmModule* m) {
+ CfreeCg* cg = cfree_cg_new(c, out, opts);
CfreeCgBuiltinTypes b = cfree_cg_builtin_types(c);
WasmCgRuntime rt;
CfreeCgSym syms[64];
@@ -4756,8 +4874,7 @@ static void wasm_emit_cg(CfreeCompiler *c, const CfreeCompileOptions *opts,
CfreeCgTypeId func_types[64];
CfreeCgLocal locals[48];
uint32_t i, j;
- if (!cg)
- wasm_error(c, wasm_loc(0, 0), "wasm: failed to initialize codegen");
+ if (!cg) wasm_error(c, wasm_loc(0, 0), "wasm: failed to initialize codegen");
if (m->nfuncs > 64u)
wasm_error(c, wasm_loc(0, 0), "wasm: too many functions");
if (m->nglobals > 64u)
@@ -4786,7 +4903,7 @@ static void wasm_emit_cg(CfreeCompiler *c, const CfreeCompileOptions *opts,
init_sym = cfree_cg_decl(cg, decl);
}
for (i = 0; i < m->nfuncs; ++i) {
- const WasmFunc *f = &m->funcs[i];
+ const WasmFunc* f = &m->funcs[i];
CfreeCgFuncParam cg_params[17];
CfreeCgFuncSig sig;
CfreeCgDecl decl;
@@ -4807,9 +4924,11 @@ static void wasm_emit_cg(CfreeCompiler *c, const CfreeCompileOptions *opts,
func_types[i] = cfree_cg_type_func(c, sig);
if (!func_types[i])
wasm_error(c, wasm_loc(0, 0), "wasm: failed to create function type");
- if (f->is_import && f->import_name) {
- source_name = cfree_sym_intern(c, f->import_name);
- } else if (f->export_name) {
+ if (f->is_import) {
+ syms[i] = CFREE_CG_SYM_NONE;
+ continue;
+ }
+ if (f->export_name) {
source_name = cfree_sym_intern(c, f->export_name);
} else {
size_t pos = 0;
@@ -4817,8 +4936,7 @@ static void wasm_emit_cg(CfreeCompiler *c, const CfreeCompileOptions *opts,
uint32_t n = i, div = 1000000000u;
memcpy(local_name, prefix, sizeof(prefix) - 1u);
pos = sizeof(prefix) - 1u;
- while (div > 1u && n / div == 0)
- div /= 10u;
+ while (div > 1u && n / div == 0) div /= 10u;
while (div) {
local_name[pos++] = (char)('0' + (n / div) % 10u);
div /= 10u;
@@ -4831,8 +4949,7 @@ static void wasm_emit_cg(CfreeCompiler *c, const CfreeCompileOptions *opts,
decl.linkage_name = cfree_cg_c_linkage_name(c, source_name);
decl.display_name = source_name;
decl.type = func_types[i];
- decl.sym.bind =
- (f->export_name || f->is_import) ? CFREE_SB_GLOBAL : CFREE_SB_LOCAL;
+ decl.sym.bind = f->export_name ? CFREE_SB_GLOBAL : CFREE_SB_LOCAL;
syms[i] = cfree_cg_decl(cg, decl);
if (!syms[i])
wasm_error(c, wasm_loc(0, 0), "wasm: failed to declare function");
@@ -4862,10 +4979,61 @@ static void wasm_emit_cg(CfreeCompiler *c, const CfreeCompileOptions *opts,
cfree_cg_memcpy(cg, m->memory.data_init_len, mem, mem);
}
}
+ for (i = 0; i < m->ntables; ++i) {
+ const WasmTable* t = &m->tables[i];
+ uint32_t max = t->has_max ? t->max : t->min;
+ wasm_cg_push_table_lvalue(cg, &rt, instance_local, i);
+ cfree_cg_field(cg, rt.table_entries_ptr_field);
+ wasm_cg_push_table_entries_array_lvalue(cg, &rt, instance_local, i);
+ cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I32]);
+ cfree_cg_index(cg, 0);
+ cfree_cg_addr(cg);
+ cfree_cg_store(cg, wasm_cg_mem_type(rt.table_entry_ptr_ty));
+ wasm_cg_push_table_lvalue(cg, &rt, instance_local, i);
+ cfree_cg_field(cg, rt.table_len_field);
+ cfree_cg_push_int(cg, t->min, b.id[CFREE_CG_BUILTIN_I32]);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ wasm_cg_push_table_lvalue(cg, &rt, instance_local, i);
+ cfree_cg_field(cg, rt.table_max_field);
+ cfree_cg_push_int(cg, max, b.id[CFREE_CG_BUILTIN_I32]);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ }
+ for (i = 0; i < m->nelems; ++i) {
+ const WasmElemSegment* seg = &m->elems[i];
+ for (j = 0; j < seg->nfuncs; ++j) {
+ uint32_t slot = (uint32_t)(seg->offset + j);
+ uint32_t funcidx = seg->funcs[j];
+ CfreeCgLocalAttrs tmp_attrs;
+ CfreeCgLocal slot_local;
+ memset(&tmp_attrs, 0, sizeof tmp_attrs);
+ tmp_attrs.flags = CFREE_CG_LOCAL_COMPILER_TEMP;
+ slot_local = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], tmp_attrs);
+ cfree_cg_push_local(cg, slot_local);
+ cfree_cg_push_int(cg, slot, b.id[CFREE_CG_BUILTIN_I32]);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local, seg->tableidx,
+ slot_local,
+ wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_field(cg, rt.table_entry_fn_field);
+ if (m->funcs[funcidx].is_import) {
+ wasm_cg_push_import_func_ptr(cg, &rt, instance_local, funcidx);
+ } else {
+ cfree_cg_push_symbol_addr(cg, syms[funcidx], 0);
+ cfree_cg_bitcast(cg, rt.void_ptr_ty);
+ }
+ cfree_cg_store(cg, wasm_cg_mem_type(rt.void_ptr_ty));
+ wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local, seg->tableidx,
+ slot_local,
+ wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_field(cg, rt.table_entry_typeidx_field);
+ cfree_cg_push_int(cg, m->funcs[funcidx].typeidx,
+ b.id[CFREE_CG_BUILTIN_I32]);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ }
+ }
for (i = 0; i < m->nglobals; ++i) {
- const WasmGlobal *g = &m->globals[i];
- if (g->is_import)
- continue;
+ const WasmGlobal* g = &m->globals[i];
+ if (g->is_import) continue;
wasm_cg_push_global_lvalue(cg, &rt, instance_local, i);
if (g->type == WASM_VAL_F32 || g->type == WASM_VAL_F64)
cfree_cg_push_float(cg, g->init.fp, wasm_cg_type(c, b, g->type));
@@ -4876,12 +5044,13 @@ static void wasm_emit_cg(CfreeCompiler *c, const CfreeCompileOptions *opts,
}
if (m->has_start)
wasm_cg_call_func(c, cg, b, &m->funcs[m->start_func], &rt,
- syms[m->start_func], instance_local);
+ syms[m->start_func], func_types[m->start_func],
+ instance_local, m->start_func);
cfree_cg_ret_void(cg);
cfree_cg_func_end(cg);
}
for (i = 0; i < m->nfuncs; ++i) {
- const WasmFunc *f = &m->funcs[i];
+ const WasmFunc* f = &m->funcs[i];
struct {
uint8_t kind;
int seen_else;
@@ -4891,8 +5060,7 @@ static void wasm_emit_cg(CfreeCompiler *c, const CfreeCompileOptions *opts,
} control[64];
uint32_t ncontrol = 0;
CfreeCgLocal instance_local;
- if (f->is_import)
- continue;
+ if (f->is_import) continue;
cfree_cg_func_begin(cg, syms[i]);
{
CfreeCgLocalAttrs attrs;
@@ -4918,637 +5086,621 @@ static void wasm_emit_cg(CfreeCompiler *c, const CfreeCompileOptions *opts,
for (j = 0; j < f->ninsns; ++j) {
WasmInsn in = f->insns[j];
switch (in.kind) {
- case WASM_INSN_UNREACHABLE:
- cfree_cg_unreachable(cg);
- break;
- case WASM_INSN_NOP:
- break;
- case WASM_INSN_BLOCK:
- if (ncontrol >= 64u)
- wasm_error(c, wasm_loc(0, 0), "wasm: control stack too deep");
- memset(&control[ncontrol], 0, sizeof control[ncontrol]);
- control[ncontrol].kind = WASM_INSN_BLOCK;
- control[ncontrol].end = cfree_cg_label_new(cg);
- ncontrol++;
- break;
- case WASM_INSN_LOOP:
- if (ncontrol >= 64u)
- wasm_error(c, wasm_loc(0, 0), "wasm: control stack too deep");
- memset(&control[ncontrol], 0, sizeof control[ncontrol]);
- control[ncontrol].kind = WASM_INSN_LOOP;
- control[ncontrol].start = cfree_cg_label_new(cg);
- control[ncontrol].end = cfree_cg_label_new(cg);
- cfree_cg_label_place(cg, control[ncontrol].start);
- ncontrol++;
- break;
- case WASM_INSN_IF:
- if (ncontrol >= 64u)
- wasm_error(c, wasm_loc(0, 0), "wasm: control stack too deep");
- memset(&control[ncontrol], 0, sizeof control[ncontrol]);
- control[ncontrol].kind = WASM_INSN_IF;
- control[ncontrol].else_label = cfree_cg_label_new(cg);
- control[ncontrol].end = cfree_cg_label_new(cg);
- cfree_cg_branch_false(cg, control[ncontrol].else_label);
- ncontrol++;
- break;
- case WASM_INSN_ELSE:
- if (!ncontrol || control[ncontrol - 1u].kind != WASM_INSN_IF)
- wasm_error(c, wasm_loc(0, 0), "wasm: else without if");
- cfree_cg_jump(cg, control[ncontrol - 1u].end);
- cfree_cg_label_place(cg, control[ncontrol - 1u].else_label);
- control[ncontrol - 1u].seen_else = 1;
- break;
- case WASM_INSN_END:
- if (!ncontrol)
- wasm_error(c, wasm_loc(0, 0), "wasm: end without block");
- ncontrol--;
- if (control[ncontrol].kind == WASM_INSN_IF &&
- !control[ncontrol].seen_else)
- cfree_cg_label_place(cg, control[ncontrol].else_label);
- cfree_cg_label_place(cg, control[ncontrol].end);
- break;
- case WASM_INSN_BR: {
- uint32_t depth = (uint32_t)in.imm;
- uint32_t idx;
- if (depth >= ncontrol)
- wasm_error(c, wasm_loc(0, 0), "wasm: branch depth out of range");
- idx = ncontrol - 1u - depth;
- cfree_cg_jump(cg, control[idx].kind == WASM_INSN_LOOP
- ? control[idx].start
- : control[idx].end);
- break;
- }
- case WASM_INSN_BR_IF: {
- uint32_t depth = (uint32_t)in.imm;
- uint32_t idx;
- if (depth >= ncontrol)
- wasm_error(c, wasm_loc(0, 0), "wasm: branch depth out of range");
- idx = ncontrol - 1u - depth;
- cfree_cg_branch_true(cg, control[idx].kind == WASM_INSN_LOOP
- ? control[idx].start
- : control[idx].end);
- break;
- }
- case WASM_INSN_BR_TABLE: {
- CfreeCgSwitchCase cases[15];
- CfreeCgSwitch sw;
- memset(cases, 0, sizeof cases);
- if (in.ntargets == 0 || in.ntargets > 16u)
- wasm_error(c, wasm_loc(0, 0), "wasm: bad br_table target count");
- for (uint32_t k = 0; k + 1u < in.ntargets; ++k) {
+ case WASM_INSN_UNREACHABLE:
+ wasm_cg_trap_unreachable(cg);
+ break;
+ case WASM_INSN_NOP:
+ break;
+ case WASM_INSN_BLOCK:
+ if (ncontrol >= 64u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: control stack too deep");
+ memset(&control[ncontrol], 0, sizeof control[ncontrol]);
+ control[ncontrol].kind = WASM_INSN_BLOCK;
+ control[ncontrol].end = cfree_cg_label_new(cg);
+ ncontrol++;
+ break;
+ case WASM_INSN_LOOP:
+ if (ncontrol >= 64u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: control stack too deep");
+ memset(&control[ncontrol], 0, sizeof control[ncontrol]);
+ control[ncontrol].kind = WASM_INSN_LOOP;
+ control[ncontrol].start = cfree_cg_label_new(cg);
+ control[ncontrol].end = cfree_cg_label_new(cg);
+ cfree_cg_label_place(cg, control[ncontrol].start);
+ ncontrol++;
+ break;
+ case WASM_INSN_IF:
+ if (ncontrol >= 64u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: control stack too deep");
+ memset(&control[ncontrol], 0, sizeof control[ncontrol]);
+ control[ncontrol].kind = WASM_INSN_IF;
+ control[ncontrol].else_label = cfree_cg_label_new(cg);
+ control[ncontrol].end = cfree_cg_label_new(cg);
+ cfree_cg_branch_false(cg, control[ncontrol].else_label);
+ ncontrol++;
+ break;
+ case WASM_INSN_ELSE:
+ if (!ncontrol || control[ncontrol - 1u].kind != WASM_INSN_IF)
+ wasm_error(c, wasm_loc(0, 0), "wasm: else without if");
+ cfree_cg_jump(cg, control[ncontrol - 1u].end);
+ cfree_cg_label_place(cg, control[ncontrol - 1u].else_label);
+ control[ncontrol - 1u].seen_else = 1;
+ break;
+ case WASM_INSN_END:
+ if (!ncontrol)
+ wasm_error(c, wasm_loc(0, 0), "wasm: end without block");
+ ncontrol--;
+ if (control[ncontrol].kind == WASM_INSN_IF &&
+ !control[ncontrol].seen_else)
+ cfree_cg_label_place(cg, control[ncontrol].else_label);
+ cfree_cg_label_place(cg, control[ncontrol].end);
+ break;
+ case WASM_INSN_BR: {
+ uint32_t depth = (uint32_t)in.imm;
uint32_t idx;
- if (in.targets[k] >= ncontrol)
+ if (depth >= ncontrol)
wasm_error(c, wasm_loc(0, 0), "wasm: branch depth out of range");
- idx = ncontrol - 1u - in.targets[k];
- cases[k].value = k;
- cases[k].label = control[idx].kind == WASM_INSN_LOOP
- ? control[idx].start
- : control[idx].end;
- }
- if (in.targets[in.ntargets - 1u] >= ncontrol)
- wasm_error(c, wasm_loc(0, 0), "wasm: branch depth out of range");
- memset(&sw, 0, sizeof sw);
- sw.selector_type = b.id[CFREE_CG_BUILTIN_I32];
- sw.cases = cases;
- sw.ncases = in.ntargets - 1u;
- sw.default_label =
- control[ncontrol - 1u - in.targets[in.ntargets - 1u]].kind ==
- WASM_INSN_LOOP
- ? control[ncontrol - 1u - in.targets[in.ntargets - 1u]].start
- : control[ncontrol - 1u - in.targets[in.ntargets - 1u]].end;
- sw.hint = CFREE_CG_SWITCH_BRANCH_CHAIN;
- cfree_cg_switch(cg, sw);
- break;
- }
- case WASM_INSN_SELECT: {
- CfreeCgTypeId ty = wasm_cg_type(c, b, (WasmValType)in.type);
- CfreeCgMemAccess mem = wasm_cg_mem(c, b, (WasmValType)in.type);
- CfreeCgLocalAttrs attrs;
- CfreeCgLocal lhs, rhs, cond, result;
- CfreeCgLabel else_label = cfree_cg_label_new(cg);
- CfreeCgLabel end_label = cfree_cg_label_new(cg);
- memset(&attrs, 0, sizeof attrs);
- attrs.flags = CFREE_CG_LOCAL_COMPILER_TEMP;
- lhs = cfree_cg_local(cg, ty, attrs);
- rhs = cfree_cg_local(cg, ty, attrs);
- result = cfree_cg_local(cg, ty, attrs);
- cond = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
-
- cfree_cg_push_local(cg, cond);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_push_local(cg, rhs);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, mem);
- cfree_cg_push_local(cg, lhs);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, mem);
-
- cfree_cg_push_local(cg, cond);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_branch_false(cg, else_label);
- cfree_cg_push_local(cg, result);
- cfree_cg_push_local(cg, lhs);
- cfree_cg_load(cg, mem);
- cfree_cg_store(cg, mem);
- cfree_cg_jump(cg, end_label);
- cfree_cg_label_place(cg, else_label);
- cfree_cg_push_local(cg, result);
- cfree_cg_push_local(cg, rhs);
- cfree_cg_load(cg, mem);
- cfree_cg_store(cg, mem);
- cfree_cg_label_place(cg, end_label);
- cfree_cg_push_local(cg, result);
- cfree_cg_load(cg, mem);
- } break;
- case WASM_INSN_I32_CONST:
- cfree_cg_push_int(cg, (uint64_t)(uint32_t)in.imm,
- b.id[CFREE_CG_BUILTIN_I32]);
- break;
- case WASM_INSN_I64_CONST:
- cfree_cg_push_int(cg, (uint64_t)in.imm, b.id[CFREE_CG_BUILTIN_I64]);
- break;
- case WASM_INSN_F32_CONST:
- cfree_cg_push_float(cg, in.fp, b.id[CFREE_CG_BUILTIN_F32]);
- break;
- case WASM_INSN_F64_CONST:
- cfree_cg_push_float(cg, in.fp, b.id[CFREE_CG_BUILTIN_F64]);
- break;
- case WASM_INSN_LOCAL_GET: {
- uint32_t index = (uint32_t)in.imm;
- cfree_cg_push_local(cg, locals[index]);
- cfree_cg_load(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
- break;
- }
- case WASM_INSN_LOCAL_SET: {
- uint32_t index = (uint32_t)in.imm;
- cfree_cg_push_local(cg, locals[index]);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
- break;
- }
- case WASM_INSN_LOCAL_TEE: {
- uint32_t index = (uint32_t)in.imm;
- cfree_cg_dup(cg);
- cfree_cg_push_local(cg, locals[index]);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
- break;
- }
- case WASM_INSN_CALL:
- wasm_cg_call_func(c, cg, b, &m->funcs[in.imm], &rt, syms[in.imm],
- instance_local);
- break;
- case WASM_INSN_CALL_INDIRECT: {
- const WasmFuncType *t = &m->types[in.imm];
- CfreeCgLocalAttrs attrs;
- CfreeCgLocal selector, args[16], result = CFREE_CG_LOCAL_NONE;
- CfreeCgSwitchCase cases[64];
- CfreeCgLabel labels[64], trap_label, done_label;
- CfreeCgSwitch sw;
- uint32_t ncases = 0;
- CfreeCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
- memset(&attrs, 0, sizeof attrs);
- attrs.flags = CFREE_CG_LOCAL_COMPILER_TEMP;
- if (t->nparams > 16u)
- wasm_error(c, wasm_loc(0, 0), "wasm: too many call_indirect args");
- selector = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
- if (t->nresults)
- result =
- cfree_cg_local(cg, wasm_cg_type(c, b, t->results[0]), attrs);
- cfree_cg_push_local(cg, selector);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, i32_mem);
- for (uint32_t p = 0; p < t->nparams; ++p) {
- uint32_t param = t->nparams - 1u - p;
- args[param] =
- cfree_cg_local(cg, wasm_cg_type(c, b, t->params[param]), attrs);
- cfree_cg_push_local(cg, args[param]);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, t->params[param]));
+ idx = ncontrol - 1u - depth;
+ cfree_cg_jump(cg, control[idx].kind == WASM_INSN_LOOP
+ ? control[idx].start
+ : control[idx].end);
+ break;
}
- memset(cases, 0, sizeof cases);
- memset(labels, 0, sizeof labels);
- trap_label = cfree_cg_label_new(cg);
- done_label = cfree_cg_label_new(cg);
- for (uint32_t e = 0; e < m->nelems; ++e) {
- const WasmElemSegment *seg = &m->elems[e];
- if (seg->tableidx != in.align)
- continue;
- for (uint32_t k = 0; k < seg->nfuncs; ++k) {
- uint32_t funcidx = seg->funcs[k];
- if (funcidx >= m->nfuncs)
- continue;
- if (m->funcs[funcidx].nparams != t->nparams ||
- m->funcs[funcidx].nresults != t->nresults ||
- memcmp(m->funcs[funcidx].params, t->params,
- sizeof(t->params[0]) * t->nparams) != 0 ||
- memcmp(m->funcs[funcidx].results, t->results,
- sizeof(t->results[0]) * t->nresults) != 0)
- continue;
- if (ncases >= 64u)
- wasm_error(c, wasm_loc(0, 0),
- "wasm: too many call_indirect table entries");
- labels[ncases] = cfree_cg_label_new(cg);
- cases[ncases].value = (uint64_t)(seg->offset + k);
- cases[ncases].label = labels[ncases];
- ncases++;
- }
+ case WASM_INSN_BR_IF: {
+ uint32_t depth = (uint32_t)in.imm;
+ uint32_t idx;
+ if (depth >= ncontrol)
+ wasm_error(c, wasm_loc(0, 0), "wasm: branch depth out of range");
+ idx = ncontrol - 1u - depth;
+ cfree_cg_branch_true(cg, control[idx].kind == WASM_INSN_LOOP
+ ? control[idx].start
+ : control[idx].end);
+ break;
}
- cfree_cg_push_local(cg, selector);
- cfree_cg_load(cg, i32_mem);
- memset(&sw, 0, sizeof sw);
- sw.selector_type = b.id[CFREE_CG_BUILTIN_I32];
- sw.default_label = trap_label;
- sw.cases = cases;
- sw.ncases = ncases;
- sw.hint = CFREE_CG_SWITCH_BRANCH_CHAIN;
- cfree_cg_switch(cg, sw);
- for (uint32_t e = 0; e < m->nelems; ++e) {
- const WasmElemSegment *seg = &m->elems[e];
- if (seg->tableidx != in.align)
- continue;
- for (uint32_t k = 0; k < seg->nfuncs; ++k) {
- uint32_t funcidx = seg->funcs[k];
- const WasmFunc *callee;
- int matched;
- CfreeCgLabel label = CFREE_CG_LABEL_NONE;
- for (uint32_t ci = 0; ci < ncases; ++ci)
- if (cases[ci].value == (uint64_t)(seg->offset + k))
- label = labels[ci];
- if (!label)
- continue;
- callee = &m->funcs[funcidx];
- matched = callee->nparams == t->nparams &&
- callee->nresults == t->nresults &&
- memcmp(callee->params, t->params,
- sizeof(t->params[0]) * t->nparams) == 0 &&
- memcmp(callee->results, t->results,
- sizeof(t->results[0]) * t->nresults) == 0;
- cfree_cg_label_place(cg, label);
- if (!matched) {
- wasm_cg_trap(cg);
- continue;
- }
- cfree_cg_push_local(cg, instance_local);
- cfree_cg_load(cg, wasm_cg_mem_type(rt.instance_ptr_ty));
- for (uint32_t p = 0; p < t->nparams; ++p) {
- cfree_cg_push_local(cg, args[p]);
- cfree_cg_load(cg, wasm_cg_mem(c, b, t->params[p]));
- }
- cfree_cg_call_symbol(cg, syms[funcidx], t->nparams + 1u,
- (CfreeCgCallAttrs){0});
- if (t->nresults) {
- cfree_cg_push_local(cg, result);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, t->results[0]));
- }
- cfree_cg_jump(cg, done_label);
+ case WASM_INSN_BR_TABLE: {
+ CfreeCgSwitchCase cases[15];
+ CfreeCgSwitch sw;
+ memset(cases, 0, sizeof cases);
+ if (in.ntargets == 0 || in.ntargets > 16u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: bad br_table target count");
+ for (uint32_t k = 0; k + 1u < in.ntargets; ++k) {
+ uint32_t idx;
+ if (in.targets[k] >= ncontrol)
+ wasm_error(c, wasm_loc(0, 0), "wasm: branch depth out of range");
+ idx = ncontrol - 1u - in.targets[k];
+ cases[k].value = k;
+ cases[k].label = control[idx].kind == WASM_INSN_LOOP
+ ? control[idx].start
+ : control[idx].end;
}
+ if (in.targets[in.ntargets - 1u] >= ncontrol)
+ wasm_error(c, wasm_loc(0, 0), "wasm: branch depth out of range");
+ memset(&sw, 0, sizeof sw);
+ sw.selector_type = b.id[CFREE_CG_BUILTIN_I32];
+ sw.cases = cases;
+ sw.ncases = in.ntargets - 1u;
+ sw.default_label =
+ control[ncontrol - 1u - in.targets[in.ntargets - 1u]].kind ==
+ WASM_INSN_LOOP
+ ? control[ncontrol - 1u - in.targets[in.ntargets - 1u]].start
+ : control[ncontrol - 1u - in.targets[in.ntargets - 1u]].end;
+ sw.hint = CFREE_CG_SWITCH_BRANCH_CHAIN;
+ cfree_cg_switch(cg, sw);
+ break;
}
- cfree_cg_label_place(cg, trap_label);
- wasm_cg_trap(cg);
- cfree_cg_label_place(cg, done_label);
- if (t->nresults) {
+ case WASM_INSN_SELECT: {
+ CfreeCgTypeId ty = wasm_cg_type(c, b, (WasmValType)in.type);
+ CfreeCgMemAccess mem = wasm_cg_mem(c, b, (WasmValType)in.type);
+ CfreeCgLocalAttrs attrs;
+ CfreeCgLocal lhs, rhs, cond, result;
+ CfreeCgLabel else_label = cfree_cg_label_new(cg);
+ CfreeCgLabel end_label = cfree_cg_label_new(cg);
+ memset(&attrs, 0, sizeof attrs);
+ attrs.flags = CFREE_CG_LOCAL_COMPILER_TEMP;
+ lhs = cfree_cg_local(cg, ty, attrs);
+ rhs = cfree_cg_local(cg, ty, attrs);
+ result = cfree_cg_local(cg, ty, attrs);
+ cond = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
+
+ cfree_cg_push_local(cg, cond);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_push_local(cg, rhs);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, mem);
+ cfree_cg_push_local(cg, lhs);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, mem);
+
+ cfree_cg_push_local(cg, cond);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_branch_false(cg, else_label);
cfree_cg_push_local(cg, result);
- cfree_cg_load(cg, wasm_cg_mem(c, b, t->results[0]));
+ cfree_cg_push_local(cg, lhs);
+ cfree_cg_load(cg, mem);
+ cfree_cg_store(cg, mem);
+ cfree_cg_jump(cg, end_label);
+ cfree_cg_label_place(cg, else_label);
+ cfree_cg_push_local(cg, result);
+ cfree_cg_push_local(cg, rhs);
+ cfree_cg_load(cg, mem);
+ cfree_cg_store(cg, mem);
+ cfree_cg_label_place(cg, end_label);
+ cfree_cg_push_local(cg, result);
+ cfree_cg_load(cg, mem);
+ } break;
+ case WASM_INSN_I32_CONST:
+ cfree_cg_push_int(cg, (uint64_t)(uint32_t)in.imm,
+ b.id[CFREE_CG_BUILTIN_I32]);
+ break;
+ case WASM_INSN_I64_CONST:
+ cfree_cg_push_int(cg, (uint64_t)in.imm, b.id[CFREE_CG_BUILTIN_I64]);
+ break;
+ case WASM_INSN_F32_CONST:
+ cfree_cg_push_float(cg, in.fp, b.id[CFREE_CG_BUILTIN_F32]);
+ break;
+ case WASM_INSN_F64_CONST:
+ cfree_cg_push_float(cg, in.fp, b.id[CFREE_CG_BUILTIN_F64]);
+ break;
+ case WASM_INSN_LOCAL_GET: {
+ uint32_t index = (uint32_t)in.imm;
+ cfree_cg_push_local(cg, locals[index]);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
+ break;
}
- break;
- }
- case WASM_INSN_GLOBAL_GET: {
- uint32_t index = (uint32_t)in.imm;
- wasm_cg_push_global_lvalue(cg, &rt, instance_local, index);
- cfree_cg_load(cg, wasm_cg_mem(c, b, m->globals[index].type));
- break;
- }
- case WASM_INSN_GLOBAL_SET: {
- uint32_t index = (uint32_t)in.imm;
- wasm_cg_push_global_lvalue(cg, &rt, instance_local, index);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, m->globals[index].type));
- break;
- }
- case WASM_INSN_RETURN:
- if (f->nresults)
- cfree_cg_ret(cg);
- else
- cfree_cg_ret_void(cg);
- break;
- case WASM_INSN_DROP:
- cfree_cg_drop(cg);
- break;
- case WASM_INSN_MEMORY_SIZE:
- wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- break;
- case WASM_INSN_MEMORY_GROW: {
- CfreeCgLocalAttrs attrs;
- CfreeCgLocal delta, old_pages, grow_result;
- CfreeCgLabel fail = cfree_cg_label_new(cg);
- CfreeCgLabel done = cfree_cg_label_new(cg);
- CfreeCgTypeId i32 = b.id[CFREE_CG_BUILTIN_I32];
- memset(&attrs, 0, sizeof attrs);
- attrs.flags = CFREE_CG_LOCAL_COMPILER_TEMP;
- delta = cfree_cg_local(cg, i32, attrs);
- old_pages = cfree_cg_local(cg, i32, attrs);
- grow_result = cfree_cg_local(cg, i32, attrs);
- cfree_cg_push_local(cg, delta);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_push_local(cg, old_pages);
- wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ case WASM_INSN_LOCAL_SET: {
+ uint32_t index = (uint32_t)in.imm;
+ cfree_cg_push_local(cg, locals[index]);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
+ break;
+ }
+ case WASM_INSN_LOCAL_TEE: {
+ uint32_t index = (uint32_t)in.imm;
+ cfree_cg_dup(cg);
+ cfree_cg_push_local(cg, locals[index]);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, wasm_func_local_type(f, index)));
+ break;
+ }
+ case WASM_INSN_CALL:
+ wasm_cg_call_func(c, cg, b, &m->funcs[in.imm], &rt, syms[in.imm],
+ func_types[in.imm], instance_local,
+ (uint32_t)in.imm);
+ break;
+ case WASM_INSN_CALL_INDIRECT: {
+ const WasmFuncType* t = &m->types[in.imm];
+ CfreeCgLocalAttrs attrs;
+ CfreeCgLocal selector, callee, args[16], result = CFREE_CG_LOCAL_NONE;
+ CfreeCgLabel ok;
+ CfreeCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32);
+ CfreeCgFuncParam indirect_params[17];
+ CfreeCgFuncSig indirect_sig;
+ CfreeCgTypeId indirect_func_type;
+ memset(&attrs, 0, sizeof attrs);
+ attrs.flags = CFREE_CG_LOCAL_COMPILER_TEMP;
+ if (t->nparams > 16u)
+ wasm_error(c, wasm_loc(0, 0), "wasm: too many call_indirect args");
+ memset(indirect_params, 0, sizeof indirect_params);
+ indirect_params[0].type = rt.instance_ptr_ty;
+ for (uint32_t p = 0; p < t->nparams; ++p)
+ indirect_params[p + 1u].type = wasm_cg_type(c, b, t->params[p]);
+ memset(&indirect_sig, 0, sizeof indirect_sig);
+ indirect_sig.ret = t->nresults ? wasm_cg_type(c, b, t->results[0])
+ : b.id[CFREE_CG_BUILTIN_VOID];
+ indirect_sig.params = indirect_params;
+ indirect_sig.nparams = t->nparams + 1u;
+ indirect_sig.call_conv = CFREE_CG_CC_TARGET_C;
+ indirect_func_type = cfree_cg_type_func(c, indirect_sig);
+ selector = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
+ callee = cfree_cg_local(cg, rt.void_ptr_ty, attrs);
+ if (t->nresults)
+ result =
+ cfree_cg_local(cg, wasm_cg_type(c, b, t->results[0]), attrs);
+ cfree_cg_push_local(cg, selector);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, i32_mem);
+ for (uint32_t p = 0; p < t->nparams; ++p) {
+ uint32_t param = t->nparams - 1u - p;
+ args[param] =
+ cfree_cg_local(cg, wasm_cg_type(c, b, t->params[param]), attrs);
+ cfree_cg_push_local(cg, args[param]);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, t->params[param]));
+ }
- cfree_cg_push_local(cg, delta);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- wasm_cg_push_memory_max_lvalue(cg, &rt, instance_local);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_push_local(cg, old_pages);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
- cfree_cg_int_cmp(cg, CFREE_CG_INT_LE_U);
- cfree_cg_branch_false(cg, fail);
-
- wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local);
- cfree_cg_push_local(cg, old_pages);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_push_local(cg, delta);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_push_local(cg, grow_result);
- cfree_cg_push_local(cg, old_pages);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_jump(cg, done);
- cfree_cg_label_place(cg, fail);
- cfree_cg_push_local(cg, grow_result);
- cfree_cg_push_int(cg, UINT64_C(0xffffffff), i32);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_label_place(cg, done);
- cfree_cg_push_local(cg, grow_result);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- break;
- }
- case WASM_INSN_I32_LOAD:
- case WASM_INSN_I64_LOAD:
- case WASM_INSN_I32_LOAD8_S:
- case WASM_INSN_I32_LOAD8_U:
- case WASM_INSN_I32_LOAD16_S:
- case WASM_INSN_I32_LOAD16_U:
- case WASM_INSN_I64_LOAD8_S:
- case WASM_INSN_I64_LOAD8_U:
- case WASM_INSN_I64_LOAD16_S:
- case WASM_INSN_I64_LOAD16_U:
- case WASM_INSN_I64_LOAD32_S:
- case WASM_INSN_I64_LOAD32_U: {
- CfreeCgTypeId storage = wasm_load_storage_type(b, in.kind);
- CfreeCgTypeId result =
- wasm_cg_type(c, b, wasm_load_result_type(in.kind));
- CfreeCgMemAccess mem;
- memset(&mem, 0, sizeof mem);
- mem.type = storage;
- mem.align = in.align;
- wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
- wasm_cg_memory_lvalue(cg, &rt, instance_local, (uint32_t)in.imm);
- cfree_cg_load(cg, mem);
- if (storage != result) {
- if (in.kind == WASM_INSN_I32_LOAD8_S ||
- in.kind == WASM_INSN_I32_LOAD16_S ||
- in.kind == WASM_INSN_I64_LOAD8_S ||
- in.kind == WASM_INSN_I64_LOAD16_S ||
- in.kind == WASM_INSN_I64_LOAD32_S)
- cfree_cg_sext(cg, result);
+ ok = cfree_cg_label_new(cg);
+ cfree_cg_push_local(cg, selector);
+ cfree_cg_load(cg, i32_mem);
+ wasm_cg_push_table_lvalue(cg, &rt, instance_local, in.align);
+ cfree_cg_field(cg, rt.table_len_field);
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_int_cmp(cg, CFREE_CG_INT_LT_U);
+ cfree_cg_branch_true(cg, ok);
+ wasm_cg_trap_table(cg);
+ cfree_cg_label_place(cg, ok);
+
+ ok = cfree_cg_label_new(cg);
+ cfree_cg_push_local(cg, callee);
+ wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local, in.align,
+ selector, i32_mem);
+ cfree_cg_field(cg, rt.table_entry_fn_field);
+ cfree_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty));
+ cfree_cg_store(cg, wasm_cg_mem_type(rt.void_ptr_ty));
+ cfree_cg_push_local(cg, callee);
+ cfree_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty));
+ cfree_cg_push_null(cg, rt.void_ptr_ty);
+ cfree_cg_int_cmp(cg, CFREE_CG_INT_NE);
+ cfree_cg_branch_true(cg, ok);
+ wasm_cg_trap_table(cg);
+ cfree_cg_label_place(cg, ok);
+
+ ok = cfree_cg_label_new(cg);
+ wasm_cg_push_table_entry_lvalue(cg, &rt, instance_local, in.align,
+ selector, i32_mem);
+ cfree_cg_field(cg, rt.table_entry_typeidx_field);
+ cfree_cg_load(cg, i32_mem);
+ cfree_cg_push_int(cg, (uint32_t)in.imm, b.id[CFREE_CG_BUILTIN_I32]);
+ cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
+ cfree_cg_branch_true(cg, ok);
+ wasm_cg_trap_signature(cg);
+ cfree_cg_label_place(cg, ok);
+
+ cfree_cg_push_local(cg, callee);
+ cfree_cg_load(cg, wasm_cg_mem_type(rt.void_ptr_ty));
+ cfree_cg_bitcast(cg, cfree_cg_type_ptr(c, indirect_func_type, 0));
+ cfree_cg_push_local(cg, instance_local);
+ cfree_cg_load(cg, wasm_cg_mem_type(rt.instance_ptr_ty));
+ for (uint32_t p = 0; p < t->nparams; ++p) {
+ cfree_cg_push_local(cg, args[p]);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, t->params[p]));
+ }
+ cfree_cg_call(cg, t->nparams + 1u, indirect_func_type,
+ (CfreeCgCallAttrs){0});
+ if (t->nresults) {
+ cfree_cg_push_local(cg, result);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, t->results[0]));
+ cfree_cg_push_local(cg, result);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, t->results[0]));
+ }
+ break;
+ }
+ case WASM_INSN_GLOBAL_GET: {
+ uint32_t index = (uint32_t)in.imm;
+ wasm_cg_push_global_value_lvalue(c, cg, b, &rt, instance_local, m,
+ index);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, m->globals[index].type));
+ break;
+ }
+ case WASM_INSN_GLOBAL_SET: {
+ uint32_t index = (uint32_t)in.imm;
+ wasm_cg_push_global_value_lvalue(c, cg, b, &rt, instance_local, m,
+ index);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, m->globals[index].type));
+ break;
+ }
+ case WASM_INSN_RETURN:
+ if (f->nresults)
+ cfree_cg_ret(cg);
else
- cfree_cg_zext(cg, result);
+ cfree_cg_ret_void(cg);
+ break;
+ case WASM_INSN_DROP:
+ cfree_cg_drop(cg);
+ break;
+ case WASM_INSN_MEMORY_SIZE:
+ wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ break;
+ case WASM_INSN_MEMORY_GROW: {
+ CfreeCgLocalAttrs attrs;
+ CfreeCgLocal delta, old_pages, grow_result;
+ CfreeCgLabel fail = cfree_cg_label_new(cg);
+ CfreeCgLabel done = cfree_cg_label_new(cg);
+ CfreeCgTypeId i32 = b.id[CFREE_CG_BUILTIN_I32];
+ memset(&attrs, 0, sizeof attrs);
+ attrs.flags = CFREE_CG_LOCAL_COMPILER_TEMP;
+ delta = cfree_cg_local(cg, i32, attrs);
+ old_pages = cfree_cg_local(cg, i32, attrs);
+ grow_result = cfree_cg_local(cg, i32, attrs);
+ cfree_cg_push_local(cg, delta);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_push_local(cg, old_pages);
+ wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+
+ cfree_cg_push_local(cg, delta);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ wasm_cg_push_memory_max_lvalue(cg, &rt, instance_local);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_push_local(cg, old_pages);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
+ cfree_cg_int_cmp(cg, CFREE_CG_INT_LE_U);
+ cfree_cg_branch_false(cg, fail);
+
+ wasm_cg_push_memory_pages_lvalue(cg, &rt, instance_local);
+ cfree_cg_push_local(cg, old_pages);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_push_local(cg, delta);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_push_local(cg, grow_result);
+ cfree_cg_push_local(cg, old_pages);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_jump(cg, done);
+ cfree_cg_label_place(cg, fail);
+ cfree_cg_push_local(cg, grow_result);
+ cfree_cg_push_int(cg, UINT64_C(0xffffffff), i32);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_label_place(cg, done);
+ cfree_cg_push_local(cg, grow_result);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ break;
}
- break;
- }
- case WASM_INSN_I32_STORE:
- case WASM_INSN_I64_STORE:
- case WASM_INSN_I32_STORE8:
- case WASM_INSN_I32_STORE16:
- case WASM_INSN_I64_STORE8:
- case WASM_INSN_I64_STORE16:
- case WASM_INSN_I64_STORE32: {
- CfreeCgTypeId storage = wasm_store_storage_type(b, in.kind);
- CfreeCgTypeId value_type =
- wasm_cg_type(c, b, wasm_store_value_type(in.kind));
- CfreeCgMemAccess mem;
- CfreeCgLocalAttrs attrs;
- CfreeCgLocal addr_tmp, value_tmp;
- memset(&mem, 0, sizeof mem);
- mem.type = storage;
- mem.align = in.align;
- if (storage != value_type)
- cfree_cg_trunc(cg, storage);
- memset(&attrs, 0, sizeof attrs);
- attrs.flags = CFREE_CG_LOCAL_COMPILER_TEMP;
- value_tmp = cfree_cg_local(cg, storage, attrs);
- addr_tmp = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
- cfree_cg_push_local(cg, value_tmp);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, mem);
- wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
- cfree_cg_push_local(cg, addr_tmp);
- cfree_cg_swap(cg);
- cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- cfree_cg_push_local(cg, addr_tmp);
- cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
- wasm_cg_memory_lvalue(cg, &rt, instance_local, (uint32_t)in.imm);
- cfree_cg_push_local(cg, value_tmp);
- cfree_cg_load(cg, mem);
- cfree_cg_store(cg, mem);
- break;
- }
- case WASM_INSN_I32_ADD:
- case WASM_INSN_I64_ADD:
- cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
- break;
- case WASM_INSN_I32_SUB:
- case WASM_INSN_I64_SUB:
- cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
- break;
- case WASM_INSN_I32_MUL:
- case WASM_INSN_I64_MUL:
- cfree_cg_int_binop(cg, CFREE_CG_INT_MUL, 0);
- break;
- case WASM_INSN_I32_DIV_S:
- wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I32, CFREE_CG_INT_SDIV);
- break;
- case WASM_INSN_I32_DIV_U:
- wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I32, CFREE_CG_INT_UDIV);
- break;
- case WASM_INSN_I32_REM_S:
- wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I32, CFREE_CG_INT_SREM);
- break;
- case WASM_INSN_I32_REM_U:
- wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I32, CFREE_CG_INT_UREM);
- break;
- case WASM_INSN_I64_DIV_S:
- wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I64, CFREE_CG_INT_SDIV);
- break;
- case WASM_INSN_I64_DIV_U:
- wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I64, CFREE_CG_INT_UDIV);
- break;
- case WASM_INSN_I64_REM_S:
- wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I64, CFREE_CG_INT_SREM);
- break;
- case WASM_INSN_I64_REM_U:
- wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I64, CFREE_CG_INT_UREM);
- break;
- case WASM_INSN_I32_AND:
- case WASM_INSN_I64_AND:
- cfree_cg_int_binop(cg, CFREE_CG_INT_AND, 0);
- break;
- case WASM_INSN_I32_OR:
- case WASM_INSN_I64_OR:
- cfree_cg_int_binop(cg, CFREE_CG_INT_OR, 0);
- break;
- case WASM_INSN_I32_XOR:
- case WASM_INSN_I64_XOR:
- cfree_cg_int_binop(cg, CFREE_CG_INT_XOR, 0);
- break;
- case WASM_INSN_I32_SHL:
- case WASM_INSN_I64_SHL:
- cfree_cg_int_binop(cg, CFREE_CG_INT_SHL, 0);
- break;
- case WASM_INSN_I32_SHR_S:
- case WASM_INSN_I64_SHR_S:
- cfree_cg_int_binop(cg, CFREE_CG_INT_ASHR, 0);
- break;
- case WASM_INSN_I32_SHR_U:
- case WASM_INSN_I64_SHR_U:
- cfree_cg_int_binop(cg, CFREE_CG_INT_LSHR, 0);
- break;
- case WASM_INSN_I32_ROTL:
- wasm_cg_rotate(c, cg, b, WASM_VAL_I32, 0);
- break;
- case WASM_INSN_I32_ROTR:
- wasm_cg_rotate(c, cg, b, WASM_VAL_I32, 1);
- break;
- case WASM_INSN_I64_ROTL:
- wasm_cg_rotate(c, cg, b, WASM_VAL_I64, 0);
- break;
- case WASM_INSN_I64_ROTR:
- wasm_cg_rotate(c, cg, b, WASM_VAL_I64, 1);
- break;
- case WASM_INSN_I32_CLZ:
- case WASM_INSN_I64_CLZ:
- cfree_cg_intrinsic(cg, CFREE_CG_INTRIN_CLZ, 1,
- in.kind == WASM_INSN_I32_CLZ
- ? b.id[CFREE_CG_BUILTIN_I32]
- : b.id[CFREE_CG_BUILTIN_I64]);
- break;
- case WASM_INSN_I32_CTZ:
- case WASM_INSN_I64_CTZ:
- cfree_cg_intrinsic(cg, CFREE_CG_INTRIN_CTZ, 1,
- in.kind == WASM_INSN_I32_CTZ
- ? b.id[CFREE_CG_BUILTIN_I32]
- : b.id[CFREE_CG_BUILTIN_I64]);
- break;
- case WASM_INSN_I32_POPCNT:
- case WASM_INSN_I64_POPCNT:
- cfree_cg_intrinsic(cg, CFREE_CG_INTRIN_POPCOUNT, 1,
- in.kind == WASM_INSN_I32_POPCNT
- ? b.id[CFREE_CG_BUILTIN_I32]
- : b.id[CFREE_CG_BUILTIN_I64]);
- break;
- case WASM_INSN_I32_EQZ:
- cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I32]);
- cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
- cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I32]);
- break;
- case WASM_INSN_I64_EQZ:
- cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I64]);
- cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
- cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I32]);
- break;
- case WASM_INSN_I32_WRAP_I64:
- cfree_cg_trunc(cg, b.id[CFREE_CG_BUILTIN_I32]);
- break;
- case WASM_INSN_I64_EXTEND_I32_S:
- cfree_cg_sext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- break;
- case WASM_INSN_I64_EXTEND_I32_U:
- cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
- break;
- case WASM_INSN_I32_TRUNC_F32_S:
- case WASM_INSN_I32_TRUNC_F64_S:
- cfree_cg_float_to_sint(cg, b.id[CFREE_CG_BUILTIN_I32],
- CFREE_CG_ROUND_TOWARD_ZERO);
- break;
- case WASM_INSN_I32_TRUNC_F32_U:
- case WASM_INSN_I32_TRUNC_F64_U:
- cfree_cg_float_to_uint(cg, b.id[CFREE_CG_BUILTIN_I32],
- CFREE_CG_ROUND_TOWARD_ZERO);
- break;
- case WASM_INSN_I64_TRUNC_F32_S:
- case WASM_INSN_I64_TRUNC_F64_S:
- cfree_cg_float_to_sint(cg, b.id[CFREE_CG_BUILTIN_I64],
- CFREE_CG_ROUND_TOWARD_ZERO);
- break;
- case WASM_INSN_I64_TRUNC_F32_U:
- case WASM_INSN_I64_TRUNC_F64_U:
- cfree_cg_float_to_uint(cg, b.id[CFREE_CG_BUILTIN_I64],
- CFREE_CG_ROUND_TOWARD_ZERO);
- break;
- case WASM_INSN_F32_CONVERT_I32_S:
- case WASM_INSN_F32_CONVERT_I64_S:
- cfree_cg_sint_to_float(cg, b.id[CFREE_CG_BUILTIN_F32],
- CFREE_CG_ROUND_DEFAULT);
- break;
- case WASM_INSN_F32_CONVERT_I32_U:
- case WASM_INSN_F32_CONVERT_I64_U:
- cfree_cg_uint_to_float(cg, b.id[CFREE_CG_BUILTIN_F32],
- CFREE_CG_ROUND_DEFAULT);
- break;
- case WASM_INSN_F64_CONVERT_I32_S:
- case WASM_INSN_F64_CONVERT_I64_S:
- cfree_cg_sint_to_float(cg, b.id[CFREE_CG_BUILTIN_F64],
- CFREE_CG_ROUND_DEFAULT);
- break;
- case WASM_INSN_F64_CONVERT_I32_U:
- case WASM_INSN_F64_CONVERT_I64_U:
- cfree_cg_uint_to_float(cg, b.id[CFREE_CG_BUILTIN_F64],
- CFREE_CG_ROUND_DEFAULT);
- break;
- case WASM_INSN_F32_DEMOTE_F64:
- cfree_cg_fptrunc(cg, b.id[CFREE_CG_BUILTIN_F32]);
- break;
- case WASM_INSN_F64_PROMOTE_F32:
- cfree_cg_fpext(cg, b.id[CFREE_CG_BUILTIN_F64]);
- break;
- case WASM_INSN_I32_REINTERPRET_F32:
- cfree_cg_bitcast(cg, b.id[CFREE_CG_BUILTIN_I32]);
- break;
- case WASM_INSN_I64_REINTERPRET_F64:
- cfree_cg_bitcast(cg, b.id[CFREE_CG_BUILTIN_I64]);
- break;
- case WASM_INSN_F32_REINTERPRET_I32:
- cfree_cg_bitcast(cg, b.id[CFREE_CG_BUILTIN_F32]);
- break;
- case WASM_INSN_F64_REINTERPRET_I64:
- cfree_cg_bitcast(cg, b.id[CFREE_CG_BUILTIN_F64]);
- break;
- default: {
- CfreeCgIntCmpOp cmp;
- CfreeCgFpBinOp fp_bin;
- CfreeCgFpCmpOp fp_cmp;
- if (wasm_int_cmp_op(in.kind, &cmp)) {
- cfree_cg_int_cmp(cg, cmp);
+ case WASM_INSN_I32_LOAD:
+ case WASM_INSN_I64_LOAD:
+ case WASM_INSN_I32_LOAD8_S:
+ case WASM_INSN_I32_LOAD8_U:
+ case WASM_INSN_I32_LOAD16_S:
+ case WASM_INSN_I32_LOAD16_U:
+ case WASM_INSN_I64_LOAD8_S:
+ case WASM_INSN_I64_LOAD8_U:
+ case WASM_INSN_I64_LOAD16_S:
+ case WASM_INSN_I64_LOAD16_U:
+ case WASM_INSN_I64_LOAD32_S:
+ case WASM_INSN_I64_LOAD32_U: {
+ CfreeCgTypeId storage = wasm_load_storage_type(b, in.kind);
+ CfreeCgTypeId result =
+ wasm_cg_type(c, b, wasm_load_result_type(in.kind));
+ CfreeCgMemAccess mem;
+ memset(&mem, 0, sizeof mem);
+ mem.type = storage;
+ mem.align = in.align;
+ wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
+ wasm_cg_memory_lvalue(cg, &rt, instance_local, (uint32_t)in.imm);
+ cfree_cg_load(cg, mem);
+ if (storage != result) {
+ if (in.kind == WASM_INSN_I32_LOAD8_S ||
+ in.kind == WASM_INSN_I32_LOAD16_S ||
+ in.kind == WASM_INSN_I64_LOAD8_S ||
+ in.kind == WASM_INSN_I64_LOAD16_S ||
+ in.kind == WASM_INSN_I64_LOAD32_S)
+ cfree_cg_sext(cg, result);
+ else
+ cfree_cg_zext(cg, result);
+ }
+ break;
+ }
+ case WASM_INSN_I32_STORE:
+ case WASM_INSN_I64_STORE:
+ case WASM_INSN_I32_STORE8:
+ case WASM_INSN_I32_STORE16:
+ case WASM_INSN_I64_STORE8:
+ case WASM_INSN_I64_STORE16:
+ case WASM_INSN_I64_STORE32: {
+ CfreeCgTypeId storage = wasm_store_storage_type(b, in.kind);
+ CfreeCgTypeId value_type =
+ wasm_cg_type(c, b, wasm_store_value_type(in.kind));
+ CfreeCgMemAccess mem;
+ CfreeCgLocalAttrs attrs;
+ CfreeCgLocal addr_tmp, value_tmp;
+ memset(&mem, 0, sizeof mem);
+ mem.type = storage;
+ mem.align = in.align;
+ if (storage != value_type) cfree_cg_trunc(cg, storage);
+ memset(&attrs, 0, sizeof attrs);
+ attrs.flags = CFREE_CG_LOCAL_COMPILER_TEMP;
+ value_tmp = cfree_cg_local(cg, storage, attrs);
+ addr_tmp = cfree_cg_local(cg, b.id[CFREE_CG_BUILTIN_I32], attrs);
+ cfree_cg_push_local(cg, value_tmp);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, mem);
+ wasm_cg_memory_check(c, cg, b, m, &rt, instance_local, &in);
+ cfree_cg_push_local(cg, addr_tmp);
+ cfree_cg_swap(cg);
+ cfree_cg_store(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ cfree_cg_push_local(cg, addr_tmp);
+ cfree_cg_load(cg, wasm_cg_mem(c, b, WASM_VAL_I32));
+ wasm_cg_memory_lvalue(cg, &rt, instance_local, (uint32_t)in.imm);
+ cfree_cg_push_local(cg, value_tmp);
+ cfree_cg_load(cg, mem);
+ cfree_cg_store(cg, mem);
+ break;
+ }
+ case WASM_INSN_I32_ADD:
+ case WASM_INSN_I64_ADD:
+ cfree_cg_int_binop(cg, CFREE_CG_INT_ADD, 0);
+ break;
+ case WASM_INSN_I32_SUB:
+ case WASM_INSN_I64_SUB:
+ cfree_cg_int_binop(cg, CFREE_CG_INT_SUB, 0);
+ break;
+ case WASM_INSN_I32_MUL:
+ case WASM_INSN_I64_MUL:
+ cfree_cg_int_binop(cg, CFREE_CG_INT_MUL, 0);
+ break;
+ case WASM_INSN_I32_DIV_S:
+ wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I32, CFREE_CG_INT_SDIV);
+ break;
+ case WASM_INSN_I32_DIV_U:
+ wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I32, CFREE_CG_INT_UDIV);
+ break;
+ case WASM_INSN_I32_REM_S:
+ wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I32, CFREE_CG_INT_SREM);
+ break;
+ case WASM_INSN_I32_REM_U:
+ wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I32, CFREE_CG_INT_UREM);
+ break;
+ case WASM_INSN_I64_DIV_S:
+ wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I64, CFREE_CG_INT_SDIV);
+ break;
+ case WASM_INSN_I64_DIV_U:
+ wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I64, CFREE_CG_INT_UDIV);
+ break;
+ case WASM_INSN_I64_REM_S:
+ wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I64, CFREE_CG_INT_SREM);
+ break;
+ case WASM_INSN_I64_REM_U:
+ wasm_cg_checked_divrem(c, cg, b, WASM_VAL_I64, CFREE_CG_INT_UREM);
+ break;
+ case WASM_INSN_I32_AND:
+ case WASM_INSN_I64_AND:
+ cfree_cg_int_binop(cg, CFREE_CG_INT_AND, 0);
+ break;
+ case WASM_INSN_I32_OR:
+ case WASM_INSN_I64_OR:
+ cfree_cg_int_binop(cg, CFREE_CG_INT_OR, 0);
+ break;
+ case WASM_INSN_I32_XOR:
+ case WASM_INSN_I64_XOR:
+ cfree_cg_int_binop(cg, CFREE_CG_INT_XOR, 0);
+ break;
+ case WASM_INSN_I32_SHL:
+ case WASM_INSN_I64_SHL:
+ cfree_cg_int_binop(cg, CFREE_CG_INT_SHL, 0);
+ break;
+ case WASM_INSN_I32_SHR_S:
+ case WASM_INSN_I64_SHR_S:
+ cfree_cg_int_binop(cg, CFREE_CG_INT_ASHR, 0);
+ break;
+ case WASM_INSN_I32_SHR_U:
+ case WASM_INSN_I64_SHR_U:
+ cfree_cg_int_binop(cg, CFREE_CG_INT_LSHR, 0);
+ break;
+ case WASM_INSN_I32_ROTL:
+ wasm_cg_rotate(c, cg, b, WASM_VAL_I32, 0);
+ break;
+ case WASM_INSN_I32_ROTR:
+ wasm_cg_rotate(c, cg, b, WASM_VAL_I32, 1);
+ break;
+ case WASM_INSN_I64_ROTL:
+ wasm_cg_rotate(c, cg, b, WASM_VAL_I64, 0);
+ break;
+ case WASM_INSN_I64_ROTR:
+ wasm_cg_rotate(c, cg, b, WASM_VAL_I64, 1);
+ break;
+ case WASM_INSN_I32_CLZ:
+ case WASM_INSN_I64_CLZ:
+ cfree_cg_intrinsic(cg, CFREE_CG_INTRIN_CLZ, 1,
+ in.kind == WASM_INSN_I32_CLZ
+ ? b.id[CFREE_CG_BUILTIN_I32]
+ : b.id[CFREE_CG_BUILTIN_I64]);
+ break;
+ case WASM_INSN_I32_CTZ:
+ case WASM_INSN_I64_CTZ:
+ cfree_cg_intrinsic(cg, CFREE_CG_INTRIN_CTZ, 1,
+ in.kind == WASM_INSN_I32_CTZ
+ ? b.id[CFREE_CG_BUILTIN_I32]
+ : b.id[CFREE_CG_BUILTIN_I64]);
+ break;
+ case WASM_INSN_I32_POPCNT:
+ case WASM_INSN_I64_POPCNT:
+ cfree_cg_intrinsic(cg, CFREE_CG_INTRIN_POPCOUNT, 1,
+ in.kind == WASM_INSN_I32_POPCNT
+ ? b.id[CFREE_CG_BUILTIN_I32]
+ : b.id[CFREE_CG_BUILTIN_I64]);
+ break;
+ case WASM_INSN_I32_EQZ:
+ cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I32]);
+ cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I32]);
- } else if (wasm_fp_binop(in.kind, &fp_bin)) {
- cfree_cg_fp_binop(cg, fp_bin, CFREE_CG_FP_NONE);
- } else if (wasm_fp_cmp_op(in.kind, &fp_cmp)) {
- cfree_cg_fp_cmp(cg, fp_cmp);
+ break;
+ case WASM_INSN_I64_EQZ:
+ cfree_cg_push_int(cg, 0, b.id[CFREE_CG_BUILTIN_I64]);
+ cfree_cg_int_cmp(cg, CFREE_CG_INT_EQ);
cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I32]);
- } else {
- wasm_error(c, wasm_loc(0, 0), "wasm: unsupported instruction");
+ break;
+ case WASM_INSN_I32_WRAP_I64:
+ cfree_cg_trunc(cg, b.id[CFREE_CG_BUILTIN_I32]);
+ break;
+ case WASM_INSN_I64_EXTEND_I32_S:
+ cfree_cg_sext(cg, b.id[CFREE_CG_BUILTIN_I64]);
+ break;
+ case WASM_INSN_I64_EXTEND_I32_U:
+ cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I64]);
+ break;
+ case WASM_INSN_I32_TRUNC_F32_S:
+ case WASM_INSN_I32_TRUNC_F64_S:
+ cfree_cg_float_to_sint(cg, b.id[CFREE_CG_BUILTIN_I32],
+ CFREE_CG_ROUND_TOWARD_ZERO);
+ break;
+ case WASM_INSN_I32_TRUNC_F32_U:
+ case WASM_INSN_I32_TRUNC_F64_U:
+ cfree_cg_float_to_uint(cg, b.id[CFREE_CG_BUILTIN_I32],
+ CFREE_CG_ROUND_TOWARD_ZERO);
+ break;
+ case WASM_INSN_I64_TRUNC_F32_S:
+ case WASM_INSN_I64_TRUNC_F64_S:
+ cfree_cg_float_to_sint(cg, b.id[CFREE_CG_BUILTIN_I64],
+ CFREE_CG_ROUND_TOWARD_ZERO);
+ break;
+ case WASM_INSN_I64_TRUNC_F32_U:
+ case WASM_INSN_I64_TRUNC_F64_U:
+ cfree_cg_float_to_uint(cg, b.id[CFREE_CG_BUILTIN_I64],
+ CFREE_CG_ROUND_TOWARD_ZERO);
+ break;
+ case WASM_INSN_F32_CONVERT_I32_S:
+ case WASM_INSN_F32_CONVERT_I64_S:
+ cfree_cg_sint_to_float(cg, b.id[CFREE_CG_BUILTIN_F32],
+ CFREE_CG_ROUND_DEFAULT);
+ break;
+ case WASM_INSN_F32_CONVERT_I32_U:
+ case WASM_INSN_F32_CONVERT_I64_U:
+ cfree_cg_uint_to_float(cg, b.id[CFREE_CG_BUILTIN_F32],
+ CFREE_CG_ROUND_DEFAULT);
+ break;
+ case WASM_INSN_F64_CONVERT_I32_S:
+ case WASM_INSN_F64_CONVERT_I64_S:
+ cfree_cg_sint_to_float(cg, b.id[CFREE_CG_BUILTIN_F64],
+ CFREE_CG_ROUND_DEFAULT);
+ break;
+ case WASM_INSN_F64_CONVERT_I32_U:
+ case WASM_INSN_F64_CONVERT_I64_U:
+ cfree_cg_uint_to_float(cg, b.id[CFREE_CG_BUILTIN_F64],
+ CFREE_CG_ROUND_DEFAULT);
+ break;
+ case WASM_INSN_F32_DEMOTE_F64:
+ cfree_cg_fptrunc(cg, b.id[CFREE_CG_BUILTIN_F32]);
+ break;
+ case WASM_INSN_F64_PROMOTE_F32:
+ cfree_cg_fpext(cg, b.id[CFREE_CG_BUILTIN_F64]);
+ break;
+ case WASM_INSN_I32_REINTERPRET_F32:
+ cfree_cg_bitcast(cg, b.id[CFREE_CG_BUILTIN_I32]);
+ break;
+ case WASM_INSN_I64_REINTERPRET_F64:
+ cfree_cg_bitcast(cg, b.id[CFREE_CG_BUILTIN_I64]);
+ break;
+ case WASM_INSN_F32_REINTERPRET_I32:
+ cfree_cg_bitcast(cg, b.id[CFREE_CG_BUILTIN_F32]);
+ break;
+ case WASM_INSN_F64_REINTERPRET_I64:
+ cfree_cg_bitcast(cg, b.id[CFREE_CG_BUILTIN_F64]);
+ break;
+ default: {
+ CfreeCgIntCmpOp cmp;
+ CfreeCgFpBinOp fp_bin;
+ CfreeCgFpCmpOp fp_cmp;
+ if (wasm_int_cmp_op(in.kind, &cmp)) {
+ cfree_cg_int_cmp(cg, cmp);
+ cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I32]);
+ } else if (wasm_fp_binop(in.kind, &fp_bin)) {
+ cfree_cg_fp_binop(cg, fp_bin, CFREE_CG_FP_NONE);
+ } else if (wasm_fp_cmp_op(in.kind, &fp_cmp)) {
+ cfree_cg_fp_cmp(cg, fp_cmp);
+ cfree_cg_zext(cg, b.id[CFREE_CG_BUILTIN_I32]);
+ } else {
+ wasm_error(c, wasm_loc(0, 0), "wasm: unsupported instruction");
+ }
+ break;
}
- break;
- }
}
}
if (f->nresults)
@@ -5560,21 +5712,18 @@ static void wasm_emit_cg(CfreeCompiler *c, const CfreeCompileOptions *opts,
cfree_cg_free(cg);
}
-static void write_byte(CfreeWriter *w, uint8_t b) {
- w->write(w, &b, 1);
-}
+static void write_byte(CfreeWriter* w, uint8_t b) { w->write(w, &b, 1); }
-static void write_uleb(CfreeWriter *w, uint64_t v) {
+static void write_uleb(CfreeWriter* w, uint64_t v) {
do {
uint8_t b = (uint8_t)(v & 0x7fu);
v >>= 7u;
- if (v)
- b |= 0x80u;
+ if (v) b |= 0x80u;
write_byte(w, b);
} while (v);
}
-static void write_sleb(CfreeWriter *w, int64_t v) {
+static void write_sleb(CfreeWriter* w, int64_t v) {
int more = 1;
while (more) {
uint8_t b = (uint8_t)(v & 0x7f);
@@ -5588,35 +5737,32 @@ static void write_sleb(CfreeWriter *w, int64_t v) {
}
}
-static void write_f32(CfreeWriter *w, double value) {
+static void write_f32(CfreeWriter* w, double value) {
float f = (float)value;
uint32_t bits;
memcpy(&bits, &f, sizeof bits);
- for (uint32_t i = 0; i < 4u; ++i)
- write_byte(w, (uint8_t)(bits >> (i * 8u)));
+ for (uint32_t i = 0; i < 4u; ++i) write_byte(w, (uint8_t)(bits >> (i * 8u)));
}
-static void write_f64(CfreeWriter *w, double value) {
+static void write_f64(CfreeWriter* w, double value) {
uint64_t bits;
memcpy(&bits, &value, sizeof bits);
- for (uint32_t i = 0; i < 8u; ++i)
- write_byte(w, (uint8_t)(bits >> (i * 8u)));
+ for (uint32_t i = 0; i < 8u; ++i) write_byte(w, (uint8_t)(bits >> (i * 8u)));
}
-static void write_name(CfreeWriter *w, const char *s) {
+static void write_name(CfreeWriter* w, const char* s) {
size_t n = strlen(s);
write_uleb(w, n);
w->write(w, s, n);
}
-static void encode_section(CfreeHeap *h, CfreeWriter *out, uint8_t id,
- void (*fn)(CfreeWriter *, const WasmModule *),
- const WasmModule *m) {
- CfreeWriter *tmp = cfree_writer_mem(h);
+static void encode_section(CfreeHeap* h, CfreeWriter* out, uint8_t id,
+ void (*fn)(CfreeWriter*, const WasmModule*),
+ const WasmModule* m) {
+ CfreeWriter* tmp = cfree_writer_mem(h);
size_t len;
- const uint8_t *bytes;
- if (!tmp)
- return;
+ const uint8_t* bytes;
+ if (!tmp) return;
fn(tmp, m);
bytes = cfree_writer_mem_bytes(tmp, &len);
write_byte(out, id);
@@ -5625,56 +5771,47 @@ static void encode_section(CfreeHeap *h, CfreeWriter *out, uint8_t id,
cfree_writer_close(tmp);
}
-static void enc_type(CfreeWriter *w, const WasmModule *m) {
+static void enc_type(CfreeWriter* w, const WasmModule* m) {
uint32_t i, j;
write_uleb(w, m->ntypes);
for (i = 0; i < m->ntypes; ++i) {
- const WasmFuncType *f = &m->types[i];
+ const WasmFuncType* f = &m->types[i];
write_byte(w, 0x60);
write_uleb(w, f->nparams);
- for (j = 0; j < f->nparams; ++j)
- write_byte(w, (uint8_t)f->params[j]);
+ for (j = 0; j < f->nparams; ++j) write_byte(w, (uint8_t)f->params[j]);
write_uleb(w, f->nresults);
- for (j = 0; j < f->nresults; ++j)
- write_byte(w, (uint8_t)f->results[j]);
+ for (j = 0; j < f->nresults; ++j) write_byte(w, (uint8_t)f->results[j]);
}
}
-static void write_limits(CfreeWriter *w, uint32_t min, uint32_t max,
+static void write_limits(CfreeWriter* w, uint32_t min, uint32_t max,
int has_max) {
write_byte(w, has_max ? 1 : 0);
write_uleb(w, min);
- if (has_max)
- write_uleb(w, max);
+ if (has_max) write_uleb(w, max);
}
-static void enc_import(CfreeWriter *w, const WasmModule *m) {
+static void enc_import(CfreeWriter* w, const WasmModule* m) {
uint32_t i, n = 0;
for (i = 0; i < m->nfuncs; ++i)
- if (m->funcs[i].is_import)
- n++;
+ if (m->funcs[i].is_import) n++;
for (i = 0; i < m->ntables; ++i)
- if (m->tables[i].is_import)
- n++;
- if (m->has_memory && m->memory.is_import)
- n++;
+ if (m->tables[i].is_import) n++;
+ if (m->has_memory && m->memory.is_import) n++;
for (i = 0; i < m->nglobals; ++i)
- if (m->globals[i].is_import)
- n++;
+ if (m->globals[i].is_import) n++;
write_uleb(w, n);
for (i = 0; i < m->nfuncs; ++i) {
- const WasmFunc *f = &m->funcs[i];
- if (!f->is_import)
- continue;
+ const WasmFunc* f = &m->funcs[i];
+ if (!f->is_import) continue;
write_name(w, f->import_module ? f->import_module : "");
write_name(w, f->import_name ? f->import_name : "");
write_byte(w, 0);
write_uleb(w, f->typeidx);
}
for (i = 0; i < m->ntables; ++i) {
- const WasmTable *t = &m->tables[i];
- if (!t->is_import)
- continue;
+ const WasmTable* t = &m->tables[i];
+ if (!t->is_import) continue;
write_name(w, t->import_module ? t->import_module : "");
write_name(w, t->import_name ? t->import_name : "");
write_byte(w, 1);
@@ -5689,9 +5826,8 @@ static void enc_import(CfreeWriter *w, const WasmModule *m) {
m->memory.has_max);
}
for (i = 0; i < m->nglobals; ++i) {
- const WasmGlobal *g = &m->globals[i];
- if (!g->is_import)
- continue;
+ const WasmGlobal* g = &m->globals[i];
+ if (!g->is_import) continue;
write_name(w, g->import_module ? g->import_module : "");
write_name(w, g->import_name ? g->import_name : "");
write_byte(w, 3);
@@ -5700,35 +5836,29 @@ static void enc_import(CfreeWriter *w, const WasmModule *m) {
}
}
-static int wasm_module_has_imports(const WasmModule *m) {
+static int wasm_module_has_imports(const WasmModule* m) {
uint32_t i;
for (i = 0; i < m->nfuncs; ++i)
- if (m->funcs[i].is_import)
- return 1;
+ if (m->funcs[i].is_import) return 1;
for (i = 0; i < m->ntables; ++i)
- if (m->tables[i].is_import)
- return 1;
- if (m->has_memory && m->memory.is_import)
- return 1;
+ if (m->tables[i].is_import) return 1;
+ if (m->has_memory && m->memory.is_import) return 1;
for (i = 0; i < m->nglobals; ++i)
- if (m->globals[i].is_import)
- return 1;
+ if (m->globals[i].is_import) return 1;
return 0;
}
-static void enc_func(CfreeWriter *w, const WasmModule *m) {
+static void enc_func(CfreeWriter* w, const WasmModule* m) {
uint32_t i;
uint32_t n = 0;
for (i = 0; i < m->nfuncs; ++i)
- if (!m->funcs[i].is_import)
- n++;
+ if (!m->funcs[i].is_import) n++;
write_uleb(w, n);
for (i = 0; i < m->nfuncs; ++i)
- if (!m->funcs[i].is_import)
- write_uleb(w, m->funcs[i].typeidx);
+ if (!m->funcs[i].is_import) write_uleb(w, m->funcs[i].typeidx);
}
-static void enc_export(CfreeWriter *w, const WasmModule *m) {
+static void enc_export(CfreeWriter* w, const WasmModule* m) {
uint32_t i;
write_uleb(w, m->nexports);
for (i = 0; i < m->nexports; ++i) {
@@ -5738,7 +5868,7 @@ static void enc_export(CfreeWriter *w, const WasmModule *m) {
}
}
-static void enc_memory(CfreeWriter *w, const WasmModule *m) {
+static void enc_memory(CfreeWriter* w, const WasmModule* m) {
if (!m->has_memory) {
write_uleb(w, 0);
return;
@@ -5746,37 +5876,32 @@ static void enc_memory(CfreeWriter *w, const WasmModule *m) {
write_uleb(w, 1);
write_byte(w, m->memory.has_max ? 1 : 0);
write_uleb(w, m->memory.min_pages);
- if (m->memory.has_max)
- write_uleb(w, m->memory.max_pages);
+ if (m->memory.has_max) write_uleb(w, m->memory.max_pages);
}
static uint8_t wasm_opcode(uint8_t kind);
-static void enc_table(CfreeWriter *w, const WasmModule *m) {
+static void enc_table(CfreeWriter* w, const WasmModule* m) {
uint32_t i, n = 0;
for (i = 0; i < m->ntables; ++i)
- if (!m->tables[i].is_import)
- n++;
+ if (!m->tables[i].is_import) n++;
write_uleb(w, n);
for (i = 0; i < m->ntables; ++i) {
- const WasmTable *t = &m->tables[i];
- if (t->is_import)
- continue;
+ const WasmTable* t = &m->tables[i];
+ if (t->is_import) continue;
write_byte(w, (uint8_t)t->elem_type);
write_limits(w, t->min, t->max, t->has_max);
}
}
-static void enc_global(CfreeWriter *w, const WasmModule *m) {
+static void enc_global(CfreeWriter* w, const WasmModule* m) {
uint32_t i, n = 0;
for (i = 0; i < m->nglobals; ++i)
- if (!m->globals[i].is_import)
- n++;
+ if (!m->globals[i].is_import) n++;
write_uleb(w, n);
for (i = 0; i < m->nglobals; ++i) {
- const WasmGlobal *g = &m->globals[i];
- if (g->is_import)
- continue;
+ const WasmGlobal* g = &m->globals[i];
+ if (g->is_import) continue;
write_byte(w, (uint8_t)g->type);
write_byte(w, g->mutable_);
write_byte(w, wasm_opcode(g->init.kind));
@@ -5793,317 +5918,316 @@ static void enc_global(CfreeWriter *w, const WasmModule *m) {
static uint8_t wasm_opcode(uint8_t kind) {
switch (kind) {
- case WASM_INSN_UNREACHABLE:
- return 0x00;
- case WASM_INSN_NOP:
- return 0x01;
- case WASM_INSN_BLOCK:
- return 0x02;
- case WASM_INSN_LOOP:
- return 0x03;
- case WASM_INSN_IF:
- return 0x04;
- case WASM_INSN_ELSE:
- return 0x05;
- case WASM_INSN_END:
- return 0x0b;
- case WASM_INSN_BR:
- return 0x0c;
- case WASM_INSN_BR_IF:
- return 0x0d;
- case WASM_INSN_BR_TABLE:
- return 0x0e;
- case WASM_INSN_I32_CONST:
- return 0x41;
- case WASM_INSN_I64_CONST:
- return 0x42;
- case WASM_INSN_F32_CONST:
- return 0x43;
- case WASM_INSN_F64_CONST:
- return 0x44;
- case WASM_INSN_LOCAL_GET:
- return 0x20;
- case WASM_INSN_LOCAL_SET:
- return 0x21;
- case WASM_INSN_LOCAL_TEE:
- return 0x22;
- case WASM_INSN_CALL:
- return 0x10;
- case WASM_INSN_CALL_INDIRECT:
- return 0x11;
- case WASM_INSN_GLOBAL_GET:
- return 0x23;
- case WASM_INSN_GLOBAL_SET:
- return 0x24;
- case WASM_INSN_RETURN:
- return 0x0f;
- case WASM_INSN_DROP:
- return 0x1a;
- case WASM_INSN_SELECT:
- return 0x1b;
- case WASM_INSN_I32_LOAD:
- return 0x28;
- case WASM_INSN_I64_LOAD:
- return 0x29;
- case WASM_INSN_I32_LOAD8_S:
- return 0x2c;
- case WASM_INSN_I32_LOAD8_U:
- return 0x2d;
- case WASM_INSN_I32_LOAD16_S:
- return 0x2e;
- case WASM_INSN_I32_LOAD16_U:
- return 0x2f;
- case WASM_INSN_I64_LOAD8_S:
- return 0x30;
- case WASM_INSN_I64_LOAD8_U:
- return 0x31;
- case WASM_INSN_I64_LOAD16_S:
- return 0x32;
- case WASM_INSN_I64_LOAD16_U:
- return 0x33;
- case WASM_INSN_I64_LOAD32_S:
- return 0x34;
- case WASM_INSN_I64_LOAD32_U:
- return 0x35;
- case WASM_INSN_I32_STORE:
- return 0x36;
- case WASM_INSN_I64_STORE:
- return 0x37;
- case WASM_INSN_I32_STORE8:
- return 0x3a;
- case WASM_INSN_I32_STORE16:
- return 0x3b;
- case WASM_INSN_I64_STORE8:
- return 0x3c;
- case WASM_INSN_I64_STORE16:
- return 0x3d;
- case WASM_INSN_I64_STORE32:
- return 0x3e;
- case WASM_INSN_MEMORY_SIZE:
- return 0x3f;
- case WASM_INSN_MEMORY_GROW:
- return 0x40;
- case WASM_INSN_I32_EQZ:
- return 0x45;
- case WASM_INSN_I32_EQ:
- return 0x46;
- case WASM_INSN_I32_NE:
- return 0x47;
- case WASM_INSN_I32_LT_S:
- return 0x48;
- case WASM_INSN_I32_LT_U:
- return 0x49;
- case WASM_INSN_I32_GT_S:
- return 0x4a;
- case WASM_INSN_I32_GT_U:
- return 0x4b;
- case WASM_INSN_I32_LE_S:
- return 0x4c;
- case WASM_INSN_I32_LE_U:
- return 0x4d;
- case WASM_INSN_I32_GE_S:
- return 0x4e;
- case WASM_INSN_I32_GE_U:
- return 0x4f;
- case WASM_INSN_I64_EQZ:
- return 0x50;
- case WASM_INSN_I64_EQ:
- return 0x51;
- case WASM_INSN_I64_NE:
- return 0x52;
- case WASM_INSN_I64_LT_S:
- return 0x53;
- case WASM_INSN_I64_LT_U:
- return 0x54;
- case WASM_INSN_I64_GT_S:
- return 0x55;
- case WASM_INSN_I64_GT_U:
- return 0x56;
- case WASM_INSN_I64_LE_S:
- return 0x57;
- case WASM_INSN_I64_LE_U:
- return 0x58;
- case WASM_INSN_I64_GE_S:
- return 0x59;
- case WASM_INSN_I64_GE_U:
- return 0x5a;
- case WASM_INSN_I32_ADD:
- return 0x6a;
- case WASM_INSN_I32_SUB:
- return 0x6b;
- case WASM_INSN_I32_MUL:
- return 0x6c;
- case WASM_INSN_I32_DIV_S:
- return 0x6d;
- case WASM_INSN_I32_DIV_U:
- return 0x6e;
- case WASM_INSN_I32_REM_S:
- return 0x6f;
- case WASM_INSN_I32_REM_U:
- return 0x70;
- case WASM_INSN_I32_AND:
- return 0x71;
- case WASM_INSN_I32_OR:
- return 0x72;
- case WASM_INSN_I32_XOR:
- return 0x73;
- case WASM_INSN_I32_SHL:
- return 0x74;
- case WASM_INSN_I32_SHR_S:
- return 0x75;
- case WASM_INSN_I32_SHR_U:
- return 0x76;
- case WASM_INSN_I32_CLZ:
- return 0x67;
- case WASM_INSN_I32_CTZ:
- return 0x68;
- case WASM_INSN_I32_POPCNT:
- return 0x69;
- case WASM_INSN_I32_ROTL:
- return 0x77;
- case WASM_INSN_I32_ROTR:
- return 0x78;
- case WASM_INSN_I64_CLZ:
- return 0x79;
- case WASM_INSN_I64_CTZ:
- return 0x7a;
- case WASM_INSN_I64_POPCNT:
- return 0x7b;
- case WASM_INSN_I64_ADD:
- return 0x7c;
- case WASM_INSN_I64_SUB:
- return 0x7d;
- case WASM_INSN_I64_MUL:
- return 0x7e;
- case WASM_INSN_I64_DIV_S:
- return 0x7f;
- case WASM_INSN_I64_DIV_U:
- return 0x80;
- case WASM_INSN_I64_REM_S:
- return 0x81;
- case WASM_INSN_I64_REM_U:
- return 0x82;
- case WASM_INSN_I64_AND:
- return 0x83;
- case WASM_INSN_I64_OR:
- return 0x84;
- case WASM_INSN_I64_XOR:
- return 0x85;
- case WASM_INSN_I64_SHL:
- return 0x86;
- case WASM_INSN_I64_SHR_S:
- return 0x87;
- case WASM_INSN_I64_SHR_U:
- return 0x88;
- case WASM_INSN_I64_ROTL:
- return 0x89;
- case WASM_INSN_I64_ROTR:
- return 0x8a;
- case WASM_INSN_F32_ADD:
- return 0x92;
- case WASM_INSN_F32_SUB:
- return 0x93;
- case WASM_INSN_F32_MUL:
- return 0x94;
- case WASM_INSN_F32_DIV:
- return 0x95;
- case WASM_INSN_F64_ADD:
- return 0xa0;
- case WASM_INSN_F64_SUB:
- return 0xa1;
- case WASM_INSN_F64_MUL:
- return 0xa2;
- case WASM_INSN_F64_DIV:
- return 0xa3;
- case WASM_INSN_F32_EQ:
- return 0x5b;
- case WASM_INSN_F32_NE:
- return 0x5c;
- case WASM_INSN_F32_LT:
- return 0x5d;
- case WASM_INSN_F32_GT:
- return 0x5e;
- case WASM_INSN_F32_LE:
- return 0x5f;
- case WASM_INSN_F32_GE:
- return 0x60;
- case WASM_INSN_F64_EQ:
- return 0x61;
- case WASM_INSN_F64_NE:
- return 0x62;
- case WASM_INSN_F64_LT:
- return 0x63;
- case WASM_INSN_F64_GT:
- return 0x64;
- case WASM_INSN_F64_LE:
- return 0x65;
- case WASM_INSN_F64_GE:
- return 0x66;
- case WASM_INSN_I32_WRAP_I64:
- return 0xa7;
- case WASM_INSN_I32_TRUNC_F32_S:
- return 0xa8;
- case WASM_INSN_I32_TRUNC_F32_U:
- return 0xa9;
- case WASM_INSN_I32_TRUNC_F64_S:
- return 0xaa;
- case WASM_INSN_I32_TRUNC_F64_U:
- return 0xab;
- case WASM_INSN_I64_EXTEND_I32_S:
- return 0xac;
- case WASM_INSN_I64_EXTEND_I32_U:
- return 0xad;
- case WASM_INSN_I64_TRUNC_F32_S:
- return 0xae;
- case WASM_INSN_I64_TRUNC_F32_U:
- return 0xaf;
- case WASM_INSN_I64_TRUNC_F64_S:
- return 0xb0;
- case WASM_INSN_I64_TRUNC_F64_U:
- return 0xb1;
- case WASM_INSN_F32_CONVERT_I32_S:
- return 0xb2;
- case WASM_INSN_F32_CONVERT_I32_U:
- return 0xb3;
- case WASM_INSN_F32_CONVERT_I64_S:
- return 0xb4;
- case WASM_INSN_F32_CONVERT_I64_U:
- return 0xb5;
- case WASM_INSN_F32_DEMOTE_F64:
- return 0xb6;
- case WASM_INSN_F64_CONVERT_I32_S:
- return 0xb7;
- case WASM_INSN_F64_CONVERT_I32_U:
- return 0xb8;
- case WASM_INSN_F64_CONVERT_I64_S:
- return 0xb9;
- case WASM_INSN_F64_CONVERT_I64_U:
- return 0xba;
- case WASM_INSN_F64_PROMOTE_F32:
- return 0xbb;
- case WASM_INSN_I32_REINTERPRET_F32:
- return 0xbc;
- case WASM_INSN_I64_REINTERPRET_F64:
- return 0xbd;
- case WASM_INSN_F32_REINTERPRET_I32:
- return 0xbe;
- case WASM_INSN_F64_REINTERPRET_I64:
- return 0xbf;
+ case WASM_INSN_UNREACHABLE:
+ return 0x00;
+ case WASM_INSN_NOP:
+ return 0x01;
+ case WASM_INSN_BLOCK:
+ return 0x02;
+ case WASM_INSN_LOOP:
+ return 0x03;
+ case WASM_INSN_IF:
+ return 0x04;
+ case WASM_INSN_ELSE:
+ return 0x05;
+ case WASM_INSN_END:
+ return 0x0b;
+ case WASM_INSN_BR:
+ return 0x0c;
+ case WASM_INSN_BR_IF:
+ return 0x0d;
+ case WASM_INSN_BR_TABLE:
+ return 0x0e;
+ case WASM_INSN_I32_CONST:
+ return 0x41;
+ case WASM_INSN_I64_CONST:
+ return 0x42;
+ case WASM_INSN_F32_CONST:
+ return 0x43;
+ case WASM_INSN_F64_CONST:
+ return 0x44;
+ case WASM_INSN_LOCAL_GET:
+ return 0x20;
+ case WASM_INSN_LOCAL_SET:
+ return 0x21;
+ case WASM_INSN_LOCAL_TEE:
+ return 0x22;
+ case WASM_INSN_CALL:
+ return 0x10;
+ case WASM_INSN_CALL_INDIRECT:
+ return 0x11;
+ case WASM_INSN_GLOBAL_GET:
+ return 0x23;
+ case WASM_INSN_GLOBAL_SET:
+ return 0x24;
+ case WASM_INSN_RETURN:
+ return 0x0f;
+ case WASM_INSN_DROP:
+ return 0x1a;
+ case WASM_INSN_SELECT:
+ return 0x1b;
+ case WASM_INSN_I32_LOAD:
+ return 0x28;
+ case WASM_INSN_I64_LOAD:
+ return 0x29;
+ case WASM_INSN_I32_LOAD8_S:
+ return 0x2c;
+ case WASM_INSN_I32_LOAD8_U:
+ return 0x2d;
+ case WASM_INSN_I32_LOAD16_S:
+ return 0x2e;
+ case WASM_INSN_I32_LOAD16_U:
+ return 0x2f;
+ case WASM_INSN_I64_LOAD8_S:
+ return 0x30;
+ case WASM_INSN_I64_LOAD8_U:
+ return 0x31;
+ case WASM_INSN_I64_LOAD16_S:
+ return 0x32;
+ case WASM_INSN_I64_LOAD16_U:
+ return 0x33;
+ case WASM_INSN_I64_LOAD32_S:
+ return 0x34;
+ case WASM_INSN_I64_LOAD32_U:
+ return 0x35;
+ case WASM_INSN_I32_STORE:
+ return 0x36;
+ case WASM_INSN_I64_STORE:
+ return 0x37;
+ case WASM_INSN_I32_STORE8:
+ return 0x3a;
+ case WASM_INSN_I32_STORE16:
+ return 0x3b;
+ case WASM_INSN_I64_STORE8:
+ return 0x3c;
+ case WASM_INSN_I64_STORE16:
+ return 0x3d;
+ case WASM_INSN_I64_STORE32:
+ return 0x3e;
+ case WASM_INSN_MEMORY_SIZE:
+ return 0x3f;
+ case WASM_INSN_MEMORY_GROW:
+ return 0x40;
+ case WASM_INSN_I32_EQZ:
+ return 0x45;
+ case WASM_INSN_I32_EQ:
+ return 0x46;
+ case WASM_INSN_I32_NE:
+ return 0x47;
+ case WASM_INSN_I32_LT_S:
+ return 0x48;
+ case WASM_INSN_I32_LT_U:
+ return 0x49;
+ case WASM_INSN_I32_GT_S:
+ return 0x4a;
+ case WASM_INSN_I32_GT_U:
+ return 0x4b;
+ case WASM_INSN_I32_LE_S:
+ return 0x4c;
+ case WASM_INSN_I32_LE_U:
+ return 0x4d;
+ case WASM_INSN_I32_GE_S:
+ return 0x4e;
+ case WASM_INSN_I32_GE_U:
+ return 0x4f;
+ case WASM_INSN_I64_EQZ:
+ return 0x50;
+ case WASM_INSN_I64_EQ:
+ return 0x51;
+ case WASM_INSN_I64_NE:
+ return 0x52;
+ case WASM_INSN_I64_LT_S:
+ return 0x53;
+ case WASM_INSN_I64_LT_U:
+ return 0x54;
+ case WASM_INSN_I64_GT_S:
+ return 0x55;
+ case WASM_INSN_I64_GT_U:
+ return 0x56;
+ case WASM_INSN_I64_LE_S:
+ return 0x57;
+ case WASM_INSN_I64_LE_U:
+ return 0x58;
+ case WASM_INSN_I64_GE_S:
+ return 0x59;
+ case WASM_INSN_I64_GE_U:
+ return 0x5a;
+ case WASM_INSN_I32_ADD:
+ return 0x6a;
+ case WASM_INSN_I32_SUB:
+ return 0x6b;
+ case WASM_INSN_I32_MUL:
+ return 0x6c;
+ case WASM_INSN_I32_DIV_S:
+ return 0x6d;
+ case WASM_INSN_I32_DIV_U:
+ return 0x6e;
+ case WASM_INSN_I32_REM_S:
+ return 0x6f;
+ case WASM_INSN_I32_REM_U:
+ return 0x70;
+ case WASM_INSN_I32_AND:
+ return 0x71;
+ case WASM_INSN_I32_OR:
+ return 0x72;
+ case WASM_INSN_I32_XOR:
+ return 0x73;
+ case WASM_INSN_I32_SHL:
+ return 0x74;
+ case WASM_INSN_I32_SHR_S:
+ return 0x75;
+ case WASM_INSN_I32_SHR_U:
+ return 0x76;
+ case WASM_INSN_I32_CLZ:
+ return 0x67;
+ case WASM_INSN_I32_CTZ:
+ return 0x68;
+ case WASM_INSN_I32_POPCNT:
+ return 0x69;
+ case WASM_INSN_I32_ROTL:
+ return 0x77;
+ case WASM_INSN_I32_ROTR:
+ return 0x78;
+ case WASM_INSN_I64_CLZ:
+ return 0x79;
+ case WASM_INSN_I64_CTZ:
+ return 0x7a;
+ case WASM_INSN_I64_POPCNT:
+ return 0x7b;
+ case WASM_INSN_I64_ADD:
+ return 0x7c;
+ case WASM_INSN_I64_SUB:
+ return 0x7d;
+ case WASM_INSN_I64_MUL:
+ return 0x7e;
+ case WASM_INSN_I64_DIV_S:
+ return 0x7f;
+ case WASM_INSN_I64_DIV_U:
+ return 0x80;
+ case WASM_INSN_I64_REM_S:
+ return 0x81;
+ case WASM_INSN_I64_REM_U:
+ return 0x82;
+ case WASM_INSN_I64_AND:
+ return 0x83;
+ case WASM_INSN_I64_OR:
+ return 0x84;
+ case WASM_INSN_I64_XOR:
+ return 0x85;
+ case WASM_INSN_I64_SHL:
+ return 0x86;
+ case WASM_INSN_I64_SHR_S:
+ return 0x87;
+ case WASM_INSN_I64_SHR_U:
+ return 0x88;
+ case WASM_INSN_I64_ROTL:
+ return 0x89;
+ case WASM_INSN_I64_ROTR:
+ return 0x8a;
+ case WASM_INSN_F32_ADD:
+ return 0x92;
+ case WASM_INSN_F32_SUB:
+ return 0x93;
+ case WASM_INSN_F32_MUL:
+ return 0x94;
+ case WASM_INSN_F32_DIV:
+ return 0x95;
+ case WASM_INSN_F64_ADD:
+ return 0xa0;
+ case WASM_INSN_F64_SUB:
+ return 0xa1;
+ case WASM_INSN_F64_MUL:
+ return 0xa2;
+ case WASM_INSN_F64_DIV:
+ return 0xa3;
+ case WASM_INSN_F32_EQ:
+ return 0x5b;
+ case WASM_INSN_F32_NE:
+ return 0x5c;
+ case WASM_INSN_F32_LT:
+ return 0x5d;
+ case WASM_INSN_F32_GT:
+ return 0x5e;
+ case WASM_INSN_F32_LE:
+ return 0x5f;
+ case WASM_INSN_F32_GE:
+ return 0x60;
+ case WASM_INSN_F64_EQ:
+ return 0x61;
+ case WASM_INSN_F64_NE:
+ return 0x62;
+ case WASM_INSN_F64_LT:
+ return 0x63;
+ case WASM_INSN_F64_GT:
+ return 0x64;
+ case WASM_INSN_F64_LE:
+ return 0x65;
+ case WASM_INSN_F64_GE:
+ return 0x66;
+ case WASM_INSN_I32_WRAP_I64:
+ return 0xa7;
+ case WASM_INSN_I32_TRUNC_F32_S:
+ return 0xa8;
+ case WASM_INSN_I32_TRUNC_F32_U:
+ return 0xa9;
+ case WASM_INSN_I32_TRUNC_F64_S:
+ return 0xaa;
+ case WASM_INSN_I32_TRUNC_F64_U:
+ return 0xab;
+ case WASM_INSN_I64_EXTEND_I32_S:
+ return 0xac;
+ case WASM_INSN_I64_EXTEND_I32_U:
+ return 0xad;
+ case WASM_INSN_I64_TRUNC_F32_S:
+ return 0xae;
+ case WASM_INSN_I64_TRUNC_F32_U:
+ return 0xaf;
+ case WASM_INSN_I64_TRUNC_F64_S:
+ return 0xb0;
+ case WASM_INSN_I64_TRUNC_F64_U:
+ return 0xb1;
+ case WASM_INSN_F32_CONVERT_I32_S:
+ return 0xb2;
+ case WASM_INSN_F32_CONVERT_I32_U:
+ return 0xb3;
+ case WASM_INSN_F32_CONVERT_I64_S:
+ return 0xb4;
+ case WASM_INSN_F32_CONVERT_I64_U:
+ return 0xb5;
+ case WASM_INSN_F32_DEMOTE_F64:
+ return 0xb6;
+ case WASM_INSN_F64_CONVERT_I32_S:
+ return 0xb7;
+ case WASM_INSN_F64_CONVERT_I32_U:
+ return 0xb8;
+ case WASM_INSN_F64_CONVERT_I64_S:
+ return 0xb9;
+ case WASM_INSN_F64_CONVERT_I64_U:
+ return 0xba;
+ case WASM_INSN_F64_PROMOTE_F32:
+ return 0xbb;
+ case WASM_INSN_I32_REINTERPRET_F32:
+ return 0xbc;
+ case WASM_INSN_I64_REINTERPRET_F64:
+ return 0xbd;
+ case WASM_INSN_F32_REINTERPRET_I32:
+ return 0xbe;
+ case WASM_INSN_F64_REINTERPRET_I64:
+ return 0xbf;
}
return 0;
}
-static void enc_code(CfreeWriter *w, const WasmModule *m) {
+static void enc_code(CfreeWriter* w, const WasmModule* m) {
uint32_t i, j;
uint32_t n = 0;
for (i = 0; i < m->nfuncs; ++i)
- if (!m->funcs[i].is_import)
- n++;
+ if (!m->funcs[i].is_import) n++;
write_uleb(w, n);
for (i = 0; i < m->nfuncs; ++i) {
- CfreeWriter *body = cfree_writer_mem(m->heap);
+ CfreeWriter* body = cfree_writer_mem(m->heap);
size_t len;
- const uint8_t *bytes;
+ const uint8_t* bytes;
if (m->funcs[i].is_import) {
cfree_writer_close(body);
continue;
@@ -6173,7 +6297,7 @@ static void enc_code(CfreeWriter *w, const WasmModule *m) {
}
}
-static void enc_data(CfreeWriter *w, const WasmModule *m) {
+static void enc_data(CfreeWriter* w, const WasmModule* m) {
if (!m->has_memory || !m->memory.data_init_len) {
write_uleb(w, 0);
return;
@@ -6187,35 +6311,32 @@ static void enc_data(CfreeWriter *w, const WasmModule *m) {
w->write(w, m->memory.data, m->memory.data_init_len);
}
-static void enc_elem(CfreeWriter *w, const WasmModule *m) {
+static void enc_elem(CfreeWriter* w, const WasmModule* m) {
uint32_t i, j;
write_uleb(w, m->nelems);
for (i = 0; i < m->nelems; ++i) {
- const WasmElemSegment *e = &m->elems[i];
+ const WasmElemSegment* e = &m->elems[i];
write_uleb(w, 0);
write_byte(w, 0x41);
write_sleb(w, e->offset);
write_byte(w, 0x0b);
write_uleb(w, e->nfuncs);
- for (j = 0; j < e->nfuncs; ++j)
- write_uleb(w, e->funcs[j]);
+ for (j = 0; j < e->nfuncs; ++j) write_uleb(w, e->funcs[j]);
}
}
-static void enc_start(CfreeWriter *w, const WasmModule *m) {
+static void enc_start(CfreeWriter* w, const WasmModule* m) {
write_uleb(w, m->start_func);
}
-static void encode_custom(CfreeHeap *h, CfreeWriter *out,
- const WasmCustom *cs) {
- CfreeWriter *tmp = cfree_writer_mem(h);
+static void encode_custom(CfreeHeap* h, CfreeWriter* out,
+ const WasmCustom* cs) {
+ CfreeWriter* tmp = cfree_writer_mem(h);
size_t len;
- const uint8_t *bytes;
- if (!tmp)
- return;
+ const uint8_t* bytes;
+ if (!tmp) return;
write_name(tmp, cs->name ? cs->name : "");
- if (cs->len)
- tmp->write(tmp, cs->data, cs->len);
+ if (cs->len) tmp->write(tmp, cs->data, cs->len);
bytes = cfree_writer_mem_bytes(tmp, &len);
write_byte(out, 0);
write_uleb(out, len);
@@ -6223,36 +6344,31 @@ static void encode_custom(CfreeHeap *h, CfreeWriter *out,
cfree_writer_close(tmp);
}
-static void wasm_encode(CfreeCompiler *c, const WasmModule *m,
- CfreeWriter *out) {
+static void wasm_encode(CfreeCompiler* c, const WasmModule* m,
+ CfreeWriter* out) {
static const uint8_t magic[] = {0x00, 0x61, 0x73, 0x6d,
0x01, 0x00, 0x00, 0x00};
- CfreeHeap *h = cfree_compiler_heap(c);
+ CfreeHeap* h = cfree_compiler_heap(c);
out->write(out, magic, sizeof magic);
for (uint32_t i = 0; i < m->ncustoms; ++i)
encode_custom(h, out, &m->customs[i]);
encode_section(h, out, 1, enc_type, m);
- if (wasm_module_has_imports(m))
- encode_section(h, out, 2, enc_import, m);
+ if (wasm_module_has_imports(m)) encode_section(h, out, 2, enc_import, m);
encode_section(h, out, 3, enc_func, m);
- if (m->ntables)
- encode_section(h, out, 4, enc_table, m);
+ if (m->ntables) encode_section(h, out, 4, enc_table, m);
if (m->has_memory && !m->memory.is_import)
encode_section(h, out, 5, enc_memory, m);
- if (m->nglobals)
- encode_section(h, out, 6, enc_global, m);
+ if (m->nglobals) encode_section(h, out, 6, enc_global, m);
encode_section(h, out, 7, enc_export, m);
- if (m->has_start)
- encode_section(h, out, 8, enc_start, m);
- if (m->nelems)
- encode_section(h, out, 9, enc_elem, m);
+ if (m->has_start) encode_section(h, out, 8, enc_start, m);
+ if (m->nelems) encode_section(h, out, 9, enc_elem, m);
encode_section(h, out, 10, enc_code, m);
if (m->has_memory && m->memory.data_init_len)
encode_section(h, out, 11, enc_data, m);
}
-static void wasm_parse_any(CfreeCompiler *c, const CfreeBytesInput *input,
- WasmModule *m) {
+static void wasm_parse_any(CfreeCompiler* c, const CfreeBytesInput* input,
+ WasmModule* m) {
if (wasm_is_binary(input))
wasm_decode_binary(c, input, m);
else
@@ -6260,8 +6376,8 @@ static void wasm_parse_any(CfreeCompiler *c, const CfreeBytesInput *input,
wasm_validate(m, c);
}
-int cfree_wasm_compile(CfreeCompiler *c, const CfreeCompileOptions *opts,
- const CfreeBytesInput *input, CfreeObjBuilder *out) {
+int cfree_wasm_compile(CfreeCompiler* c, const CfreeCompileOptions* opts,
+ const CfreeBytesInput* input, CfreeObjBuilder* out) {
WasmModule m;
wasm_module_init(&m, cfree_compiler_heap(c));
wasm_parse_any(c, input, &m);
@@ -6270,12 +6386,12 @@ int cfree_wasm_compile(CfreeCompiler *c, const CfreeCompileOptions *opts,
return 0;
}
-void cfree_wasm_register(CfreeCompiler *c) {
+void cfree_wasm_register(CfreeCompiler* c) {
(void)cfree_register_frontend(c, CFREE_LANG_WASM, cfree_wasm_compile);
}
-int cfree_wasm_wat_to_wasm(CfreeCompiler *c, const CfreeBytesInput *input,
- CfreeWriter *out) {
+int cfree_wasm_wat_to_wasm(CfreeCompiler* c, const CfreeBytesInput* input,
+ CfreeWriter* out) {
WasmModule m;
wasm_module_init(&m, cfree_compiler_heap(c));
wat_parse_module(c, input, &m);
diff --git a/test/wasm/cases/import_slot_unused.expect b/test/wasm/cases/import_slot_unused.expect
@@ -0,0 +1 @@
+42
diff --git a/test/wasm/cases/import_slot_unused.wat b/test/wasm/cases/import_slot_unused.wat
@@ -0,0 +1,4 @@
+(module
+ (import "host" "unused" (func $unused (param i32) (result i32)))
+ (func (export "test_main") (result i32)
+ i32.const 42))
diff --git a/test/wasm/cases/table_offset.expect b/test/wasm/cases/table_offset.expect
@@ -0,0 +1 @@
+42
diff --git a/test/wasm/cases/table_offset.wat b/test/wasm/cases/table_offset.wat
@@ -0,0 +1,9 @@
+(module
+ (type $ret_i32 (func (result i32)))
+ (func $target (type $ret_i32)
+ i32.const 42)
+ (table 3 funcref)
+ (elem (i32.const 2) func $target)
+ (func (export "test_main") (result i32)
+ i32.const 2
+ call_indirect (type $ret_i32)))