diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmOptimizer.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmOptimizer.kt index cb8f152b8..7a66e9263 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmOptimizer.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmOptimizer.kt @@ -113,9 +113,9 @@ private fun optimizeUselessStackByteWrites(linesByFour: List>>): List { - // optimize sequential assignments of the isSameAs value to various targets (bytes, words, floats) + // Optimize sequential assignments of the isSameAs value to various targets (bytes, words, floats) // the float one is the one that requires 2*7=14 lines of code to check... - // @todo a better place to do this is in the Compiler instead and transform the Ast, or the AsmGen, and never even create the inefficient asm in the first place... + // The better place to do this is in the Compiler instead and never create these types of assembly, but hey val mods = mutableListOf() for (lines in linesByFourteen) { diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt index 10fdd8b03..ba8ec5587 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt @@ -270,7 +270,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen // Everything else just evaluate via the stack. // (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here, // because the code here is the implementation of exactly that...) - // TODO FIX THIS... by using a temp var? so that it becomes augmentable assignment expression? + // TODO DON'T STACK-EVAL THIS... by using a temp var? so that it becomes augmentable assignment expression? asmgen.translateExpression(value) if (assign.target.datatype in WordDatatypes && assign.source.datatype in ByteDatatypes) asmgen.signExtendStackLsb(assign.source.datatype) diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt index 913764843..96bf60b25 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -301,8 +301,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } } - TargetStorageKind.REGISTER -> throw AssemblyError("missing codegen for reg in-place modification") - TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack in-place modification") + TargetStorageKind.REGISTER -> throw AssemblyError("no asm gen for reg in-place modification") + TargetStorageKind.STACK -> throw AssemblyError("no asm gen for stack in-place modification") } } @@ -1802,8 +1802,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, else -> throw AssemblyError("invalid reg dt for byte not") } } - TargetStorageKind.STACK -> TODO("missing codegen for byte stack not") - else -> throw AssemblyError("missing codegen for in-place not of ubyte ${target.kind}") + TargetStorageKind.STACK -> TODO("no asm gen for byte stack not") + else -> throw AssemblyError("no asm gen for in-place not of ubyte ${target.kind}") } } DataType.UWORD -> { @@ -1860,8 +1860,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } TargetStorageKind.MEMORY -> TODO("no asm gen for uword-memory not") - TargetStorageKind.STACK -> TODO("missing codegen for word stack not") - else -> throw AssemblyError("missing codegen for in-place not of uword for ${target.kind}") + TargetStorageKind.STACK -> TODO("no asm gen for word stack not") + else -> throw AssemblyError("no asm gen for in-place not of uword for ${target.kind}") } } else -> throw AssemblyError("boolean-not of invalid type") @@ -1911,8 +1911,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, else -> throw AssemblyError("invalid reg dt for byte invert") } } - TargetStorageKind.STACK -> TODO("missing codegen for byte stack invert") - else -> throw AssemblyError("missing codegen for in-place invert ubyte for ${target.kind}") + TargetStorageKind.STACK -> TODO("no asm gen for byte stack invert") + else -> throw AssemblyError("no asm gen for in-place invert ubyte for ${target.kind}") } } DataType.UWORD -> { @@ -1931,15 +1931,13 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, RegisterOrPair.AX -> asmgen.out(" pha | txa | eor #255 | tax | pla | eor #255") RegisterOrPair.AY -> asmgen.out(" pha | tya | eor #255 | tay | pla | eor #255") RegisterOrPair.XY -> asmgen.out(" txa | eor #255 | tax | tya | eor #255 | tay") - in Cx16VirtualRegisters -> { - TODO("codegen for cx16 word register invert") - } + in Cx16VirtualRegisters -> TODO("no asm gen for cx16 word register invert") else -> throw AssemblyError("invalid reg dt for word invert") } } TargetStorageKind.MEMORY -> TODO("no asm gen for uword-memory invert") - TargetStorageKind.STACK -> TODO("missing codegen for word stack invert") - else -> throw AssemblyError("missing codegen for in-place invert uword for ${target.kind}") + TargetStorageKind.STACK -> TODO("no asm gen for word stack invert") + else -> throw AssemblyError("no asm gen for in-place invert uword for ${target.kind}") } } else -> throw AssemblyError("invert of invalid type") @@ -1966,8 +1964,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } TargetStorageKind.MEMORY -> TODO("can't in-place negate memory ubyte") - TargetStorageKind.STACK -> TODO("missing codegen for byte stack negate") - else -> throw AssemblyError("missing codegen for in-place negate byte array") + TargetStorageKind.STACK -> TODO("no asm gen for byte stack negate") + else -> throw AssemblyError("no asm gen for in-place negate byte array") } } DataType.WORD -> { @@ -2022,15 +2020,13 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sbc P8ZP_SCRATCH_REG+1 tay""") } - in Cx16VirtualRegisters -> { - TODO("codegen for cx16 word register negate") - } + in Cx16VirtualRegisters -> TODO("no asm gen for cx16 word register negate") else -> throw AssemblyError("invalid reg dt for word neg") } } TargetStorageKind.MEMORY -> TODO("no asm gen for word memory negate") - TargetStorageKind.STACK -> TODO("missing codegen for word stack negate") - else -> throw AssemblyError("missing codegen for in-place negate word array") + TargetStorageKind.STACK -> TODO("no asm gen for word stack negate") + else -> throw AssemblyError("no asm gen for in-place negate word array") } } DataType.FLOAT -> { @@ -2043,9 +2039,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sta ${target.asmVarname}+1 """) } - TargetStorageKind.REGISTER -> TODO("missing codegen for float reg negate") - TargetStorageKind.MEMORY -> TODO("missing codegen for float memory negate") - TargetStorageKind.STACK -> TODO("missing codegen for stack float negate") + TargetStorageKind.REGISTER -> TODO("no asm gen for float reg negate") + TargetStorageKind.MEMORY -> TODO("no asm gen for float memory negate") + TargetStorageKind.STACK -> TODO("no asm gen for stack float negate") else -> throw AssemblyError("weird target kind for inplace negate float ${target.kind}") } } diff --git a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt index 764704bf4..832a7a099 100644 --- a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt +++ b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt @@ -19,12 +19,16 @@ import kotlin.math.pow Investigate what optimizations binaryen has, also see https://egorbo.com/peephole-optimizations.html +some of these may already be present: + *(&X) => X X % 1 => 0 X / 1 => X X ^ -1 => ~x X >= 1 => X > 0 X < 1 => X <= 0 + +and some const foldings (that may already be done as well): X + ะก1 == C2 => X == C2 - C1 ((X + C1) + C2) => (X + (C1 + C2)) ((X + C1) + (Y + C2)) => ((X + Y) + (C1 + C2)) diff --git a/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt b/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt index 73ca802e4..04f0689ac 100644 --- a/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt +++ b/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt @@ -124,7 +124,6 @@ class UnusedCodeRemover(private val program: Program, it.isInRegularRAMof(compTarget.machine) } if(assignTargets.size==usages.size) { - // TODO FIX THAT A MEMREAD OF THE VARIABLE ISN'T RECOGNISED AS A USE (imageviewer iff_module.p8 pixptr) errors.warn("removing unused variable '${decl.name}'", decl.position) val assignmentsToRemove = assignTargets.map { it.parent to it.parent.parent as IStatementContainer}.toSet() return assignmentsToRemove.map { diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 2a0b7529f..0d2d99f88 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -261,6 +261,7 @@ private fun processAst(program: Program, errors: IErrorReporter, compilerOptions // TODO: turning char literals into UBYTEs via an encoding should really happen in code gen - but for that we'd need DataType.CHAR // ...but what do we gain from this? We can leave it as it is now: where a char literal is no more than syntactic sugar for an UBYTE value. // By introduction a CHAR dt, we will also lose the opportunity to do constant-folding on any expression containing a char literal. + // Yes this is different from strings that are only encoded in the code gen phase. program.charLiteralsToUByteLiterals(compilerOptions.compTarget) program.constantFold(errors, compilerOptions.compTarget) errors.report() diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 716420f6d..5e716ada7 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -21,6 +21,7 @@ Future - while-expression should now also get the simplifyConditionalExpression() treatment - fix the asm-labels problem (github issue #62) - find a way to optimize asm-subroutine param passing where it now sometimes uses the evalstack? +- find a way to let registerArgsViaStackEvaluation not use the stack anymore - document the various compiler command line options in more detail. See "Compiling program code" in the docs - get rid of all TODO's in the code - improve testability further, add more tests