Commit fbf8978a authored by Sapphie's avatar Sapphie
Browse files

Implement other translations

parent 7906bafb
......@@ -8,14 +8,109 @@ import l3.{CPSTestPrimitive => CPST}
object CPSValueRepresenter extends (H.Tree => L.Tree) {
def apply(tree: H.Tree): L.Tree = tree match {
case H.LetP(n, prim, Seq(x, y), body) => applyLetPBin(n, prim, x, y, body)
case _ => ???
case H.LetP(n, prim, Seq(x), body) => applyLetPUnary(n, prim, x, body)
case H.LetP(n, prim, Seq(x, y), body) => applyLetPBinary(n, prim, x, y, body)
case H.LetP(n, prim, Seq(x, y, z), body) => applyLetPTernary(n, prim, x, y, z, body)
case H.LetF(funs, body) =>
val lFuns = funs.map(f => L.Fun(f.name, f.retC, f.args, apply(f.body)))
L.LetF(lFuns, apply(body))
case H.LetC(cnts, body) =>
val lCnts = cnts.map(c => L.Cnt(c.name, c.args, apply(c.body)))
L.LetC(lCnts, apply(body))
case H.AppF(fun, retC, args) =>
// Assuming a function is just a pointer to its first instruction
val lFun = rewrite(fun)
val lArgs = args.map(rewrite)
L.AppF(lFun, retC, lArgs)
case H.AppC(cnt, args) =>
val lArgs = args.map(rewrite)
L.AppC(cnt, lArgs)
case H.If(cond, args, thenC, elseC) =>
transformIf(cond, args, thenC, elseC)
case _ => throw new Exception(tree.getClass.toString)
}
// Transforms primitives that take 2 arguments
private def applyLetPBin(n: H.Name, prim: L3, x: H.Atom, y: H.Atom, body: H.Tree): L.LetP = {
private def transformIf(cond: L3, args: Seq[H.Atom], thenC: H.Name, elseC: H.Name): L.Tree = {
def maskAndCheck(numBits: Int, target: Bits32): L.LetP = {
val Seq(x) = args
tempLetP(CPS.And, Seq(Left(x), getMaskR(numBits))) { x1 =>
L.If(CPST.Eq, Seq(x1, L.AtomL(target)), thenC, elseC)
}
}
cond match {
case L3.BlockP =>
maskAndCheck(2, 0x0)
case L3.IntP =>
maskAndCheck(1, 0x1)
case L3.BoolP =>
maskAndCheck(4, 0xa)
case L3.UnitP =>
maskAndCheck(4, 0x2)
case L3.CharP =>
maskAndCheck(3, 0x6)
case L3.Eq =>
L.If(CPST.Eq, args.map(rewrite), thenC, elseC)
}
}
private def getMaskR(numBits: Int): Either[H.Atom, L.Atom] = Right(L.AtomL((1 << numBits) -1))
// Only to be used in cases where you can be reasonably sure you're
// dealing with integers
private def lit2Int(l: CL3Literal): Int = {
l match {
case IntLit(i) => i.toInt
case _ => 0
}
}
/*
private def addrConv(x: H.Atom): L.Atom = {
x match {
case H.AtomL(l) => L.AtomL(lit2Int(l))
case H.AtomN(n) => L.AtomN(n)
}
}
// */
// In hindsight, splitting the functions wasn't the cleanest decision
// TODO: refactor
// Transforms value primitives that take a single argument
private def applyLetPUnary(n: H.Name, prim: L3, x: H.Atom, body: H.Tree): L.LetP = {
prim match {
case L3.BlockAlloc(tag) => ???
case L3.BlockTag =>
// Unsure how I'm doing this, but in theory, addresses can never be
// literals, therefore we can assume x is a name
L.LetP(n, CPS.BlockTag, Seq(rewrite(x)), apply(body))
case L3.BlockLength => ???
case L3.ByteWrite => ???
case L3.CharToInt =>
L.LetP(n, CPS.ShiftRight, Seq(rewrite(x), L.AtomL(2)), apply(body))
case L3.Id =>
L.LetP(n, CPS.Id, Seq(rewrite(x)), apply(body))
case L3.IntToChar => ???
case _ => throw new Exception("Unreachable code (unary letP) " + prim.getClass)
}
}
// Transforms value primitives that take 2 arguments
private def applyLetPBinary(n: H.Name, prim: L3, x: H.Atom, y: H.Atom, body: H.Tree): L.LetP = {
val lAtomOne: Either[H.Atom, L.Atom] = Right(L.AtomL(1))
prim match {
case L3.BlockGet =>
// In theory, x has to be a name, since there cannot be pointer literals
val block = rewrite(x)
val idx = rewrite(y)
// NOTE: I'm not sure about this. I might have misunderstood something
L.LetP(n, CPS.BlockGet, Seq(block, idx), apply(body))
case L3.IntAdd =>
tempLetP(CPS.Sub, Seq(Left(x), lAtomOne)) { x1 =>
L.LetP(n, CPS.Add, Seq(x1, rewrite(y)), apply(body))
......@@ -64,21 +159,28 @@ object CPSValueRepresenter extends (H.Tree => L.Tree) {
L.LetP(n, CPS.XOr, Seq(x1, rewrite(y)), apply(body))
}
case _ => throw new Exception("Unreachable code (binary letP)")
}
}
private def applyLetPTernary(n: H.Name, prim: L3, x: H.Atom, y: H.Atom, z: H.Atom, body: H.Tree): L.LetP = {
prim match {
case L3.BlockSet => ???
case _ => throw new Exception("Unreachable code (ternary letP)")
}
}
// Creates an outer LetP, and binds the result to a name,
// then passes the name to mkBody
// Works similarly to transform in the CL3->CPS translation
// Does *not* tag the integers given as arguments
private def tempLetP(p: CPS, args: Seq[Either[H.Atom, L.Atom]]) (mkBody: L.Atom => L.LetP): L.LetP = {
private def tempLetP[A <: L.Tree](p: CPS, args: Seq[Either[H.Atom, L.Atom]]) (mkBody: L.Atom => A): L.LetP = {
val lArgs = args.map {
case Left(hAtom) => rewrite(hAtom)
case Right(lAtom) => lAtom
}
val tmpName = Symbol.fresh("x")
val innerLetP = mkBody(L.AtomN(tmpName))
val innerLetP: A = mkBody(L.AtomN(tmpName))
L.LetP(tmpName, p, lArgs, innerLetP)
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment