From f0f6150e18fa6c48e1a8ad2cc83336b866dde810 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 23 Dec 2020 02:30:46 +0100 Subject: [PATCH] fix problem with reuse of auto-indexer-variables that could result in wrong code for routines using multiple array indexings --- .../ast/processing/StatementReorderer.kt | 28 ++++++++----------- .../src/prog8/ast/statements/AstStatements.kt | 2 +- docs/source/todo.rst | 1 - examples/cx16/gfx2.p8 | 25 +++++++++++++---- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/compiler/src/prog8/ast/processing/StatementReorderer.kt b/compiler/src/prog8/ast/processing/StatementReorderer.kt index 5d2742017..e78eb18ec 100644 --- a/compiler/src/prog8/ast/processing/StatementReorderer.kt +++ b/compiler/src/prog8/ast/processing/StatementReorderer.kt @@ -156,28 +156,22 @@ internal class StatementReorderer(val program: Program, val errors: ErrorReporte val indexerVarPrefix = "prog8_autovar_index_" val repo = subroutine.asmGenInfo.usedAutoArrayIndexerForStatements - // TODO make this even smarter so that an indexerVar can be reused for a different following statement... requires updating the partOfStatement? - var indexerVar = repo.firstOrNull { it.replaces isSameAs expr.indexer } - if(indexerVar==null) { - // add another loop index var to be used for this expression - val indexerVarName = "$indexerVarPrefix${expr.indexer.hashCode()}" - indexerVar = AsmGenInfo.ArrayIndexerInfo(indexerVarName, expr.indexer, statement) - repo.add(indexerVar) - // create the indexer var at block level scope - val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.PREFER_ZEROPAGE, - null, indexerVarName, null, null, isArray = false, autogeneratedDontRemove = true, position = expr.position) - modifications.add(IAstModification.InsertFirst(vardecl, subroutine)) - } - indexerVar.used++ // keep track of how many times it it used, to avoid assigning it multiple times + // TODO make this a bit smarter so it can reuse indexer variables. BUT BEWARE of scoping+initialization problems then + // add another loop index var to be used for this expression + val indexerVarName = "$indexerVarPrefix${expr.indexer.hashCode()}" + val indexerVar = AsmGenInfo.ArrayIndexerInfo(indexerVarName, expr.indexer) + repo.add(indexerVar) + // create the indexer var at block level scope + val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.PREFER_ZEROPAGE, + null, indexerVarName, null, null, isArray = false, autogeneratedDontRemove = true, position = expr.position) + modifications.add(IAstModification.InsertFirst(vardecl, subroutine)) // replace the indexer with just the variable // assign the indexing expression to the helper variable, but only if that hasn't been done already val indexerExpression = expr.indexer.origExpression!! val target = AssignTarget(IdentifierReference(listOf(indexerVar.name), indexerExpression.position), null, null, indexerExpression.position) - if(indexerVar.used==1) { - val assign = Assignment(target, indexerExpression, indexerExpression.position) - modifications.add(IAstModification.InsertBefore(statement, assign, statement.definingScope())) - } + val assign = Assignment(target, indexerExpression, indexerExpression.position) + modifications.add(IAstModification.InsertBefore(statement, assign, statement.definingScope())) modifications.add(IAstModification.SetExpression( { expr.indexer.indexVar = it as IdentifierReference expr.indexer.indexNum = null diff --git a/compiler/src/prog8/ast/statements/AstStatements.kt b/compiler/src/prog8/ast/statements/AstStatements.kt index 1afb020f0..96681b6b0 100644 --- a/compiler/src/prog8/ast/statements/AstStatements.kt +++ b/compiler/src/prog8/ast/statements/AstStatements.kt @@ -698,7 +698,7 @@ class AsmGenInfo { var usedFloatEvalResultVar1 = false var usedFloatEvalResultVar2 = false - class ArrayIndexerInfo(val name: String, val replaces: ArrayIndex, val partOfStatement: Statement, var used: Int=0) + class ArrayIndexerInfo(val name: String, val replaces: ArrayIndex) } // the subroutine class covers both the normal user-defined subroutines, diff --git a/docs/source/todo.rst b/docs/source/todo.rst index a859b1140..8560cd105 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO ==== - optimize (byte) bitshifting 1< { - cx16.vpoke_or(0, y*(320/8) + x/8, bits[lsb(x)&7]) ; TODO !?!? if the &7 remains, the code at the '128' label is wrong!!! if changed or removed, the code at 128 works fine! + cx16.vpoke_or(0, y*(320/8) + x/8, bits[lsb(x)&7]) } 1 -> { void addr_mul_320_add_24(y, x) ; 24 bits result is in r0 and r1L