From f9200a2b752440561553666e2048cd4541efe586 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 2 Jul 2023 23:41:15 +0200 Subject: [PATCH] fix IR loader for romsub calls (calls to an address) --- docs/source/todo.rst | 7 ------- examples/test.p8 | 3 +-- .../src/prog8/intermediate/IRProgram.kt | 17 ++++++++++++----- intermediate/src/prog8/intermediate/Utils.kt | 18 ++++++++++++++---- virtualmachine/src/prog8/vm/VmProgramLoader.kt | 2 +- 5 files changed, 28 insertions(+), 19 deletions(-) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 2c8d29d7d..d28f97d31 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,13 +1,6 @@ TODO ==== -- fix IR loading of romsubs - romsub $FFD2 = chrout(ubyte ch @ A) - sub start() { - ubyte ch = '\n' - chrout(ch) - } - ... diff --git a/examples/test.p8 b/examples/test.p8 index d750d0ca9..ec333d23d 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -2,10 +2,9 @@ %zeropage basicsafe main { - romsub $FFD2 = chrout(ubyte ch @ A) sub start() { - ubyte ch = '\n' + ubyte ch = '2' chrout(ch) } } diff --git a/intermediate/src/prog8/intermediate/IRProgram.kt b/intermediate/src/prog8/intermediate/IRProgram.kt index 23b5a0881..29f036fee 100644 --- a/intermediate/src/prog8/intermediate/IRProgram.kt +++ b/intermediate/src/prog8/intermediate/IRProgram.kt @@ -138,9 +138,14 @@ class IRProgram(val name: String, // link all jump and branching instructions to their target chunk.instructions.forEach { - if(it.opcode in OpcodesThatBranch && it.opcode!=Opcode.RETURN && it.opcode!=Opcode.RETURNR && it.labelSymbol!=null) - it.branchTarget = labeledChunks.getValue(it.labelSymbol) - // note: branches with an address value cannot be linked to something... + if(it.opcode in OpcodesThatBranch && it.opcode!=Opcode.RETURN && it.opcode!=Opcode.RETURNR && it.labelSymbol!=null) { + if(it.labelSymbol.startsWith('$') || it.labelSymbol.first().isDigit()) { + // it's a call to an address (romsub most likely) + require(it.address!=null) + } else { + it.branchTarget = labeledChunks.getValue(it.labelSymbol) + } + } } } is IRInlineAsmChunk -> { @@ -199,8 +204,10 @@ class IRProgram(val name: String, require(!chunk.isIR) { "inline IR-asm should have been converted into regular code chunk"} } chunk.instructions.forEach { - if(it.labelSymbol!=null && it.opcode in OpcodesThatBranch) - require(it.branchTarget != null) { "branching instruction to label should have branchTarget set" } + if(it.labelSymbol!=null && it.opcode in OpcodesThatBranch) { + if(!it.labelSymbol.startsWith('$') && !it.labelSymbol.first().isDigit()) + require(it.branchTarget != null) { "branching instruction to label should have branchTarget set" } + } } } } diff --git a/intermediate/src/prog8/intermediate/Utils.kt b/intermediate/src/prog8/intermediate/Utils.kt index 378c48f07..472104780 100644 --- a/intermediate/src/prog8/intermediate/Utils.kt +++ b/intermediate/src/prog8/intermediate/Utils.kt @@ -131,11 +131,11 @@ fun parseIRCodeLine(line: String): Either { } if(format.sysCall) { val call = parseCall(rest) - val syscallNum = parseIRValue(call.target).toInt() + val syscallNum = call.address ?: parseIRValue(call.target ?: "").toInt() return left(IRInstruction(Opcode.SYSCALL, immediate = syscallNum, fcallArgs = FunctionCallArgs(call.args, call.returns))) } else if (format.funcCall) { val call = parseCall(rest) - return left(IRInstruction(Opcode.CALL, labelSymbol = call.target, fcallArgs = FunctionCallArgs(call.args, call.returns))) + return left(IRInstruction(Opcode.CALL, address = call.address, labelSymbol = call.target, fcallArgs = FunctionCallArgs(call.args, call.returns))) } else { operands.forEach { oper -> if (oper[0] == '&') @@ -222,7 +222,8 @@ fun parseIRCodeLine(line: String): Either { } private class ParsedCall( - val target: String, + val target: String?, + val address: Int?, val args: List, val returns: FunctionCallArgs.RegSpec? ) @@ -266,8 +267,17 @@ private fun parseCall(rest: String): ParsedCall { val args = match.groups["arglist"]!!.value val arguments = parseArgs(args) val returns = match.groups["returns"]?.value + var address: Int? = null + var actualTarget: String? = target + + if(target.startsWith('$') || target[0].isDigit()) { + address = parseIRValue(target).toInt() + actualTarget = null + } + return ParsedCall( - target, + actualTarget, + address, arguments, if(returns==null) null else parseRegspec(returns) ) diff --git a/virtualmachine/src/prog8/vm/VmProgramLoader.kt b/virtualmachine/src/prog8/vm/VmProgramLoader.kt index 7f3007e6e..daf236a0a 100644 --- a/virtualmachine/src/prog8/vm/VmProgramLoader.kt +++ b/virtualmachine/src/prog8/vm/VmProgramLoader.kt @@ -179,7 +179,7 @@ class VmProgramLoader { if(arg.address!=null) arg else { - val address = variableAddresses.getValue(ins.labelSymbol + "." + arg.name) + val address = ins.address ?: variableAddresses.getValue(ins.labelSymbol + "." + arg.name) FunctionCallArgs.ArgumentSpec(arg.name, address, arg.reg) } }