add consts

This commit is contained in:
sfja 2025-04-02 18:39:19 +02:00
parent d8c9336261
commit c351139f4d
7 changed files with 214 additions and 45 deletions

View File

@ -85,6 +85,9 @@ EvaledOperand eval_operand_to_imm(
case IdentResolTy_Label: case IdentResolTy_Label:
case IdentResolTy_SubLabel: case IdentResolTy_SubLabel:
return (EvaledOperand) { .ty = EoTy_Imm, .imm = re->ip }; return (EvaledOperand) { .ty = EoTy_Imm, .imm = re->ip };
case IdentResolTy_Const:
return (EvaledOperand) { .ty = EoTy_Imm, .imm = re->value };
break;
} }
fprintf(stderr, "unreachable\n"); fprintf(stderr, "unreachable\n");
exit(1); exit(1);

View File

@ -1,3 +1,4 @@
#include "asm/report.h"
#include "assemble.h" #include "assemble.h"
#include "eval.h" #include "eval.h"
#include "parse.h" #include "parse.h"
@ -91,6 +92,15 @@ int main(int argc, char** argv)
.text_len = parser.lexer.text_len, .text_len = parser.lexer.text_len,
}; };
IdentResolver resolver;
ident_resolver_construct(&resolver);
OperandEvaluator evaluator = {
.re = &resolver,
.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);
size_t lines_size = 0; size_t lines_size = 0;
@ -100,24 +110,47 @@ int main(int argc, char** argv)
lines_capacity += 2; lines_capacity += 2;
lines = realloc(lines, sizeof(PLine*) * lines_capacity); lines = realloc(lines, sizeof(PLine*) * lines_capacity);
} }
PLine* line = parser_next(&parser); PStmt* stmt = parser_next_stmt(&parser);
if (!line) { if (!stmt) {
continue; continue;
} }
lines[lines_size++] = line; switch (stmt->ty) {
case PStmtTy_Line:
lines[lines_size++] = stmt->line;
// NOTE: Shallow free.
free(stmt);
break;
case PStmtTy_Global:
pstmt_free(stmt);
break;
case PStmtTy_Extern:
pstmt_free(stmt);
break;
case PStmtTy_Const: {
const IdentResol* existing
= ident_resolver_resolve(&resolver, stmt->ident);
if (existing != NULL) {
REPORTF_ERROR("redefinition of constant '%s'", stmt->ident);
reporter_print_loc(&rep, stmt->loc);
pstmt_free(stmt);
continue;
}
EvaledOperand evaled
= eval_operand_to_imm(&evaluator, stmt->value);
if (evaled.ty == EoTy_Err) {
pstmt_free(stmt);
continue;
}
ident_resolver_define_const(
&resolver, asm_strdup(stmt->ident), stmt->loc, evaled.imm);
pstmt_free(stmt);
break;
}
}
} }
errors_occured &= parser_error_occured(&parser); errors_occured &= parser_error_occured(&parser);
IdentResolver resolver;
ident_resolver_construct(&resolver);
OperandEvaluator evaluator = {
.re = &resolver,
.rep = &rep,
.second_pass = false,
};
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);

View File

@ -126,6 +126,26 @@ void pline_free(PLine* pline)
free(pline); free(pline);
} }
PStmt* pstmt_new_line(Loc loc, PLine* line)
{
PStmt* stmt = malloc(sizeof(PStmt));
*stmt = (PStmt) { .ty = PStmtTy_Line, .loc = loc, .line = line };
return stmt;
}
PStmt* pstmt_new_ident(PStmtTy ty, Loc loc, char* ident)
{
PStmt* stmt = malloc(sizeof(PStmt));
*stmt = (PStmt) { .ty = ty, .loc = loc, .ident = ident, .value = NULL };
return stmt;
}
PStmt* pstmt_new_const(PStmtTy ty, Loc loc, char* ident, POperand* value)
{
PStmt* stmt = malloc(sizeof(PStmt));
*stmt = (PStmt) { .ty = ty, .loc = loc, .ident = ident, .value = value };
return stmt;
}
void pstmt_free(PStmt* stmt) void pstmt_free(PStmt* stmt)
{ {
switch (stmt->ty) { switch (stmt->ty) {
@ -134,9 +154,12 @@ void pstmt_free(PStmt* stmt)
break; break;
case PStmtTy_Global: case PStmtTy_Global:
case PStmtTy_Extern: case PStmtTy_Extern:
case PStmtTy_Define:
free(stmt->ident); free(stmt->ident);
break; break;
case PStmtTy_Const:
free(stmt->ident);
poperand_free(stmt->value);
break;
} }
free(stmt); free(stmt);
} }
@ -184,7 +207,7 @@ static inline bool parser_eat(Parser* parser, TokTy ty)
return false; return false;
} }
static inline char* parser_ident_val(const Parser* parser, Tok tok) static inline char* parser_text_val(const Parser* parser, Tok tok)
{ {
return asm_strndup(&parser->lexer.text[tok.loc.idx], tok.len); return asm_strndup(&parser->lexer.text[tok.loc.idx], tok.len);
} }
@ -218,7 +241,7 @@ static inline PLabel* parser_parse_labels(
plabel_free(labels); plabel_free(labels);
return NULL; return NULL;
} }
char* label_ident = parser_ident_val(parser, parser->eaten); char* label_ident = parser_text_val(parser, parser->eaten);
if (!parser_eat(parser, ':')) { if (!parser_eat(parser, ':')) {
parser_report(parser, "expected ':'", parser->tok.loc); parser_report(parser, "expected ':'", parser->tok.loc);
plabel_free(labels); plabel_free(labels);
@ -227,7 +250,7 @@ static inline PLabel* parser_parse_labels(
} }
labels = plabel_new(labels, label_ident, true, loc); labels = plabel_new(labels, label_ident, true, loc);
} else if (parser_eat(parser, TT_Ident)) { } else if (parser_eat(parser, TT_Ident)) {
*ident = parser_ident_val(parser, parser->eaten); *ident = parser_text_val(parser, parser->eaten);
*ident_loc = loc; *ident_loc = loc;
if (!parser_eat(parser, ':')) { if (!parser_eat(parser, ':')) {
break; break;
@ -269,7 +292,7 @@ static inline POperand* parser_parse_operand_0(Parser* parser)
{ {
Loc loc = parser->tok.loc; Loc loc = parser->tok.loc;
if (parser_eat(parser, TT_Ident)) { if (parser_eat(parser, TT_Ident)) {
char* ident = parser_ident_val(parser, parser->eaten); char* ident = parser_text_val(parser, parser->eaten);
const char* reg_key[10] = { const char* reg_key[10] = {
"r0", "r1", "r2", "r3", "r4", "rbp", "rsp", "rfl", "rcs", "rip" "r0", "r1", "r2", "r3", "r4", "rbp", "rsp", "rfl", "rcs", "rip"
}; };
@ -282,7 +305,7 @@ static inline POperand* parser_parse_operand_0(Parser* parser)
} }
return poperand_new_str(PoTy_Ident, ident, parser->eaten.len, loc); return poperand_new_str(PoTy_Ident, ident, parser->eaten.len, loc);
} else if (parser_eat(parser, TT_Int)) { } else if (parser_eat(parser, TT_Int)) {
char* str = parser_ident_val(parser, parser->eaten); char* str = parser_text_val(parser, parser->eaten);
uint64_t val = strtoull(str, NULL, 10); uint64_t val = strtoull(str, NULL, 10);
free(str); free(str);
if (val > 0xffff) { if (val > 0xffff) {
@ -294,7 +317,7 @@ static inline POperand* parser_parse_operand_0(Parser* parser)
uint16_t imm = (uint16_t)val; uint16_t imm = (uint16_t)val;
return poperand_new_imm(imm, loc); return poperand_new_imm(imm, loc);
} else if (parser_eat(parser, TT_Binary)) { } else if (parser_eat(parser, TT_Binary)) {
char* str = parser_ident_val(parser, parser->eaten); char* str = parser_text_val(parser, parser->eaten);
uint64_t val = strtoull(&str[2], NULL, 2); uint64_t val = strtoull(&str[2], NULL, 2);
free(str); free(str);
if (val > 0xffff) { if (val > 0xffff) {
@ -306,7 +329,7 @@ static inline POperand* parser_parse_operand_0(Parser* parser)
uint16_t imm = (uint16_t)val; uint16_t imm = (uint16_t)val;
return poperand_new_imm(imm, loc); return poperand_new_imm(imm, loc);
} else if (parser_eat(parser, TT_Hex)) { } else if (parser_eat(parser, TT_Hex)) {
char* str = parser_ident_val(parser, parser->eaten); char* str = parser_text_val(parser, parser->eaten);
uint64_t val = strtoull(&str[2], NULL, 16); uint64_t val = strtoull(&str[2], NULL, 16);
free(str); free(str);
if (val > 0xffff) { if (val > 0xffff) {
@ -318,12 +341,12 @@ static inline POperand* parser_parse_operand_0(Parser* parser)
uint16_t imm = (uint16_t)val; uint16_t imm = (uint16_t)val;
return poperand_new_imm(imm, loc); return poperand_new_imm(imm, loc);
} else if (parser_eat(parser, TT_Char)) { } else if (parser_eat(parser, TT_Char)) {
char* str = parser_ident_val(parser, parser->eaten); char* str = parser_text_val(parser, parser->eaten);
uint16_t imm = (uint16_t)literal_char_val(&str[1]); uint16_t imm = (uint16_t)literal_char_val(&str[1]);
free(str); free(str);
return poperand_new_imm(imm, loc); return poperand_new_imm(imm, loc);
} else if (parser_eat(parser, TT_Str)) { } else if (parser_eat(parser, TT_Str)) {
char* lit = parser_ident_val(parser, parser->eaten); char* lit = parser_text_val(parser, parser->eaten);
size_t lit_len = strlen(lit); size_t lit_len = strlen(lit);
char* str = calloc(lit_len - 1, sizeof(char)); char* str = calloc(lit_len - 1, sizeof(char));
size_t str_len = 0; size_t str_len = 0;
@ -337,7 +360,7 @@ static inline POperand* parser_parse_operand_0(Parser* parser)
parser_report(parser, "expected identifier", parser->tok.loc); parser_report(parser, "expected identifier", parser->tok.loc);
return NULL; return NULL;
} }
char* ident = parser_ident_val(parser, parser->eaten); char* ident = parser_text_val(parser, parser->eaten);
return poperand_new_str(PoTy_SubLabel, ident, parser->eaten.len, loc); return poperand_new_str(PoTy_SubLabel, ident, parser->eaten.len, loc);
} else if (parser_eat(parser, '(')) { } else if (parser_eat(parser, '(')) {
POperand* operand = parser_parse_operand_2(parser, parser_binary_prec); POperand* operand = parser_parse_operand_2(parser, parser_binary_prec);
@ -431,7 +454,7 @@ static inline POperand* parser_parse_operand_3(Parser* parser)
if (!parser_test(parser, TT_Ident)) { if (!parser_test(parser, TT_Ident)) {
return parser_parse_operand_2(parser, parser_binary_prec); return parser_parse_operand_2(parser, parser_binary_prec);
} }
char* ident = parser_ident_val(parser, parser->tok); char* ident = parser_text_val(parser, parser->tok);
if (strcmp(ident, "u8") == 0) { if (strcmp(ident, "u8") == 0) {
free(ident); free(ident);
parser_step(parser); parser_step(parser);
@ -473,15 +496,14 @@ static inline void parser_skip_to_next_line(Parser* parser)
} }
} }
PLine* parser_next(Parser* parser) PLine* parser_next_line(Parser* parser)
{ {
char* ident; char* ident;
Loc loc; Loc loc;
PLabel* labels = parser_parse_labels(parser, &ident, &loc); PLabel* labels = parser_parse_labels(parser, &ident, &loc);
const size_t max_ops_size = 64; const size_t max_ops_size = 64;
// TODO: Move allocation out-of-band. POperand* ops[64];
POperand** ops = malloc(sizeof(POperand) * max_ops_size);
size_t ops_size = 0; size_t ops_size = 0;
if (!parser_test(parser, TT_Eof) && !parser_test(parser, '\n')) { if (!parser_test(parser, TT_Eof) && !parser_test(parser, '\n')) {
@ -520,15 +542,77 @@ PLine* parser_next(Parser* parser)
parser_skip_newlines(parser); parser_skip_newlines(parser);
PLine* line = pline_new(ident, labels, loc, ops_size, ops); PLine* line = pline_new(ident, labels, loc, ops_size, ops);
free(ops);
return line; return line;
error_free_ops: error_free_ops:
for (size_t i = 0; i < ops_size; ++i) for (size_t i = 0; i < ops_size; ++i)
if (ops[i]) if (ops[i])
poperand_free(ops[i]); poperand_free(ops[i]);
free(ops);
plabel_free(labels); plabel_free(labels);
free(ident); free(ident);
return NULL; return NULL;
} }
static inline PStmtTy pstmt_keyword_ty(const char* ident)
{
const PStmtTy tys[] = {
PStmtTy_Global,
PStmtTy_Extern,
PStmtTy_Const,
};
const char* keywords[] = {
"global",
"extern",
"const",
};
static_assert(
sizeof(keywords) / sizeof(keywords[0]) == sizeof(tys) / sizeof(tys[0]),
"mismatch");
size_t amount = sizeof(tys) / sizeof(tys[0]);
for (size_t i = 0; i < amount; ++i) {
if (strcmp(ident, keywords[i]) == 0) {
return tys[i];
}
}
return PStmtTy_Line;
}
PStmt* parser_next_stmt(Parser* parser)
{
parser_skip_newlines(parser);
Loc loc = parser->tok.loc;
if (!parser_test(parser, TT_Ident)) {
PLine* line = parser_next_line(parser);
if (!line)
return NULL;
return pstmt_new_line(loc, line);
}
char* keyword = parser_text_val(parser, parser->tok);
PStmtTy ty = pstmt_keyword_ty(keyword);
free(keyword);
switch (ty) {
case PStmtTy_Global:
case PStmtTy_Extern:
case PStmtTy_Const: {
parser_step(parser);
if (!parser_eat(parser, TT_Ident)) {
parser_report(parser, "expected identifier", parser->tok.loc);
return NULL;
}
char* ident = parser_text_val(parser, parser->eaten);
if (ty != PStmtTy_Const) {
return pstmt_new_ident(ty, loc, ident);
}
POperand* value = parser_parse_operand_3(parser);
return pstmt_new_const(ty, loc, ident, value);
break;
}
default:
break;
}
PLine* line = parser_next_line(parser);
if (!line)
return NULL;
return pstmt_new_line(loc, line);
}

View File

@ -84,17 +84,24 @@ typedef enum {
PStmtTy_Line, PStmtTy_Line,
PStmtTy_Global, PStmtTy_Global,
PStmtTy_Extern, PStmtTy_Extern,
PStmtTy_Define, PStmtTy_Const,
} PStmtTy; } PStmtTy;
typedef struct { typedef struct {
PStmtTy ty; PStmtTy ty;
Loc loc;
union { union {
PLine* line; PLine* line;
struct {
char* ident; char* ident;
POperand* value;
};
}; };
} PStmt; } PStmt;
PStmt* pstmt_new_line(Loc loc, PLine* line);
PStmt* pstmt_new_ident(PStmtTy ty, Loc loc, char* ident);
PStmt* pstmt_new_const(PStmtTy ty, Loc loc, char* ident, POperand* value);
void pstmt_free(PStmt* stmt); void pstmt_free(PStmt* stmt);
typedef struct { typedef struct {
@ -107,4 +114,5 @@ typedef struct {
void parser_construct(Parser* parser, const char* filename, const char* text); void parser_construct(Parser* parser, const char* filename, const char* text);
bool parser_done(const Parser* parser); bool parser_done(const Parser* parser);
bool parser_error_occured(const Parser* parser); bool parser_error_occured(const Parser* parser);
PLine* parser_next(Parser* parser); PLine* parser_next_line(Parser* parser);
PStmt* parser_next_stmt(Parser* parser);

View File

@ -9,6 +9,7 @@ void ident_resol_destroy(IdentResol* resol)
break; break;
case IdentResolTy_Label: case IdentResolTy_Label:
case IdentResolTy_SubLabel: case IdentResolTy_SubLabel:
case IdentResolTy_Const:
free(resol->ident); free(resol->ident);
break; break;
} }
@ -77,6 +78,18 @@ void ident_resolver_define_sublabel(
}; };
} }
void ident_resolver_define_const(
IdentResolver* resolver, char* ident, Loc loc, uint16_t value)
{
size_t i = ident_resolver_first_empty(resolver);
resolver->resols[i] = (IdentResol) {
.ident = ident,
.loc = loc,
.ty = IdentResolTy_Const,
.value = value,
};
}
const IdentResol* ident_resolver_resolve( const IdentResol* ident_resolver_resolve(
const IdentResolver* resolver, const char* ident) const IdentResolver* resolver, const char* ident)
{ {

View File

@ -7,6 +7,7 @@ typedef enum {
IdentResolTy_None, IdentResolTy_None,
IdentResolTy_Label, IdentResolTy_Label,
IdentResolTy_SubLabel, IdentResolTy_SubLabel,
IdentResolTy_Const,
} IdentResolTy; } IdentResolTy;
typedef struct IdentResol IdentResol; typedef struct IdentResol IdentResol;
@ -17,6 +18,7 @@ struct IdentResol {
IdentResolTy ty; IdentResolTy ty;
union { union {
uint16_t ip; uint16_t ip;
uint16_t value;
}; };
}; };
@ -36,5 +38,7 @@ void ident_resolver_define_label(
IdentResolver* resolver, char* ident, Loc loc, uint16_t asm_ip); IdentResolver* resolver, char* ident, Loc loc, uint16_t asm_ip);
void ident_resolver_define_sublabel( void ident_resolver_define_sublabel(
IdentResolver* resolver, char* ident, Loc loc, uint16_t asm_ip); IdentResolver* resolver, char* ident, Loc loc, uint16_t asm_ip);
void ident_resolver_define_const(
IdentResolver* resolver, char* ident, Loc loc, uint16_t value);
const IdentResol* ident_resolver_resolve( const IdentResol* ident_resolver_resolve(
const IdentResolver* resolver, const char* ident); const IdentResolver* resolver, const char* ident);

View File

@ -1,17 +1,41 @@
const Fl_Zero 0
const Fl_Eq 1
const Fl_Be 2
const Fl_Lt 3
const Fl_Err 4
const Fl_Int 5
const Fl_Vcd 6
const Int_DiskRead 0
const Int_DiskWrite 1
const Int_Key 32
const Device_Keyboard 0
const vcd_ch_width 8
const vcd_ch_height 8
const vcd_width_in_ch 40
const vcd_height_in_ch 12
const vcd_px_width 4
const vcd_px_height 8
const vcd_width_in_px vcd_width_in_ch * vcd_ch_width * vcd_px_width
const vcd_height_in_px vcd_height_in_ch * vcd_ch_height * vcd_px_height
start: start:
; rsp points *at* the top element ; rsp points *at* the top element
mov rbp, 2048 mov rbp, 2048
mov rsp, 2048 - 2 mov rsp, 2048 - 2
lit interrupt_table lit interrupt_table
or rfl, rfl, 1 << 5 ; Fl_Int or rfl, rfl, 1 << Fl_Int
or rfl, rfl, 1 << 6 ; Fl_Vcd or rfl, rfl, 1 << Fl_Vcd
mov r0, 512 mov r0, 512
mov r1, 1 mov r1, 1
int 0 ; Int_DiskRead int Int_DiskRead
main_loop: main_loop:
hlt hlt
@ -24,7 +48,7 @@ interrupt_table:
nop nop
keyboard_interrupt: keyboard_interrupt:
and rfl, rfl, !(1 << 5) ; Fl_Int and rfl, rfl, !(1 << Fl_Int)
push rbp push rbp
mov rbp, rsp mov rbp, rsp
push r0 push r0
@ -32,21 +56,21 @@ keyboard_interrupt:
push r2 push r2
push r3 push r3
in r0, 0 ; Device_Keyboard in r0, Device_Keyboard
cmp r0, 44 cmp r0, 44
mov r1, rfl mov r1, rfl
and r1, r1, 1 << 1 ; Fl_Eq and r1, r1, 1 << Fl_Eq
jnz r1, .L0 jnz r1, .L0
cmp r0, 42 cmp r0, 42
mov r1, rfl mov r1, rfl
and r1, r1, 1 << 1 ; Fl_Eq and r1, r1, 1 << Fl_Eq
jnz r1, .L1 jnz r1, .L1
cmp r0, 40 cmp r0, 40
mov r1, rfl mov r1, rfl
and r1, r1, 1 << 1 ; Fl_Eq and r1, r1, 1 << Fl_Eq
jnz r1, .L2 jnz r1, .L2
jmp .L3 jmp .L3
@ -60,7 +84,7 @@ keyboard_interrupt:
mov r1, u16 [screen_x] mov r1, u16 [screen_x]
cmp r1, 0 cmp r1, 0
mov r2, rfl mov r2, rfl
and r2, r2, 1 << 1 ; Fl_Eq and r2, r2, 1 << Fl_Eq
jnz r2, .L4 jnz r2, .L4
sub r1, r1, 1 sub r1, r1, 1
mov u16 [screen_x], r1 mov u16 [screen_x], r1
@ -92,7 +116,7 @@ keyboard_interrupt:
pop r0 pop r0
mov rsp, rbp mov rsp, rbp
pop rbp pop rbp
or rfl, rfl, 1 << 5 ; Fl_Int or rfl, rfl, 1 << Fl_Int
iret iret
put_char: put_char:
@ -102,7 +126,7 @@ put_char:
push r2 push r2
mov r2, u16 [screen_y] mov r2, u16 [screen_y]
mul r2, r2, 40 ; vcd_width_in_ch mul r2, r2, vcd_width_in_ch
mov r1, u16 [screen_x] mov r1, u16 [screen_x]
add r1, r1, 0x0c00 add r1, r1, 0x0c00
add r1, r1, r2 add r1, r1, r2
@ -112,9 +136,9 @@ put_char:
add r1, r1, 1 add r1, r1, 1
mov u16 [screen_x], r1 mov u16 [screen_x], r1
cmp r1, 40 ; vcd_width_in_ch cmp r1, vcd_width_in_ch
mov r2, rfl mov r2, rfl
and r2, r2, 1 << 1 ; Fl_Eq and r2, r2, 1 << Fl_Eq
jnz r2, .L0 jnz r2, .L0
jmp .L1 jmp .L1