diff --git a/src/main/wacc/backend/assemblyIR.scala b/src/main/wacc/backend/assemblyIR.scala index 0777dd1..d653bfb 100644 --- a/src/main/wacc/backend/assemblyIR.scala +++ b/src/main/wacc/backend/assemblyIR.scala @@ -1,17 +1,27 @@ package wacc object assemblyIR { + + sealed trait Operand + + // did not use option because we'd have to wrap each op around Some(). can refactor + case object NoOperand extends Operand { + override def toString = "" + } + sealed trait Src extends Operand // mem location, register and imm value + sealed trait Dest extends Operand // mem location and register enum RegSize { case R64 case E32 - override def toString: String = this match { + override def toString = this match { case R64 => "r" case E32 => "e" } } - enum CLibFunc { + //arguments + enum CLibFunc extends Operand { case Scanf, Puts, Fflush, @@ -20,7 +30,7 @@ object assemblyIR { private val plt = "@plt" - override def toString: String = this match { + override def toString = this match { case Scanf => "scanf" + plt case Puts => "puts" + plt case Fflush => "fflush" + plt @@ -29,40 +39,59 @@ object assemblyIR { } } - enum Register { + enum Register extends Dest with Src { case Named(name: String, size: RegSize) case Scratch(num: Int, size: RegSize) - override def toString: String = this match { - case Named(name, size) => s"${size}${name}" + override def toString = this match { + case Named(name, size) => s"${size}${name.toLowerCase()}" case Scratch(num, size) => s"${size}${num}" } } - case class MemLocation(pointer: Long) - case class ImmediateVal(value: Int) + case class MemLocation(pointer: Long | Register) extends Dest with Src { + override def toString = pointer match { + case hex: Long => f"[0x$hex%X]" + case reg: Register => s"[$reg]" + } + } + + case class ImmediateVal(value: Int) extends Src { + override def toString = s"#${value.toString}" + } + + case class LabelArg(name: String) extends Operand { + override def toString = name + } //TODO Check if dest and src are not both memory locations - sealed trait noDupeMemLoc + abstract class Operation(ins: String, op1: Operand = NoOperand, op2: Operand = NoOperand) { + override def toString: String = if (op2 == NoOperand) { + s"$ins ${op1.toString}" + } else { + s"$ins ${op1.toString}, ${op2.toString}" + } + } + case class Add(op1: Dest, op2: Src) extends Operation("add", op1, op2) + case class Subtract(op1: Dest, op2: Src) extends Operation("sub", op1, op2) + case class Multiply(op1: Src) extends Operation("mul", op1) + case class Divide(op1: Src) extends Operation("div", op1) -// object noDupeMemLoc { -// def apply(dest: Register | MemLocation, src: Register | MemLocation | ImmediateVal) : noDupeMemLoc { -// require(!(dest.isInstanceOf[MemLocation] && src.isInstanceOf[MemLocation])) -// } -// } - case class Add(dest: Register | MemLocation, src: Register | MemLocation | ImmediateVal) extends noDupeMemLoc - case class Subtract(dest: Register | MemLocation, src: Register | MemLocation | ImmediateVal) extends noDupeMemLoc - case class Multiply(src: Register) - case class Divide(src: Register) + case class And(op1: Dest, op2: Src) extends Operation("and", op1, op2) + case class Or(op1: Dest, op2: Src) extends Operation("or", op1, op2) + case class Compare(op1: Dest, op2: Src) extends Operation("cmp", op1, op2) - case class And(dest: Register | MemLocation, src: Register | MemLocation | ImmediateVal) extends noDupeMemLoc - case class Or(dest: Register | MemLocation, src: Register | MemLocation | ImmediateVal) extends noDupeMemLoc - case class Compare(dest: Register | MemLocation, src: Register | MemLocation | ImmediateVal) extends noDupeMemLoc + //stack operations + case class Push(op1: Src) extends Operation("push", op1) + case class Pop(op1: Src) extends Operation("pop", op1) + case class Call(op1: CLibFunc) extends Operation("call", op1) - case class Call(func: CLibFunc) + case class Return() extends Operation("ret") - case class Push(src: Register | MemLocation | ImmediateVal) - case class Pop(src: Register | MemLocation | ImmediateVal) + case class Jump(op1: LabelArg) extends Operation("jmp", op1) + case class JumpIfEqual(op1: LabelArg) extends Operation("je", op1) - case class Jump() + case class LabelDef(name: String) { + override def toString = s"$name:" + } }