mirror of
https://github.com/irmen/prog8.git
synced 2025-02-16 07:31:48 +00:00
global (block-level) variables that get initialized with an array index expression now get a constant value as well if possible. This reduces the number of instructions in the init globals code block
This commit is contained in:
parent
cbc4b75e50
commit
ca5f7ae32f
@ -321,6 +321,31 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors:
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
|
||||
if(parent is VarDecl && parent.parent is Block) {
|
||||
// only block level (global) initializers are considered here, because they're run just once at program startup
|
||||
|
||||
val const = arrayIndexedExpression.constValue(program)
|
||||
if (const != null)
|
||||
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression, const, parent))
|
||||
|
||||
val constIndex = arrayIndexedExpression.indexer.constIndex()
|
||||
if (constIndex != null) {
|
||||
val arrayVar = arrayIndexedExpression.arrayvar.targetVarDecl(program)
|
||||
if(arrayVar!=null) {
|
||||
val array =arrayVar.value as? ArrayLiteral
|
||||
if(array!=null) {
|
||||
val value = array.value[constIndex].constValue(program)
|
||||
if(value!=null) {
|
||||
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression, value, parent))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(functionCallExpr: FunctionCallExpression, parent: Node): Iterable<IAstModification> {
|
||||
val constvalue = functionCallExpr.constValue(program)
|
||||
return if(constvalue!=null)
|
||||
|
@ -4,6 +4,9 @@ import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.statements.AssignmentOrigin
|
||||
import prog8.code.ast.PtAssignment
|
||||
import prog8.code.target.C64Target
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
import prog8tests.helpers.compileText
|
||||
@ -95,4 +98,95 @@ class TestVariables: FunSpec({
|
||||
errors.errors[0] shouldContain "value has incompatible type"
|
||||
errors.errors[1] shouldContain "value has incompatible type"
|
||||
}
|
||||
|
||||
test("global var init with array lookup should sometimes be const") {
|
||||
val src="""
|
||||
main {
|
||||
|
||||
bool[] barray = [true, false, true, false]
|
||||
uword[] warray = [&value1, &barray, &value5, 4242]
|
||||
|
||||
bool @shared value1
|
||||
bool @shared value2 = barray[2] ; should be const!
|
||||
bool @shared value3 = true
|
||||
bool @shared value4 = false
|
||||
bool @shared value5 = barray[cx16.r0L] ; cannot be const
|
||||
uword @shared value6 = warray[3] ; should be const!
|
||||
uword @shared value7 = warray[2] ; cannot be const
|
||||
|
||||
sub start() {
|
||||
}
|
||||
}"""
|
||||
|
||||
val result = compileText(C64Target(), true, src, writeAssembly = true)!!.compilerAst
|
||||
val main = result.allBlocks.first { it.name=="main" }
|
||||
main.statements.size shouldBe 17
|
||||
val assigns = main.statements.filterIsInstance<Assignment>()
|
||||
assigns[0].target.identifier?.nameInSource shouldBe listOf("value1")
|
||||
assigns[1].target.identifier?.nameInSource shouldBe listOf("value2")
|
||||
assigns[2].target.identifier?.nameInSource shouldBe listOf("value3")
|
||||
assigns[3].target.identifier?.nameInSource shouldBe listOf("value4")
|
||||
assigns[4].target.identifier?.nameInSource shouldBe listOf("value5")
|
||||
assigns[5].target.identifier?.nameInSource shouldBe listOf("value6")
|
||||
assigns[6].target.identifier?.nameInSource shouldBe listOf("value7")
|
||||
assigns[0].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[1].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[2].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[3].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[4].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[5].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[6].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[0].value.constValue(result)?.number shouldBe 0
|
||||
assigns[1].value.constValue(result)?.number shouldBe 1
|
||||
assigns[2].value.constValue(result)?.number shouldBe 1
|
||||
assigns[3].value.constValue(result)?.number shouldBe 0
|
||||
assigns[4].value.constValue(result) shouldBe null
|
||||
assigns[5].value.constValue(result)?.number shouldBe 4242
|
||||
assigns[6].value.constValue(result) shouldBe null
|
||||
}
|
||||
|
||||
|
||||
test("scoped var init with array lookup should never be const") {
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
bool[] barray = [true, false, true, false]
|
||||
uword[] warray = [&value1, &barray, &value5, 4242]
|
||||
|
||||
bool @shared value1
|
||||
bool @shared value2 = barray[2]
|
||||
bool @shared value3 = true
|
||||
bool @shared value4 = false
|
||||
bool @shared value5 = barray[cx16.r0L]
|
||||
uword @shared value6 = warray[3]
|
||||
uword @shared value7 = warray[2]
|
||||
}
|
||||
}"""
|
||||
|
||||
val result = compileText(C64Target(), true, src, writeAssembly = true)!!.compilerAst
|
||||
val st = result.entrypoint.statements
|
||||
st.size shouldBe 17
|
||||
val assigns = st.filterIsInstance<Assignment>()
|
||||
assigns[0].target.identifier?.nameInSource shouldBe listOf("value1")
|
||||
assigns[1].target.identifier?.nameInSource shouldBe listOf("value2")
|
||||
assigns[2].target.identifier?.nameInSource shouldBe listOf("value3")
|
||||
assigns[3].target.identifier?.nameInSource shouldBe listOf("value4")
|
||||
assigns[4].target.identifier?.nameInSource shouldBe listOf("value5")
|
||||
assigns[5].target.identifier?.nameInSource shouldBe listOf("value6")
|
||||
assigns[6].target.identifier?.nameInSource shouldBe listOf("value7")
|
||||
assigns[0].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[1].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[2].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[3].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[4].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[5].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[6].origin shouldBe AssignmentOrigin.VARINIT
|
||||
assigns[0].value.constValue(result)?.number shouldBe 0
|
||||
assigns[1].value.constValue(result) shouldBe null
|
||||
assigns[2].value.constValue(result)?.number shouldBe 1
|
||||
assigns[3].value.constValue(result)?.number shouldBe 0
|
||||
assigns[4].value.constValue(result) shouldBe null
|
||||
assigns[5].value.constValue(result) shouldBe null
|
||||
assigns[6].value.constValue(result) shouldBe null
|
||||
}
|
||||
})
|
||||
|
@ -4,20 +4,18 @@
|
||||
|
||||
main {
|
||||
|
||||
bool[] barray = [true, false, true, false]
|
||||
bool value1
|
||||
bool value2 = barray[cx16.r0L]
|
||||
bool value3 = true
|
||||
bool value4 = false
|
||||
|
||||
sub start() {
|
||||
txt.print_bool(value1)
|
||||
txt.spc()
|
||||
txt.print_bool(value2)
|
||||
txt.spc()
|
||||
txt.print_bool(value3)
|
||||
txt.nl()
|
||||
txt.print_bool(value4)
|
||||
bool[] barray = [true, false, true, false]
|
||||
uword[] warray = [&value1, &barray, &value5, 4242]
|
||||
|
||||
bool @shared value1
|
||||
bool @shared value2 = barray[2] ; should be const!
|
||||
bool @shared value3 = true
|
||||
bool @shared value4 = false
|
||||
bool @shared value5 = barray[cx16.r0L] ; cannot be const
|
||||
uword @shared value6 = warray[3] ; should be const!
|
||||
uword @shared value7 = warray[2] ; cannot be const
|
||||
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user