vm: fix scoped name in address-of inside array

This commit is contained in:
Irmen de Jong 2022-09-24 17:06:47 +02:00
parent 0e1886e6bd
commit ca41669f4f
5 changed files with 82 additions and 18 deletions

View File

@ -1,6 +1,7 @@
package prog8tests.vm
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import prog8.code.target.Cx16Target
import prog8.code.target.VMTarget
@ -32,11 +33,15 @@ main {
test("compile virtual: array with pointers") {
val src = """
main {
sub start() {
ubyte variable
uword[] words = [1111,2222,"three",&variable]
variable = 2222 in words
str localstr = "hello"
ubyte[] otherarray = [1,2,3]
uword[] words = [1111,2222,"three",&localstr,&otherarray]
uword @shared zz = &words
ubyte result = 2222 in words
zz = words[2]
zz++
zz = words[3]
}
}"""
val othertarget = Cx16Target()
@ -105,4 +110,31 @@ mylabel_inside:
VmRunner().runProgram(virtfile.readText())
}
test("case sensitive symbols") {
val src = """
%zeropage basicsafe
main {
sub start() {
ubyte bytevar = 11 ; var at 0
ubyte byteVAR = 22 ; var at 1
ubyte ByteVar = 33 ; var at 2
ubyte @shared total = bytevar+byteVAR+ByteVar ; var at 3
goto skipLABEL
SkipLabel:
return
skipLABEL:
bytevar = 42
}
}"""
val othertarget = Cx16Target()
compileText(othertarget, true, src, writeAssembly = true, keepIR=true) shouldNotBe null
val target = VMTarget()
val result = compileText(target, true, src, writeAssembly = true, keepIR=true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8virt")
VmRunner().runAndTestProgram(virtfile.readText()) { vm ->
vm.memory.getUB(0) shouldBe 42u
vm.memory.getUB(3) shouldBe 66u
}
}
})

View File

@ -3,8 +3,9 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- fix vm symbol case insensitivity (TestCompilerVirtual)
- fix vm crash in TestCompilerVirtual: array with pointers
- fix vm crash (parseValue error) in examples/vm/textelite.p8 (Assembler)
- fix vm crash (parseValue error) in examples/vm/textelite.p8 (Assembler, caused by above?)
...

View File

@ -121,8 +121,11 @@ class IRFileWriter(private val irProgram: IRProgram) {
variable.onetimeInitializationArrayValue!!.joinToString(",") {
if(it.number!=null)
it.number!!.toInt().toString()
else
"&${it.addressOf!!.joinToString(".")}"
else {
val target = variable.lookup(it.addressOf!!)
?: throw InternalCompilerException("symbol not found: ${it.addressOf} in ${variable.scopedName}")
"&${target.scopedName.joinToString(".")}"
}
}
} else {
(1..variable.length!!).joinToString(",") { "0" }

View File

@ -17,6 +17,8 @@ class Assembler {
fun initializeMemory(memsrc: String, memory: Memory) {
symbolAddresses.clear()
val arrayValuePlaceholders = mutableListOf<Pair<Int, String>>()
val instrPattern = Regex("""var (.+) @([0-9]+) ([a-z]+)(\[[0-9]+\])? (.+)""", RegexOption.IGNORE_CASE)
for(line in memsrc.lines()) {
if(line.isBlank() || line.startsWith(';'))
@ -58,18 +60,33 @@ class Assembler {
}
}
"uword", "word" -> {
val array = values.split(',').map { parseValue(Opcode.LOADCPU, it.trim(), 0).toInt() }
require(array.size==numArrayElts || array.size==1)
if(numArrayElts>array.size) {
val value = array.single().toUShort()
repeat(numArrayElts) {
memory.setUW(address, value)
address += 2
}
if(arrayspec.isBlank()) {
// single value
val value = parseValue(Opcode.LOADCPU, values.trim(), 0).toInt()
memory.setUW(address, value.toUShort())
address += 2
} else {
for (value in array) {
memory.setUW(address, value.toUShort())
address += 2
// array initializer
val array = values.split(',').withIndex().map {(index, value) ->
val tv = value.trim()
if(tv.startsWith('&')) {
arrayValuePlaceholders += Pair(address+index*2, tv.drop(1))
9999 // will be replaced with correct value at the end.
} else
parseValue(Opcode.LOADCPU, tv, 0).toInt()
}
require(array.size==numArrayElts || array.size==1)
if(numArrayElts>array.size) {
val value = array.single().toUShort()
repeat(numArrayElts) {
memory.setUW(address, value)
address += 2
}
} else {
for (value in array) {
memory.setUW(address, value.toUShort())
address += 2
}
}
}
}
@ -93,6 +110,12 @@ class Assembler {
}
}
}
// correct the addres-of values in array initializers
arrayValuePlaceholders.forEach { (address, symbol) ->
val addr = this.symbolAddresses.getValue(symbol)
memory.setUW(address, addr.toUShort())
}
}
fun assembleProgram(source: CharSequence): List<Instruction> {

View File

@ -2106,6 +2106,10 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>, val cx16vir
// probably called via reflection
class VmRunner: IVirtualMachineRunner {
override fun runProgram(source: String) {
runAndTestProgram(source) { /* no tests */ }
}
fun runAndTestProgram(source: String, test: (VirtualMachine) -> Unit) {
val (memsrc, programsrc) = source.split("------PROGRAM------".toRegex(), 2)
val memory = Memory()
val assembler = Assembler()
@ -2113,5 +2117,6 @@ class VmRunner: IVirtualMachineRunner {
val program = assembler.assembleProgram(programsrc)
val vm = VirtualMachine(memory, program, assembler.cx16virtualregBaseAdress)
vm.run()
test(vm)
}
}