diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index f763d453e..537c8c2a2 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -217,7 +217,7 @@ internal class AstChecker(private val program: Program, super.visit(label) } - private fun hasReturnOrJump(scope: IStatementContainer): Boolean { + private fun hasReturnOrJumpOrRts(scope: IStatementContainer): Boolean { class Searcher: IAstVisitor { var count=0 @@ -229,6 +229,13 @@ internal class AstChecker(private val program: Program, if(!jump.isGosub) count++ } + + override fun visit(inlineAssembly: InlineAssembly) { + val assembly = inlineAssembly.assembly + if(" rti" in assembly || "\trti" in assembly || " rts" in assembly || "\trts" in assembly || + " jmp" in assembly || "\tjmp" in assembly || " bra" in assembly || "\tbra" in assembly ) + count++ + } } val s=Searcher() @@ -262,13 +269,11 @@ internal class AstChecker(private val program: Program, // subroutine must contain at least one 'return' or 'goto' // (or if it has an asm block, that must contain a 'rts' or 'jmp' or 'bra') - if(!hasReturnOrJump(subroutine)) { - if (subroutine.amountOfRtsInAsm() == 0) { - if (subroutine.returntypes.isNotEmpty()) { - // for asm subroutines with an address, no statement check is possible. - if (subroutine.asmAddress == null && !subroutine.inline) - err("non-inline subroutine has result value(s) and thus must have at least one 'return' or 'goto' in it (or rts/jmp/bra in case of %asm)") - } + if(!hasReturnOrJumpOrRts(subroutine)) { + if (subroutine.returntypes.isNotEmpty()) { + // for asm subroutines with an address, no statement check is possible. + if (subroutine.asmAddress == null && !subroutine.inline) + err("non-inline subroutine has result value(s) and thus must have at least one 'return' or 'goto' in it (or rts/jmp/bra in case of %asm)") } } diff --git a/compilerAst/src/prog8/ast/statements/AstStatements.kt b/compilerAst/src/prog8/ast/statements/AstStatements.kt index 7ff2b88e9..c01c04d6d 100644 --- a/compilerAst/src/prog8/ast/statements/AstStatements.kt +++ b/compilerAst/src/prog8/ast/statements/AstStatements.kt @@ -706,12 +706,11 @@ class Subroutine(override val name: String, return KeepAresult(false, saveAonReturn) } - // TODO fix this to also look in asm nodes in subscopes fun amountOfRtsInAsm(): Int = statements .asSequence() .filter { it is InlineAssembly } .map { (it as InlineAssembly).assembly } - .count { " rti" in it || "\trti" in it || " rts" in it || "\trts" in it || " jmp" in it || "\tjmp" in it || " bra" in it || "\tbra" in it} + .count { " rti" in it || "\trti" in it || " rts" in it || "\trts" in it || " jmp" in it || "\tjmp" in it || " bra" in it || "\tbra" in it } // code to provide the ability to reference asmsub parameters via qualified name: diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 86c25d631..d58f014c3 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next compiler release (7.5) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- fix: amountOfRtsInAsm() look in subscopes too - fix: when statements generate unneeded branches to choice_end? diff --git a/examples/test.p8 b/examples/test.p8 index 0b2820679..1796054c5 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,4 +6,12 @@ main { sub start() { ubyte @shared bb = @(cx16.r0) } + + sub count() -> ubyte { + repeat { + %asm {{ + rts + }} + } + } }