A "high-level" language for the Gameboy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
1.9 KiB

  1. import type { AssignStmt, Expr, Stmt } from "../ast"
  2. import { Loc } from "./loc"
  3. import type { Operand, SSA } from "./ssa"
  4. type IRState = {
  5. nextID: number
  6. ssa_stmts: Array<SSA>
  7. }
  8. export const convertIR = (stmts: Array<Stmt>): Array<SSA> => {
  9. const state: IRState = {
  10. nextID: 0,
  11. ssa_stmts: [],
  12. }
  13. stmts.forEach(stmt => {
  14. const ssa_stmts = convertAssignStmt(state, stmt)
  15. state.ssa_stmts.push(...ssa_stmts)
  16. })
  17. return state.ssa_stmts
  18. }
  19. export const convertAssignStmt = (state: IRState, stmt: AssignStmt): Array<SSA> => {
  20. return convertExpr(state, Loc.vari(stmt.args.name), stmt.args.expr)
  21. }
  22. export const convertExpr = (state: IRState, dest: Loc, expr: Expr): Array<SSA> => {
  23. let expr_stmts: Array<SSA> = []
  24. if (typeof expr === "number") {
  25. expr_stmts = [{ dest, source: expr }]
  26. } else if (typeof expr === "string") {
  27. expr_stmts = [{ dest, source: Loc.vari(expr) }]
  28. } else if (expr.type === "unary") {
  29. const [source, stmts] = getSource(state, expr.arg)
  30. stmts.push({
  31. dest,
  32. op: expr.op,
  33. source,
  34. })
  35. expr_stmts = stmts
  36. } else {
  37. const [left_source, left_stmts] = getSource(state, expr.left)
  38. const [right_source, right_stmts] = getSource(state, expr.right)
  39. const stmts = [...left_stmts, ...right_stmts]
  40. stmts.push({
  41. dest,
  42. op: expr.op,
  43. source: left_source,
  44. source1: right_source,
  45. })
  46. expr_stmts = stmts
  47. }
  48. return expr_stmts
  49. }
  50. const getSource = (state: IRState, expr: Expr): [Operand, Array<SSA>] => {
  51. if (typeof expr === "number") {
  52. return [expr, []]
  53. } else if (typeof expr === "string") {
  54. return [Loc.vari(expr), []]
  55. }
  56. const source = Loc.temp(`t${state.nextID++}`)
  57. const stmts = convertExpr(state, source, expr)
  58. return [source, stmts]
  59. }