vm: fix nested label prefixing

This commit is contained in:
Irmen de Jong 2022-09-24 16:00:25 +02:00
parent c26e116f0e
commit 0e1886e6bd
8 changed files with 52 additions and 37 deletions

View File

@ -36,10 +36,10 @@ class VirtualMachineDefinition: IMachineDefinition {
val vm = Class.forName("prog8.vm.VmRunner").getDeclaredConstructor().newInstance() as IVirtualMachineRunner
val filename = programNameWithPath.name
if(filename.endsWith(".p8virt")) {
vm.runProgram(programNameWithPath.readText(), true)
vm.runProgram(programNameWithPath.readText())
} else if(File("$filename.p8virt").isFile) {
val source = File("$filename.p8virt").readText()
vm.runProgram(source, true)
vm.runProgram(source)
}
else
throw IllegalArgumentException("vm can only run .p8virt or .p8ir files")
@ -53,5 +53,5 @@ class VirtualMachineDefinition: IMachineDefinition {
}
interface IVirtualMachineRunner {
fun runProgram(source: String, throttle: Boolean)
fun runProgram(source: String)
}

View File

@ -24,6 +24,7 @@ class IRCodeGen(
internal val vmRegisters = RegisterPool()
fun generate(): IRProgram {
flattenLabelNames()
flattenNestedSubroutines()
val irProg = IRProgram(program.name, symbolTable, options, program.encoding)
@ -101,9 +102,31 @@ class IRCodeGen(
}
}
private fun flattenLabelNames() {
val renameLabels = mutableListOf<Pair<PtNode, PtLabel>>()
fun flattenRecurse(node: PtNode) {
node.children.forEach {
if (it is PtLabel)
renameLabels += Pair(it.parent, it)
else
flattenRecurse(it)
}
}
flattenRecurse(program)
renameLabels.forEach { (parent, label) ->
val renamedLabel = PtLabel(label.scopedName.joinToString("."), label.position)
val idx = parent.children.indexOf(label)
parent.children.removeAt(idx)
parent.children.add(idx, renamedLabel)
}
}
private fun flattenNestedSubroutines() {
// this moves all nested subroutines up to the block scope.
// also changes the name to be the fully scoped one so it becomes unique at the top level.
// also changes the name to be the fully scoped one, so it becomes unique at the top level.
// also moves the start() entrypoint as first subroutine.
val flattenedSubs = mutableListOf<Pair<PtBlock, PtSub>>()
val flattenedAsmSubs = mutableListOf<Pair<PtBlock, PtAsmSub>>()
@ -111,10 +134,9 @@ class IRCodeGen(
val removalsAsmSubs = mutableListOf<Pair<PtSub, PtAsmSub>>()
val renameSubs = mutableListOf<Pair<PtBlock, PtSub>>()
val renameAsmSubs = mutableListOf<Pair<PtBlock, PtAsmSub>>()
val renameLabels = mutableListOf<Pair<PtNode, PtLabel>>()
val entrypoint = program.entrypoint()
fun flattenNestedAsm(block: PtBlock, parentSub: PtSub, asmsub: PtAsmSub) {
fun flattenNestedAsmSub(block: PtBlock, parentSub: PtSub, asmsub: PtAsmSub) {
val flattened = PtAsmSub(asmsub.scopedName.joinToString("."),
asmsub.address,
asmsub.clobbers,
@ -128,9 +150,9 @@ class IRCodeGen(
removalsAsmSubs += Pair(parentSub, asmsub)
}
fun flattenNested(block: PtBlock, parentSub: PtSub, sub: PtSub) {
sub.children.filterIsInstance<PtSub>().forEach { subsub->flattenNested(block, sub, subsub) }
sub.children.filterIsInstance<PtAsmSub>().forEach { asmsubsub->flattenNestedAsm(block, sub, asmsubsub) }
fun flattenNestedSub(block: PtBlock, parentSub: PtSub, sub: PtSub) {
sub.children.filterIsInstance<PtSub>().forEach { subsub->flattenNestedSub(block, sub, subsub) }
sub.children.filterIsInstance<PtAsmSub>().forEach { asmsubsub->flattenNestedAsmSub(block, sub, asmsubsub) }
val flattened = PtSub(sub.scopedName.joinToString("."),
sub.parameters,
sub.returntype,
@ -145,24 +167,15 @@ class IRCodeGen(
block.children.forEach {
if(it is PtSub) {
// Only regular subroutines can have nested subroutines.
it.children.filterIsInstance<PtSub>().forEach { subsub->flattenNested(block, it, subsub)}
it.children.filterIsInstance<PtAsmSub>().forEach { asmsubsub->flattenNestedAsm(block, it, asmsubsub)}
it.children.filterIsInstance<PtLabel>().forEach { label->renameLabels.add(Pair(it, label))}
it.children.filterIsInstance<PtSub>().forEach { subsub->flattenNestedSub(block, it, subsub)}
it.children.filterIsInstance<PtAsmSub>().forEach { asmsubsub->flattenNestedAsmSub(block, it, asmsubsub)}
renameSubs += Pair(block, it)
}
if(it is PtAsmSub)
renameAsmSubs += Pair(block, it)
if(it is PtLabel)
renameLabels += Pair(block, it)
}
}
renameLabels.forEach { (parent, label) ->
val renamedLabel = PtLabel(label.scopedName.joinToString("."), label.position)
val idx = parent.children.indexOf(label)
parent.children.removeAt(idx)
parent.children.add(idx, renamedLabel)
}
removalsSubs.forEach { (parent, sub) -> parent.children.remove(sub) }
removalsAsmSubs.forEach { (parent, asmsub) -> parent.children.remove(asmsub) }
flattenedSubs.forEach { (block, sub) -> block.add(sub) }

View File

@ -26,7 +26,7 @@ main {
val target = VMTarget()
val result = compileText(target, true, src, writeAssembly = true, keepIR=true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8virt")
VmRunner().runProgram(virtfile.readText(), false)
VmRunner().runProgram(virtfile.readText())
}
test("compile virtual: array with pointers") {
@ -44,7 +44,7 @@ main {
val target = VMTarget()
val result = compileText(target, true, src, writeAssembly = true, keepIR=true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8virt")
VmRunner().runProgram(virtfile.readText(), false)
VmRunner().runProgram(virtfile.readText())
}
test("compile virtual: str args and return type") {
@ -62,7 +62,7 @@ main {
val target = VMTarget()
val result = compileText(target, true, src, writeAssembly = true, keepIR=true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8virt")
VmRunner().runProgram(virtfile.readText(), false)
VmRunner().runProgram(virtfile.readText())
}
test("compile virtual: nested labels") {
@ -72,6 +72,10 @@ main {
uword i
uword k
while k <= 10 {
k++
}
mylabel_outside:
for i in 0 to 10 {
mylabel_inside:
@ -98,7 +102,7 @@ mylabel_inside:
val target = VMTarget()
val result = compileText(target, true, src, writeAssembly = true, keepIR=true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8virt")
VmRunner().runProgram(virtfile.readText(), false)
VmRunner().runProgram(virtfile.readText())
}
})

View File

@ -3,9 +3,7 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- fix vm crash in TestCompilerVirtual: while loop
- fix vm crash in TestCompilerVirtual: array with pointers
- fix vm crash (while loop) in examples/vm/bsieve.p8 (Assembler)
- fix vm crash (parseValue error) in examples/vm/textelite.p8 (Assembler)
...

View File

@ -27,7 +27,7 @@ main {
k += prime
}
txt.print_uw(prime)
txt.spc()
txt.nl()
count++
}
}

View File

@ -110,7 +110,7 @@ class Assembler {
if(binarymatch!=null) {
val hex = binarymatch.groups[1]!!.value
val binary = hex.windowed(size=2, step=2).map {
it.toString().toByte(16)
it.toByte(16)
}.toByteArray()
program.add(Instruction(Opcode.BINARYDATA, binaryData = binary))
} else {

View File

@ -47,7 +47,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>, val cx16vir
throw IllegalArgumentException("program cannot contain more than 65536 instructions")
}
fun run(throttle: Boolean = true) {
fun run() {
try {
var before = System.nanoTime()
var numIns = 0
@ -55,9 +55,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>, val cx16vir
step()
numIns++
if(throttle && stepCount and 32767 == 0) {
Thread.sleep(1) // avoid 100% cpu core usage
}
// if(stepCount and 32767 == 0) {
// Thread.sleep(1) // avoid 100% cpu core usage
// }
if(stepCount and 0xffffff == 0) {
val now = System.nanoTime()
@ -2105,13 +2105,13 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>, val cx16vir
// probably called via reflection
class VmRunner: IVirtualMachineRunner {
override fun runProgram(source: String, throttle: Boolean) {
override fun runProgram(source: String) {
val (memsrc, programsrc) = source.split("------PROGRAM------".toRegex(), 2)
val memory = Memory()
val assembler = Assembler()
assembler.initializeMemory(memsrc, memory)
val program = assembler.assembleProgram(programsrc)
val vm = VirtualMachine(memory, program, assembler.cx16virtualregBaseAdress)
vm.run(throttle = throttle)
vm.run()
}
}

View File

@ -16,7 +16,7 @@ class TestVm: FunSpec( {
vm.valueStack.shouldBeEmpty()
vm.pc shouldBe 0
vm.stepCount shouldBe 0
vm.run(throttle = false)
vm.run()
vm.callStack.shouldBeEmpty()
vm.valueStack.shouldBeEmpty()
vm.pc shouldBe 0
@ -37,7 +37,7 @@ class TestVm: FunSpec( {
vm.valueStack.shouldBeEmpty()
vm.pc shouldBe 0
vm.stepCount shouldBe 0
vm.run(throttle = false)
vm.run()
memory.getUW(1000) shouldBe 12345u
vm.callStack.shouldBeEmpty()
vm.valueStack.shouldBeEmpty()
@ -47,6 +47,6 @@ class TestVm: FunSpec( {
test("vmrunner") {
val runner = VmRunner()
runner.runProgram(";comment\n------PROGRAM------\n;comment\n", false)
runner.runProgram(";comment\n------PROGRAM------\n;comment\n")
}
})