diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt index cd8554db1..1f276e893 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -100,6 +100,49 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } + val leftBinExpr = binExpr.left as? BinaryExpression + val rightBinExpr = binExpr.right as? BinaryExpression + if(leftBinExpr!=null && rightBinExpr==null) { + if(leftBinExpr.left isSameAs astTarget) { + // X = (X Right) Something + inplaceModification(target, leftBinExpr.operator, leftBinExpr.right) + inplaceModification(target, binExpr.operator, binExpr.right) + return + } + if(leftBinExpr.right isSameAs astTarget) { + // X = (Left X) Something + if(leftBinExpr.operator in associativeOperators) { + inplaceModification(target, leftBinExpr.operator, leftBinExpr.left) + inplaceModification(target, binExpr.operator, binExpr.right) + return + } else { + throw AssemblyError("operands in wrong order for non-associative operator") + } + } + } + if(leftBinExpr==null && rightBinExpr!=null) { + if(rightBinExpr.left isSameAs astTarget) { + // X = Something (X Right) + if(binExpr.operator in associativeOperators) { + inplaceModification(target, rightBinExpr.operator, rightBinExpr.right) + inplaceModification(target, binExpr.operator, binExpr.left) + return + } else { + throw AssemblyError("operands in wrong order for non-associative operator") + } + } + if(rightBinExpr.right isSameAs astTarget) { + // X = Something (Left X) + if(binExpr.operator in associativeOperators && rightBinExpr.operator in associativeOperators) { + inplaceModification(target, rightBinExpr.operator, rightBinExpr.left) + inplaceModification(target, binExpr.operator, binExpr.left) + return + } else { + throw AssemblyError("operands in wrong order for non-associative operator") + } + } + } + throw FatalAstException("assignment should follow augmentable rules $binExpr") } diff --git a/compiler/src/prog8/CompilerMain.kt b/compiler/src/prog8/CompilerMain.kt index cc149a3c7..e5523fdc4 100644 --- a/compiler/src/prog8/CompilerMain.kt +++ b/compiler/src/prog8/CompilerMain.kt @@ -66,6 +66,11 @@ private fun compileMain(args: Array): Boolean { if(srcdirs.firstOrNull()!=".") srcdirs.add(0, ".") + if (compilationTarget != C64Target.name && compilationTarget != Cx16Target.name) { + System.err.println("Invalid compilation target: $compilationTarget") + return false + } + if(watchMode==true) { val watchservice = FileSystems.getDefault().newWatchService() val allImportedFiles = mutableSetOf() diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index 70697d7cd..3bd0b2a8e 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -61,7 +61,6 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport if (!hasNextForWithThisLoopvar) { // Add assignment to initialize with zero // Note: for block-level vars, this will introduce assignments in the block scope. These have to be dealt with correctly later. - // TODO optimize this a bit so that we don't add this statement if the next one would already be an assignment to the same variable val identifier = IdentifierReference(listOf(decl.name), decl.position) val assignzero = Assignment(AssignTarget(identifier, null, null, decl.position), decl.zeroElementValue(), decl.position) return listOf(IAstModification.InsertAfter( diff --git a/compiler/test/TestOptimization.kt b/compiler/test/TestOptimization.kt index 7f643acd3..e2cb09133 100644 --- a/compiler/test/TestOptimization.kt +++ b/compiler/test/TestOptimization.kt @@ -15,7 +15,6 @@ import prog8.ast.base.Position import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.compiler.BeforeAsmGenerationAstChanger -import prog8.compiler.printProgram import prog8.compiler.target.C64Target import prog8.compilerinterface.* import prog8tests.helpers.* @@ -131,19 +130,19 @@ class TestOptimization: FunSpec({ val declY2 = mainsub.statements[7] as VarDecl val initY2 = mainsub.statements[8] as Assignment mainsub.statements[9] shouldBe instanceOf() - (declTest.value as NumericLiteralValue).number.toDouble() shouldBe 10.0 + (declTest.value as NumericLiteralValue).number shouldBe 10.0 declX1.value shouldBe null declX2.value shouldBe null declY1.value shouldBe null declY2.value shouldBe null (initX1.value as NumericLiteralValue).type shouldBe DataType.BYTE - (initX1.value as NumericLiteralValue).number.toDouble() shouldBe 11.0 + (initX1.value as NumericLiteralValue).number shouldBe 11.0 (initX2.value as NumericLiteralValue).type shouldBe DataType.BYTE - (initX2.value as NumericLiteralValue).number.toDouble() shouldBe 11.0 + (initX2.value as NumericLiteralValue).number shouldBe 11.0 (initY1.value as NumericLiteralValue).type shouldBe DataType.UBYTE - (initY1.value as NumericLiteralValue).number.toDouble() shouldBe 11.0 + (initY1.value as NumericLiteralValue).number shouldBe 11.0 (initY2.value as NumericLiteralValue).type shouldBe DataType.UBYTE - (initY2.value as NumericLiteralValue).number.toDouble() shouldBe 11.0 + (initY2.value as NumericLiteralValue).number shouldBe 11.0 } test("typecasted assignment from ubyte logical expressoin to uword var") { @@ -495,7 +494,8 @@ class TestOptimization: FunSpec({ } }""" val result = compileText(C64Target, optimize=false, src, writeAssembly=true).assertSuccess() - result.program.entrypoint.statements.size shouldBe 10 + result.program.entrypoint.statements.size shouldBe 11 + result.program.entrypoint.statements.last() shouldBe instanceOf() } test("keep the value initializer assignment if the next one depends on it") { @@ -512,7 +512,6 @@ class TestOptimization: FunSpec({ } """ val result = compileText(C64Target, optimize=true, src, writeAssembly=false).assertSuccess() - printProgram(result.program) /* expected result: uword yy yy = 20 diff --git a/docs/source/todo.rst b/docs/source/todo.rst index fd0d98146..d8f1a12ba 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,12 +3,8 @@ TODO For next compiler release (7.4) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -fix "test augmented expression asmgen" unittest (and textelite compilation) - -optimize TODO in "Add assignment to initialize with zero" in StatementReorderer -optimize TODO in after(assignment) in VariousCleanups optimize: add some more constant folders mentioned in test.p8 -optimize: there is an optimizations in AsmOptimizer that can only be done correctly +optimize: there is an optimization in AsmOptimizer that can only be done correctly if it knows about regular ram vs io space ram distinction.