diff --git a/src/main/wacc/backend/asmGenerator.scala b/src/main/wacc/backend/asmGenerator.scala index deeaf8e..27eb1ec 100644 --- a/src/main/wacc/backend/asmGenerator.scala +++ b/src/main/wacc/backend/asmGenerator.scala @@ -50,7 +50,11 @@ object asmGenerator { generateBuiltInFuncs() val strDirs = strings.toList.zipWithIndex.flatMap { case (str, i) => - List(Directive.Int(str.size), LabelDef(s".L.str$i"), Directive.Asciz(str.replace("\"", "\\\""))) + List( + Directive.Int(str.size), + LabelDef(s".L.str$i"), + Directive.Asciz(str.replace("\"", "\\\"")) + ) } List(Directive.IntelSyntax, Directive.Global("main"), Directive.RoData) ++ @@ -89,7 +93,7 @@ object asmGenerator { wrapFunc( labelGenerator.getLabel(Builtin.Malloc), List( - stack.align(), + stack.align() ) ) ++ wrapFunc(labelGenerator.getLabel(Builtin.Free), List()) ++ @@ -126,7 +130,7 @@ object asmGenerator { evalExprOntoStack(rhs) ++ List( stack.pop(RAX), - Move(dest(), RAX), + Move(dest(), RAX) ) case If(cond, thenBranch, elseBranch) => { val elseLabel = labelGenerator.getLabel() @@ -165,7 +169,7 @@ object asmGenerator { stack: Stack, strings: ListBuffer[String] ): List[AsmLine] = { - expr match { + val out = expr match { case IntLiter(v) => List(stack.push(ImmediateVal(v))) case CharLiter(v) => @@ -196,23 +200,24 @@ object asmGenerator { case NullLiter() => List(stack.push(ImmediateVal(0))) case ArrayElem(value, indices) => List() case UnaryOp(x, op) => - op match { - // TODO: chr and ord are TYPE CASTS. They do not change the internal value, - // but will need bound checking e.t.c. - case UnaryOperator.Chr => List() - case UnaryOperator.Ord => List() - case UnaryOperator.Len => List() - case UnaryOperator.Negate => - List( - Negate(stack.head(SizeDir.Word)) - ) - case UnaryOperator.Not => - evalExprOntoStack(x) ++ + evalExprOntoStack(x) ++ + (op match { + // TODO: chr and ord are TYPE CASTS. They do not change the internal value, + // but will need bound checking e.t.c. + case UnaryOperator.Chr => List() + case UnaryOperator.Ord => List() + case UnaryOperator.Len => List() + case UnaryOperator.Negate => List( - Xor(stack.head(SizeDir.Word), ImmediateVal(1)) + Negate(stack.head(SizeDir.Word)) ) + case UnaryOperator.Not => + evalExprOntoStack(x) ++ + List( + Xor(stack.head(SizeDir.Word), ImmediateVal(1)) + ) - } + }) case BinaryOp(x, y, op) => op match { case BinaryOperator.Add => @@ -288,8 +293,11 @@ object asmGenerator { Or(stack.head(SizeDir.Word), EAX) ) } - case call: microWacc.Call => generateCall(call) + case call: microWacc.Call => + generateCall(call) ++ + List(stack.push(RAX)) } + if out.isEmpty then List(stack.push(ImmediateVal(0))) else out } def generateCall(call: microWacc.Call)(using @@ -305,35 +313,10 @@ object asmGenerator { args.drop(argRegs.size).flatMap(evalExprOntoStack) ++ List(assemblyIR.Call(LabelArg(labelGenerator.getLabel(target)))) ++ (if (args.size > argRegs.size) { - List(stack.reserve(args.size - argRegs.size)) + List(stack.drop(args.size - argRegs.size)) } else Nil) } - // def readIntoVar(dest: IndexAddress, readType: Builtin.ReadInt.type | Builtin.ReadChar.type)(using - // stack: Stack, - // strings: ListBuffer[String] - // ): List[AsmLine] = { - // readType match { - // case Builtin.ReadInt => - // strings += PrintFormat.Int.toString - // case Builtin.ReadChar => - // strings += PrintFormat.Char.toString - // } - // List( - // Load( - // RDI, - // IndexAddress( - // RIP, - // LabelArg(s".L.str${strings.size - 1}") - // ) - // ), - // Load(RSI, dest) - // ) ++ - // // alignStack() ++ - // List(assemblyIR.Call(CLibFunc.Scanf)) - - // } - def generateComparison(x: Expr, y: Expr, cond: Cond)(using stack: Stack, strings: ListBuffer[String] @@ -366,91 +349,6 @@ object asmGenerator { ) } - // def saveRegs(regList: List[Register]): List[AsmLine] = regList.map(Push(_)) - // def restoreRegs(regList: List[Register]): List[AsmLine] = regList.reverse.map(Pop(_)) - -// TODO: refactor, really ugly function -// def printF(expr: Expr)(using -// stack: Stack, -// strings: ListBuffer[String] -// ): List[AsmLine] = { -// // determine the format string -// expr.ty match { -// case KnownType.String => -// strings += PrintFormat.String.toString -// case KnownType.Char => -// strings += PrintFormat.Char.toString -// case KnownType.Int => -// strings += PrintFormat.Int.toString -// case _ => -// strings += PrintFormat.String.toString -// } -// List( -// Load( -// RDI, -// IndexAddress( -// RIP, -// LabelArg(s".L.str${strings.size - 1}") -// ) -// ) -// ) -// ++ -// // determine the actual value to print -// (if (expr.ty == KnownType.Bool) { -// expr match { -// case BoolLiter(true) => { -// strings += "true" -// } -// case _ => { -// strings += "false" -// } -// } -// List( -// Load( -// RDI, -// IndexAddress( -// RIP, -// LabelArg(s".L.str${strings.size - 1}") -// ) -// ) -// ) - -// } else { -// evalExprOntoStack(expr) ++ -// List(Pop(RSI)) -// }) -// // print the value -// ++ -// List( -// assemblyIR.Call(CLibFunc.PrintF), -// Move(RDI, ImmediateVal(0)), -// assemblyIR.Call(CLibFunc.Fflush) -// ) -// } - -// prints a new line - // def printLn()(using - // stack: Stack, - // strings: ListBuffer[String] - // ): List[AsmLine] = { - // strings += "" - // Load( - // RDI, - // IndexAddress( - // RIP, - // LabelArg(s".L.str${strings.size - 1}") - // ) - // ) - // :: - // List( - // assemblyIR.Call(CLibFunc.Puts), - // Move(RDI, ImmediateVal(0)), - // assemblyIR.Call(CLibFunc.Fflush) - // ) - - // } - - class Stack { private val stack = LinkedHashMap[Expr | Int, Int]() private val RSP = Register(RegSize.R64, RegName.SP) @@ -474,11 +372,11 @@ object asmGenerator { } def reserve(n: Int = 1): AsmLine = { (1 to n).foreach(_ => stack += stack.size -> next) - Subtract(RSP, ImmediateVal(n*8)) + Subtract(RSP, ImmediateVal(n * 8)) } - def drop(n : Int = 1): AsmLine = { + def drop(n: Int = 1): AsmLine = { (1 to n).foreach(_ => stack.remove(stack.last._1)) - Add(RSP, ImmediateVal(n*8)) + Add(RSP, ImmediateVal(n * 8)) } def accessVar(ident: Ident): () => IndexAddress = () => { IndexAddress(RSP, (stack.size - stack(ident)) * 8) diff --git a/src/test/wacc/examples.scala b/src/test/wacc/examples.scala index e7397b6..1fae3d7 100644 --- a/src/test/wacc/examples.scala +++ b/src/test/wacc/examples.scala @@ -27,13 +27,13 @@ class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll with Paral forEvery(files) { (filename, expectedResult) => val baseFilename = filename.stripSuffix(".wacc") given stdout: PrintStream = PrintStream(File(baseFilename + ".out")) - val result = compile(filename) s"$filename" should "be compiled with correct result" in { + val result = compile(filename) assert(expectedResult.contains(result)) } - if (result == 0) it should "run with correct result" in { + if (expectedResult == List(0)) it should "run with correct result" in { if (fileIsDisallowedBackend(filename)) pending // Retrieve contents to get input and expected output + exit code @@ -85,24 +85,24 @@ class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll with Paral Seq( // format: off // disable formatting to avoid binPack - // "^.*wacc-examples/valid/advanced.*$", - // "^.*wacc-examples/valid/array.*$", - // "^.*wacc-examples/valid/basic/exit.*$", - // "^.*wacc-examples/valid/basic/skip.*$", - // "^.*wacc-examples/valid/expressions.*$", - // "^.*wacc-examples/valid/function/nested_functions.*$", - // "^.*wacc-examples/valid/function/simple_functions.*$", - // "^.*wacc-examples/valid/if.*$", - // "^.*wacc-examples/valid/IO/print.*$", - // "^.*wacc-examples/valid/IO/read.*$", - // "^.*wacc-examples/valid/IO/IOLoop.wacc.*$", - // "^.*wacc-examples/valid/IO/IOSequence.wacc.*$", - // "^.*wacc-examples/valid/pairs.*$", - // "^.*wacc-examples/valid/runtimeErr.*$", - // "^.*wacc-examples/valid/scope.*$", - // "^.*wacc-examples/valid/sequence.*$", - // "^.*wacc-examples/valid/variables.*$", - // "^.*wacc-examples/valid/while.*$", + "^.*wacc-examples/valid/advanced.*$", + "^.*wacc-examples/valid/array.*$", + "^.*wacc-examples/valid/basic/exit.*$", + "^.*wacc-examples/valid/basic/skip.*$", + "^.*wacc-examples/valid/expressions.*$", + "^.*wacc-examples/valid/function/nested_functions.*$", + "^.*wacc-examples/valid/function/simple_functions.*$", + "^.*wacc-examples/valid/if.*$", + "^.*wacc-examples/valid/IO/print.*$", + "^.*wacc-examples/valid/IO/read.*$", + "^.*wacc-examples/valid/IO/IOLoop.wacc.*$", + "^.*wacc-examples/valid/IO/IOSequence.wacc.*$", + "^.*wacc-examples/valid/pairs.*$", + "^.*wacc-examples/valid/runtimeErr.*$", + "^.*wacc-examples/valid/scope.*$", + "^.*wacc-examples/valid/sequence.*$", + "^.*wacc-examples/valid/variables.*$", + "^.*wacc-examples/valid/while.*$", // format: on ).find(filename.matches).isDefined }