From 9e8609af16e524d754b363d2ce8a4a9f98408b26 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sun, 5 Dec 2021 12:08:18 -0600 Subject: [PATCH] successfully loading a library dynamically with "#library" --- include/astnodes.h | 10 +++++++ include/onyx_library.h | 2 ++ include/wasm_emit.h | 1 + modules/test_library/module.onyx | 2 +- modules/test_library/test_library.c | 10 ++++++- src/astnodes.c | 1 + src/checker.c | 15 ++++++++++ src/entities.c | 3 +- src/parser.c | 9 ++++++ src/symres.c | 6 ++++ src/wasm_emit.c | 7 +++++ src/wasm_runtime.c | 43 ++++++++++++++++++----------- 12 files changed, 90 insertions(+), 19 deletions(-) diff --git a/include/astnodes.h b/include/astnodes.h index 66deb9a8..3f9ce101 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -41,6 +41,7 @@ NODE(DirectiveDefined) \ NODE(DirectiveTag) \ NODE(DirectiveInit) \ + NODE(DirectiveLibrary) \ \ NODE(Return) \ NODE(Jump) \ @@ -207,6 +208,7 @@ typedef enum AstKind { Ast_Kind_Directive_Defined, Ast_Kind_Directive_Tag, Ast_Kind_Directive_Init, + Ast_Kind_Directive_Library, Ast_Kind_Call_Site, Ast_Kind_Code_Block, @@ -1268,6 +1270,13 @@ struct AstMacro { AstTyped* body; }; +struct AstDirectiveLibrary { + AstNode_base; + + AstTyped *library_symbol; // This should resolve to a string literal + char *library_name; +}; + typedef enum EntityState { Entity_State_Error, @@ -1365,6 +1374,7 @@ typedef struct Entity { AstUse *use; AstInterface *interface; AstConstraint *constraint; + AstDirectiveLibrary *library; }; } Entity; diff --git a/include/onyx_library.h b/include/onyx_library.h index 2f7e8a5e..d19a8209 100644 --- a/include/onyx_library.h +++ b/include/onyx_library.h @@ -54,3 +54,5 @@ typedef struct WasmFuncDefinition { #define FLOAT WASM_F32 #define DOUBLE WASM_F64 #define PTR WASM_I32 + +#define ONYX_PTR(p) (wasm_memory_data(wasm_memory) + p) \ No newline at end of file diff --git a/include/wasm_emit.h b/include/wasm_emit.h index 5e80b038..3892b352 100644 --- a/include/wasm_emit.h +++ b/include/wasm_emit.h @@ -652,6 +652,7 @@ typedef struct OnyxWasmModule { bh_arr(WasmFunc) funcs; bh_arr(WasmDatum) data; bh_arr(i32) elems; + bh_arr(char *) libraries; // NOTE: Set of things used when compiling; not part of the actual module u32 export_count; diff --git a/modules/test_library/module.onyx b/modules/test_library/module.onyx index b0f3d387..aad1e543 100644 --- a/modules/test_library/module.onyx +++ b/modules/test_library/module.onyx @@ -1,6 +1,6 @@ package test_library -// #library "test_library" +#library "test_library" foo :: () -> void #foreign "test_library" "foo" --- add :: (a, b: i32) -> i32 #foreign "test_library" "add" --- diff --git a/modules/test_library/test_library.c b/modules/test_library/test_library.c index 16e1b0f6..d7917764 100644 --- a/modules/test_library/test_library.c +++ b/modules/test_library/test_library.c @@ -1,11 +1,19 @@ #include "onyx_library.h" #include #include +#include #define ONYX_LIBRARY_NAME test_library ONYX_DEF(foo, (), ()) { printf("This worked!\n"); + glfwInit(); + GLFWwindow *window = glfwCreateWindow(800, 600, "WOOT!", NULL, NULL); + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + glfwSwapBuffers(window); + } + glfwDestroyWindow(window); return NULL; } @@ -17,7 +25,7 @@ ONYX_DEF(add, (INT, INT), (INT)) { } ONYX_DEF(print_string, (PTR, INT), ()) { - char *start = wasm_memory_data(wasm_memory) + params->data[0].of.i32; + char *start = ONYX_PTR(params->data[0].of.i32); int length = params->data[1].of.i32; write(1, start, length); diff --git a/src/astnodes.c b/src/astnodes.c index 77fe25f8..1b849892 100644 --- a/src/astnodes.c +++ b/src/astnodes.c @@ -93,6 +93,7 @@ static const char* ast_node_names[] = { "DEFINED", "TAG", "INIT", + "LIBRARY", "CALL SITE", "CODE BLOCK", diff --git a/src/checker.c b/src/checker.c index 20cc4723..92dd8079 100644 --- a/src/checker.c +++ b/src/checker.c @@ -2495,6 +2495,21 @@ CheckStatus check_process_directive(AstNode* directive) { return Check_Complete; } + if (directive->kind == Ast_Kind_Directive_Library) { + AstDirectiveLibrary *library = (AstDirectiveLibrary *) directive; + + if (library->library_symbol->kind != Ast_Kind_StrLit) { + ERROR_(library->token->pos, "#library directive expected compile-time known string for library name. Got '%s'.", + onyx_ast_node_kind_string(library->library_symbol->kind)); + } + + AstStrLit *symbol = (AstStrLit *) library->library_symbol; + char* temp_name = bh_alloc_array(global_scratch_allocator, char, symbol->token->length); + i32 temp_name_len = string_process_escape_seqs(temp_name, symbol->token->text, symbol->token->length); + library->library_name = bh_strdup(global_heap_allocator, temp_name); + return Check_Success; + } + return Check_Success; } diff --git a/src/entities.c b/src/entities.c index 3f707abe..e9f9994b 100644 --- a/src/entities.c +++ b/src/entities.c @@ -344,7 +344,8 @@ void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* s case Ast_Kind_Directive_Add_Overload: case Ast_Kind_Directive_Tag: case Ast_Kind_Directive_Operator: - case Ast_Kind_Directive_Init: { + case Ast_Kind_Directive_Init: + case Ast_Kind_Directive_Library: { ent.type = Entity_Type_Process_Directive; ent.expr = (AstTyped *) node; ENTITY_INSERT(ent); diff --git a/src/parser.c b/src/parser.c index 05832ab1..bd044b64 100644 --- a/src/parser.c +++ b/src/parser.c @@ -3069,6 +3069,15 @@ static void parse_top_level_statement(OnyxParser* parser) { parse_init_directive(parser, parser->curr - 2); return; } + else if (parse_possible_directive(parser, "library")) { + // :LinearTokenDependent + AstDirectiveLibrary *library = make_node(AstDirectiveLibrary, Ast_Kind_Directive_Library); + library->token = parser->curr - 2; + library->library_symbol = parse_expression(parser, 0); + + ENTITY_SUBMIT(library); + return; + } else { OnyxToken* directive_token = expect_token(parser, '#'); OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol); diff --git a/src/symres.c b/src/symres.c index 24b341bf..e4abdb42 100644 --- a/src/symres.c +++ b/src/symres.c @@ -1274,6 +1274,12 @@ static SymresStatus symres_process_directive(AstNode* directive) { break; } + + case Ast_Kind_Directive_Library: { + AstDirectiveLibrary *library = (AstDirectiveLibrary *) directive; + SYMRES(expression, &library->library_symbol); + break; + } } return Symres_Success; diff --git a/src/wasm_emit.c b/src/wasm_emit.c index 5dc35c52..ffdaec22 100644 --- a/src/wasm_emit.c +++ b/src/wasm_emit.c @@ -3746,6 +3746,8 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { .foreign_function_count = 0, .null_proc_func_idx = -1, + + .libraries = NULL, }; bh_arena* eid = bh_alloc(global_heap_allocator, sizeof(bh_arena)); @@ -3759,6 +3761,7 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { bh_arr_new(alloc, module.globals, 4); bh_arr_new(alloc, module.data, 4); bh_arr_new(alloc, module.elems, 4); + bh_arr_new(alloc, module.libraries, 4); bh_arr_new(global_heap_allocator, module.return_location_stack, 4); bh_arr_new(global_heap_allocator, module.structured_jump_target, 16); @@ -3874,6 +3877,10 @@ void emit_entity(Entity* ent) { if (ent->expr->kind == Ast_Kind_Directive_Export) { emit_export_directive(module, (AstDirectiveExport *) ent->expr); } + + if (ent->expr->kind == Ast_Kind_Directive_Library) { + bh_arr_push(module->libraries, ent->library->library_name); + } break; } diff --git a/src/wasm_runtime.c b/src/wasm_runtime.c index 816093dd..735691d7 100644 --- a/src/wasm_runtime.c +++ b/src/wasm_runtime.c @@ -3,6 +3,7 @@ #include "astnodes.h" #include "wasm.h" #include "wasmer.h" +#include "onyx_library.h" #ifdef _BH_LINUX #include @@ -107,7 +108,7 @@ static i32 onyx_run_thread(void *data) { i32 thread_id = thread->id; { // Call the _thread_start procedure - wasm_val_t args[] = { WASM_I32_VAL(thread_id), WASM_I32_VAL(thread->tls_base), WASM_I32_VAL (thread->funcidx), WASM_I32_VAL(thread->dataptr) }; + wasm_val_t args[] = { WASM_I32_VAL(thread_id), WASM_I32_VAL(thread->tls_base), WASM_I32_VAL(thread->funcidx), WASM_I32_VAL(thread->dataptr) }; wasm_val_vec_t results; wasm_val_vec_t args_array = WASM_ARRAY_VEC(args); @@ -206,7 +207,7 @@ typedef struct OnyxProcess { } OnyxProcess; WASM_INTEROP(onyx_process_spawn_impl) { - char* process_str = (char *) wasm_memory_data(wasm_memory) + params->data[0].of.i32; + char* process_str = ONYX_PTR(params->data[0].of.i32); i32 process_len = params->data[1].of.i32; i32 args_ptr = params->data[2].of.i32; i32 args_len = params->data[3].of.i32; @@ -217,19 +218,18 @@ WASM_INTEROP(onyx_process_spawn_impl) { memcpy(process_path, process_str, process_len); process_path[process_len] = '\0'; - OnyxProcess *process = bh_alloc_item(global_heap_allocator, OnyxProcess); + OnyxProcess *process = malloc(sizeof(OnyxProcess)); memset(process, 0, sizeof(*process)); process->magic_number = ONYX_PROCESS_MAGIC_NUMBER; #ifdef _BH_LINUX - char **process_args = bh_alloc_array(global_scratch_allocator, char *, args_len + 2); - byte_t* data = wasm_memory_data(wasm_memory); - byte_t* array_loc = data + args_ptr; + char **process_args = alloca(sizeof(char *) * (args_len + 2)); + byte_t* array_loc = ONYX_PTR(args_ptr); fori (i, 0, args_len) { - char *arg_str = data + *(i32 *) (array_loc + i * 2 * POINTER_SIZE); + char *arg_str = ONYX_PTR(*(i32 *) (array_loc + i * 2 * POINTER_SIZE)); i32 arg_len = *(i32 *) (array_loc + i * 2 * POINTER_SIZE + POINTER_SIZE); - char *arg = bh_alloc_array(global_scratch_allocator, char, arg_len + 1); + char *arg = alloca(sizeof(char) * (arg_len + 1)); memcpy(arg, arg_str, arg_len); arg[arg_len] = '\0'; process_args[i + 1] = arg; @@ -287,8 +287,7 @@ WASM_INTEROP(onyx_process_spawn_impl) { memset(cmdLine, 0, 2048); strncat(cmdLine, process_path, 2047); - byte_t* data = wasm_memory_data(wasm_memory); - byte_t* array_loc = data + args_ptr; + byte_t* array_loc = ONYX_PTR(args_ptr); fori (i, 0, args_len) { char *arg_str = data + *(i32 *) (array_loc + i * 2 * POINTER_SIZE); i32 arg_len = *(i32 *) (array_loc + i * 2 * POINTER_SIZE + 4); @@ -355,7 +354,7 @@ WASM_INTEROP(onyx_process_read_impl) { i32 output_ptr = params->data[1].of.i32; i32 output_len = params->data[2].of.i32; - u8 *buffer = wasm_memory_data(wasm_memory) + output_ptr; + u8 *buffer = ONYX_PTR(output_ptr); i32 bytes_read; #ifdef _BH_LINUX @@ -381,7 +380,7 @@ WASM_INTEROP(onyx_process_write_impl) { i32 input_ptr = params->data[1].of.i32; i32 input_len = params->data[2].of.i32; - u8 *buffer = wasm_memory_data(wasm_memory) + input_ptr; + u8 *buffer = ONYX_PTR(input_ptr); i32 bytes_written; #ifdef _BH_LINUX @@ -494,13 +493,11 @@ WASM_INTEROP(onyx_process_destroy_impl) { } #endif - bh_free(global_heap_allocator, process); + free(process); return NULL; } -#include "onyx_library.h" - typedef void *(*LibraryLinker)(); static bh_arr(WasmFuncDefinition **) linkable_functions = NULL; @@ -517,16 +514,30 @@ static void onyx_load_library(char *name) { } library_load = (LibraryLinker) dlsym(handle, library_load_name); + if (library_load == NULL) { + printf("ERROR RESOLVING '%s': %s\n", library_load_name, dlerror()); + return; + } #endif WasmFuncDefinition** funcs = library_load(); bh_arr_push(linkable_functions, funcs); } +// NOCHECKIN TEMPORARY HACK +// NOCHECKIN TEMPORARY HACK +// NOCHECKIN TEMPORARY HACK +#include "wasm_emit.h" + // Returns 1 if successful b32 onyx_run_wasm(bh_buffer wasm_bytes) { bh_arr_new(global_heap_allocator, linkable_functions, 4); - onyx_load_library("test_library"); + + // NOCHECKIN TEMPORARY HACK + OnyxWasmModule* onyx_wasm_module = (OnyxWasmModule *) context.wasm_module; + bh_arr_each(char *, library_name, onyx_wasm_module->libraries) { + onyx_load_library(*library_name); + } wasm_instance_t* instance = NULL; wasmer_features_t* features = NULL; -- 2.25.1