mirror of
https://github.com/KarolS/millfork.git
synced 2024-09-10 11:54:30 +00:00
Fixed allocating allocating local variables twice
This commit is contained in:
parent
7eab7c439e
commit
cdfbbf61b8
11
src/main/scala/millfork/env/Environment.scala
vendored
11
src/main/scala/millfork/env/Environment.scala
vendored
@ -79,6 +79,15 @@ class Environment(val parent: Option[Environment], val prefix: String) {
|
|||||||
}.toList
|
}.toList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def isLocalVariableName(name: String): Boolean = name.contains('$') && !name.endsWith("$") && {
|
||||||
|
val fname = name.substring(0, name.indexOf('$'))
|
||||||
|
things.get(fname) -> parent.flatMap(_.things.get(fname)) match {
|
||||||
|
case (Some(_: NormalFunction), _) => true
|
||||||
|
case (_, Some(_: NormalFunction)) => true
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def allocateVariables(nf: Option[NormalFunction], mem: CompiledMemory, callGraph: CallGraph, allocators: Map[String, VariableAllocator], options: CompilationOptions, onEachVariable: (String, Int) => Unit): Unit = {
|
def allocateVariables(nf: Option[NormalFunction], mem: CompiledMemory, callGraph: CallGraph, allocators: Map[String, VariableAllocator], options: CompilationOptions, onEachVariable: (String, Int) => Unit): Unit = {
|
||||||
val b = get[Type]("byte")
|
val b = get[Type]("byte")
|
||||||
val p = get[Type]("pointer")
|
val p = get[Type]("pointer")
|
||||||
@ -91,7 +100,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
|
|||||||
}
|
}
|
||||||
}.toSet
|
}.toSet
|
||||||
val toAdd = things.values.flatMap {
|
val toAdd = things.values.flatMap {
|
||||||
case m: UninitializedMemory =>
|
case m: UninitializedMemory if nf.isDefined == isLocalVariableName(m.name) =>
|
||||||
val vertex = if (options.flag(CompilationFlag.VariableOverlap)) {
|
val vertex = if (options.flag(CompilationFlag.VariableOverlap)) {
|
||||||
nf.fold[VariableVertex](GlobalVertex) { f =>
|
nf.fold[VariableVertex](GlobalVertex) { f =>
|
||||||
if (m.alloc == VariableAllocationMethod.Static) {
|
if (m.alloc == VariableAllocationMethod.Static) {
|
||||||
|
@ -4,6 +4,7 @@ import millfork.error.ErrorReporting
|
|||||||
import millfork.node.{CallGraph, VariableVertex}
|
import millfork.node.{CallGraph, VariableVertex}
|
||||||
import millfork.{CompilationFlag, CompilationOptions}
|
import millfork.{CompilationFlag, CompilationOptions}
|
||||||
|
|
||||||
|
import scala.annotation.tailrec
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,10 +50,10 @@ class AfterCodeByteAllocator(val endBefore: Int) extends ByteAllocator {
|
|||||||
def notifyAboutEndOfCode(org: Int): Unit = startAt = org
|
def notifyAboutEndOfCode(org: Int): Unit = startAt = org
|
||||||
}
|
}
|
||||||
|
|
||||||
class VariableAllocator(private var pointers: List[Int], private val bytes: ByteAllocator) {
|
class VariableAllocator(private val pointers: List[Int], private val bytes: ByteAllocator) {
|
||||||
|
|
||||||
private var pointerMap = mutable.Map[Int, Set[VariableVertex]]()
|
private val pointerMap = mutable.Map[Int, Set[VariableVertex]]()
|
||||||
private var variableMap = mutable.Map[Int, mutable.Map[Int, Set[VariableVertex]]]()
|
private val variableMap = mutable.Map[Int, mutable.Map[Int, Set[VariableVertex]]]()
|
||||||
|
|
||||||
def allocatePointer(mem: MemoryBank, callGraph: CallGraph, p: VariableVertex): Int = {
|
def allocatePointer(mem: MemoryBank, callGraph: CallGraph, p: VariableVertex): Int = {
|
||||||
// TODO: search for free zeropage locations
|
// TODO: search for free zeropage locations
|
||||||
@ -62,16 +63,16 @@ class VariableAllocator(private var pointers: List[Int], private val bytes: Byte
|
|||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def pickFreePointer(): Int =
|
@tailrec
|
||||||
pointers match {
|
def pickFreePointer(ps: List[Int]): Int =
|
||||||
|
ps match {
|
||||||
case Nil =>
|
case Nil =>
|
||||||
|
ErrorReporting.trace(pointerMap.mkString(", "))
|
||||||
ErrorReporting.fatal("Out of zero-page memory")
|
ErrorReporting.fatal("Out of zero-page memory")
|
||||||
case next :: rest =>
|
case next :: rest =>
|
||||||
if (mem.occupied(next) || mem.occupied(next + 1)) {
|
if (mem.occupied(next) || mem.occupied(next + 1)) {
|
||||||
pointers = rest
|
pickFreePointer(rest)
|
||||||
pickFreePointer()
|
|
||||||
} else {
|
} else {
|
||||||
pointers = rest
|
|
||||||
mem.readable(next) = true
|
mem.readable(next) = true
|
||||||
mem.readable(next + 1) = true
|
mem.readable(next + 1) = true
|
||||||
mem.occupied(next) = true
|
mem.occupied(next) = true
|
||||||
@ -82,7 +83,7 @@ class VariableAllocator(private var pointers: List[Int], private val bytes: Byte
|
|||||||
next
|
next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pickFreePointer()
|
pickFreePointer(pointers)
|
||||||
}
|
}
|
||||||
|
|
||||||
def allocateBytes(mem: MemoryBank, callGraph: CallGraph, p: VariableVertex, options: CompilationOptions, count: Int, initialized: Boolean, writeable: Boolean): Int = {
|
def allocateBytes(mem: MemoryBank, callGraph: CallGraph, p: VariableVertex, options: CompilationOptions, count: Int, initialized: Boolean, writeable: Boolean): Int = {
|
||||||
|
Loading…
Reference in New Issue
Block a user