1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-02 18:29:50 +00:00

Constant evaluation fixes

This commit is contained in:
Karol Stasiak 2018-01-18 22:38:17 +01:00
parent 64f72c8a1c
commit 4c0d184c47
2 changed files with 47 additions and 25 deletions

View File

@ -291,7 +291,8 @@ object BuiltIns {
val env = ctx.env
val b = env.get[Type]("byte")
val firstParamCompiled = MlCompiler.compile(ctx, lhs, Some(b -> RegisterVariable(Register.A, b)), NoBranching)
env.eval(rhs) match {
val maybeConstant = env.eval(rhs)
maybeConstant match {
case Some(NumericConstant(0, _)) =>
compType match {
case ComparisonType.LessUnsigned =>
@ -318,19 +319,30 @@ object BuiltIns {
}
case _ =>
}
val secondParamCompiledUnoptimized = simpleOperation(CMP, ctx, rhs, IndexChoice.PreferY, preserveA = true, commutative = false)
val secondParamCompiled = compType match {
case ComparisonType.Equal | ComparisonType.NotEqual | ComparisonType.LessSigned | ComparisonType.GreaterOrEqualSigned =>
secondParamCompiledUnoptimized match {
case List(AssemblyLine(CMP, Immediate, NumericConstant(0, _), true)) =>
if (OpcodeClasses.ChangesAAlways(firstParamCompiled.last.opcode)) {
Nil
} else {
secondParamCompiledUnoptimized
}
case _ => secondParamCompiledUnoptimized
val secondParamCompiled = maybeConstant match {
case Some(x) =>
compType match {
case ComparisonType.Equal | ComparisonType.NotEqual | ComparisonType.LessSigned | ComparisonType.GreaterOrEqualSigned =>
if (x.quickSimplify.isLowestByteAlwaysEqual(0) && OpcodeClasses.ChangesAAlways(firstParamCompiled.last.opcode)) Nil
else List(AssemblyLine.immediate(CMP, x))
case _ =>
List(AssemblyLine.immediate(CMP, x))
}
case _ => secondParamCompiledUnoptimized
case _ => compType match {
case ComparisonType.Equal | ComparisonType.NotEqual | ComparisonType.LessSigned | ComparisonType.GreaterOrEqualSigned =>
val secondParamCompiledUnoptimized = simpleOperation(CMP, ctx, rhs, IndexChoice.PreferY, preserveA = true, commutative = false)
secondParamCompiledUnoptimized match {
case List(AssemblyLine(CMP, Immediate, NumericConstant(0, _), true)) =>
if (OpcodeClasses.ChangesAAlways(firstParamCompiled.last.opcode)) {
Nil
} else {
secondParamCompiledUnoptimized
}
case _ => secondParamCompiledUnoptimized
}
case _ =>
simpleOperation(CMP, ctx, rhs, IndexChoice.PreferY, preserveA = true, commutative = false)
}
}
val (effectiveComparisonType, label) = branches match {
case NoBranching => return Nil

View File

@ -270,6 +270,16 @@ class Environment(val parent: Option[Environment], val prefix: String) {
} yield hc.asl(8) + lc
case FunctionCallExpression(name, params) =>
name match {
case ">>'" =>
constantOperation(MathOperator.DecimalShr, params)
case "<<'" =>
constantOperation(MathOperator.DecimalShl, params)
case ">>" =>
constantOperation(MathOperator.Shr, params)
case "<<" =>
constantOperation(MathOperator.Shl, params)
case "*'" =>
constantOperation(MathOperator.DecimalTimes, params)
case "*" =>
constantOperation(MathOperator.Times, params)
case "&&" | "&" =>
@ -282,7 +292,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
None
}
}
}
}.map(_.quickSimplify)
private def constantOperation(op: MathOperator.Value, params: List[Expression]) = {
params.map(eval).reduceLeft[Option[Constant]] { (oc, om) =>
@ -515,10 +525,10 @@ class Environment(val parent: Option[Environment], val prefix: String) {
}
addThing(RelativeVariable(stmt.name + ".first", a, b, zeropage = false), stmt.position)
addThing(ConstantThing(stmt.name, a, p), stmt.position)
addThing(ConstantThing(stmt.name + ".hi", a.hiByte, b), stmt.position)
addThing(ConstantThing(stmt.name + ".lo", a.loByte, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.lo", a.loByte, b), stmt.position)
addThing(ConstantThing(stmt.name + ".hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".lo", a.loByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.lo", a.loByte.quickSimplify, b), stmt.position)
if (length < 256) {
addThing(ConstantThing(stmt.name + ".length", lengthConst, b), stmt.position)
}
@ -549,10 +559,10 @@ class Environment(val parent: Option[Environment], val prefix: String) {
}
addThing(RelativeVariable(stmt.name + ".first", a, b, zeropage = false), stmt.position)
addThing(ConstantThing(stmt.name, a, p), stmt.position)
addThing(ConstantThing(stmt.name + ".hi", a.hiByte, b), stmt.position)
addThing(ConstantThing(stmt.name + ".lo", a.loByte, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.lo", a.loByte, b), stmt.position)
addThing(ConstantThing(stmt.name + ".hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".lo", a.loByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.lo", a.loByte.quickSimplify, b), stmt.position)
if (length < 256) {
addThing(ConstantThing(stmt.name + ".length", NumericConstant(length, 1), b), stmt.position)
}
@ -588,9 +598,9 @@ class Environment(val parent: Option[Environment], val prefix: String) {
val constantValue: Constant = stmt.initialValue.flatMap(eval).getOrElse(Constant.error(s"`$name` has a non-constant value", position))
if (constantValue.requiredSize > typ.size) ErrorReporting.error(s"`$name` is has an invalid value: not in the range of `$typ`", position)
addThing(ConstantThing(prefix + name, constantValue, typ), stmt.position)
if (typ.size == 2) {
addThing(ConstantThing(prefix + name + ".hi", constantValue + 1, b), stmt.position)
addThing(ConstantThing(prefix + name + ".lo", constantValue, b), stmt.position)
if (typ.size >= 2) {
addThing(ConstantThing(prefix + name + ".hi", constantValue.hiByte, b), stmt.position)
addThing(ConstantThing(prefix + name + ".lo", constantValue.loByte, b), stmt.position)
}
} else {
if (stmt.stack && stmt.global) ErrorReporting.error(s"`$name` is static or global and cannot be on stack", position)