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:
parent
36a0065b96
commit
76dd4929a6
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
24
src/main/scala/millfork/env/Environment.scala
vendored
24
src/main/scala/millfork/env/Environment.scala
vendored
@ -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")) {
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user