mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-23 23:30:22 +00:00
Fix stack overflow
This commit is contained in:
parent
59784ad5f1
commit
4e04725f93
@ -8,6 +8,7 @@ import millfork.assembly.mos.{AssemblyLine, AssemblyLine0, OpcodeClasses}
|
||||
import millfork.assembly.opt.SingleStatus
|
||||
import millfork.env._
|
||||
import millfork.error.{ConsoleLogger, Logger}
|
||||
import scala.util.control.TailCalls.{TailRec, done, tailcall}
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
@ -37,7 +38,7 @@ object LocalVariableReadOptimization extends AssemblyOptimization[AssemblyLine]
|
||||
}
|
||||
|
||||
val statuses = CoarseFlowAnalyzer.analyze(f, code, optimizationContext)
|
||||
val (optimized, result) = optimizeImpl(code.zip(statuses), eligibleVariables, Map())
|
||||
val (optimized, result) = optimizeImpl(code.zip(statuses), eligibleVariables, Map()).result
|
||||
if (optimized) {
|
||||
optimizationContext.log.debug("Optimized local variable reads")
|
||||
reportOptimizedBlock(optimizationContext.log, code, result)
|
||||
@ -51,17 +52,17 @@ object LocalVariableReadOptimization extends AssemblyOptimization[AssemblyLine]
|
||||
def ::(head: AssemblyLine): (Boolean, List[AssemblyLine]) = (tuple._1, head :: tuple._2)
|
||||
}
|
||||
|
||||
def optimizeImpl(code: List[(AssemblyLine, CpuStatus)], variables: Set[String], map: Map[String, Int]): (Boolean, List[AssemblyLine]) = code match {
|
||||
def optimizeImpl(code: List[(AssemblyLine, CpuStatus)], variables: Set[String], map: Map[String, Int]): TailRec[(Boolean, List[AssemblyLine])] = code match {
|
||||
|
||||
case (x@AssemblyLine0(JSR, Absolute, MemoryAddressConstant(th)), _) :: xs if th.name.startsWith(".") =>
|
||||
x :: optimizeImpl(xs, variables, Map())
|
||||
tailcall(optimizeImpl(xs, variables, Map())).map(x :: _)
|
||||
|
||||
case (AssemblyLine(op@(
|
||||
LDA | LDX | LDY | LDZ |
|
||||
ADC | ORA | EOR | AND | SBC |
|
||||
CMP | CPX | CPY | CPZ), Absolute | ZeroPage, MemoryAddressConstant(th), Elidability.Elidable, s), _) :: xs
|
||||
if variables(th.name) && map.contains(th.name) =>
|
||||
true -> (AssemblyLine.immediate(op, map(th.name)).pos(s) :: optimizeImpl(xs, variables, map)._2)
|
||||
tailcall(optimizeImpl(xs, variables, map)).map(t => true -> (AssemblyLine.immediate(op, map(th.name)).pos(s) :: t._2))
|
||||
|
||||
case (x@AssemblyLine0(STA, Absolute | ZeroPage, MemoryAddressConstant(th)), status) :: xs
|
||||
if variables(th.name) =>
|
||||
@ -69,7 +70,7 @@ object LocalVariableReadOptimization extends AssemblyOptimization[AssemblyLine]
|
||||
case SingleStatus(n) => map + (th.name -> n)
|
||||
case _ => map - th.name
|
||||
}
|
||||
x :: optimizeImpl(xs, variables, newMap)
|
||||
tailcall(optimizeImpl(xs, variables, newMap)).map(x :: _)
|
||||
|
||||
case (x@AssemblyLine0(STX, Absolute | ZeroPage, MemoryAddressConstant(th)), status) :: xs
|
||||
if variables(th.name) =>
|
||||
@ -77,7 +78,7 @@ object LocalVariableReadOptimization extends AssemblyOptimization[AssemblyLine]
|
||||
case SingleStatus(n) => map + (th.name -> n)
|
||||
case _ => map - th.name
|
||||
}
|
||||
x :: optimizeImpl(xs, variables, newMap)
|
||||
tailcall(optimizeImpl(xs, variables, newMap)).map(x :: _)
|
||||
|
||||
case (x@AssemblyLine0(STY, Absolute | ZeroPage, MemoryAddressConstant(th: ThingInMemory)), status) :: xs
|
||||
if variables(th.name) =>
|
||||
@ -85,7 +86,7 @@ object LocalVariableReadOptimization extends AssemblyOptimization[AssemblyLine]
|
||||
case SingleStatus(n) => map + (th.name -> n)
|
||||
case _ => map - th.name
|
||||
}
|
||||
x :: optimizeImpl(xs, variables, newMap)
|
||||
tailcall(optimizeImpl(xs, variables, newMap)).map(x :: _)
|
||||
|
||||
case (x@AssemblyLine0(STZ, Absolute | ZeroPage, MemoryAddressConstant(th)), status) :: xs
|
||||
if variables(th.name) =>
|
||||
@ -93,7 +94,7 @@ object LocalVariableReadOptimization extends AssemblyOptimization[AssemblyLine]
|
||||
case SingleStatus(n) => map + (th.name -> n)
|
||||
case _ => map - th.name
|
||||
}
|
||||
x :: optimizeImpl(xs, variables, newMap)
|
||||
tailcall(optimizeImpl(xs, variables, newMap)).map(x :: _)
|
||||
|
||||
case (x@AssemblyLine0(SAX, Absolute | ZeroPage, MemoryAddressConstant(th)), status) :: xs
|
||||
if variables(th.name) =>
|
||||
@ -103,32 +104,32 @@ object LocalVariableReadOptimization extends AssemblyOptimization[AssemblyLine]
|
||||
case (SingleStatus(0), _) => map + (th.name -> 0)
|
||||
case _ => map - th.name
|
||||
}
|
||||
x :: optimizeImpl(xs, variables, newMap)
|
||||
tailcall(optimizeImpl(xs, variables, newMap)).map(x :: _)
|
||||
|
||||
case (x@AssemblyLine0(INC | ISC, Absolute | ZeroPage, MemoryAddressConstant(th)), _) :: xs
|
||||
if map.contains(th.name) =>
|
||||
x :: optimizeImpl(xs, variables, map + (th.name -> map(th.name).+(1).&(0xff)))
|
||||
tailcall(optimizeImpl(xs, variables, map + (th.name -> map(th.name).+(1).&(0xff)))).map(x :: _)
|
||||
|
||||
case (x@AssemblyLine0(DEC | DCP, Absolute | ZeroPage, MemoryAddressConstant(th)), _) :: xs
|
||||
if map.contains(th.name) =>
|
||||
x :: optimizeImpl(xs, variables, map + (th.name -> map(th.name).-(1).&(0xff)))
|
||||
tailcall(optimizeImpl(xs, variables, map + (th.name -> map(th.name).-(1).&(0xff)))).map(x :: _)
|
||||
|
||||
case (x@AssemblyLine0(ASL | SLO, Absolute | ZeroPage, MemoryAddressConstant(th)), _) :: xs
|
||||
if map.contains(th.name) =>
|
||||
x :: optimizeImpl(xs, variables, map + (th.name -> map(th.name).<<(1).&(0xff)))
|
||||
tailcall(optimizeImpl(xs, variables, map + (th.name -> map(th.name).<<(1).&(0xff)))).map(x :: _)
|
||||
|
||||
case (x@AssemblyLine0(LSR | SRE, Absolute | ZeroPage, MemoryAddressConstant(th)), _) :: xs
|
||||
if map.contains(th.name) =>
|
||||
x :: optimizeImpl(xs, variables, map + (th.name -> map(th.name).&(0xff).>>(1)))
|
||||
tailcall(optimizeImpl(xs, variables, map + (th.name -> map(th.name).&(0xff).>>(1)))).map(x :: _)
|
||||
|
||||
// TODO: consider handling some more opcodes
|
||||
case (x@AssemblyLine0(op, Absolute | ZeroPage, MemoryAddressConstant(th)), _) :: xs
|
||||
if (OpcodeClasses.ChangesMemoryAlways(op) || OpcodeClasses.ChangesMemoryIfNotImplied(op)) && map.contains(th.name) =>
|
||||
x :: optimizeImpl(xs, variables, map - th.name)
|
||||
tailcall(optimizeImpl(xs, variables, map - th.name)).map(x :: _)
|
||||
|
||||
case (x@AssemblyLine0(LABEL, _, _), _) :: xs => x :: optimizeImpl(xs, variables, Map())
|
||||
case (x, _) :: xs => x :: optimizeImpl(xs, variables, map)
|
||||
case Nil => (false, Nil)
|
||||
case (x@AssemblyLine0(LABEL, _, _), _) :: xs => tailcall(optimizeImpl(xs, variables, Map())).map(x :: _)
|
||||
case (x, _) :: xs => tailcall(optimizeImpl(xs, variables, map)).map(x :: _)
|
||||
case Nil => done(false -> Nil)
|
||||
}
|
||||
|
||||
def reportOptimizedBlock(log: Logger, oldCode: List[AssemblyLine], newCode: List[AssemblyLine]): Unit = {
|
||||
|
Loading…
Reference in New Issue
Block a user