mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
fix typecast removal error.
This commit is contained in:
parent
7a3163f59a
commit
e1812ce16c
@ -36,7 +36,7 @@ init_system .proc
|
||||
.pend
|
||||
|
||||
|
||||
read_byte_from_address .proc
|
||||
read_byte_from_address_on_stack .proc
|
||||
; -- read the byte from the memory address on the top of the stack, return in A (stack remains unchanged)
|
||||
lda c64.ESTACK_LO+1,x
|
||||
ldy c64.ESTACK_HI+1,x
|
||||
@ -2079,7 +2079,7 @@ ror2_array_uw .proc
|
||||
+ rts
|
||||
.pend
|
||||
|
||||
|
||||
|
||||
strcpy .proc
|
||||
; copy a string (0-terminated) from A/Y to (ZPWORD1)
|
||||
; it is assumed the target string is large enough.
|
||||
@ -2092,8 +2092,8 @@ strcpy .proc
|
||||
bne -
|
||||
rts
|
||||
.pend
|
||||
|
||||
|
||||
|
||||
|
||||
func_leftstr .proc
|
||||
; leftstr(source, target, length) with params on stack
|
||||
inx
|
||||
@ -2175,12 +2175,12 @@ func_substr .proc
|
||||
lda c64.ESTACK_LO,x ; start
|
||||
sta c64.SCRATCH_ZPB1
|
||||
inx
|
||||
lda c64.ESTACK_LO,x
|
||||
lda c64.ESTACK_LO,x
|
||||
sta c64.SCRATCH_ZPWORD2
|
||||
lda c64.ESTACK_HI,x
|
||||
sta c64.SCRATCH_ZPWORD2+1
|
||||
inx
|
||||
lda c64.ESTACK_LO,x
|
||||
lda c64.ESTACK_LO,x
|
||||
sta c64.SCRATCH_ZPWORD1
|
||||
lda c64.ESTACK_HI,x
|
||||
sta c64.SCRATCH_ZPWORD1+1
|
||||
|
@ -328,6 +328,10 @@ open class Assignment(var target: AssignTarget, var value: Expression, override
|
||||
return("Assignment(target: $target, value: $value, pos=$position)")
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the assigment value an expression that references the assignment target itself?
|
||||
* The expression can be a BinaryExpression, PrefixExpression or TypecastExpression (possibly with one sub-cast).
|
||||
*/
|
||||
val isAugmentable: Boolean
|
||||
get() {
|
||||
val binExpr = value as? BinaryExpression
|
||||
@ -354,6 +358,16 @@ open class Assignment(var target: AssignTarget, var value: Expression, override
|
||||
}
|
||||
}
|
||||
|
||||
val prefixExpr = value as? PrefixExpression
|
||||
if(prefixExpr!=null)
|
||||
return prefixExpr.expression isSameAs target
|
||||
|
||||
val castExpr = value as? TypecastExpression
|
||||
if(castExpr!=null) {
|
||||
val subCast = castExpr.expression as? TypecastExpression
|
||||
return if(subCast!=null) subCast.expression isSameAs target else castExpr.expression isSameAs target
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -1008,7 +1008,6 @@ $counterVar .byte 0""")
|
||||
val indexName = asmIdentifierName(index)
|
||||
out(" lda $indexName")
|
||||
}
|
||||
// TODO optimize more cases
|
||||
else -> {
|
||||
expressionsAsmGen.translateExpression(index)
|
||||
out(" inx | lda $ESTACK_LO_HEX,x")
|
||||
|
@ -14,14 +14,13 @@ import prog8.compiler.toHex
|
||||
|
||||
internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
||||
|
||||
private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen)
|
||||
|
||||
internal fun translate(assign: Assignment) {
|
||||
when {
|
||||
assign.value is NumericLiteralValue -> translateConstantValueAssignment(assign)
|
||||
assign.value is IdentifierReference -> translateVariableAssignment(assign)
|
||||
assign.isAugmentable -> {
|
||||
println("TODO: optimize augmentable assignment ${assign.position}") // TODO
|
||||
translateOtherAssignment(assign) // TODO generate better code here for augmentable assignments
|
||||
}
|
||||
assign.isAugmentable -> augmentableAsmGen.translate(assign)
|
||||
else -> translateOtherAssignment(assign)
|
||||
}
|
||||
}
|
||||
@ -56,7 +55,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateOtherAssignment(assign: Assignment) {
|
||||
internal fun translateOtherAssignment(assign: Assignment) {
|
||||
when (assign.value) {
|
||||
is AddressOf -> {
|
||||
val identifier = (assign.value as AddressOf).identifier
|
||||
@ -74,23 +73,20 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
}
|
||||
else -> {
|
||||
asmgen.translateExpression(read.addressExpression)
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address | inx")
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | inx")
|
||||
assignFromRegister(assign.target, CpuRegister.A)
|
||||
}
|
||||
}
|
||||
}
|
||||
is PrefixExpression -> {
|
||||
// TODO optimize common cases
|
||||
asmgen.translateExpression(assign.value as PrefixExpression)
|
||||
assignFromEvalResult(assign.target)
|
||||
}
|
||||
is BinaryExpression -> {
|
||||
// TODO optimize common cases
|
||||
asmgen.translateExpression(assign.value as BinaryExpression)
|
||||
assignFromEvalResult(assign.target)
|
||||
}
|
||||
is ArrayIndexedExpression -> {
|
||||
// TODO optimize common cases
|
||||
val arrayExpr = assign.value as ArrayIndexedExpression
|
||||
val arrayDt = arrayExpr.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
val index = arrayExpr.arrayspec.index
|
||||
@ -141,6 +137,8 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
|
||||
private fun assignFromEvalResult(target: AssignTarget) {
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
val targetMemory = target.memoryAddress
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
@ -167,14 +165,14 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
else -> throw AssemblyError("weird target variable type $targetDt")
|
||||
}
|
||||
}
|
||||
target.memoryAddress != null -> {
|
||||
targetMemory != null -> {
|
||||
asmgen.out(" inx")
|
||||
storeByteViaRegisterAInMemoryAddress("$ESTACK_LO_HEX,x", target.memoryAddress)
|
||||
storeByteViaRegisterAInMemoryAddress("$ESTACK_LO_HEX,x", targetMemory)
|
||||
}
|
||||
target.arrayindexed != null -> {
|
||||
val arrayDt = target.arrayindexed!!.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
val arrayVarName = asmgen.asmIdentifierName(target.arrayindexed!!.identifier)
|
||||
asmgen.translateExpression(target.arrayindexed!!.arrayspec.index)
|
||||
targetArrayIdx != null -> {
|
||||
val arrayDt = targetArrayIdx.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
val arrayVarName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
asmgen.translateExpression(targetArrayIdx.arrayspec.index)
|
||||
asmgen.out(" inx | lda $ESTACK_LO_HEX,x")
|
||||
popAndWriteArrayvalueWithIndexA(arrayDt, arrayVarName)
|
||||
}
|
||||
@ -285,6 +283,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
val sourceName = asmgen.asmIdentifierName(variable)
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
val targetMemory = target.memoryAddress
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
@ -293,6 +292,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
sta $targetName
|
||||
""")
|
||||
}
|
||||
targetMemory != null -> {
|
||||
storeByteViaRegisterAInMemoryAddress(sourceName, targetMemory)
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
@ -302,9 +304,6 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
asmgen.out(" inx | lda $ESTACK_LO_HEX,x")
|
||||
popAndWriteArrayvalueWithIndexA(arrayDt, targetName)
|
||||
}
|
||||
target.memoryAddress != null -> {
|
||||
storeByteViaRegisterAInMemoryAddress(sourceName, target.memoryAddress)
|
||||
}
|
||||
else -> throw AssemblyError("no asm gen for assign bytevar to $target")
|
||||
}
|
||||
}
|
||||
@ -374,11 +373,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
when {
|
||||
addressLv != null -> asmgen.out(" lda $ldaInstructionArg | sta ${addressLv.number.toHex()}")
|
||||
addressExpr is IdentifierReference -> {
|
||||
val targetName = asmgen.asmIdentifierName(addressExpr)
|
||||
val pointerVarName = asmgen.asmIdentifierName(addressExpr)
|
||||
asmgen.out("""
|
||||
lda $targetName
|
||||
lda $pointerVarName
|
||||
sta ${C64Zeropage.SCRATCH_W1}
|
||||
lda $targetName+1
|
||||
lda $pointerVarName+1
|
||||
sta ${C64Zeropage.SCRATCH_W1+1}
|
||||
lda $ldaInstructionArg
|
||||
ldy #0
|
||||
@ -465,7 +464,6 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
targetArrayIdx != null -> {
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
// TODO optimize common cases
|
||||
asmgen.translateExpression(index)
|
||||
asmgen.out("""
|
||||
inx
|
||||
@ -486,7 +484,6 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
val targetMemory = target.memoryAddress
|
||||
// TODO all via method?
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
@ -498,7 +495,6 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
targetArrayIdx != null -> {
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
// TODO optimize common cases
|
||||
asmgen.translateExpression(index)
|
||||
asmgen.out("""
|
||||
inx
|
||||
|
@ -0,0 +1,34 @@
|
||||
package prog8.compiler.target.c64.codegen
|
||||
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.expressions.BinaryExpression
|
||||
import prog8.ast.expressions.PrefixExpression
|
||||
import prog8.ast.expressions.TypecastExpression
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.compiler.AssemblyError
|
||||
|
||||
internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
private val assignmentAsmGen: AssignmentAsmGen,
|
||||
private val asmgen: AsmGen) {
|
||||
fun translate(assign: Assignment) {
|
||||
require(assign.isAugmentable)
|
||||
assignmentAsmGen.translateOtherAssignment(assign) // TODO get rid of this fallback
|
||||
|
||||
// when (assign.value) {
|
||||
// is PrefixExpression -> {
|
||||
// TODO("aug prefix")
|
||||
// }
|
||||
// is TypecastExpression -> {
|
||||
// TODO("aug typecast")
|
||||
// }
|
||||
// is BinaryExpression -> {
|
||||
// TODO("aug binary")
|
||||
// }
|
||||
// else -> {
|
||||
// throw AssemblyError("invalid aug assign value type")
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -150,7 +150,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
||||
}
|
||||
else -> {
|
||||
translateExpression(expr.addressExpression)
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address")
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack")
|
||||
asmgen.out(" sta $ESTACK_LO_PLUS1_HEX,x")
|
||||
}
|
||||
}
|
||||
|
@ -412,8 +412,8 @@ private fun numericLiteral(value: Number, position: Position): NumericLiteralVal
|
||||
floatNum
|
||||
|
||||
return when(tweakedValue) {
|
||||
is Int -> NumericLiteralValue.optimalNumeric(value.toInt(), position)
|
||||
is Short -> NumericLiteralValue.optimalNumeric(value.toInt(), position)
|
||||
is Int -> NumericLiteralValue.optimalInteger(value.toInt(), position)
|
||||
is Short -> NumericLiteralValue.optimalInteger(value.toInt(), position)
|
||||
is Byte -> NumericLiteralValue(DataType.UBYTE, value.toShort(), position)
|
||||
is Double -> NumericLiteralValue(DataType.FLOAT, value.toDouble(), position)
|
||||
is Float -> NumericLiteralValue(DataType.FLOAT, value.toDouble(), position)
|
||||
|
@ -163,7 +163,7 @@ class ConstExprEvaluator {
|
||||
val error = "cannot add $left and $right"
|
||||
return when (left.type) {
|
||||
in IntegerDatatypes -> when (right.type) {
|
||||
in IntegerDatatypes -> NumericLiteralValue.optimalNumeric(left.number.toInt() + right.number.toInt(), left.position)
|
||||
in IntegerDatatypes -> NumericLiteralValue.optimalInteger(left.number.toInt() + right.number.toInt(), left.position)
|
||||
DataType.FLOAT -> NumericLiteralValue(DataType.FLOAT, left.number.toInt() + right.number.toDouble(), left.position)
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
@ -180,7 +180,7 @@ class ConstExprEvaluator {
|
||||
val error = "cannot subtract $left and $right"
|
||||
return when (left.type) {
|
||||
in IntegerDatatypes -> when (right.type) {
|
||||
in IntegerDatatypes -> NumericLiteralValue.optimalNumeric(left.number.toInt() - right.number.toInt(), left.position)
|
||||
in IntegerDatatypes -> NumericLiteralValue.optimalInteger(left.number.toInt() - right.number.toInt(), left.position)
|
||||
DataType.FLOAT -> NumericLiteralValue(DataType.FLOAT, left.number.toInt() - right.number.toDouble(), left.position)
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
@ -197,7 +197,7 @@ class ConstExprEvaluator {
|
||||
val error = "cannot multiply ${left.type} and ${right.type}"
|
||||
return when (left.type) {
|
||||
in IntegerDatatypes -> when (right.type) {
|
||||
in IntegerDatatypes -> NumericLiteralValue.optimalNumeric(left.number.toInt() * right.number.toInt(), left.position)
|
||||
in IntegerDatatypes -> NumericLiteralValue.optimalInteger(left.number.toInt() * right.number.toInt(), left.position)
|
||||
DataType.FLOAT -> NumericLiteralValue(DataType.FLOAT, left.number.toInt() * right.number.toDouble(), left.position)
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
@ -220,7 +220,7 @@ class ConstExprEvaluator {
|
||||
in IntegerDatatypes -> {
|
||||
if(right.number.toInt()==0) divideByZeroError(right.position)
|
||||
val result: Int = left.number.toInt() / right.number.toInt()
|
||||
NumericLiteralValue.optimalNumeric(result, left.position)
|
||||
NumericLiteralValue.optimalInteger(result, left.position)
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
if(right.number.toDouble()==0.0) divideByZeroError(right.position)
|
||||
|
@ -203,7 +203,7 @@ internal class ConstantFoldingOptimizer(private val program: Program) : AstWalke
|
||||
"-" -> when (subexpr.type) {
|
||||
in IntegerDatatypes -> {
|
||||
listOf(IAstModification.ReplaceNode(expr,
|
||||
NumericLiteralValue.optimalNumeric(-subexpr.number.toInt(), subexpr.position),
|
||||
NumericLiteralValue.optimalInteger(-subexpr.number.toInt(), subexpr.position),
|
||||
parent))
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
@ -216,7 +216,7 @@ internal class ConstantFoldingOptimizer(private val program: Program) : AstWalke
|
||||
"~" -> when (subexpr.type) {
|
||||
in IntegerDatatypes -> {
|
||||
listOf(IAstModification.ReplaceNode(expr,
|
||||
NumericLiteralValue.optimalNumeric(subexpr.number.toInt().inv(), subexpr.position),
|
||||
NumericLiteralValue.optimalInteger(subexpr.number.toInt().inv(), subexpr.position),
|
||||
parent))
|
||||
}
|
||||
else -> throw ExpressionError("can only take bitwise inversion of int", subexpr.position)
|
||||
|
@ -34,15 +34,25 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
|
||||
mods += IAstModification.ReplaceNode(typecast.expression, newLiteral, typecast)
|
||||
}
|
||||
|
||||
// remove redundant nested typecasts:
|
||||
// if the typecast casts a value to the same type, remove the cast.
|
||||
// if the typecast contains another typecast, remove the inner typecast.
|
||||
// remove redundant nested typecasts
|
||||
val subTypecast = typecast.expression as? TypecastExpression
|
||||
if (subTypecast != null) {
|
||||
mods += IAstModification.ReplaceNode(typecast.expression, subTypecast.expression, typecast)
|
||||
// remove the sub-typecast if its datatype is larger than the outer typecast
|
||||
if(subTypecast.type largerThan typecast.type) {
|
||||
mods += IAstModification.ReplaceNode(typecast.expression, subTypecast.expression, typecast)
|
||||
} else {
|
||||
if(subTypecast.type == DataType.UBYTE && typecast.type == DataType.UWORD) {
|
||||
// (X as ubyte) as uword -> X & 255
|
||||
// TODO don't optimize this because the asm code generated by it is worse...
|
||||
// val and255 = BinaryExpression(subTypecast.expression, "&", NumericLiteralValue.optimalInteger(255, subTypecast.position), subTypecast.position)
|
||||
// mods += IAstModification.ReplaceNode(typecast, and255, parent)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (typecast.expression.inferType(program).istype(typecast.type))
|
||||
if (typecast.expression.inferType(program).istype(typecast.type)) {
|
||||
// remove duplicate cast
|
||||
mods += IAstModification.ReplaceNode(typecast, typecast.expression, parent)
|
||||
}
|
||||
}
|
||||
|
||||
return mods
|
||||
|
@ -7,12 +7,18 @@ main {
|
||||
|
||||
sub start() {
|
||||
|
||||
ubyte A=5
|
||||
uword clr = $d020
|
||||
A = @(clr)
|
||||
A++
|
||||
@(clr) = A
|
||||
byte A
|
||||
byte B = +A
|
||||
byte C = -A
|
||||
uword W = 43210
|
||||
A = -A
|
||||
|
||||
c64scr.print_uw(W)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
W = W as ubyte ; TODO cast(W as ubyte) as uword -> W and 255
|
||||
c64scr.print_uw(W)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
; uword xx = @(clr+1)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user