From: Brendan Hansen Date: Tue, 16 Jun 2020 04:12:17 +0000 (-0500) Subject: Code clean up and added "start" section output X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=bfb22fec3ff154edce051129efd2461a4413f09a;p=onyx.git Code clean up and added "start" section output --- diff --git a/.gitignore b/.gitignore index 8ca5336c..e11e2b69 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ tags test.c test *.wasm +*.html diff --git a/docs/plan b/docs/plan index d78b4992..d91c21b5 100644 --- a/docs/plan +++ b/docs/plan @@ -31,28 +31,81 @@ HOW: at once would be overwhelming and unsatisfying. The current progress of each stage: Stage 1 (MVP): - [ ] Can declare procedures - [ ] Procedures have params and returns of the following types: + [X] Can declare procedures + [X] Procedures have params and returns of the following types: - i32, u32 - i64, u64 - f32, f64 - [ ] Procedures have locals of the same set of types - [ ] Locals are declared in the following way - local : (const) (type) (= initial value); + [X] Procedures have locals of the same set of types + [X] Locals are declared in the following way + local : (type) ((= or :) initial value); - if const is specified, the value is unmodifiable + if : is used, the value is unmodifiable if type is specified, that is assumed to be the correct type if type is not specified, the type of initial value is used as the type - [ ] Five basic math operations are legal: + [X] Five basic math operations are legal: + - * / % - [ ] Math operations are sign aware and only operate on operands of the same type - [ ] All casts are explicit using this syntax: + [X] Math operations are sign aware and only operate on operands of the same type + [X] All casts are explicit using this syntax: X as T casts X to type T + [ ] Numeric literals are parsed and minimum type detected + [ ] Comparison operators + [ ] Proper boolean type [ ] Conditional branching works as expected [ ] Curly braces are required for all bodies of blocks [ ] Simple while loop is functioning as expected [ ] break and continue semantics + [ ] Function calling works for the builtin types + [ ] Function return values are type checked + + Stage 2: + [ ] Order of symbol declaration is irrelevant + Either: + make a graph of symbol dependencies and produce a schedule on the graph + that would allow for all symbols to be resolved + + OR + + Do as many passes on the parse tree as needed to resolve all symbols. + This could be slow but it would be easier than creating a graph + scheduling algorithm. + + [ ] Devise and implement a simple set of implicit type casting rules. + - Numeric literals always type cast to whatever type is needed (very flexible). + + [ ] Start work on evaluating compile time known values. + - An expression marked COMPTIME will be reduced to its value in the parse tree. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/onyx b/onyx index 532e9c8d..74ff9b5d 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/minimal.onyx b/progs/minimal.onyx index ba83edb0..17df6c75 100644 --- a/progs/minimal.onyx +++ b/progs/minimal.onyx @@ -19,4 +19,6 @@ export diff_square :: proc (a i32, b i32) -> i32 { return (c * d) as i32; } -export dummy :: proc () { } +export main :: proc () { + +} diff --git a/src/onyx.c b/src/onyx.c index 2c5e9d2b..c55a7b31 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -19,23 +19,16 @@ int main(int argc, char *argv[]) { bh_allocator alloc = bh_heap_allocator(); + // NOTE: 1st: Read file contents bh_file_contents fc = bh_file_read_contents(alloc, &source_file); bh_file_close(&source_file); + // NOTE: 2nd: Tokenize the contents OnyxTokenizer tokenizer = onyx_tokenizer_create(alloc, &fc); onyx_lex_tokens(&tokenizer); bh_arr(OnyxToken) token_arr = tokenizer.tokens; -#if 0 - bh_printf("There are %d tokens (Allocated space for %d tokens)\n", bh_arr_length(token_arr), bh_arr_capacity(token_arr)); - - bh_arr_each(OnyxToken, it, token_arr) { - onyx_token_null_toggle(*it); - bh_printf("%s (%s:%l:%l)\n", onyx_get_token_type_name(it->type), it->pos.filename, it->pos.line, it->pos.column); - onyx_token_null_toggle(*it); - } -#endif - + // NOTE: Create the buffer for where compiler messages will be written bh_arena msg_arena; bh_arena_init(&msg_arena, alloc, 4096); bh_allocator msg_alloc = bh_arena_allocator(&msg_arena); @@ -43,10 +36,13 @@ int main(int argc, char *argv[]) { OnyxMessages msgs; onyx_message_create(msg_alloc, &msgs); + // NOTE: Create the arena where AST nodes will exist + // Prevents nodes from being scattered across memory due to fragmentation bh_arena ast_arena; bh_arena_init(&ast_arena, alloc, 16 * 1024 * 1024); // 16MB bh_allocator ast_alloc = bh_arena_allocator(&ast_arena); + // NOTE: 3rd: parse the tokens to an AST OnyxParser parser = onyx_parser_create(ast_alloc, &tokenizer, &msgs); OnyxAstNode* program = onyx_parse(&parser); @@ -56,13 +52,42 @@ int main(int argc, char *argv[]) { onyx_message_print(&msgs); goto main_exit; } else { - onyx_ast_print(program, 0); + // onyx_ast_print(program, 0); bh_printf("\nNo errors.\n"); } + // NOTE: 4th: Generate a WASM module from the parse tree and + // write it to a file. OnyxWasmModule wasm_mod = onyx_wasm_generate_module(alloc, program); -#if 1 + bh_file out_file; + bh_file_create(&out_file, "out.wasm"); + onyx_wasm_module_write_to_file(&wasm_mod, out_file); + bh_file_close(&out_file); + + onyx_wasm_module_free(&wasm_mod); +main_exit: // NOTE: Cleanup, since C doesn't have defer + bh_arena_free(&msg_arena); + bh_arena_free(&ast_arena); + onyx_parser_free(&parser); + onyx_tokenizer_free(&tokenizer); + bh_file_contents_free(&fc); + + return 0; +} + +// NOTE: Old bits of code that may be useful again at some point. +#if 0 + bh_printf("There are %d tokens (Allocated space for %d tokens)\n", bh_arr_length(token_arr), bh_arr_capacity(token_arr)); + + bh_arr_each(OnyxToken, it, token_arr) { + onyx_token_null_toggle(*it); + bh_printf("%s (%s:%l:%l)\n", onyx_get_token_type_name(it->type), it->pos.filename, it->pos.line, it->pos.column); + onyx_token_null_toggle(*it); + } +#endif + +#if 0 // NOTE: Ensure type table made correctly bh_printf("Type map:\n"); @@ -83,7 +108,7 @@ int main(int argc, char *argv[]) { } #endif -#if 1 +#if 0 // NOTE: Ensure the export table was built correctly bh_printf("Function types:\n"); @@ -96,19 +121,3 @@ int main(int argc, char *argv[]) { bh_printf("%s: %d %d\n", key, value.kind, value.idx); bh_hash_each_end; #endif - - bh_file out_file; - bh_file_create(&out_file, "out.wasm"); - onyx_wasm_module_write_to_file(&wasm_mod, out_file); - bh_file_close(&out_file); - - onyx_wasm_module_free(&wasm_mod); -main_exit: // NOTE: Cleanup, since C doesn't have defer - bh_arena_free(&msg_arena); - bh_arena_free(&ast_arena); - onyx_parser_free(&parser); - onyx_tokenizer_free(&tokenizer); - bh_file_contents_free(&fc); - - return 0; -} diff --git a/src/onyxutils.c b/src/onyxutils.c index aff6aba5..ba50b4ee 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -89,8 +89,8 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) { } case ONYX_AST_NODE_KIND_RETURN: { - if (node->next) { - onyx_ast_print(node->next, indent + 1); + if (node->left) { + onyx_ast_print(node->left, indent + 1); } break; diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 35aabd43..4b9f2007 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -510,24 +510,9 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* count++; } - - bh_printf("\nLocals for function: %b\n", fd->token->token, fd->token->length); - bh_printf("\tI32 count: %d\n", wasm_func.locals.i32_count); - bh_printf("\tI64 count: %d\n", wasm_func.locals.i64_count); - bh_printf("\tF32 count: %d\n", wasm_func.locals.f32_count); - bh_printf("\tF64 count: %d\n", wasm_func.locals.f64_count); - bh_hash_each_start(i32, mod->local_map); - bh_printf("\t%s -> %d\n", key, value); - bh_hash_each_end; - // Generate code process_function_body(mod, &wasm_func, fd); - bh_printf("Code for function:\n"); - bh_arr_each(WasmInstruction, instr, wasm_func.code) { - bh_printf("\t%s\t%xd\n", wi_string(instr->type), instr->data.i1); - } - bh_arr_push(mod->funcs, wasm_func); // NOTE: Clear the local map on exit of generating this function @@ -719,6 +704,34 @@ static i32 output_exportsection(OnyxWasmModule* module, bh_buffer* buff) { return buff->length - prev_len; } +static i32 output_startsection(OnyxWasmModule* module, bh_buffer* buff) { + i32 prev_len = buff->length; + + i32 start_idx = -1; + bh_hash_each_start(WasmExport, module->exports) { + if (value.kind == WASM_EXPORT_FUNCTION) { + if (strncmp("main", key, 5) == 0) { + start_idx = value.idx; + break; + } + } + } bh_hash_each_end; + + if (start_idx != -1) { + 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); + 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); + bh_buffer_append(buff, start_leb, start_leb_len); + } + + return buff->length - prev_len; +} + static i32 output_locals(WasmFunc* func, bh_buffer* buff) { i32 prev_len = buff->length; @@ -840,8 +853,8 @@ void onyx_wasm_module_write_to_file(OnyxWasmModule* module, bh_file file) { output_typesection(module, &master_buffer); output_funcsection(module, &master_buffer); output_exportsection(module, &master_buffer); + output_startsection(module, &master_buffer); output_codesection(module, &master_buffer); - bh_file_write(&file, master_buffer.data, master_buffer.length); }