fix RTS-issue with inlined return statement

This commit is contained in:
Irmen de Jong 2021-04-01 23:30:19 +02:00
parent 02e12d8575
commit 8e26e38ecc
3 changed files with 15 additions and 6 deletions

View File

@ -1272,7 +1272,7 @@ $label nop""")
} }
} }
private fun translate(ret: Return) { internal fun translate(ret: Return, withRts: Boolean=true) {
ret.value?.let { returnvalue -> ret.value?.let { returnvalue ->
val sub = ret.definingSubroutine()!! val sub = ret.definingSubroutine()!!
val returnType = sub.returntypes.single() val returnType = sub.returntypes.single()
@ -1291,7 +1291,9 @@ $label nop""")
} }
} }
} }
out(" rts")
if(withRts)
out(" rts")
} }
private fun translate(asm: InlineAssembly) { private fun translate(asm: InlineAssembly) {

View File

@ -114,14 +114,23 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
if(!sub.inline || !asmgen.options.optimize) { if(!sub.inline || !asmgen.options.optimize) {
asmgen.out(" jsr $subName") asmgen.out(" jsr $subName")
} else { } 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()) if(sub.containsDefinedVariables())
throw AssemblyError("can't inline sub with vars") throw AssemblyError("can't inline sub with vars")
if(!sub.isAsmSubroutine && sub.parameters.isNotEmpty()) if(!sub.isAsmSubroutine && sub.parameters.isNotEmpty())
throw AssemblyError("can't inline a non-asm subroutine with parameters") throw AssemblyError("can't inline a non-asm subroutine with parameters")
asmgen.out(" \t; inlined routine follows: ${sub.name} from ${sub.position}") asmgen.out(" \t; inlined routine follows: ${sub.name} from ${sub.position}")
val statements = sub.statements.filter { it !is ParameterVarDecl && it !is Directive } 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 // remember: dealing with the X register and/or dealing with return values is the responsibility of the caller

View File

@ -2,8 +2,6 @@
TODO TODO
==== ====
- fix inlining issue with return statement inlined literally at call site
- allow inlining of subroutines with vardecls - allow inlining of subroutines with vardecls
- optimize several inner loops in gfx2 - 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) - 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)