commit 21984842672b546b40015dbe443e24de4e2e44c9
parent 9eb42807448acfbed5c88c8d121984560c87e30b
Author: Brian Swetland <swetland@frotz.net>
Date: Mon, 6 Dec 2021 01:08:09 -0800
compiler2: fixing bugs
- track last function ast node and error-relevant ast node and dump
the ast subtree relevent to errors when generating code
- fix up if/else/elseif ast generation
- fix up if/else/elseif code generation
Diffstat:
2 files changed, 98 insertions(+), 39 deletions(-)
diff --git a/src/codegen-risc5-simple.c b/src/codegen-risc5-simple.c
@@ -209,6 +209,17 @@ void gen_trace(str msg) {
void gen_block(Ast node);
u32 gen_expr(Ast node);
+Ast err_last_func = nil;
+Ast err_ast = nil;
+
+void dump_error_ctxt() {
+ fprintf(stderr, "\n");
+ if (err_last_func) {
+ ast_dump(err_last_func, err_ast);
+ }
+ fprintf(stderr, "\n");
+}
+
void sym_get_loc(Symbol sym, u32* base, i32* offset) {
if (sym->kind == SYM_LOCAL) {
*base = FP;
@@ -246,6 +257,7 @@ u32 gen_call(Ast node) {
emit_mem(STW, r, R11, 0x100 + sym->value * 4);
put_reg(r);
} else if (sym->type->len > 0) {
+ // XXX: must save regs
emit_opi(SUB, SP, SP, 4 * sym->type->len);
u32 n = 0;
while (arg != nil) {
@@ -257,12 +269,17 @@ u32 gen_call(Ast node) {
}
gen_branch_sym(AL|L, sym);
emit_opi(ADD, SP, SP, 4 * sym->type->len);
+ // XXX: must restore regs
} else {
// no args
gen_branch_sym(AL|L, sym);
}
// return is in r0, if it exists
- return 0;
+ // stash it somewhere where it won't get stomped
+ // by other calls in this expr
+ u32 r = get_reg_tmp();
+ emit_mov(r, R0);
+ return r;
}
u32 gen_lexpr(Ast node) {
@@ -295,6 +312,7 @@ u32 gen_relop(Ast node, u32 cc) {
}
u32 gen_expr(Ast node) {
+ err_ast = node;
gen_trace("gen_expr()\n");
if (node->kind == AST_U32) {
u32 r = get_reg_tmp();
@@ -342,7 +360,6 @@ u32 gen_expr(Ast node) {
error("gen_expr cannot handle unop %s\n", tnames[op]);
}
return r;
- error("sorry no unops");
} else if (node->kind == AST_CALL) {
return gen_call(node);
} else {
@@ -380,18 +397,42 @@ void gen_while(Ast node) {
}
void gen_if_else(Ast node) {
- gen_expr(node->c0);
- Ast ifthen = node->c1;
- Ast ifelse = node->c2;
- gen_block(ifthen);
- if (ifelse != nil) {
- gen_block(ifelse);
+ // compute if expr
+ // branch ahead if false;
+ u32 r = gen_expr(node->c0);
+ emit_mov(R11, r); // set z flag;
+ put_reg(r);
+ u32 l0_br_false = ctx.pc;
+ emit_bi(EQ, 0);
+
+ // exec then block
+ gen_block(node->c1);
+
+ node = node->c2;
+ while (node != nil) {
+ fixup_branch_fwd(l0_br_false);
+
+ if (node->kind == AST_IF) { // ifelse ...
+ r = gen_expr(node->c0);
+ emit_mov(R11, r); // set z flag
+ put_reg(r);
+ l0_br_false = ctx.pc;
+ emit_bi(EQ, 0);
+ gen_block(node->c1);
+ node = node->c2;
+ } else { // else ...
+ gen_block(node);
+ return;
+ }
}
+
+ fixup_branch_fwd(l0_br_false);
}
void gen_block(Ast node);
void gen_stmt(Ast node) {
+ err_ast = node;
gen_trace("gen_stmt()\n");
u32 kind = node->kind;
if (kind == AST_EXPR) {
@@ -455,6 +496,8 @@ void gen_block(Ast node) {
// SP -> locn
void gen_func(Ast node) {
+ err_last_func = node;
+ err_ast = node;
gen_trace("gen_func()\n");
// local space plus saved lr and fp
@@ -505,6 +548,8 @@ void gen_risc5_simple(Ast node) {
node = node->c2;
}
+ err_last_func = nil;
+
Symbol sym = symbol_find(string_make("start", 5));
if (sym == nil) {
error("no 'start' function\n");
diff --git a/src/compiler2.c b/src/compiler2.c
@@ -574,6 +574,7 @@ void ctx_init() {
}
void dump_file_line(const char* fn, u32 offset);
+void dump_error_ctxt();
#if C
void error(const char *fmt, ...)
@@ -593,6 +594,8 @@ void error(const char *fmt)
}
fprintf(stderr, "\n");
+ dump_error_ctxt();
+
if (ctx.flags & cfAbortOnError) {
abort();
} else {
@@ -1326,45 +1329,36 @@ Ast parse_while() {
}
Ast parse_if() {
- // Scope outer = scope_push(SCOPE_BLOCK, nil);
- Ast expr = parse_expr();
+ // if expr { block }
+ Ast ifnode = ast_make_simple(AST_IF, 0);
+ ifnode->c0 = parse_expr();
require(tOBRACE);
scope_push(SCOPE_BLOCK, nil);
- Ast block = parse_block();
- block->sym = scope_pop();
- Ast ifnode = ast_make_simple(AST_IF, 0);
- ifnode->c0 = expr;
- ifnode->c1 = block;
- Ast last = block;
+ ifnode->c1 = parse_block();
+ ifnode->c1->sym = scope_pop();
while (ctx.tok == tELSE) {
next();
+ // ... else ...
if (ctx.tok == tIF) {
+ // ... if expr { block }
next();
- Ast expr = parse_expr();
-
- // generate "if else" code
+ Ast ifelse = ast_make_simple(AST_IF, 0);
+ ifelse->c0 = parse_expr();
require(tOBRACE);
scope_push(SCOPE_BLOCK, nil);
- Ast block = parse_block();
- block->sym = scope_pop();
-
- last->c2 = expr;
- expr->c2 = block;
- last = block;
+ ifelse->c1 = parse_block();
+ ifelse->c1->sym = scope_pop();
+ ifnode->c2 = ifelse;
+ ifnode = ifelse;
} else {
- // generate "else" code
+ // ... { block }
require(tOBRACE);
scope_push(SCOPE_BLOCK, nil);
- Ast block = parse_block();
- block->sym = scope_pop();
- last->c2 = block;
- last = block;
+ ifnode->c2 = parse_block();
+ ifnode->c2->sym = scope_pop();
break;
}
}
-
- // close outer scope
- // scope_pop();
return ifnode;
}
@@ -1848,9 +1842,15 @@ void ast_dump_rtype(Symbol sym, u32 indent) {
printf("\n");
}
-void ast_dump(Ast node, u32 indent, bool dumplist) {
+int _ast_dump(Ast node, u32 indent, bool dumplist, Ast mark) {
u32 i = 0;
- while (i < indent) { printf(" "); i++; }
+ i32 r = 0;
+
+ if (mark == node) {
+ while (i < indent) { printf(">>"); i++; }
+ } else {
+ while (i < indent) { printf(" "); i++; }
+ }
indent = indent + 1;
printf("%s ", ast_kind[node->kind]);
@@ -1888,19 +1888,33 @@ void ast_dump(Ast node, u32 indent, bool dumplist) {
if (node->kind == AST_BLOCK) {
ast_dump_syms(node->sym, "Local", indent);
}
+ if (mark == node) {
+ return 1;
+ }
if (node->c0 != nil) {
- ast_dump(node->c0, indent, true);
+ if (_ast_dump(node->c0, indent, true, mark)) {
+ return 1;
+ }
}
if (node->c1 != nil) {
- ast_dump(node->c1, indent, true);
+ if (_ast_dump(node->c1, indent, true, mark)) {
+ return 1;
+ }
}
if (dumplist) {
node = node->c2;
while (node != nil) {
- ast_dump(node, indent, false);
+ if (_ast_dump(node, indent, false, mark)) {
+ return 1;
+ }
node = node->c2;
}
}
+ return 0;
+}
+
+void ast_dump(Ast node, Ast mark) {
+ _ast_dump(node, 0, true, mark);
}
#include "codegen-risc5-simple.c"
@@ -2083,7 +2097,7 @@ i32 main(int argc, args argv) {
Ast a = parse_program();
if (astdump) {
- ast_dump(a, 0, true);
+ ast_dump(a, nil);
}
gen_risc5_simple(a);