include and global works

This commit is contained in:
sfja 2025-04-02 22:37:48 +02:00
parent ad2baf22d2
commit bdf3516455
3 changed files with 89 additions and 10 deletions

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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