diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 67a0898..fdb017d 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -683,6 +683,7 @@ void bang_prepare_var_stack(Bang *bang, Basm *basm, size_t stack_size) assert(sizeof(stack_start_addr) == ptr_def.size); bang->stack_frame_var_addr = basm_push_buffer_to_memory(basm, (uint8_t*) &stack_start_addr, ptr_def.size).as_u64; + basm->memory_base = stack_size; } void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Bang_Var_Storage storage) diff --git a/basm/src/compiler.c b/basm/src/compiler.c index 89f7c86..c9103f3 100644 --- a/basm/src/compiler.c +++ b/basm/src/compiler.c @@ -308,7 +308,8 @@ void basm_save_to_file_as_bm(Basm *basm, const char *file_path) .version = BM_FILE_VERSION, .entry = basm->entry, .program_size = basm->program_size, - .memory_size = basm->memory_size, + .memory_base = basm->memory_base, + .memory_size = basm->memory_size - basm->memory_base, .memory_capacity = basm->memory_capacity, .externals_size = basm->external_natives_size, }; @@ -327,7 +328,7 @@ void basm_save_to_file_as_bm(Basm *basm, const char *file_path) exit(1); } - fwrite(basm->memory, sizeof(basm->memory[0]), basm->memory_size, f); + fwrite(basm->memory + basm->memory_base, sizeof(basm->memory[0]), basm->memory_size - basm->memory_base, f); if (ferror(f)) { fprintf(stderr, "ERROR: Could not write to file `%s`: %s\n", file_path, strerror(errno)); @@ -403,6 +404,10 @@ void basm_translate_block_statement(Basm *basm, Block_Statement *block) basm_translate_macrodef_statement(basm, statement.value.as_macrodef, statement.location); break; + case STATEMENT_KIND_BASE: + basm_translate_base_statement(basm, statement.value.as_base, statement.location); + break; + case STATEMENT_KIND_MACROCALL: case STATEMENT_KIND_FUNCDEF: case STATEMENT_KIND_FOR: @@ -470,6 +475,7 @@ void basm_translate_block_statement(Basm *basm, Block_Statement *block) case STATEMENT_KIND_ASSERT: case STATEMENT_KIND_INCLUDE: case STATEMENT_KIND_CONST: + case STATEMENT_KIND_BASE: // NOTE: ignored at the second pass break; @@ -1288,6 +1294,19 @@ Macrodef *basm_resolve_macrodef(Basm *basm, String_View name) return NULL; } + +void basm_translate_base_statement(Basm *basm, Base_Statement base_statement, File_Location location) +{ + if (basm->memory_size != 0 || basm->memory_base != 0) { + fprintf(stderr, FL_Fmt": ERROR: %%base should precede every memory related statements\n", + FL_Arg(location)); + exit(1); + } + + basm_push_byte_array_to_memory(basm, base_statement.size, 0); + basm->memory_base = basm->memory_size; +} + Native_ID basm_push_external_native(Basm *basm, String_View native_name) { assert(basm->external_natives_size < BM_EXTERNAL_NATIVES_CAPACITY); diff --git a/basm/src/compiler.h b/basm/src/compiler.h index a9c0bb4..d3cdba0 100644 --- a/basm/src/compiler.h +++ b/basm/src/compiler.h @@ -126,6 +126,7 @@ typedef struct { size_t string_lengths_size; uint8_t memory[BM_MEMORY_CAPACITY]; + size_t memory_base; size_t memory_size; size_t memory_capacity; @@ -179,6 +180,7 @@ bool basm_resolve_include_file_path(Basm *basm, Macrodef *basm_resolve_macrodef(Basm *basm, String_View name); void basm_translate_macrocall_statement(Basm *basm, Macrocall_Statement macrocall, File_Location location); void basm_translate_macrodef_statement(Basm *basm, Macrodef_Statement macrodef, File_Location location); +void basm_translate_base_statement(Basm *basm, Base_Statement base_statement, File_Location location); void basm_translate_block_statement(Basm *basm, Block_Statement *block); void basm_translate_const_statement(Basm *basm, Const_Statement konst, File_Location location); void basm_translate_native_statement(Basm *basm, Native_Statement native, File_Location location); diff --git a/basm/src/statement.c b/basm/src/statement.c index 55aa951..4355581 100644 --- a/basm/src/statement.c +++ b/basm/src/statement.c @@ -125,6 +125,14 @@ void dump_statement(FILE *stream, Statement statement, int level) exit(1); } break; + + case STATEMENT_KIND_BASE: { + uint64_t size = statement.value.as_base.size; + + fprintf(stream, "%*sBase:\n", level * 2, ""); + fprintf(stream, "%*s%"PRIu64"\n", (level + 1) * 2, "", size); + } + break; } } @@ -426,6 +434,20 @@ int dump_statement_as_dot_edges(FILE *stream, Statement statement, int *counter) } break; + case STATEMENT_KIND_BASE: { + int id = (*counter)++; + int child_id = (*counter)++; + + uint64_t size = statement.value.as_base.size; + + fprintf(stream, "Expr_%d [shape=diamond label=\"%%base\"]\n", id); + fprintf(stream, "Expr_%d [shape=circle label=\"%"PRIu64"\"]\n", + child_id, size); + fprintf(stream, "Expr_%d -> Expr_%d [style=dotted]\n", id, child_id); + return id; + } + break; + default: { assert(false && "dump_statement_as_dot_edges: unreachable"); exit(1); @@ -732,6 +754,23 @@ void parse_directive_from_line(Arena *arena, Linizer *linizer, Block_List *outpu exit(1); } + block_list_push(arena, output, statement); + } else if (sv_eq(name, sv_from_cstr("base"))) { + Statement statement = {0}; + statement.location = location; + statement.kind = STATEMENT_KIND_BASE; + + Tokenizer tokenizer = tokenizer_from_sv(body); + Expr base_size = parse_expr_from_tokens(arena, &tokenizer, location); + if (base_size.kind != EXPR_KIND_LIT_INT) { + fprintf(stderr, FL_Fmt": ERROR: expected memory base for %%base\n", + FL_Arg(location)); + exit(1); + } + + statement.value.as_base.size = base_size.value.as_lit_int; + expect_no_tokens(&tokenizer, location); + block_list_push(arena, output, statement); } else { Tokenizer tokenizer = tokenizer_from_sv(body); diff --git a/basm/src/statement.h b/basm/src/statement.h index 3b30da1..d667ae4 100644 --- a/basm/src/statement.h +++ b/basm/src/statement.h @@ -24,7 +24,8 @@ typedef enum { STATEMENT_KIND_FOR, STATEMENT_KIND_FUNCDEF, STATEMENT_KIND_MACROCALL, - STATEMENT_KIND_MACRODEF + STATEMENT_KIND_MACRODEF, + STATEMENT_KIND_BASE } Statement_Kind; typedef struct { @@ -92,6 +93,10 @@ typedef struct { Block_Statement *body; } Macrodef_Statement; +typedef struct { + uint64_t size; +} Base_Statement; + typedef union { Emit_Inst_Statement as_emit_inst; Label_Statement as_label; @@ -108,6 +113,7 @@ typedef union { Fundef_Statement as_fundef; Macrocall_Statement as_macrocall; Macrodef_Statement as_macrodef; + Base_Statement as_base; } Statement_Value; struct Statement { diff --git a/bm/src/bm.c b/bm/src/bm.c index 505f4ea..89ef7bb 100644 --- a/bm/src/bm.c +++ b/bm/src/bm.c @@ -891,11 +891,11 @@ void bm_load_program_from_file(Bm *bm, const char *file_path) exit(1); } - if (meta.memory_size > meta.memory_capacity) { + if (meta.memory_base + meta.memory_size > meta.memory_capacity) { fprintf(stderr, "ERROR: %s: memory size %"PRIu64" is greater than declared memory capacity %"PRIu64"\n", file_path, - meta.memory_size, + meta.memory_base + meta.memory_size, meta.memory_capacity); exit(1); } @@ -919,8 +919,9 @@ void bm_load_program_from_file(Bm *bm, const char *file_path) exit(1); } - n = fread(bm->memory, sizeof(bm->memory[0]), meta.memory_size, f); + n = fread(bm->memory + meta.memory_base, sizeof(bm->memory[0]), meta.memory_size, f); bm->expected_memory_size = meta.memory_size; + bm->memory_base = meta.memory_base; if (n != meta.memory_size) { fprintf(stderr, "ERROR: %s: read %zd bytes of memory section, but expected %"PRIu64" bytes.\n", diff --git a/bm/src/bm.h b/bm/src/bm.h index af15b5b..4e00587 100644 --- a/bm/src/bm.h +++ b/bm/src/bm.h @@ -188,6 +188,7 @@ struct Bm { // The program is allowed to access memory beyond the `expected_memory_size`. // This variable is needed for debasm to reliably recover the source code. size_t expected_memory_size; + size_t memory_base; bool halt; }; @@ -199,13 +200,14 @@ void bm_dump_stack(FILE *stream, const Bm *bm); void bm_load_program_from_file(Bm *bm, const char *file_path); #define BM_FILE_MAGIC 0xa4016d62 -#define BM_FILE_VERSION 7 +#define BM_FILE_VERSION 8 PACK(struct Bm_File_Meta { uint32_t magic; uint16_t version; uint64_t program_size; uint64_t entry; + uint64_t memory_base; uint64_t memory_size; uint64_t memory_capacity; uint64_t externals_size; diff --git a/debasm/src/debasm.c b/debasm/src/debasm.c index 3b97895..ae53b9a 100644 --- a/debasm/src/debasm.c +++ b/debasm/src/debasm.c @@ -20,8 +20,9 @@ int main(int argc, char *argv[]) printf("%%native %s\n", bm.externals[i].name); } + printf("%%base %zu\n", bm.memory_base); printf("%%const MEMORY = \""); - for (size_t i = 0; i < bm.expected_memory_size; ++i) { + for (size_t i = bm.memory_base; i < bm.expected_memory_size + bm.memory_base; ++i) { if (32 <= bm.memory[i] && bm.memory[i] < 127) { printf("%c", bm.memory[i]); } else { @@ -29,7 +30,7 @@ int main(int argc, char *argv[]) } } printf("\"\n"); - printf("%%assert MEMORY == 0\n"); + printf("%%assert MEMORY == %zu\n", bm.memory_base); for (Inst_Addr i = 0; i < bm.program_size; ++i) { if (i == bm.ip) {