diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt index 251da837e..5eade9bd1 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt @@ -1840,7 +1840,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } TargetStorageKind.STACK -> TODO("no asm gen for byte stack invert") - else -> throw AssemblyError("no asm gen for in-place invert ubyte for ${target.kind}") + else -> TODO("no asm gen for in-place invert ubyte for ${target.kind}") } } DataType.UWORD -> { @@ -1864,7 +1864,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } 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 -> TODO("no asm gen for in-place invert uword for ${target.kind}") } } else -> throw AssemblyError("invert of invalid type") @@ -1898,7 +1898,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } TargetStorageKind.MEMORY -> throw AssemblyError("memory is ubyte, can't in-place negate") TargetStorageKind.STACK -> TODO("no asm gen for byte stack negate") - else -> throw AssemblyError("no asm gen for in-place negate byte") + else -> TODO("no asm gen for in-place negate byte") } } DataType.WORD -> { @@ -1956,7 +1956,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } TargetStorageKind.STACK -> TODO("no asm gen for word stack negate") - else -> throw AssemblyError("no asm gen for in-place negate word") + else -> TODO("no asm gen for in-place negate word") } } DataType.FLOAT -> { @@ -1970,7 +1970,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, """) } TargetStorageKind.STACK -> TODO("no asm gen for float stack negate") - else -> throw AssemblyError("weird target kind for inplace negate float ${target.kind}") + else -> TODO("no asmgen for inplace negate float ${target.kind}") } } else -> throw AssemblyError("negate of invalid type $dt") diff --git a/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt b/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt index c95cc3fec..69dd0f47d 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt @@ -16,11 +16,35 @@ import prog8.code.target.VMTarget internal class AstOnetimeTransforms(private val program: Program, private val options: CompilationOptions) : AstWalker() { + override fun after(assignment: Assignment, parent: Node): Iterable { + if(options.compTarget.name != VMTarget.NAME) { + // The 6502 code-gen doesn't contain code to deal with arr[0] = -arr[0] and arr[0] = ~arr[0]. + // Replace this by assignment, operation, assignment. + // TODO make the codegen better so this work around can be removed + +// if (assignment.isAugmentable) { +// val arrayIdx = assignment.target.arrayindexed +// if (arrayIdx != null) { +// val prefixed = assignment.value as? PrefixExpression +// if (prefixed != null) { +// println("array self-assignment, operator = ${prefixed.operator}") +// if (prefixed.operator == "-") { +// TODO("array in-place -") +// } else if (prefixed.operator == "~") { +// TODO("array in-place ~") +// } +// } +// } +// } + + } + return noModifications + } + override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable { if(parent !is VarDecl) { - // TODO move this / remove this, and make the codegen better instead. - // If the expression is pointervar[idx] where pointervar is uword and not a real array, - // replace it by a @(pointervar+idx) expression. + if(options.compTarget.name == VMTarget.NAME) + return noModifications // vm codegen deals correctly with all cases // Don't replace the initializer value in a vardecl - this will be moved to a separate // assignment statement soon in after(VarDecl) return replacePointerVarIndexWithMemreadOrMemwrite(arrayIndexedExpression, parent) @@ -29,15 +53,16 @@ internal class AstOnetimeTransforms(private val program: Program, private val op } private fun replacePointerVarIndexWithMemreadOrMemwrite(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable { - if(options.compTarget.name==VMTarget.NAME) - return noModifications // vm codegen deals correctly with all cases - + // note: The CodeDesugarer already does something similar, but that is meant ONLY to take + // into account the case where the index value is a word type. + // The replacement here is to fix missing cases in the 6502 codegen. + // TODO make the 6502 codegen better so this work around can be removed val arrayVar = arrayIndexedExpression.arrayvar.targetVarDecl(program) if(arrayVar!=null && arrayVar.datatype == DataType.UWORD) { if(parent is AssignTarget) { val assignment = parent.parent as? Assignment if(assignment?.value is NumericLiteral || assignment?.value is IdentifierReference) { - // ONLY for a constant assignment, or direct variable assignment, the codegen contains correct optimized code. + // the codegen contains correct optimized code ONLY for a constant assignment, or direct variable assignment. return noModifications } // Other cases aren't covered correctly by the 6502 codegen, and there are a LOT of cases. diff --git a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt index a1ad5b372..c71ec5d1d 100644 --- a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt +++ b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt @@ -10,8 +10,7 @@ import prog8.code.core.IErrorReporter import prog8.code.core.Position -internal class CodeDesugarer(val program: Program, - private val errors: IErrorReporter) : AstWalker() { +internal class CodeDesugarer(val program: Program, private val errors: IErrorReporter) : AstWalker() { // Some more code shuffling to simplify the Ast that the codegenerator has to process. // Several changes have already been done by the StatementReorderer ! @@ -138,7 +137,8 @@ _after: } override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable { - // replace pointervar[word] by @(pointervar+word) + // replace pointervar[word] by @(pointervar+word) to avoid the + // "array indexing is limited to byte size 0..255" error for pointervariables. val indexExpr = arrayIndexedExpression.indexer.indexExpr val indexerDt = indexExpr.inferType(program) if(indexerDt.isWords) { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index d7637501c..9886dabbc 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,6 +3,12 @@ TODO For next release ^^^^^^^^^^^^^^^^ +- improve prefix expression codgen in AssignmentAsmGen.assignExpression(): + don't do this for complex assign targets such as array elements: "first assign the value to the target then apply the operator in place on the target." + this triggers foo[x] = -b to be a 2-step assignment with array in-place modification... + +- fix the array in place assignment issue, see AstOnetimeTransforms + - ir: asmsub contents remains blank in IR file ... diff --git a/examples/test.p8 b/examples/test.p8 index cef336627..daeb20cc6 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,45 +1,37 @@ -%import textio -%import math %import floats +%import textio %zeropage basicsafe main { + byte[10] foo + ubyte[10] foou + word[10] foow + uword[10] foowu + float[10] flt + byte d - sub printnumbers() { - txt.print_ub(math.rnd()) - txt.spc() - txt.print_ub(math.rnd()) - txt.spc() - txt.print_ub(math.rnd()) - txt.nl() - txt.print_uw(math.rndw()) - txt.spc() - txt.print_uw(math.rndw()) - txt.spc() - txt.print_uw(math.rndw()) - txt.nl() - floats.print_f(floats.rndf()) - txt.spc() - floats.print_f(floats.rndf()) - txt.spc() - floats.print_f(floats.rndf()) - txt.nl() - } + sub start() { + ; foo[0] = -d ; TODO fix codegen in assignExpression that splits this up + + uword pointer = $1000 + uword index + foou[1] = 42 + pointer[$40] = 24 + pointer[$40] = foou[1]+10 + txt.print_ub(@($1040)) + txt.nl() + pointer[index+$100] = foou[1] + pointer[index+$1000] = foou[1]+1 + txt.print_ub(@($1100)) + txt.nl() + txt.print_ub(@($2000)) + txt.nl() - sub start() { - txt.print("initial:\n") - math.rndseed($a55a, $7653) - floats.rndseedf(11,22,33) - printnumbers() - txt.print("\nsame seeds:\n") - math.rndseed($a55a, $7653) - floats.rndseedf(11,22,33) - printnumbers() - txt.print("\ndifferent seeds:\n") - math.rndseed($1234, $5678) - floats.rndseedf(44,55,66) - printnumbers() - txt.nl() - } +; foo[0] = -foo[0] +; foou[0] = ~foou[0] +; foow[0] = -foow[0] +; foowu[0] = ~foowu[0] +; flt[0] = -flt[0] ; TODO also fix crash when selecting vm target: fpReg1 out of bounds + } }