From 584be447431dbe9a6cf5a7f97b7ac8eb7f58fd80 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 11 Aug 2023 23:41:19 +0200 Subject: [PATCH] fix compiler error on float comparison expressions --- .../cpu6502/assignment/AssignmentAsmGen.kt | 114 +++++++++--------- compiler/test/comparisons/Makefile | 2 +- docs/source/todo.rst | 3 + 3 files changed, 62 insertions(+), 57 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index d3ad814bb..04f03001e 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -16,14 +16,16 @@ internal class AssignmentAsmGen(private val program: PtProgram, fun translate(assignment: PtAssignment) { val target = AsmAssignTarget.fromAstAssignment(assignment.target, assignment.definingISub(), asmgen) val source = AsmAssignSource.fromAstSource(assignment.value, program, asmgen).adjustSignedUnsigned(target) - val assign = AsmAssignment(source, target, program.memsizer, assignment.position) + val pos = if(assignment.position !== Position.DUMMY) assignment.position else if(assignment.target.position !== Position.DUMMY) assignment.target.position else assignment.value.position + val assign = AsmAssignment(source, target, program.memsizer, pos) translateNormalAssignment(assign, assignment.definingISub()) } fun translate(augmentedAssign: PtAugmentedAssign) { val target = AsmAssignTarget.fromAstAssignment(augmentedAssign.target, augmentedAssign.definingISub(), asmgen) val source = AsmAssignSource.fromAstSource(augmentedAssign.value, program, asmgen).adjustSignedUnsigned(target) - val assign = AsmAugmentedAssignment(source, augmentedAssign.operator, target, program.memsizer, augmentedAssign.position) + val pos = if(augmentedAssign.position !== Position.DUMMY) augmentedAssign.position else if(augmentedAssign.target.position !== Position.DUMMY) augmentedAssign.target.position else augmentedAssign.value.position + val assign = AsmAugmentedAssignment(source, augmentedAssign.operator, target, program.memsizer, pos) augmentableAsmGen.translate(assign, augmentedAssign.definingISub()) } @@ -369,7 +371,8 @@ internal class AssignmentAsmGen(private val program: PtProgram, is PtBinaryExpression -> { if(!attemptAssignOptimizedBinexpr(value, assign)) { // TOO BAD: the expression was too complex to translate into assembly. - throw AssemblyError("Expression is too complex to translate into assembly. Split it up into several separate statements, introduce a temporary variable, or otherwise rewrite it. Location: ${assign.position}") + val pos = if(value.position!==Position.DUMMY) value.position else assign.position + throw AssemblyError("Expression is too complex to translate into assembly. Split it up into several separate statements, introduce a temporary variable, or otherwise rewrite it. Location: $pos") } } else -> throw AssemblyError("weird assignment value type $value") @@ -410,66 +413,65 @@ internal class AssignmentAsmGen(private val program: PtProgram, } private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean { - if(expr.operator in ComparisonOperators) { - if(expr.right.asConstInteger() == 0) { - if(expr.operator == "==" || expr.operator=="!=") { - when(assign.target.datatype) { - in ByteDatatypes -> if(attemptAssignToByteCompareZero(expr, assign)) return true - else -> { - // do nothing, this is handled by a type cast. - } + val translatedOk = when (expr.operator) { + in ComparisonOperators -> optimizedComparison(expr, assign) + in setOf("&", "|", "^", "and", "or", "xor") -> optimizedLogicalOrBitwiseExpr(expr, assign.target) + "==", "!=" -> optimizedEqualityExpr(expr, assign.target) + "+", "-" -> optimizedPlusMinExpr(expr, assign.target) + "<<", ">>" -> optimizedBitshiftExpr(expr, assign.target) + "*" -> optimizedMultiplyExpr(expr, assign.target) + "/" -> optimizedDivideExpr(expr, assign.target) + "%" -> optimizedRemainderExpr(expr, assign.target) + else -> false + } + + return if(translatedOk) + true + else + anyExprGen.assignAnyExpressionUsingStack(expr, assign) + } + + private fun optimizedComparison(expr: PtBinaryExpression, assign: AsmAssignment): Boolean { + if(expr.right.asConstInteger() == 0) { + if(expr.operator == "==" || expr.operator=="!=") { + when(assign.target.datatype) { + in ByteDatatypes -> if(attemptAssignToByteCompareZero(expr, assign)) return true + else -> { + // do nothing, this is handled by a type cast. } } } - - if(expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) { - if(assignOptimizedComparisonBytes(expr, assign)) - return true - } else if(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) { - if(assignOptimizedComparisonWords(expr, assign)) - return true - } - - val origTarget = assign.target.origAstTarget - if(origTarget!=null) { - assignConstantByte(assign.target, 0) - val assignTrue = PtNodeGroup() - val assignment = PtAssignment(assign.position) - assignment.add(origTarget) - assignment.add(PtNumber.fromBoolean(true, assign.position)) - assignTrue.add(assignment) - val assignFalse = PtNodeGroup() - val ifelse = PtIfElse(assign.position) - val exprClone = PtBinaryExpression(expr.operator, expr.type, expr.position) - expr.children.forEach { exprClone.children.add(it) } // doesn't seem to need a deep clone - ifelse.add(exprClone) - ifelse.add(assignTrue) - ifelse.add(assignFalse) - ifelse.parent = expr.parent - asmgen.translate(ifelse) - return true - } } - if(expr.type !in IntegerDatatypes) - return anyExprGen.assignAnyExpressionUsingStack(expr, assign) + if(expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) { + if(assignOptimizedComparisonBytes(expr, assign)) + return true + } else if(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) { + if(assignOptimizedComparisonWords(expr, assign)) + return true + } - if(expr.operator in setOf("&", "|", "^", "and", "or", "xor")) - return optimizedLogicalOrBitwiseExpr(expr, assign.target) - if(expr.operator == "==" || expr.operator == "!=") - return optimizedEqualityExpr(expr, assign.target) - if(expr.operator=="+" || expr.operator=="-") - return optimizedPlusMinExpr(expr, assign.target) - if(expr.operator=="<<" || expr.operator==">>") - return optimizedBitshiftExpr(expr, assign.target) - if(expr.operator=="*") - return optimizedMultiplyExpr(expr, assign.target) - if(expr.operator=="/") - return optimizedDivideExpr(expr, assign.target) - if(expr.operator=="%") - return optimizedRemainderExpr(expr, assign.target) + val origTarget = assign.target.origAstTarget + if(origTarget!=null) { + assignConstantByte(assign.target, 0) + val assignTrue = PtNodeGroup() + val assignment = PtAssignment(assign.position) + assignment.add(origTarget) + assignment.add(PtNumber.fromBoolean(true, assign.position)) + assignTrue.add(assignment) + val assignFalse = PtNodeGroup() + val ifelse = PtIfElse(assign.position) + val exprClone = PtBinaryExpression(expr.operator, expr.type, expr.position) + expr.children.forEach { exprClone.children.add(it) } // doesn't seem to need a deep clone + ifelse.add(exprClone) + ifelse.add(assignTrue) + ifelse.add(assignFalse) + ifelse.parent = expr.parent + asmgen.translate(ifelse) + return true + } - return anyExprGen.assignAnyExpressionUsingStack(expr, assign) + return false } private fun optimizedRemainderExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean { diff --git a/compiler/test/comparisons/Makefile b/compiler/test/comparisons/Makefile index c30638e02..67445c4d8 100644 --- a/compiler/test/comparisons/Makefile +++ b/compiler/test/comparisons/Makefile @@ -9,7 +9,7 @@ test: clean generate test_prgs generate: python make_tests.py - p8compile -noopt -target cx16 *.p8 >/dev/null + p8compile -target cx16 *.p8 >/dev/null test_prgs: x16emu -run -prg more_compares.prg diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 65eec751a..6d9308cae 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,6 +1,9 @@ TODO ==== +- fix bug introduced by 017ef8a837077c339993004da9b4ccf5c8ca7b13 (> and/or <= change in AssignmentAsmGen byteLessEquals/byteGreater + Bug manifests in prog8 where 2nd row of aliens jerks too far to the right after a short while. + - [on branch:] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 .... - IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction - IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? etc), but only after setting the status bits is verified!