From e6688f4b9d6e19430ce401de715c1e86d22e11f5 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 12 Nov 2022 13:45:02 +0100 Subject: [PATCH] clearer error for VM limitation cannot load label address as value --- compiler/test/vm/TestCompilerVirtual.kt | 28 +++++++++++++++++++ docs/source/todo.rst | 2 +- .../src/prog8/vm/VmProgramLoader.kt | 14 +++++++--- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/compiler/test/vm/TestCompilerVirtual.kt b/compiler/test/vm/TestCompilerVirtual.kt index 383def318..927c95de1 100644 --- a/compiler/test/vm/TestCompilerVirtual.kt +++ b/compiler/test/vm/TestCompilerVirtual.kt @@ -242,4 +242,32 @@ main { } exc.message shouldContain("does not support non-IR asmsubs") } + + test("addresses from labels/subroutines not yet supported in VM") { + val src = """ +main { + sub start() { + +mylabel: + ubyte variable + uword @shared pointer1 = &main.start + uword @shared pointer2 = &start + uword @shared pointer3 = &main.start.mylabel + uword @shared pointer4 = &mylabel + uword[] @shared ptrs = [&variable, &start, &main.start, &mylabel, &main.start.mylabel] + } +} + +""" + val othertarget = Cx16Target() + compileText(othertarget, true, src, writeAssembly = true, keepIR=true) shouldNotBe null + + val target = VMTarget() + val result = compileText(target, false, src, writeAssembly = true)!! + val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8ir") + val exc = shouldThrow { + VmRunner().runProgram(virtfile.readText()) + } + exc.message shouldContain("cannot yet load a label address as a value") + } }) \ No newline at end of file diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 15135940a..f0b9e4402 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- fix IR/VM compiler crash: subroutine address in array: uword[] @shared ptrs = [&x1, &x2, &start] + unit test - IRFileReader should parse the p8ir file with xml parser - 6502 codegen: make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway) then we can get rid of the instruction lists in the machinedefinitions as well. This is already no problem at all in the IR codegen. @@ -29,6 +28,7 @@ Compiler: - ir: peephole opt: renumber registers in chunks to start with 1 again every time (but keep entry values in mind!) - ir peephole opt: reuse registers in chunks (but keep result registers in mind that pass values out!) - ir: add more optimizations in IRPeepholeOptimizer +- vm: somehow be able to load a label address as value? (VmProgramLoader) - see if we can let for loops skip the loop if end TODO("inline binary data not yet supported in the VM") + is IRInlineBinaryChunk -> throw IRParseException("inline binary data not yet supported in the VM") // TODO is IRCodeChunk -> programChunks += chunk else -> throw AssemblyError("weird chunk type") } @@ -153,11 +153,15 @@ class VmProgramLoader { } else { // placeholder is not a variable, so it must be a label of a code chunk instead val target: IRCodeChunk? = chunks.firstOrNull { it.label==label } + val opcode = chunk.instructions[line].opcode if(target==null) throw IRParseException("placeholder not found in variables nor labels: $label") - else { - require(chunk.instructions[line].opcode in OpcodesThatBranch) + else if(opcode in OpcodesThatBranch) { chunk.instructions[line] = chunk.instructions[line].copy(branchTarget = target, value = null) + } else if(opcode in OpcodesWithMemoryAddressAsValue) { + throw IRParseException("vm cannot yet load a label address as a value: ${chunk.instructions[line]}") // TODO + } else { + throw IRParseException("vm cannot yet load a label address as a value: ${chunk.instructions[line]}") // TODO } } } else { @@ -244,7 +248,9 @@ class VmProgramLoader { DataType.ARRAY_UW -> { for(elt in it) { if(elt.addressOf!=null) { - val symbolAddress = symbolAddresses.getValue(elt.addressOf!!.joinToString(".")) + val name = elt.addressOf!!.joinToString(".") + val symbolAddress = symbolAddresses[name] + ?: throw IRParseException("vm cannot yet load a label address as a value: ${name}") // TODO memory.setUW(addr, symbolAddress.toUShort()) } else { memory.setUW(addr, elt.number!!.toInt().toUShort())