This commit is contained in:
parent
ca6e9d1656
commit
bfac7bb765
@ -1,4 +1,134 @@
|
|||||||
import * as mir from "../../mir.ts";
|
import * as mir from "../../mir.ts";
|
||||||
|
import { Block, Fn, Inst, Reg, Regs } from "./module.ts";
|
||||||
|
|
||||||
export function selectFnInstructions(fn: mir.Fn) {
|
export function selectFnInstructions(fn: mir.Fn): Fn {
|
||||||
|
return new InstructionSelector(fn).generateFn();
|
||||||
|
}
|
||||||
|
|
||||||
|
class InstructionSelector {
|
||||||
|
private localsSize = 0;
|
||||||
|
private locals = new Map<mir.Inst, number>();
|
||||||
|
private exitBlock!: Block;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private fn: mir.Fn,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
generateFn(): Fn {
|
||||||
|
this.generateFrameLayout();
|
||||||
|
|
||||||
|
const entry = new Block();
|
||||||
|
const exit = new Block();
|
||||||
|
|
||||||
|
entry.push(new Inst({ tag: "PushR", src: Reg.reg(Regs.bp) }));
|
||||||
|
entry.push(
|
||||||
|
new Inst({
|
||||||
|
tag: "MovRR",
|
||||||
|
dst: Reg.reg(Regs.bp),
|
||||||
|
src: Reg.reg(Regs.sp),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
entry.push(
|
||||||
|
new Inst({
|
||||||
|
tag: "SubRI",
|
||||||
|
dst: Reg.reg(Regs.sp),
|
||||||
|
imm: this.localsSize,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.exitBlock = exit;
|
||||||
|
|
||||||
|
const blocks: Block[] = [];
|
||||||
|
for (const bb of this.fn.bbs) {
|
||||||
|
blocks.push(this.generateBasicBlock(bb));
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.push(new Inst({ tag: "Jmp", bb: blocks[0] ?? exit }));
|
||||||
|
|
||||||
|
exit.push(
|
||||||
|
new Inst({
|
||||||
|
tag: "MovRR",
|
||||||
|
dst: Reg.reg(Regs.sp),
|
||||||
|
src: Reg.reg(Regs.bp),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
entry.push(new Inst({ tag: "PopR", dst: Reg.reg(Regs.bp) }));
|
||||||
|
entry.push(new Inst({ tag: "Ret" }));
|
||||||
|
|
||||||
|
return new Fn([entry, ...blocks, exit]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateFrameLayout() {
|
||||||
|
let offset = 0;
|
||||||
|
|
||||||
|
const align = (alignment: number) => {
|
||||||
|
if (offset % alignment != 0) {
|
||||||
|
offset += alignment - offset % alignment;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const pushLocal = (inst: mir.Inst, size: number, alignment: number) => {
|
||||||
|
align(alignment);
|
||||||
|
this.locals.set(inst, offset);
|
||||||
|
offset += size;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.fn.visit({
|
||||||
|
visitInst(inst) {
|
||||||
|
if (inst.kind.tag === "Alloca") {
|
||||||
|
const ty = inst.ty.as("PtrMut").kind.ty;
|
||||||
|
switch (ty.kind.tag) {
|
||||||
|
case "Int": {
|
||||||
|
switch (ty.kind.intTy) {
|
||||||
|
case "i32":
|
||||||
|
pushLocal(inst, 4, 4);
|
||||||
|
break;
|
||||||
|
case "i64":
|
||||||
|
pushLocal(inst, 8, 8);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(
|
||||||
|
`not implemented (${ty.kind.intTy})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error(
|
||||||
|
`not implemented (${ty.kind.tag})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
align(16);
|
||||||
|
|
||||||
|
this.localsSize = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateBasicBlock(bb: mir.BasicBlock): Block {
|
||||||
|
const block = new Block();
|
||||||
|
for (const inst of bb.insts) {
|
||||||
|
const k = inst.kind;
|
||||||
|
switch (k.tag) {
|
||||||
|
case "Alloca":
|
||||||
|
break;
|
||||||
|
case "Int":
|
||||||
|
block.push(
|
||||||
|
new Inst({
|
||||||
|
tag: "MovRI",
|
||||||
|
dst: Reg.reg(Regs.bp),
|
||||||
|
imm: k.value,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// throw new Error(
|
||||||
|
// `not implemented (${k.tag})`,
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,9 @@ export class Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Fn {
|
export class Fn {
|
||||||
private blocks: Block[] = [];
|
constructor(
|
||||||
|
private blocks: Block[] = [],
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Block {
|
export class Block {
|
||||||
@ -15,6 +17,9 @@ export class Block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Inst {
|
export class Inst {
|
||||||
|
constructor(
|
||||||
|
public kind: InstKind,
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type InstKind =
|
export type InstKind =
|
||||||
@ -26,7 +31,7 @@ export type InstKind =
|
|||||||
| { tag: "MovMRR"; dst: Reg; offset: number; src: Reg }
|
| { tag: "MovMRR"; dst: Reg; offset: number; src: Reg }
|
||||||
| { tag: "MovRMR"; dst: Reg; src: Reg; offset: number }
|
| { tag: "MovRMR"; dst: Reg; src: Reg; offset: number }
|
||||||
| { tag: "AddR"; dst_op1: Reg; op2: Reg }
|
| { tag: "AddR"; dst_op1: Reg; op2: Reg }
|
||||||
| { tag: "Jmp"; bb: number }
|
| { tag: "Jmp"; bb: Block }
|
||||||
| { tag: "Ret" };
|
| { tag: "Ret" };
|
||||||
|
|
||||||
export class Reg {
|
export class Reg {
|
||||||
|
|||||||
@ -107,7 +107,7 @@ class TypeChecker {
|
|||||||
);
|
);
|
||||||
this.reporter.info(
|
this.reporter.info(
|
||||||
this.fn.kind.retTy?.loc ?? this.fn.loc,
|
this.fn.kind.retTy?.loc ?? this.fn.loc,
|
||||||
`return type '${retTy}' defined here`,
|
`return type '${retTy.pretty()}' defined here`,
|
||||||
);
|
);
|
||||||
this.reporter.abort();
|
this.reporter.abort();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import * as ast from "./ast.ts";
|
import * as ast from "./ast.ts";
|
||||||
|
import { selectFnInstructions } from "./codegen/x86_64/isel.ts";
|
||||||
import { Reporter } from "./diagnostics.ts";
|
import { Reporter } from "./diagnostics.ts";
|
||||||
import * as front from "./front/mod.ts";
|
import * as front from "./front/mod.ts";
|
||||||
import * as middle from "./middle.ts";
|
import * as middle from "./middle.ts";
|
||||||
@ -49,6 +50,9 @@ if (Deno.args.includes("--print-mir")) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// const result = selectFnInstructions(mainMiddleFn);
|
||||||
|
// console.log(JSON.stringify(result, null, 4));
|
||||||
|
|
||||||
if (!reporter.ok()) {
|
if (!reporter.ok()) {
|
||||||
reporter.printAll();
|
reporter.printAll();
|
||||||
Deno.exit(1);
|
Deno.exit(1);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user