external works

This commit is contained in:
sfja 2025-04-03 01:44:31 +02:00
parent bdf3516455
commit 89f20f8a35
6 changed files with 231 additions and 37 deletions

View File

@ -7,6 +7,70 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
void operand_evaluator_construct(
OperandEvaluator* evaluator, IdentResolver* re, Reporter* rep)
{
const size_t used_imms_capacity = 64;
const size_t externals_capacity = 64;
*evaluator = (OperandEvaluator) {
.re = re,
.rep = rep,
.second_pass = false,
.used_imms = malloc(sizeof(uint16_t) * used_imms_capacity),
.used_imms_size = 0,
.externals = malloc(sizeof(SurrogateExternal) * externals_capacity),
.externals_size = 0,
};
}
void operand_evaluator_destroy(OperandEvaluator* evaluator)
{
free(evaluator->used_imms);
free(evaluator->externals);
}
void operand_evaluator_reset_externals(OperandEvaluator* evaluator)
{
evaluator->used_imms_size = 0;
evaluator->externals_size = 0;
}
void operand_evaluator_use_imm(OperandEvaluator* evaluator, uint16_t imm)
{
for (size_t i = 0; i < evaluator->used_imms_size; ++i)
if (evaluator->used_imms[i] == imm)
return;
evaluator->used_imms[evaluator->used_imms_size++] = imm;
}
uint16_t operand_evaluator_use_external(
OperandEvaluator* evaluator, const IdentResol* resol)
{
uint16_t surrogate;
if (evaluator->externals_size > 0 && evaluator->used_imms_size > 0) {
surrogate
= evaluator->externals[evaluator->externals_size - 1].surrogate - 1;
while (surrogate > 0) {
bool used = false;
for (size_t i = 0; i < evaluator->used_imms_size; ++i)
if (evaluator->used_imms[i] == surrogate)
used = true;
if (!used)
break;
used -= 1;
}
} else {
surrogate = 0xffff;
}
evaluator->externals[evaluator->externals_size++] = (SurrogateExternal) {
.resol = resol,
.extern_id = resol->extern_id,
.surrogate = surrogate,
};
return surrogate;
}
static inline uint16_t eval_poperandty_unary(POperandTy ty, uint16_t operand) static inline uint16_t eval_poperandty_unary(POperandTy ty, uint16_t operand)
{ {
switch (ty) { switch (ty) {
@ -87,7 +151,11 @@ EvaledOperand eval_operand_to_imm(
return (EvaledOperand) { .ty = EoTy_Imm, .imm = re->ip }; return (EvaledOperand) { .ty = EoTy_Imm, .imm = re->ip };
case IdentResolTy_Const: case IdentResolTy_Const:
return (EvaledOperand) { .ty = EoTy_Imm, .imm = re->value }; return (EvaledOperand) { .ty = EoTy_Imm, .imm = re->value };
break; case IdentResolTy_Extern:
return (EvaledOperand) {
.ty = EoTy_Imm,
.imm = operand_evaluator_use_external(evaluator, re),
};
} }
fprintf(stderr, "unreachable\n"); fprintf(stderr, "unreachable\n");
exit(1); exit(1);
@ -299,8 +367,13 @@ EvaledOperand eval_operand(OperandEvaluator* evaluator, POperand* operand)
case PoTy_Sub: case PoTy_Sub:
case PoTy_Mul: case PoTy_Mul:
case PoTy_Div: case PoTy_Div:
case PoTy_Mod: case PoTy_Mod: {
return eval_operand_to_imm(evaluator, operand); EvaledOperand evaled = eval_operand_to_imm(evaluator, operand);
if (evaled.ty == EoTy_Imm) {
operand_evaluator_use_imm(evaluator, evaled.imm);
}
return evaled;
}
} }
fprintf(stderr, "unreachable\n"); fprintf(stderr, "unreachable\n");
exit(1); exit(1);

View File

@ -26,12 +26,30 @@ typedef struct {
uint16_t offset; uint16_t offset;
} EvaledOperand; } EvaledOperand;
typedef struct {
const IdentResol* resol;
size_t extern_id;
uint16_t surrogate;
} SurrogateExternal;
typedef struct { typedef struct {
IdentResolver* re; IdentResolver* re;
Reporter* rep; Reporter* rep;
bool second_pass; bool second_pass;
uint16_t* used_imms;
size_t used_imms_size;
SurrogateExternal* externals;
size_t externals_size;
} OperandEvaluator; } OperandEvaluator;
void operand_evaluator_construct(
OperandEvaluator* evaluator, IdentResolver* re, Reporter* rep);
void operand_evaluator_destroy(OperandEvaluator* evaluator);
void operand_evaluator_reset_externals(OperandEvaluator* evaluator);
void operand_evaluator_use_imm(OperandEvaluator* evaluator, uint16_t imm);
EvaledOperand eval_operand_to_imm( EvaledOperand eval_operand_to_imm(
OperandEvaluator* evaluator, POperand* operand); OperandEvaluator* evaluator, POperand* operand);
EvaledOperand eval_operand_indirection_expr( EvaledOperand eval_operand_indirection_expr(

View File

@ -24,12 +24,24 @@ typedef struct {
uint16_t ip; uint16_t ip;
} GlobalSym; } GlobalSym;
typedef struct {
size_t id;
char* ident;
} ExternSym;
typedef struct {
size_t id;
uint16_t ip;
} ExternRef;
static inline Args parse_args(int argc, char** argv); static inline Args parse_args(int argc, char** argv);
static inline char* read_text_file(const char* filename); static inline char* read_text_file(const char* filename);
static inline int include_file(IdentResolver* resolver, static inline int include_file(IdentResolver* resolver,
OperandEvaluator* evaluator, OperandEvaluator* evaluator,
const char* origin, const char* origin,
const char* filename); const char* filename);
static inline void report_redefinition(
const IdentResol* existing, PStmt* stmt, Reporter* rep);
static inline int define_labels( static inline int define_labels(
IdentResolver* resolver, PLabel* label, uint16_t asm_ip, Reporter* rep); IdentResolver* resolver, PLabel* label, uint16_t asm_ip, Reporter* rep);
static inline void use_labels(IdentResolver* resolver, PLabel* label); static inline void use_labels(IdentResolver* resolver, PLabel* label);
@ -56,11 +68,8 @@ int main(int argc, char** argv)
IdentResolver resolver; IdentResolver resolver;
ident_resolver_construct(&resolver); ident_resolver_construct(&resolver);
OperandEvaluator evaluator = { OperandEvaluator evaluator;
.re = &resolver, operand_evaluator_construct(&evaluator, &resolver, &rep);
.rep = &rep,
.second_pass = false,
};
size_t lines_capacity = 1024; size_t lines_capacity = 1024;
PLine** lines = malloc(sizeof(PLine*) * lines_capacity); PLine** lines = malloc(sizeof(PLine*) * lines_capacity);
@ -71,6 +80,11 @@ int main(int argc, char** argv)
= malloc(sizeof(GlobalSym) * global_symbols_capacity); = malloc(sizeof(GlobalSym) * global_symbols_capacity);
size_t global_symbols_size = 0; size_t global_symbols_size = 0;
size_t extern_symbols_capacity = 8;
ExternSym* extern_symbols
= malloc(sizeof(ExternSym) * extern_symbols_capacity);
size_t extern_symbols_size = 0;
while (!parser_done(&parser)) { while (!parser_done(&parser)) {
PStmt* stmt = parser_next_stmt(&parser); PStmt* stmt = parser_next_stmt(&parser);
if (!stmt) { if (!stmt) {
@ -99,25 +113,34 @@ int main(int argc, char** argv)
}; };
pstmt_free(stmt); pstmt_free(stmt);
break; break;
case PStmtTy_Extern: case PStmtTy_Extern: {
const IdentResol* existing
= ident_resolver_resolve(&resolver, stmt->ident);
if (existing != NULL) {
report_redefinition(existing, stmt, &rep);
pstmt_free(stmt);
continue;
}
size_t id = extern_symbols_size;
ident_resolver_define_extern(
&resolver, asm_strdup(stmt->ident), stmt->loc, id);
if (extern_symbols_size + 1 > extern_symbols_capacity) {
extern_symbols_capacity *= 2;
extern_symbols = realloc(extern_symbols,
sizeof(ExternSym) * extern_symbols_capacity);
}
extern_symbols[extern_symbols_size++] = (ExternSym) {
.ident = asm_strdup(stmt->ident),
.id = id,
};
pstmt_free(stmt); pstmt_free(stmt);
break; break;
}
case PStmtTy_Const: { case PStmtTy_Const: {
const IdentResol* existing const IdentResol* existing
= ident_resolver_resolve(&resolver, stmt->ident); = ident_resolver_resolve(&resolver, stmt->ident);
if (existing != NULL) { if (existing != NULL) {
REPORTF_ERROR( report_redefinition(existing, stmt, &rep);
"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); pstmt_free(stmt);
continue; continue;
} }
@ -150,17 +173,48 @@ int main(int argc, char** argv)
errors_occured &= parser_error_occured(&parser); errors_occured &= parser_error_occured(&parser);
size_t extern_refs_capacity = 8;
ExternRef* extern_refs = malloc(sizeof(ExternRef) * extern_refs_capacity);
size_t extern_refs_size = 0;
size_t chunk_capacity = 64; size_t chunk_capacity = 64;
uint16_t* chunk = malloc(sizeof(uint16_t) * chunk_capacity); uint16_t* chunk = malloc(sizeof(uint16_t) * chunk_capacity);
uint16_t ip = 0; uint16_t ip = 0;
for (size_t i = 0; i < lines_size; ++i) { for (size_t i = 0; i < lines_size; ++i) {
operand_evaluator_reset_externals(&evaluator);
int res = define_labels(&resolver, lines[i]->labels, ip, &rep); int res = define_labels(&resolver, lines[i]->labels, ip, &rep);
if (res != 0) if (res != 0)
errors_occured = true; errors_occured = true;
uint16_t size = pline_assemble(&evaluator, chunk, lines[i], &rep); uint16_t size = pline_assemble(&evaluator, chunk, lines[i], &rep);
if (size == 0) if (size == 0)
errors_occured = true; errors_occured = true;
for (size_t i = 0; i < evaluator.externals_size; ++i) {
const SurrogateExternal* ex = &evaluator.externals[i];
bool found = false;
for (uint16_t chunk_i = 1; chunk_i < size; ++chunk_i) {
if (chunk[chunk_i] == ex->surrogate) {
found = true;
if (extern_refs_size + 1 > extern_refs_capacity) {
extern_refs_capacity *= 2;
extern_refs = realloc(extern_refs,
sizeof(ExternRef) * extern_refs_capacity);
}
extern_refs[extern_refs_size++] = (ExternRef) {
.id = ex->extern_id,
.ip = ip + chunk_i,
};
break;
}
}
assert(found);
}
ip += size; ip += size;
} }
@ -190,6 +244,28 @@ int main(int argc, char** argv)
evaluator.second_pass = true; evaluator.second_pass = true;
printf("globals:\n");
printf("symbol address\n");
printf("-----------------------\n");
for (size_t i = 0; i < global_symbols_size; ++i) {
GlobalSym* sym = &global_symbols[i];
printf("%-15s %d\n", sym->ident, sym->ip);
}
printf("\nexterns:\n");
printf("id symbol\n");
printf("--------------------\n");
for (size_t i = 0; i < extern_symbols_size; ++i) {
ExternSym* sym = &extern_symbols[i];
printf("%-3ld %s\n", sym->id, sym->ident);
}
printf("\nextern uses:\n");
printf("id address\n");
printf("-----------\n");
for (size_t i = 0; i < extern_refs_size; ++i) {
ExternRef* ref = &extern_refs[i];
printf("%3ld %04x\n", ref->id, ref->ip);
}
FILE* output_fp = fopen(args.output_file, "wb"); FILE* output_fp = fopen(args.output_file, "wb");
if (!output_fp) { if (!output_fp) {
REPORTF_ERROR("could not open output file '%s': %s", REPORTF_ERROR("could not open output file '%s': %s",
@ -209,7 +285,7 @@ int main(int argc, char** argv)
} }
if (errors_occured) if (errors_occured)
continue; break;
size_t bytes_written = fwrite(chunk, sizeof(uint16_t), size, output_fp); size_t bytes_written = fwrite(chunk, sizeof(uint16_t), size, output_fp);
total_bytes_written += bytes_written; total_bytes_written += bytes_written;
@ -233,15 +309,18 @@ int main(int argc, char** argv)
leave_free_chunk: leave_free_chunk:
free(chunk); free(chunk);
// leave_free_lines: // leave_free_lines:
for (size_t i = 0; i < lines_size; ++i) { for (size_t i = 0; i < lines_size; ++i)
pline_free(lines[i]); pline_free(lines[i]);
} for (size_t i = 0; i < global_symbols_size; ++i)
for (size_t i = 0; i < global_symbols_size; ++i) {
free(global_symbols[i].ident); free(global_symbols[i].ident);
}
free(global_symbols); free(global_symbols);
for (size_t i = 0; i < extern_symbols_size; ++i)
free(extern_symbols[i].ident);
free(extern_symbols);
free(extern_refs);
free(lines); free(lines);
free(input_text); free(input_text);
operand_evaluator_destroy(&evaluator);
ident_resolver_destroy(&resolver); ident_resolver_destroy(&resolver);
return res; return res;
} }
@ -328,17 +407,7 @@ static inline int include_file(IdentResolver* resolver,
pstmt_free(stmt); pstmt_free(stmt);
continue; continue;
} }
REPORTF_ERROR( report_redefinition(existing, stmt, &rep);
"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; errors_occured = true;
pstmt_free(stmt); pstmt_free(stmt);
continue; continue;
@ -379,6 +448,20 @@ static inline int include_file(IdentResolver* resolver,
return errors_occured; return errors_occured;
} }
static inline void report_redefinition(
const IdentResol* existing, PStmt* stmt, Reporter* rep)
{
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;
}
static inline char* read_text_file(const char* filename) static inline char* read_text_file(const char* filename)
{ {
FILE* fp = fopen(filename, "r"); FILE* fp = fopen(filename, "r");

View File

@ -15,6 +15,9 @@ void ident_resol_destroy(IdentResol* resol)
free(resol->ident); free(resol->ident);
free(resol->src_filename); free(resol->src_filename);
break; break;
case IdentResolTy_Extern:
free(resol->ident);
break;
} }
} }
@ -97,6 +100,18 @@ void ident_resolver_define_const(IdentResolver* resolver,
}; };
} }
void ident_resolver_define_extern(
IdentResolver* resolver, char* ident, Loc loc, size_t extern_id)
{
size_t i = ident_resolver_first_empty(resolver);
resolver->resols[i] = (IdentResol) {
.ident = ident,
.loc = loc,
.ty = IdentResolTy_Extern,
.extern_id = extern_id,
};
}
const IdentResol* ident_resolver_resolve( const IdentResol* ident_resolver_resolve(
const IdentResolver* resolver, const char* ident) const IdentResolver* resolver, const char* ident)
{ {

View File

@ -8,6 +8,7 @@ typedef enum {
IdentResolTy_Label, IdentResolTy_Label,
IdentResolTy_SubLabel, IdentResolTy_SubLabel,
IdentResolTy_Const, IdentResolTy_Const,
IdentResolTy_Extern,
} IdentResolTy; } IdentResolTy;
typedef struct IdentResol IdentResol; typedef struct IdentResol IdentResol;
@ -22,6 +23,7 @@ struct IdentResol {
uint16_t value; uint16_t value;
char* src_filename; char* src_filename;
}; };
size_t extern_id;
}; };
}; };
@ -46,5 +48,7 @@ void ident_resolver_define_const(IdentResolver* resolver,
Loc loc, Loc loc,
uint16_t value, uint16_t value,
char* src_filename); char* src_filename);
void ident_resolver_define_extern(
IdentResolver* resolver, char* ident, Loc loc, size_t extern_id);
const IdentResol* ident_resolver_resolve( const IdentResol* ident_resolver_resolve(
const IdentResolver* resolver, const char* ident); const IdentResolver* resolver, const char* ident);

View File

@ -20,6 +20,7 @@ start:
int Int_DiskRead int Int_DiskRead
jmp other jmp other
jmp other
main_loop: main_loop:
hlt hlt