mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
also consider Y register for clobber check for functioncall arguments
This commit is contained in:
parent
b438d8aec0
commit
a2db44f80c
@ -1,11 +1,9 @@
|
||||
package prog8.compiler.target
|
||||
|
||||
import com.github.michaelbull.result.fold
|
||||
import prog8.ast.base.ByteDatatypes
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.base.PassByReferenceDatatypes
|
||||
import prog8.ast.base.WordDatatypes
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.expressions.Expression
|
||||
import prog8.ast.statements.RegisterOrStatusflag
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.compiler.target.c64.C64MachineDefinition
|
||||
import prog8.compiler.target.cbm.Petscii
|
||||
@ -26,8 +24,10 @@ object C64Target: ICompilationTarget {
|
||||
override fun decodeString(bytes: List<UByte>, altEncoding: Boolean) =
|
||||
if (altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
|
||||
|
||||
override fun asmsubArgsEvalOrder(sub: Subroutine): List<Int> = asmsub6502ArgsEvalOrder(sub)
|
||||
override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>) = asmsub6502ArgsHaveRegisterClobberRisk(args)
|
||||
override fun asmsubArgsEvalOrder(sub: Subroutine): List<Int> =
|
||||
asmsub6502ArgsEvalOrder(sub)
|
||||
override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>, paramRegisters: List<RegisterOrStatusflag>) =
|
||||
asmsub6502ArgsHaveRegisterClobberRisk(args, paramRegisters)
|
||||
|
||||
override fun memorySize(dt: DataType): Int {
|
||||
return when(dt) {
|
||||
|
@ -6,6 +6,7 @@ import prog8.ast.base.DataType
|
||||
import prog8.ast.base.PassByReferenceDatatypes
|
||||
import prog8.ast.base.WordDatatypes
|
||||
import prog8.ast.expressions.Expression
|
||||
import prog8.ast.statements.RegisterOrStatusflag
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.compiler.target.cbm.Petscii
|
||||
import prog8.compiler.target.cpu6502.codegen.asmsub6502ArgsEvalOrder
|
||||
@ -27,8 +28,10 @@ object Cx16Target: ICompilationTarget {
|
||||
override fun decodeString(bytes: List<UByte>, altEncoding: Boolean) =
|
||||
if (altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
|
||||
|
||||
override fun asmsubArgsEvalOrder(sub: Subroutine): List<Int> = asmsub6502ArgsEvalOrder(sub)
|
||||
override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>) = asmsub6502ArgsHaveRegisterClobberRisk(args)
|
||||
override fun asmsubArgsEvalOrder(sub: Subroutine): List<Int> =
|
||||
asmsub6502ArgsEvalOrder(sub)
|
||||
override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>, paramRegisters: List<RegisterOrStatusflag>) =
|
||||
asmsub6502ArgsHaveRegisterClobberRisk(args, paramRegisters)
|
||||
|
||||
override fun memorySize(dt: DataType): Int {
|
||||
return when(dt) {
|
||||
|
@ -104,8 +104,10 @@ class AsmGen(private val program: Program,
|
||||
internal fun isTargetCpu(cpu: CpuType) = compTarget.machine.cpu == cpu
|
||||
internal fun haveFPWR() = compTarget is Cx16Target
|
||||
|
||||
internal fun asmsubArgsEvalOrder(sub: Subroutine) = compTarget.asmsubArgsEvalOrder(sub)
|
||||
internal fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>) = compTarget.asmsubArgsHaveRegisterClobberRisk(args)
|
||||
internal fun asmsubArgsEvalOrder(sub: Subroutine) =
|
||||
compTarget.asmsubArgsEvalOrder(sub)
|
||||
internal fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>, paramRegisters: List<RegisterOrStatusflag>) =
|
||||
compTarget.asmsubArgsHaveRegisterClobberRisk(args, paramRegisters)
|
||||
|
||||
private fun header() {
|
||||
val ourName = this.javaClass.name
|
||||
|
@ -3,6 +3,7 @@ package prog8.compiler.target.cpu6502.codegen
|
||||
import prog8.ast.base.Cx16VirtualRegisters
|
||||
import prog8.ast.base.RegisterOrPair
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.RegisterOrStatusflag
|
||||
import prog8.ast.statements.Subroutine
|
||||
|
||||
|
||||
@ -34,19 +35,27 @@ internal fun asmsub6502ArgsEvalOrder(sub: Subroutine): List<Int> {
|
||||
return order
|
||||
}
|
||||
|
||||
internal fun asmsub6502ArgsHaveRegisterClobberRisk(args: List<Expression>): Boolean {
|
||||
internal fun asmsub6502ArgsHaveRegisterClobberRisk(args: List<Expression>,
|
||||
paramRegisters: List<RegisterOrStatusflag>): Boolean {
|
||||
fun isClobberRisk(expr: Expression): Boolean {
|
||||
if (expr.isSimple && expr !is PrefixExpression)
|
||||
return false
|
||||
|
||||
if (expr is FunctionCall) {
|
||||
if (expr.target.nameInSource == listOf("lsb") || expr.target.nameInSource == listOf("msb"))
|
||||
return isClobberRisk(expr.args[0])
|
||||
if (expr.target.nameInSource == listOf("mkword"))
|
||||
return isClobberRisk(expr.args[0]) && isClobberRisk(expr.args[1])
|
||||
when (expr) {
|
||||
is ArrayIndexedExpression -> {
|
||||
return paramRegisters.any {
|
||||
it.registerOrPair in listOf(RegisterOrPair.Y, RegisterOrPair.AY, RegisterOrPair.XY)
|
||||
}
|
||||
}
|
||||
is PrefixExpression -> {
|
||||
return true // TODO really, is prefixexpression problematic for register clobbering?
|
||||
}
|
||||
is FunctionCall -> {
|
||||
if (expr.target.nameInSource == listOf("lsb") || expr.target.nameInSource == listOf("msb"))
|
||||
return isClobberRisk(expr.args[0])
|
||||
if (expr.target.nameInSource == listOf("mkword"))
|
||||
return isClobberRisk(expr.args[0]) && isClobberRisk(expr.args[1])
|
||||
return !expr.isSimple
|
||||
}
|
||||
else -> return !expr.isSimple
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return args.size>1 && args.any { isClobberRisk(it) }
|
||||
|
@ -114,7 +114,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
||||
if(sub.parameters.size==1) {
|
||||
argumentViaRegister(sub, IndexedValue(0, sub.parameters.single()), call.args[0])
|
||||
} else {
|
||||
if(asmgen.asmsubArgsHaveRegisterClobberRisk(call.args)) {
|
||||
if(asmgen.asmsubArgsHaveRegisterClobberRisk(call.args, sub.asmParameterRegisters)) {
|
||||
registerArgsViaStackEvaluation(call, sub)
|
||||
} else {
|
||||
asmgen.asmsubArgsEvalOrder(sub).forEach {
|
||||
|
@ -411,7 +411,7 @@ internal class StatementReorderer(val program: Program,
|
||||
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)) {
|
||||
} else if(!options.compTarget.asmsubArgsHaveRegisterClobberRisk(call.args, function.asmParameterRegisters)) {
|
||||
// No register clobber risk, let the asmgen assign values to the registers directly.
|
||||
// this is more efficient than first evaluating them to the stack.
|
||||
// As complex expressions will be flagged as a clobber-risk, these will be simplified below.
|
||||
|
@ -9,6 +9,7 @@ import io.kotest.matchers.comparables.shouldBeGreaterThan
|
||||
import io.kotest.matchers.shouldBe
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.expressions.Expression
|
||||
import prog8.ast.statements.RegisterOrStatusflag
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.compiler.target.Cx16Target
|
||||
@ -37,7 +38,8 @@ class TestAbstractZeropage: FunSpec({
|
||||
throw NotImplementedError("dummy")
|
||||
}
|
||||
|
||||
override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>): Boolean {
|
||||
override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>,
|
||||
paramRegisters: List<RegisterOrStatusflag>): Boolean {
|
||||
throw NotImplementedError("dummy")
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package prog8.compilerinterface
|
||||
|
||||
import prog8.ast.expressions.Expression
|
||||
import prog8.ast.statements.RegisterOrStatusflag
|
||||
import prog8.ast.statements.Subroutine
|
||||
|
||||
interface ICompilationTarget: IStringEncoding, IMemSizer {
|
||||
@ -10,5 +11,6 @@ interface ICompilationTarget: IStringEncoding, IMemSizer {
|
||||
override fun decodeString(bytes: List<UByte>, altEncoding: Boolean): String
|
||||
|
||||
fun asmsubArgsEvalOrder(sub: Subroutine): List<Int>
|
||||
fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>): Boolean
|
||||
fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>,
|
||||
paramRegisters: List<RegisterOrStatusflag>): Boolean
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ TODO
|
||||
For next compiler release (7.4)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
BUG: sys.rsave/sys.rrestore can never work as subroutine because stack is used -> builtin funcs
|
||||
|
||||
BUG: balls example crashes / animates wrong!
|
||||
caused by c83882161521378f20dc0076c01e18e8556e363e 'refactor function arguments codegen a bit'
|
||||
on the lines that call txt.setclr(BX[lp], BY[lp], BC[lp]) - they work with regular vars as args
|
||||
|
@ -1,28 +1,26 @@
|
||||
%import textio
|
||||
%import test_stack
|
||||
%zeropage dontuse
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
test_stack.test()
|
||||
|
||||
ubyte[50] xpos = 49 to 0 step -1
|
||||
ubyte[50] ypos = 49 to 0 step -1
|
||||
ubyte[20] xpos = 19 to 0 step -1
|
||||
ubyte[20] ypos = 19 to 0 step -1
|
||||
|
||||
ubyte ball
|
||||
for ball in 0 to len(xpos)-1 {
|
||||
txt.print_ub(xpos[ball])
|
||||
txt.spc()
|
||||
txt.print_ub(ypos[ball])
|
||||
txt.nl()
|
||||
ubyte xx = xpos[ball] + 1
|
||||
ubyte yy = ypos[ball]
|
||||
txt.setchr(xx,yy,87) ; correct codegen
|
||||
txt.setclr(xx,yy,5) ; correct codegen
|
||||
txt.setchr(xpos[ball], ypos[ball], 81) ; TODO WRONG CODEGEN WITH NOOPT
|
||||
txt.setclr(xpos[ball], ypos[ball], 6) ; TODO WRONG CODEGEN WITH NOOPT
|
||||
}
|
||||
|
||||
ubyte @shared x1 = 10
|
||||
ubyte @shared x2 = 20
|
||||
ubyte @shared x3 = 30
|
||||
|
||||
test_stack.test()
|
||||
|
||||
repeat {
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user