optimized codegen for pointer indexing (read expressions)

This commit is contained in:
Irmen de Jong 2022-06-04 17:18:24 +02:00
parent 7f69517fd4
commit 2002412026
4 changed files with 34 additions and 5 deletions

View File

@ -72,6 +72,23 @@ internal class AssignmentAsmGen(private val program: Program,
val value = assign.source.array!! val value = assign.source.array!!
val elementDt = assign.source.datatype val elementDt = assign.source.datatype
val arrayVarName = asmgen.asmVariableName(value.arrayvar) val arrayVarName = asmgen.asmVariableName(value.arrayvar)
val arrayVarDecl = value.arrayvar.targetVarDecl(program)!!
if(arrayVarDecl.datatype==DataType.UWORD) {
// indexing a pointer var instead of a real array or string
if(elementDt !in ByteDatatypes)
throw AssemblyError("non-array var indexing requires bytes dt")
asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.Y)
if(asmgen.isZpVar(value.arrayvar)) {
asmgen.out(" lda ($arrayVarName),y")
} else {
asmgen.out(" lda $arrayVarName | sta P8ZP_SCRATCH_W1 | lda $arrayVarName+1 | sta P8ZP_SCRATCH_W1+1")
asmgen.out(" lda (P8ZP_SCRATCH_W1),y")
}
assignRegisterByte(assign.target, CpuRegister.A)
return
}
val constIndex = value.indexer.constIndex() val constIndex = value.indexer.constIndex()
if (constIndex!=null) { if (constIndex!=null) {
// constant array index value // constant array index value

View File

@ -149,6 +149,20 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val code = VmCodeChunk() val code = VmCodeChunk()
val idxReg = codeGen.vmRegisters.nextFree() val idxReg = codeGen.vmRegisters.nextFree()
val arrayLocation = codeGen.allocations.get(arrayIx.variable.targetName) val arrayLocation = codeGen.allocations.get(arrayIx.variable.targetName)
if(arrayIx.variable.type==DataType.UWORD) {
// indexing a pointer var instead of a real array or string
if(eltSize!=1)
throw AssemblyError("non-array var indexing requires bytes dt")
val pointerReg = codeGen.vmRegisters.nextFree()
code += translateExpression(arrayIx.index, idxReg, -1)
// TODO introduce LOADIX instruction to skip the ADD (requires 3 registers)
code += VmCodeInstruction(Opcode.LOADM, VmDataType.WORD, reg1=pointerReg, value=arrayLocation)
code += VmCodeInstruction(Opcode.ADD, VmDataType.WORD, reg1=pointerReg, reg2=idxReg)
code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1=resultRegister, reg2=pointerReg)
return code
}
if(arrayIx.index is PtNumber) { if(arrayIx.index is PtNumber) {
// optimized code when index is known - just calculate the memory address here // optimized code when index is known - just calculate the memory address here
val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize

View File

@ -45,13 +45,11 @@ internal class AstOnetimeTransforms(private val program: Program) : AstWalker()
return if(fcall!=null) { return if(fcall!=null) {
val fname = fcall.target.nameInSource val fname = fcall.target.nameInSource
if(fname.size==1 && fname[0] in InplaceModifyingBuiltinFunctions) { if(fname.size==1 && fname[0] in InplaceModifyingBuiltinFunctions) {
// TODO for now, swap() etc don't work on pointer var indexed args // TODO for now, swap() etc don't work on pointer var indexed args, so still replace this
val memread = DirectMemoryRead(add, arrayIndexedExpression.position) val memread = DirectMemoryRead(add, arrayIndexedExpression.position)
listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent)) listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent))
} else { } else {
// TODO first candidate for optimization is to remove this: noModifications
val memread = DirectMemoryRead(add, arrayIndexedExpression.position)
listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent))
} }
} else { } else {
val memread = DirectMemoryRead(add, arrayIndexedExpression.position) val memread = DirectMemoryRead(add, arrayIndexedExpression.position)

View File

@ -1,5 +1,5 @@
%import textio %import textio
%zeropage dontuse %zeropage basicsafe
; NOTE: meant to test to virtual machine output target (use -target vitual) ; NOTE: meant to test to virtual machine output target (use -target vitual)