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 result = compileText(target, true, src, writeAssembly = true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8ir")
var result = compileText(target, false, src, writeAssembly = true)!!
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())
}
@ -107,7 +111,7 @@ mylabel_inside:
}"""
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")
VmRunner().runProgram(virtfile.readText())
}

View File

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

View File

@ -1,17 +1,20 @@
%import textio
%import floats
%zeropage basicsafe
main {
float[10] flt
sub start() {
float ff = 9.0
flt[1] = 42.42
flt[1] = -9.0
flt[1] = -ff
flt[1] = -flt[1] ; TODO also fix crash when selecting vm target: fpReg1 out of bounds
floats.print_f(flt[1])
txt.nl()
cx16.r0 = 42
goto foobar
my_label:
txt.print_uwhex(cx16.r0, true)
txt.spc()
cx16.r0--
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
},
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 labelSymbol: String?=null, // symbolic label name as alternative to value (so only for Branch/jump/call Instructions!)
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)
// 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(fpReg1==null || fpReg1 in 0..65536) {"fpReg1 out of bounds"}
require(fpReg2==null || fpReg2 in 0..65536) {"fpReg2 out of bounds"}
if(value!=null) {
if(value!=null && labelSymbol==null) {
when (type) {
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"}

View File

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

View File

@ -132,10 +132,15 @@ class VirtualMachine(irProgram: IRProgram) {
}
private fun branchTo(i: IRInstruction) {
if(i.branchTarget==null)
TODO("no branchtarget in $i (remove this check)")
pcChunk = i.branchTarget!!
pcIndex = 0
val target = i.branchTarget
when (target) {
is IRCodeChunk -> {
pcChunk = target
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) {