From: Brendan Hansen Date: Thu, 16 Jul 2020 18:13:38 +0000 (-0500) Subject: Started working on an IR; decided it's not needed X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=44ea3f2dd2d04c060e5d9732adffb19afd28b11d;p=onyx.git Started working on an IR; decided it's not needed Leaving the code for it in the tree though --- diff --git a/docs/thoughts b/docs/thoughts index b9402481..188e314d 100644 --- a/docs/thoughts +++ b/docs/thoughts @@ -57,9 +57,6 @@ Treating top level declarations differently: global :: 5 - This would replace all instances of 'global' with the integer constant 5. This would not make a global in WASM. - global := 5 - This would work as expected but will make generating the WASM more difficult. - This feature may wait to come back. - global :: i32 - This would work as a type alias. 'global' would have the type node as it's 'node' print :: proc #foriegn "host" "print" (...) --- @@ -102,3 +99,5 @@ Explicit overriden functions: min(2, 5); min(4.5, 10.4); + + diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index ba6fe398..081d20f1 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -228,12 +228,13 @@ typedef enum OnyxIntrinsic { // same position as AstNodeCall struct AstIntrinsicCall { AstTyped base; AstArgument *arguments; OnyxIntrinsic intrinsic; }; -typedef struct OnyxProgram { +// NOTE: Simple data structure for storing what comes out of the parser +typedef struct ParserOutput { bh_arr(AstBinding *) top_level_bindings; bh_arr(AstNode *) nodes_to_process; bh_arr(AstFunction *) functions; -} OnyxProgram; +} ParserOutput; diff --git a/include/onyxir.h b/include/onyxir.h new file mode 100644 index 00000000..97e0a3cb --- /dev/null +++ b/include/onyxir.h @@ -0,0 +1,58 @@ +#ifndef ONYXIR_H +#define ONYXIR_H + +#include "bh.h" +#include "onyxastnodes.h" +#include "onyxtypes.h" +#include "onyxmsgs.h" + +typedef struct IrFunction { + AstFunction* ast_func; + Type* type; + bh_arr(AstLocal *) locals; + AstLocal* first_param; + AstNode* body; + + // NOTE: A function can either be either be: + // Normal + // Intrinsic + // Exported + // Foreign + union { + // NOTE: Set if the function is exported + char* exported_name; + + // NOTE: Set if the function is a foreign + struct { + char* foreign_module; + char* foreign_name; + }; + + // NOTE: Set if the function is intrinsic + OnyxIntrinsic intrinsic; + }; + + u32 is_exported : 1; + u32 is_foreign : 1; + u32 is_intrinsic : 1; + +} IrFunction; + +typedef struct IrContext { + // NOTE: Properties used after ir generation is done + bh_allocator allocator; + + bh_arr(IrFunction *) functions; + + // NOTE: Properties used while ir is generating + IrFunction* curr_function; + + OnyxMessages* msgs; +} IrContext; + + +IrContext ir_context_create(bh_allocator allocator); +void ir_context_free(IrContext* context); +void ir_generate(IrContext* context, ParserOutput parse_output); + +#endif // #ifndef ONYXIR_H diff --git a/include/onyxsempass.h b/include/onyxsempass.h index 138ef8e0..c2d1a529 100644 --- a/include/onyxsempass.h +++ b/include/onyxsempass.h @@ -29,13 +29,13 @@ typedef struct OnyxSemPassState { } OnyxSemPassState; // NOTE: Resolving all symbols in the tree -void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program); +void onyx_resolve_symbols(OnyxSemPassState* state, ParserOutput* program); // NOTE: Inferring and checking types in the tree -void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program); +void onyx_type_check(OnyxSemPassState* state, ParserOutput* program); // NOTE: Full semantic pass OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc, OnyxMessages* msgs); -void onyx_sempass(OnyxSemPassState* state, OnyxProgram* program); +void onyx_sempass(OnyxSemPassState* state, ParserOutput* program); #endif diff --git a/include/onyxwasm.h b/include/onyxwasm.h index fe0e32c3..24b951c1 100644 --- a/include/onyxwasm.h +++ b/include/onyxwasm.h @@ -5,6 +5,7 @@ #include "onyxastnodes.h" #include "onyxmsgs.h" +#include "onyxir.h" typedef u8 WasmType; @@ -301,14 +302,12 @@ typedef struct OnyxWasmModule { u16 next_type_idx; u16 next_func_idx; - u16 next_import_func_idx; u16 next_global_idx; - u16 next_import_global_idx; u16 export_count; } OnyxWasmModule; OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs); -void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program); +void onyx_wasm_module_compile(OnyxWasmModule* module, ParserOutput* program); void onyx_wasm_module_free(OnyxWasmModule* module); void onyx_wasm_module_write_to_file(OnyxWasmModule* module, bh_file file); diff --git a/onyx b/onyx index 9fb8a4b9..791a5a19 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/basic.onyx b/progs/basic.onyx index e7a0c5f0..fdba0aec 100644 --- a/progs/basic.onyx +++ b/progs/basic.onyx @@ -37,8 +37,7 @@ main :: proc #export { b := 1 + foo(2); print(b); - if b == 13 - --- + if b == 13 {} else { print(1024); } diff --git a/progs/test.onyx b/progs/test.onyx index 6214b278..1522bf3b 100644 --- a/progs/test.onyx +++ b/progs/test.onyx @@ -24,11 +24,11 @@ local_brute :: proc { c := 123.0; { - a := 5.0f; - b := 12.3; + d := 5.0f; + e := 12.3; - print_f32(a); - print_f64(b); + print_f32(d); + print_f64(e); } print_i32(a); @@ -91,6 +91,8 @@ main2 :: proc #export { // } main :: proc #export { + local_brute(); + print_i32(clz_i32(16)); print_f32(sqrt_f32(2.0f)); diff --git a/src/onyx.c b/src/onyx.c index b7c24e29..93824ca0 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -60,7 +60,7 @@ typedef struct CompilerState { bh_arr(const char *) queued_files; OnyxMessages msgs; - OnyxProgram program; + ParserOutput parse_output; OnyxWasmModule wasm_mod; } CompilerState; @@ -154,10 +154,10 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char* } bh_arr_each(AstBinding *, binding_node, results.bindings) - bh_arr_push(compiler_state->program.top_level_bindings, *binding_node); + bh_arr_push(compiler_state->parse_output.top_level_bindings, *binding_node); bh_arr_each(AstNode *, node, results.nodes_to_process) - bh_arr_push(compiler_state->program.nodes_to_process, *node); + bh_arr_push(compiler_state->parse_output.nodes_to_process, *node); if (onyx_message_has_errors(&compiler_state->msgs)) { return ONYX_COMPILER_PROGRESS_FAILED_PARSE; @@ -169,8 +169,9 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char* static void compiler_state_init(CompilerState* compiler_state, OnyxCompileOptions* opts) { compiler_state->options = opts; - bh_arr_new(global_heap_allocator, compiler_state->program.top_level_bindings, 4); - bh_arr_new(global_heap_allocator, compiler_state->program.functions, 4); + bh_arr_new(global_heap_allocator, compiler_state->parse_output.top_level_bindings, 4); + bh_arr_new(global_heap_allocator, compiler_state->parse_output.nodes_to_process, 4); + bh_arr_new(global_heap_allocator, compiler_state->parse_output.functions, 4); bh_arena_init(&compiler_state->msg_arena, opts->allocator, 4096); compiler_state->msg_alloc = bh_arena_allocator(&compiler_state->msg_arena); @@ -214,7 +215,7 @@ static i32 onyx_compile(CompilerState* compiler_state) { bh_printf("[Checking semantics]\n"); OnyxSemPassState sp_state = onyx_sempass_create(compiler_state->sp_alloc, compiler_state->ast_alloc, &compiler_state->msgs); - onyx_sempass(&sp_state, &compiler_state->program); + onyx_sempass(&sp_state, &compiler_state->parse_output); if (onyx_message_has_errors(&compiler_state->msgs)) { return ONYX_COMPILER_PROGRESS_FAILED_SEMPASS; @@ -226,7 +227,7 @@ static i32 onyx_compile(CompilerState* compiler_state) { bh_printf("[Generating WASM]\n"); compiler_state->wasm_mod = onyx_wasm_module_create(compiler_state->options->allocator, &compiler_state->msgs); - onyx_wasm_module_compile(&compiler_state->wasm_mod, &compiler_state->program); + onyx_wasm_module_compile(&compiler_state->wasm_mod, &compiler_state->parse_output); if (onyx_message_has_errors(&compiler_state->msgs)) { return ONYX_COMPILER_PROGRESS_FAILED_BINARY_GEN; @@ -265,7 +266,7 @@ int main(int argc, char *argv[]) { OnyxCompileOptions compile_opts = compile_opts_parse(global_heap_allocator, argc, argv); CompilerState compile_state = { - .program = { + .parse_output = { .top_level_bindings = NULL, .nodes_to_process = NULL, diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 365a11c9..64e6836d 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -518,30 +518,19 @@ static b32 check_function(OnyxSemPassState* state, AstFunction* func) { static b32 check_node(OnyxSemPassState* state, AstNode* node) { switch (node->kind) { - case Ast_Kind_Function: return check_function(state, (AstFunction *) node); - case Ast_Kind_Block: return check_block(state, (AstBlock *) node); - case Ast_Kind_Assignment: return check_assignment(state, (AstAssign *) node); - case Ast_Kind_Return: return check_return(state, (AstReturn *) node); - case Ast_Kind_If: return check_if(state, (AstIf *) node); - case Ast_Kind_While: return check_while(state, (AstWhile *) node); - case Ast_Kind_Call: return check_call(state, (AstCall *) node); - case Ast_Kind_Binary_Op: return check_binaryop(state, (AstBinaryOp *) node); - default: return check_expression(state, (AstTyped *) node); + case Ast_Kind_Function: return check_function(state, (AstFunction *) node); + case Ast_Kind_Block: return check_block(state, (AstBlock *) node); + case Ast_Kind_Assignment: return check_assignment(state, (AstAssign *) node); + case Ast_Kind_Return: return check_return(state, (AstReturn *) node); + case Ast_Kind_If: return check_if(state, (AstIf *) node); + case Ast_Kind_While: return check_while(state, (AstWhile *) node); + case Ast_Kind_Call: return check_call(state, (AstCall *) node); + case Ast_Kind_Binary_Op: return check_binaryop(state, (AstBinaryOp *) node); + default: return check_expression(state, (AstTyped *) node); } } -void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program) { - - // bh_arr_each(AstForeign *, foreign, program->foreigns) - // if ((*foreign)->import->kind == Ast_Kind_Function) - // check_function(state, (AstFunction *) (*foreign)->import); - - // bh_arr_each(AstGlobal *, global, program->globals) - // check_global(state, *global); - - // bh_arr_each(AstFunction *, function, program->functions) - // check_function(state, *function); - +void onyx_type_check(OnyxSemPassState* state, ParserOutput* program) { bh_arr_each(AstNode *, node, program->nodes_to_process) { check_node(state, *node); diff --git a/src/onyxir.c b/src/onyxir.c new file mode 100644 index 00000000..1002249b --- /dev/null +++ b/src/onyxir.c @@ -0,0 +1,190 @@ +#include "onyxir.h" + +#define IR_FUNC(kind, ...) static void ir_ ## kind (IrContext* c, __VA_ARGS__) + +IR_FUNC(function, AstFunction* ast_func); +IR_FUNC(function_body, AstFunction* fd); +IR_FUNC(block, AstBlock* block); +IR_FUNC(statement, AstNode* stmt); +IR_FUNC(assign_lval, AstTyped* lval); +IR_FUNC(assignment, AstAssign* assign); +IR_FUNC(if, AstIf* if_node); +IR_FUNC(while, AstWhile* while_node); +IR_FUNC(binop, AstBinaryOp* binop); +IR_FUNC(unaryop, AstUnaryOp* unop); +IR_FUNC(call, AstCall* call); +IR_FUNC(intrinsic_call, AstIntrinsicCall* call); +IR_FUNC(expression, AstTyped* expr); +IR_FUNC(cast, AstUnaryOp* cast); +IR_FUNC(return, AstReturn* ret); + +static OnyxIntrinsic intrinsic_lookup(char* name) { + if (!strcmp("memory_size", name)) return ONYX_INTRINSIC_MEMORY_SIZE; + else if (!strcmp("memory_grow", name)) return ONYX_INTRINSIC_MEMORY_GROW; + + else if (!strcmp("clz_i32", name)) return ONYX_INTRINSIC_I32_CLZ; + else if (!strcmp("ctz_i32", name)) return ONYX_INTRINSIC_I32_CTZ; + else if (!strcmp("popcnt_i32", name)) return ONYX_INTRINSIC_I32_POPCNT; + else if (!strcmp("and_i32", name)) return ONYX_INTRINSIC_I32_AND; + else if (!strcmp("or_i32", name)) return ONYX_INTRINSIC_I32_OR; + else if (!strcmp("xor_i32", name)) return ONYX_INTRINSIC_I32_XOR; + else if (!strcmp("shl_i32", name)) return ONYX_INTRINSIC_I32_SHL; + else if (!strcmp("slr_i32", name)) return ONYX_INTRINSIC_I32_SLR; + else if (!strcmp("sar_i32", name)) return ONYX_INTRINSIC_I32_SAR; + else if (!strcmp("rotl_i32", name)) return ONYX_INTRINSIC_I32_ROTL; + else if (!strcmp("rotr_i32", name)) return ONYX_INTRINSIC_I32_ROTR; + + else if (!strcmp("clz_i64", name)) return ONYX_INTRINSIC_I64_CLZ; + else if (!strcmp("ctz_i64", name)) return ONYX_INTRINSIC_I64_CTZ; + else if (!strcmp("popcnt_i64", name)) return ONYX_INTRINSIC_I64_POPCNT; + else if (!strcmp("and_i64", name)) return ONYX_INTRINSIC_I64_AND; + else if (!strcmp("or_i64", name)) return ONYX_INTRINSIC_I64_OR; + else if (!strcmp("xor_i64", name)) return ONYX_INTRINSIC_I64_XOR; + else if (!strcmp("shl_i64", name)) return ONYX_INTRINSIC_I64_SHL; + else if (!strcmp("slr_i64", name)) return ONYX_INTRINSIC_I64_SLR; + else if (!strcmp("sar_i64", name)) return ONYX_INTRINSIC_I64_SAR; + else if (!strcmp("rotl_i64", name)) return ONYX_INTRINSIC_I64_ROTL; + else if (!strcmp("rotr_i64", name)) return ONYX_INTRINSIC_I64_ROTR; + + else if (!strcmp("abs_f32", name)) return ONYX_INTRINSIC_F32_ABS; + else if (!strcmp("ceil_f32", name)) return ONYX_INTRINSIC_F32_CEIL; + else if (!strcmp("floor_f32", name)) return ONYX_INTRINSIC_F32_FLOOR; + else if (!strcmp("trunc_f32", name)) return ONYX_INTRINSIC_F32_TRUNC; + else if (!strcmp("nearest_f32", name)) return ONYX_INTRINSIC_F32_NEAREST; + else if (!strcmp("sqrt_f32", name)) return ONYX_INTRINSIC_F32_SQRT; + else if (!strcmp("min_f32", name)) return ONYX_INTRINSIC_F32_MIN; + else if (!strcmp("max_f32", name)) return ONYX_INTRINSIC_F32_MAX; + else if (!strcmp("copysign_f32", name)) return ONYX_INTRINSIC_F32_COPYSIGN; + + else if (!strcmp("abs_f64", name)) return ONYX_INTRINSIC_F64_ABS; + else if (!strcmp("ceil_f64", name)) return ONYX_INTRINSIC_F64_CEIL; + else if (!strcmp("floor_f64", name)) return ONYX_INTRINSIC_F64_FLOOR; + else if (!strcmp("trunc_f64", name)) return ONYX_INTRINSIC_F64_TRUNC; + else if (!strcmp("nearest_f64", name)) return ONYX_INTRINSIC_F64_NEAREST; + else if (!strcmp("sqrt_f64", name)) return ONYX_INTRINSIC_F64_SQRT; + else if (!strcmp("min_f64", name)) return ONYX_INTRINSIC_F64_MIN; + else if (!strcmp("max_f64", name)) return ONYX_INTRINSIC_F64_MAX; + else if (!strcmp("copysign_f64", name)) return ONYX_INTRINSIC_F64_COPYSIGN; + else return ONYX_INTRINSIC_UNDEFINED; +} + +static void ir_add_local(IrContext* c, AstLocal* local) { + bh_arr_push(c->curr_function->locals, local); +} + +IR_FUNC(ir_function, AstFunction* ast_func) { + IrFunction* func = bh_alloc_item(c->allocator, IrFunction); + + func->ast_func = ast_func; + func->body = ast_func->body->body; + func->first_param = ast_func->params; + + // NOTE: This is actually the return type (for now) + func->type = ast_func->base.type; + + func->locals = NULL; + bh_arr_new(c->allocator, func->locals, 4); + + func->is_exported = (ast_func->base.flags & Ast_Flag_Exported) != 0; + func->is_foreign = (ast_func->base.flags & Ast_Flag_Foreign) != 0; + func->is_intrinsic = (ast_func->base.flags & Ast_Flag_Intrinsic) != 0; + + if (func->is_intrinsic) { + onyx_token_null_toggle(ast_func->base.token); + func->intrinsic = intrinsic_lookup(ast_func->base.token->text); + onyx_token_null_toggle(ast_func->base.token); + } + + else if (func->is_exported) { + onyx_token_null_toggle(ast_func->base.token); + func->exported_name = bh_aprintf(c->allocator, "%s", ast_func->base.token->text); + onyx_token_null_toggle(ast_func->base.token); + } + + else if (func->is_foreign) { + onyx_token_null_toggle(ast_func->foreign_module); + func->foreign_module = bh_aprintf(c->allocator, "%s", ast_func->foreign_module); + onyx_token_null_toggle(ast_func->foreign_module); + + onyx_token_null_toggle(ast_func->foreign_name); + func->foreign_module = bh_aprintf(c->allocator, "%s", ast_func->foreign_name); + onyx_token_null_toggle(ast_func->foreign_name); + } + + if (func->body != NULL) { + c->curr_function = func; + } +} + +IR_FUNC(function_body, AstFunction* fd) { + if (fd->body == NULL) return; + ir_block(c, fd->body); +} + +IR_FUNC(block, AstBlock* block) { + forll (AstLocal, local, block->locals->last_local, prev_local) { + ir_add_local(c, local); + } + + forll (AstNode, stmt, block->body, next) { + ir_statement(c, stmt); + } +} + +IR_FUNC(statement, AstNode* stmt) { + switch (stmt->kind) { + case Ast_Kind_Return: return ir_return(c, (AstReturn *) stmt); + case Ast_Kind_Assignment: return ir_assignment(c, (AstAssign *) stmt); + case Ast_Kind_If: return ir_if(c, (AstIf *) stmt); + case Ast_Kind_While: return ir_while(c, (AstWhile *) stmt); + case Ast_Kind_Block: return ir_block(c, (AstBlock *) stmt); + + default: break; + } +} + +IR_FUNC(if, AstIf* if_node) { + if (if_node->true_block.as_if->base.kind == Ast_Kind_Block) { + ir_block(c, if_node->true_block.as_block); + } + + if (if_node->false_block.as_if->base.kind == Ast_Kind_Block) { + ir_block(c, if_node->false_block.as_block); + } +} + +IR_FUNC(while, AstWhile* while_node) { + ir_block(c, while_node->body); +} + +// NOTE: Currently, these functions don't have anything to +// do so they are empty and not called. When I have a reason +// to use them, I will populate their bodies +IR_FUNC(assign_lval, AstTyped* lval) {} +IR_FUNC(assignment, AstAssign* assign) {} +IR_FUNC(binop, AstBinaryOp* binop) {} +IR_FUNC(unaryop, AstUnaryOp* unop) {} +IR_FUNC(expression, AstTyped* expr) {} +IR_FUNC(cast, AstUnaryOp* cast) {} +IR_FUNC(return, AstReturn* ret) {} + +IrContext ir_context_create(bh_allocator allocator) { + IrContext context = { + .allocator = allocator, + .functions = NULL, + + .curr_function = NULL, + }; + + bh_arr_new(allocator, context.functions, 4); + + return context; +} + +void ir_context_free(IrContext* context) { + bh_arr_free(context.functions); +} + +void ir_generate(IrContext* context, ParserOutput parse_output) { + +} diff --git a/src/onyxsempass.c b/src/onyxsempass.c index 9c8d225c..68ea2e2d 100644 --- a/src/onyxsempass.c +++ b/src/onyxsempass.c @@ -23,68 +23,70 @@ OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc // WASM, this function may not be needed. It brings all of the locals // defined in sub-scopes up to the function-block level. This is a // requirement of WASM, but not of other targets. -// static void collapse_scopes(OnyxProgram* program) { -// bh_arr(AstBlock*) traversal_queue = NULL; -// bh_arr_new(global_scratch_allocator, traversal_queue, 4); -// bh_arr_set_length(traversal_queue, 0); -// -// bh_arr_each(AstFunction *, func, program->functions) { -// AstLocalGroup* top_locals = (*func)->body->locals; -// -// bh_arr_push(traversal_queue, (*func)->body); -// while (!bh_arr_is_empty(traversal_queue)) { -// AstBlock* block = traversal_queue[0]; -// -// if (block->base.kind == Ast_Kind_If) { -// AstIf* if_node = (AstIf *) block; -// if (if_node->true_block.as_block != NULL) -// bh_arr_push(traversal_queue, if_node->true_block.as_block); -// -// if (if_node->false_block.as_block != NULL) -// bh_arr_push(traversal_queue, if_node->false_block.as_block); -// -// } else { -// -// if (block->locals != top_locals && block->locals->last_local != NULL) { -// AstLocal* last_local = block->locals->last_local; -// while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local; -// -// last_local->prev_local = top_locals->last_local; -// top_locals->last_local = block->locals->last_local; -// block->locals->last_local = NULL; -// } -// -// AstNode* walker = block->body; -// while (walker) { -// if (walker->kind == Ast_Kind_Block) { -// bh_arr_push(traversal_queue, (AstBlock *) walker); -// -// } else if (walker->kind == Ast_Kind_While) { -// bh_arr_push(traversal_queue, ((AstWhile *) walker)->body); -// -// } else if (walker->kind == Ast_Kind_If) { -// if (((AstIf *) walker)->true_block.as_block != NULL) -// bh_arr_push(traversal_queue, ((AstIf *) walker)->true_block.as_block); -// -// if (((AstIf *) walker)->false_block.as_block != NULL) -// bh_arr_push(traversal_queue, ((AstIf *) walker)->false_block.as_block); -// } -// -// walker = walker->next; -// } -// } -// -// bh_arr_deleten(traversal_queue, 0, 1); -// } -// } -// } - -void onyx_sempass(OnyxSemPassState* state, OnyxProgram* program) { +static void collapse_scopes(ParserOutput* program) { + bh_arr(AstBlock*) traversal_queue = NULL; + bh_arr_new(global_scratch_allocator, traversal_queue, 4); + bh_arr_set_length(traversal_queue, 0); + + bh_arr_each(AstFunction *, func, program->functions) { + if ((*func)->base.flags & Ast_Flag_Intrinsic) continue; + + AstLocalGroup* top_locals = (*func)->body->locals; + + bh_arr_push(traversal_queue, (*func)->body); + while (!bh_arr_is_empty(traversal_queue)) { + AstBlock* block = traversal_queue[0]; + + if (block->base.kind == Ast_Kind_If) { + AstIf* if_node = (AstIf *) block; + if (if_node->true_block.as_block != NULL) + bh_arr_push(traversal_queue, if_node->true_block.as_block); + + if (if_node->false_block.as_block != NULL) + bh_arr_push(traversal_queue, if_node->false_block.as_block); + + } else { + + if (block->locals != top_locals && block->locals->last_local != NULL) { + AstLocal* last_local = block->locals->last_local; + while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local; + + last_local->prev_local = top_locals->last_local; + top_locals->last_local = block->locals->last_local; + block->locals->last_local = NULL; + } + + AstNode* walker = block->body; + while (walker) { + if (walker->kind == Ast_Kind_Block) { + bh_arr_push(traversal_queue, (AstBlock *) walker); + + } else if (walker->kind == Ast_Kind_While) { + bh_arr_push(traversal_queue, ((AstWhile *) walker)->body); + + } else if (walker->kind == Ast_Kind_If) { + if (((AstIf *) walker)->true_block.as_block != NULL) + bh_arr_push(traversal_queue, ((AstIf *) walker)->true_block.as_block); + + if (((AstIf *) walker)->false_block.as_block != NULL) + bh_arr_push(traversal_queue, ((AstIf *) walker)->false_block.as_block); + } + + walker = walker->next; + } + } + + bh_arr_deleten(traversal_queue, 0, 1); + } + } +} + +void onyx_sempass(OnyxSemPassState* state, ParserOutput* program) { onyx_resolve_symbols(state, program); if (onyx_message_has_errors(state->msgs)) return; onyx_type_check(state, program); if (onyx_message_has_errors(state->msgs)) return; - // collapse_scopes(program); + collapse_scopes(program); } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index c363c396..02774125 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -314,7 +314,7 @@ static void symres_top_node(OnyxSemPassState* state, AstNode** node) { } } -void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program) { +void onyx_resolve_symbols(OnyxSemPassState* state, ParserOutput* program) { // NOTE: Add types to global scope symbol_basic_type_introduce(state, &basic_type_void); diff --git a/src/onyxutils.c b/src/onyxutils.c index 26a384f3..09881374 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -35,7 +35,6 @@ static const char* ast_node_names[] = { "PARAM", "ARGUMENT", "CALL", - "INTRINSIC_CALL", "ASSIGN", "RETURN", diff --git a/src/onyxwasm.c b/src/onyxwasm.c index b67b091e..8dc425b4 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -209,7 +209,7 @@ static WasmType onyx_type_to_wasm_type(Type* type) { } if (basic->flags & Basic_Flag_Float) { if (basic->size <= 4) return WASM_TYPE_FLOAT32; - if (basic->size == 8) return WASM_TYPE_FLOAT64;; + if (basic->size == 8) return WASM_TYPE_FLOAT64; } if (basic->size == 0) return WASM_TYPE_VOID; } @@ -296,13 +296,13 @@ COMPILE_FUNC(statement, AstNode* stmt) { bh_arr(WasmInstruction) code = *pcode; switch (stmt->kind) { - case Ast_Kind_Return: compile_return(mod, &code, (AstReturn *) stmt); break; + case Ast_Kind_Return: compile_return(mod, &code, (AstReturn *) stmt); break; case Ast_Kind_Assignment: compile_assignment(mod, &code, (AstAssign *) stmt); break; - case Ast_Kind_If: compile_if(mod, &code, (AstIf *) stmt); break; - case Ast_Kind_While: compile_while(mod, &code, (AstWhile *) stmt); break; - case Ast_Kind_Break: compile_structured_jump(mod, &code, 0); break; - case Ast_Kind_Continue: compile_structured_jump(mod, &code, 1); break; - case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) stmt); break; + case Ast_Kind_If: compile_if(mod, &code, (AstIf *) stmt); break; + case Ast_Kind_While: compile_while(mod, &code, (AstWhile *) stmt); break; + case Ast_Kind_Break: compile_structured_jump(mod, &code, 0); break; + case Ast_Kind_Continue: compile_structured_jump(mod, &code, 1); break; + case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) stmt); break; case Ast_Kind_Call: case Ast_Kind_Intrinsic_Call: @@ -453,8 +453,8 @@ COMPILE_FUNC(binop, AstBinaryOp* binop) { WasmType operator_type = onyx_type_to_wasm_type(binop->left->type); i32 optype = 0; - if (operator_type == WASM_TYPE_INT32) optype = 0; - else if (operator_type == WASM_TYPE_INT64) optype = 1; + if (operator_type == WASM_TYPE_INT32) optype = 0; + else if (operator_type == WASM_TYPE_INT64) optype = 1; else if (operator_type == WASM_TYPE_FLOAT32) optype = 2; else if (operator_type == WASM_TYPE_FLOAT64) optype = 3; @@ -961,8 +961,6 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs) { .export_count = 0, .imports = NULL, - .next_import_func_idx = 0, - .next_import_global_idx = 0, .globals = NULL, .next_global_idx = 0, @@ -989,7 +987,7 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs) { return module; } -void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program) { +void onyx_wasm_module_compile(OnyxWasmModule* module, ParserOutput* program) { // NOTE: First, introduce all indicies for globals and functions // bh_arr_each(AstForeign *, foreign, program->foreigns) { @@ -1015,7 +1013,7 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program) { bh_arr_each(AstFunction *, function, program->functions) { if ((*function)->base.flags & Ast_Flag_Foreign) continue; - + if (((*function)->base.flags & Ast_Flag_Intrinsic) == 0) bh_imap_put(&module->func_map, (u64) *function, module->next_func_idx++); }