fix: reset scope after all branching
This commit is contained in:
parent
2cf18a47a8
commit
09df7af2ab
@ -4,7 +4,6 @@ import scala.collection.mutable.LinkedHashMap
|
|||||||
import scala.collection.mutable.ListBuffer
|
import scala.collection.mutable.ListBuffer
|
||||||
import cats.data.Chain
|
import cats.data.Chain
|
||||||
import cats.syntax.foldable._
|
import cats.syntax.foldable._
|
||||||
// import parsley.token.errors.Label
|
|
||||||
|
|
||||||
object asmGenerator {
|
object asmGenerator {
|
||||||
import microWacc._
|
import microWacc._
|
||||||
@ -183,13 +182,33 @@ object asmGenerator {
|
|||||||
chain
|
chain
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Wraps a chain in a stack reset.
|
||||||
|
*
|
||||||
|
* This is useful for ensuring that the stack size at the death of scope is the same as the stack
|
||||||
|
* size at the start of the scope. See branching (If / While)
|
||||||
|
*
|
||||||
|
* @param genChain
|
||||||
|
* Function that generates the scope AsmLines
|
||||||
|
* @param stack
|
||||||
|
* The stack to reset
|
||||||
|
* @return
|
||||||
|
* The generated scope AsmLines
|
||||||
|
*/
|
||||||
|
private def generateScope(genChain: () => Chain[AsmLine])(using
|
||||||
|
stack: Stack
|
||||||
|
): Chain[AsmLine] = {
|
||||||
|
val stackSizeStart = stack.size
|
||||||
|
var chain = genChain()
|
||||||
|
chain += stack.drop(stack.size - stackSizeStart)
|
||||||
|
chain
|
||||||
|
}
|
||||||
|
|
||||||
def generateStmt(stmt: Stmt)(using
|
def generateStmt(stmt: Stmt)(using
|
||||||
stack: Stack,
|
stack: Stack,
|
||||||
strings: ListBuffer[String],
|
strings: ListBuffer[String],
|
||||||
labelGenerator: LabelGenerator
|
labelGenerator: LabelGenerator
|
||||||
): Chain[AsmLine] = {
|
): Chain[AsmLine] = {
|
||||||
var chain = Chain.empty[AsmLine]
|
var chain = Chain.empty[AsmLine]
|
||||||
|
|
||||||
stmt match {
|
stmt match {
|
||||||
case Assign(lhs, rhs) =>
|
case Assign(lhs, rhs) =>
|
||||||
var dest: () => IndexAddress = () => IndexAddress(RAX, 0) // overwritten below
|
var dest: () => IndexAddress = () => IndexAddress(RAX, 0) // overwritten below
|
||||||
@ -215,11 +234,11 @@ object asmGenerator {
|
|||||||
chain += Compare(RAX, ImmediateVal(0))
|
chain += Compare(RAX, ImmediateVal(0))
|
||||||
chain += Jump(LabelArg(elseLabel), Cond.Equal)
|
chain += Jump(LabelArg(elseLabel), Cond.Equal)
|
||||||
|
|
||||||
chain ++= thenBranch.foldMap(generateStmt)
|
chain ++= generateScope(() => thenBranch.foldMap(generateStmt))
|
||||||
chain += Jump(LabelArg(endLabel))
|
chain += Jump(LabelArg(endLabel))
|
||||||
chain += LabelDef(elseLabel)
|
chain += LabelDef(elseLabel)
|
||||||
|
|
||||||
chain ++= elseBranch.foldMap(generateStmt)
|
chain ++= generateScope(() => elseBranch.foldMap(generateStmt))
|
||||||
chain += LabelDef(endLabel)
|
chain += LabelDef(endLabel)
|
||||||
|
|
||||||
case While(cond, body) =>
|
case While(cond, body) =>
|
||||||
@ -232,7 +251,7 @@ object asmGenerator {
|
|||||||
chain += Compare(RAX, ImmediateVal(0))
|
chain += Compare(RAX, ImmediateVal(0))
|
||||||
chain += Jump(LabelArg(endLabel), Cond.Equal)
|
chain += Jump(LabelArg(endLabel), Cond.Equal)
|
||||||
|
|
||||||
chain ++= body.foldMap(generateStmt)
|
chain ++= generateScope(() => body.foldMap(generateStmt))
|
||||||
chain += Jump(LabelArg(startLabel))
|
chain += Jump(LabelArg(startLabel))
|
||||||
chain += LabelDef(endLabel)
|
chain += LabelDef(endLabel)
|
||||||
|
|
||||||
@ -259,7 +278,7 @@ object asmGenerator {
|
|||||||
labelGenerator: LabelGenerator
|
labelGenerator: LabelGenerator
|
||||||
): Chain[AsmLine] = {
|
): Chain[AsmLine] = {
|
||||||
var chain = Chain.empty[AsmLine]
|
var chain = Chain.empty[AsmLine]
|
||||||
|
val stackSizeStart = stack.size
|
||||||
expr match {
|
expr match {
|
||||||
case IntLiter(v) => chain += stack.push(ImmediateVal(v))
|
case IntLiter(v) => chain += stack.push(ImmediateVal(v))
|
||||||
case CharLiter(v) => chain += stack.push(ImmediateVal(v.toInt))
|
case CharLiter(v) => chain += stack.push(ImmediateVal(v.toInt))
|
||||||
@ -333,6 +352,8 @@ object asmGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if chain.isEmpty then chain += stack.push(ImmediateVal(0))
|
if chain.isEmpty then chain += stack.push(ImmediateVal(0))
|
||||||
|
|
||||||
|
assert(stack.size == stackSizeStart + 1)
|
||||||
chain
|
chain
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,6 +425,7 @@ object asmGenerator {
|
|||||||
private val RSP = Register(RegSize.R64, RegName.SP)
|
private val RSP = Register(RegSize.R64, RegName.SP)
|
||||||
|
|
||||||
private def next: Int = stack.size + 1
|
private def next: Int = stack.size + 1
|
||||||
|
def size: Int = stack.size
|
||||||
def push(expr: Expr, src: Src): AsmLine = {
|
def push(expr: Expr, src: Src): AsmLine = {
|
||||||
stack += expr -> next
|
stack += expr -> next
|
||||||
Push(src)
|
Push(src)
|
||||||
|
@ -99,7 +99,8 @@ class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll {
|
|||||||
// "^.*wacc-examples/valid/IO/IOSequence.wacc.*$",
|
// "^.*wacc-examples/valid/IO/IOSequence.wacc.*$",
|
||||||
"^.*wacc-examples/valid/pairs.*$",
|
"^.*wacc-examples/valid/pairs.*$",
|
||||||
"^.*wacc-examples/valid/runtimeErr.*$",
|
"^.*wacc-examples/valid/runtimeErr.*$",
|
||||||
"^.*wacc-examples/valid/scope.*$",
|
// "^.*wacc-examples/valid/scope.*$",
|
||||||
|
"^.*wacc-examples/valid/scope/printAllTypes.wacc$", // while we still don't have arrays implemented
|
||||||
// "^.*wacc-examples/valid/sequence.*$",
|
// "^.*wacc-examples/valid/sequence.*$",
|
||||||
// "^.*wacc-examples/valid/variables.*$",
|
// "^.*wacc-examples/valid/variables.*$",
|
||||||
// "^.*wacc-examples/valid/while.*$",
|
// "^.*wacc-examples/valid/while.*$",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user