From 0b65a5841f6078c7d013f10e96d351ac54495bd9 Mon Sep 17 00:00:00 2001 From: SimonFJ20 Date: Wed, 26 Mar 2025 12:57:22 +0100 Subject: [PATCH] compiler: loops work --- backup-compiler/asm_gen.ts | 5 +++-- backup-compiler/lib.c | 6 ++++++ backup-compiler/lir.ts | 10 +++++----- backup-compiler/lir_gen.ts | 6 +++--- backup-compiler/lir_optimize.ts | 7 +++++++ backup-compiler/mir_gen.ts | 11 ++++++----- backup-compiler/program.sbl | 17 ++++++++++++++--- 7 files changed, 44 insertions(+), 18 deletions(-) diff --git a/backup-compiler/asm_gen.ts b/backup-compiler/asm_gen.ts index fde8979..051fbb3 100644 --- a/backup-compiler/asm_gen.ts +++ b/backup-compiler/asm_gen.ts @@ -163,14 +163,15 @@ export class AsmGen { this.writeIns(`jmp .L${ins.target}`); return; case "jnz_reg": - this.writeIns(`jnz ${r(ins.reg)}, .L${ins.target}`); + this.writeIns(`cmp ${r(ins.reg)}, 0`); + this.writeIns(`jne .L${ins.target}`); return; case "ret": this.writeIns(`jmp .exit`); return; case "lt": this.writeIns(`cmp ${r(ins.dst)}, ${r(ins.src)}`); - this.writeIns(`setle ${this.reg8(ins.dst)}`); + this.writeIns(`setl ${this.reg8(ins.dst)}`); return; case "eq": this.writeIns(`cmp ${r(ins.dst)}, ${r(ins.src)}`); diff --git a/backup-compiler/lib.c b/backup-compiler/lib.c index 5262dda..322264d 100644 --- a/backup-compiler/lib.c +++ b/backup-compiler/lib.c @@ -1,6 +1,12 @@ #include #include +int64_t notice(void) +{ + printf("NOTICE!\n"); + return 0; +} + int64_t print_int(int64_t value) { printf("%ld\n", value); diff --git a/backup-compiler/lir.ts b/backup-compiler/lir.ts index 0f447b4..d2021b2 100644 --- a/backup-compiler/lir.ts +++ b/backup-compiler/lir.ts @@ -81,19 +81,19 @@ export class ProgramStringifyer { case "pop": return `pop %${ins.reg}`; case "load": - return `load %${ins.reg}, ${ins.offset}`; + return `load %${ins.reg}, [${ins.offset}]`; case "store_reg": - return `store_reg ${ins.offset}, %${ins.reg}`; + return `store_reg [${ins.offset}], %${ins.reg}`; case "store_imm": - return `store_val ${ins.offset}, ${ins.val}`; + return `store_val [${ins.offset}], ${ins.val}`; case "call_reg": return `call_reg %${ins.reg}, ${ins.args}`; case "call_imm": return `call_fn ${ins.fn.label}, ${ins.args}`; case "jmp": - return `jmp .b${ins.target}`; + return `jmp .L${ins.target}`; case "jnz_reg": - return `jmp %${ins.reg}, .b${ins.target}`; + return `jnz_reg %${ins.reg}, .L${ins.target}`; case "ret": return "ret"; case "lt": diff --git a/backup-compiler/lir_gen.ts b/backup-compiler/lir_gen.ts index a05cdf8..65558e7 100644 --- a/backup-compiler/lir_gen.ts +++ b/backup-compiler/lir_gen.ts @@ -204,10 +204,10 @@ class FnGen { case "eq": case "add": case "mul": { - const dst = this.reg(); const src = this.reg(); - this.pushIns({ tag: "pop", reg: dst }); + const dst = this.reg(); this.pushIns({ tag: "pop", reg: src }); + this.pushIns({ tag: "pop", reg: dst }); this.pushIns({ tag: k.tag, dst, src }); this.pushIns({ tag: "push", reg: dst }); this.pushIns({ tag: "kill", reg: src }); @@ -242,7 +242,7 @@ class FnGen { this.pushIns({ tag: "jnz_reg", reg, - target: this.blockLabels.get(k.falsy.id)!, + target: this.blockLabels.get(k.truthy.id)!, }); this.pushIns({ tag: "kill", reg }); this.pushIns({ diff --git a/backup-compiler/lir_optimize.ts b/backup-compiler/lir_optimize.ts index 7c0092e..da8ecf9 100644 --- a/backup-compiler/lir_optimize.ts +++ b/backup-compiler/lir_optimize.ts @@ -186,6 +186,13 @@ function eliminatePushPopShadowed(fn: Fn) { const toRemove = pop.ins.reg; const replacement = push.ins.reg; fn.lines.splice(popIdx, 1); + for (let i = pushIdx + 1; i <= popIdx - 1; ++i) { + const kill = fn.lines[i].ins; + if (kill.tag === "kill" && kill.reg === push.ins.reg) { + fn.lines.splice(i, 1); + break; + } + } fn.lines.splice(pushIdx, 1); replaceReg(fn, toRemove, replacement); } diff --git a/backup-compiler/mir_gen.ts b/backup-compiler/mir_gen.ts index ce30931..33a7d9e 100644 --- a/backup-compiler/mir_gen.ts +++ b/backup-compiler/mir_gen.ts @@ -97,13 +97,13 @@ export class FnMirGen { const exit = this.block(); const loop = this.block(); + entry.ter = Ter({ tag: "goto", target: loop }); + this.loopExitBlocks.set(stmt.id, exit); this.currentBlock = loop; this.lowerBlock(k.body); - - entry.ter = Ter({ tag: "goto", target: loop }); - loop.ter = Ter({ tag: "goto", target: exit }); + this.currentBlock.ter = Ter({ tag: "goto", target: loop }); this.currentBlock = exit; return; @@ -116,17 +116,18 @@ export class FnMirGen { this.currentBlock = truthy; this.lowerBlock(k.truthy); - truthy.ter = Ter({ tag: "goto", target: exit }); + this.currentBlock.ter = Ter({ tag: "goto", target: exit }); let falsy = exit; if (k.falsy) { falsy = this.block(); this.currentBlock = falsy; this.lowerBlock(k.falsy); - falsy.ter = Ter({ tag: "goto", target: exit }); + this.currentBlock.ter = Ter({ tag: "goto", target: exit }); } entry.ter = Ter({ tag: "if", truthy, falsy }); + this.currentBlock = exit; return; } case "return": { diff --git a/backup-compiler/program.sbl b/backup-compiler/program.sbl index 1c526a5..d1b34e0 100644 --- a/backup-compiler/program.sbl +++ b/backup-compiler/program.sbl @@ -1,4 +1,7 @@ +#[c_function("notice")] +fn notice() {} + #[c_function("print_int")] fn print_int(value) {} @@ -8,9 +11,17 @@ fn inner(value) { } fn main() { - let a = 4; - inner(a + 2); - return a; + let i = 0; + loop { + if 10 < i + 1 { + break; + } + let a = 4; + inner(a + 2); + + i = i + 1; + } + return i; } // vim: syntax=rust commentstring=//\ %s