From 3a13a2f95832e1905bb5086ab6bf6b5c5e49c86d Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Fri, 19 Jun 2020 11:05:36 -0500 Subject: [PATCH] Added foreign functions (WASM imports) --- Makefile | 2 +- docs/plan | 2 +- include/bh.h | 2 +- include/onyxwasm.h | 34 ++++++++++------- onyx | Bin 151080 -> 152816 bytes progs/minimal.onyx | 3 +- src/onyxparser.c | 47 ++++++++++++++++------- src/onyxwasm.c | 93 ++++++++++++++++++++++++++++++++++++++++----- 8 files changed, 143 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index 32e6043f..54dc1cbb 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,6 @@ onyx: $(OBJ_FILES) $(CC) $(FLAGS) $(OBJ_FILES) -o $@ $(LIBS) clean: - rm $(OBJ_FILES) 2>&1 >/dev/null + rm -f $(OBJ_FILES) 2>&1 >/dev/null all: onyx diff --git a/docs/plan b/docs/plan index 21597ed3..bb41161e 100644 --- a/docs/plan +++ b/docs/plan @@ -55,7 +55,7 @@ HOW: [X] Curly braces are required for all bodies of blocks [X] Numeric literals are parsed [X] Numeric literals have the minimum type detected - [ ] Foreign imports (functions only) + [X] Foreign imports (functions only) [ ] Comparison operators [ ] Proper boolean type [ ] Conditional branching works as expected diff --git a/include/bh.h b/include/bh.h index 38b7fa11..85ad7699 100644 --- a/include/bh.h +++ b/include/bh.h @@ -582,7 +582,7 @@ typedef struct bh__table { #else #define bh_table_init(allocator_, tab, hs) bh__table_init(allocator_, (bh__table **)&(tab), hs) #define bh_table_free(tab) bh__table_free((bh__table **)&(tab)) - #define bh_table_put(T, tab, key, value) (*((T *) bh__table_put((bh__table *) tab, sizeof(T), key)) = value) + #define bh_table_put(T, tab, key, value) (*((T *) bh__table_put((bh__table *) tab, sizeof(T), key)) = (T) value) #define bh_table_has(T, tab, key) (bh__table_has((bh__table *) tab, sizeof(T), key)) #define bh_table_get(T, tab, key) (*((T *) bh__table_get((bh__table *) tab, sizeof(T), key))) #define bh_table_delete(T, tab, key) (bh__table_delete((bh__table *) tab, sizeof(T), key)) diff --git a/include/onyxwasm.h b/include/onyxwasm.h index c8482ada..3ae0f67e 100644 --- a/include/onyxwasm.h +++ b/include/onyxwasm.h @@ -249,18 +249,24 @@ typedef struct WasmFunc { bh_arr(WasmInstruction) code; } WasmFunc; -typedef enum WasmExportKind { - WASM_EXPORT_FUNCTION = 0x00, - WASM_EXPORT_TABLE = 0x01, - WASM_EXPORT_MEMORY = 0x02, - WASM_EXPORT_GLOBAL = 0x03, -} WasmExportKind; +typedef enum WasmForeignKind { + WASM_FOREIGN_FUNCTION = 0x00, + WASM_FOREIGN_TABLE = 0x01, + WASM_FOREIGN_MEMORY = 0x02, + WASM_FOREIGN_GLOBAL = 0x03, +} WasmForeignKind; typedef struct WasmExport { - WasmExportKind kind; + WasmForeignKind kind; i32 idx; } WasmExport; +typedef struct WasmImport { + WasmForeignKind kind; + i32 idx; + OnyxToken *mod, *name; +} WasmImport; + typedef struct OnyxWasmModule { bh_allocator allocator; @@ -271,16 +277,18 @@ typedef struct OnyxWasmModule { // 0x7f 0x7f : 0x7f ( (i32, i32) -> i32 ) // to the function type index if it has been created. bh_table(i32) type_map; - i32 next_type_idx; - // NOTE: This have to be pointers because the type is variadic in size - bh_arr(WasmFuncType*) functypes; + bh_arr(WasmFuncType*) functypes; // NOTE: This have to be pointers because the type is variadic in size bh_arr(WasmFunc) funcs; - // NOTE: Maps from ast node pointers to the function index - bh_imap func_map; - i32 next_func_idx; + bh_imap func_map; // NOTE: Maps from ast node pointers to the function index bh_table(WasmExport) exports; + + bh_arr(WasmImport) imports; + + i32 next_type_idx; + i32 next_func_idx; + i32 next_import_func_idx; i32 export_count; } OnyxWasmModule; diff --git a/onyx b/onyx index e09523b81a2d60ab26149a45a80840c4abdf1129..be18df102da38964c6521c4c42c8cebd0f0ac8d6 100755 GIT binary patch delta 50823 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 IM#>KV2V72v&;S4c diff --git a/progs/minimal.onyx b/progs/minimal.onyx index 83b863d6..def47486 100644 --- a/progs/minimal.onyx +++ b/progs/minimal.onyx @@ -25,5 +25,6 @@ export do_stuff :: proc -> i32 { } export main :: proc { - output :: do_stuff(); + output := do_stuff() * (0 - 2); + print(output); } diff --git a/src/onyxparser.c b/src/onyxparser.c index b0ad3861..c98c1609 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -249,6 +249,8 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) { ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL, sym_token->pos, sym_token->token); onyx_token_null_toggle(*sym_token); + + return sym_node; } if (parser->curr_token->type != TOKEN_TYPE_OPEN_PAREN) { @@ -709,6 +711,26 @@ static OnyxAstNode* parse_top_level_symbol(OnyxParser* parser) { } } +static b32 define_function(OnyxParser* parser, OnyxAstNodeFuncDef* func) { + onyx_token_null_toggle(*func->token); + + if (!bh_table_has(OnyxAstNode *, parser->identifiers, func->token->token)) { + bh_table_put(OnyxAstNode *, parser->identifiers, func->token->token, func); + } else { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION, + func->token->pos, + func->token->token); + + // NOTE: I really wish C had defer... + onyx_token_null_toggle(*func->token); + return 0; + } + + onyx_token_null_toggle(*func->token); + return 1; +} + static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) { switch (parser->curr_token->type) { case TOKEN_TYPE_KEYWORD_USE: @@ -744,23 +766,22 @@ static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) { if (node->kind == ONYX_AST_NODE_KIND_FUNCDEF) { node->token = symbol; - onyx_token_null_toggle(*symbol); - - if (!bh_table_has(OnyxAstNode *, parser->identifiers, symbol->token)) { - bh_table_put(OnyxAstNode *, parser->identifiers, symbol->token, node); - } else { - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION, - symbol->pos, - symbol->token); - - // NOTE: I really wish C had defer... - onyx_token_null_toggle(*symbol); + if (!define_function(parser, &node->as_funcdef)) { return NULL; } + } - onyx_token_null_toggle(*symbol); + if (node->kind == ONYX_AST_NODE_KIND_FOREIGN) { + OnyxAstNodeForeign* foreign = &node->as_foreign; + + foreign->import->token = symbol; + if (foreign->import->kind == ONYX_AST_NODE_KIND_FUNCDEF) { + if (!define_function(parser, &foreign->import->as_funcdef)) { + return NULL; + } + } } + return node; } diff --git a/src/onyxwasm.c b/src/onyxwasm.c index f4515a4a..e4577803 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -440,7 +440,7 @@ static void process_return(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* ret bh_arr_push(func->code, ((WasmInstruction){ WI_RETURN, 0x00 })); } -static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) { +static i32 generate_type_idx(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) { static char type_repr_buf[128]; char* t = type_repr_buf; @@ -479,6 +479,12 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* mod->next_type_idx++; } + return type_idx; +} + +static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) { + i32 type_idx = generate_type_idx(mod, fd); + WasmFunc wasm_func = { .type_idx = type_idx, .locals = { @@ -496,7 +502,7 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* onyx_token_null_toggle(*fd->token); WasmExport wasm_export = { - .kind = WASM_EXPORT_FUNCTION, + .kind = WASM_FOREIGN_FUNCTION, .idx = func_idx, }; bh_table_put(WasmExport, mod->exports, fd->token->token, wasm_export); @@ -543,8 +549,24 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* bh_imap_clear(&mod->local_map); } -void process_foreign(OnyxWasmModule* module, OnyxAstNodeForeign* foreign) { - +static void process_foreign(OnyxWasmModule* module, OnyxAstNodeForeign* foreign) { + if (foreign->import->kind == ONYX_AST_NODE_KIND_FUNCDEF) { + i32 type_idx = generate_type_idx(module, &foreign->import->as_funcdef); + + WasmImport import = { + .kind = WASM_FOREIGN_FUNCTION, + .idx = type_idx, + .mod = foreign->mod_token, + .name = foreign->name_token, + }; + + bh_arr_push(module->imports, import); + + } else { + DEBUG_HERE; + // NOTE: Invalid foreign + assert(0); + } } OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* program) { @@ -560,10 +582,14 @@ OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* progra .exports = NULL, .export_count = 0, + + .imports = NULL, + .next_import_func_idx = 0, }; bh_arr_new(alloc, module.functypes, 4); bh_arr_new(alloc, module.funcs, 4); + bh_arr_new(alloc, module.imports, 4); bh_table_init(bh_heap_allocator(), module.type_map, 61); bh_table_init(bh_heap_allocator(), module.exports, 61); @@ -571,7 +597,18 @@ OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* progra bh_imap_init(&module.local_map, bh_heap_allocator()); bh_imap_init(&module.func_map, bh_heap_allocator()); + // NOTE: Count number of import functions OnyxAstNode* walker = program; + while (walker) { + if (walker->kind == ONYX_AST_NODE_KIND_FOREIGN + && walker->as_foreign.import->kind == ONYX_AST_NODE_KIND_FUNCDEF) { + module.next_func_idx++; + } + + walker = walker->next; + } + + walker = program; while (walker) { switch (walker->kind) { case ONYX_AST_NODE_KIND_FUNCDEF: @@ -637,6 +674,14 @@ static i32 output_vector(void** arr, i32 stride, i32 arrlen, vector_func elem, b return vec_buff->length; } +static i32 output_name(const char* start, i32 length, bh_buffer* buff) { + i32 leb_len, prev_len = buff->length; + u8* leb = uint_to_uleb128((u64) length, &leb_len); + bh_buffer_append(buff, leb, leb_len); + bh_buffer_append(buff, start, length); + return buff->length - prev_len; +} + static i32 output_functype(WasmFuncType* type, bh_buffer* buff) { i32 prev_len = buff->length; @@ -706,6 +751,35 @@ static i32 output_funcsection(OnyxWasmModule* module, bh_buffer* buff) { return buff->length - prev_len; } +static i32 output_importsection(OnyxWasmModule* module, bh_buffer* buff) { + i32 prev_len = buff->length; + bh_buffer_write_byte(buff, WASM_SECTION_ID_IMPORT); + + bh_buffer vec_buff; + bh_buffer_init(&vec_buff, buff->allocator, 128); + + i32 leb_len; + u8* leb = uint_to_uleb128((u64) (bh_arr_length(module->imports)), &leb_len); + bh_buffer_append(&vec_buff, leb, leb_len); + + bh_arr_each(WasmImport, import, module->imports) { + output_name(import->mod->token, import->mod->length, &vec_buff); + output_name(import->name->token, import->name->length, &vec_buff); + bh_buffer_write_byte(&vec_buff, (u8) import->kind); + + leb = uint_to_uleb128((u64) import->idx, &leb_len); + bh_buffer_append(&vec_buff, leb, leb_len); + } + + leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len); + bh_buffer_append(buff, leb, leb_len); + + bh_buffer_concat(buff, vec_buff); + bh_buffer_free(&vec_buff); + + return buff->length - prev_len; +} + static i32 output_exportsection(OnyxWasmModule* module, bh_buffer* buff) { i32 prev_len = buff->length; bh_buffer_write_byte(buff, WASM_SECTION_ID_EXPORT); @@ -720,9 +794,7 @@ static i32 output_exportsection(OnyxWasmModule* module, bh_buffer* buff) { i32 key_len = 0; bh_table_each_start(WasmExport, module->exports); key_len = strlen(key); - leb = uint_to_uleb128((u64) key_len, &leb_len); - bh_buffer_append(&vec_buff, leb, leb_len); - bh_buffer_append(&vec_buff, key, key_len); + output_name(key, key_len, &vec_buff); bh_buffer_write_byte(&vec_buff, (u8) (value.kind)); leb = uint_to_uleb128((u64) value.idx, &leb_len); @@ -743,7 +815,7 @@ static i32 output_startsection(OnyxWasmModule* module, bh_buffer* buff) { i32 start_idx = -1; bh_table_each_start(WasmExport, module->exports) { - if (value.kind == WASM_EXPORT_FUNCTION) { + if (value.kind == WASM_FOREIGN_FUNCTION) { if (strncmp("main", key, 5) == 0) { start_idx = value.idx; break; @@ -755,11 +827,11 @@ static i32 output_startsection(OnyxWasmModule* module, bh_buffer* buff) { bh_buffer_write_byte(buff, WASM_SECTION_ID_START); i32 start_leb_len, section_leb_len; - u8* start_leb = uint_to_uleb128((u64) start_idx, &start_leb_len); + uint_to_uleb128((u64) start_idx, &start_leb_len); u8* section_leb = uint_to_uleb128((u64) start_leb_len, §ion_leb_len); bh_buffer_append(buff, section_leb, section_leb_len); - start_leb = uint_to_uleb128((u64) start_idx, &start_leb_len); + u8* start_leb = uint_to_uleb128((u64) start_idx, &start_leb_len); bh_buffer_append(buff, start_leb, start_leb_len); } @@ -893,6 +965,7 @@ void onyx_wasm_module_write_to_file(OnyxWasmModule* module, bh_file file) { bh_buffer_append(&master_buffer, WASM_VERSION, 4); output_typesection(module, &master_buffer); + output_importsection(module, &master_buffer); output_funcsection(module, &master_buffer); output_exportsection(module, &master_buffer); output_startsection(module, &master_buffer); -- 2.25.1