mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-28 00:34:06 +02:00
compiler: fix pop parameters
This commit is contained in:
parent
d5541c46fa
commit
827e26577a
@ -168,7 +168,7 @@ export class AsmGen {
|
|||||||
this.writeIns(`push rbp`);
|
this.writeIns(`push rbp`);
|
||||||
this.writeIns(`mov rbp, rsp`);
|
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}`);
|
this.writeIns(`jmp .L${fn.mir.entry.id}`);
|
||||||
|
|
||||||
for (const line of fn.lines.slice(bodyIdx)) {
|
for (const line of fn.lines.slice(bodyIdx)) {
|
||||||
@ -422,6 +422,7 @@ class StackAllocator {
|
|||||||
currentOffset -= 8;
|
currentOffset -= 8;
|
||||||
// caller rbp
|
// caller rbp
|
||||||
currentOffset -= 8;
|
currentOffset -= 8;
|
||||||
|
frameSize += 8;
|
||||||
|
|
||||||
for (const [reg, size] of this.localRegs) {
|
for (const [reg, size] of this.localRegs) {
|
||||||
regOffsets.set(reg, currentOffset);
|
regOffsets.set(reg, currentOffset);
|
||||||
|
@ -12,6 +12,10 @@ import * as ast from "./ast.ts";
|
|||||||
import * as mir from "./mir.ts";
|
import * as mir from "./mir.ts";
|
||||||
import { optimizeMirFn } from "./mir_optimize.ts";
|
import { optimizeMirFn } from "./mir_optimize.ts";
|
||||||
|
|
||||||
|
export type LirGenOpts = {
|
||||||
|
optimize?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export class LirGen {
|
export class LirGen {
|
||||||
private strings = new StringIntern();
|
private strings = new StringIntern();
|
||||||
|
|
||||||
@ -22,6 +26,7 @@ export class LirGen {
|
|||||||
public constructor(
|
public constructor(
|
||||||
private ast: ast.Stmt[],
|
private ast: ast.Stmt[],
|
||||||
private mirGen: MirGen,
|
private mirGen: MirGen,
|
||||||
|
private opts: LirGenOpts = {},
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public generate(): Program {
|
public generate(): Program {
|
||||||
@ -30,7 +35,9 @@ export class LirGen {
|
|||||||
throw new Error("only functions can compile top level");
|
throw new Error("only functions can compile top level");
|
||||||
}
|
}
|
||||||
const mir = this.mirGen.fnMir(stmt, stmt.kind);
|
const mir = this.mirGen.fnMir(stmt, stmt.kind);
|
||||||
|
if (this.opts.optimize !== false) {
|
||||||
optimizeMirFn(mir);
|
optimizeMirFn(mir);
|
||||||
|
}
|
||||||
const id = this.fnIds++;
|
const id = this.fnIds++;
|
||||||
const label = `sbc__${stmt.kind.ident}`;
|
const label = `sbc__${stmt.kind.ident}`;
|
||||||
const fn: Fn = {
|
const fn: Fn = {
|
||||||
@ -189,6 +196,16 @@ class FnGen {
|
|||||||
this.pushIns({ tag: "pop", reg });
|
this.pushIns({ tag: "pop", reg });
|
||||||
this.pushIns({ tag: "call_reg", reg, args: k.args });
|
this.pushIns({ tag: "call_reg", reg, args: k.args });
|
||||||
this.pushIns({ tag: "kill", reg });
|
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;
|
return;
|
||||||
}
|
}
|
||||||
case "lt":
|
case "lt":
|
||||||
|
@ -17,6 +17,8 @@ async function main() {
|
|||||||
const re = new Resolver(ast).resolve();
|
const re = new Resolver(ast).resolve();
|
||||||
const ch = new Checker(re);
|
const ch = new Checker(re);
|
||||||
|
|
||||||
|
const optimize = true;
|
||||||
|
|
||||||
const mirGen = new MirGen(re, ch);
|
const mirGen = new MirGen(re, ch);
|
||||||
|
|
||||||
// console.log("=== MIR ===");
|
// console.log("=== MIR ===");
|
||||||
@ -28,11 +30,15 @@ async function main() {
|
|||||||
// console.log(new FnStringifyer(fnMir).stringify());
|
// 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("=== LIR ===");
|
||||||
// console.log(new ProgramStringifyer(lir).stringify());
|
// console.log(new ProgramStringifyer(lir).stringify());
|
||||||
|
|
||||||
|
if (optimize) {
|
||||||
optimizeLir(lir);
|
optimizeLir(lir);
|
||||||
|
}
|
||||||
|
|
||||||
const asm = new AsmGen(lir).generate();
|
const asm = new AsmGen(lir).generate();
|
||||||
// console.log("=== ASM ===");
|
// console.log("=== ASM ===");
|
||||||
|
@ -110,15 +110,18 @@ export class FnMirGen {
|
|||||||
}
|
}
|
||||||
case "while": {
|
case "while": {
|
||||||
const entry = this.currentBlock;
|
const entry = this.currentBlock;
|
||||||
|
|
||||||
const cond = this.block();
|
const cond = this.block();
|
||||||
const loop = this.block();
|
this.currentBlock = cond;
|
||||||
const exit = this.block();
|
this.lowerExpr(k.expr);
|
||||||
|
const condExit = this.currentBlock;
|
||||||
|
|
||||||
entry.ter = Ter({ tag: "goto", target: cond });
|
entry.ter = Ter({ tag: "goto", target: cond });
|
||||||
|
|
||||||
this.currentBlock = cond;
|
const loop = this.block();
|
||||||
this.lowerExpr(k.expr);
|
const exit = this.block();
|
||||||
this.currentBlock.ter = Ter({
|
|
||||||
|
condExit.ter = Ter({
|
||||||
tag: "if",
|
tag: "if",
|
||||||
truthy: loop,
|
truthy: loop,
|
||||||
falsy: exit,
|
falsy: exit,
|
||||||
@ -128,7 +131,8 @@ export class FnMirGen {
|
|||||||
|
|
||||||
this.currentBlock = loop;
|
this.currentBlock = loop;
|
||||||
this.lowerBlock(k.body);
|
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;
|
this.currentBlock = exit;
|
||||||
return;
|
return;
|
||||||
@ -136,23 +140,31 @@ export class FnMirGen {
|
|||||||
case "if": {
|
case "if": {
|
||||||
this.lowerExpr(k.expr);
|
this.lowerExpr(k.expr);
|
||||||
const entry = this.currentBlock;
|
const entry = this.currentBlock;
|
||||||
const exit = this.block();
|
|
||||||
const truthy = this.block();
|
|
||||||
|
|
||||||
|
const truthy = this.block();
|
||||||
this.currentBlock = truthy;
|
this.currentBlock = truthy;
|
||||||
this.lowerBlock(k.truthy);
|
this.lowerBlock(k.truthy);
|
||||||
this.currentBlock.ter = Ter({ tag: "goto", target: exit });
|
const truthyExit = this.currentBlock;
|
||||||
|
|
||||||
let falsy = exit;
|
|
||||||
if (k.falsy) {
|
if (k.falsy) {
|
||||||
falsy = this.block();
|
const falsy = this.block();
|
||||||
this.currentBlock = falsy;
|
this.currentBlock = falsy;
|
||||||
this.lowerBlock(k.falsy);
|
this.lowerBlock(k.falsy);
|
||||||
this.currentBlock.ter = Ter({ tag: "goto", target: exit });
|
const falsyExit = this.currentBlock;
|
||||||
}
|
|
||||||
|
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 });
|
entry.ter = Ter({ tag: "if", truthy, falsy });
|
||||||
this.currentBlock = exit;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
case "return": {
|
case "return": {
|
||||||
|
@ -2,9 +2,9 @@ import * as ast from "./ast.ts";
|
|||||||
import { Block, Fn, FnStringifyer } from "./mir.ts";
|
import { Block, Fn, FnStringifyer } from "./mir.ts";
|
||||||
|
|
||||||
export function optimizeMirFn(fn: Fn) {
|
export function optimizeMirFn(fn: Fn) {
|
||||||
console.log(`=== OPTIMIZING ${(fn.stmt.kind as ast.FnStmt).ident} ===`);
|
// console.log(`=== OPTIMIZING ${(fn.stmt.kind as ast.FnStmt).ident} ===`);
|
||||||
console.log("=== BEFORE OPTIMIZATION ===");
|
// console.log("=== BEFORE OPTIMIZATION ===");
|
||||||
console.log(new FnStringifyer(fn).stringify());
|
// console.log(new FnStringifyer(fn).stringify());
|
||||||
|
|
||||||
const blockSize = fn.blocks
|
const blockSize = fn.blocks
|
||||||
.map((block) => block.stmts.length)
|
.map((block) => block.stmts.length)
|
||||||
@ -27,8 +27,8 @@ export function optimizeMirFn(fn: Fn) {
|
|||||||
sizeHistory.add(sizeBefore);
|
sizeHistory.add(sizeBefore);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("=== AFTER OPTIMIZATION ===");
|
// console.log("=== AFTER OPTIMIZATION ===");
|
||||||
console.log(new FnStringifyer(fn).stringify());
|
// console.log(new FnStringifyer(fn).stringify());
|
||||||
}
|
}
|
||||||
|
|
||||||
function fnSize(fn: Fn, blockSize: number): number {
|
function fnSize(fn: Fn, blockSize: number): number {
|
||||||
|
@ -4,16 +4,27 @@ fn println(value: *str) -> int {}
|
|||||||
#[c_function("print_int")]
|
#[c_function("print_int")]
|
||||||
fn print_int(value: int) -> 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")]
|
#[c_export("sbc_main")]
|
||||||
fn main() -> int {
|
fn main() -> int {
|
||||||
let i = 0;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user