From: Brendan Hansen Date: Sat, 10 Oct 2020 04:06:46 +0000 (-0500) Subject: BIG CHANGES TO COMPILER ARCHITECTURE; using entity pumping system X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=b98ecb14b2c37b9ab2f9d3b6ac13f2e425a511ee;p=onyx.git BIG CHANGES TO COMPILER ARCHITECTURE; using entity pumping system --- diff --git a/Makefile b/Makefile index b073230e..65688706 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ OBJ_FILES=\ build/onyxclone.o \ build/onyxtypes.o \ build/onyxbuiltins.o \ + build/onyxentities.o \ build/onyxsempass.o \ build/onyxsymres.o \ build/onyxchecker.o \ diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 11995de3..e3ee250f 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -608,7 +608,7 @@ struct AstTypeRawAlias { AstType_base; Type* to; }; // Top level nodes struct AstBinding { AstTyped_base; AstNode* node; }; struct AstMemRes { AstTyped_base; u64 addr; AstTyped *initial_value; }; -struct AstInclude { AstNode_base; OnyxToken *name; }; +struct AstInclude { AstNode_base; char* name; }; struct AstUsePackage { AstNode_base; @@ -691,10 +691,26 @@ struct AstPackage { Package* package; }; +typedef enum EntityState { + Entity_State_Error, + + Entity_State_Parse_Builtin, + Entity_State_Parse, + Entity_State_Resolve_Symbols, + Entity_State_Check_Types, + Entity_State_Code_Gen, + Entity_State_Finalized, + + Entity_State_Count, +} EntityState; + // NOTE: An Entity represents something will need to be // processed later down the pipeline. typedef enum EntityType { Entity_Type_Unknown, + + Entity_Type_Include_Folder, + Entity_Type_Include_File, Entity_Type_Use_Package, Entity_Type_String_Literal, Entity_Type_File_Contents, @@ -703,20 +719,25 @@ typedef enum EntityType { Entity_Type_Memory_Reservation, Entity_Type_Polymorphic_Proc, Entity_Type_Foreign_Function_Header, + Entity_Type_Foreign_Global_Header, Entity_Type_Function_Header, Entity_Type_Global_Header, Entity_Type_Expression, Entity_Type_Global, Entity_Type_Overloaded_Function, Entity_Type_Function, + + Entity_Type_Count, } EntityType; typedef struct Entity { EntityType type; + EntityState state; Package *package; Scope *scope; union { + AstInclude *include; AstUsePackage *use_package; AstFunction *function; AstOverloadedFunction *overloaded_function; @@ -731,6 +752,21 @@ typedef struct Entity { }; } Entity; +typedef struct EntityHeap { + bh_arr(Entity) entities; + + i32 state_count[Entity_State_Count]; +} EntityHeap; + +void entity_heap_insert(EntityHeap* entities, Entity e); +Entity entity_heap_top(EntityHeap* entities); +void entity_heap_change_top(EntityHeap* entities, Entity new_top); +void entity_heap_remove_top(EntityHeap* entities); + +void symres_entity(Entity* ent); +void check_entity(Entity* ent); +void emit_entity(Entity* ent); + struct Package { char *name; @@ -743,13 +779,11 @@ typedef struct ProgramInfo { Scope *global_scope; bh_table(Package *) packages; - bh_arr(Entity) entities; + EntityHeap entities; u32 foreign_global_count; } ProgramInfo; -i32 sort_entities(const void* e1, const void* e2); - // NOTE: Basic internal types constructed in the parser extern AstBasicType basic_type_void; extern AstBasicType basic_type_bool; diff --git a/include/onyxsempass.h b/include/onyxsempass.h index d5af9acf..9293353b 100644 --- a/include/onyxsempass.h +++ b/include/onyxsempass.h @@ -14,7 +14,6 @@ typedef struct SemState { // NOTE: Used wherever ProgramInfo* program; - bh_arr(Entity) other_entities; // NOTE: Used in symbol resolution phase Package* curr_package; @@ -31,21 +30,14 @@ typedef struct SemState { extern SemState semstate; -// NOTE: Resolving all symbols in the tree -void onyx_resolve_symbols(); - AstType* symres_type(AstType* type); void symres_function(AstFunction* func); -// NOTE: Inferring and checking types in the tree -void onyx_type_check(); - b32 check_expression(AstTyped** expr); b32 check_function_header(AstFunction* func); b32 check_function(AstFunction* func); -// NOTE: Full semantic pass +// TODO: This should be moved elsewhere. void onyx_sempass_init(bh_allocator alloc, bh_allocator node_alloc); -void onyx_sempass(ProgramInfo* program); #endif diff --git a/include/onyxwasm.h b/include/onyxwasm.h index e9dcdaed..a86b140a 100644 --- a/include/onyxwasm.h +++ b/include/onyxwasm.h @@ -531,9 +531,10 @@ typedef struct OnyxWasmModule { u32 next_type_idx; u32 next_func_idx; u32 next_global_idx; - u32 next_foreign_global_idx; u32 next_datum_offset; u32 next_elem_idx; + u32 foreign_function_count; + u32 foreign_global_count; i32 *stack_top_ptr; u64 stack_base_idx; @@ -542,6 +543,8 @@ typedef struct OnyxWasmModule { b32 has_stack_locals : 1; } OnyxWasmModule; +extern OnyxWasmModule global_wasm_module; + OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc); void onyx_wasm_module_compile(OnyxWasmModule* module, ProgramInfo* program); void onyx_wasm_module_free(OnyxWasmModule* module); diff --git a/onyx b/onyx index 77f2b16c..3ff6901b 100755 Binary files a/onyx and b/onyx differ diff --git a/src/onyx.c b/src/onyx.c index a5a6d789..d961cf5f 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -141,8 +141,7 @@ static void compile_opts_free(OnyxCompileOptions* opts) { typedef enum CompilerProgress { ONYX_COMPILER_PROGRESS_FAILED_READ, ONYX_COMPILER_PROGRESS_FAILED_PARSE, - ONYX_COMPILER_PROGRESS_FAILED_SEMPASS, - ONYX_COMPILER_PROGRESS_FAILED_BINARY_GEN, + ONYX_COMPILER_PROGRESS_ERROR, ONYX_COMPILER_PROGRESS_FAILED_OUTPUT, ONYX_COMPILER_PROGRESS_SUCCESS } CompilerProgress; @@ -154,14 +153,19 @@ typedef struct CompilerState { bh_allocator token_alloc, ast_alloc, sp_alloc; bh_table(bh_file_contents) loaded_files; - bh_arr(const char *) queued_files; ProgramInfo prog_info; - OnyxWasmModule wasm_mod; } CompilerState; static char* lookup_included_file(CompilerState* cs, char* filename); +static AstInclude* create_include_file(bh_allocator alloc, char* filename) { + AstInclude* include_node = onyx_ast_node_new(alloc, sizeof(AstInclude), Ast_Kind_Include_File); + include_node->name = filename; + + return include_node; +} + static void compiler_state_init(CompilerState* compiler_state, OnyxCompileOptions* opts) { compiler_state->options = opts; @@ -180,30 +184,46 @@ static void compiler_state_init(CompilerState* compiler_state, OnyxCompileOption bh_arena_init(&compiler_state->sp_arena, opts->allocator, 16 * 1024); compiler_state->sp_alloc = bh_arena_allocator(&compiler_state->sp_arena); - bh_arr_new(opts->allocator, compiler_state->queued_files, 4); + onyx_sempass_init(compiler_state->sp_alloc, compiler_state->ast_alloc); + + // HACK + global_wasm_module = onyx_wasm_module_create(compiler_state->options->allocator); - bh_arr_push(compiler_state->queued_files, lookup_included_file(compiler_state, "core/builtin")); + entity_heap_insert(&compiler_state->prog_info.entities, ((Entity) { + .state = Entity_State_Parse_Builtin, + .type = Entity_Type_Include_File, + .package = NULL, + .include = create_include_file(compiler_state->sp_alloc, "core/builtin"), + })); // NOTE: Add all files passed by command line to the queue - bh_arr_each(const char *, filename, opts->files) - bh_arr_push(compiler_state->queued_files, (char *) *filename); + bh_arr_each(const char *, filename, opts->files) { + entity_heap_insert(&compiler_state->prog_info.entities, ((Entity) { + .state = Entity_State_Parse, + .type = Entity_Type_Include_File, + .package = NULL, + .include = create_include_file(compiler_state->sp_alloc, (char *) *filename), + })); + } } static void compiler_state_free(CompilerState* cs) { bh_arena_free(&cs->ast_arena); bh_arena_free(&cs->sp_arena); bh_table_free(cs->loaded_files); - onyx_wasm_module_free(&cs->wasm_mod); } - - +// NOTE: This should not be called until immediately before using the return value. +// This function can return a static variable which will change if this is called +// another time. -brendanfh 2020/10/09 static char* lookup_included_file(CompilerState* cs, char* filename) { static char path[256]; - fori (i, 0, 256) path[i] = 0; + fori (i, 0, 256) + path[i] = 0; static char fn[128]; fori (i, 0, 128) fn[i] = 0; + if (!bh_str_ends_with(filename, ".onyx")) { bh_snprintf(fn, 128, "%s.onyx", filename); } else { @@ -239,17 +259,16 @@ static ParseResults parse_source_file(CompilerState* compiler_state, bh_file_con static void merge_parse_results(CompilerState* compiler_state, ParseResults* results) { bh_arr_each(AstInclude *, include, results->includes) { - if ((*include)->kind == Ast_Kind_Include_File) { - token_toggle_end((*include)->name); - char* filename = lookup_included_file(compiler_state, (*include)->name->text); - token_toggle_end((*include)->name); - - char* formatted_name = bh_strdup(global_heap_allocator, filename); - bh_arr_push(compiler_state->queued_files, formatted_name); - } else if ((*include)->kind == Ast_Kind_Include_Folder) { - const char* folder = bh_aprintf(global_heap_allocator, "%b", (*include)->name->text, (*include)->name->length); - bh_arr_push(compiler_state->options->included_folders, folder); - } + EntityType et = Entity_Type_Include_File; + if ((*include)->kind == Ast_Kind_Include_Folder) + et = Entity_Type_Include_Folder; + + entity_heap_insert(&compiler_state->prog_info.entities, (Entity) { + .state = Entity_State_Parse, + .type = et, + .scope = NULL, + .include = *include, + }); } Entity ent; @@ -257,6 +276,7 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res AstNode* node = n->node; AstKind nkind = node->kind; + ent.state = Entity_State_Resolve_Symbols; ent.package = n->package; ent.scope = n->scope; @@ -265,16 +285,16 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res if ((node->flags & Ast_Flag_Foreign) != 0) { ent.type = Entity_Type_Foreign_Function_Header; ent.function = (AstFunction *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); } else { ent.type = Entity_Type_Function_Header; ent.function = (AstFunction *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); ent.type = Entity_Type_Function; ent.function = (AstFunction *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); } break; } @@ -282,32 +302,39 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res case Ast_Kind_Overloaded_Function: { ent.type = Entity_Type_Overloaded_Function; ent.overloaded_function = (AstOverloadedFunction *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); break; } case Ast_Kind_Global: { - ent.type = Entity_Type_Global_Header; - ent.global = (AstGlobal *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + if ((node->flags & Ast_Flag_Foreign) != 0) { + ent.type = Entity_Type_Foreign_Global_Header; + ent.global = (AstGlobal *) node; + entity_heap_insert(&compiler_state->prog_info.entities, ent); - ent.type = Entity_Type_Global; - ent.global = (AstGlobal *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + } else { + ent.type = Entity_Type_Global_Header; + ent.global = (AstGlobal *) node; + entity_heap_insert(&compiler_state->prog_info.entities, ent); + + ent.type = Entity_Type_Global; + ent.global = (AstGlobal *) node; + entity_heap_insert(&compiler_state->prog_info.entities, ent); + } break; } case Ast_Kind_StrLit: { ent.type = Entity_Type_String_Literal; ent.strlit = (AstStrLit *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); break; } case Ast_Kind_File_Contents: { ent.type = Entity_Type_File_Contents; ent.file_contents = (AstFileContents *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); break; } @@ -316,42 +343,42 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res case Ast_Kind_Poly_Struct_Type: { ent.type = Entity_Type_Type_Alias; ent.type_alias = (AstType *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); break; } case Ast_Kind_Enum_Type: { ent.type = Entity_Type_Enum; ent.enum_type = (AstEnumType *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); break; } case Ast_Kind_Use_Package: { ent.type = Entity_Type_Use_Package; ent.use_package = (AstUsePackage *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); break; } case Ast_Kind_Memres: { ent.type = Entity_Type_Memory_Reservation; ent.mem_res = (AstMemRes *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); break; } case Ast_Kind_Polymorphic_Proc: { ent.type = Entity_Type_Polymorphic_Proc; ent.poly_proc = (AstPolyProc *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); break; } default: { ent.type = Entity_Type_Expression; ent.expr = (AstTyped *) node; - bh_arr_push(compiler_state->prog_info.entities, ent); + entity_heap_insert(&compiler_state->prog_info.entities, ent); break; } } @@ -369,7 +396,8 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char* bh_file_error err = bh_file_open(&file, filename); if (err != BH_FILE_ERROR_NONE) { - bh_printf_err("Failed to open file %s\n", filename); + // bh_printf_err("Failed to open file %s\n", filename); + onyx_report_error((OnyxFilePos) { 0 }, "Failed to open file %s\n", filename); return ONYX_COMPILER_PROGRESS_FAILED_READ; } @@ -407,98 +435,90 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char* } } +static b32 process_include_entity(CompilerState* compiler_state, Entity* ent) { + assert(ent->type == Entity_Type_Include_File || ent->type == Entity_Type_Include_Folder); + AstInclude* include = ent->include; -static i32 onyx_compile(CompilerState* compiler_state) { + if (include->kind == Ast_Kind_Include_File) { + char* filename = lookup_included_file(compiler_state, include->name); -#ifdef REPORT_TIMES - timer_stack_push("Parsing"); -#endif + char* formatted_name = bh_strdup(global_heap_allocator, filename); + process_source_file(compiler_state, formatted_name); - // NOTE: While the queue is not empty, process the next file - while (!bh_arr_is_empty(compiler_state->queued_files)) { - CompilerProgress result = process_source_file(compiler_state, (char *) compiler_state->queued_files[0]); + } else if (include->kind == Ast_Kind_Include_Folder) { + bh_arr_push(compiler_state->options->included_folders, include->name); + } - if (result != ONYX_COMPILER_PROGRESS_SUCCESS) - return result; + return 1; +} - bh_arr_fastdelete(compiler_state->queued_files, 0); - } +static b32 process_entity(CompilerState* compiler_state, Entity* ent) { + i32 changed = 1; -#ifdef REPORT_TIMES - timer_stack_pop(); - - timer_stack_push("Checking semantics"); - timer_stack_push("Initializing builtins"); -#endif + switch (ent->state) { + case Entity_State_Parse_Builtin: + case Entity_State_Parse: + process_include_entity(compiler_state, ent); + ent->state = Entity_State_Finalized; + break; - initialize_builtins(compiler_state->ast_alloc, &compiler_state->prog_info); - if (onyx_has_errors()) { - return ONYX_COMPILER_PROGRESS_FAILED_SEMPASS; + case Entity_State_Resolve_Symbols: symres_entity(ent); break; + case Entity_State_Check_Types: check_entity(ent); break; + case Entity_State_Code_Gen: emit_entity(ent); break; + + default: + changed = 0; } - // Add builtin one-time entities - bh_arr_push(compiler_state->prog_info.entities, ((Entity) { - .type = Entity_Type_Global_Header, - .global = &builtin_stack_top - })); - bh_arr_push(compiler_state->prog_info.entities, ((Entity) { - .type = Entity_Type_Global, - .global = &builtin_stack_top - })); + return changed; +} - qsort(compiler_state->prog_info.entities, - bh_arr_length(compiler_state->prog_info.entities), - sizeof(Entity), - sort_entities); -#ifdef REPORT_TIMES - timer_stack_pop(); -#endif +static i32 onyx_compile(CompilerState* compiler_state) { + { + entity_heap_insert(&compiler_state->prog_info.entities, ((Entity) { + .state = Entity_State_Resolve_Symbols, + .type = Entity_Type_Global_Header, + .global = &builtin_stack_top + })); + entity_heap_insert(&compiler_state->prog_info.entities, ((Entity) { + .state = Entity_State_Resolve_Symbols, + .type = Entity_Type_Global, + .global = &builtin_stack_top + })); - // NOTE: Check types and semantic rules - if (compiler_state->options->verbose_output) - bh_printf("[Checking semantics]\n"); + Entity ent = entity_heap_top(&compiler_state->prog_info.entities); + assert(ent.state == Entity_State_Parse_Builtin); + DEBUG_HERE; - onyx_sempass_init(compiler_state->sp_alloc, compiler_state->ast_alloc); - onyx_sempass(&compiler_state->prog_info); + process_entity(compiler_state, &ent); -#ifdef REPORT_TIMES - timer_stack_pop(); -#endif + if (onyx_has_errors()) return ONYX_COMPILER_PROGRESS_ERROR; - if (onyx_has_errors()) { - return ONYX_COMPILER_PROGRESS_FAILED_SEMPASS; - } + entity_heap_remove_top(&compiler_state->prog_info.entities); - if (compiler_state->options->action == ONYX_COMPILE_ACTION_DOCUMENT) { - OnyxDocumentation docs = onyx_docs_generate(&compiler_state->prog_info); - docs.format = Doc_Format_Tags; - onyx_docs_emit(&docs); + initialize_builtins(compiler_state->ast_alloc, &compiler_state->prog_info); - return ONYX_COMPILER_PROGRESS_SUCCESS; + semstate.program = &compiler_state->prog_info; } - // NOTE: Generate WASM instructions - if (compiler_state->options->verbose_output) - bh_printf("[Generating WASM]\n"); + while (!bh_arr_is_empty(compiler_state->prog_info.entities.entities)) { + Entity ent = entity_heap_top(&compiler_state->prog_info.entities); + b32 changed = process_entity(compiler_state, &ent); -#ifdef REPORT_TIMES - timer_stack_push("Code generation"); - timer_stack_push("Generating WASM"); -#endif - - compiler_state->wasm_mod = onyx_wasm_module_create(compiler_state->options->allocator); - onyx_wasm_module_compile(&compiler_state->wasm_mod, &compiler_state->prog_info); + if (onyx_has_errors()) { + return ONYX_COMPILER_PROGRESS_ERROR; + } - if (onyx_has_errors()) { - return ONYX_COMPILER_PROGRESS_FAILED_BINARY_GEN; + if (changed) { + if (ent.state == Entity_State_Finalized) { + entity_heap_remove_top(&compiler_state->prog_info.entities); + } else { + entity_heap_change_top(&compiler_state->prog_info.entities, ent); + } + } } -#ifdef REPORT_TIMES - timer_stack_pop(); - timer_stack_push("Write to file"); -#endif - // NOTE: Output to file bh_file output_file; if (bh_file_create(&output_file, compiler_state->options->target_file) != BH_FILE_ERROR_NONE) { @@ -508,12 +528,7 @@ static i32 onyx_compile(CompilerState* compiler_state) { if (compiler_state->options->verbose_output) bh_printf("[Writing WASM] %s\n", output_file.filename); - onyx_wasm_module_write_to_file(&compiler_state->wasm_mod, output_file); - -#ifdef REPORT_TIMES - timer_stack_pop(); - timer_stack_pop(); -#endif + onyx_wasm_module_write_to_file(&global_wasm_module, output_file); return ONYX_COMPILER_PROGRESS_SUCCESS; } @@ -553,8 +568,7 @@ int main(int argc, char *argv[]) { break; case ONYX_COMPILER_PROGRESS_FAILED_PARSE: - case ONYX_COMPILER_PROGRESS_FAILED_SEMPASS: - case ONYX_COMPILER_PROGRESS_FAILED_BINARY_GEN: + case ONYX_COMPILER_PROGRESS_ERROR: onyx_errors_print(); break; diff --git a/src/onyxchecker.c b/src/onyxchecker.c index bbd7fcf3..1fcd0e5d 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -1468,55 +1468,44 @@ b32 check_node(AstNode* node) { } } -void onyx_type_check() { - bh_arr_each(Entity, entity, semstate.program->entities) { - switch (entity->type) { - case Entity_Type_Foreign_Function_Header: - case Entity_Type_Function_Header: - if (check_function_header(entity->function)) return; - break; - - case Entity_Type_Function: - if (check_function(entity->function)) return; - break; - - case Entity_Type_Overloaded_Function: - if (check_overloaded_function(entity->overloaded_function)) return; - break; - - case Entity_Type_Global: - if (entity->global->flags & Ast_Flag_Foreign) - semstate.program->foreign_global_count++; - - if (check_global(entity->global)) return; - break; - - case Entity_Type_Expression: - if (check_expression(&entity->expr)) return; - break; - - case Entity_Type_Type_Alias: - if (entity->type_alias->kind == Ast_Kind_Struct_Type) - if (check_struct((AstStructType *) entity->type_alias)) return; - break; +void check_entity(Entity* ent) { + switch (ent->type) { + case Entity_Type_Foreign_Function_Header: + case Entity_Type_Function_Header: + if (check_function_header(ent->function)) return; + break; - case Entity_Type_Memory_Reservation: - if (check_memres(entity->mem_res)) return; - break; + case Entity_Type_Function: + if (check_function(ent->function)) return; + break; - case Entity_Type_Enum: break; + case Entity_Type_Overloaded_Function: + if (check_overloaded_function(ent->overloaded_function)) return; + break; - case Entity_Type_String_Literal: break; + case Entity_Type_Foreign_Global_Header: + semstate.program->foreign_global_count++; + // fallthrough - case Entity_Type_File_Contents: break; + case Entity_Type_Global: + if (check_global(ent->global)) return; + break; - case Entity_Type_Global_Header: break; + case Entity_Type_Expression: + if (check_expression(&ent->expr)) return; + break; - case Entity_Type_Use_Package: break; + case Entity_Type_Type_Alias: + if (ent->type_alias->kind == Ast_Kind_Struct_Type) + if (check_struct((AstStructType *) ent->type_alias)) return; + break; - case Entity_Type_Polymorphic_Proc: break; + case Entity_Type_Memory_Reservation: + if (check_memres(ent->mem_res)) return; + break; - default: DEBUG_HERE; break; - } + default: break; } -} + + ent->state = Entity_State_Code_Gen; +} \ No newline at end of file diff --git a/src/onyxentities.c b/src/onyxentities.c new file mode 100644 index 00000000..55a5a800 --- /dev/null +++ b/src/onyxentities.c @@ -0,0 +1,78 @@ +#include "bh.h" +#include "onyxastnodes.h" +#include "onyxutils.h" + +// NOTE: Returns >0 if e1 should be processed after e2. +static i32 entity_compare(Entity* e1, Entity* e2) { + if (e1->state != e2->state) + return (i32) e1->state - (i32) e2->state; + else + return (i32) e1->type - (i32) e2->type; +} + +#define eh_parent(index) (((index) - 1) / 2) +#define eh_lchild(index) (((index) * 2) + 1) +#define eh_rchild(index) (((index) * 2) + 2) + +static void eh_shift_up(EntityHeap* entities, i32 index) { + while (index > 0 && entity_compare(&entities->entities[eh_parent(index)], &entities->entities[index]) > 0) { + Entity tmp = entities->entities[eh_parent(index)]; + entities->entities[eh_parent(index)] = entities->entities[index]; + entities->entities[index] = tmp; + + index = eh_parent(index); + } +} + +static void eh_shift_down(EntityHeap* entities, i32 index) { + i32 min_index = index; + + i32 l = eh_lchild(index); + if (l < bh_arr_length(entities->entities) + && entity_compare(&entities->entities[l], &entities->entities[min_index]) <= 0) { + min_index = l; + } + + i32 r = eh_rchild(index); + if (r < bh_arr_length(entities->entities) + && entity_compare(&entities->entities[r], &entities->entities[min_index]) <= 0) { + min_index = r; + } + + if (index != min_index) { + Entity tmp = entities->entities[min_index]; + entities->entities[min_index] = entities->entities[index]; + entities->entities[index] = tmp; + + eh_shift_down(entities, min_index); + } +} + +void entity_heap_insert(EntityHeap* entities, Entity e) { + if (entities->entities == NULL) { + bh_arr_new(global_heap_allocator, entities->entities, 128); + } + + bh_arr_push(entities->entities, e); + eh_shift_up(entities, bh_arr_length(entities->entities) - 1); + + entities->state_count[e.state]++; +} + +Entity entity_heap_top(EntityHeap* entities) { + return entities->entities[0]; +} + +void entity_heap_change_top(EntityHeap* entities, Entity new_top) { + entities->state_count[entities->entities[0].state]--; + entities->state_count[new_top.state]--; + + entities->entities[0] = new_top; + eh_shift_down(entities, 0); +} + +void entity_heap_remove_top(EntityHeap* entities) { + entities->entities[0] = entities->entities[bh_arr_length(entities->entities) - 1]; + bh_arr_pop(entities->entities); + eh_shift_down(entities, 0); +} diff --git a/src/onyxparser.c b/src/onyxparser.c index cc389240..64ebfe6c 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -1965,14 +1965,26 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) { if (parse_possible_directive(parser, "include_file")) { AstInclude* include = make_node(AstInclude, Ast_Kind_Include_File); include->token = dir_token; - include->name = expect_token(parser, Token_Type_Literal_String); + + OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String); + if (str_token != NULL) { + token_toggle_end(str_token); + include->name = bh_strdup(parser->allocator, str_token->text); + token_toggle_end(str_token); + } return (AstNode *) include; } else if (parse_possible_directive(parser, "include_folder")) { AstInclude* include = make_node(AstInclude, Ast_Kind_Include_Folder); include->token = dir_token; - include->name = expect_token(parser, Token_Type_Literal_String); + + OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String); + if (str_token != NULL) { + token_toggle_end(str_token); + include->name = bh_strdup(parser->allocator, str_token->text); + token_toggle_end(str_token); + } return (AstNode *) include; } diff --git a/src/onyxsempass.c b/src/onyxsempass.c index 73e33595..3de8b26c 100644 --- a/src/onyxsempass.c +++ b/src/onyxsempass.c @@ -1,3 +1,5 @@ +// TODO: This file has become useless. It should be removed soon. + #define BH_DEBUG #include "onyxsempass.h" #include "onyxutils.h" @@ -13,30 +15,9 @@ void onyx_sempass_init(bh_allocator alloc, bh_allocator node_alloc) { .curr_scope = NULL, .block_stack = NULL, - .other_entities = NULL, .defer_allowed = 1, }; bh_arr_new(global_heap_allocator, semstate.block_stack, 4); - bh_arr_new(global_heap_allocator, semstate.other_entities, 4); -} - -void onyx_sempass(ProgramInfo* program) { - semstate.program = program; - - onyx_resolve_symbols(program); - if (onyx_has_errors()) return; - - onyx_type_check(program); - - if (bh_arr_length(semstate.other_entities) > 0) { - bh_arr_each(Entity, e, semstate.other_entities) - bh_arr_push(semstate.program->entities, *e); - - qsort(semstate.program->entities, bh_arr_length(semstate.program->entities), sizeof(Entity), sort_entities); - bh_arr_clear(semstate.other_entities); - } - - if (onyx_has_errors()) return; } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 34aa440b..d75a4aae 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -774,33 +774,30 @@ static void symres_polyproc(AstPolyProc* pp) { pp->poly_scope = scope_create(semstate.node_allocator, semstate.curr_scope, pp->token->pos); } -void onyx_resolve_symbols() { +void symres_entity(Entity* ent) { + if (ent->package) { + scope_enter(ent->scope); + semstate.curr_package = ent->package; + } + + switch (ent->type) { + case Entity_Type_Foreign_Function_Header: + case Entity_Type_Function: symres_function(ent->function); break; + + case Entity_Type_Use_Package: symres_use_package(ent->use_package); break; + case Entity_Type_Overloaded_Function: symres_overloaded_function(ent->overloaded_function); break; + case Entity_Type_Global: symres_global(ent->global); break; + case Entity_Type_Expression: symres_expression(&ent->expr); break; + case Entity_Type_Type_Alias: ent->type_alias = symres_type(ent->type_alias); break; + case Entity_Type_Enum: symres_enum(ent->enum_type); break; + case Entity_Type_Memory_Reservation: symres_memres(&ent->mem_res); break; + case Entity_Type_Polymorphic_Proc: symres_polyproc(ent->poly_proc); break; + case Entity_Type_String_Literal: symres_expression(&ent->expr); break; - semstate.curr_scope = semstate.program->global_scope; + default: break; + } - bh_arr_each(Entity, entity, semstate.program->entities) { - if (entity->package) { - scope_enter(entity->scope); - semstate.curr_package = entity->package; - } + ent->state = Entity_State_Check_Types; - switch (entity->type) { - case Entity_Type_Foreign_Function_Header: - case Entity_Type_Function: symres_function(entity->function); break; - - case Entity_Type_Use_Package: symres_use_package(entity->use_package); break; - case Entity_Type_Overloaded_Function: symres_overloaded_function(entity->overloaded_function); break; - case Entity_Type_Global: symres_global(entity->global); break; - case Entity_Type_Expression: symres_expression(&entity->expr); break; - case Entity_Type_Type_Alias: entity->type_alias = symres_type(entity->type_alias); break; - case Entity_Type_Enum: symres_enum(entity->enum_type); break; - case Entity_Type_Memory_Reservation: symres_memres(&entity->mem_res); break; - case Entity_Type_Polymorphic_Proc: symres_polyproc(entity->poly_proc); break; - case Entity_Type_String_Literal: symres_expression(&entity->expr); break; - - default: break; - } - - if (entity->package) scope_leave(); - } -} + if (ent->package) scope_leave(); +} \ No newline at end of file diff --git a/src/onyxutils.c b/src/onyxutils.c index c39768d4..2aa7b5e4 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -101,8 +101,8 @@ void program_info_init(ProgramInfo* prog, bh_allocator alloc) { bh_table_init(alloc, prog->packages, 16); - prog->entities = NULL; - bh_arr_new(alloc, prog->entities, 4); + // NOTE: This will be initialized upon the first call to entity_heap_insert. + prog->entities.entities = NULL; } Package* program_info_package_lookup(ProgramInfo* prog, char* package_name) { @@ -537,8 +537,6 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lo if (onyx_has_errors()) goto has_error; if (check_function_header(func)) goto has_error; - if (check_function(func)) goto has_error; - if (onyx_has_errors()) goto has_error; goto no_errors; has_error: @@ -549,16 +547,19 @@ has_error: no_errors: semstate.expected_return_type = old_return_type; - bh_arr_push(semstate.other_entities, ((Entity) { + entity_heap_insert(&semstate.program->entities, (Entity) { + .state = Entity_State_Code_Gen, .type = Entity_Type_Function_Header, .function = func, .package = NULL, - })); - bh_arr_push(semstate.other_entities, ((Entity) { + }); + + entity_heap_insert(&semstate.program->entities, (Entity) { + .state = Entity_State_Check_Types, .type = Entity_Type_Function, .function = func, .package = NULL, - })); + }); return func; } @@ -641,7 +642,3 @@ no_errors: return concrete_struct; } - -i32 sort_entities(const void* e1, const void* e2) { - return ((Entity *)e1)->type - ((Entity *)e2)->type; -} diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 3d5acfc1..0a4611b8 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -2,6 +2,8 @@ #include "onyxwasm.h" #include "onyxutils.h" +OnyxWasmModule global_wasm_module; + // NOTE: Allows easier testing of types since most of the characters // corresponding to these values are not printable #if 1 @@ -2666,11 +2668,11 @@ static void emit_function(OnyxWasmModule* mod, AstFunction* fd) { bh_arr_new(mod->allocator, wasm_func.code, 4); + i32 func_idx = (i32) bh_imap_get(&mod->index_map, (u64) fd); + if (fd->flags & Ast_Flag_Exported) { token_toggle_end(fd->exported_name); - i32 func_idx = (i32) bh_imap_get(&mod->index_map, (u64) fd); - WasmExport wasm_export = { .kind = WASM_FOREIGN_FUNCTION, .idx = func_idx, @@ -2734,7 +2736,10 @@ static void emit_function(OnyxWasmModule* mod, AstFunction* fd) { bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_BLOCK_END, 0x00 })); - bh_arr_push(mod->funcs, wasm_func); + // HACK: This is gross + bh_arr_grow(mod->funcs, func_idx - mod->foreign_function_count + 1); + mod->funcs[func_idx - mod->foreign_function_count] = wasm_func; + bh_arr_set_length(mod->funcs, bh_max(bh_arr_length(mod->funcs), func_idx - mod->foreign_function_count + 1)); // NOTE: Clear the local map on exit of generating this function bh_imap_clear(&mod->local_map); @@ -2759,29 +2764,17 @@ static void emit_foreign_function(OnyxWasmModule* mod, AstFunction* fd) { static void emit_global(OnyxWasmModule* module, AstGlobal* global) { WasmType global_type = onyx_type_to_wasm_type(global->type); - if (global->flags & Ast_Flag_Foreign) { - WasmImport import = { - .kind = WASM_FOREIGN_GLOBAL, - .idx = global_type, - .mod = global->foreign_module, - .name = global->foreign_name, - }; - - bh_arr_push(module->imports, import); - return; - } - WasmGlobal glob = { .type = global_type, .mutable = (global->flags & Ast_Flag_Const) == 0, .initial_value = NULL, }; + i32 global_idx = (i32) bh_imap_get(&module->index_map, (u64) global); + if ((global->flags & Ast_Flag_Exported) != 0) { token_toggle_end(global->exported_name); - i32 global_idx = (i32) bh_imap_get(&module->index_map, (u64) global); - WasmExport wasm_export = { .kind = WASM_FOREIGN_GLOBAL, .idx = global_idx, @@ -2803,11 +2796,31 @@ static void emit_global(OnyxWasmModule* module, AstGlobal* global) { default: assert(("Invalid global type", 0)); break; } - bh_arr_push(module->globals, glob); + bh_arr_grow(module->globals, global_idx + 1); + module->globals[global_idx] = glob; + bh_arr_set_length(module->globals, bh_max(bh_arr_length(module->globals), global_idx + 1)); + + bh_arr_grow(module->globals, global_idx - module->foreign_global_count + 1); + module->globals[global_idx - module->foreign_global_count] = glob; + bh_arr_set_length(module->globals, bh_max(bh_arr_length(module->globals), global_idx - module->foreign_global_count + 1)); if (global->flags & Ast_Flag_Global_Stack_Top) - module->stack_top_ptr = &bh_arr_last(module->globals).initial_value[0].data.i1; + module->stack_top_ptr = &module->globals[global_idx].initial_value[0].data.i1; +} + +static void emit_foreign_global(OnyxWasmModule* module, AstGlobal* global) { + WasmType global_type = onyx_type_to_wasm_type(global->type); + + if (global->flags & Ast_Flag_Foreign) { + WasmImport import = { + .kind = WASM_FOREIGN_GLOBAL, + .idx = global_type, + .mod = global->foreign_module, + .name = global->foreign_name, + }; + bh_arr_push(module->imports, import); + } } static void emit_string_literal(OnyxWasmModule* mod, AstStrLit* strlit) { @@ -3025,7 +3038,6 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { .globals = NULL, .next_global_idx = 0, - .next_foreign_global_idx = 0, .data = NULL, .next_datum_offset = 0, @@ -3037,6 +3049,9 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { .stack_top_ptr = NULL, .stack_base_idx = 0, + + .foreign_function_count = 0, + .foreign_global_count = 0, }; bh_arena* eid = bh_alloc(global_heap_allocator, sizeof(bh_arena)); @@ -3066,77 +3081,77 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { bh_arr_new(global_heap_allocator, module.deferred_stmts, 4); - return module; -} - -void onyx_wasm_module_compile(OnyxWasmModule* module, ProgramInfo* program) { - module->next_global_idx = program->foreign_global_count; - WasmExport mem_export = { .kind = WASM_FOREIGN_MEMORY, .idx = 0, }; - bh_table_put(WasmExport, module->exports, "memory", mem_export); - module->export_count++; + bh_table_put(WasmExport, module.exports, "memory", mem_export); + module.export_count++; - bh_arr_each(Entity, entity, program->entities) { + return module; +} - if (module->stack_top_ptr) { - *module->stack_top_ptr = module->next_datum_offset; +void emit_entity(Entity* ent) { + OnyxWasmModule* module = &global_wasm_module; - if (*module->stack_top_ptr % 16 != 0) { - *module->stack_top_ptr += 16 - (*module->stack_top_ptr % 16); - } + if (module->stack_top_ptr) { + *module->stack_top_ptr = module->next_datum_offset; - builtin_heap_start.value.i = *module->stack_top_ptr + (1 << 16); - if (builtin_heap_start.value.i % 16 != 0) { - builtin_heap_start.value.i += 16 - (builtin_heap_start.value.i % 16); - } + if (*module->stack_top_ptr % 16 != 0) { + *module->stack_top_ptr += 16 - (*module->stack_top_ptr % 16); } - switch (entity->type) { - case Entity_Type_Foreign_Function_Header: - emit_foreign_function(module, entity->function); - // fallthrough + builtin_heap_start.value.i = *module->stack_top_ptr + (1 << 16); + if (builtin_heap_start.value.i % 16 != 0) { + builtin_heap_start.value.i += 16 - (builtin_heap_start.value.i % 16); + } + } - case Entity_Type_Function_Header: - if (!should_emit_function(entity->function)) break; + switch (ent->type) { + case Entity_Type_Foreign_Function_Header: + if (!should_emit_function(ent->function)) break; + + module->foreign_function_count++; + emit_foreign_function(module, ent->function); + // fallthrough - bh_imap_put(&module->index_map, (u64) entity->function, module->next_func_idx++); - break; + case Entity_Type_Function_Header: + if (!should_emit_function(ent->function)) break; - case Entity_Type_Global_Header: { - u64 global_idx; - if ((entity->global->flags & Ast_Flag_Foreign) != 0) - global_idx = module->next_foreign_global_idx++; - else - global_idx = module->next_global_idx++; + bh_imap_put(&module->index_map, (u64) ent->function, module->next_func_idx++); + break; - bh_imap_put(&module->index_map, (u64) entity->global, global_idx); - break; - } + case Entity_Type_Foreign_Global_Header: + module->foreign_global_count++; + emit_foreign_global(module, ent->global); + // fallthrough - case Entity_Type_String_Literal: { - emit_string_literal(module, (AstStrLit *) entity->strlit); - break; - } - - case Entity_Type_File_Contents: { - emit_file_contents(module, (AstFileContents *) entity->file_contents); - break; - } + case Entity_Type_Global_Header: + bh_imap_put(&module->index_map, (u64) ent->global, module->next_global_idx++); + break; - case Entity_Type_Memory_Reservation: { - emit_memory_reservation(module, (AstMemRes *) entity->mem_res); - break; - } + case Entity_Type_String_Literal: { + emit_string_literal(module, (AstStrLit *) ent->strlit); + break; + } - case Entity_Type_Function: emit_function(module, entity->function); break; - case Entity_Type_Global: emit_global(module, entity->global); break; + case Entity_Type_File_Contents: { + emit_file_contents(module, (AstFileContents *) ent->file_contents); + break; + } - default: break; + case Entity_Type_Memory_Reservation: { + emit_memory_reservation(module, (AstMemRes *) ent->mem_res); + break; } + + case Entity_Type_Function: emit_function(module, ent->function); break; + case Entity_Type_Global: emit_global(module, ent->global); break; + + default: break; } + + ent->state = Entity_State_Finalized; } void onyx_wasm_module_free(OnyxWasmModule* module) {