feat: x86 code generation implementation without runtime checking #29

Merged
gk1623 merged 58 commits from asm-gen into master 2025-02-27 18:54:57 +00:00
11 changed files with 607 additions and 226 deletions
Showing only changes of commit 07c67dbef6 - Show all commits

View File

@@ -12,6 +12,24 @@ object asmGenerator {
import wacc.types._
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 EAX = Register(RegSize.E32, RegName.AX)
val ESP = Register(RegSize.E32, RegName.SP)
@@ -66,7 +84,7 @@ object asmGenerator {
LabelDef(s".L.str$i"),
Directive.Asciz(str.escaped)
)
}
} ++ zeroDivError.stringDef
Chain(
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
}
@@ -254,6 +283,8 @@ object asmGenerator {
chain += stack.push(RAX)
case BinaryOperator.Div =>
chain += Compare(stack.head(SizeDir.Word), ImmediateVal(0))
chain += Jump(LabelArg(zeroDivError.errLabel), Cond.Equal)
chain += CDQ()
chain += Divide(stack.head(SizeDir.Word))
chain += stack.drop()