Assembly ir
Merge request lab2425_spring/WACC_37!23 Co-authored-by: Barf-Vader <47476490+Barf-Vader@users.noreply.github.com> Co-authored-by: Guy C <gc1523@ic.ac.uk>
This commit is contained in:
commit
2a234f6db8
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,3 +3,5 @@
|
||||
.scala-build/
|
||||
.vscode/
|
||||
wacc-examples/
|
||||
.idea/
|
||||
|
||||
|
110
src/main/wacc/backend/assemblyIR.scala
Normal file
110
src/main/wacc/backend/assemblyIR.scala
Normal file
@ -0,0 +1,110 @@
|
||||
package wacc
|
||||
|
||||
object assemblyIR {
|
||||
|
||||
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*) {
|
||||
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) {
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
65
src/test/wacc/instructionSpec.scala
Normal file
65
src/test/wacc/instructionSpec.scala
Normal file
@ -0,0 +1,65 @@
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
import wacc.assemblyIR._
|
||||
|
||||
class instructionSpec extends AnyFunSuite {
|
||||
|
||||
val named64BitRegister = Register.Named("ax", RegSize.R64)
|
||||
|
||||
test("named 64-bit register toString") {
|
||||
assert(named64BitRegister.toString == "rax")
|
||||
}
|
||||
|
||||
val named32BitRegister = Register.Named("ax", RegSize.E32)
|
||||
|
||||
test("named 32-bit register toString") {
|
||||
assert(named32BitRegister.toString == "eax")
|
||||
}
|
||||
|
||||
val scratch64BitRegister = Register.Scratch(1, RegSize.R64)
|
||||
|
||||
test("scratch 64-bit register toString") {
|
||||
assert(scratch64BitRegister.toString == "r1")
|
||||
}
|
||||
|
||||
val scratch32BitRegister = Register.Scratch(1, RegSize.E32)
|
||||
|
||||
test("scratch 32-bit register toString") {
|
||||
assert(scratch32BitRegister.toString == "r1d")
|
||||
}
|
||||
|
||||
val memLocationWithHex = MemLocation(0x12345678)
|
||||
|
||||
test("mem location with hex toString") {
|
||||
assert(memLocationWithHex.toString == "[0x12345678]")
|
||||
}
|
||||
|
||||
val memLocationWithRegister = MemLocation(named64BitRegister)
|
||||
|
||||
test("mem location with register toString") {
|
||||
assert(memLocationWithRegister.toString == "[rax]")
|
||||
}
|
||||
|
||||
val immediateVal = ImmediateVal(123)
|
||||
|
||||
test("immediate value toString") {
|
||||
assert(immediateVal.toString == "123")
|
||||
}
|
||||
|
||||
val addInstruction = Add(named64BitRegister, immediateVal)
|
||||
|
||||
test("x86: add instruction toString") {
|
||||
assert(addInstruction.toString == "\tadd rax, 123")
|
||||
}
|
||||
|
||||
val subInstruction = Subtract(scratch64BitRegister, named64BitRegister)
|
||||
|
||||
test("x86: sub instruction toString") {
|
||||
assert(subInstruction.toString == "\tsub r1, rax")
|
||||
}
|
||||
|
||||
val callInstruction = Call(CLibFunc.Scanf)
|
||||
|
||||
test("x86: call instruction toString") {
|
||||
assert(callInstruction.toString == "\tcall scanf@plt")
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user