mirror of
https://github.com/irmen/prog8.git
synced 2025-11-03 19:16:13 +00:00
fix &x +/- offset pointer arithmetic expression
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
--------------------------
|
||||
|
||||
124
examples/test.p8
124
examples/test.p8
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user