From 74a687f96663f254ab7ab10ff36fce924635a978 Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 24 Jun 2021 18:22:23 +0700 Subject: [PATCH 1/7] (#458) Introduce customizable stack size for `bang build` command --- bang/src/bang.c | 34 ++++++++++++++++++++++++++++------ bang/src/bang_compiler.c | 19 +++++++++---------- bang/src/bang_compiler.h | 10 ++++------ 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/bang/src/bang.c b/bang/src/bang.c index 69a9640..6e1fc21 100644 --- a/bang/src/bang.c +++ b/bang/src/bang.c @@ -9,6 +9,8 @@ // #include "./basm.h" #include "./bang_compiler.h" +#define BANG_DEFAULT_STACK_SIZE 4096 + static void build_usage(FILE *stream) { fprintf(stream, "Usage: bang build [OPTIONS] \n"); @@ -16,6 +18,7 @@ static void build_usage(FILE *stream) fprintf(stream, " -o Provide output path\n"); fprintf(stream, " -t Output target. Default is `bm`.\n"); fprintf(stream, " Provide `list` to get the list of all available targets.\n"); + fprintf(stream, " -s Local variables stack size in bytes. (default %zu)\n", (size_t) BANG_DEFAULT_STACK_SIZE); fprintf(stream, " -h Print this help to stdout\n"); } @@ -74,9 +77,10 @@ static void run_subcommand(int argc, char **argv) Bang_Module module = parse_bang_module(&basm.arena, &lexer); bang.write_id = basm_push_external_native(&basm, SV("write")); - bang_prepare_var_stack(&bang, &basm); + // TODO: there is no way to customize the stack size for `bang run` command + bang_prepare_var_stack(&bang, &basm, BANG_DEFAULT_STACK_SIZE); - bang_push_new_scope(&bang); + bang_push_new_scope(&bang, &basm); { compile_bang_module_into_basm(&bang, &basm, module); @@ -84,7 +88,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); + bang_pop_scope(&bang, &basm); basm_save_to_bm(&basm, &bm); @@ -112,6 +116,7 @@ static void build_subcommand(int argc, char **argv) const char *input_file_path = NULL; const char *output_file_path = NULL; + size_t stack_size = BANG_DEFAULT_STACK_SIZE; Target output_target = TARGET_BM; while (argc > 0) { @@ -146,6 +151,23 @@ static void build_subcommand(int argc, char **argv) fprintf(stderr, "ERROR: unknown target: `%s`\n", name); exit(1); } + } else if (strcmp(flag, "-s") == 0) { + if (argc <= 0) { + build_usage(stderr); + fprintf(stderr, "ERROR: no value is provided for flag `%s`\n", flag); + exit(1); + } + const char *stack_size_cstr = shift(&argc, &argv); + char *endptr = NULL; + + stack_size = strtoumax(stack_size_cstr, &endptr, 10); + + if (stack_size_cstr == endptr || *endptr != '\0') { + build_usage(stderr); + fprintf(stderr, "ERROR: `%s` is not a valid size of the stack\n", + stack_size_cstr); + exit(1); + } } else if (strcmp(flag, "-h") == 0) { build_usage(stdout); exit(0); @@ -181,9 +203,9 @@ static void build_subcommand(int argc, char **argv) Bang_Module module = parse_bang_module(&basm.arena, &lexer); bang.write_id = basm_push_external_native(&basm, SV("write")); - bang_prepare_var_stack(&bang, &basm); + bang_prepare_var_stack(&bang, &basm, stack_size); - bang_push_new_scope(&bang); + bang_push_new_scope(&bang, &basm); { compile_bang_module_into_basm(&bang, &basm, module); @@ -192,7 +214,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); + bang_pop_scope(&bang, &basm); arena_free(&basm.arena); arena_free(&bang.arena); diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index d3d5160..e367ee8 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -551,12 +551,12 @@ 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_push_new_scope(bang); + bang_push_new_scope(bang, basm); while (block) { compile_stmt_into_basm(bang, basm, block->stmt); block = block->next; } - bang_pop_scope(bang); + bang_pop_scope(bang, basm); } Compiled_Proc *bang_get_compiled_proc_by_name(Bang *bang, String_View name) @@ -672,14 +672,11 @@ void bang_generate_heap_base(Bang *bang, Basm *basm, String_View heap_base_var_n } } -void bang_prepare_var_stack(Bang *bang, Basm *basm) +void bang_prepare_var_stack(Bang *bang, Basm *basm, size_t stack_size) { - basm_push_byte_array_to_memory(basm, BANG_STACK_CAPACITY, 0); - const Memory_Addr stack_start_addr = BANG_STACK_CAPACITY; + basm_push_byte_array_to_memory(basm, stack_size, 0); + const Memory_Addr stack_start_addr = stack_size; - bang->stack_top_var_addr = - basm_push_buffer_to_memory( - basm, (uint8_t*) &stack_start_addr, sizeof(stack_start_addr)).as_u64; bang->stack_frame_var_addr = basm_push_buffer_to_memory( basm, (uint8_t*) &stack_start_addr, sizeof(stack_start_addr)).as_u64; @@ -754,15 +751,17 @@ void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_de assert(false && "TODO(#458): compiling the stack variable is not implemented"); } -void bang_push_new_scope(Bang *bang) +void bang_push_new_scope(Bang *bang, Basm *basm) { + (void) basm; Bang_Scope *scope = arena_alloc(&bang->arena, sizeof(Bang_Scope)); scope->parent = bang->scope; bang->scope = scope; } -void bang_pop_scope(Bang *bang) +void bang_pop_scope(Bang *bang, Basm *basm) { + (void) basm; assert(bang->scope != NULL); bang->scope = bang->scope->parent; } diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index 239eb4f..ee1cbc0 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -57,13 +57,12 @@ struct Bang_Scope { Bang_Scope *parent; Compiled_Var vars[BANG_SCOPE_VARS_CAPACITY]; size_t vars_count; + Memory_Addr frame_top_offset; }; Compiled_Var *bang_scope_get_compiled_var_by_name(Bang_Scope *scope, String_View name); void bang_scope_push_var(Bang_Scope *scope, Compiled_Var var); -#define BANG_STACK_CAPACITY 32 - #define STACK_TOP_VAR_TYPE BANG_TYPE_I64 #define STACK_FRAME_VAR_TYPE BANG_TYPE_I64 @@ -72,7 +71,6 @@ typedef struct { Native_ID write_id; - Memory_Addr stack_top_var_addr; Memory_Addr stack_frame_var_addr; Bang_Scope *scope; @@ -108,14 +106,14 @@ void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_de Bang_Type compile_var_read_into_basm(Bang *bang, Basm *basm, Bang_Var_Read var_read); Bang_Type compile_binary_op_into_basm(Bang *bang, Basm *basm, Bang_Binary_Op binary_op); -void bang_push_new_scope(Bang *bang); -void bang_pop_scope(Bang *bang); +void bang_push_new_scope(Bang *bang, Basm *basm); +void bang_pop_scope(Bang *bang, Basm *basm); 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); void bang_funcall_expect_arity(Bang_Funcall funcall, size_t expected_arity); -void bang_prepare_var_stack(Bang *bang, Basm *basm); +void bang_prepare_var_stack(Bang *bang, Basm *basm, size_t stack_size); #endif // BANG_COMPILER_H_ From 9a6015b0817ea98f2a4100bbbf22020f692bfa3b Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 24 Jun 2021 19:43:58 +0700 Subject: [PATCH 2/7] (#458) Implement compile_read_frame_addr/compile_write_frame_addr --- bang/src/bang_compiler.c | 54 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index e367ee8..45319e5 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -751,9 +751,59 @@ void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_de assert(false && "TODO(#458): compiling the stack variable is not implemented"); } +static void compile_read_frame_addr(Bang *bang, Basm *basm) +{ + basm_push_inst(basm, INST_PUSH, word_u64(bang->stack_frame_var_addr)); + basm_push_inst(basm, INST_READ64U, word_u64(0)); +} + +static void compile_write_frame_addr(Bang *bang, Basm *basm) +{ + basm_push_inst(basm, INST_PUSH, word_u64(bang->stack_frame_var_addr)); + basm_push_inst(basm, INST_SWAP, word_u64(1)); + basm_push_inst(basm, INST_WRITE64, word_u64(0)); +} + +static 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(bang->scope->frame_top_offset)); + basm_push_inst(basm, INST_MINUSI, word_u64(0)); + + // 3. allocate memory to store the prev frame addr + // TODO: get the actual size of the pointer from the definition of the ptr type + basm_push_inst(basm, INST_PUSH, word_u64(8)); + basm_push_inst(basm, INST_MINUSI, word_u64(0)); + basm_push_inst(basm, INST_DUP, word_u64(0)); + compile_read_frame_addr(bang, basm); + basm_push_inst(basm, INST_WRITE64, word_u64(0)); + + // 4. redirect the current frame + compile_write_frame_addr(bang, basm); +} + +static void compile_pop_frame(Bang *bang, Basm *basm) +{ + // 1. read frame addr + compile_read_frame_addr(bang, basm); + + // 2. read prev frame addr + basm_push_inst(basm, INST_READ64U, word_u64(0)); + + // 3. write the prev frame back to the current frame + compile_write_frame_addr(bang, basm); +} + void bang_push_new_scope(Bang *bang, Basm *basm) { - (void) basm; + if (bang->scope) { + compile_push_new_frame(bang, basm); + } + Bang_Scope *scope = arena_alloc(&bang->arena, sizeof(Bang_Scope)); scope->parent = bang->scope; bang->scope = scope; @@ -761,7 +811,7 @@ void bang_push_new_scope(Bang *bang, Basm *basm) void bang_pop_scope(Bang *bang, Basm *basm) { - (void) basm; + compile_pop_frame(bang, basm); assert(bang->scope != NULL); bang->scope = bang->scope->parent; } From c46dc19d48e9f938fc7afb1d1595d69db4a12cc0 Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 24 Jun 2021 20:20:12 +0700 Subject: [PATCH 3/7] (#458) Introduce tracing mode for `bang run` --- bang/src/bang.c | 81 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 11 deletions(-) diff --git a/bang/src/bang.c b/bang/src/bang.c index 6e1fc21..193cc71 100644 --- a/bang/src/bang.c +++ b/bang/src/bang.c @@ -49,7 +49,11 @@ static void help_subcommand(int argc, char **argv) static void run_usage(FILE *stream) { - fprintf(stream, "Usage: bang run \n"); + fprintf(stream, "Usage: bang run [OPTIONS] \n"); + fprintf(stream, "OPTIONS:\n"); + fprintf(stream, " -t Enable trace mode\n"); + fprintf(stream, " -s Local variables stack size in bytes. (default %zu)\n", (size_t) BANG_DEFAULT_STACK_SIZE); + fprintf(stream, " -h Print this help to stdout\n"); } static void run_subcommand(int argc, char **argv) @@ -58,14 +62,45 @@ static void run_subcommand(int argc, char **argv) static Basm basm = {0}; static Bang bang = {0}; - if (argc == 0) { + bool trace = false; + const char *input_file_path = NULL; + size_t stack_size = BANG_DEFAULT_STACK_SIZE; + + while (argc > 0) { + const char *flag = shift(&argc, &argv); + if (strcmp(flag, "-t") == 0) { + trace = true; + } else if (strcmp(flag, "-h") == 0) { + run_usage(stdout); + exit(0); + } else if (strcmp(flag, "-s") == 0) { + if (argc <= 0) { + run_usage(stderr); + fprintf(stderr, "ERROR: no value is provided for flag `%s`\n", flag); + exit(1); + } + const char *stack_size_cstr = shift(&argc, &argv); + char *endptr = NULL; + + stack_size = strtoumax(stack_size_cstr, &endptr, 10); + + if (stack_size_cstr == endptr || *endptr != '\0') { + run_usage(stderr); + fprintf(stderr, "ERROR: `%s` is not a valid size of the stack\n", + stack_size_cstr); + exit(1); + } + } else { + input_file_path = flag; + } + } + + if (input_file_path == NULL) { run_usage(stderr); fprintf(stderr, "ERROR: no input file is provided\n"); exit(1); } - const char *input_file_path = shift(&argc, &argv); - String_View content = {0}; if (arena_slurp_file(&bang.arena, sv_from_cstr(input_file_path), &content) < 0) { fprintf(stderr, "ERROR: could not read file `%s`: %s", @@ -77,8 +112,7 @@ static void run_subcommand(int argc, char **argv) Bang_Module module = parse_bang_module(&basm.arena, &lexer); bang.write_id = basm_push_external_native(&basm, SV("write")); - // TODO: there is no way to customize the stack size for `bang run` command - bang_prepare_var_stack(&bang, &basm, BANG_DEFAULT_STACK_SIZE); + bang_prepare_var_stack(&bang, &basm, stack_size); bang_push_new_scope(&bang, &basm); { @@ -100,12 +134,37 @@ static void run_subcommand(int argc, char **argv) } } - const int limit = -1; - Err err = bm_execute_program(&bm, limit); + while (!bm.halt) { + if (trace) { + const Inst inst = bm.program[bm.ip]; + const Inst_Def def = get_inst_def(inst.type); + fprintf(stderr, "%s", def.name); + if (def.has_operand) { + fprintf(stderr, " %"PRIu64, inst.operand.as_u64); + } + fprintf(stderr, "\n"); + } + Err err = bm_execute_inst(&bm); + if (trace) { + // TODO: `bang run` needs a way to customize trace mode parameters +#define BANG_TRACE_MEMORY_START 0 +#define BANG_TRACE_CELL_COUNT 5 +#define BANG_TRACE_CELL_SIZE 8 + for (size_t cell = 0; cell < BANG_TRACE_CELL_COUNT; ++cell) { + const Memory_Addr start = BANG_TRACE_MEMORY_START + cell * BANG_TRACE_CELL_SIZE; + fprintf(stderr, " %04lX:", start); + for (size_t byte = 0; byte < BANG_TRACE_CELL_SIZE; ++byte) { + const Memory_Addr addr = start + byte; + fprintf(stderr, " %02X", bm.memory[addr]); + } + fprintf(stderr, "\n"); + } + } - if (err != ERR_OK) { - fprintf(stderr, "ERROR: %s\n", err_as_cstr(err)); - exit(1); + if (err != ERR_OK) { + fprintf(stderr, "ERROR: %s\n", err_as_cstr(err)); + exit(1); + } } } From 1089908c8257484ea68b3a72b2c1848b5bbd168e Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 24 Jun 2021 20:42:58 +0700 Subject: [PATCH 4/7] (#458) Implement the compilation of the local variables --- bang/src/bang_compiler.c | 17 +++++++++++++---- bang/src/bang_compiler.h | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 45319e5..12e8a3a 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -539,7 +539,7 @@ void compile_stmt_into_basm(Bang *bang, Basm *basm, Bang_Stmt stmt) break; case BANG_STMT_KIND_VAR_DEF: - compile_stack_var_def_into_basm(bang, basm, stmt.as.var_def); + compile_stack_var_def_into_basm(bang, stmt.as.var_def); break; case COUNT_BANG_STMT_KINDS: @@ -718,7 +718,7 @@ void compile_static_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_d bang_scope_push_var(bang->scope, new_var); } -void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def) +void compile_stack_var_def_into_basm(Bang *bang, Bang_Var_Def var_def) { Bang_Type type = 0; if (!bang_type_by_name(var_def.type_name, &type)) { @@ -747,8 +747,17 @@ void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_de exit(1); } - (void) basm; - assert(false && "TODO(#458): compiling the stack variable is not implemented"); + Bang_Type_Def type_def = bang_type_def(type); + + Compiled_Var new_var = {0}; + new_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; + + bang_scope_push_var(bang->scope, new_var); } static void compile_read_frame_addr(Bang *bang, Basm *basm) diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index ee1cbc0..3042832 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -102,7 +102,7 @@ void compile_bang_while_into_basm(Bang *bang, Basm *basm, Bang_While hwile); void compile_bang_var_assign_into_basm(Bang *bang, Basm *basm, Bang_Var_Assign var_assign); void compile_bang_module_into_basm(Bang *bang, Basm *basm, Bang_Module module); void compile_static_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def); -void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def); +void compile_stack_var_def_into_basm(Bang *bang, Bang_Var_Def var_def); Bang_Type compile_var_read_into_basm(Bang *bang, Basm *basm, Bang_Var_Read var_read); Bang_Type compile_binary_op_into_basm(Bang *bang, Basm *basm, Bang_Binary_Op binary_op); From e33b0a778db5f7620d7c6f87a5eaddab6a114e2e Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 24 Jun 2021 20:45:25 +0700 Subject: [PATCH 5/7] Add TODO(#469) --- bang/src/bang.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bang/src/bang.c b/bang/src/bang.c index 193cc71..bac4d4a 100644 --- a/bang/src/bang.c +++ b/bang/src/bang.c @@ -146,7 +146,7 @@ static void run_subcommand(int argc, char **argv) } Err err = bm_execute_inst(&bm); if (trace) { - // TODO: `bang run` needs a way to customize trace mode parameters + // TODO(#469): `bang run` needs a way to customize trace mode parameters #define BANG_TRACE_MEMORY_START 0 #define BANG_TRACE_CELL_COUNT 5 #define BANG_TRACE_CELL_SIZE 8 From 4dc82a9b5deebcf4d7e2881cb2ccc9fd4480d52a Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 24 Jun 2021 20:45:25 +0700 Subject: [PATCH 6/7] Add TODO(#470) --- bang/src/bang_compiler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 12e8a3a..b37cd95 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -784,7 +784,7 @@ static void compile_push_new_frame(Bang *bang, Basm *basm) basm_push_inst(basm, INST_MINUSI, word_u64(0)); // 3. allocate memory to store the prev frame addr - // TODO: get the actual size of the pointer from the definition of the ptr type + // TODO(#470): get the actual size of the pointer from the definition of the ptr type basm_push_inst(basm, INST_PUSH, word_u64(8)); basm_push_inst(basm, INST_MINUSI, word_u64(0)); basm_push_inst(basm, INST_DUP, word_u64(0)); From c123d65643700e996f34f0ec12952fdac95acc75 Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 24 Jun 2021 20:50:53 +0700 Subject: [PATCH 7/7] (#458) Try to fix MSVC build --- bang/src/bang.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bang/src/bang.c b/bang/src/bang.c index bac4d4a..2c96b48 100644 --- a/bang/src/bang.c +++ b/bang/src/bang.c @@ -152,7 +152,7 @@ static void run_subcommand(int argc, char **argv) #define BANG_TRACE_CELL_SIZE 8 for (size_t cell = 0; cell < BANG_TRACE_CELL_COUNT; ++cell) { const Memory_Addr start = BANG_TRACE_MEMORY_START + cell * BANG_TRACE_CELL_SIZE; - fprintf(stderr, " %04lX:", start); + fprintf(stderr, " %04"PRIX64":", start); for (size_t byte = 0; byte < BANG_TRACE_CELL_SIZE; ++byte) { const Memory_Addr addr = start + byte; fprintf(stderr, " %02X", bm.memory[addr]);