From 582a70b046255eae2a8b1b43da975537bf1bf231 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 4 Mar 2025 21:53:39 +0100 Subject: [PATCH] fix calling label as subroutine (JSR label) --- .../src/prog8/codegen/cpu6502/AsmGen.kt | 14 ++++++--- .../codegen/cpu6502/FunctionCallAsmGen.kt | 7 +++++ .../codegen/intermediate/ExpressionGen.kt | 16 ++++++++-- compiler/test/TestScoping.kt | 9 ++++++ examples/test.p8 | 29 ++++++------------- 5 files changed, 49 insertions(+), 26 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index c37167fe6..bdc9cf4be 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -138,7 +138,9 @@ class AsmGen6502(val prefixSymbols: Boolean, private val lastGeneratedLabelSeque functionCallsToPrefix.reversed().forEach { (parent, index) -> val node = parent.children[index] if(node is PtFunctionCall) { - parent.children[index] = node.prefix(parent) + val prefixedName = PtIdentifier(node.name, DataType.forDt(BaseDataType.UNDEFINED), Position.DUMMY).prefix(parent, st) + val prefixedNode = node.withNewName(prefixedName.name) + parent.children[index] = prefixedNode } else { throw AssemblyError("expected PtFunctionCall") } @@ -198,9 +200,13 @@ private fun PtVariable.prefix(parent: PtNode, st: SymbolTable): PtVariable { else this } -private fun PtFunctionCall.prefix(parent: PtNode): PtFunctionCall { - val newName = prefixScopedName(name, 's') - val call = PtFunctionCall(newName, void, type, position) +//private fun PtFunctionCall.prefix(targetType: Char): PtFunctionCall { +// val newName = prefixScopedName(name, targetType) +// return this.withNewName(newName) +//} + +private fun PtFunctionCall.withNewName(name: String): PtFunctionCall { + val call = PtFunctionCall(name, void, type, position) call.children.addAll(children) call.children.forEach { it.parent = call } call.parent = parent diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt index 71cc2aae8..8064af2fd 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt @@ -1,5 +1,6 @@ package prog8.codegen.cpu6502 +import prog8.code.StNodeType import prog8.code.ast.* import prog8.code.core.* import prog8.codegen.cpu6502.assignment.AsmAssignSource @@ -33,6 +34,12 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as // (you can use subroutine.shouldSaveX() and saveX()/restoreX() routines as a help for this) val symbol = asmgen.symbolTable.lookup(call.name)!! + if(symbol.type == StNodeType.LABEL) { + require(call.void) + asmgen.out(" jsr ${asmgen.asmSymbolName(symbol.scopedName)}") + return + } + val sub = symbol.astNode as IPtSubroutine val subAsmName = asmgen.asmSymbolName(call.name) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 7b5f8c8dd..3a7322467 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -2,6 +2,7 @@ package prog8.codegen.intermediate import prog8.code.StNode import prog8.code.StExtSub +import prog8.code.StNodeType import prog8.code.StSub import prog8.code.ast.* import prog8.code.core.* @@ -579,7 +580,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } internal fun translate(fcall: PtFunctionCall): ExpressionCodeResult { - val callTarget = codeGen.symbolTable.flat.getValue(fcall.name) + val callTarget = codeGen.symbolTable.lookup(fcall.name)!! if(callTarget.scopedName in listOf("sys.push", "sys.pushw", "sys.pop", "sys.popw", "floats.push", "floats.pop")) { // special case, these should be inlined, or even use specialized instructions. Instead of doing a normal subroutine call. @@ -755,7 +756,18 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { else ExpressionCodeResult(result, returnRegSpec!!.dt, finalReturnRegister, -1) } - else -> throw AssemblyError("invalid node type") + else -> { + if(callTarget.type == StNodeType.LABEL) { + require(fcall.void) + val result = mutableListOf() + val args = FunctionCallArgs(emptyList(), emptyList()) + addInstr(result, IRInstruction(Opcode.CALL, labelSymbol = fcall.name, fcallArgs = args), null) + return ExpressionCodeResult(result, IRDataType.BYTE, -1, -1) + } + else { + throw AssemblyError("invalid node type") + } + } } } diff --git a/compiler/test/TestScoping.kt b/compiler/test/TestScoping.kt index f253fe6a2..ec1b2c6dd 100644 --- a/compiler/test/TestScoping.kt +++ b/compiler/test/TestScoping.kt @@ -460,6 +460,7 @@ thing { sub routine() { other.something() other.counter++ + other.asmsomething() } } @@ -467,8 +468,16 @@ other { sub something() { } + asmsub asmsomething() { + %asm {{ + nop + rts + }} + } + uword @shared counter } + """ compileText(C64Target(), false, src, writeAssembly = true) shouldNotBe null diff --git a/examples/test.p8 b/examples/test.p8 index d4a382eb5..8d108345b 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,23 +1,12 @@ -; scoping bug: +%import textio +%zeropage basicsafe main { - sub start() { - thing.routine() - } -} - -thing { - %option no_symbol_prefixing - - sub routine() { - other.something() - other.counter++ - } -} - -other { - sub something() { - } - - uword @shared counter + sub start() { + txt.print("1\n") + label() + txt.print("2\n") +label: + txt.print("3\n") + } }