From 9502a6f59014dec173cfc19d9413b39e707d6f08 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 13 Mar 2026 21:49:55 +0100 Subject: [PATCH] fix invalid augmented assignment optimization, and a call to pop() that crashed a symbol prefix test because the call wasn't defined as a builtin --- .../compiler/astprocessing/CodeDesugarer.kt | 22 +++++++++++-------- .../prog8/compiler/astprocessing/Utility.kt | 2 +- docs/source/todo.rst | 3 --- examples/test.p8 | 11 ++++++++-- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt index 8da2f641f..44f4a3ca5 100644 --- a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt +++ b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt @@ -946,21 +946,25 @@ _after: // consolidates simple assignment followed by augmented assignment into a single combined assignment. // a = simplevalue | a += expression --> a = simplevalue + expression (for all augmented operators) // NOTE: this is NOT SAFE to do when dealing with pointer arithmetic because the semantics of the combined expression is different! + // NOTE: this is also NOT SAFE when the augmented assignment's RHS references the target variable (e.g., a = b; a *= a) if(!assignment.isAugmentable && assignment.value.isSimple) { val next = assignment.nextSibling() as? Assignment if(next?.isAugmentable==true && next.value is BinaryExpression && next.target.isSameAs(assignment.target, program)) { val combined = next.value as BinaryExpression if(combined.left isSameAs assignment.target) { - if(!assignment.target.inferType(program).isPointer && (assignment.value.inferType(program).isPointer || combined.right.inferType(program).isPointer)) { - // avoid pointer arithmetic: a = (simplevalue as uword) + expression - combined.left = TypecastExpression(assignment.value, DataType.UWORD, true, combined.left.position) - } else { - // no pointer arithmetic done, just transform it into a = simplevalue + expression - combined.left = assignment.value + // Check if RHS also references the target variable - if so, can't optimize + if(!(combined.right isSameAs assignment.target)) { + if(!assignment.target.inferType(program).isPointer && (assignment.value.inferType(program).isPointer || combined.right.inferType(program).isPointer)) { + // avoid pointer arithmetic: a = (simplevalue as uword) + expression + combined.left = TypecastExpression(assignment.value, DataType.UWORD, true, combined.left.position) + } else { + // no pointer arithmetic done, just transform it into a = simplevalue + expression + combined.left = assignment.value + } + assignment.value = combined + combined.linkParents(assignment) + return listOf(IAstModification.Remove(next, parent as IStatementContainer)) } - assignment.value = combined - combined.linkParents(assignment) - return listOf(IAstModification.Remove(next, parent as IStatementContainer)) } } } diff --git a/compiler/src/prog8/compiler/astprocessing/Utility.kt b/compiler/src/prog8/compiler/astprocessing/Utility.kt index 05ab6788d..07df84bb9 100644 --- a/compiler/src/prog8/compiler/astprocessing/Utility.kt +++ b/compiler/src/prog8/compiler/astprocessing/Utility.kt @@ -50,7 +50,7 @@ internal fun makePushPopFunctionCalls(value: PtExpression): Pair