1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-12-25 06:29:17 +00:00

6502: Track which pointers need to be on zeropage

This commit is contained in:
Karol Stasiak 2018-12-21 22:36:05 +01:00
parent 36a0065b96
commit 76dd4929a6
5 changed files with 45 additions and 12 deletions

View File

@ -27,12 +27,13 @@ class AbstractExpressionCompiler[T <: AbstractCode] {
// TODO
}
def callingContext(ctx: CompilationContext, v: MemoryVariable): CompilationContext = {
def callingContext(ctx: CompilationContext, callee: String, v: MemoryVariable): CompilationContext = {
val result = new Environment(Some(ctx.env), "", ctx.options.platform.cpuFamily, ctx.jobContext)
val isPointy = ctx.env.isKnownPointy(callee, v.name.stripPrefix(callee + '$'))
result.registerVariable(VariableDeclarationStatement(
v.name, v.typ.name,
stack = false, global = false, constant = false, volatile = false, register = false,
initialValue = None, address = None, bank = v.declaredBank, alignment = None), ctx.options)
initialValue = None, address = None, bank = v.declaredBank, alignment = None), ctx.options, isPointy = isPointy)
ctx.copy(env = result)
}

View File

@ -1166,7 +1166,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case NormalParamSignature(paramVars) =>
params.zip(paramVars).flatMap {
case (paramExpr, paramVar) =>
val callCtx = callingContext(ctx, paramVar)
val callCtx = callingContext(ctx, function.name, paramVar)
compileAssignment(callCtx, paramExpr, VariableExpression(paramVar.name))
} ++ List(AssemblyLine.absoluteOrLongAbsolute(JSR, function, ctx.options))
}

View File

@ -895,7 +895,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
case NormalParamSignature(paramVars) =>
params.zip(paramVars).flatMap {
case (paramExpr, paramVar) =>
val callCtx = callingContext(ctx, paramVar)
val callCtx = callingContext(ctx, function.name, paramVar)
paramVar.typ.size match {
case 1 =>
compileToA(ctx, paramExpr) ++ storeA(callCtx, VariableExpression(paramVar.name), paramVar.typ.isSigned)

View File

@ -210,8 +210,8 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
private def addThing(t: Thing, position: Option[Position]): Unit = {
if (assertNotDefined(t.name, position)) {
things(t.name.stripPrefix(prefix)) = t
}
things(t.name.stripPrefix(prefix)) = t
}
}
def removeVariable(str: String): Unit = {
@ -726,7 +726,17 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
}
}
def collectPointies(stmts: Seq[Statement]): Set[String] = {
val pointies: mutable.Set[String] = new mutable.HashSet()
pointies ++= stmts.flatMap(_.getAllPointies)
pointies ++ getAliases.filterKeys(pointies).values
log.trace("Collected pointies: " + pointies)
pointies.toSet
}
def registerFunction(stmt: FunctionDeclarationStatement, options: CompilationOptions): Unit = {
val pointies = collectPointies(stmt.statements.getOrElse(Seq.empty))
pointiesUsed(stmt.name) = pointies
val w = get[Type]("word")
val name = stmt.name
val resultType = get[Type](stmt.resultType)
@ -782,7 +792,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
})
}
if (resultType.size > Cpu.getMaxSizeReturnableViaRegisters(options.platform.cpu, options)) {
registerVariable(VariableDeclarationStatement(stmt.name + ".return", stmt.resultType, None, global = true, stack = false, constant = false, volatile = false, register = false, None, None, None), options)
registerVariable(VariableDeclarationStatement(stmt.name + ".return", stmt.resultType, None, global = true, stack = false, constant = false, volatile = false, register = false, None, None, None), options, isPointy = false)
}
stmt.statements match {
case None =>
@ -806,7 +816,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
case Some(statements) =>
statements.foreach {
case v: VariableDeclarationStatement => env.registerVariable(v, options)
case v: VariableDeclarationStatement => env.registerVariable(v, options, pointies(v.name))
case _ => ()
}
val executableStatements = statements.flatMap {
@ -1108,7 +1118,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
}
}
def registerVariable(stmt: VariableDeclarationStatement, options: CompilationOptions): Unit = {
def registerVariable(stmt: VariableDeclarationStatement, options: CompilationOptions, isPointy: Boolean): Unit = {
val name = stmt.name
val position = stmt.position
if (stmt.stack && parent.isEmpty) {
@ -1160,7 +1170,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
} else {
val (v, addr) = stmt.address.fold[(VariableInMemory, Constant)]({
val alloc =
if (typ.name == "pointer" || typ.name == "__reg$type") VariableAllocationMethod.Zeropage
if (isPointy || typ.name == "__reg$type") VariableAllocationMethod.Zeropage
else if (stmt.global) VariableAllocationMethod.Static
else if (stmt.register) VariableAllocationMethod.Register
else VariableAllocationMethod.Auto
@ -1280,9 +1290,11 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
case e: EnumDefinitionStatement => registerEnum(e)
case _ =>
}
val pointies = collectPointies(program.declarations)
pointiesUsed("") = pointies
program.declarations.foreach {
case f: FunctionDeclarationStatement => registerFunction(f, options)
case v: VariableDeclarationStatement => registerVariable(v, options)
case v: VariableDeclarationStatement => registerVariable(v, options, pointies(v.name))
case a: ArrayDeclarationStatement => registerArray(a, options)
case _ =>
}
@ -1299,7 +1311,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
register = false,
initialValue = None,
address = None,
alignment = None), options)
alignment = None), options, isPointy = true)
}
if (CpuFamily.forType(options.platform.cpu) == CpuFamily.M6502) {
if (!things.contains("__constant8")) {

View File

@ -30,6 +30,7 @@ object Node {
sealed trait Expression extends Node {
def replaceVariable(variable: String, actualParam: Expression): Expression
def containsVariable(variable: String): Boolean
def getPointies: Seq[String]
def isPure: Boolean
def getAllIdentifiers: Set[String]
}
@ -37,6 +38,7 @@ sealed trait Expression extends Node {
case class ConstantArrayElementExpression(constant: Constant) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this
override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty
}
@ -44,6 +46,7 @@ case class ConstantArrayElementExpression(constant: Constant) extends Expression
case class LiteralExpression(value: Long, requiredSize: Int) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this
override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty
}
@ -51,6 +54,7 @@ case class LiteralExpression(value: Long, requiredSize: Int) extends Expression
case class TextLiteralExpression(characters: List[Expression]) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this
override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty
}
@ -58,6 +62,7 @@ case class TextLiteralExpression(characters: List[Expression]) extends Expressio
case class GeneratedConstantExpression(value: Constant, typ: Type) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this
override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty
}
@ -65,6 +70,7 @@ case class GeneratedConstantExpression(value: Constant, typ: Type) extends Expre
case class BooleanLiteralExpression(value: Boolean) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this
override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty
}
@ -74,6 +80,7 @@ sealed trait LhsExpression extends Expression
case object BlackHoleExpression extends LhsExpression {
override def replaceVariable(variable: String, actualParam: Expression): LhsExpression = this
override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty
}
@ -84,6 +91,7 @@ case class SeparateBytesExpression(hi: Expression, lo: Expression) extends LhsEx
hi.replaceVariable(variable, actualParam),
lo.replaceVariable(variable, actualParam)).pos(position)
override def containsVariable(variable: String): Boolean = hi.containsVariable(variable) || lo.containsVariable(variable)
override def getPointies: Seq[String] = hi.getPointies ++ lo.getPointies
override def isPure: Boolean = hi.isPure && lo.isPure
override def getAllIdentifiers: Set[String] = hi.getAllIdentifiers ++ lo.getAllIdentifiers
}
@ -92,6 +100,7 @@ case class SumExpression(expressions: List[(Boolean, Expression)], decimal: Bool
override def replaceVariable(variable: String, actualParam: Expression): Expression =
SumExpression(expressions.map { case (n, e) => n -> e.replaceVariable(variable, actualParam) }, decimal).pos(position)
override def containsVariable(variable: String): Boolean = expressions.exists(_._2.containsVariable(variable))
override def getPointies: Seq[String] = expressions.flatMap(_._2.getPointies)
override def isPure: Boolean = expressions.forall(_._2.isPure)
override def getAllIdentifiers: Set[String] = expressions.map(_._2.getAllIdentifiers).fold(Set[String]())(_ ++ _)
}
@ -102,6 +111,7 @@ case class FunctionCallExpression(functionName: String, expressions: List[Expres
_.replaceVariable(variable, actualParam)
}).pos(position)
override def containsVariable(variable: String): Boolean = expressions.exists(_.containsVariable(variable))
override def getPointies: Seq[String] = expressions.flatMap(_.getPointies)
override def isPure: Boolean = false // TODO
override def getAllIdentifiers: Set[String] = expressions.map(_.getAllIdentifiers).fold(Set[String]())(_ ++ _) + functionName
}
@ -110,6 +120,7 @@ case class HalfWordExpression(expression: Expression, hiByte: Boolean) extends E
override def replaceVariable(variable: String, actualParam: Expression): Expression =
HalfWordExpression(expression.replaceVariable(variable, actualParam), hiByte).pos(position)
override def containsVariable(variable: String): Boolean = expression.containsVariable(variable)
override def getPointies: Seq[String] = expression.getPointies
override def isPure: Boolean = expression.isPure
override def getAllIdentifiers: Set[String] = expression.getAllIdentifiers
}
@ -170,6 +181,7 @@ case class VariableExpression(name: String) extends LhsExpression {
override def replaceVariable(variable: String, actualParam: Expression): Expression =
if (name == variable) actualParam else this
override def containsVariable(variable: String): Boolean = name == variable
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set(name)
}
@ -184,12 +196,14 @@ case class IndexedExpression(name: String, index: Expression) extends LhsExpress
}
} else IndexedExpression(name, index.replaceVariable(variable, actualParam)).pos(position)
override def containsVariable(variable: String): Boolean = name == variable || index.containsVariable(variable)
override def getPointies: Seq[String] = Seq(name)
override def isPure: Boolean = index.isPure
override def getAllIdentifiers: Set[String] = index.getAllIdentifiers + name
}
sealed trait Statement extends Node {
def getAllExpressions: List[Expression]
def getAllPointies: Seq[String] = getAllExpressions.flatMap(_.getPointies)
}
sealed trait DeclarationStatement extends Statement {
@ -357,6 +371,12 @@ case class Assignment(destination: LhsExpression, source: Expression) extends Ex
case class MosAssemblyStatement(opcode: Opcode.Value, addrMode: AddrMode.Value, expression: Expression, elidability: Elidability.Value) extends ExecutableStatement {
override def getAllExpressions: List[Expression] = List(expression)
override def getAllPointies: Seq[String] = addrMode match {
case AddrMode.IndexedY | AddrMode.IndexedX | AddrMode.LongIndexedY | AddrMode.IndexedZ | AddrMode.LongIndexedZ |
AddrMode.ZeroPage | AddrMode.ZeroPageX | AddrMode.ZeroPageY =>
expression.getAllIdentifiers.toSeq.map(_.takeWhile(_ != '.'))
case _ => Seq.empty
}
}
case class Z80AssemblyStatement(opcode: ZOpcode.Value, registers: ZRegisters, offsetExpression: Option[Expression], expression: Expression, elidability: Elidability.Value) extends ExecutableStatement {