mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-04 10: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
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
 | 
			
		||||
        if(arrayIndexedExpression.indexer.constIndex()==0) {
 | 
			
		||||
            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()
 | 
			
		||||
                    if(dt.isPointer) {
 | 
			
		||||
                        // pointer[0]  -->   pointer^^
 | 
			
		||||
                        val deref = PtrDereference(arrayIndexedExpression.plainarrayvar!!.nameInSource, true, arrayIndexedExpression.plainarrayvar!!.position)
 | 
			
		||||
                        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
 | 
			
		||||
 
 | 
			
		||||
@@ -384,4 +384,25 @@ internal class StatementReorderer(
 | 
			
		||||
        )
 | 
			
		||||
        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>()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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") {
 | 
			
		||||
        val src="""
 | 
			
		||||
%import floats
 | 
			
		||||
@@ -2571,4 +2459,54 @@ main {
 | 
			
		||||
}"""
 | 
			
		||||
        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
 | 
			
		||||
--------------------------
 | 
			
		||||
 | 
			
		||||
- 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.
 | 
			
		||||
- optimize deref in PointerAssignmentsGen: optimize 'forceTemporary' to only use a temporary when the offset is >0
 | 
			
		||||
- optimize the float copying in assignIndexedPointer() (also word?)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,11 @@
 | 
			
		||||
main {
 | 
			
		||||
 | 
			
		||||
    sub start() {
 | 
			
		||||
        ubyte @shared ok = sprites[2].y         ; this one is fine...
 | 
			
		||||
        ubyte @shared y = sprites[2].y         ; TODO fix crash
 | 
			
		||||
        ; TODO assigning to pointer indexed is not yet supported:
 | 
			
		||||
        sprptr[2]^^.y = 99
 | 
			
		||||
        sprptr[cx6.r0L]^^.y = 99
 | 
			
		||||
        sprites[2]^^.y = 99
 | 
			
		||||
        sprites[cx6.r0L]^^.y = 99
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct Sprite {
 | 
			
		||||
@@ -12,5 +15,6 @@ main {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    ^^Sprite[4] @shared sprites
 | 
			
		||||
    ^^Sprite @shared sprptr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user