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 kotlin.io.path.Path
import kotlin.io.path.isRegularFile
import kotlin.math.log2
/**
@@ -773,19 +774,21 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
}
} else {
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) {
"+", "-" -> transformWithPointerArithmetic(srcExpr)
"-" -> transformWithPointerArithmetic(srcExpr) // '+' is handled above
in ComparisonOperators -> transformWithPointerComparison(srcExpr)
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
}
}
}
private fun transformWithPointerComparison(expr: BinaryExpression): PtBinaryExpression {
val leftDt = expr.left.inferType(program)
@@ -830,12 +833,21 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
return plus
} else {
// ptr + right * structSize
val total = PtBinaryExpression("*", DataType.UWORD, expr.position)
total.add(transformExpression(expr.right))
total.add(PtNumber(BaseDataType.UWORD, structSize.toDouble(), expr.position))
val offset: PtExpression
if(structSize in powersOfTwoInt) {
// 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)
plusorminus.add(transformExpression(expr.left))
plusorminus.add(total)
plusorminus.add(offset)
return plusorminus
}
}
@@ -863,12 +875,21 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
return plus
} else {
// ptr + left * structSize
val total = PtBinaryExpression("*", DataType.UWORD, expr.position)
total.add(transformExpression(expr.left))
total.add(PtNumber(BaseDataType.UWORD, structSize.toDouble(), expr.position))
val offset: PtExpression
if(structSize in powersOfTwoInt) {
// 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)
plusorminus.add(offset)
plusorminus.add(transformExpression(expr.right))
plusorminus.add(total)
return plusorminus
}
}

View File

@@ -574,6 +574,7 @@ data class AddressOf(var identifier: IdentifierReference?, var arrayIndex: Array
return null
}
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 {
if(identifier!=null) {
val type = identifier!!.inferType(program).getOrUndef()

View File

@@ -1,6 +1,10 @@
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
--------------------------

View File

@@ -1,92 +1,52 @@
%import textio
%option enable_floats
%import textio
%zeropage basicsafe
%option no_sysinit
main {
ubyte @shared thingIndex = 10
uword[20] @shared dummy
uword[10] @split curframesplit
uword[10] @nosplit curframe
uword p1, p2
float f
sub start() {
^^ubyte[4] array1
^^byte[4] array2
^^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)
classic()
; new()
}
sub error1(^^ubyte ptr) {
cx16.r0++
}
sub error2(^^byte ptr) {
cx16.r0++
}
sub error3(^^bool ptr) {
cx16.r0++
}
sub error4(^^word ptr) {
cx16.r0++
}
sub error5(^^uword ptr) {
cx16.r0++
}
sub error6(^^float ptr) {
cx16.r0++
}
sub error7(^^long ptr) {
cx16.r0++
}
sub error8(^^str ptr) {
cx16.r0++
sub classic() {
txt.print("float pointer+1: ")
txt.print_uwhex(&f, true)
txt.spc()
txt.print_uwhex(&f + 1, true)
txt.nl()
p1 = &curframesplit[thingIndex]
p2 = &curframe[thingIndex]
txt.print("&array (split): ")
txt.print_uwhex(&curframesplit, true)
txt.spc()
txt.print_uwhex(p1, true)
txt.spc()
txt.print_uw(p1 - &curframesplit)
txt.spc()
txt.print_uwhex(p1 + &curframesplit, true)
txt.nl()
txt.print("&array (normal): ")
txt.print_uwhex(&curframe, true)
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) {
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()
}
; 6502 data size: $0251
}