From 818a6bbb9bf35ec25b0d025505873fb83b9c271f Mon Sep 17 00:00:00 2001 From: rexim Date: Fri, 25 Jun 2021 19:06:52 +0700 Subject: [PATCH 1/5] (#455) Implement taking pointer to a stack var --- bang/src/bang_compiler.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index b140864..c26c106 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -261,18 +261,8 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr } Compiled_Var *var = bang_get_compiled_var_by_name(bang, arg.as.var_read.name); - switch (var->storage) { - case BANG_VAR_STATIC_STORAGE: { - basm_push_inst(basm, INST_PUSH, word_u64(var->addr)); - result.type = BANG_TYPE_PTR; - } - break; - - case BANG_VAR_STACK_STORAGE: { - assert(false && "TODO(#455): Taking a pointer to stack variable is not implemented"); - } - break; - } + compile_get_var_addr(bang, basm, var); + result.type = BANG_TYPE_PTR; } else if (sv_eq(funcall.name, SV("write_ptr"))) { bang_funcall_expect_arity(funcall, 2); Bang_Funcall_Arg *args = funcall.args; From 1db1d0c70a939981c94a1bfe73180ab0d5ed5ff2 Mon Sep 17 00:00:00 2001 From: rexim Date: Fri, 25 Jun 2021 19:07:11 +0700 Subject: [PATCH 2/5] (#455) Separate stack frames from the scopes Don't push a new frame on each and individual scope. Several scopes may share the same frame. Only proc-s introduce new frames into the scope. Other constructions (like while, if, etc) inherit the frame of the parent scope. --- bang/src/bang.c | 8 +++---- bang/src/bang_compiler.c | 49 +++++++++++++++++++++++++--------------- bang/src/bang_compiler.h | 14 ++++++++---- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/bang/src/bang.c b/bang/src/bang.c index 2c96b48..411435d 100644 --- a/bang/src/bang.c +++ b/bang/src/bang.c @@ -114,7 +114,7 @@ static void run_subcommand(int argc, char **argv) bang.write_id = basm_push_external_native(&basm, SV("write")); bang_prepare_var_stack(&bang, &basm, stack_size); - bang_push_new_scope(&bang, &basm); + bang_push_new_scope(&bang, NULL); { compile_bang_module_into_basm(&bang, &basm, module); @@ -122,7 +122,7 @@ static void run_subcommand(int argc, char **argv) bang_generate_heap_base(&bang, &basm, SV("heap_base")); assert(basm.has_entry); } - bang_pop_scope(&bang, &basm); + bang_pop_scope(&bang); basm_save_to_bm(&basm, &bm); @@ -264,7 +264,7 @@ static void build_subcommand(int argc, char **argv) bang.write_id = basm_push_external_native(&basm, SV("write")); bang_prepare_var_stack(&bang, &basm, stack_size); - bang_push_new_scope(&bang, &basm); + bang_push_new_scope(&bang, NULL); { compile_bang_module_into_basm(&bang, &basm, module); @@ -273,7 +273,7 @@ static void build_subcommand(int argc, char **argv) assert(basm.has_entry); basm_save_to_file_as_target(&basm, output_file_path, output_target); } - bang_pop_scope(&bang, &basm); + bang_pop_scope(&bang); arena_free(&basm.arena); arena_free(&bang.arena); diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index c26c106..d535771 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -414,10 +414,10 @@ void compile_bang_if_into_basm(Bang *bang, Basm *basm, Bang_If eef) basm_push_inst(basm, INST_NOT, word_u64(0)); Inst_Addr then_jmp_addr = basm_push_inst(basm, INST_JMP_IF, word_u64(0)); - compile_block_into_basm(bang, basm, eef.then); + compile_block_into_basm(bang, basm, eef.then, bang->scope->frame); Inst_Addr else_jmp_addr = basm_push_inst(basm, INST_JMP, word_u64(0)); Inst_Addr else_addr = basm->program_size; - compile_block_into_basm(bang, basm, eef.elze); + compile_block_into_basm(bang, basm, eef.elze, bang->scope->frame); Inst_Addr end_addr = basm->program_size; basm->program[then_jmp_addr].operand = word_u64(else_addr); @@ -507,7 +507,7 @@ void compile_bang_while_into_basm(Bang *bang, Basm *basm, Bang_While hwile) basm_push_inst(basm, INST_NOT, word_u64(0)); Inst_Addr fallthrough_addr = basm_push_inst(basm, INST_JMP_IF, word_u64(0)); - compile_block_into_basm(bang, basm, hwile.body); + compile_block_into_basm(bang, basm, hwile.body, bang->scope->frame); basm_push_inst(basm, INST_JMP, word_u64(cond_expr.addr)); const Inst_Addr body_end_addr = basm->program_size; @@ -549,14 +549,14 @@ void compile_stmt_into_basm(Bang *bang, Basm *basm, Bang_Stmt stmt) } } -void compile_block_into_basm(Bang *bang, Basm *basm, Bang_Block *block) +void compile_block_into_basm(Bang *bang, Basm *basm, Bang_Block *block, Bang_Frame *frame) { - bang_push_new_scope(bang, basm); + bang_push_new_scope(bang, frame); while (block) { compile_stmt_into_basm(bang, basm, block->stmt); block = block->next; } - bang_pop_scope(bang, basm); + bang_pop_scope(bang); } Compiled_Proc *bang_get_compiled_proc_by_name(Bang *bang, String_View name) @@ -587,7 +587,10 @@ void compile_proc_def_into_basm(Bang *bang, Basm *basm, Bang_Proc_Def proc_def) assert(bang->procs_count < BANG_PROCS_CAPACITY); bang->procs[bang->procs_count++] = proc; - compile_block_into_basm(bang, basm, proc_def.body); + compile_push_new_frame(bang, basm, bang->scope->frame ? bang->scope->frame->offset : 0); + Bang_Frame *frame = arena_alloc(&bang->arena, sizeof(*frame)); + compile_block_into_basm(bang, basm, proc_def.body, frame); + compile_pop_frame(bang, basm); basm_push_inst(basm, INST_RET, word_u64(0)); } @@ -754,20 +757,21 @@ void compile_stack_var_def_into_basm(Bang *bang, Bang_Var_Def var_def) new_var.type = type; new_var.storage = BANG_VAR_STACK_STORAGE; assert(type_def.size > 0); - bang->scope->frame_top_offset += type_def.size; - new_var.addr = bang->scope->frame_top_offset; + assert(bang->scope->frame != NULL); + bang->scope->frame->offset += type_def.size; + new_var.addr = bang->scope->frame->offset; bang_scope_push_var(bang->scope, new_var); } -void compile_push_new_frame(Bang *bang, Basm *basm) +void compile_push_new_frame(Bang *bang, Basm *basm, Memory_Addr frame_top_offset) { // 1. read frame addr compile_read_frame_addr(bang, basm); // 2. offset the frame addr to find the top of the stack assert(bang->scope != NULL); - basm_push_inst(basm, INST_PUSH, word_u64(bang->scope->frame_top_offset)); + basm_push_inst(basm, INST_PUSH, word_u64(frame_top_offset)); basm_push_inst(basm, INST_MINUSI, word_u64(0)); // 3. allocate memory to store the prev frame addr @@ -794,20 +798,29 @@ void compile_pop_frame(Bang *bang, Basm *basm) compile_write_frame_addr(bang, basm); } -void bang_push_new_scope(Bang *bang, Basm *basm) +void bang_push_new_scope(Bang *bang, Bang_Frame *frame) { - if (bang->scope) { - compile_push_new_frame(bang, basm); - } - Bang_Scope *scope = arena_alloc(&bang->arena, sizeof(Bang_Scope)); scope->parent = bang->scope; + scope->frame = frame; bang->scope = scope; } -void bang_pop_scope(Bang *bang, Basm *basm) +void bang_pop_scope(Bang *bang) { - compile_pop_frame(bang, basm); assert(bang->scope != NULL); + Bang_Scope *scope = bang->scope; + + if (scope->frame) { + size_t dealloc_size = 0; + for (size_t i = 0; i < scope->vars_count; ++i) { + if (scope->vars[i].storage == BANG_VAR_STACK_STORAGE) { + Bang_Type_Def def = bang_type_def(scope->vars[i].type); + dealloc_size += def.size; + } + } + scope->frame->offset -= dealloc_size; + } + bang->scope = bang->scope->parent; } diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index 21a109e..f2e307f 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -51,13 +51,17 @@ typedef struct { Inst_Addr addr; } Compiled_Proc; +typedef struct { + Memory_Addr offset; +} Bang_Frame; + typedef struct Bang_Scope Bang_Scope; struct Bang_Scope { Bang_Scope *parent; Compiled_Var vars[BANG_SCOPE_VARS_CAPACITY]; size_t vars_count; - Memory_Addr frame_top_offset; + Bang_Frame *frame; }; Compiled_Var *bang_scope_get_compiled_var_by_name(Bang_Scope *scope, String_View name); @@ -95,7 +99,7 @@ void compile_typed_read(Basm *basm, Bang_Type type); void compile_typed_write(Basm *basm, Bang_Type type); Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr); void compile_stmt_into_basm(Bang *bang, Basm *basm, Bang_Stmt stmt); -void compile_block_into_basm(Bang *bang, Basm *basm, Bang_Block *block); +void compile_block_into_basm(Bang *bang, Basm *basm, Bang_Block *block, Bang_Frame *frame); void compile_proc_def_into_basm(Bang *bang, Basm *basm, Bang_Proc_Def proc_def); void compile_bang_if_into_basm(Bang *bang, Basm *basm, Bang_If eef); void compile_bang_while_into_basm(Bang *bang, Basm *basm, Bang_While hwile); @@ -108,11 +112,11 @@ Bang_Type compile_binary_op_into_basm(Bang *bang, Basm *basm, Bang_Binary_Op bin void compile_get_var_addr(Bang *bang, Basm *basm, Compiled_Var *var); void compile_read_frame_addr(Bang *bang, Basm *basm); void compile_write_frame_addr(Bang *bang, Basm *basm); -void compile_push_new_frame(Bang *bang, Basm *basm); +void compile_push_new_frame(Bang *bang, Basm *basm, Memory_Addr frame_top_offset); void compile_pop_frame(Bang *bang, Basm *basm); -void bang_push_new_scope(Bang *bang, Basm *basm); -void bang_pop_scope(Bang *bang, Basm *basm); +void bang_push_new_scope(Bang *bang, Bang_Frame *frame); +void bang_pop_scope(Bang *bang); void bang_generate_entry_point(Bang *bang, Basm *basm, String_View entry_proc_name); void bang_generate_heap_base(Bang *bang, Basm *basm, String_View heap_base_var_name); From f39da83ce173fdd81c24f8018b9e7e4bf8d37ed5 Mon Sep 17 00:00:00 2001 From: rexim Date: Fri, 25 Jun 2021 20:01:36 +0700 Subject: [PATCH 3/5] (#455) push/pop the frame on proc call instead of proc body --- bang/src/bang.c | 4 ++-- bang/src/bang_compiler.c | 43 ++++++++++++++++++---------------------- bang/src/bang_compiler.h | 12 ++++------- 3 files changed, 25 insertions(+), 34 deletions(-) diff --git a/bang/src/bang.c b/bang/src/bang.c index 411435d..71b0a71 100644 --- a/bang/src/bang.c +++ b/bang/src/bang.c @@ -114,7 +114,7 @@ static void run_subcommand(int argc, char **argv) bang.write_id = basm_push_external_native(&basm, SV("write")); bang_prepare_var_stack(&bang, &basm, stack_size); - bang_push_new_scope(&bang, NULL); + bang_push_new_scope(&bang); { compile_bang_module_into_basm(&bang, &basm, module); @@ -264,7 +264,7 @@ static void build_subcommand(int argc, char **argv) bang.write_id = basm_push_external_native(&basm, SV("write")); bang_prepare_var_stack(&bang, &basm, stack_size); - bang_push_new_scope(&bang, NULL); + bang_push_new_scope(&bang); { compile_bang_module_into_basm(&bang, &basm, module); diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index d535771..bc70ae2 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -359,7 +359,9 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr SV_Arg(funcall.name)); exit(1); } + compile_push_new_frame(bang, basm); basm_push_inst(basm, INST_CALL, word_u64(proc->addr)); + compile_pop_frame(bang, basm); result.type = BANG_TYPE_VOID; } } @@ -414,10 +416,10 @@ void compile_bang_if_into_basm(Bang *bang, Basm *basm, Bang_If eef) basm_push_inst(basm, INST_NOT, word_u64(0)); Inst_Addr then_jmp_addr = basm_push_inst(basm, INST_JMP_IF, word_u64(0)); - compile_block_into_basm(bang, basm, eef.then, bang->scope->frame); + compile_block_into_basm(bang, basm, eef.then); Inst_Addr else_jmp_addr = basm_push_inst(basm, INST_JMP, word_u64(0)); Inst_Addr else_addr = basm->program_size; - compile_block_into_basm(bang, basm, eef.elze, bang->scope->frame); + compile_block_into_basm(bang, basm, eef.elze); Inst_Addr end_addr = basm->program_size; basm->program[then_jmp_addr].operand = word_u64(else_addr); @@ -507,7 +509,7 @@ void compile_bang_while_into_basm(Bang *bang, Basm *basm, Bang_While hwile) basm_push_inst(basm, INST_NOT, word_u64(0)); Inst_Addr fallthrough_addr = basm_push_inst(basm, INST_JMP_IF, word_u64(0)); - compile_block_into_basm(bang, basm, hwile.body, bang->scope->frame); + compile_block_into_basm(bang, basm, hwile.body); basm_push_inst(basm, INST_JMP, word_u64(cond_expr.addr)); const Inst_Addr body_end_addr = basm->program_size; @@ -549,9 +551,9 @@ void compile_stmt_into_basm(Bang *bang, Basm *basm, Bang_Stmt stmt) } } -void compile_block_into_basm(Bang *bang, Basm *basm, Bang_Block *block, Bang_Frame *frame) +void compile_block_into_basm(Bang *bang, Basm *basm, Bang_Block *block) { - bang_push_new_scope(bang, frame); + bang_push_new_scope(bang); while (block) { compile_stmt_into_basm(bang, basm, block->stmt); block = block->next; @@ -587,10 +589,7 @@ void compile_proc_def_into_basm(Bang *bang, Basm *basm, Bang_Proc_Def proc_def) assert(bang->procs_count < BANG_PROCS_CAPACITY); bang->procs[bang->procs_count++] = proc; - compile_push_new_frame(bang, basm, bang->scope->frame ? bang->scope->frame->offset : 0); - Bang_Frame *frame = arena_alloc(&bang->arena, sizeof(*frame)); - compile_block_into_basm(bang, basm, proc_def.body, frame); - compile_pop_frame(bang, basm); + compile_block_into_basm(bang, basm, proc_def.body); basm_push_inst(basm, INST_RET, word_u64(0)); } @@ -757,21 +756,20 @@ void compile_stack_var_def_into_basm(Bang *bang, Bang_Var_Def var_def) new_var.type = type; new_var.storage = BANG_VAR_STACK_STORAGE; assert(type_def.size > 0); - assert(bang->scope->frame != NULL); - bang->scope->frame->offset += type_def.size; - new_var.addr = bang->scope->frame->offset; + bang->frame_size += type_def.size; + new_var.addr = bang->frame_size; bang_scope_push_var(bang->scope, new_var); } -void compile_push_new_frame(Bang *bang, Basm *basm, Memory_Addr frame_top_offset) +void compile_push_new_frame(Bang *bang, Basm *basm) { // 1. read frame addr compile_read_frame_addr(bang, basm); // 2. offset the frame addr to find the top of the stack assert(bang->scope != NULL); - basm_push_inst(basm, INST_PUSH, word_u64(frame_top_offset)); + basm_push_inst(basm, INST_PUSH, word_u64(bang->frame_size)); basm_push_inst(basm, INST_MINUSI, word_u64(0)); // 3. allocate memory to store the prev frame addr @@ -798,11 +796,10 @@ void compile_pop_frame(Bang *bang, Basm *basm) compile_write_frame_addr(bang, basm); } -void bang_push_new_scope(Bang *bang, Bang_Frame *frame) +void bang_push_new_scope(Bang *bang) { Bang_Scope *scope = arena_alloc(&bang->arena, sizeof(Bang_Scope)); scope->parent = bang->scope; - scope->frame = frame; bang->scope = scope; } @@ -811,16 +808,14 @@ void bang_pop_scope(Bang *bang) assert(bang->scope != NULL); Bang_Scope *scope = bang->scope; - if (scope->frame) { - size_t dealloc_size = 0; - for (size_t i = 0; i < scope->vars_count; ++i) { - if (scope->vars[i].storage == BANG_VAR_STACK_STORAGE) { - Bang_Type_Def def = bang_type_def(scope->vars[i].type); - dealloc_size += def.size; - } + size_t dealloc_size = 0; + for (size_t i = 0; i < scope->vars_count; ++i) { + if (scope->vars[i].storage == BANG_VAR_STACK_STORAGE) { + Bang_Type_Def def = bang_type_def(scope->vars[i].type); + dealloc_size += def.size; } - scope->frame->offset -= dealloc_size; } + bang->frame_size -= dealloc_size; bang->scope = bang->scope->parent; } diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index f2e307f..2038af4 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -51,17 +51,12 @@ typedef struct { Inst_Addr addr; } Compiled_Proc; -typedef struct { - Memory_Addr offset; -} Bang_Frame; - typedef struct Bang_Scope Bang_Scope; struct Bang_Scope { Bang_Scope *parent; Compiled_Var vars[BANG_SCOPE_VARS_CAPACITY]; size_t vars_count; - Bang_Frame *frame; }; Compiled_Var *bang_scope_get_compiled_var_by_name(Bang_Scope *scope, String_View name); @@ -78,6 +73,7 @@ typedef struct { Memory_Addr stack_frame_var_addr; Bang_Scope *scope; + size_t frame_size; Compiled_Proc procs[BANG_PROCS_CAPACITY]; size_t procs_count; @@ -99,7 +95,7 @@ void compile_typed_read(Basm *basm, Bang_Type type); void compile_typed_write(Basm *basm, Bang_Type type); Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr); void compile_stmt_into_basm(Bang *bang, Basm *basm, Bang_Stmt stmt); -void compile_block_into_basm(Bang *bang, Basm *basm, Bang_Block *block, Bang_Frame *frame); +void compile_block_into_basm(Bang *bang, Basm *basm, Bang_Block *block); void compile_proc_def_into_basm(Bang *bang, Basm *basm, Bang_Proc_Def proc_def); void compile_bang_if_into_basm(Bang *bang, Basm *basm, Bang_If eef); void compile_bang_while_into_basm(Bang *bang, Basm *basm, Bang_While hwile); @@ -112,10 +108,10 @@ Bang_Type compile_binary_op_into_basm(Bang *bang, Basm *basm, Bang_Binary_Op bin void compile_get_var_addr(Bang *bang, Basm *basm, Compiled_Var *var); void compile_read_frame_addr(Bang *bang, Basm *basm); void compile_write_frame_addr(Bang *bang, Basm *basm); -void compile_push_new_frame(Bang *bang, Basm *basm, Memory_Addr frame_top_offset); +void compile_push_new_frame(Bang *bang, Basm *basm); void compile_pop_frame(Bang *bang, Basm *basm); -void bang_push_new_scope(Bang *bang, Bang_Frame *frame); +void bang_push_new_scope(Bang *bang); void bang_pop_scope(Bang *bang); void bang_generate_entry_point(Bang *bang, Basm *basm, String_View entry_proc_name); From 5b2ec03784946b27d07136b605bc672ee2e92e99 Mon Sep 17 00:00:00 2001 From: rexim Date: Fri, 25 Jun 2021 20:04:01 +0700 Subject: [PATCH 4/5] (#455) Refactor rule110 to use local variables more --- bang/examples/rule110.bang | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/bang/examples/rule110.bang b/bang/examples/rule110.bang index 47a4c21..777a331 100644 --- a/bang/examples/rule110.bang +++ b/bang/examples/rule110.bang @@ -11,12 +11,6 @@ var state_next: i64; var display_base: ptr; -var i: i64; -var j: i64; - -var cell_ptr: ptr; -var cell: u8; - proc init() { # Init lookup table table_base = heap_base; @@ -41,7 +35,10 @@ proc init() { } proc print_state_current() { + var cell_ptr: ptr; + var cell: u8; + var i: i64; i = 0; while i < state_size { cell_ptr = states_base + cast(ptr, state_current * state_size + i); @@ -63,7 +60,12 @@ proc print_state_current() { } proc next_state() { + var cell_ptr: ptr; + var cell: u8; + state_next = 1 - state_current; + + var i: i64; i = 1; while i < state_size - 1 { table_index = cast(u8, 0); @@ -93,10 +95,11 @@ proc next_state() { proc main() { init(); - j = 0; - while j < state_size - 2 { + var i: i64; + i = 0; + while i < state_size - 2 { print_state_current(); next_state(); - j = j + 1; + i = i + 1; } } From 92770d8c565c9617674ddbc6ca7adc18cc136ed6 Mon Sep 17 00:00:00 2001 From: rexim Date: Fri, 25 Jun 2021 20:08:08 +0700 Subject: [PATCH 5/5] (#455) refactor gol example to use local variables more --- bang/examples/gol.bang | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/bang/examples/gol.bang b/bang/examples/gol.bang index ee85c26..36b56c7 100644 --- a/bang/examples/gol.bang +++ b/bang/examples/gol.bang @@ -9,18 +9,6 @@ var board_next: i64; var display_base: ptr; -var cell_ptr: ptr; -var cell: u8; - -var row: i64; -var col: i64; -var drow: i64; -var dcol: i64; - -var nbors: i64; - -var i: i64; - proc init() { boards_base = heap_base; board_rows = 10; @@ -38,8 +26,13 @@ proc init() { } proc print_board_current() { + var row: i64; row = 0; while row < board_rows { + var cell_ptr: ptr; + var cell: u8; + + var col: i64; col = 0; while col < board_cols { cell_ptr = boards_base + cast(ptr, board_size * board_current + row * board_cols + col); @@ -66,14 +59,23 @@ proc print_board_current() { proc next_board() { board_next = 1 - board_current; + var row: i64; row = 0; while row < board_rows { + var cell_ptr: ptr; + var cell: u8; + + var col: i64; col = 0; while col < board_cols { # Nbors begin + var nbors: i64; nbors = 0; + + var drow: i64; drow = row - 1; while drow < row + 2 { + var dcol: i64; dcol = col - 1; while dcol < col + 2 { if drow >= 0 && drow < board_rows { @@ -122,6 +124,7 @@ proc next_board() { proc main() { init(); + var i: i64; i = 0; while i < 10 { print_board_current();