From 2a97c8906ae7e2ffb8da49205564cb3bf9c4250b Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Tue, 21 Jun 2022 22:13:14 -0500 Subject: [PATCH] closer to converting wasm -> ovm --- build.sh | 15 ++++- include/onyx_wasm.h | 26 +++++++- src/{cli.c => ovm_cli_test.c} | 0 src/wasm/module.c | 112 +++++++++++++++++++++++++++------ src/wasm_cli_test.c | 23 +++++++ math.asm => tests/ovm/math.asm | 0 tests/ovm/out.ovm | Bin 0 -> 674 bytes test.asm => tests/ovm/test.asm | 0 tests/wasm/out.wasm | Bin 0 -> 713 bytes tests/wasm/tiny.onyx | 15 +++++ 10 files changed, 166 insertions(+), 25 deletions(-) rename src/{cli.c => ovm_cli_test.c} (100%) create mode 100644 src/wasm_cli_test.c rename math.asm => tests/ovm/math.asm (100%) create mode 100644 tests/ovm/out.ovm rename test.asm => tests/ovm/test.asm (100%) create mode 100644 tests/wasm/out.wasm create mode 100644 tests/wasm/tiny.onyx diff --git a/build.sh b/build.sh index cea3591..8ebf101 100755 --- a/build.sh +++ b/build.sh @@ -10,15 +10,24 @@ C_FILES="src/wasm.c src/vm/* src/wasm/*" $CC $FLAGS $INCLUDES -shared -fPIC -o $TARGET $C_FILES $LIBS $WARNINGS -C_FILES="src/cli.c" -TARGET=onyx-debug + +C_FILES="src/ovm_cli_test.c" +TARGET=bin/ovm_cli_test LIBS="-L$(pwd) -lonyx_embedder -lm -Wl,-rpath=./" $CC $FLAGS $INCLUDES -o $TARGET $C_FILES $LIBS $WARNINGS + +C_FILES="src/wasm_cli_test.c" +TARGET=bin/wasm_cli_test +LIBS="-L$(pwd) -lonyx_embedder -lm -Wl,-rpath=./" + +$CC $FLAGS $INCLUDES -o $TARGET $C_FILES $LIBS $WARNINGS + + flex -o src/tools/lex.yy.c src/tools/asm.l -TARGET="assembler" +TARGET="bin/assembler" C_FILES="src/tools/assembler.c src/tools/lex.yy.c" $CC $FLAGS $INCLUDES -o $TARGET $C_FILES $LIBS $WARNINGS diff --git a/include/onyx_wasm.h b/include/onyx_wasm.h index 971b68f..b93dc65 100644 --- a/include/onyx_wasm.h +++ b/include/onyx_wasm.h @@ -75,6 +75,7 @@ struct wasm_importtype_t { struct wasm_exporttype_t { wasm_name_t *name; wasm_externtype_t *type; + int index; }; @@ -92,6 +93,13 @@ struct wasm_trap_t { struct wasm_foreign_t { }; +struct wasm_data_t { + void *data; + unsigned int length; + unsigned int offset; + bool passive; +}; + struct wasm_module_t { wasm_store_t *store; @@ -105,8 +113,14 @@ struct wasm_module_t { wasm_exporttype_vec_t exports; int start_func_idx; + + unsigned int elem_count; unsigned int *elem_entries; // Array of function indicies + bool data_count_present; + unsigned int data_count; + struct wasm_data_t *data_entries; + ovm_program_t *program; bool valid; }; @@ -154,6 +168,14 @@ struct wasm_instance_t { }; + +wasm_functype_t *wasm_module_index_functype(wasm_module_t *module, int index); +wasm_tabletype_t *wasm_module_index_tabletype(wasm_module_t *module, int index); +wasm_globaltype_t *wasm_module_index_globaltype(wasm_module_t *module, int index); +wasm_memorytype_t *wasm_module_index_memorytype(wasm_module_t *module, int index); + + + #define WASM_DECLARE_VEC_IMPL(type, ptr_or_none) \ void wasm_##type##_vec_new_empty(wasm_##type##_vec_t *out) { \ out->size = 0; \ @@ -161,12 +183,12 @@ struct wasm_instance_t { } \ \ void wasm_##type##_vec_new_uninitialized(wasm_##type##_vec_t *out, size_t size) { \ - out->data = malloc(sizeof(wasm_##type##_t) * size); \ + out->data = malloc(sizeof(wasm_##type##_t ptr_or_none) * size); \ out->size = size; \ } \ \ void wasm_##type##_vec_new(wasm_##type##_vec_t *out, size_t size, wasm_##type##_t ptr_or_none const data[]) { \ - out->data = malloc(sizeof(wasm_##type##_t) * size); \ + out->data = malloc(sizeof(wasm_##type##_t ptr_or_none) * size); \ out->size = size; \ \ fori (i, 0, (i32) size) { \ diff --git a/src/cli.c b/src/ovm_cli_test.c similarity index 100% rename from src/cli.c rename to src/ovm_cli_test.c diff --git a/src/wasm/module.c b/src/wasm/module.c index c42f910..84c6f70 100644 --- a/src/wasm/module.c +++ b/src/wasm/module.c @@ -95,7 +95,7 @@ static wasm_tabletype_t *parse_tabletype(build_context *ctx) { assert(CONSUME_BYTE(ctx) == 0x70); // @ReportError wasm_limits_t limits = parse_limits(ctx); - wasm_tabletype_t *tt = wasm_tabletype_new(wasm_valtype_new(0x70), &limits); + wasm_tabletype_t *tt = wasm_tabletype_new(wasm_valtype_new(WASM_FUNCREF), &limits); return tt; } @@ -155,7 +155,8 @@ static void parse_func_section(build_context *ctx) { wasm_functype_vec_new_uninitialized(&ctx->module->functypes, func_count); fori (i, 0, (int) func_count) { - ctx->module->functypes.data[i] = ctx->module->type_section.data[i]; + unsigned int index = uleb128_to_uint(ctx->binary.data, &ctx->offset); + ctx->module->functypes.data[i] = ctx->module->type_section.data[index]; } } @@ -218,6 +219,8 @@ static void parse_global_section(build_context *ctx) { } } + assert(CONSUME_BYTE(ctx) == 0x0b); + ctx->module->globaltypes.data[i] = gt; } } @@ -234,20 +237,20 @@ static void parse_export_section(build_context *ctx) { wasm_byte_vec_new_uninitialized(&export_name, export_name_size); fori (n, 0, export_name_size) export_name.data[n] = CONSUME_BYTE(ctx); - wasm_externtype_t *export_type; - switch (CONSUME_BYTE(ctx)) { - case 0x00: { - unsigned int type_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset); - export_type = wasm_functype_as_externtype(ctx->module->type_section.data[type_idx]); - break; - } + unsigned int type = CONSUME_BYTE(ctx); + unsigned int idx = uleb128_to_uint(ctx->binary.data, &ctx->offset); - case 0x01: export_type = wasm_tabletype_as_externtype(parse_tabletype(ctx)); break; - case 0x02: export_type = wasm_memorytype_as_externtype(parse_memorytype(ctx)); break; - case 0x03: export_type = wasm_globaltype_as_externtype(parse_globaltype(ctx)); break; + wasm_externtype_t *export_type = NULL; + + switch (type) { + case 0x00: export_type = wasm_functype_as_externtype(wasm_module_index_functype(ctx->module, idx)); break; + case 0x01: export_type = wasm_tabletype_as_externtype(wasm_module_index_tabletype(ctx->module, idx)); break; + case 0x02: export_type = wasm_memorytype_as_externtype(wasm_module_index_memorytype(ctx->module, idx)); break; + case 0x03: export_type = wasm_globaltype_as_externtype(wasm_module_index_globaltype(ctx->module, idx)); break; } wasm_exporttype_t *export = wasm_exporttype_new(&export_name, export_type); + export->index = idx; ctx->module->exports.data[i] = export; } } @@ -261,18 +264,18 @@ static void parse_elem_section(build_context *ctx) { unsigned int section_size = uleb128_to_uint(ctx->binary.data, &ctx->offset); unsigned int elem_count = uleb128_to_uint(ctx->binary.data, &ctx->offset); - // This is going to be a mess... // I am only going to handle the case of a single, active, offset-0, // element entry. This is all that Onyx uses and will probably ever // use. assert(elem_count == 1); - assert(uleb128_to_uint(ctx->binary.data, &ctx->offset) == 0x00); - assert(uleb128_to_uint(ctx->binary.data, &ctx->offset) == 0x40); - assert(uleb128_to_uint(ctx->binary.data, &ctx->offset) == 0x00); - assert(uleb128_to_uint(ctx->binary.data, &ctx->offset) == 0x0B); + assert(CONSUME_BYTE(ctx) == 0x00); + assert(CONSUME_BYTE(ctx) == 0x41); + assert(CONSUME_BYTE(ctx) == 0x00); + assert(CONSUME_BYTE(ctx) == 0x0B); unsigned int entry_count = uleb128_to_uint(ctx->binary.data, &ctx->offset); + ctx->module->elem_count = entry_count; ctx->module->elem_entries = malloc(sizeof(unsigned int) * entry_count); fori (i, 0, (int) entry_count) { @@ -286,8 +289,49 @@ static void parse_code_section(build_context *ctx) { // TODO } -static void parse_data_section(build_context *ctx) {} -static void parse_data_count_section(build_context *ctx) {} +static void parse_data_section(build_context *ctx) { + unsigned int section_size = uleb128_to_uint(ctx->binary.data, &ctx->offset); + unsigned int data_count = uleb128_to_uint(ctx->binary.data, &ctx->offset); + + if (ctx->module->data_count_present) { + assert(ctx->module->data_count == data_count); + } else { + ctx->module->data_count = data_count; + } + + ctx->module->data_entries = malloc(sizeof(struct wasm_data_t) * data_count); + + fori (i, 0, (int) data_count) { + char data_type = CONSUME_BYTE(ctx); + assert(data_type == 0x00 || data_type == 0x01); + + struct wasm_data_t data_entry; + data_entry.data = NULL; + data_entry.offset = 0; + data_entry.length = 0; + data_entry.passive = true; + + if (data_type == 0x00) { + assert(CONSUME_BYTE(ctx) == 0x41); + data_entry.offset = uleb128_to_uint(ctx->binary.data, &ctx->offset); + assert(CONSUME_BYTE(ctx) == 0x0B); + } + + data_entry.length = uleb128_to_uint(ctx->binary.data, &ctx->offset); + data_entry.data = bh_pointer_add(ctx->binary.data, ctx->offset); + ctx->offset += data_entry.length; + + ctx->module->data_entries[i] = data_entry; + } +} + +static void parse_data_count_section(build_context *ctx) { + unsigned int section_size = uleb128_to_uint(ctx->binary.data, &ctx->offset); + unsigned int data_count = uleb128_to_uint(ctx->binary.data, &ctx->offset); + + ctx->module->data_count_present = true; + ctx->module->data_count = data_count; +} static void parse_section(build_context *ctx) { char section_number = CONSUME_BYTE(ctx); @@ -316,7 +360,7 @@ static bool module_build(wasm_module_t *module, const wasm_byte_vec_t *binary) { build_context ctx; ctx.binary = *binary; - ctx.offset = 0; + ctx.offset = 8; // Skip the magic bytes and version ctx.module = module; ctx.program = module->program; ctx.store = engine->store; @@ -324,11 +368,39 @@ static bool module_build(wasm_module_t *module, const wasm_byte_vec_t *binary) { while (ctx.offset < binary->size) { parse_section(&ctx); } + + module->program->register_count = module->globaltypes.size; return true; } +#define WASM_MODULE_INDEX(k1, k2) \ + wasm_##k1##type_t *wasm_module_index_##k1##type(wasm_module_t *module, int index) { \ + fori (i, 0, (int) module->imports.size) { \ + if (module->imports.data[i]->type->kind == k2) { \ + if (index == 0) { \ + return wasm_externtype_as_##k1##type(module->imports.data[i]->type); \ + } \ + \ + index -= 1; \ + } \ + } \ + \ + if (index < (int) module->k1##types.size) { \ + return module->k1##types.data[index]; \ + } \ + \ + return NULL; \ + } + +WASM_MODULE_INDEX(func, WASM_EXTERN_FUNC) +WASM_MODULE_INDEX(memory, WASM_EXTERN_MEMORY) +WASM_MODULE_INDEX(table, WASM_EXTERN_TABLE) +WASM_MODULE_INDEX(global, WASM_EXTERN_GLOBAL) + +#undef WASM_MODULE_INDEX + // Ommitting the "sharable ref" crap that I don't think will // ever be needed for a module. diff --git a/src/wasm_cli_test.c b/src/wasm_cli_test.c new file mode 100644 index 0000000..8d2337d --- /dev/null +++ b/src/wasm_cli_test.c @@ -0,0 +1,23 @@ +#include "onyx_wasm.h" + + +int main(int argc, char *argv[]) { + wasm_config_t *config = wasm_config_new(); + wasm_config_enable_debug(config, true); + + wasm_engine_t *engine = wasm_engine_new_with_config(config); + + wasm_store_t *store = wasm_store_new(engine); + + wasm_byte_vec_t wasm_bytes; + { + bh_file_contents contents = bh_file_read_contents(bh_heap_allocator(), argv[1]); + + wasm_bytes.size = contents.length; + wasm_bytes.data = contents.data; + } + + wasm_module_t *module = wasm_module_new(store, &wasm_bytes); + assert(module); +} + diff --git a/math.asm b/tests/ovm/math.asm similarity index 100% rename from math.asm rename to tests/ovm/math.asm diff --git a/tests/ovm/out.ovm b/tests/ovm/out.ovm new file mode 100644 index 0000000000000000000000000000000000000000..9f68090ad81613a64de68b69153088d5679463d5 GIT binary patch literal 674 zcmZ9Iy$%6U5QWFjDkMTfp%f3`=K)YEM5h&@5wY2@3h}5OMX~0)?or%H?%p|P&OI}; z+udeuX0;I?vqs%-!gHI3%uHO*>+l=`Of3t@Y!Yu>^O#8Q+J;>-8Bn1{Jq+UIv8k{hWuK_xJK}yzGneW?vx*7MTD5 literal 0 HcmV?d00001 diff --git a/test.asm b/tests/ovm/test.asm similarity index 100% rename from test.asm rename to tests/ovm/test.asm diff --git a/tests/wasm/out.wasm b/tests/wasm/out.wasm new file mode 100644 index 0000000000000000000000000000000000000000..2678395df54988164c2d451d83cc0906651b17cb GIT binary patch literal 713 zcmbVK+fKqj5S`gx081hoqKPqaQDc0lu3QA-TND4IAYB5+wxqkLJgr}$pQE4UlX14_ zJK^C>+q37Knb{P^Dn$Um3xDJoV_@V`HE2ejecBgRR)7)G7ejEW6+i}#>$xs206iDs zt?JjA!RQMDst{C896yz5UaT0@rps&+>(xRc__5OCLW5VUAdn9IINBD_Tr$}6;E2OH`~^hofPhXS9vn{cLW*LU>3J%}!*c$V#Q8!ihz7y`Mn7yn z&a>5PTyC3Br%GydOgDQ^ND1$RPr^5$Lsu@Ast{^6rey0AWe=OJ=h?Mo?gpK(d$WPA z-MI i32 { + return a + b; +} + +g :: (x) => x + 1; + +#export "_start" () { + a := 10; + b := 20; + c := f(a, b); + + z: (i32) -> i32 = g; + z(10); +} \ No newline at end of file -- 2.25.1