diff --git a/src/main/scala/millfork/env/Environment.scala b/src/main/scala/millfork/env/Environment.scala index 6b00e54b..2e2b2578 100644 --- a/src/main/scala/millfork/env/Environment.scala +++ b/src/main/scala/millfork/env/Environment.scala @@ -1676,10 +1676,13 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa case Some(typ) => log.error(s"Type $name cannot be used as an array index", l.position) w -> Constant.Zero - case _ => w -> eval(l).getOrElse(errorConstant(s"Array `${stmt.name}` has non-constant length", stmt.position)) + case _ => + val constant = eval(l).getOrElse(errorConstant(s"Array `${stmt.name}` has non-constant length", stmt.position)) + w -> constant } case _ => - w -> eval(l).getOrElse(errorConstant(s"Array `${stmt.name}` has non-constant length", stmt.position)) + val constant = eval(l).getOrElse(errorConstant(s"Array `${stmt.name}` has non-constant length", stmt.position)) + w -> constant } lengthConst match { case NumericConstant(length, _) => diff --git a/src/main/scala/millfork/node/opt/UnusedGlobalVariables.scala b/src/main/scala/millfork/node/opt/UnusedGlobalVariables.scala index dee0ff9c..b2f8bd64 100644 --- a/src/main/scala/millfork/node/opt/UnusedGlobalVariables.scala +++ b/src/main/scala/millfork/node/opt/UnusedGlobalVariables.scala @@ -16,7 +16,7 @@ object UnusedGlobalVariables extends NodeOptimization { case _ => None }.toMap val allNonvolatileGlobalVariables = nodes.flatMap { - case v: VariableDeclarationStatement => if (v.address.isDefined || v.volatile) Nil else List(v.name) + case v: VariableDeclarationStatement => if (v.address.isDefined || v.volatile || v.constant) Nil else List(v.name) case v: ArrayDeclarationStatement => if (v.address.isDefined) Nil else List(v.name) case _ => Nil }.toSet @@ -50,7 +50,7 @@ object UnusedGlobalVariables extends NodeOptimization { def getAllReadVariables(expressions: List[Node]): List[String] = expressions.flatMap { case s: VariableDeclarationStatement => getAllReadVariables(s.address.toList) ++ getAllReadVariables(s.initialValue.toList) ++ (if (s.stack) List("__sp", "__stack") else Nil) - case s: ArrayDeclarationStatement => getAllReadVariables(s.address.toList) ++ getAllReadVariables(s.elements.toList) + case s: ArrayDeclarationStatement => getAllReadVariables(s.address.toList) ++ getAllReadVariables(s.length.toList) ++ getAllReadVariables(s.elements.toList) case s: ArrayContents => getAllReadVariables(s.getAllExpressions(false)) // endianness doesn't matter here at all case s: FunctionDeclarationStatement => getAllReadVariables(s.address.toList) ++ getAllReadVariables(s.statements.getOrElse(Nil)) case Assignment(VariableExpression(_), expr) => getAllReadVariables(expr :: Nil) diff --git a/src/test/scala/millfork/test/ConstantSuite.scala b/src/test/scala/millfork/test/ConstantSuite.scala index 7604a95f..a637e342 100644 --- a/src/test/scala/millfork/test/ConstantSuite.scala +++ b/src/test/scala/millfork/test/ConstantSuite.scala @@ -2,7 +2,7 @@ package millfork.test import millfork.Cpu import millfork.env.{BasicPlainType, DerivedPlainType, NumericConstant} -import millfork.test.emu.{EmuUnoptimizedCrossPlatformRun, EmuUnoptimizedRun, ShouldNotCompile} +import millfork.test.emu.{EmuBenchmarkRun, EmuOptimizedCmosRun, EmuUnoptimizedCrossPlatformRun, EmuUnoptimizedRun, ShouldNotCompile} import org.scalatest.{FunSuite, Matchers} /** @@ -130,4 +130,19 @@ class ConstantSuite extends FunSuite with Matchers { m.readByte(0xc011) should equal(89) } + + test("Constant array sizes") { + val m = EmuOptimizedCmosRun( + """ + | const byte A = 8 + | const byte B = 8 + | const byte SIZE = A * B + | array(byte) arr[SIZE] @$c000 + | void main() { + | arr[0] = 1 + | } + | + """.stripMargin) + m.readByte(0xc000) should equal(1) + } }