improved pointer[0]

This commit is contained in:
Irmen de Jong
2025-09-24 22:23:26 +02:00
parent 50fecbcebe
commit abeefb5655
5 changed files with 90 additions and 117 deletions

View File

@@ -492,17 +492,27 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
return noModifications return noModifications
} }
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> { override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
if(arrayIndexedExpression.indexer.constIndex()==0) { if(arrayIndexedExpression.indexer.constIndex()==0) {
if(arrayIndexedExpression.plainarrayvar!=null) { if(arrayIndexedExpression.plainarrayvar!=null) {
if((arrayIndexedExpression.parent as? BinaryExpression)?.operator !=".") { val binexprParent = arrayIndexedExpression.parent as? BinaryExpression
if(binexprParent?.operator!=".") {
val dt = arrayIndexedExpression.plainarrayvar!!.inferType(program).getOrUndef() val dt = arrayIndexedExpression.plainarrayvar!!.inferType(program).getOrUndef()
if(dt.isPointer) { if(dt.isPointer) {
// pointer[0] --> pointer^^ // pointer[0] --> pointer^^
val deref = PtrDereference(arrayIndexedExpression.plainarrayvar!!.nameInSource, true, arrayIndexedExpression.plainarrayvar!!.position) val deref = PtrDereference(arrayIndexedExpression.plainarrayvar!!.nameInSource, true, arrayIndexedExpression.plainarrayvar!!.position)
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression,deref, parent)) return listOf(IAstModification.ReplaceNode(arrayIndexedExpression,deref, parent))
} }
} else if(arrayIndexedExpression.pointerderef==null) {
// possibly pointer[0].field --> pointer.field
val target = arrayIndexedExpression.plainarrayvar!!.targetVarDecl()
if(target?.datatype?.isPointer==true) {
val field = (binexprParent.right as? IdentifierReference)?.nameInSource
if(field!=null) {
val deref = PtrDereference(arrayIndexedExpression.plainarrayvar!!.nameInSource + field, false, arrayIndexedExpression.plainarrayvar!!.position)
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression.parent, deref, arrayIndexedExpression.parent.parent))
}
}
} }
} }
val ptrDeref = arrayIndexedExpression.pointerderef val ptrDeref = arrayIndexedExpression.pointerderef

View File

@@ -384,4 +384,25 @@ internal class StatementReorderer(
) )
return listOf(IAstModification.ReplaceNode(assign, strcopy, assign.parent)) return listOf(IAstModification.ReplaceNode(assign, strcopy, assign.parent))
} }
override fun after(deref: ArrayIndexedPtrDereference, parent: Node): Iterable<IAstModification> {
if(parent is AssignTarget) {
val zeroIndexer = deref.chain.firstOrNull { it.second?.constIndex()==0 }
if(zeroIndexer!=null) {
val target = deref.definingScope.lookup(listOf(zeroIndexer.first))
if(target is VarDecl && target.datatype.isPointer) {
val position = deref.chain.indexOf(zeroIndexer)
val rest = deref.chain.drop(position + 1)
if (rest.size == 1 && rest[0].second == null) {
// pointer[0]^^.field = xxx --> pointer^^.field = xxx
val noindexer = zeroIndexer.first to null
val newchain = deref.chain.take(position) + noindexer + rest
val newDeref = PtrDereference(newchain.map { it.first }, false, deref.position)
return listOf(IAstModification.ReplaceNode(deref, newDeref, parent))
}
}
}
}
return noModifications
}
} }

View File

@@ -1027,118 +1027,6 @@ main {
st[8] shouldBe instanceOf<Assignment>() st[8] shouldBe instanceOf<Assignment>()
} }
test("indexing pointers with index 0 is just a direct pointer dereference except when followed by a struct field lookup") {
val src="""
%import floats
main {
struct List {
^^uword s
ubyte n
}
sub start() {
^^List l1 = ^^List : []
^^word @shared wptr
^^float @shared fptr
float f1,f2
cx16.r0 = l1.s^^
cx16.r1 = l1^^.s^^
cx16.r2 = l1.s^^
cx16.r3 = l1.s[0]
cx16.r4 = l1^^.s[0]
l1.s^^ = 4242
l1^^.s^^ = 4242
l1.s^^ = 4242
l1.s[0] = 4242
;; l1^^.s[0] = 4242 ; TODO fix parse syntax error
cx16.r0s = wptr[0]
cx16.r1s = wptr^^
wptr^^ = 4242
wptr[0] = 4242
f1 = fptr^^
f2 = fptr[0]
fptr^^ = 1.234
fptr[0] = 1.234
; not changed to dereference:
cx16.r0L = l1[0].n
cx16.r1L = l1[1].n
}
}"""
val result = compileText(VMTarget(), true, src, outputDir, writeAssembly = false)!!
val st = result.compilerAst.entrypoint.statements
st.size shouldBe 30
val dr0 = (st[10] as Assignment).value as PtrDereference
val dr1 = (st[11] as Assignment).value as PtrDereference
val dr2 = (st[12] as Assignment).value as PtrDereference
val dr3 = (st[13] as Assignment).value as PtrDereference
val dr4 = (st[14] as Assignment).value as PtrDereference
val dr5 = (st[15] as Assignment).target.pointerDereference!!
val dr6 = (st[16] as Assignment).target.pointerDereference!!
val dr7 = (st[17] as Assignment).target.pointerDereference!!
val dr8 = (st[18] as Assignment).target.pointerDereference!!
val dr9 = (st[19] as Assignment).value as FunctionCallExpression
val dr10 = (st[20] as Assignment).value as PtrDereference
val dr11 = (st[21] as Assignment).target.pointerDereference!!
(st[22] as FunctionCallStatement).target.nameInSource shouldBe listOf("pokew")
val dr13 = (st[23] as Assignment).value as PtrDereference
((st[24] as Assignment).value as FunctionCallExpression).target.nameInSource shouldBe listOf("peekf")
val dr15 = (st[25] as Assignment).target.pointerDereference!!
(st[26] as FunctionCallStatement).target.nameInSource shouldBe listOf("pokef")
dr0.chain shouldBe listOf("l1", "s")
dr0.derefLast shouldBe true
dr1.chain shouldBe listOf("l1", "s")
dr1.derefLast shouldBe true
dr2.chain shouldBe listOf("l1", "s")
dr2.derefLast shouldBe true
dr3.chain shouldBe listOf("l1", "s")
dr3.derefLast shouldBe true
dr4.chain shouldBe listOf("l1", "s")
dr4.derefLast shouldBe true
dr5.chain shouldBe listOf("l1", "s")
dr5.derefLast shouldBe true
dr6.chain shouldBe listOf("l1", "s")
dr6.derefLast shouldBe true
dr7.chain shouldBe listOf("l1", "s")
dr7.derefLast shouldBe true
dr8.chain shouldBe listOf("l1", "s")
dr8.derefLast shouldBe true
dr9.target.nameInSource shouldBe listOf("peekw")
dr10.chain shouldBe listOf("wptr")
dr10.derefLast shouldBe true
dr11.chain shouldBe listOf("wptr")
dr11.derefLast shouldBe true
dr13.chain shouldBe listOf("fptr")
dr13.derefLast shouldBe true
dr15.chain shouldBe listOf("fptr")
dr15.derefLast shouldBe true
val list0 = (st[27] as Assignment).value as BinaryExpression
val list1 = (st[28] as Assignment).value as BinaryExpression
list0.operator shouldBe "."
(list0.right as IdentifierReference).nameInSource shouldBe listOf("n")
val list0left = list0.left as ArrayIndexedExpression
list0left.plainarrayvar!!.nameInSource shouldBe listOf("l1")
list0left.indexer.constIndex() shouldBe 0
list1.operator shouldBe "."
(list1.right as IdentifierReference).nameInSource shouldBe listOf("n")
val list1left = list0.left as ArrayIndexedExpression
list1left.plainarrayvar!!.nameInSource shouldBe listOf("l1")
list1left.indexer.constIndex() shouldBe 0
}
test("indexing pointers to structs") { test("indexing pointers to structs") {
val src=""" val src="""
%import floats %import floats
@@ -2571,4 +2459,54 @@ main {
}""" }"""
compileText(VMTarget(), false, src, outputDir, writeAssembly = false) shouldNotBe null compileText(VMTarget(), false, src, outputDir, writeAssembly = false) shouldNotBe null
} }
test("0-indexed optimizations") {
val src="""
main {
struct Sprite {
uword x
ubyte y
}
^^Sprite[4] @shared sprites
^^Sprite @shared sprptr
sub start() {
sprptr.y = 99
sprptr[0]^^.y = 99
;; sprites[0]^^.y = 99 ; no change here. TODO: this syntax doesn't compile yet...
cx16.r0 = &sprptr[0]
cx16.r2L = sprptr.y
cx16.r0L = sprptr[0].y
cx16.r1L = sprites[0].y ; no change here, need first array element
cx16.r0 = sprites[0] ; no change here, need first array element
cx16.r0 = sprites[0] ; no change here, need first array element
}
}"""
val result = compileText(VMTarget(), true, src, outputDir, writeAssembly = false)!!
val st = result.compilerAst.entrypoint.statements
st.size shouldBe 8
val a1 = st[0] as Assignment
val a2 = st[1] as Assignment
val a3 = st[2] as Assignment
val a4 = st[3] as Assignment
val a5 = st[4] as Assignment
val a6 = st[5] as Assignment
val a7 = st[6] as Assignment
a1.target.arrayIndexedDereference shouldBe null
a1.target.pointerDereference!!.chain shouldBe listOf("sprptr", "y")
a2.target.arrayIndexedDereference shouldBe null
a2.target.pointerDereference!!.chain shouldBe listOf("sprptr", "y")
(a3.value as? AddressOf)?.identifier?.nameInSource shouldBe listOf("sprptr")
(a4.value as? PtrDereference)?.chain shouldBe listOf("sprptr", "y")
(a5.value as? PtrDereference)?.chain shouldBe listOf("sprptr", "y")
val be6 = a6.value as BinaryExpression // this one is an actual array and we need the first element so no change here
be6.operator shouldBe "."
be6.left shouldBe instanceOf<ArrayIndexedExpression>()
be6.right shouldBe instanceOf<IdentifierReference>()
(a7.value as? ArrayIndexedExpression)?.indexer?.constIndex() shouldBe 0
}
}) })

View File

@@ -5,7 +5,7 @@ TODO
STRUCTS and TYPED POINTERS STRUCTS and TYPED POINTERS
-------------------------- --------------------------
- make this array indexed assignment work: ^^Node np / np[2]^^.field = 9999 likely needs more support in the assignment target class (remove Note in docs when fixed) - make this array indexed assignment work: ^^Node np / np[2]^^.field = 9999 (same for pointer arrays!) likely needs more support in the assignment target class (remove Note in docs when fixed)
- implement the remaining TODO's in PointerAssignmentsGen. - implement the remaining TODO's in PointerAssignmentsGen.
- optimize deref in PointerAssignmentsGen: optimize 'forceTemporary' to only use a temporary when the offset is >0 - optimize deref in PointerAssignmentsGen: optimize 'forceTemporary' to only use a temporary when the offset is >0
- optimize the float copying in assignIndexedPointer() (also word?) - optimize the float copying in assignIndexedPointer() (also word?)

View File

@@ -1,8 +1,11 @@
main { main {
sub start() { sub start() {
ubyte @shared ok = sprites[2].y ; this one is fine... ; TODO assigning to pointer indexed is not yet supported:
ubyte @shared y = sprites[2].y ; TODO fix crash sprptr[2]^^.y = 99
sprptr[cx6.r0L]^^.y = 99
sprites[2]^^.y = 99
sprites[cx6.r0L]^^.y = 99
} }
struct Sprite { struct Sprite {
@@ -12,5 +15,6 @@ main {
^^Sprite[4] @shared sprites ^^Sprite[4] @shared sprites
^^Sprite @shared sprptr
} }