compiler: fix pop parameters

This commit is contained in:
SimonFJ20 2025-03-27 14:56:59 +01:00
parent d5541c46fa
commit 827e26577a
6 changed files with 77 additions and 30 deletions

View File

@ -168,7 +168,7 @@ export class AsmGen {
this.writeIns(`push rbp`);
this.writeIns(`mov rbp, rsp`);
this.writeIns(`sub rsp, ${this.layout.frameSize}`);
this.writeIns(`sub rsp, ${this.layout.frameSize - 8}`);
this.writeIns(`jmp .L${fn.mir.entry.id}`);
for (const line of fn.lines.slice(bodyIdx)) {
@ -422,6 +422,7 @@ class StackAllocator {
currentOffset -= 8;
// caller rbp
currentOffset -= 8;
frameSize += 8;
for (const [reg, size] of this.localRegs) {
regOffsets.set(reg, currentOffset);

View File

@ -12,6 +12,10 @@ import * as ast from "./ast.ts";
import * as mir from "./mir.ts";
import { optimizeMirFn } from "./mir_optimize.ts";
export type LirGenOpts = {
optimize?: boolean;
};
export class LirGen {
private strings = new StringIntern();
@ -22,6 +26,7 @@ export class LirGen {
public constructor(
private ast: ast.Stmt[],
private mirGen: MirGen,
private opts: LirGenOpts = {},
) {}
public generate(): Program {
@ -30,7 +35,9 @@ export class LirGen {
throw new Error("only functions can compile top level");
}
const mir = this.mirGen.fnMir(stmt, stmt.kind);
optimizeMirFn(mir);
if (this.opts.optimize !== false) {
optimizeMirFn(mir);
}
const id = this.fnIds++;
const label = `sbc__${stmt.kind.ident}`;
const fn: Fn = {
@ -189,6 +196,16 @@ class FnGen {
this.pushIns({ tag: "pop", reg });
this.pushIns({ tag: "call_reg", reg, args: k.args });
this.pushIns({ tag: "kill", reg });
const rval = this.reg();
this.pushIns({ tag: "pop", reg: rval });
for (let i = 0; i < k.args; ++i) {
const reg = this.reg();
this.pushIns({ tag: "pop", reg });
this.pushIns({ tag: "kill", reg });
}
this.pushIns({ tag: "push", reg: rval });
this.pushIns({ tag: "kill", reg: rval });
return;
}
case "lt":

View File

@ -17,6 +17,8 @@ async function main() {
const re = new Resolver(ast).resolve();
const ch = new Checker(re);
const optimize = true;
const mirGen = new MirGen(re, ch);
// console.log("=== MIR ===");
@ -28,11 +30,15 @@ async function main() {
// console.log(new FnStringifyer(fnMir).stringify());
// }
const lir = new LirGen(ast, mirGen).generate();
const lir = new LirGen(ast, mirGen, {
optimize,
}).generate();
// console.log("=== LIR ===");
// console.log(new ProgramStringifyer(lir).stringify());
optimizeLir(lir);
if (optimize) {
optimizeLir(lir);
}
const asm = new AsmGen(lir).generate();
// console.log("=== ASM ===");

View File

@ -110,15 +110,18 @@ export class FnMirGen {
}
case "while": {
const entry = this.currentBlock;
const cond = this.block();
const loop = this.block();
const exit = this.block();
this.currentBlock = cond;
this.lowerExpr(k.expr);
const condExit = this.currentBlock;
entry.ter = Ter({ tag: "goto", target: cond });
this.currentBlock = cond;
this.lowerExpr(k.expr);
this.currentBlock.ter = Ter({
const loop = this.block();
const exit = this.block();
condExit.ter = Ter({
tag: "if",
truthy: loop,
falsy: exit,
@ -128,7 +131,8 @@ export class FnMirGen {
this.currentBlock = loop;
this.lowerBlock(k.body);
this.currentBlock.ter = Ter({ tag: "goto", target: cond });
const loopExit = this.currentBlock;
loopExit.ter = Ter({ tag: "goto", target: cond });
this.currentBlock = exit;
return;
@ -136,23 +140,31 @@ export class FnMirGen {
case "if": {
this.lowerExpr(k.expr);
const entry = this.currentBlock;
const exit = this.block();
const truthy = this.block();
const truthy = this.block();
this.currentBlock = truthy;
this.lowerBlock(k.truthy);
this.currentBlock.ter = Ter({ tag: "goto", target: exit });
const truthyExit = this.currentBlock;
let falsy = exit;
if (k.falsy) {
falsy = this.block();
const falsy = this.block();
this.currentBlock = falsy;
this.lowerBlock(k.falsy);
this.currentBlock.ter = Ter({ tag: "goto", target: exit });
}
const falsyExit = this.currentBlock;
entry.ter = Ter({ tag: "if", truthy, falsy });
this.currentBlock = exit;
const exit = this.block();
truthyExit.ter = Ter({ tag: "goto", target: exit });
falsyExit.ter = Ter({ tag: "goto", target: exit });
entry.ter = Ter({ tag: "if", truthy, falsy });
this.currentBlock = exit;
} else {
const exit = this.block();
truthyExit.ter = Ter({ tag: "goto", target: exit });
entry.ter = Ter({ tag: "if", truthy, falsy: exit });
this.currentBlock = exit;
}
return;
}
case "return": {

View File

@ -2,9 +2,9 @@ import * as ast from "./ast.ts";
import { Block, Fn, FnStringifyer } from "./mir.ts";
export function optimizeMirFn(fn: Fn) {
console.log(`=== OPTIMIZING ${(fn.stmt.kind as ast.FnStmt).ident} ===`);
console.log("=== BEFORE OPTIMIZATION ===");
console.log(new FnStringifyer(fn).stringify());
// console.log(`=== OPTIMIZING ${(fn.stmt.kind as ast.FnStmt).ident} ===`);
// console.log("=== BEFORE OPTIMIZATION ===");
// console.log(new FnStringifyer(fn).stringify());
const blockSize = fn.blocks
.map((block) => block.stmts.length)
@ -27,8 +27,8 @@ export function optimizeMirFn(fn: Fn) {
sizeHistory.add(sizeBefore);
}
console.log("=== AFTER OPTIMIZATION ===");
console.log(new FnStringifyer(fn).stringify());
// console.log("=== AFTER OPTIMIZATION ===");
// console.log(new FnStringifyer(fn).stringify());
}
function fnSize(fn: Fn, blockSize: number): number {

View File

@ -4,16 +4,27 @@ fn println(value: *str) -> int {}
#[c_function("print_int")]
fn print_int(value: int) -> int {}
fn factorial(v: int) -> int {
if v == 0 {
return 1;
}
return v * factorial(v - 1);
}
#[c_export("sbc_main")]
fn main() -> int {
let i = 0;
while i < 10 {
// while i < 10 {
//
// println("Hello\ world");
//
// i = i + 1;
// }
println("Hello\ world");
let a = factorial(5);
i = i + 1;
}
print_int(a);
return 0;
}