diff --git a/codeCore/src/prog8/code/SymbolTable.kt b/codeCore/src/prog8/code/SymbolTable.kt index a2b6a6c69..8900eb341 100644 --- a/codeCore/src/prog8/code/SymbolTable.kt +++ b/codeCore/src/prog8/code/SymbolTable.kt @@ -33,9 +33,9 @@ class SymbolTable(astProgram: PtProgram) : StNode(astProgram.name, StNodeType.GL return result } -// fun resetCachedFlat() { -// cachedFlat = null -// } + fun resetCachedFlat() { + cachedFlat = null + } val allVariables: Collection by lazy { val vars = mutableListOf() diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index 1551df8f3..1ae9d4e42 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -1174,30 +1174,29 @@ $repeatLabel lda $counterVar private fun translateCompareAndJumpIfTrueRPN(expr: PtRpn, jump: PtJump) { val (left, oper, right) = expr.finalOperation() - if(expr.children.size>3) { - TODO("RPN comparison too complex ${expr.position}") - } - - require(left is PtExpression && right is PtExpression) - if(oper.operator !in ComparisonOperators) throw AssemblyError("must be comparison expression") + if(expr.children.size>3) { + TODO("RPN comparison too complex ${expr.position} - split off the comparison + compare value") + } // invert the comparison, so we can reuse the JumpIfFalse code generation routines val invertedComparisonOperator = invertedComparisonOperator(oper.operator) ?: throw AssemblyError("can't invert comparison $expr") - val rightConstVal = right as? PtNumber - val label = when { jump.generatedLabel!=null -> jump.generatedLabel!! jump.identifier!=null -> asmSymbolName(jump.identifier!!) jump.address!=null -> jump.address!!.toHex() else -> throw AssemblyError("weird jump") } - if (rightConstVal!=null && rightConstVal.number == 0.0) + val rightConstVal = right as? PtNumber + if (rightConstVal!=null && rightConstVal.number == 0.0) { + require(left is PtExpression) testZeroAndJump(left, invertedComparisonOperator, label) + } else { + require(left is PtExpression && right is PtExpression) val leftConstVal = left as? PtNumber testNonzeroComparisonAndJump(left, invertedComparisonOperator, right, label, leftConstVal, rightConstVal) } @@ -1206,7 +1205,7 @@ $repeatLabel lda $counterVar private fun translateCompareAndJumpIfFalseRPN(expr: PtRpn, jumpIfFalseLabel: String) { val (left, oper, right) = expr.finalOperation() if(expr.children.size>3) { - TODO("RPN comparison too complex ${expr.position}") + TODO("RPN comparison too complex ${expr.position} - split off the comparison + compare value") } require(left is PtExpression && right is PtExpression) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 045b08ef1..6f0b9d21f 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -365,7 +365,9 @@ internal class AssignmentAsmGen(private val program: PtProgram, private fun attemptAssignOptimizedExprRPN(assign: AsmAssignment, scope: IPtSubroutine): Boolean { val value = assign.source.expression as PtRpn val (left, oper, right) = value.finalOperation() - if(oper.operator in ComparisonOperators) { + + // TODO RPN the fallthrough if size>3 seems to generate not 100% correct code... (balls example fills the screen weird) + if(value.children.size==3 && oper.operator in ComparisonOperators) { assignRPNComparison(assign, value) return true } @@ -424,19 +426,18 @@ internal class AssignmentAsmGen(private val program: PtProgram, value.children.forEach { when (it) { is PtRpnOperator -> { - val varDt = getVarDt(it.type) - val rightvar = evalVars.getValue(varDt).pop() - val leftvar = evalVars.getValue(varDt).pop() + val rightvar = evalVars.getValue(getVarDt(it.rightType)).pop() + val leftvar = evalVars.getValue(getVarDt(it.leftType)).pop() depth-=2 val resultVarname = evalVarName(it.type, depth) depth++ require(resultVarname==leftvar) - // TODO no longer needed? symbolTable.resetCachedFlat() + symbolTable.resetCachedFlat() if(it.operator in ComparisonOperators) { val scopeName = (scope as PtNamedNode).scopedName val comparison = PtRpn(DataType.UBYTE, assign.position) comparison.addRpnNode(PtIdentifier("$scopeName.$resultVarname", it.type, value.position)) - comparison.addRpnNode(PtIdentifier("$scopeName.$rightvar", it.type, value.position)) + comparison.addRpnNode(PtIdentifier("$scopeName.$rightvar", it.rightType, value.position)) comparison.addRpnNode(PtRpnOperator(it.operator, it.type, it.leftType, it.rightType, it.position)) comparison.parent = scope val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UBYTE, expression = comparison) @@ -577,7 +578,6 @@ internal class AssignmentAsmGen(private val program: PtProgram, else -> throw AssemblyError("invalid dt") } asmgen.out(jumpIfFalseLabel) - asmgen.out("; cmp done") } private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 260feb810..43caa9ad1 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,10 +1,12 @@ TODO ==== +BRANCH: balls.p8 directions are wrong since the comparison operator fallthrough in attemptAssignOptimizedExprRPN BRANCH: Fix the TODO RPN routines to be optimized assembly in RpnExpressionAsmGen.kt BRANCH: check BinExprSplitter disablement any effect for RPN? BRANCH: Implement RPN codegen for IR. + For next minor release ^^^^^^^^^^^^^^^^^^^^^^ ... diff --git a/examples/test.p8 b/examples/test.p8 index 54dbcf0c9..06f840700 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,12 +6,15 @@ main { sub start() { - ubyte[255] BC - bool[255] DX +; ubyte[255] BC +; bool[255] DX - BC[2] = math.rnd() & 15 - BC[3] = math.rnd() & 15 - BC[4] = math.rnd() & 15 + if math.rnd() & 22 { + cx16.r0L++ + } +; BC[2] = math.rnd() & 15 +; BC[3] = math.rnd() & 15 +; BC[4] = math.rnd() & 15 ;DX[2] = math.rnd() & 1 } }