diff --git a/src/main/scala/millfork/assembly/opt/FlowAnalyzer.scala b/src/main/scala/millfork/assembly/opt/FlowAnalyzer.scala index a556df35..f11165bf 100644 --- a/src/main/scala/millfork/assembly/opt/FlowAnalyzer.scala +++ b/src/main/scala/millfork/assembly/opt/FlowAnalyzer.scala @@ -8,7 +8,16 @@ import millfork.env.{Label, MemoryAddressConstant, NormalFunction} * @author Karol Stasiak */ -case class FlowInfo(statusBefore: CpuStatus, importanceAfter: CpuImportance, labelUseCountMap: Option[Map[String, Int]]) { +class FlowHolder(_statusBefore: () => List[CpuStatus], _importanceAfter: () => List[CpuImportance]) { + lazy val statusBefore: List[CpuStatus] = _statusBefore() + lazy val importanceAfter: List[CpuImportance] = _importanceAfter() +} + +case class FlowInfo(holder: FlowHolder, index: Int, _labelUseCountMap: () => Option[Map[String, Int]]) { + + lazy val statusBefore: CpuStatus = holder.statusBefore(index) + lazy val importanceAfter = holder.importanceAfter(index) + lazy val labelUseCountMap: Option[Map[String, Int]] = _labelUseCountMap() def hasClear(state: State.Value): Boolean = statusBefore.hasClear(state) @@ -19,35 +28,36 @@ case class FlowInfo(statusBefore: CpuStatus, importanceAfter: CpuImportance, lab def labelUseCount(label: String): Int = labelUseCountMap.map(_.getOrElse(label, 0)).getOrElse(-1) } -object FlowInfo { - val Default = FlowInfo(CpuStatus(), CpuImportance(), None) -} - object FlowAnalyzer { + + private val EmptyCpuStatus = CpuStatus() + private val EmptyCpuImportance = CpuImportance() + def analyze(f: NormalFunction, code: List[AssemblyLine], options: CompilationOptions, req: FlowInfoRequirement.Value): List[(FlowInfo, AssemblyLine)] = { val forwardFlow = req match { case FlowInfoRequirement.BothFlows | FlowInfoRequirement.ForwardFlow => if (options.flag(CompilationFlag.DetailedFlowAnalysis)) { - QuantumFlowAnalyzer.analyze(f, code).map(_.collapse) + () => QuantumFlowAnalyzer.analyze(f, code).map(_.collapse) } else { - CoarseFlowAnalyzer.analyze(f, code) + () => CoarseFlowAnalyzer.analyze(f, code) } case FlowInfoRequirement.BackwardFlow | FlowInfoRequirement.JustLabels | FlowInfoRequirement.NoRequirement => - List.fill(code.size)(CpuStatus()) + () => List.fill(code.size)(EmptyCpuStatus) } val reverseFlow = req match { case FlowInfoRequirement.BothFlows | FlowInfoRequirement.BackwardFlow => - ReverseFlowAnalyzer.analyze(f, code) + () => ReverseFlowAnalyzer.analyze(f, code) case FlowInfoRequirement.ForwardFlow | FlowInfoRequirement.JustLabels | FlowInfoRequirement.NoRequirement => - List.fill(code.size)(CpuImportance()) + () => List.fill(code.size)(EmptyCpuImportance) } - val labelMap = req match { + val labelMap: (() => Option[Map[String, Int]]) = () => req match { case FlowInfoRequirement.NoRequirement => None case _ => Some(code.flatMap { case AssemblyLine(op, _, MemoryAddressConstant(Label(l)), _) if op != Opcode.LABEL => Some(l) case _ => None }.groupBy(identity).mapValues(_.size)) } - forwardFlow.zip(reverseFlow).map { case (s, i) => FlowInfo(s, i, labelMap) }.zip(code) + val holder = new FlowHolder(forwardFlow, reverseFlow) + code.zipWithIndex.map{ case (line, i) => FlowInfo(holder, i, labelMap) -> line} } }