Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 96 additions & 15 deletions bang/src/bang.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
// #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] <input.bang>\n");
fprintf(stream, "OPTIONS:\n");
fprintf(stream, " -o <output> Provide output path\n");
fprintf(stream, " -t <target> Output target. Default is `bm`.\n");
fprintf(stream, " Provide `list` to get the list of all available targets.\n");
fprintf(stream, " -s <bytes> Local variables stack size in bytes. (default %zu)\n", (size_t) BANG_DEFAULT_STACK_SIZE);
fprintf(stream, " -h Print this help to stdout\n");
}

Expand Down Expand Up @@ -46,7 +49,11 @@ static void help_subcommand(int argc, char **argv)

static void run_usage(FILE *stream)
{
fprintf(stream, "Usage: bang run <input.bang>\n");
fprintf(stream, "Usage: bang run [OPTIONS] <input.bang>\n");
fprintf(stream, "OPTIONS:\n");
fprintf(stream, " -t Enable trace mode\n");
fprintf(stream, " -s <bytes> 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)
Expand All @@ -55,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",
Expand All @@ -74,17 +112,17 @@ 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);
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);

bang_generate_entry_point(&bang, &basm, SV("main"));
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);

Expand All @@ -96,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(#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
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, " %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]);
}
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);
}
}
}

Expand All @@ -112,6 +175,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) {
Expand Down Expand Up @@ -146,6 +210,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);
Expand Down Expand Up @@ -181,9 +262,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);

Expand All @@ -192,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);
bang_pop_scope(&bang, &basm);

arena_free(&basm.arena);
arena_free(&bang.arena);
Expand Down
86 changes: 72 additions & 14 deletions bang/src/bang_compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -721,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)) {
Expand Down Expand Up @@ -750,19 +747,80 @@ 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)
{
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));
}

void bang_push_new_scope(Bang *bang)
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(#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));
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)
{
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;
}

void bang_pop_scope(Bang *bang)
void bang_pop_scope(Bang *bang, Basm *basm)
{
compile_pop_frame(bang, basm);
assert(bang->scope != NULL);
bang->scope = bang->scope->parent;
}
12 changes: 5 additions & 7 deletions bang/src/bang_compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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;
Expand Down Expand Up @@ -104,18 +102,18 @@ 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);

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_