mirror of
https://github.com/irmen/prog8.git
synced 2024-09-07 19:54:26 +00:00
use var initializer assignments in a clearer way
This commit is contained in:
parent
de3b2fb95b
commit
056ec986c2
@ -220,11 +220,7 @@ class AsmGen(private val program: Program,
|
|||||||
if(options.dontReinitGlobals) {
|
if(options.dontReinitGlobals) {
|
||||||
block.statements.asSequence().filterIsInstance<VarDecl>().forEach {
|
block.statements.asSequence().filterIsInstance<VarDecl>().forEach {
|
||||||
it.zeropage = ZeropageWish.NOT_IN_ZEROPAGE
|
it.zeropage = ZeropageWish.NOT_IN_ZEROPAGE
|
||||||
val init = it.nextSibling() as? Assignment
|
it.findInitializer(program)?.let { initializer -> it.value = initializer.value } // put the init value back into the vardecl
|
||||||
if(init?.target?.identifier?.targetVarDecl(program) === it) {
|
|
||||||
// put the init value back into the vardecl
|
|
||||||
it.value = init.value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,4 +85,16 @@ class AstPreprocessor(val program: Program, val errors: IErrorReporter) : AstWal
|
|||||||
}
|
}
|
||||||
return noModifications
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,16 +58,9 @@ internal class StatementReorderer(val program: Program,
|
|||||||
// no need to zero out the special internal returnvalue intermediates.
|
// no need to zero out the special internal returnvalue intermediates.
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
val nextStmt = decl.nextSibling()
|
if(decl.findInitializer(program)!=null)
|
||||||
val nextAssign = nextStmt as? Assignment
|
return noModifications // an initializer assignment for a vardecl is already here
|
||||||
if(nextAssign!=null && !nextAssign.isAugmentable) {
|
val nextFor = decl.nextSibling() as? ForLoop
|
||||||
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
|
|
||||||
val hasNextForWithThisLoopvar = nextFor?.loopVar?.nameInSource==listOf(decl.name)
|
val hasNextForWithThisLoopvar = nextFor?.loopVar?.nameInSource==listOf(decl.name)
|
||||||
if (!hasNextForWithThisLoopvar) {
|
if (!hasNextForWithThisLoopvar) {
|
||||||
// Add assignment to initialize with zero
|
// Add assignment to initialize with zero
|
||||||
|
@ -10,7 +10,6 @@ import prog8.ast.base.DataType
|
|||||||
import prog8.ast.base.VarDeclType
|
import prog8.ast.base.VarDeclType
|
||||||
import prog8.ast.expressions.IdentifierReference
|
import prog8.ast.expressions.IdentifierReference
|
||||||
import prog8.ast.expressions.NumericLiteralValue
|
import prog8.ast.expressions.NumericLiteralValue
|
||||||
import prog8.ast.statements.Assignment
|
|
||||||
import prog8.codegen.target.Cx16Target
|
import prog8.codegen.target.Cx16Target
|
||||||
import prog8tests.helpers.assertSuccess
|
import prog8tests.helpers.assertSuccess
|
||||||
import prog8tests.helpers.compileText
|
import prog8tests.helpers.compileText
|
||||||
@ -76,7 +75,7 @@ class TestCompilerOnCharLit: FunSpec({
|
|||||||
withClue("initializer value should have been moved to separate assignment"){
|
withClue("initializer value should have been moved to separate assignment"){
|
||||||
decl.value shouldBe null
|
decl.value shouldBe null
|
||||||
}
|
}
|
||||||
val assignInitialValue = decl.nextSibling() as Assignment
|
val assignInitialValue = decl.findInitializer(program)!!
|
||||||
assignInitialValue.target.identifier!!.nameInSource shouldBe listOf("ch")
|
assignInitialValue.target.identifier!!.nameInSource shouldBe listOf("ch")
|
||||||
withClue("char literal should have been replaced by ubyte literal") {
|
withClue("char literal should have been replaced by ubyte literal") {
|
||||||
assignInitialValue.value shouldBe instanceOf<NumericLiteralValue>()
|
assignInitialValue.value shouldBe instanceOf<NumericLiteralValue>()
|
||||||
|
@ -604,24 +604,26 @@ class TestOptimization: FunSpec({
|
|||||||
uword @shared zz
|
uword @shared zz
|
||||||
zz += 60 ; NOT ok to remove initializer, should evaluate to 60
|
zz += 60 ; NOT ok to remove initializer, should evaluate to 60
|
||||||
ubyte @shared xx
|
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()
|
val result = compileText(C64Target, optimize=true, src, writeAssembly=false).assertSuccess()
|
||||||
|
printProgram(result.program)
|
||||||
/* expected result:
|
/* expected result:
|
||||||
uword yy
|
uword yy
|
||||||
yy = 20
|
yy = 20
|
||||||
uword zz
|
uword zz
|
||||||
zz = 60
|
zz = 60
|
||||||
ubyte xx
|
ubyte xx
|
||||||
|
xx = 0
|
||||||
xx = sin8u(xx)
|
xx = sin8u(xx)
|
||||||
xx += 6
|
xx += 6
|
||||||
*/
|
*/
|
||||||
val stmts = result.program.entrypoint.statements
|
val stmts = result.program.entrypoint.statements
|
||||||
stmts.size shouldBe 7
|
stmts.size shouldBe 8
|
||||||
stmts.filterIsInstance<VarDecl>().size shouldBe 3
|
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") {
|
test("only substitue assignments with 0 after a =0 initializer if it is the same variable") {
|
||||||
|
@ -272,6 +272,12 @@ class VarDecl(val type: VarDeclType,
|
|||||||
copy.allowInitializeWithZero = this.allowInitializeWithZero
|
copy.allowInitializeWithZero = this.allowInitializeWithZero
|
||||||
return copy
|
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,
|
class ArrayIndex(var indexExpr: Expression,
|
||||||
@ -399,6 +405,12 @@ class Assignment(var target: AssignTarget, var value: Expression, var origin: As
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun initializerFor(program: Program) =
|
||||||
|
if(origin==AssignmentOrigin.VARINIT)
|
||||||
|
target.identifier!!.targetVarDecl(program)
|
||||||
|
else
|
||||||
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AssignTarget(var identifier: IdentifierReference?,
|
data class AssignTarget(var identifier: IdentifierReference?,
|
||||||
|
@ -3,7 +3,6 @@ TODO
|
|||||||
|
|
||||||
For next compiler release (7.7)
|
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
|
- optimize codegen of pipe operator to avoid needless assigns to temp var
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user