This commit is contained in:
parent
bfac7bb765
commit
ec84b385d3
@ -1,14 +1,9 @@
|
|||||||
|
|
||||||
fn add(a: int, b: int) -> int
|
fn main() -> i32
|
||||||
{
|
{
|
||||||
return a + b;
|
let a = 2;
|
||||||
}
|
let b = a + 5;
|
||||||
|
return b;
|
||||||
fn main()
|
|
||||||
{
|
|
||||||
let sum = add(2, 3);
|
|
||||||
print_int(sum);
|
|
||||||
print_int(2 - 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -52,10 +52,10 @@ class InstructionSelector {
|
|||||||
src: Reg.reg(Regs.bp),
|
src: Reg.reg(Regs.bp),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
entry.push(new Inst({ tag: "PopR", dst: Reg.reg(Regs.bp) }));
|
exit.push(new Inst({ tag: "PopR", dst: Reg.reg(Regs.bp) }));
|
||||||
entry.push(new Inst({ tag: "Ret" }));
|
exit.push(new Inst({ tag: "Ret" }));
|
||||||
|
|
||||||
return new Fn([entry, ...blocks, exit]);
|
return new Fn(this.fn, [entry, ...blocks, exit]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private generateFrameLayout() {
|
private generateFrameLayout() {
|
||||||
@ -63,14 +63,14 @@ class InstructionSelector {
|
|||||||
|
|
||||||
const align = (alignment: number) => {
|
const align = (alignment: number) => {
|
||||||
if (offset % alignment != 0) {
|
if (offset % alignment != 0) {
|
||||||
offset += alignment - offset % alignment;
|
offset -= alignment + offset % alignment;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const pushLocal = (inst: mir.Inst, size: number, alignment: number) => {
|
const pushLocal = (inst: mir.Inst, size: number, alignment: number) => {
|
||||||
align(alignment);
|
align(alignment);
|
||||||
this.locals.set(inst, offset);
|
this.locals.set(inst, offset);
|
||||||
offset += size;
|
offset -= size;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.fn.visit({
|
this.fn.visit({
|
||||||
@ -102,28 +102,93 @@ class InstructionSelector {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// c abi requires 16 bit stack alignment,
|
||||||
|
// might aswell do it here.
|
||||||
align(16);
|
align(16);
|
||||||
|
|
||||||
this.localsSize = offset;
|
this.localsSize = -offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
private generateBasicBlock(bb: mir.BasicBlock): Block {
|
private generateBasicBlock(bb: mir.BasicBlock): Block {
|
||||||
|
const regs = new Map<mir.Inst, Reg>();
|
||||||
|
|
||||||
const block = new Block();
|
const block = new Block();
|
||||||
for (const inst of bb.insts) {
|
for (const inst of bb.insts) {
|
||||||
|
const save = (r: Reg): Reg => {
|
||||||
|
regs.set(inst, r);
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
const k = inst.kind;
|
const k = inst.kind;
|
||||||
switch (k.tag) {
|
switch (k.tag) {
|
||||||
case "Alloca":
|
case "Alloca":
|
||||||
|
save(Reg.temp());
|
||||||
|
break;
|
||||||
|
case "Void":
|
||||||
|
block.push(
|
||||||
|
new Inst({
|
||||||
|
tag: "MovRI",
|
||||||
|
dst: save(Reg.temp()),
|
||||||
|
imm: 0,
|
||||||
|
}),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "Int":
|
case "Int":
|
||||||
block.push(
|
block.push(
|
||||||
new Inst({
|
new Inst({
|
||||||
tag: "MovRI",
|
tag: "MovRI",
|
||||||
dst: Reg.reg(Regs.bp),
|
dst: save(Reg.temp()),
|
||||||
imm: k.value,
|
imm: k.value,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case "Store":
|
||||||
|
block.push(
|
||||||
|
new Inst({
|
||||||
|
tag: "MovMRR",
|
||||||
|
dst: Reg.reg(Regs.bp),
|
||||||
|
offset: this.locals.get(k.target)!,
|
||||||
|
src: regs.get(k.source)!,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "Load":
|
||||||
|
block.push(
|
||||||
|
new Inst({
|
||||||
|
tag: "MovRMR",
|
||||||
|
dst: save(Reg.temp()),
|
||||||
|
offset: this.locals.get(k.source)!,
|
||||||
|
src: Reg.reg(Regs.bp),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "Add":
|
||||||
|
block.push(
|
||||||
|
new Inst({
|
||||||
|
tag: "AddR",
|
||||||
|
dst_op1: save(regs.get(k.left)!),
|
||||||
|
op2: regs.get(k.right)!,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Return":
|
||||||
|
block.push(
|
||||||
|
new Inst({
|
||||||
|
tag: "MovRR",
|
||||||
|
dst: Reg.reg(Regs.a),
|
||||||
|
src: regs.get(k.source)!,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
block.push(
|
||||||
|
new Inst({
|
||||||
|
tag: "Jmp",
|
||||||
|
bb: this.exitBlock,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
|
console.error(`not implemented (${k.tag})`);
|
||||||
// throw new Error(
|
// throw new Error(
|
||||||
// `not implemented (${k.tag})`,
|
// `not implemented (${k.tag})`,
|
||||||
// );
|
// );
|
||||||
|
|||||||
@ -1,15 +1,18 @@
|
|||||||
|
import * as mir from "../../mir.ts";
|
||||||
|
|
||||||
export class Module {
|
export class Module {
|
||||||
private fns: Fn[] = [];
|
private fns: Fn[] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Fn {
|
export class Fn {
|
||||||
constructor(
|
constructor(
|
||||||
private blocks: Block[] = [],
|
public mirFn: mir.Fn,
|
||||||
|
public blocks: Block[] = [],
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Block {
|
export class Block {
|
||||||
private insts: Inst[] = [];
|
public insts: Inst[] = [];
|
||||||
|
|
||||||
push(inst: Inst) {
|
push(inst: Inst) {
|
||||||
this.insts.push(inst);
|
this.insts.push(inst);
|
||||||
@ -38,7 +41,7 @@ export class Reg {
|
|||||||
static tempId = 1000;
|
static tempId = 1000;
|
||||||
|
|
||||||
private constructor(
|
private constructor(
|
||||||
private id: number,
|
public id: number,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
static reg(reg: Regs): Reg {
|
static reg(reg: Regs): Reg {
|
||||||
|
|||||||
@ -50,7 +50,10 @@ if (Deno.args.includes("--print-mir")) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// const result = selectFnInstructions(mainMiddleFn);
|
const result = selectFnInstructions(mainMiddleFn);
|
||||||
|
stringify.printWithConsoleColors(
|
||||||
|
stringify.x86_64FnPretty(result, stringify.consoleColors),
|
||||||
|
);
|
||||||
// console.log(JSON.stringify(result, null, 4));
|
// console.log(JSON.stringify(result, null, 4));
|
||||||
|
|
||||||
if (!reporter.ok()) {
|
if (!reporter.ok()) {
|
||||||
|
|||||||
109
src/stringify.ts
109
src/stringify.ts
@ -1,5 +1,6 @@
|
|||||||
import * as ty from "./ty.ts";
|
import * as ty from "./ty.ts";
|
||||||
import * as mir from "./mir.ts";
|
import * as mir from "./mir.ts";
|
||||||
|
import * as codegenX8664 from "./codegen/x86_64/module.ts";
|
||||||
|
|
||||||
export type PrettyColors = {
|
export type PrettyColors = {
|
||||||
punctuation: string;
|
punctuation: string;
|
||||||
@ -336,3 +337,111 @@ class MirFnPrettyStringifier {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function x86_64FnPretty(fn: codegenX8664.Fn, colors = noColors): string {
|
||||||
|
const c = colors;
|
||||||
|
const blockIds = new Map<codegenX8664.Block, number>();
|
||||||
|
|
||||||
|
const reg = (reg: codegenX8664.Reg): string => {
|
||||||
|
const cl = c.typeIdent;
|
||||||
|
switch (reg.id) {
|
||||||
|
case codegenX8664.Regs.a:
|
||||||
|
return `${cl}rax`;
|
||||||
|
case codegenX8664.Regs.b:
|
||||||
|
return `${cl}rbx`;
|
||||||
|
case codegenX8664.Regs.c:
|
||||||
|
return `${cl}rbc`;
|
||||||
|
case codegenX8664.Regs.si:
|
||||||
|
return `${cl}rsi`;
|
||||||
|
case codegenX8664.Regs.di:
|
||||||
|
return `${cl}rdi`;
|
||||||
|
case codegenX8664.Regs.sp:
|
||||||
|
return `${cl}rsp`;
|
||||||
|
case codegenX8664.Regs.bp:
|
||||||
|
return `${cl}rbp`;
|
||||||
|
case codegenX8664.Regs.r8:
|
||||||
|
return `${cl}r8`;
|
||||||
|
case codegenX8664.Regs.r9:
|
||||||
|
return `${cl}r9`;
|
||||||
|
case codegenX8664.Regs.r10:
|
||||||
|
return `${cl}r10`;
|
||||||
|
case codegenX8664.Regs.r11:
|
||||||
|
return `${cl}r11`;
|
||||||
|
case codegenX8664.Regs.r12:
|
||||||
|
return `${cl}r12`;
|
||||||
|
case codegenX8664.Regs.r13:
|
||||||
|
return `${cl}r13`;
|
||||||
|
case codegenX8664.Regs.r14:
|
||||||
|
return `${cl}r14`;
|
||||||
|
case codegenX8664.Regs.r15:
|
||||||
|
return `${cl}r15`;
|
||||||
|
default:
|
||||||
|
return `${c.varIdent}%${reg.id - 1000}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const imm = (v: number): string => {
|
||||||
|
return `${c.literal}${v}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const mem = (r: codegenX8664.Reg, off: number): string => {
|
||||||
|
return `${c.keyword}qword ${c.punctuation}[${reg(r)}${c.punctuation}${
|
||||||
|
off !== 0 ? `-${c.literal}${-off}${c.punctuation}` : ""
|
||||||
|
}]`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const line = (op: string, ...ops: string[]): string => {
|
||||||
|
return ` ${c.operator}${op} ${ops.join(", ")}\n`;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const block of fn.blocks) {
|
||||||
|
const id = blockIds.size;
|
||||||
|
blockIds.set(block, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = "";
|
||||||
|
result += `${c.fnIdent}${fn.mirFn.stmt.kind.ident}${c.punctuation}:\n`;
|
||||||
|
for (const block of fn.blocks) {
|
||||||
|
const id = blockIds.get(block)!;
|
||||||
|
result += `${c.varIdent}.l${id}${c.punctuation}:\n`;
|
||||||
|
for (const inst of block.insts) {
|
||||||
|
const k = inst.kind;
|
||||||
|
switch (k.tag) {
|
||||||
|
case "PushR":
|
||||||
|
result += line("push", reg(k.src));
|
||||||
|
break;
|
||||||
|
case "PopR":
|
||||||
|
result += line("pop", reg(k.dst));
|
||||||
|
break;
|
||||||
|
case "MovRR":
|
||||||
|
result += line("mov", reg(k.dst), reg(k.src));
|
||||||
|
break;
|
||||||
|
case "SubRI":
|
||||||
|
result += line("sub", reg(k.dst), imm(k.imm));
|
||||||
|
break;
|
||||||
|
case "MovRI":
|
||||||
|
result += line("mov", reg(k.dst), imm(k.imm));
|
||||||
|
break;
|
||||||
|
case "MovMRR":
|
||||||
|
result += line("mov", mem(k.dst, k.offset), reg(k.src));
|
||||||
|
break;
|
||||||
|
case "MovRMR":
|
||||||
|
result += line("mov", reg(k.dst), mem(k.src, k.offset));
|
||||||
|
break;
|
||||||
|
case "AddR":
|
||||||
|
result += line("add", reg(k.dst_op1), reg(k.op2));
|
||||||
|
break;
|
||||||
|
case "Jmp":
|
||||||
|
result += line(
|
||||||
|
"jmp",
|
||||||
|
`${c.varIdent}.l${blockIds.get(k.bb)!}`,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "Ret":
|
||||||
|
result += line("ret");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user