From 40071b14313432d7008348a871c301c281a59d15 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 9 Sep 2020 21:37:56 +0200 Subject: [PATCH] fix compiler crash with adding too many typecasts to args. useless lsb() and msb() are optimized away. --- .../prog8/ast/processing/TypecastsAdder.kt | 1 + .../prog8/optimizer/ExpressionSimplifier.kt | 43 +++++++++++++++++++ examples/test.p8 | 3 -- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/compiler/src/prog8/ast/processing/TypecastsAdder.kt b/compiler/src/prog8/ast/processing/TypecastsAdder.kt index 4641cacd1..1c4c1136a 100644 --- a/compiler/src/prog8/ast/processing/TypecastsAdder.kt +++ b/compiler/src/prog8/ast/processing/TypecastsAdder.kt @@ -139,6 +139,7 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke call.args[arg.second.index], TypecastExpression(arg.second.value, possibleType, true, arg.second.value.position), call as Node) + break } } } diff --git a/compiler/src/prog8/optimizer/ExpressionSimplifier.kt b/compiler/src/prog8/optimizer/ExpressionSimplifier.kt index bbe7a03cf..ba971d7c9 100644 --- a/compiler/src/prog8/optimizer/ExpressionSimplifier.kt +++ b/compiler/src/prog8/optimizer/ExpressionSimplifier.kt @@ -297,6 +297,49 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker() return noModifications } + override fun after(functionCall: FunctionCall, parent: Node): Iterable { + if(functionCall.target.nameInSource == listOf("lsb")) { + val arg = functionCall.args[0] + if(arg is TypecastExpression) { + val valueDt = arg.expression.inferType(program) + if (valueDt.istype(DataType.BYTE) || valueDt.istype(DataType.UBYTE)) { + // useless lsb() of byte value that was casted to word + return listOf(IAstModification.ReplaceNode(functionCall, arg.expression, parent)) + } + } else { + val argDt = arg.inferType(program) + if (argDt.istype(DataType.BYTE) || argDt.istype(DataType.UBYTE)) { + // useless lsb() of byte value + return listOf(IAstModification.ReplaceNode(functionCall, arg, parent)) + } + } + } + else if(functionCall.target.nameInSource == listOf("msb")) { + val arg = functionCall.args[0] + if(arg is TypecastExpression) { + val valueDt = arg.expression.inferType(program) + if (valueDt.istype(DataType.BYTE) || valueDt.istype(DataType.UBYTE)) { + // useless msb() of byte value that was casted to word, replace with 0 + return listOf(IAstModification.ReplaceNode( + functionCall, + NumericLiteralValue(valueDt.typeOrElse(DataType.UBYTE), 0, arg.expression.position), + parent)) + } + } else { + val argDt = arg.inferType(program) + if (argDt.istype(DataType.BYTE) || argDt.istype(DataType.UBYTE)) { + // useless msb() of byte value, replace with 0 + return listOf(IAstModification.ReplaceNode( + functionCall, + NumericLiteralValue(argDt.typeOrElse(DataType.UBYTE), 0, arg.position), + parent)) + } + } + } + + return noModifications + } + private fun determineY(x: Expression, subBinExpr: BinaryExpression): Expression? { return when { subBinExpr.left isSameAs x -> subBinExpr.right diff --git a/examples/test.p8 b/examples/test.p8 index 7f53bfdfc..fb53ce240 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -11,9 +11,6 @@ main { c64.CHROUT('*') - uword value = lsb(rnd() & 31) ; TODO fix compiler crash - - ;asmsub clear_screen (ubyte char @ A, ubyte color @ Y) clobbers(A) { ...} ; TODO dont cause name conflict if we define sub or sub with param 'color' or even a var 'color' later.