use an AnonymousScope to contain GoSub changes instead of adding separate statements

This commit is contained in:
Irmen de Jong 2021-11-28 12:09:13 +01:00
parent 3d23b39f4c
commit c52aa648c0
2 changed files with 20 additions and 34 deletions

View File

@ -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<IAstModification> {
if(function.parameters.isEmpty()) {
// 0 params -> just GoSub
val modifications = mutableListOf<IAstModification>()
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<IAstModification>()
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))
}
}

View File

@ -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: