preparing optimizing pointer indexing

This commit is contained in:
Irmen de Jong
2022-06-04 12:46:32 +02:00
parent 0349d1d57c
commit c40cfaa388
5 changed files with 48 additions and 27 deletions

View File

@@ -3,19 +3,16 @@ package prog8.compiler.astprocessing
import prog8.ast.Node import prog8.ast.Node
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.expressions.ArrayIndexedExpression import prog8.ast.expressions.ArrayIndexedExpression
import prog8.ast.expressions.BinaryExpression
import prog8.ast.expressions.DirectMemoryRead
import prog8.ast.statements.AssignTarget
import prog8.ast.statements.DirectMemoryWrite
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.statements.VarDecl import prog8.ast.statements.VarDecl
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.code.core.DataType
internal class AstVariousTransforms(private val program: Program) : AstWalker() { internal class AstVariousTransforms(private val program: Program) : AstWalker() {
// TODO can this be integrated in another walker
override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> { override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> {
// For non-kernal subroutines and non-asm parameters: // For non-kernal subroutines and non-asm parameters:
// inject subroutine params as local variables (if they're not there yet). // inject subroutine params as local variables (if they're not there yet).
@@ -38,29 +35,8 @@ internal class AstVariousTransforms(private val program: Program) : AstWalker()
return noModifications return noModifications
} }
// TODO move this / remove this. Needed here atm otherwise a replacement error occurs later in StatementReorderer
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> { override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
return replacePointerVarIndexWithMemreadOrMemwrite(program, arrayIndexedExpression, parent) return replacePointerVarIndexWithMemreadOrMemwrite(program, arrayIndexedExpression, parent)
} }
} }
internal fun replacePointerVarIndexWithMemreadOrMemwrite(program: Program, arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
val arrayVar = arrayIndexedExpression.arrayvar.targetVarDecl(program)
if(arrayVar!=null && arrayVar.datatype == DataType.UWORD) {
// rewrite pointervar[index] into @(pointervar+index)
val indexer = arrayIndexedExpression.indexer
val add = BinaryExpression(arrayIndexedExpression.arrayvar.copy(), "+", indexer.indexExpr, arrayIndexedExpression.position)
return if(parent is AssignTarget) {
// we're part of the target of an assignment, we have to actually change the assign target itself
val memwrite = DirectMemoryWrite(add, arrayIndexedExpression.position)
val newtarget = AssignTarget(null, null, memwrite, arrayIndexedExpression.position)
listOf(IAstModification.ReplaceNode(parent, newtarget, parent.parent))
} else {
val memread = DirectMemoryRead(add, arrayIndexedExpression.position)
listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent))
}
}
return emptyList()
}

View File

@@ -576,3 +576,25 @@ private fun makeGosubWithArgsViaCpuStack(
} }
return listOf(IAstModification.ReplaceNode(call as Node, scope, parent)) return listOf(IAstModification.ReplaceNode(call as Node, scope, parent))
} }
internal fun replacePointerVarIndexWithMemreadOrMemwrite(program: Program, arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
val arrayVar = arrayIndexedExpression.arrayvar.targetVarDecl(program)
if(arrayVar!=null && arrayVar.datatype == DataType.UWORD) {
// rewrite pointervar[index] into @(pointervar+index)
val indexer = arrayIndexedExpression.indexer
val add = BinaryExpression(arrayIndexedExpression.arrayvar.copy(), "+", indexer.indexExpr, arrayIndexedExpression.position)
return if(parent is AssignTarget) {
// we're part of the target of an assignment, we have to actually change the assign target itself
val memwrite = DirectMemoryWrite(add, arrayIndexedExpression.position)
val newtarget = AssignTarget(null, null, memwrite, arrayIndexedExpression.position)
listOf(IAstModification.ReplaceNode(parent, newtarget, parent.parent))
} else {
val memread = DirectMemoryRead(add, arrayIndexedExpression.position)
listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent))
}
}
return emptyList()
}

View File

@@ -757,4 +757,19 @@ class TestOptimization: FunSpec({
val ifStmt = stmts[4] as IfElse val ifStmt = stmts[4] as IfElse
ifStmt.condition shouldBe instanceOf<BinaryExpression>() ifStmt.condition shouldBe instanceOf<BinaryExpression>()
} }
test("pointer indexing inside other expression ok") {
val src="""
main{
sub start () {
uword eRef
if eRef[3] and 10 {
return
}
}
}"""
val result = compileText(C64Target(), optimize=true, src, writeAssembly=false)!!
val stmts = result.program.entrypoint.statements
stmts.size shouldBe 3
}
}) })

View File

@@ -3,6 +3,7 @@ TODO
For next release For next release
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
- try to integrated AstVariousTransforms into another walker
- why is this code so much larger: - why is this code so much larger:
uword xx uword xx
for xx in 0 to size-1 { for xx in 0 to size-1 {

View File

@@ -28,6 +28,13 @@ main {
; txt.spc() ; txt.spc()
; } ; }
sub crash () {
uword eRef
if eRef[3] and 10 {
return
}
}
sub start() { sub start() {
; mcCarthy() ; mcCarthy()