refactor: rename local builder chain to asm
This commit is contained in:
@@ -82,11 +82,11 @@ object asmGenerator {
|
||||
private def wrapBuiltinFunc(labelName: String, funcBody: Chain[AsmLine])(using
|
||||
stack: Stack
|
||||
): Chain[AsmLine] = {
|
||||
var chain = Chain.one[AsmLine](LabelDef(labelName))
|
||||
chain ++= funcPrologue()
|
||||
chain ++= funcBody
|
||||
chain ++= funcEpilogue()
|
||||
chain
|
||||
var asm = Chain.one[AsmLine](LabelDef(labelName))
|
||||
asm ++= funcPrologue()
|
||||
asm ++= funcBody
|
||||
asm ++= funcEpilogue()
|
||||
asm
|
||||
}
|
||||
|
||||
private def generateUserFunc(func: FuncDecl)(using
|
||||
@@ -97,29 +97,29 @@ object asmGenerator {
|
||||
// Setup the stack with param 7 and up
|
||||
func.params.drop(argRegs.size).foreach(stack.reserve(_))
|
||||
stack.reserve(Q64) // Reserve return pointer slot
|
||||
var chain = Chain.one[AsmLine](LabelDef(labelGenerator.getLabel(func.name)))
|
||||
chain ++= funcPrologue()
|
||||
var asm = Chain.one[AsmLine](LabelDef(labelGenerator.getLabel(func.name)))
|
||||
asm ++= funcPrologue()
|
||||
// Push the rest of params onto the stack for simplicity
|
||||
argRegs.zip(func.params).foreach { (reg, param) =>
|
||||
chain += stack.push(param, Register(Q64, reg))
|
||||
asm += stack.push(param, Register(Q64, reg))
|
||||
}
|
||||
chain ++= func.body.foldMap(generateStmt(_))
|
||||
asm ++= func.body.foldMap(generateStmt(_))
|
||||
// No need for epilogue here since all user functions must return explicitly
|
||||
chain
|
||||
asm
|
||||
}
|
||||
|
||||
private def generateBuiltInFuncs()(using
|
||||
stack: Stack,
|
||||
labelGenerator: LabelGenerator
|
||||
): Chain[AsmLine] = {
|
||||
var chain = Chain.empty[AsmLine]
|
||||
var asm = Chain.empty[AsmLine]
|
||||
|
||||
chain ++= wrapBuiltinFunc(
|
||||
asm ++= wrapBuiltinFunc(
|
||||
labelGenerator.getLabel(Builtin.Exit),
|
||||
Chain(stackAlign, assemblyIR.Call(CLibFunc.Exit))
|
||||
)
|
||||
|
||||
chain ++= wrapBuiltinFunc(
|
||||
asm ++= wrapBuiltinFunc(
|
||||
labelGenerator.getLabel(Builtin.Printf),
|
||||
Chain(
|
||||
stackAlign,
|
||||
@@ -129,7 +129,7 @@ object asmGenerator {
|
||||
)
|
||||
)
|
||||
|
||||
chain ++= wrapBuiltinFunc(
|
||||
asm ++= wrapBuiltinFunc(
|
||||
labelGenerator.getLabel(Builtin.PrintCharArray),
|
||||
Chain(
|
||||
stackAlign,
|
||||
@@ -141,7 +141,7 @@ object asmGenerator {
|
||||
)
|
||||
)
|
||||
|
||||
chain ++= wrapBuiltinFunc(
|
||||
asm ++= wrapBuiltinFunc(
|
||||
labelGenerator.getLabel(Builtin.Malloc),
|
||||
Chain(
|
||||
stackAlign,
|
||||
@@ -152,7 +152,7 @@ object asmGenerator {
|
||||
)
|
||||
)
|
||||
|
||||
chain ++= wrapBuiltinFunc(
|
||||
asm ++= wrapBuiltinFunc(
|
||||
labelGenerator.getLabel(Builtin.Free),
|
||||
Chain(
|
||||
stackAlign,
|
||||
@@ -163,7 +163,7 @@ object asmGenerator {
|
||||
)
|
||||
)
|
||||
|
||||
chain ++= wrapBuiltinFunc(
|
||||
asm ++= wrapBuiltinFunc(
|
||||
labelGenerator.getLabel(Builtin.Read),
|
||||
Chain(
|
||||
stackAlign,
|
||||
@@ -175,9 +175,9 @@ object asmGenerator {
|
||||
)
|
||||
)
|
||||
|
||||
chain ++= RuntimeError.all.foldMap(_.generateHandler)
|
||||
asm ++= RuntimeError.all.foldMap(_.generateHandler)
|
||||
|
||||
chain
|
||||
asm
|
||||
}
|
||||
|
||||
private def generateStmt(stmt: Stmt)(using
|
||||
@@ -185,33 +185,33 @@ object asmGenerator {
|
||||
strings: ListBuffer[String],
|
||||
labelGenerator: LabelGenerator
|
||||
): Chain[AsmLine] = {
|
||||
var chain = Chain.empty[AsmLine]
|
||||
chain += Comment(stmt.toString)
|
||||
var asm = Chain.empty[AsmLine]
|
||||
asm += Comment(stmt.toString)
|
||||
stmt match {
|
||||
case Assign(lhs, rhs) =>
|
||||
lhs match {
|
||||
case ident: Ident =>
|
||||
if (!stack.contains(ident)) chain += stack.reserve(ident)
|
||||
chain ++= evalExprOntoStack(rhs)
|
||||
chain += stack.pop(RAX)
|
||||
chain += Move(stack.accessVar(ident), RAX)
|
||||
if (!stack.contains(ident)) asm += stack.reserve(ident)
|
||||
asm ++= evalExprOntoStack(rhs)
|
||||
asm += stack.pop(RAX)
|
||||
asm += Move(stack.accessVar(ident), RAX)
|
||||
case ArrayElem(x, i) =>
|
||||
chain ++= evalExprOntoStack(rhs)
|
||||
chain ++= evalExprOntoStack(i)
|
||||
chain += stack.pop(RCX)
|
||||
chain += Compare(ECX, ImmediateVal(0))
|
||||
chain += Jump(LabelArg(OutOfBoundsError.errLabel), Cond.Less)
|
||||
chain += stack.push(Q64, RCX)
|
||||
chain ++= evalExprOntoStack(x)
|
||||
chain += stack.pop(RAX)
|
||||
chain += stack.pop(RCX)
|
||||
chain += Compare(EAX, ImmediateVal(0))
|
||||
chain += Jump(LabelArg(NullPtrError.errLabel), Cond.Equal)
|
||||
chain += Compare(MemLocation(RAX, D32), ECX)
|
||||
chain += Jump(LabelArg(OutOfBoundsError.errLabel), Cond.LessEqual)
|
||||
chain += stack.pop(RDX)
|
||||
asm ++= evalExprOntoStack(rhs)
|
||||
asm ++= evalExprOntoStack(i)
|
||||
asm += stack.pop(RCX)
|
||||
asm += Compare(ECX, ImmediateVal(0))
|
||||
asm += Jump(LabelArg(OutOfBoundsError.errLabel), Cond.Less)
|
||||
asm += stack.push(Q64, RCX)
|
||||
asm ++= evalExprOntoStack(x)
|
||||
asm += stack.pop(RAX)
|
||||
asm += stack.pop(RCX)
|
||||
asm += Compare(EAX, ImmediateVal(0))
|
||||
asm += Jump(LabelArg(NullPtrError.errLabel), Cond.Equal)
|
||||
asm += Compare(MemLocation(RAX, D32), ECX)
|
||||
asm += Jump(LabelArg(OutOfBoundsError.errLabel), Cond.LessEqual)
|
||||
asm += stack.pop(RDX)
|
||||
|
||||
chain += Move(
|
||||
asm += Move(
|
||||
IndexAddress(RAX, KnownType.Int.size.toInt, RCX, x.ty.elemSize.toInt),
|
||||
Register(x.ty.elemSize, DX)
|
||||
)
|
||||
@@ -221,47 +221,47 @@ object asmGenerator {
|
||||
val elseLabel = labelGenerator.getLabel()
|
||||
val endLabel = labelGenerator.getLabel()
|
||||
|
||||
chain ++= evalExprOntoStack(cond)
|
||||
chain += stack.pop(RAX)
|
||||
chain += Compare(RAX, ImmediateVal(0))
|
||||
chain += Jump(LabelArg(elseLabel), Cond.Equal)
|
||||
asm ++= evalExprOntoStack(cond)
|
||||
asm += stack.pop(RAX)
|
||||
asm += Compare(RAX, ImmediateVal(0))
|
||||
asm += Jump(LabelArg(elseLabel), Cond.Equal)
|
||||
|
||||
chain ++= stack.withScope(() => thenBranch.foldMap(generateStmt))
|
||||
chain += Jump(LabelArg(endLabel))
|
||||
chain += LabelDef(elseLabel)
|
||||
asm ++= stack.withScope(() => thenBranch.foldMap(generateStmt))
|
||||
asm += Jump(LabelArg(endLabel))
|
||||
asm += LabelDef(elseLabel)
|
||||
|
||||
chain ++= stack.withScope(() => elseBranch.foldMap(generateStmt))
|
||||
chain += LabelDef(endLabel)
|
||||
asm ++= stack.withScope(() => elseBranch.foldMap(generateStmt))
|
||||
asm += LabelDef(endLabel)
|
||||
|
||||
case While(cond, body) =>
|
||||
val startLabel = labelGenerator.getLabel()
|
||||
val endLabel = labelGenerator.getLabel()
|
||||
|
||||
chain += LabelDef(startLabel)
|
||||
chain ++= evalExprOntoStack(cond)
|
||||
chain += stack.pop(RAX)
|
||||
chain += Compare(RAX, ImmediateVal(0))
|
||||
chain += Jump(LabelArg(endLabel), Cond.Equal)
|
||||
asm += LabelDef(startLabel)
|
||||
asm ++= evalExprOntoStack(cond)
|
||||
asm += stack.pop(RAX)
|
||||
asm += Compare(RAX, ImmediateVal(0))
|
||||
asm += Jump(LabelArg(endLabel), Cond.Equal)
|
||||
|
||||
chain ++= stack.withScope(() => body.foldMap(generateStmt))
|
||||
chain += Jump(LabelArg(startLabel))
|
||||
chain += LabelDef(endLabel)
|
||||
asm ++= stack.withScope(() => body.foldMap(generateStmt))
|
||||
asm += Jump(LabelArg(startLabel))
|
||||
asm += LabelDef(endLabel)
|
||||
|
||||
case call: microWacc.Call =>
|
||||
chain ++= generateCall(call, isTail = false)
|
||||
asm ++= generateCall(call, isTail = false)
|
||||
|
||||
case microWacc.Return(expr) =>
|
||||
expr match {
|
||||
case call: microWacc.Call =>
|
||||
chain ++= generateCall(call, isTail = true) // tco
|
||||
asm ++= generateCall(call, isTail = true) // tco
|
||||
case _ =>
|
||||
chain ++= evalExprOntoStack(expr)
|
||||
chain += stack.pop(RAX)
|
||||
chain ++= funcEpilogue()
|
||||
asm ++= evalExprOntoStack(expr)
|
||||
asm += stack.pop(RAX)
|
||||
asm ++= funcEpilogue()
|
||||
}
|
||||
}
|
||||
|
||||
chain
|
||||
asm
|
||||
}
|
||||
|
||||
private def evalExprOntoStack(expr: Expr)(using
|
||||
@@ -269,138 +269,138 @@ object asmGenerator {
|
||||
strings: ListBuffer[String],
|
||||
labelGenerator: LabelGenerator
|
||||
): Chain[AsmLine] = {
|
||||
var chain = Chain.empty[AsmLine]
|
||||
var asm = Chain.empty[AsmLine]
|
||||
val stackSizeStart = stack.size
|
||||
expr match {
|
||||
case IntLiter(v) => chain += stack.push(KnownType.Int.size, ImmediateVal(v))
|
||||
case CharLiter(v) => chain += stack.push(KnownType.Char.size, ImmediateVal(v.toInt))
|
||||
case ident: Ident => chain += stack.push(ident.ty.size, stack.accessVar(ident))
|
||||
case IntLiter(v) => asm += stack.push(KnownType.Int.size, ImmediateVal(v))
|
||||
case CharLiter(v) => asm += stack.push(KnownType.Char.size, ImmediateVal(v.toInt))
|
||||
case ident: Ident => asm += stack.push(ident.ty.size, stack.accessVar(ident))
|
||||
|
||||
case array @ ArrayLiter(elems) =>
|
||||
expr.ty match {
|
||||
case KnownType.String =>
|
||||
strings += elems.collect { case CharLiter(v) => v }.mkString
|
||||
chain += Load(RAX, IndexAddress(RIP, LabelArg(s".L.str${strings.size - 1}")))
|
||||
chain += stack.push(Q64, RAX)
|
||||
asm += Load(RAX, IndexAddress(RIP, LabelArg(s".L.str${strings.size - 1}")))
|
||||
asm += stack.push(Q64, RAX)
|
||||
case ty =>
|
||||
chain ++= generateCall(
|
||||
asm ++= generateCall(
|
||||
microWacc.Call(Builtin.Malloc, List(IntLiter(array.heapSize))),
|
||||
isTail = false
|
||||
)
|
||||
chain += stack.push(Q64, RAX)
|
||||
asm += stack.push(Q64, RAX)
|
||||
// Store the length of the array at the start
|
||||
chain += Move(MemLocation(RAX, D32), ImmediateVal(elems.size))
|
||||
asm += Move(MemLocation(RAX, D32), ImmediateVal(elems.size))
|
||||
elems.zipWithIndex.foldMap { (elem, i) =>
|
||||
chain ++= evalExprOntoStack(elem)
|
||||
chain += stack.pop(RCX)
|
||||
chain += stack.pop(RAX)
|
||||
chain += Move(IndexAddress(RAX, 4 + i * ty.elemSize.toInt), Register(ty.elemSize, CX))
|
||||
chain += stack.push(Q64, RAX)
|
||||
asm ++= evalExprOntoStack(elem)
|
||||
asm += stack.pop(RCX)
|
||||
asm += stack.pop(RAX)
|
||||
asm += Move(IndexAddress(RAX, 4 + i * ty.elemSize.toInt), Register(ty.elemSize, CX))
|
||||
asm += stack.push(Q64, RAX)
|
||||
}
|
||||
}
|
||||
|
||||
case BoolLiter(true) =>
|
||||
chain += stack.push(KnownType.Bool.size, ImmediateVal(1))
|
||||
asm += stack.push(KnownType.Bool.size, ImmediateVal(1))
|
||||
case BoolLiter(false) =>
|
||||
chain += Xor(RAX, RAX)
|
||||
chain += stack.push(KnownType.Bool.size, RAX)
|
||||
asm += Xor(RAX, RAX)
|
||||
asm += stack.push(KnownType.Bool.size, RAX)
|
||||
case NullLiter() =>
|
||||
chain += stack.push(KnownType.Pair(?, ?).size, ImmediateVal(0))
|
||||
asm += stack.push(KnownType.Pair(?, ?).size, ImmediateVal(0))
|
||||
case ArrayElem(x, i) =>
|
||||
chain ++= evalExprOntoStack(x)
|
||||
chain ++= evalExprOntoStack(i)
|
||||
chain += stack.pop(RCX)
|
||||
chain += Compare(RCX, ImmediateVal(0))
|
||||
chain += Jump(LabelArg(OutOfBoundsError.errLabel), Cond.Less)
|
||||
chain += stack.pop(RAX)
|
||||
chain += Compare(EAX, ImmediateVal(0))
|
||||
chain += Jump(LabelArg(NullPtrError.errLabel), Cond.Equal)
|
||||
chain += Compare(MemLocation(RAX, D32), ECX)
|
||||
chain += Jump(LabelArg(OutOfBoundsError.errLabel), Cond.LessEqual)
|
||||
asm ++= evalExprOntoStack(x)
|
||||
asm ++= evalExprOntoStack(i)
|
||||
asm += stack.pop(RCX)
|
||||
asm += Compare(RCX, ImmediateVal(0))
|
||||
asm += Jump(LabelArg(OutOfBoundsError.errLabel), Cond.Less)
|
||||
asm += stack.pop(RAX)
|
||||
asm += Compare(EAX, ImmediateVal(0))
|
||||
asm += Jump(LabelArg(NullPtrError.errLabel), Cond.Equal)
|
||||
asm += Compare(MemLocation(RAX, D32), ECX)
|
||||
asm += Jump(LabelArg(OutOfBoundsError.errLabel), Cond.LessEqual)
|
||||
// + Int because we store the length of the array at the start
|
||||
chain += Move(
|
||||
asm += Move(
|
||||
Register(x.ty.elemSize, AX),
|
||||
IndexAddress(RAX, KnownType.Int.size.toInt, RCX, x.ty.elemSize.toInt)
|
||||
)
|
||||
chain += stack.push(x.ty.elemSize, RAX)
|
||||
asm += stack.push(x.ty.elemSize, RAX)
|
||||
case UnaryOp(x, op) =>
|
||||
chain ++= evalExprOntoStack(x)
|
||||
asm ++= evalExprOntoStack(x)
|
||||
op match {
|
||||
case UnaryOperator.Chr =>
|
||||
chain += Move(EAX, stack.head)
|
||||
chain += And(EAX, ImmediateVal(~_7_BIT_MASK))
|
||||
chain += Compare(EAX, ImmediateVal(0))
|
||||
chain += Jump(LabelArg(BadChrError.errLabel), Cond.NotEqual)
|
||||
asm += Move(EAX, stack.head)
|
||||
asm += And(EAX, ImmediateVal(~_7_BIT_MASK))
|
||||
asm += Compare(EAX, ImmediateVal(0))
|
||||
asm += Jump(LabelArg(BadChrError.errLabel), Cond.NotEqual)
|
||||
case UnaryOperator.Ord => // No op needed
|
||||
case UnaryOperator.Len =>
|
||||
chain += stack.pop(RAX)
|
||||
chain += Move(EAX, MemLocation(RAX, D32))
|
||||
chain += stack.push(D32, RAX)
|
||||
asm += stack.pop(RAX)
|
||||
asm += Move(EAX, MemLocation(RAX, D32))
|
||||
asm += stack.push(D32, RAX)
|
||||
case UnaryOperator.Negate =>
|
||||
chain += Xor(EAX, EAX)
|
||||
chain += Subtract(EAX, stack.head)
|
||||
chain += Jump(LabelArg(OverflowError.errLabel), Cond.Overflow)
|
||||
chain += stack.drop()
|
||||
chain += stack.push(Q64, RAX)
|
||||
asm += Xor(EAX, EAX)
|
||||
asm += Subtract(EAX, stack.head)
|
||||
asm += Jump(LabelArg(OverflowError.errLabel), Cond.Overflow)
|
||||
asm += stack.drop()
|
||||
asm += stack.push(Q64, RAX)
|
||||
case UnaryOperator.Not =>
|
||||
chain += Xor(stack.head, ImmediateVal(1))
|
||||
asm += Xor(stack.head, ImmediateVal(1))
|
||||
}
|
||||
|
||||
case BinaryOp(x, y, op) =>
|
||||
val destX = Register(x.ty.size, AX)
|
||||
chain ++= evalExprOntoStack(y)
|
||||
chain ++= evalExprOntoStack(x)
|
||||
chain += stack.pop(RAX)
|
||||
asm ++= evalExprOntoStack(y)
|
||||
asm ++= evalExprOntoStack(x)
|
||||
asm += stack.pop(RAX)
|
||||
|
||||
op match {
|
||||
case BinaryOperator.Add =>
|
||||
chain += Add(stack.head, destX)
|
||||
chain += Jump(LabelArg(OverflowError.errLabel), Cond.Overflow)
|
||||
asm += Add(stack.head, destX)
|
||||
asm += Jump(LabelArg(OverflowError.errLabel), Cond.Overflow)
|
||||
case BinaryOperator.Sub =>
|
||||
chain += Subtract(destX, stack.head)
|
||||
chain += Jump(LabelArg(OverflowError.errLabel), Cond.Overflow)
|
||||
chain += stack.drop()
|
||||
chain += stack.push(destX.size, RAX)
|
||||
asm += Subtract(destX, stack.head)
|
||||
asm += Jump(LabelArg(OverflowError.errLabel), Cond.Overflow)
|
||||
asm += stack.drop()
|
||||
asm += stack.push(destX.size, RAX)
|
||||
case BinaryOperator.Mul =>
|
||||
chain += Multiply(destX, stack.head)
|
||||
chain += Jump(LabelArg(OverflowError.errLabel), Cond.Overflow)
|
||||
chain += stack.drop()
|
||||
chain += stack.push(destX.size, RAX)
|
||||
asm += Multiply(destX, stack.head)
|
||||
asm += Jump(LabelArg(OverflowError.errLabel), Cond.Overflow)
|
||||
asm += stack.drop()
|
||||
asm += stack.push(destX.size, RAX)
|
||||
|
||||
case BinaryOperator.Div =>
|
||||
chain += Compare(stack.head, ImmediateVal(0))
|
||||
chain += Jump(LabelArg(ZeroDivError.errLabel), Cond.Equal)
|
||||
chain += CDQ()
|
||||
chain += Divide(stack.head)
|
||||
chain += stack.drop()
|
||||
chain += stack.push(destX.size, RAX)
|
||||
asm += Compare(stack.head, ImmediateVal(0))
|
||||
asm += Jump(LabelArg(ZeroDivError.errLabel), Cond.Equal)
|
||||
asm += CDQ()
|
||||
asm += Divide(stack.head)
|
||||
asm += stack.drop()
|
||||
asm += stack.push(destX.size, RAX)
|
||||
|
||||
case BinaryOperator.Mod =>
|
||||
chain += Compare(stack.head, ImmediateVal(0))
|
||||
chain += Jump(LabelArg(ZeroDivError.errLabel), Cond.Equal)
|
||||
chain += CDQ()
|
||||
chain += Divide(stack.head)
|
||||
chain += stack.drop()
|
||||
chain += stack.push(destX.size, RDX)
|
||||
asm += Compare(stack.head, ImmediateVal(0))
|
||||
asm += Jump(LabelArg(ZeroDivError.errLabel), Cond.Equal)
|
||||
asm += CDQ()
|
||||
asm += Divide(stack.head)
|
||||
asm += stack.drop()
|
||||
asm += stack.push(destX.size, RDX)
|
||||
|
||||
case BinaryOperator.Eq => chain ++= generateComparison(destX, Cond.Equal)
|
||||
case BinaryOperator.Neq => chain ++= generateComparison(destX, Cond.NotEqual)
|
||||
case BinaryOperator.Greater => chain ++= generateComparison(destX, Cond.Greater)
|
||||
case BinaryOperator.GreaterEq => chain ++= generateComparison(destX, Cond.GreaterEqual)
|
||||
case BinaryOperator.Less => chain ++= generateComparison(destX, Cond.Less)
|
||||
case BinaryOperator.LessEq => chain ++= generateComparison(destX, Cond.LessEqual)
|
||||
case BinaryOperator.And => chain += And(stack.head, destX)
|
||||
case BinaryOperator.Or => chain += Or(stack.head, destX)
|
||||
case BinaryOperator.Eq => asm ++= generateComparison(destX, Cond.Equal)
|
||||
case BinaryOperator.Neq => asm ++= generateComparison(destX, Cond.NotEqual)
|
||||
case BinaryOperator.Greater => asm ++= generateComparison(destX, Cond.Greater)
|
||||
case BinaryOperator.GreaterEq => asm ++= generateComparison(destX, Cond.GreaterEqual)
|
||||
case BinaryOperator.Less => asm ++= generateComparison(destX, Cond.Less)
|
||||
case BinaryOperator.LessEq => asm ++= generateComparison(destX, Cond.LessEqual)
|
||||
case BinaryOperator.And => asm += And(stack.head, destX)
|
||||
case BinaryOperator.Or => asm += Or(stack.head, destX)
|
||||
}
|
||||
|
||||
case call: microWacc.Call =>
|
||||
chain ++= generateCall(call, isTail = false)
|
||||
chain += stack.push(call.ty.size, RAX)
|
||||
asm ++= generateCall(call, isTail = false)
|
||||
asm += stack.push(call.ty.size, RAX)
|
||||
}
|
||||
|
||||
assert(stack.size == stackSizeStart + 1)
|
||||
chain ++= zeroRest(MemLocation(stack.head.pointer, Q64), expr.ty.size)
|
||||
chain
|
||||
asm ++= zeroRest(MemLocation(stack.head.pointer, Q64), expr.ty.size)
|
||||
asm
|
||||
}
|
||||
|
||||
private def generateCall(call: microWacc.Call, isTail: Boolean)(using
|
||||
@@ -408,65 +408,65 @@ object asmGenerator {
|
||||
strings: ListBuffer[String],
|
||||
labelGenerator: LabelGenerator
|
||||
): Chain[AsmLine] = {
|
||||
var chain = Chain.empty[AsmLine]
|
||||
var asm = Chain.empty[AsmLine]
|
||||
val microWacc.Call(target, args) = call
|
||||
|
||||
argRegs
|
||||
.zip(args)
|
||||
.map { (reg, expr) =>
|
||||
chain ++= evalExprOntoStack(expr)
|
||||
asm ++= evalExprOntoStack(expr)
|
||||
reg
|
||||
}
|
||||
.reverse
|
||||
.foreach { reg =>
|
||||
chain += stack.pop(Register(Q64, reg))
|
||||
asm += stack.pop(Register(Q64, reg))
|
||||
}
|
||||
|
||||
args.drop(argRegs.size).foldMap {
|
||||
chain ++= evalExprOntoStack(_)
|
||||
asm ++= evalExprOntoStack(_)
|
||||
}
|
||||
|
||||
// Tail Call Optimisation (TCO)
|
||||
if (isTail) {
|
||||
chain += Jump(LabelArg(labelGenerator.getLabel(target))) // tail call
|
||||
asm += Jump(LabelArg(labelGenerator.getLabel(target))) // tail call
|
||||
} else {
|
||||
chain += assemblyIR.Call(LabelArg(labelGenerator.getLabel(target))) // regular call
|
||||
asm += assemblyIR.Call(LabelArg(labelGenerator.getLabel(target))) // regular call
|
||||
}
|
||||
|
||||
if (args.size > argRegs.size) {
|
||||
chain += stack.drop(args.size - argRegs.size)
|
||||
asm += stack.drop(args.size - argRegs.size)
|
||||
}
|
||||
|
||||
chain
|
||||
asm
|
||||
}
|
||||
|
||||
private def generateComparison(destX: Register, cond: Cond)(using
|
||||
stack: Stack
|
||||
): Chain[AsmLine] = {
|
||||
var chain = Chain.empty[AsmLine]
|
||||
var asm = Chain.empty[AsmLine]
|
||||
|
||||
chain += Compare(destX, stack.head)
|
||||
chain += Set(Register(B8, AX), cond)
|
||||
chain ++= zeroRest(RAX, B8)
|
||||
chain += stack.drop()
|
||||
chain += stack.push(B8, RAX)
|
||||
asm += Compare(destX, stack.head)
|
||||
asm += Set(Register(B8, AX), cond)
|
||||
asm ++= zeroRest(RAX, B8)
|
||||
asm += stack.drop()
|
||||
asm += stack.push(B8, RAX)
|
||||
|
||||
chain
|
||||
asm
|
||||
}
|
||||
|
||||
private def funcPrologue()(using stack: Stack): Chain[AsmLine] = {
|
||||
var chain = Chain.empty[AsmLine]
|
||||
chain += stack.push(Q64, RBP)
|
||||
chain += Move(RBP, Register(Q64, SP))
|
||||
chain
|
||||
var asm = Chain.empty[AsmLine]
|
||||
asm += stack.push(Q64, RBP)
|
||||
asm += Move(RBP, Register(Q64, SP))
|
||||
asm
|
||||
}
|
||||
|
||||
private def funcEpilogue(): Chain[AsmLine] = {
|
||||
var chain = Chain.empty[AsmLine]
|
||||
chain += Move(Register(Q64, SP), RBP)
|
||||
chain += Pop(RBP)
|
||||
chain += assemblyIR.Return()
|
||||
chain
|
||||
var asm = Chain.empty[AsmLine]
|
||||
asm += Move(Register(Q64, SP), RBP)
|
||||
asm += Pop(RBP)
|
||||
asm += assemblyIR.Return()
|
||||
asm
|
||||
}
|
||||
|
||||
def stackAlign: AsmLine = And(Register(Q64, SP), ImmediateVal(-16))
|
||||
|
||||
Reference in New Issue
Block a user