fix &x +/- offset pointer arithmetic expression

This commit is contained in:
Irmen de Jong
2025-07-06 23:56:14 +02:00
parent 9a9bf170c6
commit f9fbfe30e3
4 changed files with 82 additions and 96 deletions

View File

@@ -17,6 +17,7 @@ import prog8.compiler.builtinFunctionReturnType
import java.io.File import java.io.File
import kotlin.io.path.Path import kotlin.io.path.Path
import kotlin.io.path.isRegularFile import kotlin.io.path.isRegularFile
import kotlin.math.log2
/** /**
@@ -773,17 +774,19 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
} }
} else { } else {
if(srcExpr.left.inferType(program).isPointer || srcExpr.right.inferType(program).isPointer) { if(srcExpr.left.inferType(program).isPointer || srcExpr.right.inferType(program).isPointer) {
if (srcExpr.operator == "+") return transformWithPointerArithmetic(srcExpr)
else if (srcExpr.operator in ComparisonOperators) return transformWithPointerComparison(srcExpr)
} else if(srcExpr.left.inferType(program).isPointer) {
return when (srcExpr.operator) { return when (srcExpr.operator) {
"+", "-" -> transformWithPointerArithmetic(srcExpr) "-" -> transformWithPointerArithmetic(srcExpr) // '+' is handled above
in ComparisonOperators -> transformWithPointerComparison(srcExpr) in ComparisonOperators -> transformWithPointerComparison(srcExpr)
else -> throw FatalAstException("unsupported operator on pointer: ${srcExpr.operator} at ${srcExpr.position}") else -> throw FatalAstException("unsupported operator on pointer: ${srcExpr.operator} at ${srcExpr.position}")
} }
} else {
val expr = PtBinaryExpression(srcExpr.operator, type, srcExpr.position)
expr.add(transformExpression(srcExpr.left))
expr.add(transformExpression(srcExpr.right))
return expr
} }
val expr = PtBinaryExpression(srcExpr.operator, type, srcExpr.position)
expr.add(transformExpression(srcExpr.left))
expr.add(transformExpression(srcExpr.right))
return expr
} }
} }
@@ -830,12 +833,21 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
return plus return plus
} else { } else {
// ptr + right * structSize // ptr + right * structSize
val total = PtBinaryExpression("*", DataType.UWORD, expr.position) val offset: PtExpression
total.add(transformExpression(expr.right)) if(structSize in powersOfTwoInt) {
total.add(PtNumber(BaseDataType.UWORD, structSize.toDouble(), expr.position)) // don't multiply simply shift
offset = PtBinaryExpression("<<", DataType.UWORD, expr.position)
offset.add(transformExpression(expr.right))
offset.add(PtNumber(BaseDataType.UWORD, log2(structSize.toDouble()), expr.position))
}
else {
offset = PtBinaryExpression("*", DataType.UWORD, expr.position)
offset.add(transformExpression(expr.right))
offset.add(PtNumber(BaseDataType.UWORD, structSize.toDouble(), expr.position))
}
val plusorminus = PtBinaryExpression(operator, resultDt, expr.position) val plusorminus = PtBinaryExpression(operator, resultDt, expr.position)
plusorminus.add(transformExpression(expr.left)) plusorminus.add(transformExpression(expr.left))
plusorminus.add(total) plusorminus.add(offset)
return plusorminus return plusorminus
} }
} }
@@ -863,12 +875,21 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
return plus return plus
} else { } else {
// ptr + left * structSize // ptr + left * structSize
val total = PtBinaryExpression("*", DataType.UWORD, expr.position) val offset: PtExpression
total.add(transformExpression(expr.left)) if(structSize in powersOfTwoInt) {
total.add(PtNumber(BaseDataType.UWORD, structSize.toDouble(), expr.position)) // don't multiply simply shift
offset = PtBinaryExpression("<<", DataType.UWORD, expr.position)
offset.add(transformExpression(expr.left))
offset.add(PtNumber(BaseDataType.UWORD, log2(structSize.toDouble()), expr.position))
}
else {
offset = PtBinaryExpression("*", DataType.UWORD, expr.position)
offset.add(transformExpression(expr.left))
offset.add(PtNumber(BaseDataType.UWORD, structSize.toDouble(), expr.position))
}
val plusorminus = PtBinaryExpression(operator, resultDt, expr.position) val plusorminus = PtBinaryExpression(operator, resultDt, expr.position)
plusorminus.add(offset)
plusorminus.add(transformExpression(expr.right)) plusorminus.add(transformExpression(expr.right))
plusorminus.add(total)
return plusorminus return plusorminus
} }
} }

View File

@@ -574,6 +574,7 @@ data class AddressOf(var identifier: IdentifierReference?, var arrayIndex: Array
return null return null
} }
override fun referencesIdentifier(nameInSource: List<String>) = identifier?.nameInSource==nameInSource || arrayIndex?.referencesIdentifier(nameInSource)==true || dereference?.referencesIdentifier(nameInSource)==true override fun referencesIdentifier(nameInSource: List<String>) = identifier?.nameInSource==nameInSource || arrayIndex?.referencesIdentifier(nameInSource)==true || dereference?.referencesIdentifier(nameInSource)==true
// override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(BaseDataType.UWORD) // TODO orignal behavior
override fun inferType(program: Program): InferredTypes.InferredType { override fun inferType(program: Program): InferredTypes.InferredType {
if(identifier!=null) { if(identifier!=null) {
val type = identifier!!.inferType(program).getOrUndef() val type = identifier!!.inferType(program).getOrUndef()

View File

@@ -1,6 +1,10 @@
TODO TODO
==== ====
What to do with the changed adress-of behavior? &x now returns a typed pointer to &x + 10 will now be calculated differently (C pointer arithmetic semantics rather than simply byte addition)
compiler flag to select old behavior? new operator that has the new behavior? Don't want to break existing code that used &....
Old behavior can be put back by always returning UWORD as the inferred type for AddressOf nodes
STRUCTS and TYPED POINTERS STRUCTS and TYPED POINTERS
-------------------------- --------------------------

View File

@@ -1,92 +1,52 @@
%import textio
%option enable_floats %option enable_floats
%import textio
%zeropage basicsafe
%option no_sysinit
main { main {
ubyte @shared thingIndex = 10
uword[20] @shared dummy
uword[10] @split curframesplit
uword[10] @nosplit curframe
uword p1, p2
float f
sub start() { sub start() {
^^ubyte[4] array1 classic()
^^byte[4] array2 ; new()
^^bool[4] array3
^^word[4] array4
^^uword[4] array5
^^float[4] array6
^^long[4] array7
^^str[4] array8
error1(array1)
error2(array2)
error3(array3)
error4(array4)
error5(array5)
error6(array6)
error7(array7)
error8(array8)
ok1(array1)
ok2(array2)
ok3(array3)
ok4(array4)
ok5(array5)
ok6(array6)
ok7(array7)
ok8(array8)
} }
sub error1(^^ubyte ptr) { sub classic() {
cx16.r0++ txt.print("float pointer+1: ")
} txt.print_uwhex(&f, true)
sub error2(^^byte ptr) { txt.spc()
cx16.r0++ txt.print_uwhex(&f + 1, true)
} txt.nl()
sub error3(^^bool ptr) {
cx16.r0++ p1 = &curframesplit[thingIndex]
} p2 = &curframe[thingIndex]
sub error4(^^word ptr) {
cx16.r0++ txt.print("&array (split): ")
} txt.print_uwhex(&curframesplit, true)
sub error5(^^uword ptr) { txt.spc()
cx16.r0++ txt.print_uwhex(p1, true)
} txt.spc()
sub error6(^^float ptr) { txt.print_uw(p1 - &curframesplit)
cx16.r0++ txt.spc()
} txt.print_uwhex(p1 + &curframesplit, true)
sub error7(^^long ptr) { txt.nl()
cx16.r0++
} txt.print("&array (normal): ")
sub error8(^^str ptr) { txt.print_uwhex(&curframe, true)
cx16.r0++ txt.spc()
txt.print_uwhex(p2, true)
txt.spc()
txt.print_uw(p2 - &curframe)
txt.spc()
txt.print_uwhex(p2 + &curframe, true)
txt.nl()
} }
sub ok1(^^ubyte[] ptr) { ; 6502 data size: $0251
txt.print_uw(ptr)
txt.nl()
}
sub ok2(^^byte[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok3(^^bool[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok4(^^word[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok5(^^uword[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok6(^^float[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok7(^^long[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok8(^^str[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
} }