mirror of
https://github.com/irmen/prog8.git
synced 2024-09-29 08:57:51 +00:00
optimize unneeded type casts for register args
This commit is contained in:
parent
81f7419f70
commit
35aebbc209
@ -1,5 +1,6 @@
|
|||||||
package prog8.compiler
|
package prog8.compiler
|
||||||
|
|
||||||
|
import prog8.ast.IFunctionCall
|
||||||
import prog8.ast.Node
|
import prog8.ast.Node
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
@ -114,6 +115,18 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
|
|||||||
// that the types of assignment values and their target are the same,
|
// that the types of assignment values and their target are the same,
|
||||||
// and that the types of both operands of a binaryexpression node are the same.
|
// and that the types of both operands of a binaryexpression node are the same.
|
||||||
// So, it is not easily possible to remove the typecasts that are there to make these conditions true.
|
// So, it is not easily possible to remove the typecasts that are there to make these conditions true.
|
||||||
|
// The only place for now where we can do this is for:
|
||||||
|
// asmsub register pair parameter.
|
||||||
|
|
||||||
|
if(typecast.type in WordDatatypes) {
|
||||||
|
val fcall = typecast.parent as? IFunctionCall
|
||||||
|
if (fcall != null) {
|
||||||
|
val sub = fcall.target.targetStatement(program.namespace) as? Subroutine
|
||||||
|
if (sub != null && sub.isAsmSubroutine) {
|
||||||
|
return listOf(IAstModification.ReplaceNode(typecast, typecast.expression, parent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(sourceDt in PassByReferenceDatatypes) {
|
if(sourceDt in PassByReferenceDatatypes) {
|
||||||
if(typecast.type==DataType.UWORD) {
|
if(typecast.type==DataType.UWORD) {
|
||||||
|
@ -159,6 +159,7 @@ internal class AsmAssignment(val source: AsmAssignSource,
|
|||||||
val position: Position) {
|
val position: Position) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
require(source.datatype==target.datatype) {"source and target datatype must be identical"}
|
if(target.register !in setOf(RegisterOrPair.XY, RegisterOrPair.AX, RegisterOrPair.AY))
|
||||||
|
require(source.datatype==target.datatype) {"source and target datatype must be identical"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,7 +262,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
RegisterOrPair.A -> asmgen.out(" inx | lda P8ESTACK_LO,x")
|
RegisterOrPair.A -> asmgen.out(" inx | lda P8ESTACK_LO,x")
|
||||||
RegisterOrPair.X -> throw AssemblyError("can't load X from stack here - use intermediary var? ${target.origAstTarget?.position}")
|
RegisterOrPair.X -> throw AssemblyError("can't load X from stack here - use intermediary var? ${target.origAstTarget?.position}")
|
||||||
RegisterOrPair.Y -> asmgen.out(" inx | ldy P8ESTACK_LO,x")
|
RegisterOrPair.Y -> asmgen.out(" inx | ldy P8ESTACK_LO,x")
|
||||||
else -> throw AssemblyError("can't assign byte to register pair word")
|
RegisterOrPair.AX -> asmgen.out(" inx | lda P8ESTACK_LO,x | ldx #0")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" inx | lda P8ESTACK_LO,x | ldy #0")
|
||||||
|
else -> throw AssemblyError("can't assign byte from stack to register pair XY")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> {
|
DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> {
|
||||||
@ -571,19 +573,25 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
RegisterOrPair.A -> {}
|
RegisterOrPair.A -> {}
|
||||||
RegisterOrPair.X -> { asmgen.out(" tax") }
|
RegisterOrPair.X -> { asmgen.out(" tax") }
|
||||||
RegisterOrPair.Y -> { asmgen.out(" tay") }
|
RegisterOrPair.Y -> { asmgen.out(" tay") }
|
||||||
else -> throw AssemblyError("attempt to assign byte to register pair word")
|
RegisterOrPair.AY -> { asmgen.out(" ldy #0") }
|
||||||
|
RegisterOrPair.AX -> { asmgen.out(" ldx #0") }
|
||||||
|
RegisterOrPair.XY -> { asmgen.out(" tax | ldy #0") }
|
||||||
}
|
}
|
||||||
CpuRegister.X -> when(target.register!!) {
|
CpuRegister.X -> when(target.register!!) {
|
||||||
RegisterOrPair.A -> { asmgen.out(" txa") }
|
RegisterOrPair.A -> { asmgen.out(" txa") }
|
||||||
RegisterOrPair.X -> { }
|
RegisterOrPair.X -> { }
|
||||||
RegisterOrPair.Y -> { asmgen.out(" txy") }
|
RegisterOrPair.Y -> { asmgen.out(" txy") }
|
||||||
else -> throw AssemblyError("attempt to assign byte to register pair word")
|
RegisterOrPair.AY -> { asmgen.out(" txa | ldy #0") }
|
||||||
|
RegisterOrPair.AX -> { asmgen.out(" txa | ldx #0") }
|
||||||
|
RegisterOrPair.XY -> { asmgen.out(" ldy #0") }
|
||||||
}
|
}
|
||||||
CpuRegister.Y -> when(target.register!!) {
|
CpuRegister.Y -> when(target.register!!) {
|
||||||
RegisterOrPair.A -> { asmgen.out(" tya") }
|
RegisterOrPair.A -> { asmgen.out(" tya") }
|
||||||
RegisterOrPair.X -> { asmgen.out(" tyx") }
|
RegisterOrPair.X -> { asmgen.out(" tyx") }
|
||||||
RegisterOrPair.Y -> { }
|
RegisterOrPair.Y -> { }
|
||||||
else -> throw AssemblyError("attempt to assign byte to register pair word")
|
RegisterOrPair.AY -> { asmgen.out(" tya | ldy #0") }
|
||||||
|
RegisterOrPair.AX -> { asmgen.out(" tya | ldx #0") }
|
||||||
|
RegisterOrPair.XY -> { asmgen.out(" tya | tax | ldy #0") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -692,7 +700,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
RegisterOrPair.A -> asmgen.out(" lda #${byte.toHex()}")
|
RegisterOrPair.A -> asmgen.out(" lda #${byte.toHex()}")
|
||||||
RegisterOrPair.X -> asmgen.out(" ldx #${byte.toHex()}")
|
RegisterOrPair.X -> asmgen.out(" ldx #${byte.toHex()}")
|
||||||
RegisterOrPair.Y -> asmgen.out(" ldy #${byte.toHex()}")
|
RegisterOrPair.Y -> asmgen.out(" ldy #${byte.toHex()}")
|
||||||
else -> throw AssemblyError("can't assign byte to word register apir")
|
RegisterOrPair.AX -> asmgen.out(" lda #${byte.toHex()} | ldx #0")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" lda #${byte.toHex()} | ldy #0")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" ldx #${byte.toHex()} | ldy #0")
|
||||||
}
|
}
|
||||||
TargetStorageKind.STACK -> {
|
TargetStorageKind.STACK -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
@ -847,7 +857,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
RegisterOrPair.A -> asmgen.out(" lda ${address.toHex()}")
|
RegisterOrPair.A -> asmgen.out(" lda ${address.toHex()}")
|
||||||
RegisterOrPair.X -> asmgen.out(" ldx ${address.toHex()}")
|
RegisterOrPair.X -> asmgen.out(" ldx ${address.toHex()}")
|
||||||
RegisterOrPair.Y -> asmgen.out(" ldy ${address.toHex()}")
|
RegisterOrPair.Y -> asmgen.out(" ldy ${address.toHex()}")
|
||||||
else -> throw AssemblyError("can't assign byte to word register apir")
|
RegisterOrPair.AX -> asmgen.out(" lda ${address.toHex()} | ldx #0")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" lda ${address.toHex()} | ldy #0")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" ldy ${address.toHex()} | ldy #0")
|
||||||
}
|
}
|
||||||
TargetStorageKind.STACK -> {
|
TargetStorageKind.STACK -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
@ -875,7 +887,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
RegisterOrPair.A -> {}
|
RegisterOrPair.A -> {}
|
||||||
RegisterOrPair.X -> asmgen.out(" tax")
|
RegisterOrPair.X -> asmgen.out(" tax")
|
||||||
RegisterOrPair.Y -> asmgen.out(" tay")
|
RegisterOrPair.Y -> asmgen.out(" tay")
|
||||||
else -> throw AssemblyError("can't assign byte to word register apir")
|
RegisterOrPair.AX -> asmgen.out(" ldx #0")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" ldy #0")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" tax | ldy #0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TargetStorageKind.STACK -> {
|
TargetStorageKind.STACK -> {
|
||||||
|
@ -23,8 +23,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
// A = -A , A = +A, A = ~A, A = not A
|
// A = -A , A = +A, A = ~A, A = not A
|
||||||
val type = value.inferType(program).typeOrElse(DataType.STRUCT)
|
val type = value.inferType(program).typeOrElse(DataType.STRUCT)
|
||||||
when (value.operator) {
|
when (value.operator) {
|
||||||
"+" -> {
|
"+" -> {}
|
||||||
}
|
|
||||||
"-" -> inplaceNegate(assign.target, type)
|
"-" -> inplaceNegate(assign.target, type)
|
||||||
"~" -> inplaceInvert(assign.target, type)
|
"~" -> inplaceInvert(assign.target, type)
|
||||||
"not" -> inplaceBooleanNot(assign.target, type)
|
"not" -> inplaceBooleanNot(assign.target, type)
|
||||||
@ -219,6 +218,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun tryRemoveRedundantCast(value: TypecastExpression, target: AsmAssignTarget, operator: String): Boolean {
|
private fun tryRemoveRedundantCast(value: TypecastExpression, target: AsmAssignTarget, operator: String): Boolean {
|
||||||
|
// TODO doesn't always remove casts for instance uword xx = xb generates complex stack based type cast evaluation...
|
||||||
if (target.datatype == value.type) {
|
if (target.datatype == value.type) {
|
||||||
val childDt = value.expression.inferType(program).typeOrElse(DataType.STRUCT)
|
val childDt = value.expression.inferType(program).typeOrElse(DataType.STRUCT)
|
||||||
if (value.type.equalsSize(childDt) || value.type.largerThan(childDt)) {
|
if (value.type.equalsSize(childDt) || value.type.largerThan(childDt)) {
|
||||||
|
@ -38,7 +38,7 @@ main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if iter & 1
|
if iter & 1
|
||||||
graphics.plot(pixelx, pixely) ; TODO get rid of typecast in pixelx arg
|
graphics.plot(pixelx, pixely)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +248,7 @@ waitkey:
|
|||||||
c64.CHROUT('K')
|
c64.CHROUT('K')
|
||||||
|
|
||||||
while c64.GETIN()!=133 {
|
while c64.GETIN()!=133 {
|
||||||
|
; TODO FIX THIS, DOESN'T TRIGGER ANYMORE ON F1
|
||||||
; endless loop until user presses F1 to restart the game
|
; endless loop until user presses F1 to restart the game
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
;%import c64flt
|
;%import c64flt
|
||||||
;%option enable_floats
|
;%option enable_floats
|
||||||
; %zeropage kernalsafe
|
; %zeropage kernalsafe
|
||||||
|
; TODO system reset should also work when kernal is paged out
|
||||||
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
@ -18,7 +19,6 @@ main {
|
|||||||
; sub color(...) {}
|
; sub color(...) {}
|
||||||
; sub other(ubyte color) {} ; TODO don't cause name conflict
|
; sub other(ubyte color) {} ; TODO don't cause name conflict
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
|
; TODO this program gets corrupted graphics and crashes near the end
|
||||||
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
graphics.enable_bitmap_mode()
|
graphics.enable_bitmap_mode()
|
||||||
turtle.init()
|
turtle.init()
|
||||||
|
Loading…
Reference in New Issue
Block a user