1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-12-25 21:29:25 +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 // 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 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( result.registerVariable(VariableDeclarationStatement(
v.name, v.typ.name, v.name, v.typ.name,
stack = false, global = false, constant = false, volatile = false, register = false, 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) ctx.copy(env = result)
} }

View File

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

View File

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

View File

@ -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 = { 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 w = get[Type]("word")
val name = stmt.name val name = stmt.name
val resultType = get[Type](stmt.resultType) 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)) { 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 { stmt.statements match {
case None => case None =>
@ -806,7 +816,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
case Some(statements) => case Some(statements) =>
statements.foreach { statements.foreach {
case v: VariableDeclarationStatement => env.registerVariable(v, options) case v: VariableDeclarationStatement => env.registerVariable(v, options, pointies(v.name))
case _ => () case _ => ()
} }
val executableStatements = statements.flatMap { 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 name = stmt.name
val position = stmt.position val position = stmt.position
if (stmt.stack && parent.isEmpty) { if (stmt.stack && parent.isEmpty) {
@ -1160,7 +1170,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
} else { } else {
val (v, addr) = stmt.address.fold[(VariableInMemory, Constant)]({ val (v, addr) = stmt.address.fold[(VariableInMemory, Constant)]({
val alloc = 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.global) VariableAllocationMethod.Static
else if (stmt.register) VariableAllocationMethod.Register else if (stmt.register) VariableAllocationMethod.Register
else VariableAllocationMethod.Auto else VariableAllocationMethod.Auto
@ -1280,9 +1290,11 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
case e: EnumDefinitionStatement => registerEnum(e) case e: EnumDefinitionStatement => registerEnum(e)
case _ => case _ =>
} }
val pointies = collectPointies(program.declarations)
pointiesUsed("") = pointies
program.declarations.foreach { program.declarations.foreach {
case f: FunctionDeclarationStatement => registerFunction(f, options) 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 a: ArrayDeclarationStatement => registerArray(a, options)
case _ => case _ =>
} }
@ -1299,7 +1311,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
register = false, register = false,
initialValue = None, initialValue = None,
address = None, address = None,
alignment = None), options) alignment = None), options, isPointy = true)
} }
if (CpuFamily.forType(options.platform.cpu) == CpuFamily.M6502) { if (CpuFamily.forType(options.platform.cpu) == CpuFamily.M6502) {
if (!things.contains("__constant8")) { if (!things.contains("__constant8")) {

View File

@ -30,6 +30,7 @@ object Node {
sealed trait Expression extends Node { sealed trait Expression extends Node {
def replaceVariable(variable: String, actualParam: Expression): Expression def replaceVariable(variable: String, actualParam: Expression): Expression
def containsVariable(variable: String): Boolean def containsVariable(variable: String): Boolean
def getPointies: Seq[String]
def isPure: Boolean def isPure: Boolean
def getAllIdentifiers: Set[String] def getAllIdentifiers: Set[String]
} }
@ -37,6 +38,7 @@ sealed trait Expression extends Node {
case class ConstantArrayElementExpression(constant: Constant) extends Expression { case class ConstantArrayElementExpression(constant: Constant) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this override def replaceVariable(variable: String, actualParam: Expression): Expression = this
override def containsVariable(variable: String): Boolean = false override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty 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 { case class LiteralExpression(value: Long, requiredSize: Int) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this override def replaceVariable(variable: String, actualParam: Expression): Expression = this
override def containsVariable(variable: String): Boolean = false override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty 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 { case class TextLiteralExpression(characters: List[Expression]) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this override def replaceVariable(variable: String, actualParam: Expression): Expression = this
override def containsVariable(variable: String): Boolean = false override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty 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 { case class GeneratedConstantExpression(value: Constant, typ: Type) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this override def replaceVariable(variable: String, actualParam: Expression): Expression = this
override def containsVariable(variable: String): Boolean = false override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty 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 { case class BooleanLiteralExpression(value: Boolean) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this override def replaceVariable(variable: String, actualParam: Expression): Expression = this
override def containsVariable(variable: String): Boolean = false override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty override def getAllIdentifiers: Set[String] = Set.empty
} }
@ -74,6 +80,7 @@ sealed trait LhsExpression extends Expression
case object BlackHoleExpression extends LhsExpression { case object BlackHoleExpression extends LhsExpression {
override def replaceVariable(variable: String, actualParam: Expression): LhsExpression = this override def replaceVariable(variable: String, actualParam: Expression): LhsExpression = this
override def containsVariable(variable: String): Boolean = false override def containsVariable(variable: String): Boolean = false
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set.empty override def getAllIdentifiers: Set[String] = Set.empty
} }
@ -84,6 +91,7 @@ case class SeparateBytesExpression(hi: Expression, lo: Expression) extends LhsEx
hi.replaceVariable(variable, actualParam), hi.replaceVariable(variable, actualParam),
lo.replaceVariable(variable, actualParam)).pos(position) lo.replaceVariable(variable, actualParam)).pos(position)
override def containsVariable(variable: String): Boolean = hi.containsVariable(variable) || lo.containsVariable(variable) 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 isPure: Boolean = hi.isPure && lo.isPure
override def getAllIdentifiers: Set[String] = hi.getAllIdentifiers ++ lo.getAllIdentifiers 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 = override def replaceVariable(variable: String, actualParam: Expression): Expression =
SumExpression(expressions.map { case (n, e) => n -> e.replaceVariable(variable, actualParam) }, decimal).pos(position) 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 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 isPure: Boolean = expressions.forall(_._2.isPure)
override def getAllIdentifiers: Set[String] = expressions.map(_._2.getAllIdentifiers).fold(Set[String]())(_ ++ _) 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) _.replaceVariable(variable, actualParam)
}).pos(position) }).pos(position)
override def containsVariable(variable: String): Boolean = expressions.exists(_.containsVariable(variable)) 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 isPure: Boolean = false // TODO
override def getAllIdentifiers: Set[String] = expressions.map(_.getAllIdentifiers).fold(Set[String]())(_ ++ _) + functionName 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 = override def replaceVariable(variable: String, actualParam: Expression): Expression =
HalfWordExpression(expression.replaceVariable(variable, actualParam), hiByte).pos(position) HalfWordExpression(expression.replaceVariable(variable, actualParam), hiByte).pos(position)
override def containsVariable(variable: String): Boolean = expression.containsVariable(variable) override def containsVariable(variable: String): Boolean = expression.containsVariable(variable)
override def getPointies: Seq[String] = expression.getPointies
override def isPure: Boolean = expression.isPure override def isPure: Boolean = expression.isPure
override def getAllIdentifiers: Set[String] = expression.getAllIdentifiers 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 = override def replaceVariable(variable: String, actualParam: Expression): Expression =
if (name == variable) actualParam else this if (name == variable) actualParam else this
override def containsVariable(variable: String): Boolean = name == variable override def containsVariable(variable: String): Boolean = name == variable
override def getPointies: Seq[String] = Seq.empty
override def isPure: Boolean = true override def isPure: Boolean = true
override def getAllIdentifiers: Set[String] = Set(name) 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) } else IndexedExpression(name, index.replaceVariable(variable, actualParam)).pos(position)
override def containsVariable(variable: String): Boolean = name == variable || index.containsVariable(variable) 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 isPure: Boolean = index.isPure
override def getAllIdentifiers: Set[String] = index.getAllIdentifiers + name override def getAllIdentifiers: Set[String] = index.getAllIdentifiers + name
} }
sealed trait Statement extends Node { sealed trait Statement extends Node {
def getAllExpressions: List[Expression] def getAllExpressions: List[Expression]
def getAllPointies: Seq[String] = getAllExpressions.flatMap(_.getPointies)
} }
sealed trait DeclarationStatement extends Statement { 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 { 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 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 { case class Z80AssemblyStatement(opcode: ZOpcode.Value, registers: ZRegisters, offsetExpression: Option[Expression], expression: Expression, elidability: Elidability.Value) extends ExecutableStatement {