mirror of
https://github.com/irmen/prog8.git
synced 2025-02-18 05:30:34 +00:00
fix problem with reuse of auto-indexer-variables that could result in wrong code for routines using multiple array indexings
This commit is contained in:
parent
dc600cc3ed
commit
f0f6150e18
@ -156,28 +156,22 @@ internal class StatementReorderer(val program: Program, val errors: ErrorReporte
|
|||||||
val indexerVarPrefix = "prog8_autovar_index_"
|
val indexerVarPrefix = "prog8_autovar_index_"
|
||||||
val repo = subroutine.asmGenInfo.usedAutoArrayIndexerForStatements
|
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?
|
// TODO make this a bit smarter so it can reuse indexer variables. BUT BEWARE of scoping+initialization problems then
|
||||||
var indexerVar = repo.firstOrNull { it.replaces isSameAs expr.indexer }
|
// add another loop index var to be used for this expression
|
||||||
if(indexerVar==null) {
|
val indexerVarName = "$indexerVarPrefix${expr.indexer.hashCode()}"
|
||||||
// add another loop index var to be used for this expression
|
val indexerVar = AsmGenInfo.ArrayIndexerInfo(indexerVarName, expr.indexer)
|
||||||
val indexerVarName = "$indexerVarPrefix${expr.indexer.hashCode()}"
|
repo.add(indexerVar)
|
||||||
indexerVar = AsmGenInfo.ArrayIndexerInfo(indexerVarName, expr.indexer, statement)
|
// create the indexer var at block level scope
|
||||||
repo.add(indexerVar)
|
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.PREFER_ZEROPAGE,
|
||||||
// create the indexer var at block level scope
|
null, indexerVarName, null, null, isArray = false, autogeneratedDontRemove = true, position = expr.position)
|
||||||
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.PREFER_ZEROPAGE,
|
modifications.add(IAstModification.InsertFirst(vardecl, subroutine))
|
||||||
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
|
|
||||||
|
|
||||||
// replace the indexer with just the variable
|
// replace the indexer with just the variable
|
||||||
// assign the indexing expression to the helper variable, but only if that hasn't been done already
|
// assign the indexing expression to the helper variable, but only if that hasn't been done already
|
||||||
val indexerExpression = expr.indexer.origExpression!!
|
val indexerExpression = expr.indexer.origExpression!!
|
||||||
val target = AssignTarget(IdentifierReference(listOf(indexerVar.name), indexerExpression.position), null, null, indexerExpression.position)
|
val target = AssignTarget(IdentifierReference(listOf(indexerVar.name), indexerExpression.position), null, null, indexerExpression.position)
|
||||||
if(indexerVar.used==1) {
|
val assign = Assignment(target, indexerExpression, indexerExpression.position)
|
||||||
val assign = Assignment(target, indexerExpression, indexerExpression.position)
|
modifications.add(IAstModification.InsertBefore(statement, assign, statement.definingScope()))
|
||||||
modifications.add(IAstModification.InsertBefore(statement, assign, statement.definingScope()))
|
|
||||||
}
|
|
||||||
modifications.add(IAstModification.SetExpression( {
|
modifications.add(IAstModification.SetExpression( {
|
||||||
expr.indexer.indexVar = it as IdentifierReference
|
expr.indexer.indexVar = it as IdentifierReference
|
||||||
expr.indexer.indexNum = null
|
expr.indexer.indexNum = null
|
||||||
|
@ -698,7 +698,7 @@ class AsmGenInfo {
|
|||||||
var usedFloatEvalResultVar1 = false
|
var usedFloatEvalResultVar1 = false
|
||||||
var usedFloatEvalResultVar2 = 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,
|
// the subroutine class covers both the normal user-defined subroutines,
|
||||||
|
@ -3,7 +3,6 @@ TODO
|
|||||||
====
|
====
|
||||||
|
|
||||||
- optimize (byte) bitshifting 1<<x (and 2**x) via lookup table 1,2,4,8,...
|
- optimize (byte) bitshifting 1<<x (and 2**x) via lookup table 1,2,4,8,...
|
||||||
- Cx16 target: support full-screen 640x480 and 320x240 graphics? That requires our own custom graphics routines though to draw lines, and plot pixels.
|
|
||||||
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)
|
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)
|
||||||
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'
|
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'
|
||||||
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)
|
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)
|
||||||
|
@ -1,18 +1,29 @@
|
|||||||
%import textio
|
%import textio
|
||||||
%import diskio
|
|
||||||
%import floats
|
|
||||||
%import graphics
|
%import graphics
|
||||||
%import test_stack
|
%import test_stack
|
||||||
%zeropage basicsafe
|
|
||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
|
|
||||||
|
; TODO full-screen graphics mode library, in development. (as replacement for the graphics routines in ROM that are constrained to 200 vertical pixels and lores mode only)
|
||||||
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start () {
|
sub start () {
|
||||||
|
ubyte[] modes = [0, 1, 128]
|
||||||
|
ubyte mode
|
||||||
|
for mode in modes {
|
||||||
|
gfx2.set_mode(mode)
|
||||||
|
gfx2.clear_screen()
|
||||||
|
draw()
|
||||||
|
cx16.wait(120)
|
||||||
|
}
|
||||||
|
|
||||||
gfx2.set_mode(128)
|
repeat {
|
||||||
gfx2.clear_screen()
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub draw() {
|
||||||
uword offset
|
uword offset
|
||||||
ubyte angle
|
ubyte angle
|
||||||
uword x
|
uword x
|
||||||
@ -42,11 +53,13 @@ main {
|
|||||||
|
|
||||||
gfx2 {
|
gfx2 {
|
||||||
|
|
||||||
|
; read-only control variables:
|
||||||
ubyte active_mode = 255
|
ubyte active_mode = 255
|
||||||
uword width = 0
|
uword width = 0
|
||||||
uword height = 0
|
uword height = 0
|
||||||
ubyte bpp = 0
|
ubyte bpp = 0
|
||||||
|
|
||||||
|
|
||||||
sub set_mode(ubyte mode) {
|
sub set_mode(ubyte mode) {
|
||||||
; mode 0 = bitmap 320 x 240 x 1c monochrome
|
; mode 0 = bitmap 320 x 240 x 1c monochrome
|
||||||
; mode 1 = bitmap 320 x 240 x 256c
|
; mode 1 = bitmap 320 x 240 x 256c
|
||||||
@ -130,7 +143,7 @@ gfx2 {
|
|||||||
ubyte[8] bits = [128, 64, 32, 16, 8, 4, 2, 1]
|
ubyte[8] bits = [128, 64, 32, 16, 8, 4, 2, 1]
|
||||||
when active_mode {
|
when active_mode {
|
||||||
0 -> {
|
0 -> {
|
||||||
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 -> {
|
1 -> {
|
||||||
void addr_mul_320_add_24(y, x) ; 24 bits result is in r0 and r1L
|
void addr_mul_320_add_24(y, x) ; 24 bits result is in r0 and r1L
|
||||||
|
Loading…
x
Reference in New Issue
Block a user