Skip to content

Commit 81bd5c7

Browse files
committed
don't remove consecutive assigns to IO space location
1 parent b526e13 commit 81bd5c7

File tree

3 files changed

+70
-6
lines changed

3 files changed

+70
-6
lines changed

compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,18 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
6262
}
6363

6464
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
65-
val nextAssign = assignment.nextSibling() as? Assignment
66-
if(nextAssign!=null && nextAssign.target.isSameAs(assignment.target, program)) {
67-
if(!nextAssign.isAugmentable && nextAssign.value isSameAs assignment.value && assignment.value !is IFunctionCall) // don't remove function calls even when they're duplicates
68-
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
65+
// remove duplicated assignments, but not if it's a memory mapped IO register
66+
val isIO = try {
67+
assignment.target.isIOAddress(options.compTarget.machine)
68+
} catch (_: FatalAstException) {
69+
false
70+
}
71+
if(!isIO) {
72+
val nextAssign = assignment.nextSibling() as? Assignment
73+
if (nextAssign != null && nextAssign.target.isSameAs(assignment.target, program)) {
74+
if (!nextAssign.isAugmentable && nextAssign.value isSameAs assignment.value && assignment.value !is IFunctionCall) // don't remove function calls even when they're duplicates
75+
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
76+
}
6977
}
7078

7179
return noModifications

compiler/test/TestOptimization.kt

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import prog8.ast.statements.*
1515
import prog8.code.core.DataType
1616
import prog8.code.core.Position
1717
import prog8.code.target.C64Target
18+
import prog8.code.target.Cx16Target
1819
import prog8.compiler.printProgram
1920
import prog8tests.helpers.*
2021

@@ -736,4 +737,60 @@ class TestOptimization: FunSpec({
736737
val stmts = result.program.entrypoint.statements
737738
stmts.size shouldBe 3
738739
}
740+
741+
test("repeated assignments to IO register should remain") {
742+
val srcX16="""
743+
main {
744+
sub start() {
745+
ubyte @shared xx
746+
xx = 42
747+
xx = 42 ; removed
748+
xx = 42 ; removed
749+
cx16.VERA_DATA0 = 0
750+
cx16.VERA_DATA0 = 0
751+
cx16.VERA_DATA0 = 0
752+
@($9fff) = 0
753+
@($9fff) = 0
754+
@($9fff) = 0
755+
return
756+
}
757+
}"""
758+
var result = compileText(Cx16Target(), true, srcX16, writeAssembly = true)!!
759+
var statements = result.program.entrypoint.statements
760+
statements.size shouldBe 9
761+
(statements[1] as Assignment).target.identifier!!.nameInSource shouldBe listOf("xx")
762+
(statements[2] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "VERA_DATA0")
763+
(statements[3] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "VERA_DATA0")
764+
(statements[4] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "VERA_DATA0")
765+
(statements[5] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 0x9fff
766+
(statements[6] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 0x9fff
767+
(statements[7] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 0x9fff
768+
769+
val srcC64="""
770+
main {
771+
sub start() {
772+
ubyte @shared xx
773+
xx = 42
774+
xx = 42 ;removed
775+
xx = 42 ;removed
776+
c64.EXTCOL = 0
777+
c64.EXTCOL = 0
778+
c64.EXTCOL = 0
779+
@(53281) = 0
780+
@(53281) = 0
781+
@(53281) = 0
782+
return
783+
}
784+
}"""
785+
result = compileText(C64Target(), true, srcC64, writeAssembly = true)!!
786+
statements = result.program.entrypoint.statements
787+
statements.size shouldBe 9
788+
(statements[1] as Assignment).target.identifier!!.nameInSource shouldBe listOf("xx")
789+
(statements[2] as Assignment).target.identifier!!.nameInSource shouldBe listOf("c64", "EXTCOL")
790+
(statements[3] as Assignment).target.identifier!!.nameInSource shouldBe listOf("c64", "EXTCOL")
791+
(statements[4] as Assignment).target.identifier!!.nameInSource shouldBe listOf("c64", "EXTCOL")
792+
(statements[5] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 53281.0
793+
(statements[6] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 53281.0
794+
(statements[7] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 53281.0
795+
}
739796
})

compilerAst/src/prog8/ast/statements/AstStatements.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,7 @@ data class AssignTarget(var identifier: IdentifierReference?,
532532
} else false
533533
}
534534
ident != null -> {
535-
val decl = ident.targetVarDecl(definingModule.program) ?:
536-
throw FatalAstException("invalid identifier ${ident.nameInSource}")
535+
val decl = ident.targetVarDecl(definingModule.program) ?: throw FatalAstException("invalid identifier ${ident.nameInSource}")
537536
return if (decl.type == VarDeclType.MEMORY && decl.value is NumericLiteral)
538537
machine.isIOAddress((decl.value as NumericLiteral).number.toUInt())
539538
else

0 commit comments

Comments
 (0)