mirror of
https://github.com/irmen/prog8.git
synced 2024-11-22 15:33:02 +00:00
preparing for more optimizations
This commit is contained in:
parent
53ac11983b
commit
75a06d2a40
@ -146,7 +146,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
|
||||
}
|
||||
|
||||
override fun after(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> {
|
||||
// see if we can remove superfluous typecasts (outside of expressions)
|
||||
// see if we can remove redundant typecasts (outside of expressions)
|
||||
// such as casting byte<->ubyte, word<->uword
|
||||
// Also the special typecast of a reference type (str, array) to an UWORD will be changed into address-of,
|
||||
// UNLESS it's a str parameter in the containing subroutine - then we remove the typecast altogether
|
||||
|
@ -47,7 +47,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk
|
||||
val rightDt = expr.right.inferType(program)
|
||||
if(leftDt.isKnown && rightDt.isKnown && leftDt!=rightDt) {
|
||||
// determine common datatype and add typecast as required to make left and right equal types
|
||||
val (commonDt, toFix) = BinaryExpression.commonDatatype(leftDt.getOr(DataType.UNDEFINED), rightDt.getOr(DataType.UNDEFINED), expr.left, expr.right)
|
||||
val (commonDt, toFix) = BinaryExpression.commonDatatype(leftDt.getOr(DataType.UNDEFINED), rightDt.getOr(DataType.UNDEFINED), expr.left, expr.operator, expr.right)
|
||||
if(toFix!=null) {
|
||||
return when {
|
||||
toFix===expr.left -> listOf(IAstModification.ReplaceNode(
|
||||
|
@ -74,6 +74,19 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter)
|
||||
if(sourceDt istype typecast.type)
|
||||
return listOf(IAstModification.ReplaceNode(typecast, typecast.expression, parent))
|
||||
|
||||
// TODO finish this; get rid of redundant final typecast to variable's type if they are the same
|
||||
// if(parent is Assignment) {
|
||||
// val targetDt = (parent).target.inferType(program).getOrElse { throw FatalAstException("invalid dt") }
|
||||
// if(sourceDt istype targetDt) {
|
||||
// // we can get rid of this typecast because the type is already
|
||||
// // TODO REMOVE IT
|
||||
// println("TYPECAST IN ASSIGNMENT $parent") // TODO DEBUG
|
||||
// } else {
|
||||
// // TODO
|
||||
// println("${typecast.expression} : source=$sourceDt to $targetDt")
|
||||
// }
|
||||
// }
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
|
@ -190,6 +190,39 @@ class TestOptimization: FunSpec({
|
||||
asm.valid shouldBe true
|
||||
}
|
||||
|
||||
test("intermediate assignment steps 2 have correct types for codegen phase (BeforeAsmGenerationAstChanger)") {
|
||||
val src = """
|
||||
main {
|
||||
sub start() {
|
||||
ubyte r
|
||||
ubyte @shared bb = (cos8(r)/2 + 100) as ubyte
|
||||
}
|
||||
}
|
||||
"""
|
||||
val result = compileText(C64Target, true, src, writeAssembly = false).assertSuccess()
|
||||
|
||||
// bb = (cos8(r)/2 + 100) as ubyte
|
||||
val bbAssign = result.program.entrypoint.statements.last() as Assignment
|
||||
val texpr = bbAssign.value as TypecastExpression
|
||||
texpr.type shouldBe DataType.UBYTE
|
||||
texpr.expression shouldBe instanceOf<BinaryExpression>()
|
||||
texpr.expression.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.BYTE
|
||||
|
||||
val options = CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, true, C64Target)
|
||||
val changer = BeforeAsmGenerationAstChanger(result.program,
|
||||
options,
|
||||
ErrorReporterForTests()
|
||||
)
|
||||
|
||||
changer.visit(result.program)
|
||||
while(changer.applyModifications()>0) {
|
||||
changer.visit(result.program)
|
||||
}
|
||||
|
||||
// printAst(result.program)
|
||||
// TODO finish this test
|
||||
}
|
||||
|
||||
test("asmgen correctly deals with float typecasting in augmented assignment") {
|
||||
val src="""
|
||||
%option enable_floats
|
||||
|
@ -170,7 +170,7 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
|
||||
commonDatatype(
|
||||
leftDt.getOr(DataType.BYTE),
|
||||
rightDt.getOr(DataType.BYTE),
|
||||
null, null
|
||||
null, "", null
|
||||
).first
|
||||
)
|
||||
} catch (x: FatalAstException) {
|
||||
@ -192,7 +192,7 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
|
||||
|
||||
companion object {
|
||||
fun commonDatatype(leftDt: DataType, rightDt: DataType,
|
||||
left: Expression?, right: Expression?): Pair<DataType, Expression?> {
|
||||
left: Expression?, operator: String, right: Expression?): Pair<DataType, Expression?> {
|
||||
// byte + byte -> byte
|
||||
// byte + word -> word
|
||||
// word + byte -> word
|
||||
|
@ -675,4 +675,51 @@ class TestProg8Parser: FunSpec( {
|
||||
expr.right.inferType(program).getOrElse { fail("dt") } shouldBe DataType.UWORD
|
||||
expr.inferType(program).getOrElse { fail("dt") } shouldBe DataType.UBYTE
|
||||
}
|
||||
|
||||
test("inferred type for typecasted expressions with logical operators") {
|
||||
val src=SourceCode.Text("""
|
||||
main {
|
||||
ubyte bb
|
||||
uword ww
|
||||
uword qq = (not bb as uword)
|
||||
uword zz = not bb or not ww
|
||||
ubyte bb2 = not bb or not ww
|
||||
uword zz2 = (not bb as uword) or not ww
|
||||
}
|
||||
""")
|
||||
val module = parseModule(src)
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
module.linkIntoProgram(program)
|
||||
val stmts = (module.statements.single() as Block).statements
|
||||
stmts.size shouldBe 6
|
||||
val qq = (stmts[2] as VarDecl).value as TypecastExpression
|
||||
val zz = (stmts[3] as VarDecl).value as BinaryExpression
|
||||
val bb2 = (stmts[4] as VarDecl).value as BinaryExpression
|
||||
val zz2 = (stmts[5] as VarDecl).value as BinaryExpression
|
||||
qq.inferType(program).getOrElse { fail("dt") } shouldBe DataType.UWORD
|
||||
zz.inferType(program).getOrElse { fail("dt") } shouldBe DataType.UBYTE
|
||||
bb2.inferType(program).getOrElse { fail("dt") } shouldBe DataType.UBYTE
|
||||
|
||||
zz2.operator shouldBe "or"
|
||||
val left = zz2.left as TypecastExpression
|
||||
val right = zz2.right as PrefixExpression
|
||||
left.inferType(program).getOrElse { fail("dt") } shouldBe DataType.UWORD
|
||||
right.inferType(program).getOrElse { fail("dt") } shouldBe DataType.UWORD
|
||||
zz2.inferType(program).getOrElse { fail("dt") } shouldBe DataType.UBYTE // 'or' causes UBYTE result
|
||||
}
|
||||
|
||||
test("type cast from byte to ubyte as desired target type") {
|
||||
val src = SourceCode.Text("""
|
||||
main {
|
||||
ubyte r
|
||||
ubyte ub = (cos8(r)/2 + 100) as ubyte
|
||||
}""")
|
||||
val module = parseModule(src)
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
module.linkIntoProgram(program)
|
||||
val stmts = (module.statements.single() as Block).statements
|
||||
stmts.size shouldBe 2
|
||||
val ubexpr = (stmts[1] as VarDecl).value as TypecastExpression
|
||||
ubexpr.inferType(program).getOrElse { fail("dt") } shouldBe DataType.UBYTE
|
||||
}
|
||||
})
|
||||
|
@ -7,7 +7,7 @@ main {
|
||||
sub start() {
|
||||
ubyte bb
|
||||
uword ww
|
||||
ww = not bb or not ww ; TODO WHY DOES THIS USE STACK EVAL
|
||||
uword @shared zz = not bb or not ww ; TODO WHY DOES THIS USE STACK EVAL-because of typecastings?
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user