feat: add zero division error handling in asmGenerator

This commit is contained in:
Guy C 2025-02-26 07:13:12 +00:00
parent fc2c58002e
commit 07c67dbef6

View File

@ -12,6 +12,24 @@ object asmGenerator {
import wacc.types._ import wacc.types._
import lexer.escapedChars import lexer.escapedChars
abstract case class Error() {
def strLabel: String
def errStr: String
def errLabel: String
def stringDef: Chain[AsmLine] = Chain(
Directive.Int(errStr.size),
LabelDef(strLabel),
Directive.Asciz(errStr)
)
}
object zeroDivError extends Error {
// TODO: is this bad? Can we make an error case class/some other structure?
def strLabel = ".L._errDivZero_str0"
def errStr = "fatal error: division or modulo by zero"
def errLabel = ".L._errDivZero"
}
val RAX = Register(RegSize.R64, RegName.AX) val RAX = Register(RegSize.R64, RegName.AX)
val EAX = Register(RegSize.E32, RegName.AX) val EAX = Register(RegSize.E32, RegName.AX)
val ESP = Register(RegSize.E32, RegName.SP) val ESP = Register(RegSize.E32, RegName.SP)
@ -66,7 +84,7 @@ object asmGenerator {
LabelDef(s".L.str$i"), LabelDef(s".L.str$i"),
Directive.Asciz(str.escaped) Directive.Asciz(str.escaped)
) )
} } ++ zeroDivError.stringDef
Chain( Chain(
Directive.IntelSyntax, Directive.IntelSyntax,
@ -135,6 +153,17 @@ object asmGenerator {
) )
) )
chain ++= Chain(
// TODO can this be done with a call to generateStmt?
// Consider other error cases -> look to generalise
LabelDef(zeroDivError.errLabel),
stack.align(),
Load(RDI, IndexAddress(RIP, LabelArg(zeroDivError.strLabel))),
assemblyIR.Call(CLibFunc.PrintF),
Move(RDI, ImmediateVal(-1)),
assemblyIR.Call(CLibFunc.Exit)
)
chain chain
} }
@ -254,6 +283,8 @@ object asmGenerator {
chain += stack.push(RAX) chain += stack.push(RAX)
case BinaryOperator.Div => case BinaryOperator.Div =>
chain += Compare(stack.head(SizeDir.Word), ImmediateVal(0))
chain += Jump(LabelArg(zeroDivError.errLabel), Cond.Equal)
chain += CDQ() chain += CDQ()
chain += Divide(stack.head(SizeDir.Word)) chain += Divide(stack.head(SizeDir.Word))
chain += stack.drop() chain += stack.drop()