From 334d382bfa2fa079da3cf2d57edaba054d6d0fdc Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 7 Jul 2023 18:25:05 +0200 Subject: [PATCH] ir: JUMPI instruction added to support indirect jumps --- .../prog8/codegen/intermediate/IRCodeGen.kt | 26 ++++++++++++------- examples/test.p8 | 4 +-- .../src/prog8/intermediate/IRInstructions.kt | 12 ++++----- .../src/prog8/intermediate/IRProgram.kt | 2 ++ virtualmachine/src/prog8/vm/VirtualMachine.kt | 7 +++-- .../src/prog8/vm/VmProgramLoader.kt | 2 -- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index fe497f46a..0d4a282ab 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -1,9 +1,6 @@ package prog8.codegen.intermediate -import prog8.code.StMemVar -import prog8.code.StNode -import prog8.code.StStaticVariable -import prog8.code.SymbolTable +import prog8.code.* import prog8.code.ast.* import prog8.code.core.* import prog8.intermediate.* @@ -1520,17 +1517,26 @@ class IRCodeGen( private fun translate(jump: PtJump): IRCodeChunks { val result = mutableListOf() - val instr = if(jump.address!=null) { - IRInstruction(Opcode.JUMPA, address = jump.address!!.toInt()) + val chunk = IRCodeChunk(null, null) + if(jump.address!=null) { + chunk += IRInstruction(Opcode.JUMP, address = jump.address!!.toInt()) } else { if (jump.generatedLabel != null) - IRInstruction(Opcode.JUMP, labelSymbol = jump.generatedLabel!!) - else if (jump.identifier != null) - IRInstruction(Opcode.JUMP, labelSymbol = jump.identifier!!.name) + chunk += IRInstruction(Opcode.JUMP, labelSymbol = jump.generatedLabel!!) + else if (jump.identifier != null) { + val symbol = symbolTable.lookup(jump.identifier!!.name) + if(symbol?.type==StNodeType.MEMVAR || symbol?.type==StNodeType.STATICVAR) { + val jumpReg = registers.nextFree() + chunk += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1 = jumpReg, labelSymbol = jump.identifier!!.name) + chunk += IRInstruction(Opcode.JUMPI, reg1 = jumpReg) + } else { + chunk += IRInstruction(Opcode.JUMP, labelSymbol = jump.identifier!!.name) + } + } else throw AssemblyError("weird jump") } - addInstr(result, instr, null) + result += chunk return result } diff --git a/examples/test.p8 b/examples/test.p8 index 79d9a1d5e..7dfc8f478 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -17,10 +17,10 @@ main { txt.print_ub('a' in name) txt.print_ub('e' in name) txt.nl() - txt.print_ub(all(othercells)) ;; TODO fix vm ALL() ! + txt.print_ub(all(othercells)) txt.print_ub(any(othercells)) othercells[3] = 0 - txt.print_ub(all(othercells)) ;; TODO fix vm ALL() ! + txt.print_ub(all(othercells)) txt.print_ub(any(othercells)) reverse(othercells) sort(othercells) diff --git a/intermediate/src/prog8/intermediate/IRInstructions.kt b/intermediate/src/prog8/intermediate/IRInstructions.kt index 0bcae7733..db36d4dbe 100644 --- a/intermediate/src/prog8/intermediate/IRInstructions.kt +++ b/intermediate/src/prog8/intermediate/IRInstructions.kt @@ -51,8 +51,8 @@ storezx reg1, address - store zero at memory address, indexed by CONTROL FLOW ------------ -jump location - continue running at instruction number given by location -jumpa address - continue running at memory address (note: only used to encode a physical cpu jump to fixed address instruction) +jump location - continue running at instruction at 'location' (label/memory address) +jumpi reg1 - continue running at memory address in reg1 (indirect jump) call label(argument register list) [: resultreg.type] - calls a subroutine with the given arguments and return value (optional). save current instruction location+1, continue execution at instruction nr of the label. @@ -240,7 +240,7 @@ enum class Opcode { STOREZX, JUMP, - JUMPA, + JUMPI, CALL, SYSCALL, RETURN, @@ -378,14 +378,14 @@ enum class Opcode { val OpcodesThatJump = setOf( Opcode.JUMP, - Opcode.JUMPA, + Opcode.JUMPI, Opcode.RETURN, Opcode.RETURNR ) val OpcodesThatBranch = setOf( Opcode.JUMP, - Opcode.JUMPA, + Opcode.JUMPI, Opcode.RETURN, Opcode.RETURNR, Opcode.CALL, @@ -514,7 +514,7 @@ val instructionFormats = mutableMapOf( Opcode.STOREZI to InstructionFormat.from("BW,a | F,a"), Opcode.JUMP to InstructionFormat.from("N, { if(i.address!=null) throw IllegalArgumentException("vm program can't jump to system memory address (${i.opcode} ${i.address!!.toHex()})") + else if(i.labelSymbol!=null) + throw IllegalArgumentException("vm program can't jump to system memory address (${i.opcode} ${i.labelSymbol})") + else if(i.reg1!=null) + throw IllegalArgumentException("vm program can't jump to system memory address (${i})") else throw IllegalArgumentException("no branchtarget in $i") } @@ -174,8 +178,7 @@ class VirtualMachine(irProgram: IRProgram) { Opcode.STOREZM -> InsSTOREZM(ins) Opcode.STOREZX -> InsSTOREZX(ins) Opcode.STOREZI -> InsSTOREZI(ins) - Opcode.JUMP -> InsJUMP(ins) - Opcode.JUMPA -> throw IllegalArgumentException("vm program can't jump to system memory address (JUMPA)") + Opcode.JUMP, Opcode.JUMPI -> InsJUMP(ins) Opcode.CALL -> InsCALL(ins) Opcode.SYSCALL -> InsSYSCALL(ins) Opcode.RETURN -> InsRETURN() diff --git a/virtualmachine/src/prog8/vm/VmProgramLoader.kt b/virtualmachine/src/prog8/vm/VmProgramLoader.kt index 06072c8cb..496805bbf 100644 --- a/virtualmachine/src/prog8/vm/VmProgramLoader.kt +++ b/virtualmachine/src/prog8/vm/VmProgramLoader.kt @@ -191,8 +191,6 @@ class VmProgramLoader { } } - private val functionCallOpcodes = setOf(Opcode.CALL, Opcode.SYSCALL, Opcode.JUMP, Opcode.JUMPA) - private fun varsToMemory( program: IRProgram, allocations: VmVariableAllocator,