optimized typecasting more

This commit is contained in:
Irmen de Jong 2019-07-10 02:54:39 +02:00
parent 12cb7d7abe
commit 7eed1ebbf8
6 changed files with 49 additions and 94 deletions

View File

@ -44,6 +44,13 @@ enum class DataType {
in WordDatatypes -> other in ByteDatatypes in WordDatatypes -> other in ByteDatatypes
else -> true else -> true
} }
infix fun equalsSize(other: DataType) =
when(this) {
in ByteDatatypes -> other in ByteDatatypes
in WordDatatypes -> other in WordDatatypes
else -> false
}
} }
enum class Register { enum class Register {

View File

@ -519,8 +519,7 @@ open class LiteralValue(val type: DataType,
return LiteralValue(targettype, floatvalue = wordvalue!!.toDouble(), position = position) return LiteralValue(targettype, floatvalue = wordvalue!!.toDouble(), position = position)
} }
DataType.FLOAT -> { DataType.FLOAT -> {
if(floor(floatvalue!!) ==floatvalue) { val value = floatvalue!!.toInt()
val value = floatvalue.toInt()
if (targettype == DataType.BYTE && value in -128..127) if (targettype == DataType.BYTE && value in -128..127)
return LiteralValue(targettype, bytevalue = value.toShort(), position = position) return LiteralValue(targettype, bytevalue = value.toShort(), position = position)
if (targettype == DataType.UBYTE && value in 0..255) if (targettype == DataType.UBYTE && value in 0..255)
@ -530,7 +529,6 @@ open class LiteralValue(val type: DataType,
if (targettype == DataType.UWORD && value in 0..65535) if (targettype == DataType.UWORD && value in 0..65535)
return LiteralValue(targettype, wordvalue = value, position = position) return LiteralValue(targettype, wordvalue = value, position = position)
} }
}
in StringDatatypes -> { in StringDatatypes -> {
if(targettype in StringDatatypes) if(targettype in StringDatatypes)
return this return this

View File

@ -360,8 +360,9 @@ class AstToSourceCode(val output: (text: String) -> Unit): IAstVisitor {
} }
override fun visit(typecast: TypecastExpression) { override fun visit(typecast: TypecastExpression) {
output("(")
typecast.expression.accept(this) typecast.expression.accept(this)
output(" as ${datatypeString(typecast.type)} ") output(" as ${datatypeString(typecast.type)}) ")
} }
override fun visit(memread: DirectMemoryRead) { override fun visit(memread: DirectMemoryRead) {
@ -424,6 +425,6 @@ class AstToSourceCode(val output: (text: String) -> Unit): IAstVisitor {
outputln("") outputln("")
} }
override fun visit(nopStatement: NopStatement) { override fun visit(nopStatement: NopStatement) {
TODO("NOP???") output("; NOP")
} }
} }

View File

@ -87,7 +87,7 @@ fun compileProgram(filepath: Path,
programAst.checkValid(compilerOptions) // check if final tree is valid programAst.checkValid(compilerOptions) // check if final tree is valid
programAst.checkRecursion() // check if there are recursive subroutine calls programAst.checkRecursion() // check if there are recursive subroutine calls
// printAst(programAst) printAst(programAst)
// namespace.debugPrint() // namespace.debugPrint()
if(generateVmCode) { if(generateVmCode) {

View File

@ -36,8 +36,19 @@ internal class SimplifyExpressions(private val program: Program) : IAstModifying
} }
override fun visit(typecast: TypecastExpression): IExpression { override fun visit(typecast: TypecastExpression): IExpression {
// remove redundant typecasts
var tc = typecast var tc = typecast
// try to statically convert a literal value into one of the desired type
val literal = tc.expression as? LiteralValue
if(literal!=null) {
val newLiteral = literal.cast(tc.type)
if(newLiteral!=null && newLiteral!==literal) {
optimizationsDone++
return newLiteral
}
}
// remove redundant typecasts
while(true) { while(true) {
val expr = tc.expression val expr = tc.expression
if(expr !is TypecastExpression || expr.type!=tc.type) { if(expr !is TypecastExpression || expr.type!=tc.type) {
@ -50,16 +61,21 @@ internal class SimplifyExpressions(private val program: Program) : IAstModifying
} }
} }
// if the previous typecast was casting to a 'bigger' type, just ignore that one
val subTc = tc.expression as? TypecastExpression val subTc = tc.expression as? TypecastExpression
if(subTc!=null && subTc.type largerThan tc.type) { if(subTc!=null) {
// if the previous typecast was casting to a 'bigger' type, just ignore that one
// if the previous typecast was casting to a similar type, ignore that one
if(subTc.type largerThan tc.type || subTc.type equalsSize tc.type) {
subTc.type = tc.type subTc.type = tc.type
subTc.parent = tc.parent subTc.parent = tc.parent
optimizationsDone++ optimizationsDone++
return subTc return subTc
} }
}
return super.visit(tc) return super.visit(tc)
} }
optimizationsDone++ optimizationsDone++
tc = expr tc = expr
} }

View File

@ -1,85 +1,18 @@
%import c64utils %import c64utils
%zeropage basicsafe %zeropage basicsafe
%option enable_floats
~ main { ~ main {
sub start() { sub start() {
ubyte aa = 100
ubyte yy = 22
uword uw = (aa as uword)*yy
c64scr.print("stack (255?): ") word zc
c64scr.print_ub(X) word qq = zc>>13
c64.CHROUT('\n') ubyte[] colors = [1,2,3,4,5,6,7,8]
aa=30 uword bb = zc>>13
yy=2 c64.SPCOL[0] = colors[(zc>>13) as byte + 4]
c64scr.print_ub(7)
c64scr.print("?: ")
check(3, 4)
c64scr.print_ub(aa+yy)
c64scr.print("?: ")
check(aa, yy)
aa++
c64scr.print_ub(aa+yy)
c64scr.print("?: ")
check(aa, yy)
aa++
c64scr.print_ub(aa+yy)
c64scr.print("?: ")
check(aa, yy)
c64scr.print_uw(uw)
c64scr.print("?: ")
checkuw(uw)
uw++
c64scr.print_uw(uw)
c64scr.print("?: ")
checkuw(uw)
uw++
c64scr.print_uw(uw)
c64scr.print("?: ")
checkuw(uw)
c64scr.print("stack (255?): ")
c64scr.print_ub(X)
} }
sub checkuw(uword uw) {
when uw {
12345 -> c64scr.print("12345")
12346 -> c64scr.print("12346")
2200 -> c64scr.print("2200")
2202 -> c64scr.print("2202")
12347 -> c64scr.print("12347")
else -> c64scr.print("not in table")
}
c64.CHROUT('\n')
}
sub check(ubyte a, ubyte y) {
when a+y {
10 -> {
c64scr.print("ten")
}
5, 6, 7 -> c64scr.print("five or six or seven")
30 -> c64scr.print("thirty")
31 -> c64scr.print("thirty1")
32 -> c64scr.print("thirty2")
33 -> c64scr.print("thirty3")
99 -> c64scr.print("nn")
55 -> {
; should be optimized away
}
56 -> {
; should be optimized away
}
else -> {
c64scr.print("not in table")
}
}
c64.CHROUT('\n')
}
} }