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;
|
||||
}
|
||||
|
||||
fn main()
|
||||
{
|
||||
let sum = add(2, 3);
|
||||
print_int(sum);
|
||||
print_int(2 - 3);
|
||||
let a = 2;
|
||||
let b = a + 5;
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -52,10 +52,10 @@ class InstructionSelector {
|
||||
src: Reg.reg(Regs.bp),
|
||||
}),
|
||||
);
|
||||
entry.push(new Inst({ tag: "PopR", dst: Reg.reg(Regs.bp) }));
|
||||
entry.push(new Inst({ tag: "Ret" }));
|
||||
exit.push(new Inst({ tag: "PopR", dst: Reg.reg(Regs.bp) }));
|
||||
exit.push(new Inst({ tag: "Ret" }));
|
||||
|
||||
return new Fn([entry, ...blocks, exit]);
|
||||
return new Fn(this.fn, [entry, ...blocks, exit]);
|
||||
}
|
||||
|
||||
private generateFrameLayout() {
|
||||
@ -63,14 +63,14 @@ class InstructionSelector {
|
||||
|
||||
const align = (alignment: number) => {
|
||||
if (offset % alignment != 0) {
|
||||
offset += alignment - offset % alignment;
|
||||
offset -= alignment + offset % alignment;
|
||||
}
|
||||
};
|
||||
|
||||
const pushLocal = (inst: mir.Inst, size: number, alignment: number) => {
|
||||
align(alignment);
|
||||
this.locals.set(inst, offset);
|
||||
offset += size;
|
||||
offset -= size;
|
||||
};
|
||||
|
||||
this.fn.visit({
|
||||
@ -102,28 +102,93 @@ class InstructionSelector {
|
||||
},
|
||||
});
|
||||
|
||||
// c abi requires 16 bit stack alignment,
|
||||
// might aswell do it here.
|
||||
align(16);
|
||||
|
||||
this.localsSize = offset;
|
||||
this.localsSize = -offset;
|
||||
}
|
||||
|
||||
private generateBasicBlock(bb: mir.BasicBlock): Block {
|
||||
const regs = new Map<mir.Inst, Reg>();
|
||||
|
||||
const block = new Block();
|
||||
for (const inst of bb.insts) {
|
||||
const save = (r: Reg): Reg => {
|
||||
regs.set(inst, r);
|
||||
return r;
|
||||
};
|
||||
|
||||
const k = inst.kind;
|
||||
switch (k.tag) {
|
||||
case "Alloca":
|
||||
save(Reg.temp());
|
||||
break;
|
||||
case "Void":
|
||||
block.push(
|
||||
new Inst({
|
||||
tag: "MovRI",
|
||||
dst: save(Reg.temp()),
|
||||
imm: 0,
|
||||
}),
|
||||
);
|
||||
break;
|
||||
case "Int":
|
||||
block.push(
|
||||
new Inst({
|
||||
tag: "MovRI",
|
||||
dst: Reg.reg(Regs.bp),
|
||||
dst: save(Reg.temp()),
|
||||
imm: k.value,
|
||||
}),
|
||||
);
|
||||
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:
|
||||
console.error(`not implemented (${k.tag})`);
|
||||
// throw new Error(
|
||||
// `not implemented (${k.tag})`,
|
||||
// );
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
import * as mir from "../../mir.ts";
|
||||
|
||||
export class Module {
|
||||
private fns: Fn[] = [];
|
||||
}
|
||||
|
||||
export class Fn {
|
||||
constructor(
|
||||
private blocks: Block[] = [],
|
||||
public mirFn: mir.Fn,
|
||||
public blocks: Block[] = [],
|
||||
) {}
|
||||
}
|
||||
|
||||
export class Block {
|
||||
private insts: Inst[] = [];
|
||||
public insts: Inst[] = [];
|
||||
|
||||
push(inst: Inst) {
|
||||
this.insts.push(inst);
|
||||
@ -38,7 +41,7 @@ export class Reg {
|
||||
static tempId = 1000;
|
||||
|
||||
private constructor(
|
||||
private id: number,
|
||||
public id: number,
|
||||
) {}
|
||||
|
||||
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));
|
||||
|
||||
if (!reporter.ok()) {
|
||||
|
||||
109
src/stringify.ts
109
src/stringify.ts
@ -1,5 +1,6 @@
|
||||
import * as ty from "./ty.ts";
|
||||
import * as mir from "./mir.ts";
|
||||
import * as codegenX8664 from "./codegen/x86_64/module.ts";
|
||||
|
||||
export type PrettyColors = {
|
||||
punctuation: string;
|
||||
@ -336,3 +337,111 @@ class MirFnPrettyStringifier {
|
||||
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