fix calling label as subroutine (JSR label)

This commit is contained in:
Irmen de Jong 2025-03-04 21:53:39 +01:00
parent 5b63590ebf
commit 582a70b046
5 changed files with 49 additions and 26 deletions

View File

@ -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

View File

@ -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)

View File

@ -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<IRCodeChunkBase>()
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")
}
}
}
}

View File

@ -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

View File

@ -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")
}
}