mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
some more optimizations for swap() function call asm code generation
This commit is contained in:
parent
cb9825484d
commit
ee2ba5f398
@ -10,6 +10,46 @@ import prog8.ast.statements.*
|
||||
internal class AstVariousTransforms(private val program: Program) : AstWalker() {
|
||||
private val noModifications = emptyList<IAstModification>()
|
||||
|
||||
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> {
|
||||
if(functionCallStatement.target.nameInSource == listOf("swap")) {
|
||||
// if x and y are both just identifiers, do not rewrite (there should be asm generation for that)
|
||||
// otherwise:
|
||||
// rewrite swap(x,y) as follows:
|
||||
// - declare a temp variable of the same datatype
|
||||
// - temp = x, x = y, y= temp
|
||||
val first = functionCallStatement.args[0]
|
||||
val second = functionCallStatement.args[1]
|
||||
if(first !is IdentifierReference && second !is IdentifierReference) {
|
||||
val dt = first.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
val tempname = "prog8_swaptmp_${functionCallStatement.hashCode()}"
|
||||
val tempvardecl = VarDecl(VarDeclType.VAR, dt, ZeropageWish.DONTCARE, null, tempname, null, null, isArray = false, autogeneratedDontRemove = true, position = first.position)
|
||||
val tempvar = IdentifierReference(listOf(tempname), first.position)
|
||||
val assignTemp = Assignment(
|
||||
AssignTarget(null, tempvar, null, null, first.position),
|
||||
null,
|
||||
first,
|
||||
first.position
|
||||
)
|
||||
val assignFirst = Assignment(
|
||||
AssignTarget.fromExpr(first),
|
||||
null,
|
||||
second,
|
||||
first.position
|
||||
)
|
||||
val assignSecond = Assignment(
|
||||
AssignTarget.fromExpr(second),
|
||||
null,
|
||||
tempvar,
|
||||
first.position
|
||||
)
|
||||
val scope = AnonymousScope(mutableListOf(tempvardecl, assignTemp, assignFirst, assignSecond), first.position)
|
||||
return listOf(IAstModification.ReplaceNode(functionCallStatement, scope, parent))
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun before(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> {
|
||||
if(functionCall.target.nameInSource.size==1 && functionCall.target.nameInSource[0]=="lsb") {
|
||||
// lsb(...) is just an alias for type cast to ubyte, so replace with "... as ubyte"
|
||||
@ -104,11 +144,11 @@ internal class AstVariousTransforms(private val program: Program) : AstWalker()
|
||||
// this array literal is part of an expression, turn it into an identifier reference
|
||||
val litval2 = array.cast(arrayDt.typeOrElse(DataType.STRUCT))
|
||||
if(litval2!=null && litval2!=array) {
|
||||
val vardecl = VarDecl.createAuto(litval2)
|
||||
val identifier = IdentifierReference(listOf(vardecl.name), vardecl.position)
|
||||
val vardecl2 = VarDecl.createAuto(litval2)
|
||||
val identifier = IdentifierReference(listOf(vardecl2.name), vardecl2.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(array, identifier, parent),
|
||||
IAstModification.InsertFirst(vardecl, array.definingScope() as Node)
|
||||
IAstModification.InsertFirst(vardecl2, array.definingScope() as Node)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,8 @@ package prog8.compiler.target.c64.codegen
|
||||
|
||||
import prog8.ast.IFunctionCall
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.ByteDatatypes
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.base.Register
|
||||
import prog8.ast.base.WordDatatypes
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.AssignTarget
|
||||
import prog8.ast.statements.FunctionCallStatement
|
||||
import prog8.compiler.AssemblyError
|
||||
import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage
|
||||
@ -605,48 +601,8 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
||||
}
|
||||
}
|
||||
|
||||
// TODO more optimized cases?
|
||||
|
||||
// if(first is ArrayIndexedExpression && second is ArrayIndexedExpression && first.identifier == second.identifier) {
|
||||
// // swapping two elements of an array
|
||||
// // we optimize just some simple cases here: same array, const/var/reg index.
|
||||
// val arrayName = asmgen.asmIdentifierName(first.identifier)
|
||||
// val dt = first.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
// val constIndex1 = first.arrayspec.index.constValue(program)
|
||||
// val constIndex2 = second.arrayspec.index.constValue(program)
|
||||
// val varIndex1 = first.arrayspec.index as? IdentifierReference
|
||||
// val varIndex2 = first.arrayspec.index as? IdentifierReference
|
||||
// val regIndex1 = (first.arrayspec.index as? RegisterExpr)?.register
|
||||
// val regIndex2 = (first.arrayspec.index as? RegisterExpr)?.register
|
||||
// when(dt) {
|
||||
// DataType.UBYTE, DataType.BYTE -> {
|
||||
// TODO("swap byte in array $arrayName")
|
||||
// }
|
||||
// DataType.UWORD, DataType.WORD -> {
|
||||
// // swap word in array
|
||||
// if(varIndex1!=null && varIndex2!=null){
|
||||
// TODO("swap word in array $arrayName with varindexes")
|
||||
// } else if(constIndex1!=null && constIndex2!=null) {
|
||||
// TODO("swap word in array $arrayName with constants")
|
||||
// } else if(regIndex1!=null && regIndex2!=null) {
|
||||
// TODO("swap word in array $arrayName with register indexes")
|
||||
// }
|
||||
// }
|
||||
// DataType.FLOAT -> {
|
||||
// TODO("swap float in array $arrayName")
|
||||
// }
|
||||
// else -> throw AssemblyError("invalid array dt")
|
||||
// }
|
||||
// }
|
||||
|
||||
// suboptimal code via the evaluation stack...
|
||||
asmgen.translateExpression(first)
|
||||
asmgen.translateExpression(second)
|
||||
// pop in reverse order
|
||||
val firstTarget = AssignTarget.fromExpr(first)
|
||||
val secondTarget = AssignTarget.fromExpr(second)
|
||||
asmgen.assignFromEvalResult(firstTarget)
|
||||
asmgen.assignFromEvalResult(secondTarget)
|
||||
// other types of swap() calls should have been replaced by a different statement sequence involving a temp variable
|
||||
throw AssemblyError("no asm generation for swap funccall $fcall")
|
||||
}
|
||||
|
||||
private fun funcAbs(fcall: IFunctionCall, func: FSignature) {
|
||||
|
@ -143,18 +143,9 @@ main {
|
||||
for i1 in 0 to i {
|
||||
ubyte i2 = i1+1
|
||||
if(rotatedz[i1] > rotatedz[i2]) {
|
||||
; swap(rotatedx[i1], rotatedx[i2]) ; TODO eventually, implment the swap()
|
||||
; swap(rotatedy[i1], rotatedy[i2])
|
||||
; swap(rotatedz[i1], rotatedz[i2])
|
||||
word tmp1 = rotatedx[i1]
|
||||
rotatedx[i1] = rotatedx[i2] ; TODO fix assignment error
|
||||
rotatedx[i2] = tmp1
|
||||
tmp1 = rotatedy[i1]
|
||||
rotatedy[i1] = rotatedy[i2]
|
||||
rotatedy[i2] = tmp1
|
||||
tmp1 = rotatedz[i1]
|
||||
rotatedz[i1] = rotatedz[i2]
|
||||
rotatedz[i2] = tmp1
|
||||
swap(rotatedx[i1], rotatedx[i2])
|
||||
swap(rotatedy[i1], rotatedy[i2])
|
||||
swap(rotatedz[i1], rotatedz[i2])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,10 +23,6 @@ main {
|
||||
swap(uba[0], uba[1])
|
||||
swap(uwa[0], uwa[1])
|
||||
|
||||
swap(fa[A], fa[Y])
|
||||
swap(uba[A], uba[Y])
|
||||
swap(uwa[A], uwa[Y])
|
||||
|
||||
ubyte i1
|
||||
ubyte i2
|
||||
swap(fa[i1], fa[i2])
|
||||
|
Loading…
x
Reference in New Issue
Block a user