fix optimized codegen for 2 arg functions, sometimes was passing wrong arg value due to register overwriting

This commit is contained in:
Irmen de Jong 2022-06-06 13:21:45 +02:00
parent 46ca0ac10d
commit f70b914779
5 changed files with 44 additions and 32 deletions

View File

@ -1384,12 +1384,12 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex")
} else {
val reg = resultRegister ?: RegisterOrPair.AY
var needAsave = !(fcall.args[0] is DirectMemoryRead || fcall.args[0] is NumericLiteral || fcall.args[0] is IdentifierReference)
var needAsave = needAsaveForOtherArg(fcall.args[0])
if(!needAsave) {
val mr0 = fcall.args[0] as? DirectMemoryRead
val mr1 = fcall.args[1] as? DirectMemoryRead
if (mr0 != null)
needAsave = mr0.addressExpression !is NumericLiteral && mr0.addressExpression !is IdentifierReference
needAsave = mr0.addressExpression !is NumericLiteral && mr0.addressExpression !is IdentifierReference
if (mr1 != null)
needAsave = needAsave or (mr1.addressExpression !is NumericLiteral && mr1.addressExpression !is IdentifierReference)
}
@ -1633,4 +1633,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
}
}
private fun needAsaveForOtherArg(arg: Expression): Boolean =
arg !is NumericLiteral && arg !is IdentifierReference && arg !is DirectMemoryRead
}

View File

@ -3,10 +3,7 @@ package prog8.codegen.cpu6502
import prog8.ast.IFunctionCall
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.expressions.AddressOf
import prog8.ast.expressions.Expression
import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteral
import prog8.ast.expressions.*
import prog8.ast.statements.*
import prog8.code.core.*
import prog8.codegen.cpu6502.assignment.AsmAssignSource
@ -72,6 +69,10 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
(sub.parameters.size==1 && sub.parameters[0].type in IntegerDatatypes)
|| (sub.parameters.size==2 && sub.parameters[0].type in ByteDatatypes && sub.parameters[1].type in ByteDatatypes)
private fun needAsaveForOtherArg(arg: Expression): Boolean =
arg !is NumericLiteral && arg !is IdentifierReference && arg !is DirectMemoryRead
internal fun translateFunctionCall(call: IFunctionCall, isExpression: Boolean) {
// Output only the code to set up the parameters and perform the actual call
// NOTE: does NOT output the code to deal with the result values!
@ -111,10 +112,10 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
} else {
// 2 byte params, second in Y, first in A
argumentViaRegister(sub, IndexedValue(0, sub.parameters[0]), call.args[0], RegisterOrPair.A)
if(!call.args[1].isSimple)
if(needAsaveForOtherArg(call.args[1]))
asmgen.out(" pha")
argumentViaRegister(sub, IndexedValue(1, sub.parameters[1]), call.args[1], RegisterOrPair.Y)
if(!call.args[1].isSimple)
if(needAsaveForOtherArg(call.args[1]))
asmgen.out(" pla")
}
} else {

View File

@ -50,12 +50,8 @@ internal class AstOnetimeTransforms(private val program: Program, private val op
} else {
val fcall = parent as? IFunctionCall
if(fcall!=null) {
if(options.compTarget.name != VMTarget.NAME) {
// TODO for now, 6502 codegen seems wrong when using pointer indexed args to any function.
val memread = DirectMemoryRead(add, arrayIndexedExpression.position)
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent))
} else if(fcall.target.nameInSource.size==1 && fcall.target.nameInSource[0] in InplaceModifyingBuiltinFunctions) {
// TODO for now, vm codegen seems wrong when using pointer indexed args to an in-place modifying function.
// TODO for now, codegen seems wrong when using pointer indexed args to an in-place modifying function.
if(fcall.target.nameInSource.size==1 && fcall.target.nameInSource[0] in InplaceModifyingBuiltinFunctions) {
val memread = DirectMemoryRead(add, arrayIndexedExpression.position)
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent))
} else {

View File

@ -3,7 +3,7 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- optimize pointervar indexing codegen: make them work as subroutine paramers
- optimize pointervar indexing codegen: make them work as params to in-place modifying functions (rol, swap, ...)
- optimize pointervar indexing codegen: writing (all sorts of things)
- pipe operator: (targets other than 'Virtual'): allow non-unary function calls in the pipe that specify the other argument(s) in the calls. Already working for VM target.
- add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value?

View File

@ -29,27 +29,39 @@ main {
; txt.spc()
; }
; sub derp(ubyte u1, ubyte u2, ubyte u3) {
; txt.print_ub(u1)
; txt.spc()
; txt.print_ub(u2)
; txt.spc()
; txt.print_ub(u3)
; txt.nl()
; }
sub derp2(ubyte u1, ubyte u2) {
txt.print_ub(u1)
txt.spc()
txt.print_ub(u2)
txt.nl()
}
sub start() {
; mcCarthy()
uword uw1 = 9999
uword uw2 = uw1 - 2000 + 10000
ubyte ub1 = 99
ubyte ub2 = ub1 - 2 + 10
ubyte ubb = ub2 - -10
txt.print_uw(uw2)
txt.spc()
txt.print_ub(ub2)
txt.spc()
txt.print_ub(ubb)
txt.nl()
;test_stack.test()
; ubyte value = 0
; ubyte one = 1
; ubyte[10] data = [11,22,33,4,5,6,7,8,9,10]
; uword bitmapbuf = &data
;
ubyte value = 0
ubyte one = 1
ubyte two = 2
ubyte[10] data = [11,22,33,4,5,6,7,8,9,10]
uword bitmapbuf = &data
;derp(data[0],data[1],data[2])
;derp(bitmapbuf[0], bitmapbuf[1], bitmapbuf[2])
derp2(1,2)
derp2(one, two)
derp2(data[1], data[2])
derp2(bitmapbuf[1], bitmapbuf[2])
; value = bitmapbuf[2]
; txt.print_ub(value) ;; 33
; txt.nl()