mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-03 19:16:13 +00:00 
			
		
		
		
	improved pointer[0]
This commit is contained in:
		@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
@@ -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?)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user