compiler

Unnamed Compiled Systems Language Project
git clone http://frotz.net/git/compiler.git
Log | Files | Refs

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:
Msrc/codegen-risc5-simple.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/compiler2.c | 76+++++++++++++++++++++++++++++++++++++++++++++-------------------------------
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);