mirror of
https://github.com/irmen/prog8.git
synced 2026-04-20 11:17:01 +00:00
slightly optimize certain pointer indexing calculation, fix invalid deref optimization
This commit is contained in:
@@ -447,26 +447,11 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
fun complicatedFallback() {
|
||||
// slow fallback routine that can deal with any expression for value
|
||||
require(value.type.isWord)
|
||||
asmgen.pushCpuStack(BaseDataType.UWORD, value)
|
||||
|
||||
if (scale == null || scale == 1) {
|
||||
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_W1", DataType.UWORD)
|
||||
} else {
|
||||
// P8ZP_SCRATCH_W1 = value * scale
|
||||
// TODO optimize this when the value is a binary expression with operator '+'
|
||||
val mult = PtBinaryExpression("*", DataType.UWORD, value.position)
|
||||
mult.parent = value.parent
|
||||
mult.add(value)
|
||||
mult.add(PtNumber(BaseDataType.UWORD, scale.toDouble(), value.position))
|
||||
val multSrc = AsmAssignSource.fromAstSource(mult, asmgen.program, asmgen)
|
||||
val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, value.definingISub(), value.position, variableAsmName = "P8ZP_SCRATCH_W1")
|
||||
val assign= AsmAssignment(multSrc, listOf(target), asmgen.program.memsizer, value.position)
|
||||
asmgen.translateNormalAssignment(assign, value.definingISub())
|
||||
}
|
||||
|
||||
asmgen.restoreRegisterStack(CpuRegister.Y, false) // msb
|
||||
asmgen.restoreRegisterStack(CpuRegister.A, false) // lsb
|
||||
asmgen.out("""
|
||||
fun restoreAYandAddAsmVariable(varname: String) {
|
||||
asmgen.restoreRegisterStack(CpuRegister.Y, false) // msb
|
||||
asmgen.restoreRegisterStack(CpuRegister.A, false) // lsb
|
||||
asmgen.out("""
|
||||
clc
|
||||
adc P8ZP_SCRATCH_W1
|
||||
pha
|
||||
@@ -474,6 +459,31 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
adc P8ZP_SCRATCH_W1+1
|
||||
tay
|
||||
pla""")
|
||||
}
|
||||
|
||||
if (scale == null || scale == 1) {
|
||||
asmgen.pushCpuStack(BaseDataType.UWORD, value)
|
||||
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_W1", DataType.UWORD)
|
||||
restoreAYandAddAsmVariable("P8ZP_SCRATCH_W1")
|
||||
} else {
|
||||
// P8ZP_SCRATCH_W1 = value * scale
|
||||
if(value is PtBinaryExpression && value.operator=="+" && value.right is PtNumber) {
|
||||
// (x + y) * scale == (x * scale) + (y * scale)
|
||||
addUnsignedWordToAY(value.left, scale)
|
||||
addUnsignedWordToAY(value.right, scale)
|
||||
} else {
|
||||
asmgen.pushCpuStack(BaseDataType.UWORD, value)
|
||||
val mult = PtBinaryExpression("*", DataType.UWORD, value.position)
|
||||
mult.parent = value.parent
|
||||
mult.add(value)
|
||||
mult.add(PtNumber(BaseDataType.UWORD, scale.toDouble(), value.position))
|
||||
val multSrc = AsmAssignSource.fromAstSource(mult, asmgen.program, asmgen)
|
||||
val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, value.definingISub(), value.position, variableAsmName = "P8ZP_SCRATCH_W1")
|
||||
val assign= AsmAssignment(multSrc, listOf(target), asmgen.program.memsizer, value.position)
|
||||
asmgen.translateNormalAssignment(assign, value.definingISub())
|
||||
restoreAYandAddAsmVariable("P8ZP_SCRATCH_W1")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when(value) {
|
||||
|
||||
@@ -430,11 +430,13 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
|
||||
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
|
||||
if(arrayIndexedExpression.indexer.constIndex()==0) {
|
||||
if(arrayIndexedExpression.plainarrayvar!=null) {
|
||||
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))
|
||||
if((arrayIndexedExpression.parent as? BinaryExpression)?.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))
|
||||
}
|
||||
}
|
||||
}
|
||||
val ptrDeref = arrayIndexedExpression.pointerderef
|
||||
|
||||
@@ -1027,7 +1027,7 @@ main {
|
||||
st[8] shouldBe instanceOf<Assignment>()
|
||||
}
|
||||
|
||||
test("indexing pointers with index 0 is just a direct pointer dereference") {
|
||||
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 {
|
||||
@@ -1062,12 +1062,16 @@ main {
|
||||
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 28
|
||||
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
|
||||
@@ -1119,6 +1123,20 @@ main {
|
||||
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") {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
fix compiler crash about structpointer[0].name (works fine with index 1...)
|
||||
|
||||
|
||||
not all source lines are correctly reported in the IR file,
|
||||
for example the below subroutine only shows the sub() line:
|
||||
sub two() {
|
||||
|
||||
Reference in New Issue
Block a user