From 8e26e38ecc730c956e8b714d526c61aaa659a313 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 1 Apr 2021 23:30:19 +0200 Subject: [PATCH] fix RTS-issue with inlined return statement --- .../prog8/compiler/target/cpu6502/codegen/AsmGen.kt | 6 ++++-- .../target/cpu6502/codegen/FunctionCallAsmGen.kt | 13 +++++++++++-- docs/source/todo.rst | 2 -- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt index b0403a138..5ee41fdb6 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt @@ -1272,7 +1272,7 @@ $label nop""") } } - private fun translate(ret: Return) { + internal fun translate(ret: Return, withRts: Boolean=true) { ret.value?.let { returnvalue -> val sub = ret.definingSubroutine()!! val returnType = sub.returntypes.single() @@ -1291,7 +1291,9 @@ $label nop""") } } } - out(" rts") + + if(withRts) + out(" rts") } private fun translate(asm: InlineAssembly) { diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt index 6d98aaa23..631db8920 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt @@ -114,14 +114,23 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg if(!sub.inline || !asmgen.options.optimize) { asmgen.out(" jsr $subName") } else { - // inline the subroutine + // inline the subroutine. + // we do this by copying the subroutine's statements at the call site. + // NOTE: *if* there is a return statement, it will be the only one, and the very last statement of the subroutine + // (this condition has been enforced by an ast check earlier) if(sub.containsDefinedVariables()) throw AssemblyError("can't inline sub with vars") if(!sub.isAsmSubroutine && sub.parameters.isNotEmpty()) throw AssemblyError("can't inline a non-asm subroutine with parameters") asmgen.out(" \t; inlined routine follows: ${sub.name} from ${sub.position}") val statements = sub.statements.filter { it !is ParameterVarDecl && it !is Directive } - statements.forEach { asmgen.translate(it) } + statements.forEach { + if(it is Return) { + asmgen.translate(it, false) // don't use RTS for the inlined return statement + } else { + asmgen.translate(it) + } + } } // remember: dealing with the X register and/or dealing with return values is the responsibility of the caller diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 3befcad78..2e98e58fe 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -2,8 +2,6 @@ TODO ==== -- fix inlining issue with return statement inlined literally at call site - - allow inlining of subroutines with vardecls - optimize several inner loops in gfx2 - hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)