Files
WACC_37/src/main/wacc/backend/RuntimeError.scala

141 lines
4.0 KiB
Scala

package wacc
import cats.data.Chain
import wacc.assemblyIR._
val ERROR_CODE = 255
sealed trait RuntimeError {
def strLabel: String
def errStr: String
def errLabel: String
def stringDef: Chain[AsmLine] = Chain(
Directive.Int(errStr.length),
LabelDef(strLabel),
Directive.Asciz(errStr)
)
def generateHandler: Chain[AsmLine]
}
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 strLabel = ".L._errDivZero_str0"
val errStr = "fatal error: division or modulo by zero"
val errLabel = ".L._errDivZero"
def generateHandler: Chain[AsmLine] = Chain(
LabelDef(ZeroDivError.errLabel),
stackAlign,
Load(RDI, IndexAddress(RIP, LabelArg(ZeroDivError.strLabel))),
assemblyIR.Call(CLibFunc.PrintF),
Move(RDI, ImmediateVal(-1)),
assemblyIR.Call(CLibFunc.Exit)
)
}
case object BadChrError extends RuntimeError {
val strLabel = ".L._errBadChr_str0"
val errStr = "fatal error: int %d is not an ASCII character 0-127"
val errLabel = ".L._errBadChr"
def generateHandler: Chain[AsmLine] = Chain(
LabelDef(BadChrError.errLabel),
Pop(RSI),
stackAlign,
Load(RDI, IndexAddress(RIP, LabelArg(BadChrError.strLabel))),
assemblyIR.Call(CLibFunc.PrintF),
Move(RDI, ImmediateVal(ERROR_CODE)),
assemblyIR.Call(CLibFunc.Exit)
)
}
case object NullPtrError extends RuntimeError {
val strLabel = ".L._errNullPtr_str0"
val errStr = "fatal error: null pair dereferenced or freed"
val errLabel = ".L._errNullPtr"
def generateHandler: Chain[AsmLine] = Chain(
LabelDef(NullPtrError.errLabel),
stackAlign,
Load(RDI, IndexAddress(RIP, LabelArg(NullPtrError.strLabel))),
assemblyIR.Call(CLibFunc.PrintF),
Move(RDI, ImmediateVal(ERROR_CODE)),
assemblyIR.Call(CLibFunc.Exit)
)
}
case object OverflowError extends RuntimeError {
val strLabel = ".L._errOverflow_str0"
val errStr = "fatal error: integer overflow or underflow occurred"
val errLabel = ".L._errOverflow"
def generateHandler: Chain[AsmLine] = Chain(
LabelDef(OverflowError.errLabel),
stackAlign,
Load(RDI, IndexAddress(RIP, LabelArg(OverflowError.strLabel))),
assemblyIR.Call(CLibFunc.PrintF),
Move(RDI, ImmediateVal(ERROR_CODE)),
assemblyIR.Call(CLibFunc.Exit)
)
}
case object OutOfBoundsError extends RuntimeError {
val strLabel = ".L._errOutOfBounds_str0"
val errStr = "fatal error: array index %d out of bounds"
val errLabel = ".L._errOutOfBounds"
def generateHandler: Chain[AsmLine] = Chain(
LabelDef(OutOfBoundsError.errLabel),
Move(RSI, RCX),
stackAlign,
Load(RDI, IndexAddress(RIP, LabelArg(OutOfBoundsError.strLabel))),
assemblyIR.Call(CLibFunc.PrintF),
Move(RDI, ImmediateVal(ERROR_CODE)),
assemblyIR.Call(CLibFunc.Exit)
)
}
case object OutOfMemoryError extends RuntimeError {
val strLabel = ".L._errOutOfMemory_str0"
val errStr = "fatal error: out of memory"
val errLabel = ".L._errOutOfMemory"
def generateHandler: Chain[AsmLine] = Chain(
LabelDef(OutOfMemoryError.errLabel),
stackAlign,
Load(RDI, IndexAddress(RIP, LabelArg(OutOfMemoryError.strLabel))),
assemblyIR.Call(CLibFunc.PrintF),
Move(RDI, ImmediateVal(ERROR_CODE)),
assemblyIR.Call(CLibFunc.Exit)
)
}
val all: Chain[RuntimeError] =
Chain(ZeroDivError, BadChrError, NullPtrError, OverflowError, OutOfBoundsError,
OutOfMemoryError)
}