ir: fix non-code chunk linkage

This commit is contained in:
Irmen de Jong 2022-10-30 11:09:32 +01:00
parent 224f490455
commit 7cc3cc3990
8 changed files with 40 additions and 39 deletions

View File

@ -67,8 +67,12 @@ main {
} }
}""" }"""
val target = VMTarget() val target = VMTarget()
val result = compileText(target, true, src, writeAssembly = true)!! var result = compileText(target, false, src, writeAssembly = true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8ir") var virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8ir")
VmRunner().runProgram(virtfile.readText())
result = compileText(target, true, src, writeAssembly = true)!!
virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8ir")
VmRunner().runProgram(virtfile.readText()) VmRunner().runProgram(virtfile.readText())
} }
@ -107,7 +111,7 @@ mylabel_inside:
}""" }"""
val target = VMTarget() val target = VMTarget()
val result = compileText(target, true, src, writeAssembly = true)!! val result = compileText(target, false, src, writeAssembly = true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8ir") val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8ir")
VmRunner().runProgram(virtfile.readText()) VmRunner().runProgram(virtfile.readText())
} }

View File

@ -4,6 +4,7 @@ TODO
For next release For next release
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
- ir: fix unit tests - ir: fix unit tests
- ir: join more codechunks
- ir: fix removeWeirdBranches in IR optimizer - ir: fix removeWeirdBranches in IR optimizer
- update diagram in technical.rst? - update diagram in technical.rst?

View File

@ -1,17 +1,20 @@
%import textio %import textio
%import floats
%zeropage basicsafe %zeropage basicsafe
main { main {
float[10] flt
sub start() { sub start() {
float ff = 9.0 cx16.r0 = 42
flt[1] = 42.42 goto foobar
flt[1] = -9.0 my_label:
flt[1] = -ff txt.print_uwhex(cx16.r0, true)
flt[1] = -flt[1] ; TODO also fix crash when selecting vm target: fpReg1 out of bounds txt.spc()
floats.print_f(flt[1]) cx16.r0--
txt.nl() if cx16.r0
goto my_label
sys.exit(0)
foobar:
txt.print("yeooo\n")
goto my_label
} }
} }

View File

@ -464,7 +464,7 @@ class IRFileReader {
chunk += it chunk += it
}, },
ifRight = { ifRight = {
TODO("PROCESS LABEL $it") throw IRParseException("code chunk should not contain a separate label line anymore, this should be the proper label of a new separate chunk")
} }
) )
} }

View File

@ -620,7 +620,7 @@ data class IRInstruction(
val fpValue: Float?=null, val fpValue: Float?=null,
val labelSymbol: String?=null, // symbolic label name as alternative to value (so only for Branch/jump/call Instructions!) val labelSymbol: String?=null, // symbolic label name as alternative to value (so only for Branch/jump/call Instructions!)
val binaryData: Collection<UByte>?=null, val binaryData: Collection<UByte>?=null,
var branchTarget: IRCodeChunk? = null // will be linked after loading var branchTarget: IRCodeChunkBase? = null // will be linked after loading
) { ) {
// reg1 and fpreg1 can be IN/OUT/INOUT (all others are readonly INPUT) // reg1 and fpreg1 can be IN/OUT/INOUT (all others are readonly INPUT)
// This knowledge is useful in IL assembly optimizers to see how registers are used. // This knowledge is useful in IL assembly optimizers to see how registers are used.
@ -635,7 +635,7 @@ data class IRInstruction(
require(reg2==null || reg2 in 0..65536) {"reg2 out of bounds"} require(reg2==null || reg2 in 0..65536) {"reg2 out of bounds"}
require(fpReg1==null || fpReg1 in 0..65536) {"fpReg1 out of bounds"} require(fpReg1==null || fpReg1 in 0..65536) {"fpReg1 out of bounds"}
require(fpReg2==null || fpReg2 in 0..65536) {"fpReg2 out of bounds"} require(fpReg2==null || fpReg2 in 0..65536) {"fpReg2 out of bounds"}
if(value!=null) { if(value!=null && labelSymbol==null) {
when (type) { when (type) {
IRDataType.BYTE -> require(value in -128..255) {"value out of range for byte: $value"} IRDataType.BYTE -> require(value in -128..255) {"value out of range for byte: $value"}
IRDataType.WORD -> require(value in -32768..65535) {"value out of range for word: $value"} IRDataType.WORD -> require(value in -32768..65535) {"value out of range for word: $value"}

View File

@ -76,17 +76,11 @@ class IRProgram(val name: String,
val firstBlock = blocks.firstOrNull() val firstBlock = blocks.firstOrNull()
if(firstBlock!=null) { if(firstBlock!=null) {
if(firstBlock.inlineAssembly.isNotEmpty()) { if(firstBlock.inlineAssembly.isNotEmpty()) {
TODO("link to inline assembly block") globalInits.next = firstBlock.inlineAssembly.first()
// irprog.globalInits.next = firstBlock.inlineAssembly.first()
} else if(firstBlock.subroutines.isNotEmpty()) { } else if(firstBlock.subroutines.isNotEmpty()) {
val firstSub = firstBlock.subroutines.first() val firstSub = firstBlock.subroutines.first()
if(firstSub.chunks.isNotEmpty()) { if(firstSub.chunks.isNotEmpty())
val firstChunk = firstSub.chunks.first() globalInits.next = firstSub.chunks.first()
when(firstChunk) {
is IRCodeChunk -> globalInits.next = firstChunk
else -> TODO("link to other type of chunk")
}
}
} }
} }
} }
@ -94,7 +88,6 @@ class IRProgram(val name: String,
blocks.asSequence().flatMap { it.subroutines }.forEach { sub -> blocks.asSequence().flatMap { it.subroutines }.forEach { sub ->
sub.chunks.withIndex().forEach { (index, chunk) -> sub.chunks.withIndex().forEach { (index, chunk) ->
fun nextChunk(): IRCodeChunkBase? = if(index<sub.chunks.size-1) sub.chunks[index + 1] else null fun nextChunk(): IRCodeChunkBase? = if(index<sub.chunks.size-1) sub.chunks[index + 1] else null
@ -118,10 +111,7 @@ class IRProgram(val name: String,
chunk.instructions.forEach { chunk.instructions.forEach {
if(it.opcode in OpcodesThatBranch && it.opcode!=Opcode.RETURN && it.labelSymbol!=null) { if(it.opcode in OpcodesThatBranch && it.opcode!=Opcode.RETURN && it.labelSymbol!=null) {
val targetChunk = labeledChunks.getValue(it.labelSymbol) val targetChunk = labeledChunks.getValue(it.labelSymbol)
if(targetChunk is IRCodeChunk)
it.branchTarget = targetChunk it.branchTarget = targetChunk
else
println("TODO: branchTarget to non-codechunk $targetChunk with label ${targetChunk.label}") // TODO
} }
// note: branches with an address value cannot be linked to something... // note: branches with an address value cannot be linked to something...
} }
@ -159,10 +149,8 @@ class IRProgram(val name: String,
else else
require(chunk.instructions.isEmpty()) require(chunk.instructions.isEmpty())
chunk.instructions.forEach { chunk.instructions.forEach {
if(it.labelSymbol!=null && it.opcode in OpcodesThatBranch) { if(it.labelSymbol!=null && it.opcode in OpcodesThatBranch)
if(it.branchTarget==null) println("TODO: fix branching instruction to label ${it.labelSymbol} should have branchTarget set") // TODO require(it.branchTarget != null) { "branching instruction to label should have branchTarget set" }
// TODO require(it.branchTarget != null) { "branching instruction to label should have branchTarget set" }
}
} }
} }
} }

View File

@ -171,7 +171,7 @@ fun parseIRCodeLine(line: String, location: Pair<IRCodeChunk, Int>?, placeholder
operands.clear() operands.clear()
} }
if(operands.isNotEmpty()) { if(operands.isNotEmpty()) {
TODO("placeholder symbol? $operands rest=$rest'") TODO("huh even more operands? $operands rest=$rest'")
// operands.clear() // operands.clear()
} }
} }

View File

@ -132,11 +132,16 @@ class VirtualMachine(irProgram: IRProgram) {
} }
private fun branchTo(i: IRInstruction) { private fun branchTo(i: IRInstruction) {
if(i.branchTarget==null) val target = i.branchTarget
TODO("no branchtarget in $i (remove this check)") when (target) {
pcChunk = i.branchTarget!! is IRCodeChunk -> {
pcChunk = target
pcIndex = 0 pcIndex = 0
} }
null -> TODO("no branchtarget in $i (remove this check)")
else -> throw IllegalArgumentException("VM can't execute code in a non-codechunk: $target")
}
}
private fun dispatch(ins: IRInstruction) { private fun dispatch(ins: IRInstruction) {
when(ins.opcode) { when(ins.opcode) {