compiler: loops work

This commit is contained in:
SimonFJ20 2025-03-26 12:57:22 +01:00
parent 2dfd713e4e
commit 0b65a5841f
7 changed files with 44 additions and 18 deletions

View File

@ -163,14 +163,15 @@ export class AsmGen {
this.writeIns(`jmp .L${ins.target}`); this.writeIns(`jmp .L${ins.target}`);
return; return;
case "jnz_reg": 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; return;
case "ret": case "ret":
this.writeIns(`jmp .exit`); this.writeIns(`jmp .exit`);
return; return;
case "lt": case "lt":
this.writeIns(`cmp ${r(ins.dst)}, ${r(ins.src)}`); this.writeIns(`cmp ${r(ins.dst)}, ${r(ins.src)}`);
this.writeIns(`setle ${this.reg8(ins.dst)}`); this.writeIns(`setl ${this.reg8(ins.dst)}`);
return; return;
case "eq": case "eq":
this.writeIns(`cmp ${r(ins.dst)}, ${r(ins.src)}`); this.writeIns(`cmp ${r(ins.dst)}, ${r(ins.src)}`);

View File

@ -1,6 +1,12 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
int64_t notice(void)
{
printf("NOTICE!\n");
return 0;
}
int64_t print_int(int64_t value) int64_t print_int(int64_t value)
{ {
printf("%ld\n", value); printf("%ld\n", value);

View File

@ -81,19 +81,19 @@ export class ProgramStringifyer {
case "pop": case "pop":
return `pop %${ins.reg}`; return `pop %${ins.reg}`;
case "load": case "load":
return `load %${ins.reg}, ${ins.offset}`; return `load %${ins.reg}, [${ins.offset}]`;
case "store_reg": case "store_reg":
return `store_reg ${ins.offset}, %${ins.reg}`; return `store_reg [${ins.offset}], %${ins.reg}`;
case "store_imm": case "store_imm":
return `store_val ${ins.offset}, ${ins.val}`; return `store_val [${ins.offset}], ${ins.val}`;
case "call_reg": case "call_reg":
return `call_reg %${ins.reg}, ${ins.args}`; return `call_reg %${ins.reg}, ${ins.args}`;
case "call_imm": case "call_imm":
return `call_fn ${ins.fn.label}, ${ins.args}`; return `call_fn ${ins.fn.label}, ${ins.args}`;
case "jmp": case "jmp":
return `jmp .b${ins.target}`; return `jmp .L${ins.target}`;
case "jnz_reg": case "jnz_reg":
return `jmp %${ins.reg}, .b${ins.target}`; return `jnz_reg %${ins.reg}, .L${ins.target}`;
case "ret": case "ret":
return "ret"; return "ret";
case "lt": case "lt":

View File

@ -204,10 +204,10 @@ class FnGen {
case "eq": case "eq":
case "add": case "add":
case "mul": { case "mul": {
const dst = this.reg();
const src = 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: src });
this.pushIns({ tag: "pop", reg: dst });
this.pushIns({ tag: k.tag, dst, src }); this.pushIns({ tag: k.tag, dst, src });
this.pushIns({ tag: "push", reg: dst }); this.pushIns({ tag: "push", reg: dst });
this.pushIns({ tag: "kill", reg: src }); this.pushIns({ tag: "kill", reg: src });
@ -242,7 +242,7 @@ class FnGen {
this.pushIns({ this.pushIns({
tag: "jnz_reg", tag: "jnz_reg",
reg, reg,
target: this.blockLabels.get(k.falsy.id)!, target: this.blockLabels.get(k.truthy.id)!,
}); });
this.pushIns({ tag: "kill", reg }); this.pushIns({ tag: "kill", reg });
this.pushIns({ this.pushIns({

View File

@ -186,6 +186,13 @@ function eliminatePushPopShadowed(fn: Fn) {
const toRemove = pop.ins.reg; const toRemove = pop.ins.reg;
const replacement = push.ins.reg; const replacement = push.ins.reg;
fn.lines.splice(popIdx, 1); 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); fn.lines.splice(pushIdx, 1);
replaceReg(fn, toRemove, replacement); replaceReg(fn, toRemove, replacement);
} }

View File

@ -97,13 +97,13 @@ export class FnMirGen {
const exit = this.block(); const exit = this.block();
const loop = this.block(); const loop = this.block();
entry.ter = Ter({ tag: "goto", target: loop });
this.loopExitBlocks.set(stmt.id, exit); this.loopExitBlocks.set(stmt.id, exit);
this.currentBlock = loop; this.currentBlock = loop;
this.lowerBlock(k.body); this.lowerBlock(k.body);
this.currentBlock.ter = Ter({ tag: "goto", target: loop });
entry.ter = Ter({ tag: "goto", target: loop });
loop.ter = Ter({ tag: "goto", target: exit });
this.currentBlock = exit; this.currentBlock = exit;
return; return;
@ -116,17 +116,18 @@ export class FnMirGen {
this.currentBlock = truthy; this.currentBlock = truthy;
this.lowerBlock(k.truthy); this.lowerBlock(k.truthy);
truthy.ter = Ter({ tag: "goto", target: exit }); this.currentBlock.ter = Ter({ tag: "goto", target: exit });
let falsy = exit; let falsy = exit;
if (k.falsy) { if (k.falsy) {
falsy = this.block(); falsy = this.block();
this.currentBlock = falsy; this.currentBlock = falsy;
this.lowerBlock(k.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 }); entry.ter = Ter({ tag: "if", truthy, falsy });
this.currentBlock = exit;
return; return;
} }
case "return": { case "return": {

View File

@ -1,4 +1,7 @@
#[c_function("notice")]
fn notice() {}
#[c_function("print_int")] #[c_function("print_int")]
fn print_int(value) {} fn print_int(value) {}
@ -8,9 +11,17 @@ fn inner(value) {
} }
fn main() { fn main() {
let a = 4; let i = 0;
inner(a + 2); loop {
return a; if 10 < i + 1 {
break;
}
let a = 4;
inner(a + 2);
i = i + 1;
}
return i;
} }
// vim: syntax=rust commentstring=//\ %s // vim: syntax=rust commentstring=//\ %s