diff --git a/src/main/wacc/backend/asmGenerator.scala b/src/main/wacc/backend/asmGenerator.scala index c962c71..bf4e404 100644 --- a/src/main/wacc/backend/asmGenerator.scala +++ b/src/main/wacc/backend/asmGenerator.scala @@ -3,7 +3,7 @@ package wacc import scala.collection.mutable.LinkedHashMap import scala.collection.mutable.ListBuffer import cats.data.Chain -// import cats.syntax.foldable._ +import cats.syntax.foldable._ // import parsley.token.errors.Label object asmGenerator { @@ -30,6 +30,9 @@ object asmGenerator { extension (chain: Chain[AsmLine]) def +=(line: AsmLine): Chain[AsmLine] = chain.append(line) + def concatAll(chains: Chain[AsmLine]*): Chain[AsmLine] = + chains.foldLeft(chain)(_ ++ _) + class LabelGenerator { var labelVal = -1 def getLabel(): String = { @@ -42,40 +45,38 @@ object asmGenerator { } } - def generateAsm(microProg: Program): List[AsmLine] = { given stack: Stack = Stack() given strings: ListBuffer[String] = ListBuffer[String]() given labelGenerator: LabelGenerator = LabelGenerator() - val Program(funcs, main) = microProg - val progAsm = - Chain.one(LabelDef("main")) ++ - funcPrologue() ++ - Chain(stack.align()) ++ - main.foldLeft(Chain.empty[AsmLine])(_ ++ generateStmt(_)) ++ - Chain.one(Move(RAX, ImmediateVal(0))) ++ - funcEpilogue() ++ - generateBuiltInFuncs() - - val strDirs = strings.toList.zipWithIndex.foldLeft(Chain.empty[AsmLine]) { - case (acc, (str, i)) => - acc ++ Chain( - Directive.Int(str.size), - LabelDef(s".L.str$i"), - Directive.Asciz(str.escaped) - ) + val strDirs = strings.toList.zipWithIndex.foldMap { case (str, i) => + Chain( + Directive.Int(str.size), + LabelDef(s".L.str$i"), + Directive.Asciz(str.escaped) + ) } - val finalChain = Chain( + val progAsm = Chain(LabelDef("main")).concatAll( + funcPrologue(), + Chain.one(stack.align()), + main.foldMap(generateStmt(_)), + Chain.one(Move(RAX, ImmediateVal(0))), + funcEpilogue(), + generateBuiltInFuncs() + ) + + Chain( Directive.IntelSyntax, Directive.Global("main"), Directive.RoData - ) ++ strDirs ++ Chain.one(Directive.Text) ++ progAsm - - finalChain.toList - + ).concatAll( + strDirs, + Chain.one(Directive.Text), + progAsm + ).toList } def wrapFunc(labelName: String, funcBody: Chain[AsmLine])(using @@ -137,7 +138,11 @@ object asmGenerator { chain } - def generateStmt(stmt: Stmt)(using stack: Stack, strings: ListBuffer[String], labelGenerator: LabelGenerator): Chain[AsmLine] = { + def generateStmt(stmt: Stmt)(using + stack: Stack, + strings: ListBuffer[String], + labelGenerator: LabelGenerator + ): Chain[AsmLine] = { var chain = Chain.empty[AsmLine] stmt match { @@ -214,21 +219,20 @@ object asmGenerator { 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(RAX) + chain += Load(RAX, IndexAddress(RIP, LabelArg(s".L.str${strings.size - 1}"))) + chain += stack.push(RAX) case _ => // Other array types TODO } case BoolLiter(v) => chain += stack.push(ImmediateVal(if (v) 1 else 0)) case NullLiter() => chain += stack.push(ImmediateVal(0)) case ArrayElem(_, _) => // TODO: Implement handling - case UnaryOp(x, op) => chain ++= evalExprOntoStack(x) op match { case UnaryOperator.Chr | UnaryOperator.Ord | UnaryOperator.Len => // No op needed case UnaryOperator.Negate => chain += Negate(stack.head(SizeDir.Word)) - case UnaryOperator.Not => + case UnaryOperator.Not => chain += Xor(stack.head(SizeDir.Word), ImmediateVal(1)) }