package wacc object assemblyIR { sealed trait AsmLine sealed trait Operand 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 = this match { case R64 => "r" case E32 => "e" } } // arguments enum CLibFunc extends Operand { case Scanf, Puts, Fflush, Exit, PrintF private val plt = "@plt" override def toString = this match { case Scanf => "scanf" + plt case Puts => "puts" + plt case Fflush => "fflush" + plt case Exit => "exit" + plt case PrintF => "printf" + plt } } enum Register extends Dest with Src { case Named(name: String, size: RegSize) case Scratch(num: Int, size: RegSize) override def toString = this match { case Named(name, size) => s"${size}${name.toLowerCase()}" case Scratch(num, size) => s"r${num}${if (size == RegSize.E32) "d" else ""}" } } 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 = value.toString } case class LabelArg(name: String) extends Operand { override def toString = name } // TODO Check if dest and src are not both memory locations abstract class Operation(ins: String, ops: Operand*) extends AsmLine { override def toString: String = s"\t$ins ${ops.mkString(", ")}" } 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(ops: Operand*) extends Operation("mul", ops*) case class Divide(op1: Src) extends Operation("div", op1) 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) // 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 Move(op1: Dest, op2: Src) extends Operation("mov", op1, op2) case class Load(op1: Register, op2: MemLocation) extends Operation("lea ", op1, op2) case class Return() extends Operation("ret") case class Jump(op1: LabelArg, condition: Cond = Cond.Always) extends Operation(s"j${condition.toString}", op1) case class LabelDef(name: String) extends AsmLine { override def toString = s"$name:" } enum Cond { case Equal, NotEqual, Greater, GreaterEqual, Less, LessEqual, Overflow, Always override def toString(): String = this match { case Equal => "e" case NotEqual => "ne" case Greater => "g" case GreaterEqual => "ge" case Less => "l" case LessEqual => "le" case Overflow => "o" case Always => "mp" } } }