diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index 56649fc75..339102cec 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -389,30 +389,23 @@ internal class StatementReorderer(val program: Program, } Assignment(AssignTarget(paramIdentifier, null, null, argumentValue.position), argumentValue, argumentValue.position) } - return assignParams.map { IAstModification.InsertBefore(call, it, parent as IStatementContainer) } + - IAstModification.ReplaceNode( - call, - GoSub(null, call.target, null, call.position), - parent) + val scope = AnonymousScope(assignParams.toMutableList(), call.position) + scope.statements += GoSub(null, call.target, null, call.position) + return listOf(IAstModification.ReplaceNode(call, scope, parent)) } private fun replaceCallAsmSubStatementWithGosub(function: Subroutine, call: FunctionCallStatement, parent: Node): Iterable { if(function.parameters.isEmpty()) { // 0 params -> just GoSub - val modifications = mutableListOf() + val scope = AnonymousScope(mutableListOf(), call.position) if(function.shouldSaveX()) { - modifications += IAstModification.InsertBefore( - call, - FunctionCallStatement(IdentifierReference(listOf("sys", "rsavex"), call.position), mutableListOf(), true, call.position), - parent as IStatementContainer - ) - modifications += IAstModification.InsertAfter( - call, - FunctionCallStatement(IdentifierReference(listOf("sys", "rrestorex"), call.position), mutableListOf(), true, call.position), - parent as IStatementContainer - ) + scope.statements += FunctionCallStatement(IdentifierReference(listOf("sys", "rsavex"), call.position), mutableListOf(), true, call.position) } - return modifications + IAstModification.ReplaceNode(call, GoSub(null, call.target, null, call.position), parent) + scope.statements += GoSub(null, call.target, null, call.position) + if(function.shouldSaveX()) { + scope.statements += FunctionCallStatement(IdentifierReference(listOf("sys", "rrestorex"), call.position), mutableListOf(), true, call.position) + } + return listOf(IAstModification.ReplaceNode(call, scope, parent)) } else if(!options.compTarget.asmsubArgsHaveRegisterClobberRisk(call.args)) { // no register clobber risk, let the asmgen assign values to the registers directly. // this is more efficient than first evaluating them to the stack @@ -423,34 +416,26 @@ internal class StatementReorderer(val program: Program, if (options.slowCodegenWarnings) errors.warn("slow argument passing used to avoid register clobbering", call.position) val argOrder = options.compTarget.asmsubArgsEvalOrder(function) - val modifications = mutableListOf() + val scope = AnonymousScope(mutableListOf(), call.position) if(function.shouldSaveX()) { - modifications += IAstModification.InsertBefore( - call, - FunctionCallStatement(IdentifierReference(listOf("sys", "rsavex"), call.position), mutableListOf(), true, call.position), - parent as IStatementContainer - ) - modifications += IAstModification.InsertAfter( - call, - FunctionCallStatement(IdentifierReference(listOf("sys", "rrestorex"), call.position), mutableListOf(), true, call.position), - parent as IStatementContainer - ) + scope.statements += FunctionCallStatement(IdentifierReference(listOf("sys", "rsavex"), call.position), mutableListOf(), true, call.position) } argOrder.reversed().forEach { val arg = call.args[it] val param = function.parameters[it] - val push = pushCall(arg, param.type, arg.position) - modifications += IAstModification.InsertBefore(call, push, parent as IStatementContainer) + scope.statements += pushCall(arg, param.type, arg.position) } // ... and pop them off again into the registers. argOrder.forEach { val param = function.parameters[it] val targetName = function.scopedName + param.name - val pop = popCall(targetName, param.type, call.position) - modifications += IAstModification.InsertBefore(call, pop, parent as IStatementContainer) + scope.statements += popCall(targetName, param.type, call.position) } - - return modifications + IAstModification.ReplaceNode(call, GoSub(null, call.target, null, call.position), parent) + scope.statements += GoSub(null, call.target, null, call.position) + if(function.shouldSaveX()) { + scope.statements += FunctionCallStatement(IdentifierReference(listOf("sys", "rrestorex"), call.position), mutableListOf(), true, call.position) + } + return listOf(IAstModification.ReplaceNode(call, scope, parent)) } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index e5b476417..312aee84f 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -7,6 +7,7 @@ Use GoSub to call subroutines (statements): - [DONE] allow separate assigns to subroutine's parameter variables / registers - [DONE] turn a regular subroutine call into assignments to the parameters + GoSub (take code from gosub branch) - [DONE] also do this for asmsubs taking >0 parameters + - make that push(x+1) doesn't use stack evaluation, via a temp var? Optimize Function calls in expressions: