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}`);
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)}`);

View File

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

View File

@ -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":

View File

@ -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({

View File

@ -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);
}

View File

@ -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": {

View File

@ -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 i = 0;
loop {
if 10 < i + 1 {
break;
}
let a = 4;
inner(a + 2);
return a;
i = i + 1;
}
return i;
}
// vim: syntax=rust commentstring=//\ %s