use var initializer assignments in a clearer way

This commit is contained in:
Irmen de Jong 2022-01-11 00:34:44 +01:00
parent de3b2fb95b
commit 056ec986c2
7 changed files with 34 additions and 21 deletions

View File

@ -220,11 +220,7 @@ class AsmGen(private val program: Program,
if(options.dontReinitGlobals) {
block.statements.asSequence().filterIsInstance<VarDecl>().forEach {
it.zeropage = ZeropageWish.NOT_IN_ZEROPAGE
val init = it.nextSibling() as? Assignment
if(init?.target?.identifier?.targetVarDecl(program) === it) {
// put the init value back into the vardecl
it.value = init.value
}
it.findInitializer(program)?.let { initializer -> it.value = initializer.value } // put the init value back into the vardecl
}
}

View File

@ -85,4 +85,16 @@ class AstPreprocessor(val program: Program, val errors: IErrorReporter) : AstWal
}
return noModifications
}
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
val nextAssignment = decl.nextSibling() as? Assignment
if(nextAssignment!=null && nextAssignment.origin!=AssignmentOrigin.VARINIT) {
// check if it's a proper initializer assignment for the variable
if(decl.value==null && nextAssignment.target.identifier?.targetVarDecl(program)===decl) {
if(!nextAssignment.value.referencesIdentifier(nextAssignment.target.identifier!!.nameInSource))
nextAssignment.origin = AssignmentOrigin.VARINIT
}
}
return noModifications
}
}

View File

@ -58,16 +58,9 @@ internal class StatementReorderer(val program: Program,
// no need to zero out the special internal returnvalue intermediates.
return noModifications
}
val nextStmt = decl.nextSibling()
val nextAssign = nextStmt as? Assignment
if(nextAssign!=null && !nextAssign.isAugmentable) {
val target = nextAssign.target.identifier?.targetStatement(program)
if(target === decl) {
// an initializer assignment for a vardecl is already here
return noModifications
}
}
val nextFor = nextStmt as? ForLoop
if(decl.findInitializer(program)!=null)
return noModifications // an initializer assignment for a vardecl is already here
val nextFor = decl.nextSibling() as? ForLoop
val hasNextForWithThisLoopvar = nextFor?.loopVar?.nameInSource==listOf(decl.name)
if (!hasNextForWithThisLoopvar) {
// Add assignment to initialize with zero

View File

@ -10,7 +10,6 @@ import prog8.ast.base.DataType
import prog8.ast.base.VarDeclType
import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.statements.Assignment
import prog8.codegen.target.Cx16Target
import prog8tests.helpers.assertSuccess
import prog8tests.helpers.compileText
@ -76,7 +75,7 @@ class TestCompilerOnCharLit: FunSpec({
withClue("initializer value should have been moved to separate assignment"){
decl.value shouldBe null
}
val assignInitialValue = decl.nextSibling() as Assignment
val assignInitialValue = decl.findInitializer(program)!!
assignInitialValue.target.identifier!!.nameInSource shouldBe listOf("ch")
withClue("char literal should have been replaced by ubyte literal") {
assignInitialValue.value shouldBe instanceOf<NumericLiteralValue>()

View File

@ -604,24 +604,26 @@ class TestOptimization: FunSpec({
uword @shared zz
zz += 60 ; NOT ok to remove initializer, should evaluate to 60
ubyte @shared xx
xx = 6+sin8u(xx) ; NOT ok to remove initializer
xx = 6+sin8u(xx) ; is not an initializer because it references xx
}
}
"""
val result = compileText(C64Target, optimize=true, src, writeAssembly=false).assertSuccess()
printProgram(result.program)
/* expected result:
uword yy
yy = 20
uword zz
zz = 60
ubyte xx
xx = 0
xx = sin8u(xx)
xx += 6
*/
val stmts = result.program.entrypoint.statements
stmts.size shouldBe 7
stmts.size shouldBe 8
stmts.filterIsInstance<VarDecl>().size shouldBe 3
stmts.filterIsInstance<Assignment>().size shouldBe 4
stmts.filterIsInstance<Assignment>().size shouldBe 5
}
test("only substitue assignments with 0 after a =0 initializer if it is the same variable") {

View File

@ -272,6 +272,12 @@ class VarDecl(val type: VarDeclType,
copy.allowInitializeWithZero = this.allowInitializeWithZero
return copy
}
fun findInitializer(program: Program): Assignment? =
(parent as IStatementContainer).statements
.asSequence()
.filterIsInstance<Assignment>()
.singleOrNull { it.origin==AssignmentOrigin.VARINIT && it.target.identifier?.targetVarDecl(program) === this }
}
class ArrayIndex(var indexExpr: Expression,
@ -399,6 +405,12 @@ class Assignment(var target: AssignTarget, var value: Expression, var origin: As
return false
}
fun initializerFor(program: Program) =
if(origin==AssignmentOrigin.VARINIT)
target.identifier!!.targetVarDecl(program)
else
null
}
data class AssignTarget(var identifier: IdentifierReference?,

View File

@ -3,7 +3,6 @@ TODO
For next compiler release (7.7)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- use the assignment origin? in codegen? (origin VARINIT)
- optimize codegen of pipe operator to avoid needless assigns to temp var