mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-27 08:24:05 +02:00
works, but segfaults
This commit is contained in:
parent
2025a450f6
commit
fd2f6243a2
14
backup-compiler/.clang-format
Normal file
14
backup-compiler/.clang-format
Normal file
@ -0,0 +1,14 @@
|
||||
Language: Cpp
|
||||
BasedOnStyle: WebKit
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 80
|
||||
IndentCaseLabels: true
|
||||
InsertNewlineAtEOF: true
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
|
||||
BinPackArguments: false
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
|
||||
BinPackParameters: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
|
4
backup-compiler/.gitignore
vendored
Normal file
4
backup-compiler/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
out.nasm
|
||||
*.o
|
||||
out
|
||||
|
18
backup-compiler/Makefile
Normal file
18
backup-compiler/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
all: out
|
||||
|
||||
out: entry.o out.o lib.o
|
||||
gcc $^ -o $@ -no-pie
|
||||
|
||||
%.o: %.c
|
||||
gcc -c -o $@ -std=c17 -Wall -Wextra -Wpedantic -pedantic -pedantic-errors $^
|
||||
|
||||
%.o: %.nasm
|
||||
nasm -f elf64 $< -o $@
|
||||
|
||||
out.nasm: program.sbl
|
||||
deno run --allow-read --allow-write --check main.ts $<
|
||||
|
||||
clean:
|
||||
rm -rf out.asm out.o lib.o entry.o out
|
||||
|
@ -25,17 +25,28 @@ export class AsmGen {
|
||||
}
|
||||
this.writeln(`section .text`);
|
||||
for (const fn of this.lir.fns) {
|
||||
this.writeln(`align 8`);
|
||||
this.writeln(`global ${fn.label}:`);
|
||||
this.writeln(`${fn.label}:`);
|
||||
|
||||
this.generateFnBody(fn);
|
||||
this.generateFn(fn);
|
||||
}
|
||||
|
||||
this.writeln(`; vim: syntax=nasm commentstring=;\\ %s`);
|
||||
this.writeln("");
|
||||
return this.writer.finalize();
|
||||
}
|
||||
|
||||
private generateFnBody(fn: lir.Fn) {
|
||||
private generateFn(fn: lir.Fn) {
|
||||
const query = this.queryCFunction(fn);
|
||||
if (query.found) {
|
||||
const { label, args } = query;
|
||||
this.generateCFunctionBody(fn, label, args);
|
||||
return;
|
||||
}
|
||||
|
||||
this.generateFnBody(fn);
|
||||
}
|
||||
|
||||
private queryCFunction(
|
||||
fn: lir.Fn,
|
||||
): { found: false } | { found: true; label: string; args: number } {
|
||||
const stmtKind = fn.mir.stmt.kind;
|
||||
if (stmtKind.tag !== "fn") {
|
||||
throw new Error();
|
||||
@ -45,12 +56,41 @@ export class AsmGen {
|
||||
if (!arg || arg.kind.tag !== "string") {
|
||||
throw new Error("incorrect args for attribute");
|
||||
}
|
||||
const label = arg.kind.val;
|
||||
this.generateCFunctionBody(label, fn.mir.paramLocals.size);
|
||||
return;
|
||||
return {
|
||||
found: true,
|
||||
label: arg.kind.val,
|
||||
args: fn.mir.paramLocals.size,
|
||||
};
|
||||
}
|
||||
return { found: false };
|
||||
}
|
||||
|
||||
private generateCFunctionBody(fn: lir.Fn, label: string, args: number) {
|
||||
this.writeln(`extern ${label}`);
|
||||
this.writeln(`global ${fn.label}`);
|
||||
this.writeln(`${fn.label}:`);
|
||||
|
||||
this.writeIns(`push rbp`);
|
||||
this.writeIns(`mov rbp, rsp`);
|
||||
for (let i = 0; i < args; ++i) {
|
||||
this.writeIns(`mov rax, ${this.relative((i + 2) * 8)}`);
|
||||
this.writeIns(`push rax`);
|
||||
}
|
||||
|
||||
this.writeIns(`push r12`);
|
||||
const argRegs = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
|
||||
for (const reg of argRegs.slice(0, args + 1)) {
|
||||
this.writeIns(`pop ${reg}`);
|
||||
}
|
||||
|
||||
this.writeIns(`call ${label}`);
|
||||
this.writeIns(`mov rsp, rbp`);
|
||||
this.writeIns(`pop rbp`);
|
||||
this.writeIns(`ret`);
|
||||
}
|
||||
|
||||
private generateFnBody(fn: lir.Fn) {
|
||||
this.writeln(`global ${fn.label}:`);
|
||||
this.writeln(`${fn.label}:`);
|
||||
this.writeIns(`push rbp`);
|
||||
this.writeIns(`mov rbp, rsp`);
|
||||
this.writeIns(`sub rsp, ${fn.frameSize}`);
|
||||
@ -64,30 +104,11 @@ export class AsmGen {
|
||||
}
|
||||
|
||||
this.writeln(`.exit:`);
|
||||
const returnLocalOffset = fn.localOffsets.get(fn.mir.returnLocal.id)!;
|
||||
this.writeIns(`mov rax, QWORD ${this.relative(returnLocalOffset)}`);
|
||||
this.writeIns(`mov rsp, rbp`);
|
||||
this.writeIns(`pop rbp`);
|
||||
this.writeIns(`pop r12`);
|
||||
}
|
||||
|
||||
private generateCFunctionBody(label: string, args: number) {
|
||||
const argRegs = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
|
||||
const returnReg = "rax";
|
||||
if (args > argRegs.length) {
|
||||
throw new Error(
|
||||
`arg count (${args}) > ${argRegs.length} not supported`,
|
||||
);
|
||||
}
|
||||
this.writeIns(`push ${returnReg}`);
|
||||
for (const reg of argRegs.slice(0, args + 1)) {
|
||||
this.writeIns(`push ${reg}`);
|
||||
}
|
||||
this.writeIns(`call ${label}`);
|
||||
this.writeIns(`mov r12, rax`);
|
||||
for (const reg of argRegs.slice(0, args + 1).toReversed()) {
|
||||
this.writeIns(`push ${reg}`);
|
||||
}
|
||||
this.writeIns(`pop ${returnReg}`);
|
||||
this.writeIns(`push r12`);
|
||||
this.writeIns(`ret`);
|
||||
}
|
||||
|
||||
private generateIns(ins: lir.Ins) {
|
||||
@ -115,16 +136,27 @@ export class AsmGen {
|
||||
this.writeIns(`pop ${r(ins.reg)}`);
|
||||
return;
|
||||
case "load":
|
||||
this.writeIns(`mov QWORD [rbp${ins.offset}], ${r(ins.reg)}`);
|
||||
this.writeIns(
|
||||
`mov ${r(ins.reg)}, QWORD ${this.relative(ins.offset)}`,
|
||||
);
|
||||
return;
|
||||
case "store":
|
||||
this.writeIns(`mov ${r(ins.reg)}, QWORD [rbp${ins.offset}]`);
|
||||
case "store_reg":
|
||||
this.writeIns(
|
||||
`mov QWORD ${this.relative(ins.offset)}, ${r(ins.reg)}`,
|
||||
);
|
||||
return;
|
||||
case "store_imm":
|
||||
this.writeIns(
|
||||
`mov QWORD ${this.relative(ins.offset)}, ${ins.val}`,
|
||||
);
|
||||
return;
|
||||
case "call_reg":
|
||||
this.generateCall(r(ins.reg), ins.args);
|
||||
this.writeIns(`call ${r(ins.reg)}`);
|
||||
this.writeIns(`push rax`);
|
||||
return;
|
||||
case "call_fn":
|
||||
this.generateCall(ins.fn.label, ins.args);
|
||||
case "call_imm":
|
||||
this.writeIns(`call ${ins.fn.label}`);
|
||||
this.writeIns(`push rax`);
|
||||
return;
|
||||
case "jmp":
|
||||
this.writeIns(`jmp .L${ins.target}`);
|
||||
@ -153,27 +185,7 @@ export class AsmGen {
|
||||
this.kill(ins.reg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private generateCall(value: string, args: number) {
|
||||
const argRegs = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
|
||||
const returnReg = "rax";
|
||||
if (args > argRegs.length) {
|
||||
throw new Error(
|
||||
`arg count (${args}) > ${argRegs.length} not supported`,
|
||||
);
|
||||
}
|
||||
this.writeIns(`push ${returnReg}`);
|
||||
for (const reg of argRegs.slice(0, args + 1)) {
|
||||
this.writeIns(`push ${reg}`);
|
||||
}
|
||||
this.writeIns(`call ${value}`);
|
||||
this.writeIns(`mov r12, rax`);
|
||||
for (const reg of argRegs.slice(0, args + 1).toReversed()) {
|
||||
this.writeIns(`push ${reg}`);
|
||||
}
|
||||
this.writeIns(`pop ${returnReg}`);
|
||||
this.writeIns(`push r12`);
|
||||
const _: never = ins;
|
||||
}
|
||||
|
||||
private reg(reg: lir.Reg): string {
|
||||
@ -198,7 +210,6 @@ export class AsmGen {
|
||||
|
||||
private allocReg(reg: lir.Reg) {
|
||||
if (!this.liveRegs.has(reg)) {
|
||||
this.liveRegs.add(reg);
|
||||
const regSel = [
|
||||
"rax",
|
||||
"rdi",
|
||||
@ -213,10 +224,15 @@ export class AsmGen {
|
||||
if (!regSel) {
|
||||
throw new Error("ran out of registers");
|
||||
}
|
||||
this.liveRegs.add(reg);
|
||||
this.regSelect.set(reg, regSel);
|
||||
}
|
||||
}
|
||||
|
||||
private relative(offset: number): string {
|
||||
return `[rbp${offset >= 0 ? `+${offset}` : `${offset}`}]`;
|
||||
}
|
||||
|
||||
private kill(reg: lir.Reg) {
|
||||
this.liveRegs.delete(reg);
|
||||
this.regSelect.delete(reg);
|
||||
|
8
backup-compiler/entry.c
Normal file
8
backup-compiler/entry.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <stdint.h>
|
||||
|
||||
extern int32_t sbc__main(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
sbc__main();
|
||||
}
|
8
backup-compiler/lib.c
Normal file
8
backup-compiler/lib.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int64_t print_int(int64_t value)
|
||||
{
|
||||
printf("%ld\n", value);
|
||||
return 0;
|
||||
}
|
@ -11,6 +11,7 @@ export type Fn = {
|
||||
mir: mir.Fn;
|
||||
lines: Line[];
|
||||
frameSize: number;
|
||||
localOffsets: Map<number, number>;
|
||||
};
|
||||
|
||||
export type Line = {
|
||||
@ -27,9 +28,10 @@ export type Ins =
|
||||
| { tag: "push"; reg: Reg }
|
||||
| { tag: "pop"; reg: Reg }
|
||||
| { tag: "load"; reg: Reg; offset: number }
|
||||
| { tag: "store"; offset: number; reg: Reg }
|
||||
| { tag: "store_reg"; offset: number; reg: Reg }
|
||||
| { tag: "store_imm"; offset: number; val: number }
|
||||
| { tag: "call_reg"; reg: Reg; args: number }
|
||||
| { tag: "call_fn"; fn: Fn; args: number }
|
||||
| { tag: "call_imm"; fn: Fn; args: number }
|
||||
| { tag: "jmp"; target: Label }
|
||||
| { tag: "jnz_reg"; reg: Reg; target: Label }
|
||||
| { tag: "ret" }
|
||||
@ -52,7 +54,7 @@ export class ProgramStringifyer {
|
||||
.map((label) =>
|
||||
`${
|
||||
label.labels
|
||||
.map((label) => `.${label}:\n`)
|
||||
.map((label) => `.L${label}:\n`)
|
||||
.join()
|
||||
} ${this.ins(label.ins)}\n`
|
||||
)
|
||||
@ -80,11 +82,13 @@ export class ProgramStringifyer {
|
||||
return `pop %${ins.reg}`;
|
||||
case "load":
|
||||
return `load %${ins.reg}, ${ins.offset}`;
|
||||
case "store":
|
||||
return `store ${ins.offset}, %${ins.reg}`;
|
||||
case "store_reg":
|
||||
return `store_reg ${ins.offset}, %${ins.reg}`;
|
||||
case "store_imm":
|
||||
return `store_val ${ins.offset}, ${ins.val}`;
|
||||
case "call_reg":
|
||||
return `call_reg %${ins.reg}, ${ins.args}`;
|
||||
case "call_fn":
|
||||
case "call_imm":
|
||||
return `call_fn ${ins.fn.label}, ${ins.args}`;
|
||||
case "jmp":
|
||||
return `jmp .b${ins.target}`;
|
||||
|
@ -31,7 +31,14 @@ export class LirGen {
|
||||
const mir = this.mirGen.fnMir(stmt, stmt.kind);
|
||||
const id = this.fnIds++;
|
||||
const label = `sbc__${stmt.kind.ident}`;
|
||||
const fn: Fn = { id, label, mir, lines: [], frameSize: 0 };
|
||||
const fn: Fn = {
|
||||
id,
|
||||
label,
|
||||
mir,
|
||||
lines: [],
|
||||
frameSize: 0,
|
||||
localOffsets: new Map(),
|
||||
};
|
||||
this.fns.set(id, fn);
|
||||
this.stmtFns.set(stmt.id, fn);
|
||||
}
|
||||
@ -69,8 +76,6 @@ class FnGen {
|
||||
|
||||
private currentLabels: Label[] = [];
|
||||
|
||||
private nextOffset = -8;
|
||||
private frameSize = 0;
|
||||
private localOffsets = new Map<number, number>();
|
||||
|
||||
public constructor(
|
||||
@ -84,12 +89,33 @@ class FnGen {
|
||||
const label = this.labelIds++;
|
||||
this.blockLabels.set(block.id, label);
|
||||
}
|
||||
for (const local of this.fn.mir.locals) {
|
||||
this.localOffsets.set(local.id, this.nextOffset);
|
||||
this.nextOffset -= 8;
|
||||
this.frameSize += 8;
|
||||
|
||||
let currentOffset = 8 + this.fn.mir.paramLocals.size * 8;
|
||||
let frameSize = 0;
|
||||
|
||||
for (const local of this.fn.mir.paramLocals.values()) {
|
||||
this.localOffsets.set(local.id, currentOffset);
|
||||
currentOffset -= 8;
|
||||
}
|
||||
this.fn.frameSize = this.frameSize;
|
||||
// return address
|
||||
currentOffset -= 8;
|
||||
// old rbp
|
||||
currentOffset -= 8;
|
||||
// return value
|
||||
this.localOffsets.set(this.fn.mir.returnLocal.id, currentOffset);
|
||||
currentOffset -= 8;
|
||||
frameSize += 8;
|
||||
for (const local of this.fn.mir.locals) {
|
||||
if (this.localOffsets.has(local.id)) {
|
||||
continue;
|
||||
}
|
||||
this.localOffsets.set(local.id, currentOffset);
|
||||
currentOffset -= 8;
|
||||
frameSize += 8;
|
||||
}
|
||||
this.fn.frameSize = frameSize;
|
||||
this.fn.localOffsets = this.localOffsets;
|
||||
|
||||
for (const block of this.fn.mir.blocks) {
|
||||
this.currentLabels.push(this.blockLabels.get(block.id)!);
|
||||
for (const stmt of block.stmts) {
|
||||
@ -158,7 +184,7 @@ class FnGen {
|
||||
const reg = this.reg();
|
||||
const offset = this.localOffsets.get(k.local.id)!;
|
||||
this.pushIns({ tag: "pop", reg });
|
||||
this.pushIns({ tag: "store", offset, reg });
|
||||
this.pushIns({ tag: "store_reg", offset, reg });
|
||||
this.pushIns({ tag: "kill", reg });
|
||||
return;
|
||||
}
|
||||
@ -175,8 +201,8 @@ class FnGen {
|
||||
case "mul": {
|
||||
const dst = this.reg();
|
||||
const src = this.reg();
|
||||
this.pushIns({ tag: "pop", reg: src });
|
||||
this.pushIns({ tag: "pop", reg: dst });
|
||||
this.pushIns({ tag: "pop", reg: src });
|
||||
this.pushIns({ tag: k.tag, dst, src });
|
||||
this.pushIns({ tag: "push", reg: dst });
|
||||
this.pushIns({ tag: "kill", reg: src });
|
||||
|
185
backup-compiler/lir_optimize.ts
Normal file
185
backup-compiler/lir_optimize.ts
Normal file
@ -0,0 +1,185 @@
|
||||
import {
|
||||
Fn,
|
||||
Ins,
|
||||
Label,
|
||||
Line,
|
||||
Program,
|
||||
ProgramStringifyer,
|
||||
Reg,
|
||||
} from "./lir.ts";
|
||||
|
||||
export function lirOptimize(program: Program) {
|
||||
console.log("=== BEFORE OPTIMIZATION ===");
|
||||
console.log(new ProgramStringifyer(program).stringify());
|
||||
for (const fn of program.fns) {
|
||||
eliminatePushPop(fn);
|
||||
eliminateMovFnCall(fn);
|
||||
eliminateMovIntStoreReg(fn);
|
||||
}
|
||||
console.log("=== AFTER OPTIMIZATION ===");
|
||||
console.log(new ProgramStringifyer(program).stringify());
|
||||
}
|
||||
|
||||
function eliminatePushPop(fn: Fn) {
|
||||
const candidates: number[] = [];
|
||||
|
||||
for (let i = 0; i < fn.lines.length - 2; ++i) {
|
||||
const [push, kill, pop] = fn.lines.slice(i);
|
||||
if (
|
||||
push.ins.tag === "push" &&
|
||||
kill.ins.tag === "kill" &&
|
||||
pop.ins.tag === "pop" &&
|
||||
kill.labels.length === 0 &&
|
||||
pop.labels.length === 0 &&
|
||||
push.ins.reg === kill.ins.reg
|
||||
) {
|
||||
candidates.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (const i of candidates.toReversed()) {
|
||||
if (i + 3 >= fn.lines.length) {
|
||||
fn.lines[i + 3].labels.push(...fn.lines[i].labels);
|
||||
}
|
||||
const [push, kill, pop] = fn.lines.slice(i);
|
||||
if (
|
||||
!(
|
||||
push.ins.tag === "push" &&
|
||||
kill.ins.tag === "kill" &&
|
||||
pop.ins.tag === "pop"
|
||||
)
|
||||
) {
|
||||
throw new Error();
|
||||
}
|
||||
const toRemove = pop.ins.reg;
|
||||
const replacement = push.ins.reg;
|
||||
fn.lines.splice(i, 3);
|
||||
replaceReg(fn, toRemove, replacement);
|
||||
}
|
||||
}
|
||||
|
||||
function eliminateMovFnCall(fn: Fn) {
|
||||
const candidates: number[] = [];
|
||||
|
||||
for (let i = 0; i < fn.lines.length - 2; ++i) {
|
||||
const [movFn, callReg, kill] = fn.lines.slice(i);
|
||||
if (
|
||||
movFn.ins.tag === "mov_fn" &&
|
||||
callReg.ins.tag === "call_reg" &&
|
||||
kill.ins.tag === "kill" &&
|
||||
callReg.labels.length === 0 &&
|
||||
kill.labels.length === 0 &&
|
||||
movFn.ins.reg === callReg.ins.reg &&
|
||||
movFn.ins.reg === kill.ins.reg
|
||||
) {
|
||||
candidates.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (const i of candidates.toReversed()) {
|
||||
const [movFn, callReg, kill] = fn.lines.slice(i);
|
||||
if (
|
||||
!(
|
||||
movFn.ins.tag === "mov_fn" &&
|
||||
callReg.ins.tag === "call_reg" &&
|
||||
kill.ins.tag === "kill"
|
||||
)
|
||||
) {
|
||||
throw new Error();
|
||||
}
|
||||
const fnVal = movFn.ins.fn;
|
||||
const args = callReg.ins.args;
|
||||
fn.lines.splice(i + 1, 2);
|
||||
fn.lines[i].ins = { tag: "call_imm", fn: fnVal, args };
|
||||
}
|
||||
}
|
||||
|
||||
function eliminateMovIntStoreReg(fn: Fn) {
|
||||
const candidates: number[] = [];
|
||||
|
||||
for (let i = 0; i < fn.lines.length - 2; ++i) {
|
||||
const [movInt, storeReg, kill] = fn.lines.slice(i);
|
||||
if (
|
||||
movInt.ins.tag === "mov_int" &&
|
||||
storeReg.ins.tag === "store_reg" &&
|
||||
kill.ins.tag === "kill" &&
|
||||
storeReg.labels.length === 0 &&
|
||||
kill.labels.length === 0 &&
|
||||
movInt.ins.reg === storeReg.ins.reg &&
|
||||
movInt.ins.reg === kill.ins.reg
|
||||
) {
|
||||
candidates.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (const i of candidates.toReversed()) {
|
||||
const [movInt, storeReg, kill] = fn.lines.slice(i);
|
||||
if (
|
||||
!(
|
||||
movInt.ins.tag === "mov_int" &&
|
||||
storeReg.ins.tag === "store_reg" &&
|
||||
kill.ins.tag === "kill"
|
||||
)
|
||||
) {
|
||||
throw new Error();
|
||||
}
|
||||
const offset = storeReg.ins.offset;
|
||||
const val = movInt.ins.val;
|
||||
fn.lines.splice(i + 1, 2);
|
||||
fn.lines[i].ins = { tag: "store_imm", offset, val };
|
||||
}
|
||||
}
|
||||
|
||||
function replaceReg(fn: Fn, cand: Reg, replacement: Reg) {
|
||||
const r = (reg: Reg): Reg => reg === cand ? replacement : reg;
|
||||
|
||||
for (const { ins } of fn.lines) {
|
||||
switch (ins.tag) {
|
||||
case "error":
|
||||
break;
|
||||
case "nop":
|
||||
break;
|
||||
case "mov_int":
|
||||
case "mov_string":
|
||||
case "mov_fn":
|
||||
ins.reg = r(ins.reg);
|
||||
break;
|
||||
case "push":
|
||||
case "pop":
|
||||
ins.reg = r(ins.reg);
|
||||
break;
|
||||
case "load":
|
||||
case "store_reg":
|
||||
ins.reg = r(ins.reg);
|
||||
break;
|
||||
case "store_imm":
|
||||
break;
|
||||
case "call_reg":
|
||||
ins.reg = r(ins.reg);
|
||||
break;
|
||||
case "call_imm":
|
||||
break;
|
||||
case "jmp":
|
||||
break;
|
||||
case "jnz_reg":
|
||||
ins.reg = r(ins.reg);
|
||||
break;
|
||||
case "ret":
|
||||
break;
|
||||
case "lt":
|
||||
case "eq":
|
||||
case "add":
|
||||
case "mul":
|
||||
ins.dst = r(ins.dst);
|
||||
ins.src = r(ins.src);
|
||||
break;
|
||||
case "kill":
|
||||
ins.reg = r(ins.reg);
|
||||
break;
|
||||
default: {
|
||||
const _: never = ins;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,35 +5,40 @@ import { FnStringifyer } from "./mir.ts";
|
||||
import { LirGen } from "./lir_gen.ts";
|
||||
import { ProgramStringifyer } from "./lir.ts";
|
||||
import { AsmGen } from "./asm_gen.ts";
|
||||
import { lirOptimize } from "./lir_optimize.ts";
|
||||
|
||||
async function main() {
|
||||
const text = await Deno.readTextFile(Deno.args[0]);
|
||||
|
||||
const ast = new Parser(text).parse();
|
||||
console.log("=== AST ===");
|
||||
console.log(yaml.stringify(ast));
|
||||
// console.log("=== AST ===");
|
||||
// console.log(yaml.stringify(ast));
|
||||
|
||||
const re = new Resolver(ast).resolve();
|
||||
const ch = new Checker(re);
|
||||
|
||||
const mirGen = new MirGen(re, ch);
|
||||
|
||||
console.log("=== MIR ===");
|
||||
for (const stmt of ast) {
|
||||
if (stmt.kind.tag !== "fn") {
|
||||
throw new Error("only functions can compile top level");
|
||||
}
|
||||
const fnMir = mirGen.fnMir(stmt, stmt.kind);
|
||||
console.log(new FnStringifyer(fnMir).stringify());
|
||||
}
|
||||
// console.log("=== MIR ===");
|
||||
// for (const stmt of ast) {
|
||||
// if (stmt.kind.tag !== "fn") {
|
||||
// throw new Error("only functions can compile top level");
|
||||
// }
|
||||
// const fnMir = mirGen.fnMir(stmt, stmt.kind);
|
||||
// console.log(new FnStringifyer(fnMir).stringify());
|
||||
// }
|
||||
|
||||
const lir = new LirGen(ast, mirGen).generate();
|
||||
console.log("=== LIR ===");
|
||||
console.log(new ProgramStringifyer(lir).stringify());
|
||||
// console.log("=== LIR ===");
|
||||
// console.log(new ProgramStringifyer(lir).stringify());
|
||||
|
||||
lirOptimize(lir);
|
||||
|
||||
const asm = new AsmGen(lir).generate();
|
||||
console.log("=== ASM ===");
|
||||
console.log(asm);
|
||||
// console.log("=== ASM ===");
|
||||
// console.log(asm);
|
||||
|
||||
await Deno.writeTextFile("out.nasm", asm);
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -51,11 +51,12 @@ export class FnMirGen {
|
||||
|
||||
const entry = this.block();
|
||||
const exit = this.block();
|
||||
this.returnBlock = exit;
|
||||
|
||||
this.currentBlock = entry;
|
||||
this.lowerBlock(this.stmtKind.body);
|
||||
|
||||
entry.ter = Ter({ tag: "goto", target: exit });
|
||||
this.currentBlock.ter = Ter({ tag: "goto", target: exit });
|
||||
exit.ter = Ter({ tag: "return" });
|
||||
return {
|
||||
stmt: this.stmt,
|
||||
@ -251,6 +252,8 @@ export class FnMirGen {
|
||||
return;
|
||||
}
|
||||
case "binary": {
|
||||
this.lowerExpr(k.left);
|
||||
this.lowerExpr(k.right);
|
||||
switch (k.op) {
|
||||
case "<":
|
||||
this.pushStmt({ tag: "lt" });
|
||||
@ -290,4 +293,3 @@ export class FnMirGen {
|
||||
this.currentBlock.stmts.push(Stmt(kind));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,15 @@
|
||||
#[c_function("print_int")]
|
||||
fn print_int(value) {}
|
||||
|
||||
// #[c_function("println")]
|
||||
// fn println(value) {}
|
||||
fn inner(value) {
|
||||
print_int(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// println("hello\ world");
|
||||
let a = 4;
|
||||
print_int(a + 2);
|
||||
inner(a + 2);
|
||||
return a;
|
||||
}
|
||||
|
||||
// vim: syntax=rust commentstring=//\ %s
|
||||
|
Loading…
x
Reference in New Issue
Block a user