diff --git a/codeCore/src/prog8/code/ast/AstExpressions.kt b/codeCore/src/prog8/code/ast/AstExpressions.kt index f0650ee6c..5db58c38a 100644 --- a/codeCore/src/prog8/code/ast/AstExpressions.kt +++ b/codeCore/src/prog8/code/ast/AstExpressions.kt @@ -204,7 +204,7 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) { return false } - fun maxDepth(): Pair, Int> { + fun maxDepth(): Map { val depths = mutableMapOf( DataType.UBYTE to 0, DataType.UWORD to 0, @@ -225,7 +225,7 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) { depths[DataType.UBYTE] = depth maxDepths[DataType.UBYTE] = max(maxDepths.getValue(DataType.UBYTE), depth) } - in WordDatatypes -> { + in WordDatatypes, in PassByReferenceDatatypes -> { val depth = depths.getValue(DataType.UWORD) + 1 depths[DataType.UWORD] = depth maxDepths[DataType.UWORD] = max(maxDepths.getValue(DataType.UWORD), depth) @@ -243,7 +243,7 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) { fun pop(type: DataType) { when (type) { in ByteDatatypes -> depths[DataType.UBYTE]=depths.getValue(DataType.UBYTE) - 1 - in WordDatatypes -> depths[DataType.UWORD]=depths.getValue(DataType.UWORD) - 1 + in WordDatatypes, in PassByReferenceDatatypes -> depths[DataType.UWORD]=depths.getValue(DataType.UWORD) - 1 DataType.FLOAT -> depths[DataType.FLOAT]=depths.getValue(DataType.FLOAT) - 1 else -> throw IllegalArgumentException("invalid dt") } @@ -260,10 +260,10 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) { push((node as PtExpression).type) } } - require(numPushes==numPops+1) { - "RPN not balanced, pushes=$numPushes pops=$numPops" + require(numPushes==numPops+1 && numPushes==children.size) { + "RPN not balanced, pushes=$numPushes pops=$numPops childs=${children.size}" } - return Pair(maxDepths, numPushes) + return maxDepths } fun finalOperator() = children.last() as PtRpnOperator diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index 3eaf99e04..7c795736d 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -1013,8 +1013,29 @@ $repeatLabel lda $counterVar when (pointerOffsetExpr) { is PtRpn -> { if(pointerOffsetExpr.children.size>3) { - println("TODO: RPN: too complicated pointerViaIndexRegisterPossible") // TODO RPN: split expression? - return null // expression is too complex, we need just a pointer var + index + val rightmostOperator = pointerOffsetExpr.finalOperator() + if(rightmostOperator.operator=="+") { + val rightmostOperand = pointerOffsetExpr.finalRightOperand() + if ((rightmostOperand is PtNumber && rightmostOperand.type in IntegerDatatypes && rightmostOperand.number.toInt() in 0..255) + || (rightmostOperand is PtExpression && rightmostOperand.type == DataType.UBYTE) + || (rightmostOperand is PtTypeCast && rightmostOperand.value.type == DataType.UBYTE) + ) { + // split up the big expression in 2 parts so that we CAN use ZP,Y indexing after all + pointerOffsetExpr.children.removeLast() + pointerOffsetExpr.children.removeLast() + val tempvar = getTempVarName(DataType.UWORD) + assignExpressionToVariable(pointerOffsetExpr, tempvar, DataType.UWORD, pointerOffsetExpr.definingISub()) + val smallExpr = PtRpn(DataType.UWORD, pointerOffsetExpr.position) + smallExpr.addRpnNode(PtIdentifier(tempvar, DataType.UWORD, pointerOffsetExpr.position)) + smallExpr.addRpnNode(rightmostOperand) + smallExpr.addRpnNode(rightmostOperator) + smallExpr.parent = pointerOffsetExpr.parent + val result = pointerViaIndexRegisterPossible(smallExpr) + require(result != null) + return result + } + } + return null // expression is too complex } val (leftNode, oper, rightNode) = pointerOffsetExpr.finalOperation() operator=oper.operator @@ -2910,9 +2931,7 @@ $repeatLabel lda $counterVar } is PtRpn -> { val addrExpr = expr.address as PtRpn - if(addrExpr.children.size>3) - println("TODO: RPN: too complicated translateDirectMemReadExpressionToRegAorStack") // TODO RPN: split expression? - if(addrExpr.children.size==3 && tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { + if(tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { if(pushResultOnEstack) out(" sta P8ESTACK_LO,x | dex") } else { diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 4d7a675cf..32dd83182 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -146,9 +146,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } is PtRpn -> { val addrExpr = value.address as PtRpn - if(addrExpr.children.size>3) - println("TODO: RPN: too complex translateNormalAssignment") // TODO RPN: split expression? - if(addrExpr.children.size==3 && asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { + if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { assignRegisterByte(assign.target, CpuRegister.A) } else { assignViaExprEval(value.address) @@ -926,10 +924,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } is PtRpn -> { val addrExpr = value.address as PtRpn - if(addrExpr.children.size>3) { - println("TODO: RPN: too complex assignTypeCastedValue") // TODO RPN : split expression? - } - if(addrExpr.children.size==3 && asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { + if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { asmgen.out(" ldy #0") assignRegisterpairWord(target, RegisterOrPair.AY) } else { @@ -2859,9 +2854,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, asmgen.storeAIntoPointerVar(addressExpr) } addressExpr is PtRpn -> { - if(addressExpr.children.size>3) - println("TODO: RPN: too complex storeRegisterAInMemoryAddress $memoryAddress") // TODO RPN: split expression? - if(addressExpr.children.size!=3 || !asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.finalOperator().operator, true)) + if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.finalOperator().operator, true)) storeViaExprEval() } addressExpr is PtBinaryExpression -> { diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/RpnExpressionAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/RpnExpressionAsmGen.kt index 6433e27c5..a93c73706 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/RpnExpressionAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/RpnExpressionAsmGen.kt @@ -13,7 +13,7 @@ internal class RpnExpressionAsmGen( fun attemptAssignOptimizedExpr(assign: AsmAssignment): Boolean { val value = assign.source.expression as PtRpn - println("TODO: RPN: optimized assignment ${value.position}") // TODO RPN: optimized assignment + println("TODO: RPN: optimized assignment ${value.position} maxdepth=${value.maxDepth()}") // TODO RPN: optimized assignment // NOTE: don't forgot to evaluate the rest of the RPN expr as well return false } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 5f95ca1fa..8dcf1d569 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,9 +1,9 @@ TODO ==== +BRANCH: Write some unit tests for the RPN. BRANCH: Fix the TODO RPN routines to be optimized assembly in RpnExpressionAsmGen.kt - -Implement RPN codegen for IR. +BRANCH: Implement RPN codegen for IR. For next minor release ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/examples/test.p8 b/examples/test.p8 index e75034c14..336aec8c3 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -8,17 +8,18 @@ main { sub start() { - test_stack.test() - uword xx=4000 - ubyte a - ubyte b - ubyte c - ubyte d + ubyte a=11 + ubyte b=22 + ubyte c=33 - cx16.r0 = peekw(xx+42) - ; TODO cx16.r0 = peekw(a+xx+b+c+d+) - ; TODO @(a+xx+b+c+d) = cx16.r0L +; cx16.r0 = peekw(xx+a+b+c) +; cx16.r1 = peekw(xx+a+b+c+42) +; pokew(xx+a+b+c, xx) +; pokew(xx+a+b+c+42, xx) + + if a and a & $40 == 0 + cx16.r0++ ; if cx16.r0L in "derp" { ; xx++ @@ -26,7 +27,6 @@ main { ; ; xx = xx+(3*func(xx)+xx*2*cx16.r0L) ; txt.print_uw(xx) - test_stack.test() } ; sub func(uword value) -> uword {