fix RPN issues

This commit is contained in:
Irmen de Jong 2023-03-19 17:35:21 +01:00
parent df2d7d4734
commit a819b4a5a5
5 changed files with 61 additions and 34 deletions

View File

@ -1175,12 +1175,15 @@ $repeatLabel lda $counterVar
} }
private fun translateCompareAndJumpIfTrueRPN(expr: PtRpn, jump: PtJump) { private fun translateCompareAndJumpIfTrueRPN(expr: PtRpn, jump: PtJump) {
val (left, oper, right) = expr.finalOperation() val (leftRpn, oper, right) = expr.finalOperation()
if(oper.operator !in ComparisonOperators) if(oper.operator !in ComparisonOperators)
throw AssemblyError("must be comparison expression") throw AssemblyError("must be comparison expression")
if(expr.children.size>3) { val left: PtExpression = if(expr.children.size>3 || leftRpn !is PtExpression) {
TODO("RPN comparison too complex ${expr.position} - split off the comparison + compare value") expr.children.removeLast()
} expr.children.removeLast()
expr
} else
leftRpn
// invert the comparison, so we can reuse the JumpIfFalse code generation routines // invert the comparison, so we can reuse the JumpIfFalse code generation routines
val invertedComparisonOperator = invertedComparisonOperator(oper.operator) val invertedComparisonOperator = invertedComparisonOperator(oper.operator)
@ -1194,23 +1197,25 @@ $repeatLabel lda $counterVar
} }
val rightConstVal = right as? PtNumber val rightConstVal = right as? PtNumber
if (rightConstVal!=null && rightConstVal.number == 0.0) { if (rightConstVal!=null && rightConstVal.number == 0.0) {
require(left is PtExpression)
testZeroAndJump(left, invertedComparisonOperator, label) testZeroAndJump(left, invertedComparisonOperator, label)
} }
else { else {
require(left is PtExpression && right is PtExpression) require(right is PtExpression)
val leftConstVal = left as? PtNumber val leftConstVal = left as? PtNumber
testNonzeroComparisonAndJump(left, invertedComparisonOperator, right, label, leftConstVal, rightConstVal) testNonzeroComparisonAndJump(left, invertedComparisonOperator, right, label, leftConstVal, rightConstVal)
} }
} }
private fun translateCompareAndJumpIfFalseRPN(expr: PtRpn, jumpIfFalseLabel: String) { private fun translateCompareAndJumpIfFalseRPN(expr: PtRpn, jumpIfFalseLabel: String) {
val (left, oper, right) = expr.finalOperation() val (leftRpn, oper, right) = expr.finalOperation()
if(expr.children.size>3) { val left: PtExpression = if(expr.children.size>3 || leftRpn !is PtExpression) {
TODO("RPN comparison too complex ${expr.position} - split off the comparison + compare value") expr.children.removeLast()
} expr.children.removeLast()
expr
} else
leftRpn
require(left is PtExpression && right is PtExpression) require(right is PtExpression)
val leftConstVal = left as? PtNumber val leftConstVal = left as? PtNumber
val rightConstVal = right as? PtNumber val rightConstVal = right as? PtNumber

View File

@ -202,12 +202,13 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
asmgen.signExtendVariableLsb("P8ZP_SCRATCH_W1", value.type) asmgen.signExtendVariableLsb("P8ZP_SCRATCH_W1", value.type)
asmgen.assignVariableToRegister("P8ZP_SCRATCH_W1", register, null, Position.DUMMY) asmgen.assignVariableToRegister("P8ZP_SCRATCH_W1", register, null, Position.DUMMY)
} else { } else {
val scope = value.definingISub()
val target: AsmAssignTarget = val target: AsmAssignTarget =
if(parameter.value.type in ByteDatatypes && (register==RegisterOrPair.AX || register == RegisterOrPair.AY || register==RegisterOrPair.XY || register in Cx16VirtualRegisters)) if(parameter.value.type in ByteDatatypes && (register==RegisterOrPair.AX || register == RegisterOrPair.AY || register==RegisterOrPair.XY || register in Cx16VirtualRegisters))
AsmAssignTarget(TargetStorageKind.REGISTER, asmgen, parameter.value.type, sub, value.position, register = register) AsmAssignTarget(TargetStorageKind.REGISTER, asmgen, parameter.value.type, scope, value.position, register = register)
else { else {
val signed = parameter.value.type == DataType.BYTE || parameter.value.type == DataType.WORD val signed = parameter.value.type == DataType.BYTE || parameter.value.type == DataType.WORD
AsmAssignTarget.fromRegisters(register, signed, value.position, sub, asmgen) AsmAssignTarget.fromRegisters(register, signed, value.position, scope, asmgen)
} }
val src = if(value.type in PassByReferenceDatatypes) { val src = if(value.type in PassByReferenceDatatypes) {
if(value is PtIdentifier) { if(value is PtIdentifier) {
@ -221,7 +222,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
} else { } else {
AsmAssignSource.fromAstSource(value, program, asmgen).adjustSignedUnsigned(target) AsmAssignSource.fromAstSource(value, program, asmgen).adjustSignedUnsigned(target)
} }
asmgen.translateNormalAssignment(AsmAssignment(src, target, program.memsizer, Position.DUMMY), sub) asmgen.translateNormalAssignment(AsmAssignment(src, target, program.memsizer, Position.DUMMY), scope)
} }
} }
} }

View File

@ -359,13 +359,18 @@ internal class ProgramAndVarsGen(
asmgen.out("; variables") asmgen.out("; variables")
val asmGenInfo = asmgen.subroutineExtra(sub) val asmGenInfo = asmgen.subroutineExtra(sub)
// TODO move these to BSS as well
for((dt, name, addr) in asmGenInfo.extraVars) { for((dt, name, addr) in asmGenInfo.extraVars) {
if(addr!=null) if(addr!=null)
asmgen.out("$name = $addr") asmgen.out("$name = $addr")
else when(dt) { else when(dt) {
DataType.UBYTE -> asmgen.out("$name .byte 0") DataType.UBYTE -> asmgen.out("$name .byte 0")
DataType.UWORD -> asmgen.out("$name .word 0") DataType.UWORD -> asmgen.out("$name .word 0")
else -> throw AssemblyError("weird dt") DataType.FLOAT -> {
require(options.compTarget.machine.FLOAT_MEM_SIZE==5)
asmgen.out("$name .byte 0,0,0,0,0")
}
else -> throw AssemblyError("weird dt for extravar $dt")
} }
} }
if(asmGenInfo.usedRegsaveA) // will probably never occur if(asmGenInfo.usedRegsaveA) // will probably never occur

View File

@ -366,8 +366,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
val value = assign.source.expression as PtRpn val value = assign.source.expression as PtRpn
val (left, oper, right) = value.finalOperation() val (left, oper, right) = value.finalOperation()
// TODO RPN the fallthrough if size>3 seems to generate very inefficient code... if(oper.operator in ComparisonOperators) {
if(value.children.size==3 && oper.operator in ComparisonOperators) {
assignRPNComparison(assign, value) assignRPNComparison(assign, value)
return true return true
} }
@ -416,7 +415,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
val dummyNode = PtVariable(name, varDt, ZeropageWish.DONTCARE, null, null, Position.DUMMY) val dummyNode = PtVariable(name, varDt, ZeropageWish.DONTCARE, null, null, Position.DUMMY)
dummyNode.parent = scope dummyNode.parent = scope
stScope.add(StStaticVariable(name, varDt, null, null, null, null, ZeropageWish.DONTCARE, dummyNode)) stScope.add(StStaticVariable(name, varDt, null, null, null, null, ZeropageWish.DONTCARE, dummyNode))
asmExtra.extraVars.add(Triple(dt, name, null)) asmExtra.extraVars.add(Triple(varDt, name, null))
} }
return name return name
} }
@ -431,12 +430,12 @@ internal class AssignmentAsmGen(private val program: PtProgram,
depth-=2 depth-=2
val resultVarname = evalVarName(it.type, depth) val resultVarname = evalVarName(it.type, depth)
depth++ depth++
require(resultVarname==leftvar)
symbolTable.resetCachedFlat() symbolTable.resetCachedFlat()
if(it.operator in ComparisonOperators) { if(it.operator in ComparisonOperators) {
require(it.type == DataType.UBYTE)
val scopeName = (scope as PtNamedNode).scopedName val scopeName = (scope as PtNamedNode).scopedName
val comparison = PtRpn(DataType.UBYTE, assign.position) val comparison = PtRpn(DataType.UBYTE, assign.position)
comparison.addRpnNode(PtIdentifier("$scopeName.$resultVarname", it.type, value.position)) comparison.addRpnNode(PtIdentifier("$scopeName.$leftvar", it.type, value.position))
comparison.addRpnNode(PtIdentifier("$scopeName.$rightvar", it.rightType, 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.addRpnNode(PtRpnOperator(it.operator, it.type, it.leftType, it.rightType, it.position))
comparison.parent = scope comparison.parent = scope
@ -445,8 +444,11 @@ internal class AssignmentAsmGen(private val program: PtProgram,
val normalAssign = AsmAssignment(src, target, program.memsizer, assign.position) val normalAssign = AsmAssignment(src, target, program.memsizer, assign.position)
assignRPNComparison(normalAssign, comparison) assignRPNComparison(normalAssign, comparison)
} else { } else {
val src = AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, DataType.UBYTE, variableAsmName = rightvar) require(resultVarname==leftvar) {
val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UBYTE, scope, assign.position, variableAsmName = resultVarname) "expected result $resultVarname == leftvar $leftvar"
}
val src = AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, it.rightType, variableAsmName = rightvar)
val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, it.type, scope, assign.position, variableAsmName = resultVarname)
val augAssign = AsmAugmentedAssignment(src, it.operator+"=", target, program.memsizer, assign.position) val augAssign = AsmAugmentedAssignment(src, it.operator+"=", target, program.memsizer, assign.position)
augmentableAsmGen.translate(augAssign, scope) augmentableAsmGen.translate(augAssign, scope)
} }
@ -534,7 +536,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
private fun assignRPNComparison(assign: AsmAssignment, comparison: PtRpn) { private fun assignRPNComparison(assign: AsmAssignment, comparison: PtRpn) {
val (left, oper, right) = comparison.finalOperation() val (leftRpn, oper, right) = comparison.finalOperation()
val constRight = (right as PtExpression).asConstInteger() val constRight = (right as PtExpression).asConstInteger()
if(constRight == 0) { if(constRight == 0) {
if(oper.operator == "==" || oper.operator == "!=") { if(oper.operator == "==" || oper.operator == "!=") {
@ -555,18 +557,19 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
} }
if(comparison.children.size>3) { val left: PtExpression = if(comparison.children.size>3 || leftRpn !is PtExpression) {
TODO("RPN comparison too complex ${comparison.position}") comparison.children.removeLast()
} comparison.children.removeLast()
comparison
} else
leftRpn
require(left is PtExpression)
val leftNum = left as? PtNumber val leftNum = left as? PtNumber
val rightNum = right as? PtNumber val rightNum = right as? PtNumber
val jumpIfFalseLabel = asmgen.makeLabel("cmp") val jumpIfFalseLabel = asmgen.makeLabel("cmp")
if(assign.target.isSameAs(left)) { if(assign.target.isSameAs(left)) {
// In-place comparison Target = Target <compare> Right // In-place comparison Target = Target <compare> Right
// NOTE : this generates pretty inefficient code.... TODO RPN optimize?
val targetDt = assign.target.datatype val targetDt = assign.target.datatype
val tempVar = asmgen.getTempVarName(assign.target.datatype) val tempVar = asmgen.getTempVarName(assign.target.datatype)
val tempTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, targetDt, comparison.definingISub(), comparison.position, variableAsmName = tempVar) val tempTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, targetDt, comparison.definingISub(), comparison.position, variableAsmName = tempVar)
@ -989,9 +992,13 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
private fun attemptAssignToByteCompareZeroRPN(expr: PtRpn, assign: AsmAssignment): Boolean { private fun attemptAssignToByteCompareZeroRPN(expr: PtRpn, assign: AsmAssignment): Boolean {
val (left, oper, right) = expr.finalOperation() val (leftRpn, oper, right) = expr.finalOperation()
if(expr.children.size!=3 || left !is PtExpression) val left = if(expr.children.size!=3 || leftRpn !is PtExpression) {
return false expr.children.removeLast()
expr.children.removeLast()
expr
} else
leftRpn
when (oper.operator) { when (oper.operator) {
"==" -> { "==" -> {
when(val dt = left.type) { when(val dt = left.type) {

View File

@ -1,9 +1,18 @@
TODO TODO
==== ====
RPN: examples/line-circle-txt crashes
RPN: examples/turtlegfx crashes
RPN: examples/maze crashes
RPN: examples/bsieve,charset compilation crash (bit shift expression)
RPN: cube3d-float is massive and slow
RPN: mandelbrot is big, but seems faster
RPN: swirl is MUCH slower, wizzine is slower
BRANCH: Fix the TODO RPN routines to be optimized assembly in RpnExpressionAsmGen.kt RPN: Fix the TODO RPN routines to be optimized assembly in RpnExpressionAsmGen.kt
BRANCH: check BinExprSplitter disablement any effect for RPN? RPN: check BinExprSplitter disablement any effect for RPN?
BRANCH: Implement RPN codegen for IR. RPN: Implement RPN codegen for IR.
- Move asmExtra vars into BSS as well, now are .byte 0 allocated
For next minor release For next minor release