Browse Source

Reduce IR to two-address code

master
Forest Belton 2 years ago
parent
commit
d245d2d992
7 changed files with 36 additions and 51 deletions
  1. +5
    -5
      lib/ir/convert.ts
  2. +2
    -2
      lib/ir/pretty.ts
  3. +4
    -2
      lib/ir/ssa.d.ts
  4. +0
    -8
      lib/regalloc.ts
  5. +19
    -28
      lib/sm83/codegen.ts
  6. +2
    -2
      test/ir/pretty.spec.ts
  7. +4
    -4
      test/regalloc.spec.ts

+ 5
- 5
lib/ir/convert.ts View File

@ -1,7 +1,7 @@
import type { AssignStmt, Expr, Stmt } from "../ast"
import { R8 } from "../sm83/cpu"
import { Loc, LocType } from "./loc"
import type { Operand, SSA } from "./ssa"
import type { Operand, SSA, SSAWithBinary } from "./ssa"
type IRState = {
nextID: number
@ -47,7 +47,7 @@ export const convertExpr = (state: IRState, dest: Loc, expr: Expr): Array =
output.push(
{ dest: Loc.reg(R8.A), source: ssa.source },
{ dest: Loc.reg(R8.A), source: Loc.reg(R8.A), op: ssa.op, source1 },
{ dest: Loc.reg(R8.A), op: ssa.op, source: source1 },
{ dest: ssa.dest, source: Loc.reg(R8.A) },
)
} else {
@ -62,8 +62,8 @@ export const convertExpr = (state: IRState, dest: Loc, expr: Expr): Array =
return output
}
export const convertExpr3 = (state: IRState, dest: Loc, expr: Expr): Array<SSA> => {
let expr_stmts: Array<SSA> = []
export const convertExpr3 = (state: IRState, dest: Loc, expr: Expr): Array<SSAWithBinary> => {
let expr_stmts: Array<SSAWithBinary> = []
if (typeof expr === "number") {
expr_stmts = [{ dest, source: expr }]
@ -96,7 +96,7 @@ export const convertExpr3 = (state: IRState, dest: Loc, expr: Expr): Array
return expr_stmts
}
const getSource = (state: IRState, expr: Expr): [Operand, Array<SSA>] => {
const getSource = (state: IRState, expr: Expr): [Operand, Array<SSAWithBinary>] => {
if (typeof expr === "number") {
return [expr, []]
} else if (typeof expr === "string") {

+ 2
- 2
lib/ir/pretty.ts View File

@ -1,11 +1,11 @@
import type { Loc } from "./loc"
import type { Operand, SSA } from "./ssa"
import type { Operand, SSA, SSAWithBinary } from "./ssa"
export const prettyPrintBlock = (block: Array<SSA>): string => {
return block.map(prettyPrintSSA).join("\n")
}
export const prettyPrintSSA = (ssa: SSA): string => {
export const prettyPrintSSA = (ssa: SSAWithBinary): string => {
let output = ""
if ("source1" in ssa) {

+ 4
- 2
lib/ir/ssa.d.ts View File

@ -9,9 +9,11 @@ type ASSA = { dest: Loc, source: Operand } & Data
export type SSACopy = ASSA<{}>
// dest = op(source)
export type SSAUnary = ASSA<{ op: UnaryOp }>
export type SSAUnary = ASSA<{ op: UnaryOp | BinaryOp }>
// dest = op(source, source1)
export type SSABinary = ASSA<{ op: BinaryOp, source1: Operand }>
export type SSA = SSACopy | SSAUnary | SSABinary
export type SSA = SSACopy | SSAUnary
export type SSAWithBinary = SSA | SSABinary

+ 0
- 8
lib/regalloc.ts View File

@ -19,10 +19,6 @@ export const liveness = (block: Array): LivenessInfo => {
info[i].add(insn.source)
}
if ("source1" in insn && typeof insn.source1 !== "number") {
info[i].add(insn.source1)
}
last.forEach(loc => {
if (loc.toString() === insn.dest.toString()) {
return
@ -44,10 +40,6 @@ export const locations = (block: Array): Set => {
if (typeof ssa.source !== "number") {
ls.add(ssa.source)
}
if ("source1" in ssa && typeof ssa.source1 !== "number") {
ls.add(ssa.source1)
}
})
return ls

+ 19
- 28
lib/sm83/codegen.ts View File

@ -2,7 +2,7 @@ import { R8 } from "../sm83/cpu"
import { Loc, LocType } from "../ir/loc"
import type { Operand, SSA, SSABinary, SSACopy, SSAUnary } from "../ir/ssa"
import type { RegAlloc } from "../regalloc"
import { UnaryOp } from "../ast"
import { BinaryOp, UnaryOp } from "../ast"
export const generateBlock = (alloc: RegAlloc, block: Array<SSA>): Array<string> => {
const output: Array<string> = []
@ -17,9 +17,7 @@ export const generateBlock = (alloc: RegAlloc, block: Array): Array
export const generateSSA = (alloc: RegAlloc, ssa: SSA): Array<string> => {
let output: Array<string> = []
if ("source1" in ssa) {
output = generateSSA_Binary(alloc, ssa)
} else if ("op" in ssa) {
if ("op" in ssa) {
output = generateSSA_Unary(alloc, ssa)
} else {
output = generateSSA_Copy(alloc, ssa)
@ -83,40 +81,33 @@ export const generateSSA_Unary = (alloc: RegAlloc, ssa: SSAUnary): Array
throw new Error("Unexpected form for unary operation")
}
const output: Array<string> = []
if (typeof ssa.source === "number") {
output.push(`LD A, ${ssa.source}`)
} else if (ssa.source.type === LocType.REGISTER) {
if (!isA(ssa.dest)) {
output.push(`LD A, ${ssa.source.name}`)
}
} else {
// TODO: ??
output.push(`LD A, ${alloc[ssa.source.toString()]}`)
}
const source = typeof ssa.source === 'number'
? ssa.source.toString()
: getAlloc(alloc, ssa.source).name
const ops = unaryOps[ssa.op]
if (!ops) {
throw new Error(`unsupported unary op \`${ssa.op}'`)
}
switch (ssa.op) {
case "add":
return [`ADD ${source}`]
return output.concat(ops)
}
case "arith_negate":
return ["CPL", "INC A"]
const unaryOps = {
"arith_negate": ["CPL", "INC A"],
"bit_negate": ["CPL"]
case "bit_negate":
return ["CPL"]
default:
throw new Error(`unsupported unary op \`${ssa.op}'`)
}
}
/*
export const generateSSA_Binary = (alloc: RegAlloc, ssa: SSABinary): Array<string> => {
if (!isA(ssa.dest) || !isA(ssa.source)) {
throw new Error("Unexpected form for binary operation")
}
const output: Array<string> = []
const source = typeof ssa.source1 === 'number'
? ssa.source1
: getAlloc(alloc, ssa.source1).name
switch (ssa.op) {
case "add":
@ -128,7 +119,7 @@ export const generateSSA_Binary = (alloc: RegAlloc, ssa: SSABinary): Array
}
return output
}
} */
const isA = (loc: Operand): boolean =>
typeof loc === "object" && loc.type === LocType.REGISTER && loc.name === R8.A

+ 2
- 2
test/ir/pretty.spec.ts View File

@ -2,7 +2,7 @@ import { expect } from "chai"
import { Loc } from "../../lib/ir/loc"
import { prettyPrintSSA } from "../../lib/ir/pretty"
import type { SSA } from "../../lib/ir/ssa"
import type { SSA, SSAWithBinary } from "../../lib/ir/ssa"
describe("ir", () => {
describe("prettyPrintSSA", () => {
@ -53,7 +53,7 @@ describe("ir", () => {
})
it("binary op", () => {
const ssa: SSA = {
const ssa: SSAWithBinary = {
dest: Loc.vari("x"),
source: Loc.vari("y"),
source1: 42,

+ 4
- 4
test/regalloc.spec.ts View File

@ -13,10 +13,10 @@ describe("liveness", () => {
const block: Array<SSA> = [
{ dest: x[0], source: 1 },
{ dest: x[1], source: x[0], op: "add", source1: x[0] },
{ dest: x[2], source: x[1], op: "add", source1: x[0] },
{ dest: y[0], source: x[0], op: "add", source1: x[1] },
{ dest: y[1], source: y[0], op: "add", source1: x[2] },
{ dest: x[1], source: x[0], op: "add" },
{ dest: x[2], source: x[1], op: "add" },
{ dest: y[0], source: x[0], op: "add" },
{ dest: y[1], source: y[0], op: "add" },
]
const info = liveness(block)

Loading…
Cancel
Save