mirror of
https://github.com/irmen/prog8.git
synced 2025-11-03 04:17:16 +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