mirror of
https://github.com/irmen/prog8.git
synced 2024-10-05 03:56:02 +00:00
vm: fixed array initialization values with address-ofs
This commit is contained in:
parent
885df9156f
commit
229c1114dd
@ -25,18 +25,29 @@ class IRUnusedCodeRemover(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun pruneSymboltable(blockLabel: String) {
|
private fun pruneSymboltable(blockLabel: String) {
|
||||||
// we could clean up the SymbolTable as well, but ONLY if these symbols aren't referenced somewhere still in an instruction
|
// we could clean up the SymbolTable as well, but ONLY if these symbols aren't referenced somewhere still in an instruction or variable initializer value
|
||||||
val prefix = "$blockLabel."
|
val prefix = "$blockLabel."
|
||||||
val blockVars = irprog.st.allVariables().filter { it.name.startsWith(prefix) }
|
val blockVars = irprog.st.allVariables().filter { it.name.startsWith(prefix) }
|
||||||
blockVars.forEach { stVar ->
|
blockVars.forEach { stVar ->
|
||||||
irprog.allSubs().flatMap { it.chunks }.forEach { chunk ->
|
irprog.allSubs().flatMap { it.chunks }.forEach { chunk ->
|
||||||
chunk.instructions.forEach { ins ->
|
chunk.instructions.forEach { ins ->
|
||||||
if(ins.labelSymbol == stVar.name) {
|
if(ins.labelSymbol == stVar.name) {
|
||||||
return
|
return // symbol occurs in an instruction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
irprog.st.allVariables().forEach { stVar->
|
||||||
|
val initValue = stVar.onetimeInitializationArrayValue
|
||||||
|
if(initValue!=null && !initValue.isEmpty()) {
|
||||||
|
if(initValue.any {
|
||||||
|
it.addressOfSymbol?.startsWith(blockLabel)==true
|
||||||
|
})
|
||||||
|
return // symbol occurs in an initializer value (address-of this symbol)_
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
irprog.st.removeTree(blockLabel)
|
irprog.st.removeTree(blockLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,9 +218,7 @@ class IRUnusedCodeRemover(
|
|||||||
return removeUnlinkedChunks(linkedChunks)
|
return removeUnlinkedChunks(linkedChunks)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeUnlinkedChunks(
|
private fun removeUnlinkedChunks(linkedChunks: Set<IRCodeChunkBase>): Int {
|
||||||
linkedChunks: Set<IRCodeChunkBase>
|
|
||||||
): Int {
|
|
||||||
var numRemoved = 0
|
var numRemoved = 0
|
||||||
irprog.foreachSub { sub ->
|
irprog.foreachSub { sub ->
|
||||||
sub.chunks.withIndex().reversed().forEach { (index, chunk) ->
|
sub.chunks.withIndex().reversed().forEach { (index, chunk) ->
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- fix compiler error with vm/expericodegen: petaxian (minimal error cases in test.p8)
|
|
||||||
|
|
||||||
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
||||||
- IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction
|
- IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction
|
||||||
- IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? etc), but only after setting the status bits is verified!
|
- IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? etc), but only after setting the status bits is verified!
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
|
%import textio
|
||||||
|
|
||||||
main {
|
main {
|
||||||
uword[] pages = [ &page_credits.chars_1]
|
uword[] pages1 = [ &page_credits.chars_1]
|
||||||
|
uword foo2 = &page_credits.chars_1
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
; cx16.r0 = pages[0] ; TODO fix IR compiler error undefined symbol pages
|
txt.print_uw(foo2)
|
||||||
uword @shared foo = pages[0] ; TODO fix IR compiler error no chunk with label 'page_credits.chars_1' (caused by optimizer)
|
uword @shared foo = pages1[0] ; TODO fix IR compiler error no chunk with label 'page_credits.chars_1' (caused by optimizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
page_credits {
|
page_credits {
|
||||||
ubyte[] chars_1 = [11]
|
ubyte[] chars_1 = [11]
|
||||||
; TODO fix IR compiler crash when this array is moved into main block itself
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package prog8.vm
|
package prog8.vm
|
||||||
|
|
||||||
|
import prog8.code.StArray
|
||||||
|
import prog8.code.StArrayElement
|
||||||
|
import prog8.code.StStaticVariable
|
||||||
import prog8.code.core.ArrayDatatypes
|
import prog8.code.core.ArrayDatatypes
|
||||||
import prog8.code.core.AssemblyError
|
import prog8.code.core.AssemblyError
|
||||||
import prog8.code.core.DataType
|
import prog8.code.core.DataType
|
||||||
@ -239,62 +242,157 @@ class VmProgramLoader {
|
|||||||
else -> throw IRParseException("invalid dt")
|
else -> throw IRParseException("invalid dt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
variable.onetimeInitializationArrayValue?.let {
|
variable.onetimeInitializationArrayValue?.let { iElts ->
|
||||||
require(variable.length==it.size || it.size==1 || it.size==0)
|
require(variable.length==iElts.size || iElts.size==1 || iElts.size==0)
|
||||||
if(it.isEmpty() || it.size==1) {
|
if(iElts.isEmpty() || iElts.size==1) {
|
||||||
val value = if(it.isEmpty()) {
|
val iElt = if(iElts.isEmpty()) {
|
||||||
require(variable.uninitialized)
|
require(variable.uninitialized)
|
||||||
0.0
|
StArrayElement(0.0, null)
|
||||||
} else {
|
} else {
|
||||||
require(!variable.uninitialized)
|
require(!variable.uninitialized)
|
||||||
it[0].number!!
|
iElts[0]
|
||||||
}
|
}
|
||||||
|
initializeWithOneValue(variable, iElt, addr, symbolAddresses, memory, program)
|
||||||
|
} else {
|
||||||
|
initializeWithValues(variable, iElts, addr, symbolAddresses, memory, program)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require(variable.onetimeInitializationStringValue==null) { "in vm/ir, strings should have been converted into bytearrays." }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initializeWithValues(
|
||||||
|
variable: StStaticVariable,
|
||||||
|
iElts: StArray,
|
||||||
|
startAddress: Int,
|
||||||
|
symbolAddresses: MutableMap<String, Int>,
|
||||||
|
memory: Memory,
|
||||||
|
program: IRProgram
|
||||||
|
) {
|
||||||
|
var address = startAddress
|
||||||
when (variable.dt) {
|
when (variable.dt) {
|
||||||
DataType.STR, DataType.ARRAY_UB -> {
|
DataType.STR, DataType.ARRAY_UB -> {
|
||||||
repeat(variable.length!!) {
|
for (elt in iElts) {
|
||||||
memory.setUB(addr, value.toInt().toUByte())
|
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toInt().toUByte()
|
||||||
addr++
|
memory.setUB(address, value)
|
||||||
|
address++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DataType.ARRAY_B -> {
|
DataType.ARRAY_B -> {
|
||||||
repeat(variable.length!!) {
|
for (elt in iElts) {
|
||||||
memory.setSB(addr, value.toInt().toByte())
|
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toInt().toByte()
|
||||||
addr++
|
memory.setSB(address, value)
|
||||||
|
address++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DataType.ARRAY_UW -> {
|
DataType.ARRAY_UW -> {
|
||||||
repeat(variable.length!!) {
|
for (elt in iElts) {
|
||||||
memory.setUW(addr, value.toInt().toUShort())
|
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toInt().toUShort()
|
||||||
addr+=2
|
memory.setUW(address, value)
|
||||||
|
address += 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DataType.ARRAY_W -> {
|
DataType.ARRAY_W -> {
|
||||||
repeat(variable.length!!) {
|
for (elt in iElts) {
|
||||||
memory.setSW(addr, value.toInt().toShort())
|
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toInt().toShort()
|
||||||
addr+=2
|
memory.setSW(address, value)
|
||||||
|
address += 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
in SplitWordArrayTypes -> {
|
in SplitWordArrayTypes -> {
|
||||||
val number = value.toUInt()
|
for (elt in iElts) {
|
||||||
for(elt in it) {
|
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toUInt()
|
||||||
memory.setUB(addr, (number and 255u).toUByte())
|
memory.setUB(address, (value and 255u).toUByte())
|
||||||
memory.setUB(addr+variable.length!!, (number shr 8).toUByte())
|
memory.setUB(address + variable.length!!, (value shr 8).toUByte())
|
||||||
addr++
|
address++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DataType.ARRAY_F -> {
|
DataType.ARRAY_F -> {
|
||||||
repeat(variable.length!!) {
|
for (elt in iElts) {
|
||||||
memory.setFloat(addr, value.toFloat())
|
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toFloat()
|
||||||
addr += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
memory.setFloat(address, value)
|
||||||
|
address += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw IRParseException("invalid dt")
|
else -> throw IRParseException("invalid dt")
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
private fun initializeWithOneValue(
|
||||||
|
variable: StStaticVariable,
|
||||||
|
iElt: StArrayElement,
|
||||||
|
startAddress: Int,
|
||||||
|
symbolAddresses: MutableMap<String, Int>,
|
||||||
|
memory: Memory,
|
||||||
|
program: IRProgram
|
||||||
|
) {
|
||||||
|
var address = startAddress
|
||||||
when (variable.dt) {
|
when (variable.dt) {
|
||||||
DataType.STR, DataType.ARRAY_UB -> {
|
DataType.STR, DataType.ARRAY_UB -> {
|
||||||
for(elt in it) {
|
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toInt().toUByte()
|
||||||
|
repeat(variable.length!!) {
|
||||||
|
memory.setUB(address, value)
|
||||||
|
address++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataType.ARRAY_B -> {
|
||||||
|
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toInt().toByte()
|
||||||
|
repeat(variable.length!!) {
|
||||||
|
memory.setSB(address, value)
|
||||||
|
address++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataType.ARRAY_UW -> {
|
||||||
|
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toInt().toUShort()
|
||||||
|
repeat(variable.length!!) {
|
||||||
|
memory.setUW(address, value)
|
||||||
|
address += 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataType.ARRAY_W -> {
|
||||||
|
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toInt().toShort()
|
||||||
|
repeat(variable.length!!) {
|
||||||
|
memory.setSW(address, value)
|
||||||
|
address += 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in SplitWordArrayTypes -> {
|
||||||
|
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toUInt()
|
||||||
|
val lsb = (value and 255u).toUByte()
|
||||||
|
val msb = (value shr 8).toUByte()
|
||||||
|
repeat(variable.length!!) {
|
||||||
|
memory.setUB(address, lsb)
|
||||||
|
memory.setUB(address + variable.length!!, msb)
|
||||||
|
address++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataType.ARRAY_F -> {
|
||||||
|
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toFloat()
|
||||||
|
repeat(variable.length!!) {
|
||||||
|
memory.setFloat(address, value)
|
||||||
|
address += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> throw IRParseException("invalid dt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getInitializerValue(arrayDt: DataType, elt: StArrayElement, symbolAddresses: MutableMap<String, Int>): Double {
|
||||||
if(elt.addressOfSymbol!=null) {
|
if(elt.addressOfSymbol!=null) {
|
||||||
|
when(arrayDt) {
|
||||||
|
DataType.ARRAY_UB, DataType.STR, DataType.ARRAY_B, DataType.ARRAY_BOOL -> {
|
||||||
val name = elt.addressOfSymbol!!
|
val name = elt.addressOfSymbol!!
|
||||||
val symbolAddress = if(name.startsWith('<')) {
|
val symbolAddress = if(name.startsWith('<')) {
|
||||||
symbolAddresses[name.drop(1)]?.and(255)
|
symbolAddresses[name.drop(1)]?.and(255)
|
||||||
@ -304,64 +402,17 @@ class VmProgramLoader {
|
|||||||
?: throw IRParseException("vm cannot yet load a label address as a value: $name")
|
?: throw IRParseException("vm cannot yet load a label address as a value: $name")
|
||||||
} else
|
} else
|
||||||
throw IRParseException("for byte-array address-of, expected < or > (lsb/msb)")
|
throw IRParseException("for byte-array address-of, expected < or > (lsb/msb)")
|
||||||
memory.setUB(addr, symbolAddress.toUByte())
|
return symbolAddress.toDouble()
|
||||||
} else {
|
|
||||||
memory.setUB(addr, elt.number!!.toInt().toUByte())
|
|
||||||
}
|
}
|
||||||
addr++
|
else -> {
|
||||||
}
|
|
||||||
}
|
|
||||||
DataType.ARRAY_B -> {
|
|
||||||
for(elt in it) {
|
|
||||||
memory.setSB(addr, elt.number!!.toInt().toByte())
|
|
||||||
addr++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataType.ARRAY_UW -> {
|
|
||||||
for(elt in it) {
|
|
||||||
if(elt.addressOfSymbol!=null) {
|
|
||||||
val name = elt.addressOfSymbol!!
|
val name = elt.addressOfSymbol!!
|
||||||
val symbolAddress = symbolAddresses[name]
|
val symbolAddress = symbolAddresses[name]
|
||||||
?: throw IRParseException("vm cannot yet load a label address as a value: $name")
|
?: throw IRParseException("vm cannot yet load a label address as a value: $name")
|
||||||
memory.setUW(addr, symbolAddress.toUShort())
|
return symbolAddress.toDouble()
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
memory.setUW(addr, elt.number!!.toInt().toUShort())
|
return elt.number!!
|
||||||
}
|
|
||||||
addr+=2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataType.ARRAY_W -> {
|
|
||||||
for(elt in it) {
|
|
||||||
memory.setSW(addr, elt.number!!.toInt().toShort())
|
|
||||||
addr+=2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
in SplitWordArrayTypes -> {
|
|
||||||
for(elt in it) {
|
|
||||||
val number = if(elt.addressOfSymbol!=null) {
|
|
||||||
val name = elt.addressOfSymbol!!
|
|
||||||
val symbolAddress = symbolAddresses[name]
|
|
||||||
?: throw IRParseException("vm cannot yet load a label address as a value: $name")
|
|
||||||
symbolAddress.toUInt()
|
|
||||||
} else {
|
|
||||||
elt.number!!.toInt().toUInt()
|
|
||||||
}
|
|
||||||
memory.setUB(addr, (number and 255u).toUByte())
|
|
||||||
memory.setUB(addr + variable.length!!, (number shr 8).toUByte())
|
|
||||||
addr++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataType.ARRAY_F -> {
|
|
||||||
for(elt in it) {
|
|
||||||
memory.setFloat(addr, elt.number!!.toFloat())
|
|
||||||
addr+=program.options.compTarget.machine.FLOAT_MEM_SIZE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> throw IRParseException("invalid dt")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
require(variable.onetimeInitializationStringValue==null) { "in vm/ir, strings should have been converted into bytearrays." }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user