refactor: redesigned runtime errors with added functionality
This commit is contained in:
104
src/main/wacc/backend/RuntimeError.scala
Normal file
104
src/main/wacc/backend/RuntimeError.scala
Normal file
@@ -0,0 +1,104 @@
|
||||
package wacc
|
||||
|
||||
import cats.data.Chain
|
||||
import wacc.assemblyIR._
|
||||
|
||||
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(255)),
|
||||
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(255)),
|
||||
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(255)),
|
||||
assemblyIR.Call(CLibFunc.Exit)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
val all: Chain[RuntimeError] = Chain(ZeroDivError, BadChrError, NullPtrError, OverflowError)
|
||||
}
|
||||
Reference in New Issue
Block a user