fix sub return register

This commit is contained in:
Irmen de Jong 2023-02-03 00:27:50 +01:00
parent 201b77d5b6
commit 109e118aba
7 changed files with 38 additions and 26 deletions

View File

@ -835,7 +835,7 @@ $repeatLabel lda $counterVar
private fun translate(ret: PtReturn, withRts: Boolean=true) { private fun translate(ret: PtReturn, withRts: Boolean=true) {
ret.value?.let { returnvalue -> ret.value?.let { returnvalue ->
val sub = ret.definingSub()!! val sub = ret.definingSub()!!
val returnReg = RegisterOrStatusflag(RegisterOrPair.A, null) // TODO("what is returnReg of the sub?") val returnReg = sub.returnRegister()!!
when (sub.returntype) { when (sub.returntype) {
in NumericDatatypes -> { in NumericDatatypes -> {
assignExpressionToRegister(returnvalue, returnReg.registerOrPair!!) assignExpressionToRegister(returnvalue, returnReg.registerOrPair!!)

View File

@ -44,7 +44,7 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
private fun translateFunctionCallResultOntoStack(call: PtFunctionCall) { private fun translateFunctionCallResultOntoStack(call: PtFunctionCall) {
// only for use in nested expression evaluation // only for use in nested expression evaluation
val sub = call.targetSubroutine(program)!! val sub = call.targetSubroutine(program)
asmgen.saveXbeforeCall(call) asmgen.saveXbeforeCall(call)
asmgen.translateFunctionCall(call, true) asmgen.translateFunctionCall(call, true)
if(sub.regXasResult()) { if(sub.regXasResult()) {

View File

@ -66,6 +66,7 @@ internal fun PtIdentifier.targetStatement(program: PtProgram): PtNode {
} }
internal fun PtProgram.lookup(name: String): PtNode { internal fun PtProgram.lookup(name: String): PtNode {
// TODO should be cached?
fun searchLocalSymbol(node: PtNode, namePart: String): PtNode? { fun searchLocalSymbol(node: PtNode, namePart: String): PtNode? {
when(node) { when(node) {
is PtProgram -> { is PtProgram -> {
@ -131,8 +132,8 @@ internal fun PtAsmSub.shouldKeepA(): KeepAresult {
return KeepAresult(false, saveAonReturn) return KeepAresult(false, saveAonReturn)
} }
internal fun PtFunctionCall.targetSubroutine(program: PtProgram): IPtSubroutine? = internal fun PtFunctionCall.targetSubroutine(program: PtProgram): IPtSubroutine =
this.targetStatement(program) as? IPtSubroutine this.targetStatement(program) as IPtSubroutine
internal fun PtFunctionCall.targetStatement(program: PtProgram): PtNode { internal fun PtFunctionCall.targetStatement(program: PtProgram): PtNode {
return if(name in BuiltinFunctions) return if(name in BuiltinFunctions)
@ -186,3 +187,13 @@ internal fun PtExpression.clone(): PtExpression {
is PtTypeCast -> return withClonedChildrenFrom(this, PtTypeCast(type, position)) is PtTypeCast -> return withClonedChildrenFrom(this, PtTypeCast(type, position))
} }
} }
internal fun PtSub.returnRegister(): RegisterOrStatusflag? {
return when(returntype) {
in ByteDatatypes -> RegisterOrStatusflag(RegisterOrPair.A, null)
in WordDatatypes -> RegisterOrStatusflag(RegisterOrPair.AY, null)
DataType.FLOAT -> RegisterOrStatusflag(RegisterOrPair.FAC1, null)
null -> null
else -> RegisterOrStatusflag(RegisterOrPair.AY, null)
}
}

View File

@ -18,7 +18,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
} }
internal fun saveXbeforeCall(stmt: PtFunctionCall) { internal fun saveXbeforeCall(stmt: PtFunctionCall) {
val sub = stmt.targetSubroutine(program) ?: throw AssemblyError("undefined subroutine ${stmt.name}") val sub = stmt.targetSubroutine(program)
if(sub.shouldSaveX()) { if(sub.shouldSaveX()) {
if(sub is PtAsmSub) { if(sub is PtAsmSub) {
val regSaveOnStack = sub.address == null // rom-routines don't require registers to be saved on stack, normal subroutines do because they can contain nested calls val regSaveOnStack = sub.address == null // rom-routines don't require registers to be saved on stack, normal subroutines do because they can contain nested calls
@ -32,7 +32,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
} }
internal fun restoreXafterCall(stmt: PtFunctionCall) { internal fun restoreXafterCall(stmt: PtFunctionCall) {
val sub = stmt.targetSubroutine(program) ?: throw AssemblyError("undefined subroutine ${stmt.name}") val sub = stmt.targetSubroutine(program)
if(sub.shouldSaveX()) { if(sub.shouldSaveX()) {
if(sub is PtAsmSub) { if(sub is PtAsmSub) {
val regSaveOnStack = sub.address == null // rom-routines don't require registers to be saved on stack, normal subroutines do because they can contain nested calls val regSaveOnStack = sub.address == null // rom-routines don't require registers to be saved on stack, normal subroutines do because they can contain nested calls
@ -55,7 +55,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
// NOTE: does NOT output code to save/restore the X register for this call! Every caller should deal with this in their own way!! // NOTE: does NOT output code to save/restore the X register for this call! Every caller should deal with this in their own way!!
// (you can use subroutine.shouldSaveX() and saveX()/restoreX() routines as a help for this) // (you can use subroutine.shouldSaveX() and saveX()/restoreX() routines as a help for this)
val sub: IPtSubroutine = call.targetSubroutine(program) ?: throw AssemblyError("undefined subroutine ${call.name}") val sub: IPtSubroutine = call.targetSubroutine(program)
val subAsmName = asmgen.asmSymbolName(call.name) val subAsmName = asmgen.asmSymbolName(call.name)
if(sub is PtAsmSub) { if(sub is PtAsmSub) {

View File

@ -158,7 +158,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, value.type, expression = value) AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, value.type, expression = value)
} }
is PtFunctionCall -> { is PtFunctionCall -> {
val sub = value.targetSubroutine(program)!! val sub = value.targetSubroutine(program)
val returnType = sub.returnsWhatWhere().firstOrNull { rr -> rr.second.registerOrPair != null || rr.second.statusflag!=null }?.first val returnType = sub.returnsWhatWhere().firstOrNull { rr -> rr.second.registerOrPair != null || rr.second.statusflag!=null }?.first
?: throw AssemblyError("can't translate zero return values in assignment") ?: throw AssemblyError("can't translate zero return values in assignment")

View File

@ -178,7 +178,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
is PtMemoryByte -> throw AssemblyError("source kind should have been memory") is PtMemoryByte -> throw AssemblyError("source kind should have been memory")
is PtTypeCast -> assignTypeCastedValue(assign.target, value.type, value.value, value) is PtTypeCast -> assignTypeCastedValue(assign.target, value.type, value.value, value)
is PtFunctionCall -> { is PtFunctionCall -> {
val sub = value.targetSubroutine(program)!! val sub = value.targetSubroutine(program)
asmgen.saveXbeforeCall(value) asmgen.saveXbeforeCall(value)
asmgen.translateFunctionCall(value, true) asmgen.translateFunctionCall(value, true)
val returnValue = sub.returnsWhatWhere().singleOrNull() { it.second.registerOrPair!=null } ?: sub.returnsWhatWhere().single() { it.second.statusflag!=null } val returnValue = sub.returnsWhatWhere().singleOrNull() { it.second.registerOrPair!=null } ?: sub.returnsWhatWhere().single() { it.second.statusflag!=null }

View File

@ -1,22 +1,23 @@
%import textio
%option no_sysinit
%zeropage basicsafe
main { main {
sub start() { sub start() {
rsavex() testscope.duplicate()
cx16.r0L = testscope.duplicate2()
ubyte @shared ub }
main.normalfoo.arg=99 }
void normalfoo(42)
somelabel: testscope {
ub++
txt.print_ub(ub) sub sub1() {
} ubyte @shared duplicate
ubyte @shared duplicate2
sub normalfoo(ubyte arg) -> ubyte { }
arg++
return 42 sub duplicate() {
; do nothing
}
sub duplicate2() -> ubyte {
return cx16.r0L
} }
} }