|
@ -1,18 +1,24 @@ |
|
|
import type { AssignStmt, Expr, Stmt } from "../ast" |
|
|
import type { AssignStmt, Expr, Stmt } from "../ast" |
|
|
import { R8 } from "../sm83/cpu" |
|
|
import { R8 } from "../sm83/cpu" |
|
|
import { Loc, LocType } from "./loc" |
|
|
import { Loc, LocType } from "./loc" |
|
|
import type { Operand, AbsInsn2, AbsInsn3 } from "./insn" |
|
|
|
|
|
|
|
|
import { Operand, AbsInsn2, AbsInsn3, CopyInsn, UnaryInsn, BinaryInsn } from "./insn" |
|
|
|
|
|
|
|
|
export type IRState = { |
|
|
|
|
|
|
|
|
export class IRState { |
|
|
nextID: number |
|
|
nextID: number |
|
|
insns: Array<AbsInsn2> |
|
|
insns: Array<AbsInsn2> |
|
|
|
|
|
|
|
|
|
|
|
constructor() { |
|
|
|
|
|
this.nextID = 0 |
|
|
|
|
|
this.insns = [] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
temp(): Loc { |
|
|
|
|
|
return Loc.temp(`t${this.nextID++}`) |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
export const convertIR = (stmts: Array<Stmt>): Array<AbsInsn2> => { |
|
|
export const convertIR = (stmts: Array<Stmt>): Array<AbsInsn2> => { |
|
|
const state: IRState = { |
|
|
|
|
|
nextID: 0, |
|
|
|
|
|
insns: [], |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
const state: IRState = new IRState() |
|
|
|
|
|
|
|
|
stmts.forEach(stmt => { |
|
|
stmts.forEach(stmt => { |
|
|
convertAssignStmt(state, stmt) |
|
|
convertAssignStmt(state, stmt) |
|
@ -36,26 +42,26 @@ export const convertExpr = (state: IRState, dest: Loc, expr: Expr): void => { |
|
|
|
|
|
|
|
|
case 'unary': |
|
|
case 'unary': |
|
|
state.insns.push( |
|
|
state.insns.push( |
|
|
{ type: "copy", dest: Loc.reg(R8.A), source: ssa.source }, |
|
|
|
|
|
{ type: "unary", dest: Loc.reg(R8.A), source: Loc.reg(R8.A), op: ssa.op }, |
|
|
|
|
|
{ type: "copy", dest: ssa.dest, source: Loc.reg(R8.A) }, |
|
|
|
|
|
|
|
|
CopyInsn(Loc.reg(R8.A), ssa.source), |
|
|
|
|
|
UnaryInsn(Loc.reg(R8.A), ssa.op, Loc.reg(R8.A)), |
|
|
|
|
|
CopyInsn(ssa.dest, Loc.reg(R8.A)), |
|
|
) |
|
|
) |
|
|
break |
|
|
break |
|
|
|
|
|
|
|
|
case 'binary': |
|
|
case 'binary': |
|
|
let source1 = ssa.source1 |
|
|
let source1 = ssa.source1 |
|
|
if (typeof source1 !== 'number' && source1.type === LocType.VARIABLE) { |
|
|
if (typeof source1 !== 'number' && source1.type === LocType.VARIABLE) { |
|
|
source1 = Loc.temp(`t${state.nextID++}`) |
|
|
|
|
|
|
|
|
source1 = state.temp() |
|
|
state.insns.push( |
|
|
state.insns.push( |
|
|
{ type: "copy", dest: Loc.reg(R8.A), source: ssa.source1 }, |
|
|
|
|
|
{ type: "copy", dest: source1, source: Loc.reg(R8.A) }, |
|
|
|
|
|
|
|
|
CopyInsn(Loc.reg(R8.A), ssa.source1), |
|
|
|
|
|
CopyInsn(source1, Loc.reg(R8.A)), |
|
|
) |
|
|
) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
state.insns.push( |
|
|
state.insns.push( |
|
|
{ type: "copy", dest: Loc.reg(R8.A), source: ssa.source }, |
|
|
|
|
|
{ type: "unary", dest: Loc.reg(R8.A), op: ssa.op, source: source1 }, |
|
|
|
|
|
{ type: "copy", dest: ssa.dest, source: Loc.reg(R8.A) }, |
|
|
|
|
|
|
|
|
CopyInsn(Loc.reg(R8.A), ssa.source), |
|
|
|
|
|
UnaryInsn(Loc.reg(R8.A), ssa.op, source1), |
|
|
|
|
|
CopyInsn(ssa.dest, Loc.reg(R8.A)), |
|
|
) |
|
|
) |
|
|
break |
|
|
break |
|
|
} |
|
|
} |
|
@ -65,47 +71,30 @@ export const convertExpr = (state: IRState, dest: Loc, expr: Expr): void => { |
|
|
export const convertExpr3 = (state: IRState, dest: Loc, expr: Expr): Array<AbsInsn3> => { |
|
|
export const convertExpr3 = (state: IRState, dest: Loc, expr: Expr): Array<AbsInsn3> => { |
|
|
let expr_stmts: Array<AbsInsn3> = [] |
|
|
let expr_stmts: Array<AbsInsn3> = [] |
|
|
|
|
|
|
|
|
|
|
|
const getSource = (expr: Expr): [Operand, Array<AbsInsn3>] => { |
|
|
|
|
|
if (typeof expr === "number") { |
|
|
|
|
|
return [expr, []] |
|
|
|
|
|
} else if (typeof expr === "string") { |
|
|
|
|
|
return [Loc.vari(expr), []] |
|
|
|
|
|
} |
|
|
|
|
|
const source = state.temp() |
|
|
|
|
|
const stmts = convertExpr3(state, source, expr) |
|
|
|
|
|
return [source, stmts] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (typeof expr === "number") { |
|
|
if (typeof expr === "number") { |
|
|
expr_stmts = [{ type: "copy", dest, source: expr }] |
|
|
|
|
|
|
|
|
expr_stmts.push(CopyInsn(dest, expr)) |
|
|
} else if (typeof expr === "string") { |
|
|
} else if (typeof expr === "string") { |
|
|
expr_stmts = [{ type: "copy", dest, source: Loc.vari(expr) }] |
|
|
|
|
|
|
|
|
expr_stmts.push(CopyInsn(dest, Loc.vari(expr))) |
|
|
} else if (expr.type === "unary") { |
|
|
} else if (expr.type === "unary") { |
|
|
const [source, stmts] = getSource(state, expr.arg) |
|
|
|
|
|
stmts.push({ |
|
|
|
|
|
type: "unary", |
|
|
|
|
|
dest, |
|
|
|
|
|
op: expr.op, |
|
|
|
|
|
source, |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const [source, stmts] = getSource(expr.arg) |
|
|
|
|
|
stmts.push(UnaryInsn(dest, expr.op, source)) |
|
|
expr_stmts = stmts |
|
|
expr_stmts = stmts |
|
|
} else { |
|
|
} else { |
|
|
const [left_source, left_stmts] = getSource(state, expr.left) |
|
|
|
|
|
const [right_source, right_stmts] = getSource(state, expr.right) |
|
|
|
|
|
|
|
|
|
|
|
const stmts = [...left_stmts, ...right_stmts] |
|
|
|
|
|
stmts.push({ |
|
|
|
|
|
type: "binary", |
|
|
|
|
|
dest, |
|
|
|
|
|
op: expr.op, |
|
|
|
|
|
source: left_source, |
|
|
|
|
|
source1: right_source, |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
expr_stmts = stmts |
|
|
|
|
|
|
|
|
const [left_source, left_stmts] = getSource(expr.left) |
|
|
|
|
|
const [right_source, right_stmts] = getSource(expr.right) |
|
|
|
|
|
expr_stmts = [...left_stmts, ...right_stmts, BinaryInsn(dest, left_source, expr.op, right_source)] |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return expr_stmts |
|
|
return expr_stmts |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const getSource = (state: IRState, expr: Expr): [Operand, Array<AbsInsn3>] => { |
|
|
|
|
|
if (typeof expr === "number") { |
|
|
|
|
|
return [expr, []] |
|
|
|
|
|
} else if (typeof expr === "string") { |
|
|
|
|
|
return [Loc.vari(expr), []] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const source = Loc.temp(`t${state.nextID++}`) |
|
|
|
|
|
const stmts = convertExpr3(state, source, expr) |
|
|
|
|
|
return [source, stmts] |
|
|
|
|
|
} |
|
|
|