diff --git a/asm/main.c b/asm/main.c index 346bebb..74f2b01 100644 --- a/asm/main.c +++ b/asm/main.c @@ -18,6 +18,12 @@ typedef struct { const char* output_file; } Args; +typedef struct { + char* ident; + Loc loc; + uint16_t ip; +} GlobalSym; + static inline Args parse_args(int argc, char** argv); static inline char* read_text_file(const char* filename); static inline int include_file(IdentResolver* resolver, @@ -60,22 +66,37 @@ int main(int argc, char** argv) PLine** lines = malloc(sizeof(PLine*) * lines_capacity); size_t lines_size = 0; + size_t global_symbols_capacity = 8; + GlobalSym* global_symbols + = malloc(sizeof(GlobalSym) * global_symbols_capacity); + size_t global_symbols_size = 0; + while (!parser_done(&parser)) { - if (lines_size + 1 > lines_capacity) { - lines_capacity += 2; - lines = realloc(lines, sizeof(PLine*) * lines_capacity); - } PStmt* stmt = parser_next_stmt(&parser); if (!stmt) { continue; } switch (stmt->ty) { case PStmtTy_Line: + if (lines_size + 1 > lines_capacity) { + lines_capacity *= 2; + lines = realloc(lines, sizeof(PLine*) * lines_capacity); + } lines[lines_size++] = stmt->line; // NOTE: Shallow free. free(stmt); break; case PStmtTy_Global: + if (global_symbols_size + 1 > global_symbols_capacity) { + global_symbols_capacity *= 2; + global_symbols = realloc(global_symbols, + sizeof(GlobalSym) * global_symbols_capacity); + } + global_symbols[global_symbols_size++] = (GlobalSym) { + .ident = asm_strdup(stmt->ident), + .loc = stmt->loc, + .ip = 0, + }; pstmt_free(stmt); break; case PStmtTy_Extern: @@ -85,8 +106,17 @@ int main(int argc, char** argv) const IdentResol* existing = ident_resolver_resolve(&resolver, stmt->ident); if (existing != NULL) { - REPORTF_ERROR("redefinition of constant '%s'", stmt->ident); + REPORTF_ERROR( + "redefinition of identifier '%s'", stmt->ident); reporter_print_loc(&rep, stmt->loc); + const char* filename = rep.filename; + if (existing->ty == IdentResolTy_Const) { + filename = existing->src_filename; + } + REPORTF_INFO( + "previous definition of '%s' here", existing->ident); + reporter_print_loc(&rep, existing->loc); + rep.filename = filename; errors_occured = true; pstmt_free(stmt); continue; @@ -134,6 +164,24 @@ int main(int argc, char** argv) ip += size; } + for (size_t i = 0; i < global_symbols_size; ++i) { + const IdentResol* res + = ident_resolver_resolve(&resolver, global_symbols[i].ident); + if (res == NULL) { + REPORTF_ERROR("undefined global '%s'", global_symbols[i].ident); + REPORTF_INFO("'%s' declared global here", global_symbols[i].ident); + reporter_print_loc(&rep, global_symbols[i].loc); + continue; + } else if (res->ty != IdentResolTy_Label) { + REPORTF_ERROR("'%s' cannot be declared global", res->ident); + reporter_print_loc(&rep, res->loc); + REPORTF_INFO("'%s' declared global here", global_symbols[i].ident); + reporter_print_loc(&rep, global_symbols[i].loc); + continue; + } + global_symbols[i].ip = res->ip; + } + if (errors_occured) { fprintf(stderr, "nothing written. stopping...\n"); res = -1; @@ -188,6 +236,10 @@ leave_free_chunk: for (size_t i = 0; i < lines_size; ++i) { pline_free(lines[i]); } + for (size_t i = 0; i < global_symbols_size; ++i) { + free(global_symbols[i].ident); + } + free(global_symbols); free(lines); free(input_text); ident_resolver_destroy(&resolver); @@ -270,8 +322,23 @@ static inline int include_file(IdentResolver* resolver, const IdentResol* existing = ident_resolver_resolve(resolver, stmt->ident); if (existing != NULL) { - REPORTF_ERROR("redefinition of constant '%s'", stmt->ident); + if (existing->ty == IdentResolTy_Const + && strcmp(existing->src_filename, filepath) == 0) { + // Same file included multiple times. + pstmt_free(stmt); + continue; + } + REPORTF_ERROR( + "redefinition of identifier '%s'", stmt->ident); reporter_print_loc(&rep, stmt->loc); + const char* filename = rep.filename; + if (existing->ty == IdentResolTy_Const) { + filename = existing->src_filename; + } + REPORTF_INFO( + "previous definition of '%s' here", existing->ident); + reporter_print_loc(&rep, existing->loc); + rep.filename = filename; errors_occured = true; pstmt_free(stmt); continue; @@ -372,7 +439,7 @@ static inline void use_labels(IdentResolver* resolver, PLabel* label) return; use_labels(resolver, label->next); const IdentResol* existing = ident_resolver_resolve(resolver, label->ident); - if (existing->ty == IdentResolTy_Label) { + if (existing && existing->ty == IdentResolTy_Label) { resolver->current_parent = existing; } } diff --git a/asm/report.c b/asm/report.c index b6f5404..6f43e13 100644 --- a/asm/report.c +++ b/asm/report.c @@ -4,6 +4,12 @@ void print_report_loc( const char* filename, const char* text, size_t text_len, Loc loc) { + const char* displacement_spaces + = " " + " " + " " + " "; + size_t line_start = loc.idx; while (line_start > 0 && text[line_start] != '\n') { line_start -= 1; @@ -20,8 +26,8 @@ void print_report_loc( fprintf(stderr, " \x1b[96m--> ./%s:%d:%d\n " - "\x1b[37m|\n\x1b[96m%5d\x1b[37m|%.*s\n " - "|%*c\x1b[1;91m^\x1b[0m\n", + "\x1b[37m|\n\x1b[96m%5d\x1b[37m|\x1b[0m%.*s\n " + "\x1b[37m|%.*s\x1b[1;91m^\x1b[0m\n", filename, loc.line, loc.col, @@ -29,7 +35,7 @@ void print_report_loc( line_len, line, loc.col - 1, - ' '); + displacement_spaces); } void reporter_print_loc(Reporter* rep, Loc loc) diff --git a/kern/main.asm b/kern/main.asm index d3e8807..b13d736 100644 --- a/kern/main.asm +++ b/kern/main.asm @@ -1,6 +1,10 @@ include "arch.asm" + +global start +extern other + start: ; rsp points *at* the top element mov rbp, 2048 @@ -15,6 +19,8 @@ start: mov r1, 1 int Int_DiskRead + jmp other + main_loop: hlt jmp main_loop