diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a35047b..361ff2f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,8 @@ This matches both the CC65 behaviour and the return values from `readkey()`. * incorrect removal of unused local variables; + * incorrect removal of certain type casts; + * broken parameter passing to tail calls; * 6502: miscompilation when using the zeropage pseudoregister; diff --git a/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala b/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala index 7458b0e6..2f303fd1 100644 --- a/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala +++ b/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala @@ -500,6 +500,12 @@ abstract class AbstractStatementPreprocessor(protected val ctx: CompilationConte def pointlessCast(t1: String, expr: Expression): Boolean = { val typ1 = env.maybeGet[Type](t1).getOrElse(return false) val typ2 = getExpressionType(ctx, expr) + if (!typ1.isSigned) { + expr match { + case SumExpression(params, false) => if (params.exists(_._1)) return false + case _ => + } + } typ1.name == typ2.name } diff --git a/src/main/scala/millfork/env/Constant.scala b/src/main/scala/millfork/env/Constant.scala index 5bb743bf..d46628c4 100644 --- a/src/main/scala/millfork/env/Constant.scala +++ b/src/main/scala/millfork/env/Constant.scala @@ -25,6 +25,7 @@ sealed trait Constant { def isProvably(value: Int): Boolean = false def isProvablyInRange(startInclusive: Int, endInclusive: Int): Boolean = false def isProvablyNonnegative: Boolean = false + final def isProvablyGreaterOrEqualThan(other: Int): Boolean = isProvablyGreaterOrEqualThan(Constant(other)) def isProvablyGreaterOrEqualThan(other: Constant): Boolean = other match { case NumericConstant(0, _) => true case _ => false @@ -615,4 +616,23 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co override def isRelatedTo(v: Thing): Boolean = lhs.isRelatedTo(v) || rhs.isRelatedTo(v) override def refersTo(name: String): Boolean = lhs.refersTo(name) || rhs.refersTo(name) + + override def subbyte(index: Int): Constant = { + if (index != 0) return super.subbyte(index) + operator match { + case MathOperator.Minus if lhs.isProvablyZero => ((lhs+256)-rhs).quickSimplify.subbyte(0).quickSimplify + case MathOperator.Shl if rhs.isProvablyGreaterOrEqualThan(8) => Constant.Zero + case _ => super.subbyte(index) + } + } + + override def loByte: Constant = { + val result = operator match { + case MathOperator.Minus if lhs.isProvablyZero => + ((lhs+256)-rhs).quickSimplify.loByte.quickSimplify + case MathOperator.Shl if rhs.isProvablyGreaterOrEqualThan(8) => Constant.Zero + case _ => super.loByte + } + result + } } diff --git a/src/main/scala/millfork/env/Environment.scala b/src/main/scala/millfork/env/Environment.scala index c87b11af..1cbc0586 100644 --- a/src/main/scala/millfork/env/Environment.scala +++ b/src/main/scala/millfork/env/Environment.scala @@ -752,9 +752,15 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa } else None case Some(_: UnionType) => None - case Some(_) => + case Some(t) => if (params.size == 1) { - eval(params.head) + eval(params.head).map{ c => + (t.size, t.isSigned) match { + case (1, false) => c.loByte + case (2, false) => c.subword(0) + case _ => c // TODO + } + } } else None case _ => None }