mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
fixed wrong return value when calling other subroutines in the return expression
This commit is contained in:
parent
2ff04d2abd
commit
1fe4439395
@ -15,6 +15,8 @@ import prog8.compiler.target.ICompilationTarget
|
|||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
|
|
||||||
|
private const val retvalName = "prog8_retval"
|
||||||
|
|
||||||
|
|
||||||
internal class StatementOptimizer(private val program: Program,
|
internal class StatementOptimizer(private val program: Program,
|
||||||
private val errors: IErrorReporter,
|
private val errors: IErrorReporter,
|
||||||
@ -25,6 +27,7 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
|
|
||||||
private val noModifications = emptyList<IAstModification>()
|
private val noModifications = emptyList<IAstModification>()
|
||||||
private val callgraph = CallGraph(program, asmFileLoader)
|
private val callgraph = CallGraph(program, asmFileLoader)
|
||||||
|
private val subsThatNeedReturnVariable = mutableSetOf<Triple<INameScope, DataType, Position>>()
|
||||||
|
|
||||||
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
|
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
|
||||||
if("force_output" !in block.options()) {
|
if("force_output" !in block.options()) {
|
||||||
@ -43,6 +46,12 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> {
|
override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> {
|
||||||
|
for(returnvar in subsThatNeedReturnVariable) {
|
||||||
|
val decl = VarDecl(VarDeclType.VAR, returnvar.second, ZeropageWish.DONTCARE, null, retvalName, null, null, false, true, returnvar.third)
|
||||||
|
returnvar.first.statements.add(0, decl)
|
||||||
|
}
|
||||||
|
subsThatNeedReturnVariable.clear()
|
||||||
|
|
||||||
val forceOutput = "force_output" in subroutine.definingBlock().options()
|
val forceOutput = "force_output" in subroutine.definingBlock().options()
|
||||||
if(subroutine.asmAddress==null && !forceOutput) {
|
if(subroutine.asmAddress==null && !forceOutput) {
|
||||||
if(subroutine.containsNoCodeNorVars() && !subroutine.inline) {
|
if(subroutine.containsNoCodeNorVars() && !subroutine.inline) {
|
||||||
@ -436,18 +445,13 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun after(returnStmt: Return, parent: Node): Iterable<IAstModification> {
|
override fun after(returnStmt: Return, parent: Node): Iterable<IAstModification> {
|
||||||
fun returnViaIntermediary(value: Expression): Iterable<IAstModification>? {
|
fun returnViaIntermediaryVar(value: Expression): Iterable<IAstModification>? {
|
||||||
val returnDt = returnStmt.definingSubroutine()!!.returntypes.single()
|
val subr = returnStmt.definingSubroutine()!!
|
||||||
|
val returnDt = subr.returntypes.single()
|
||||||
if (returnDt in IntegerDatatypes) {
|
if (returnDt in IntegerDatatypes) {
|
||||||
// first assign to intermediary, then return that register
|
// first assign to intermediary variable, then return that
|
||||||
val returnValueIntermediary =
|
subsThatNeedReturnVariable.add(Triple(subr, returnDt, returnStmt.position))
|
||||||
when(returnDt) {
|
val returnValueIntermediary = IdentifierReference(listOf(retvalName), returnStmt.position)
|
||||||
DataType.UBYTE -> IdentifierReference(listOf("prog8_lib", "retval_interm_ub"), returnStmt.position)
|
|
||||||
DataType.BYTE -> IdentifierReference(listOf("prog8_lib", "retval_interm_b"), returnStmt.position)
|
|
||||||
DataType.UWORD -> IdentifierReference(listOf("prog8_lib", "retval_interm_uw"), returnStmt.position)
|
|
||||||
DataType.WORD -> IdentifierReference(listOf("prog8_lib", "retval_interm_w"), returnStmt.position)
|
|
||||||
else -> throw FatalAstException("weird return dt")
|
|
||||||
}
|
|
||||||
val tgt = AssignTarget(returnValueIntermediary, null, null, returnStmt.position)
|
val tgt = AssignTarget(returnValueIntermediary, null, null, returnStmt.position)
|
||||||
val assign = Assignment(tgt, value, returnStmt.position)
|
val assign = Assignment(tgt, value, returnStmt.position)
|
||||||
val returnReplacement = Return(returnValueIntermediary, returnStmt.position)
|
val returnReplacement = Return(returnValueIntermediary, returnStmt.position)
|
||||||
@ -461,12 +465,12 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
|
|
||||||
when(returnStmt.value) {
|
when(returnStmt.value) {
|
||||||
is PrefixExpression -> {
|
is PrefixExpression -> {
|
||||||
val mod = returnViaIntermediary(returnStmt.value!!)
|
val mod = returnViaIntermediaryVar(returnStmt.value!!)
|
||||||
if(mod!=null)
|
if(mod!=null)
|
||||||
return mod
|
return mod
|
||||||
}
|
}
|
||||||
is BinaryExpression -> {
|
is BinaryExpression -> {
|
||||||
val mod = returnViaIntermediary(returnStmt.value!!)
|
val mod = returnViaIntermediaryVar(returnStmt.value!!)
|
||||||
if(mod!=null)
|
if(mod!=null)
|
||||||
return mod
|
return mod
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user