1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-04 16:29:52 +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 env = ctx.env
val b = env.get[Type]("byte") val b = env.get[Type]("byte")
val firstParamCompiled = MlCompiler.compile(ctx, lhs, Some(b -> RegisterVariable(Register.A, b)), NoBranching) 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, _)) => case Some(NumericConstant(0, _)) =>
compType match { compType match {
case ComparisonType.LessUnsigned => case ComparisonType.LessUnsigned =>
@ -318,19 +319,30 @@ object BuiltIns {
} }
case _ => case _ =>
} }
val secondParamCompiledUnoptimized = simpleOperation(CMP, ctx, rhs, IndexChoice.PreferY, preserveA = true, commutative = false) val secondParamCompiled = maybeConstant match {
val secondParamCompiled = compType match { case Some(x) =>
case ComparisonType.Equal | ComparisonType.NotEqual | ComparisonType.LessSigned | ComparisonType.GreaterOrEqualSigned => compType match {
secondParamCompiledUnoptimized match { case ComparisonType.Equal | ComparisonType.NotEqual | ComparisonType.LessSigned | ComparisonType.GreaterOrEqualSigned =>
case List(AssemblyLine(CMP, Immediate, NumericConstant(0, _), true)) => if (x.quickSimplify.isLowestByteAlwaysEqual(0) && OpcodeClasses.ChangesAAlways(firstParamCompiled.last.opcode)) Nil
if (OpcodeClasses.ChangesAAlways(firstParamCompiled.last.opcode)) { else List(AssemblyLine.immediate(CMP, x))
Nil case _ =>
} else { List(AssemblyLine.immediate(CMP, x))
secondParamCompiledUnoptimized
}
case _ => secondParamCompiledUnoptimized
} }
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 { val (effectiveComparisonType, label) = branches match {
case NoBranching => return Nil case NoBranching => return Nil

View File

@ -270,6 +270,16 @@ class Environment(val parent: Option[Environment], val prefix: String) {
} yield hc.asl(8) + lc } yield hc.asl(8) + lc
case FunctionCallExpression(name, params) => case FunctionCallExpression(name, params) =>
name match { 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 "*" => case "*" =>
constantOperation(MathOperator.Times, params) constantOperation(MathOperator.Times, params)
case "&&" | "&" => case "&&" | "&" =>
@ -282,7 +292,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
None None
} }
} }
} }.map(_.quickSimplify)
private def constantOperation(op: MathOperator.Value, params: List[Expression]) = { private def constantOperation(op: MathOperator.Value, params: List[Expression]) = {
params.map(eval).reduceLeft[Option[Constant]] { (oc, om) => 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(RelativeVariable(stmt.name + ".first", a, b, zeropage = false), stmt.position)
addThing(ConstantThing(stmt.name, a, p), stmt.position) addThing(ConstantThing(stmt.name, a, p), stmt.position)
addThing(ConstantThing(stmt.name + ".hi", a.hiByte, b), stmt.position) addThing(ConstantThing(stmt.name + ".hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".lo", a.loByte, b), stmt.position) addThing(ConstantThing(stmt.name + ".lo", a.loByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte, b), stmt.position) addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.lo", a.loByte, b), stmt.position) addThing(ConstantThing(stmt.name + ".array.lo", a.loByte.quickSimplify, b), stmt.position)
if (length < 256) { if (length < 256) {
addThing(ConstantThing(stmt.name + ".length", lengthConst, b), stmt.position) 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(RelativeVariable(stmt.name + ".first", a, b, zeropage = false), stmt.position)
addThing(ConstantThing(stmt.name, a, p), stmt.position) addThing(ConstantThing(stmt.name, a, p), stmt.position)
addThing(ConstantThing(stmt.name + ".hi", a.hiByte, b), stmt.position) addThing(ConstantThing(stmt.name + ".hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".lo", a.loByte, b), stmt.position) addThing(ConstantThing(stmt.name + ".lo", a.loByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte, b), stmt.position) addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.lo", a.loByte, b), stmt.position) addThing(ConstantThing(stmt.name + ".array.lo", a.loByte.quickSimplify, b), stmt.position)
if (length < 256) { if (length < 256) {
addThing(ConstantThing(stmt.name + ".length", NumericConstant(length, 1), b), stmt.position) 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)) 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) 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) addThing(ConstantThing(prefix + name, constantValue, typ), stmt.position)
if (typ.size == 2) { if (typ.size >= 2) {
addThing(ConstantThing(prefix + name + ".hi", constantValue + 1, b), stmt.position) addThing(ConstantThing(prefix + name + ".hi", constantValue.hiByte, b), stmt.position)
addThing(ConstantThing(prefix + name + ".lo", constantValue, b), stmt.position) addThing(ConstantThing(prefix + name + ".lo", constantValue.loByte, b), stmt.position)
} }
} else { } else {
if (stmt.stack && stmt.global) ErrorReporting.error(s"`$name` is static or global and cannot be on stack", position) if (stmt.stack && stmt.global) ErrorReporting.error(s"`$name` is static or global and cannot be on stack", position)