110 lines
3.3 KiB
Scala
110 lines
3.3 KiB
Scala
package wacc
|
|
|
|
import cats.data.Chain
|
|
import wacc.assemblyIR._
|
|
|
|
sealed trait RuntimeError {
|
|
val name: String
|
|
protected val errStr: String
|
|
|
|
protected def getErrLabel(using labelGenerator: LabelGenerator): LabelArg =
|
|
labelGenerator.getLabelArg(errStr, name = name)
|
|
|
|
protected def generateHandler(using labelGenerator: LabelGenerator): Chain[AsmLine]
|
|
|
|
def generate(using labelGenerator: LabelGenerator): Chain[AsmLine] =
|
|
labelGenerator.getLabelDef(this) +: generateHandler
|
|
}
|
|
|
|
object RuntimeError {
|
|
|
|
// TODO: Refactor to mitigate imports and redeclared vals perhaps
|
|
|
|
import wacc.asmGenerator.stackAlign
|
|
import assemblyIR.Size._
|
|
import assemblyIR.RegName._
|
|
|
|
// private val RAX = Register(Q64, AX)
|
|
// private val EAX = Register(D32, AX)
|
|
private val RDI = Register(Q64, DI)
|
|
private val RIP = Register(Q64, IP)
|
|
// private val RBP = Register(Q64, BP)
|
|
private val RSI = Register(Q64, SI)
|
|
// private val RDX = Register(Q64, DX)
|
|
// private val RCX = Register(Q64, CX)
|
|
|
|
case object ZeroDivError extends RuntimeError {
|
|
val name = "errDivZero"
|
|
protected val errStr = "fatal error: division or modulo by zero"
|
|
|
|
protected def generateHandler(using labelGenerator: LabelGenerator): Chain[AsmLine] = Chain(
|
|
stackAlign,
|
|
Load(RDI, IndexAddress(RIP, getErrLabel)),
|
|
assemblyIR.Call(CLibFunc.PrintF),
|
|
Move(RDI, ImmediateVal(-1)),
|
|
assemblyIR.Call(CLibFunc.Exit)
|
|
)
|
|
|
|
}
|
|
|
|
case object BadChrError extends RuntimeError {
|
|
val name = "errBadChr"
|
|
protected val errStr = "fatal error: int %d is not an ASCII character 0-127"
|
|
|
|
protected def generateHandler(using labelGenerator: LabelGenerator): Chain[AsmLine] = Chain(
|
|
Pop(RSI),
|
|
stackAlign,
|
|
Load(RDI, IndexAddress(RIP, getErrLabel)),
|
|
assemblyIR.Call(CLibFunc.PrintF),
|
|
Move(RDI, ImmediateVal(255)),
|
|
assemblyIR.Call(CLibFunc.Exit)
|
|
)
|
|
|
|
}
|
|
|
|
case object NullPtrError extends RuntimeError {
|
|
val name = "errNullPtr"
|
|
protected val errStr = "fatal error: null pair dereferenced or freed"
|
|
|
|
protected def generateHandler(using labelGenerator: LabelGenerator): Chain[AsmLine] = Chain(
|
|
stackAlign,
|
|
Load(RDI, IndexAddress(RIP, getErrLabel)),
|
|
assemblyIR.Call(CLibFunc.PrintF),
|
|
Move(RDI, ImmediateVal(255)),
|
|
assemblyIR.Call(CLibFunc.Exit)
|
|
)
|
|
|
|
}
|
|
|
|
case object OverflowError extends RuntimeError {
|
|
val name = "errOverflow"
|
|
protected val errStr = "fatal error: integer overflow or underflow occurred"
|
|
|
|
protected def generateHandler(using labelGenerator: LabelGenerator): Chain[AsmLine] = Chain(
|
|
stackAlign,
|
|
Load(RDI, IndexAddress(RIP, getErrLabel)),
|
|
assemblyIR.Call(CLibFunc.PrintF),
|
|
Move(RDI, ImmediateVal(255)),
|
|
assemblyIR.Call(CLibFunc.Exit)
|
|
)
|
|
|
|
}
|
|
|
|
case object OutOfBoundsError extends RuntimeError {
|
|
val name = "errOutOfBounds"
|
|
protected val errStr = "fatal error: array index %d out of bounds"
|
|
|
|
protected def generateHandler(using labelGenerator: LabelGenerator): Chain[AsmLine] = Chain(
|
|
Move(RSI, Register(Q64, CX)),
|
|
stackAlign,
|
|
Load(RDI, IndexAddress(RIP, getErrLabel)),
|
|
assemblyIR.Call(CLibFunc.PrintF),
|
|
Move(RDI, ImmediateVal(255)),
|
|
assemblyIR.Call(CLibFunc.Exit)
|
|
)
|
|
}
|
|
|
|
val all: Chain[RuntimeError] =
|
|
Chain(ZeroDivError, BadChrError, NullPtrError, OverflowError, OutOfBoundsError)
|
|
}
|