mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-22 16:31:02 +00:00
Better tracking of the original source
This commit is contained in:
parent
4fb786522d
commit
8fcf628c8f
@ -49,6 +49,8 @@ Choose syntax for assembly output on 8080-like targets.
|
||||
|
||||
* `-fline-numbers`, `-fno-line-numbers` – Whether should show source line numbers in assembly output.
|
||||
|
||||
* `-fline-numbers`, `-fno-line-numbers` – Whether should show the original source in assembly output. Implies `-fline-numbers`
|
||||
|
||||
## Verbosity options
|
||||
|
||||
* `-q` – Suppress all messages except for errors.
|
||||
|
@ -50,6 +50,8 @@ You may be also interested in the following:
|
||||
* `-s` – additionally generate assembly output
|
||||
(if targeting Intel 8080, use `--syntax=intel` or `--syntax=zilog` to choose the preferred assembly syntax)
|
||||
|
||||
* `-fsource-in-asm` – show original Millfork source in the assembly output
|
||||
|
||||
* `-g` – additionally generate a label file, in format compatible with VICE emulator
|
||||
|
||||
* `-r PROGRAM` – automatically launch given program after successful compilation
|
||||
|
@ -304,7 +304,7 @@ object Cpu extends Enumeration {
|
||||
object CompilationFlag extends Enumeration {
|
||||
val
|
||||
// common compilation options:
|
||||
EmitIllegals, DecimalMode, ReadOnlyArrays, LenientTextEncoding, LineNumbersInAssembly,
|
||||
EmitIllegals, DecimalMode, ReadOnlyArrays, LenientTextEncoding, LineNumbersInAssembly, SourceInAssembly,
|
||||
// compilation options for MOS:
|
||||
EmitCmosOpcodes, EmitCmosNopOpcodes, EmitHudsonOpcodes, Emit65CE02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes,
|
||||
PreventJmpIndirectBug, LargeCode, ReturnWordsViaAccumulator, SoftwareStack,
|
||||
|
@ -239,6 +239,7 @@ object Main {
|
||||
result
|
||||
}
|
||||
|
||||
//noinspection NameBooleanParameters
|
||||
private def parser(errorReporting: Logger): CliParser[Context] = new CliParser[Context] {
|
||||
|
||||
fluff("Main options:", "")
|
||||
@ -302,6 +303,14 @@ object Main {
|
||||
c.changeFlag(CompilationFlag.LineNumbersInAssembly, v)
|
||||
).description("Show source line numbers in assembly.")
|
||||
|
||||
boolean("-fsource-in-asm", "-fno-source-in-asm").action((c,v) =>
|
||||
if (v) {
|
||||
c.changeFlag(CompilationFlag.SourceInAssembly, true).changeFlag(CompilationFlag.LineNumbersInAssembly, true)
|
||||
} else {
|
||||
c.changeFlag(CompilationFlag.LineNumbersInAssembly, false)
|
||||
}
|
||||
).description("Show source in assembly.")
|
||||
|
||||
endOfFlags("--").description("Marks the end of options.")
|
||||
|
||||
fluff("", "Verbosity options:", "")
|
||||
|
@ -222,6 +222,8 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
||||
|
||||
def position(s: Option[Position]): ZLine = pos(SourceLine.of(s))
|
||||
|
||||
def positionIfEmpty(s: Option[Position]): ZLine = if (s.isEmpty || source.isDefined) this else pos(SourceLine.of(s))
|
||||
|
||||
def pos(s: Seq[Option[SourceLine]]): ZLine = pos(SourceLine.merge(s))
|
||||
|
||||
def mergePos(s: Seq[Option[SourceLine]]): ZLine = if (s.isEmpty) this else pos(SourceLine.merge(this.source, s))
|
||||
|
@ -25,7 +25,7 @@ abstract class MacroExpander[T <: AbstractCode] {
|
||||
|
||||
def h(s: String) = if (s == paramName) target.asInstanceOf[VariableExpression].name else s
|
||||
|
||||
stmt match {
|
||||
(stmt match {
|
||||
case RawBytesStatement(contents) => RawBytesStatement(contents.replaceVariable(paramName, target))
|
||||
case ExpressionStatement(e) => ExpressionStatement(e.replaceVariable(paramName, target))
|
||||
case ReturnStatement(e) => ReturnStatement(e.map(f))
|
||||
@ -45,7 +45,7 @@ abstract class MacroExpander[T <: AbstractCode] {
|
||||
case _ =>
|
||||
println(stmt)
|
||||
???
|
||||
}
|
||||
}).pos(stmt.position)
|
||||
}
|
||||
|
||||
def inlineFunction(ctx: CompilationContext, i: MacroFunction, params: List[Expression], position: Option[Position]): (List[T], List[ExecutableStatement]) = {
|
||||
|
@ -192,7 +192,7 @@ object Z80StatementCompiler extends AbstractStatementCompiler[ZLine] {
|
||||
case _ => reg
|
||||
}
|
||||
List(ZLine(op, registers, param, elidability))
|
||||
}).map(_.position(statement.position))
|
||||
}).map(_.positionIfEmpty(statement.position))
|
||||
}
|
||||
|
||||
private def fixStackOnReturn(ctx: CompilationContext): List[ZLine] = {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package millfork.error
|
||||
|
||||
import millfork.assembly.SourceLine
|
||||
import millfork.node.Position
|
||||
|
||||
import scala.collection.mutable
|
||||
@ -117,4 +118,8 @@ class ConsoleLogger extends Logger {
|
||||
sourceLines(filename) = lines
|
||||
}
|
||||
|
||||
override def getLine(line: SourceLine): Option[String] = for {
|
||||
file <- sourceLines.get(line.moduleName)
|
||||
line <- file.lift(line.line - 1)
|
||||
} yield line
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package millfork.error
|
||||
|
||||
import millfork.assembly.SourceLine
|
||||
import millfork.node.Position
|
||||
|
||||
/**
|
||||
@ -27,4 +28,6 @@ class ErrorsOnlyLogger(inner: Logger) extends Logger {
|
||||
override def assertNoErrors(msg: String): Unit = inner.assertNoErrors(msg)
|
||||
|
||||
override def addSource(filename: String, lines: IndexedSeq[String]): Unit = ()
|
||||
|
||||
override def getLine(line: SourceLine): Option[String] = None
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package millfork.error
|
||||
|
||||
import millfork.assembly.SourceLine
|
||||
import millfork.node.Position
|
||||
|
||||
/**
|
||||
@ -28,4 +29,6 @@ trait Logger {
|
||||
def assertNoErrors(msg: String): Unit
|
||||
|
||||
def addSource(filename: String, lines: IndexedSeq[String]): Unit
|
||||
|
||||
def getLine(line: SourceLine): Option[String]
|
||||
}
|
@ -82,7 +82,7 @@ case class SeparateBytesExpression(hi: Expression, lo: Expression) extends LhsEx
|
||||
def replaceVariable(variable: String, actualParam: Expression): Expression =
|
||||
SeparateBytesExpression(
|
||||
hi.replaceVariable(variable, actualParam),
|
||||
lo.replaceVariable(variable, actualParam))
|
||||
lo.replaceVariable(variable, actualParam)).pos(position)
|
||||
override def containsVariable(variable: String): Boolean = hi.containsVariable(variable) || lo.containsVariable(variable)
|
||||
override def isPure: Boolean = hi.isPure && lo.isPure
|
||||
override def getAllIdentifiers: Set[String] = hi.getAllIdentifiers ++ lo.getAllIdentifiers
|
||||
@ -90,7 +90,7 @@ case class SeparateBytesExpression(hi: Expression, lo: Expression) extends LhsEx
|
||||
|
||||
case class SumExpression(expressions: List[(Boolean, Expression)], decimal: Boolean) extends Expression {
|
||||
override def replaceVariable(variable: String, actualParam: Expression): Expression =
|
||||
SumExpression(expressions.map { case (n, e) => n -> e.replaceVariable(variable, actualParam) }, decimal)
|
||||
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 isPure: Boolean = expressions.forall(_._2.isPure)
|
||||
override def getAllIdentifiers: Set[String] = expressions.map(_._2.getAllIdentifiers).fold(Set[String]())(_ ++ _)
|
||||
@ -100,7 +100,7 @@ case class FunctionCallExpression(functionName: String, expressions: List[Expres
|
||||
override def replaceVariable(variable: String, actualParam: Expression): Expression =
|
||||
FunctionCallExpression(functionName, expressions.map {
|
||||
_.replaceVariable(variable, actualParam)
|
||||
})
|
||||
}).pos(position)
|
||||
override def containsVariable(variable: String): Boolean = expressions.exists(_.containsVariable(variable))
|
||||
override def isPure: Boolean = false // TODO
|
||||
override def getAllIdentifiers: Set[String] = expressions.map(_.getAllIdentifiers).fold(Set[String]())(_ ++ _) + functionName
|
||||
@ -108,7 +108,7 @@ case class FunctionCallExpression(functionName: String, expressions: List[Expres
|
||||
|
||||
case class HalfWordExpression(expression: Expression, hiByte: Boolean) extends Expression {
|
||||
override def replaceVariable(variable: String, actualParam: Expression): Expression =
|
||||
HalfWordExpression(expression.replaceVariable(variable, actualParam), hiByte)
|
||||
HalfWordExpression(expression.replaceVariable(variable, actualParam), hiByte).pos(position)
|
||||
override def containsVariable(variable: String): Boolean = expression.containsVariable(variable)
|
||||
override def isPure: Boolean = expression.isPure
|
||||
override def getAllIdentifiers: Set[String] = expression.getAllIdentifiers
|
||||
@ -178,10 +178,11 @@ case class IndexedExpression(name: String, index: Expression) extends LhsExpress
|
||||
override def replaceVariable(variable: String, actualParam: Expression): Expression =
|
||||
if (name == variable) {
|
||||
actualParam match {
|
||||
case VariableExpression(actualVariable) => IndexedExpression(actualVariable, index.replaceVariable(variable, actualParam))
|
||||
case VariableExpression(actualVariable) =>
|
||||
IndexedExpression(actualVariable, index.replaceVariable(variable, actualParam)).pos(position)
|
||||
case _ => ??? // TODO
|
||||
}
|
||||
} else IndexedExpression(name, index.replaceVariable(variable, actualParam))
|
||||
} else IndexedExpression(name, index.replaceVariable(variable, actualParam)).pos(position)
|
||||
override def containsVariable(variable: String): Boolean = name == variable || index.containsVariable(variable)
|
||||
override def isPure: Boolean = index.isPure
|
||||
override def getAllIdentifiers: Set[String] = index.getAllIdentifiers + name
|
||||
|
@ -10,15 +10,15 @@ object UnreachableCode extends NodeOptimization {
|
||||
|
||||
override def optimize(nodes: List[Node], options: CompilationOptions): List[Node] = nodes match {
|
||||
case (x:FunctionDeclarationStatement)::xs =>
|
||||
x.copy(statements = x.statements.map(optimizeStatements(_, options))) :: optimize(xs, options)
|
||||
x.copy(statements = x.statements.map(optimizeStatements(_, options))).pos(x.position) :: optimize(xs, options)
|
||||
case (x:IfStatement)::xs =>
|
||||
x.copy(
|
||||
thenBranch = optimizeExecutableStatements(x.thenBranch, options),
|
||||
elseBranch = optimizeExecutableStatements(x.elseBranch, options)) :: optimize(xs, options)
|
||||
elseBranch = optimizeExecutableStatements(x.elseBranch, options)).pos(x.position) :: optimize(xs, options)
|
||||
case (x:WhileStatement)::xs =>
|
||||
x.copy(body = optimizeExecutableStatements(x.body, options)) :: optimize(xs, options)
|
||||
x.copy(body = optimizeExecutableStatements(x.body, options)).pos(x.position) :: optimize(xs, options)
|
||||
case (x:DoWhileStatement)::xs =>
|
||||
x.copy(body = optimizeExecutableStatements(x.body, options)) :: optimize(xs, options)
|
||||
x.copy(body = optimizeExecutableStatements(x.body, options)).pos(x.position) :: optimize(xs, options)
|
||||
case (x:ReturnStatement) :: xs =>
|
||||
x :: Nil
|
||||
case x :: xs =>
|
||||
|
@ -72,7 +72,7 @@ object UnusedGlobalVariables extends NodeOptimization {
|
||||
params.flatMap {
|
||||
case VariableExpression(_) => None
|
||||
case LiteralExpression(_, _) => None
|
||||
case x => Some(ExpressionStatement(x))
|
||||
case x => Some(ExpressionStatement(x).pos(s.position))
|
||||
}
|
||||
} else Some(s)
|
||||
case s@Assignment(VariableExpression(n), VariableExpression(_)) =>
|
||||
@ -80,35 +80,35 @@ object UnusedGlobalVariables extends NodeOptimization {
|
||||
case s@Assignment(VariableExpression(n), LiteralExpression(_, _)) =>
|
||||
if (globalsToRemove(n)) Nil else Some(s)
|
||||
case s@Assignment(VariableExpression(n), expr) =>
|
||||
if (globalsToRemove(n)) Some(ExpressionStatement(expr)) else Some(s)
|
||||
case s@Assignment(SeparateBytesExpression(VariableExpression(h), VariableExpression(l)), expr) =>
|
||||
if (globalsToRemove(n)) Some(ExpressionStatement(expr).pos(s.position)) else Some(s)
|
||||
case s@Assignment(SeparateBytesExpression(he@VariableExpression(h), le@VariableExpression(l)), expr) =>
|
||||
if (globalsToRemove(h)) {
|
||||
if (globalsToRemove(l))
|
||||
Some(ExpressionStatement(expr))
|
||||
Some(ExpressionStatement(expr).pos(s.position))
|
||||
else
|
||||
Some(Assignment(SeparateBytesExpression(BlackHoleExpression, VariableExpression(l)), expr))
|
||||
Some(Assignment(SeparateBytesExpression(BlackHoleExpression, le).pos(he.position), expr).pos(s.position))
|
||||
} else {
|
||||
if (globalsToRemove(l))
|
||||
Some(Assignment(SeparateBytesExpression(VariableExpression(h), BlackHoleExpression), expr))
|
||||
Some(Assignment(SeparateBytesExpression(he, BlackHoleExpression).pos(he.position), expr).pos(s.position))
|
||||
else
|
||||
Some(s)
|
||||
}
|
||||
case s@Assignment(SeparateBytesExpression(h, VariableExpression(l)), expr) =>
|
||||
if (globalsToRemove(l)) Some(Assignment(SeparateBytesExpression(h, BlackHoleExpression), expr))
|
||||
case s@Assignment(SeparateBytesExpression(h, le@VariableExpression(l)), expr) =>
|
||||
if (globalsToRemove(l)) Some(Assignment(SeparateBytesExpression(h, BlackHoleExpression).pos(h.position), expr).pos(s.position))
|
||||
else Some(s)
|
||||
case s@Assignment(SeparateBytesExpression(VariableExpression(h), l), expr) =>
|
||||
if (globalsToRemove(h)) Some(Assignment(SeparateBytesExpression(BlackHoleExpression, l), expr))
|
||||
case s@Assignment(SeparateBytesExpression(he@VariableExpression(h), l), expr) =>
|
||||
if (globalsToRemove(h)) Some(Assignment(SeparateBytesExpression(BlackHoleExpression, l).pos(he.position), expr).pos(s.position))
|
||||
else Some(s)
|
||||
case s: IfStatement =>
|
||||
Some(s.copy(
|
||||
thenBranch = removeVariablesFromStatement(s.thenBranch, globalsToRemove).asInstanceOf[List[ExecutableStatement]],
|
||||
elseBranch = removeVariablesFromStatement(s.elseBranch, globalsToRemove).asInstanceOf[List[ExecutableStatement]]))
|
||||
elseBranch = removeVariablesFromStatement(s.elseBranch, globalsToRemove).asInstanceOf[List[ExecutableStatement]]).pos(s.position))
|
||||
case s: WhileStatement =>
|
||||
Some(s.copy(
|
||||
body = removeVariablesFromStatement(s.body, globalsToRemove).asInstanceOf[List[ExecutableStatement]]))
|
||||
body = removeVariablesFromStatement(s.body, globalsToRemove).asInstanceOf[List[ExecutableStatement]]).pos(s.position))
|
||||
case s: DoWhileStatement =>
|
||||
Some(s.copy(
|
||||
body = removeVariablesFromStatement(s.body, globalsToRemove).asInstanceOf[List[ExecutableStatement]]))
|
||||
body = removeVariablesFromStatement(s.body, globalsToRemove).asInstanceOf[List[ExecutableStatement]]).pos(s.position))
|
||||
case s => Some(s)
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ object UnusedLocalVariables extends NodeOptimization {
|
||||
params.flatMap {
|
||||
case VariableExpression(_) => None
|
||||
case LiteralExpression(_, _) => None
|
||||
case x => Some(ExpressionStatement(x))
|
||||
case x => Some(ExpressionStatement(x).pos(s.position))
|
||||
}
|
||||
} else Some(s)
|
||||
case s@Assignment(VariableExpression(n), VariableExpression(_)) =>
|
||||
@ -88,35 +88,52 @@ object UnusedLocalVariables extends NodeOptimization {
|
||||
case s@Assignment(VariableExpression(n), LiteralExpression(_, _)) =>
|
||||
if (localsToRemove(n)) Nil else Some(s)
|
||||
case s@Assignment(VariableExpression(n), expr) =>
|
||||
if (localsToRemove(n)) Some(ExpressionStatement(expr)) else Some(s)
|
||||
case s@Assignment(SeparateBytesExpression(VariableExpression(h), VariableExpression(l)), expr) =>
|
||||
if (localsToRemove(n)) Some(ExpressionStatement(expr).pos(s.position)) else Some(s)
|
||||
case s@Assignment(SeparateBytesExpression(he@VariableExpression(h), le@VariableExpression(l)), expr) =>
|
||||
if (localsToRemove(h)) {
|
||||
if (localsToRemove(l))
|
||||
Some(ExpressionStatement(expr))
|
||||
Some(ExpressionStatement(expr).pos(s.position))
|
||||
else
|
||||
Some(Assignment(SeparateBytesExpression(BlackHoleExpression, VariableExpression(l)), expr))
|
||||
Some(Assignment(
|
||||
SeparateBytesExpression(
|
||||
BlackHoleExpression,
|
||||
VariableExpression(l).pos(le.position)
|
||||
).pos(he.position),
|
||||
expr
|
||||
).pos(s.position))
|
||||
} else {
|
||||
if (localsToRemove(l))
|
||||
Some(Assignment(SeparateBytesExpression(VariableExpression(h), BlackHoleExpression), expr))
|
||||
Some(Assignment(
|
||||
SeparateBytesExpression(
|
||||
VariableExpression(h).pos(he.position),
|
||||
BlackHoleExpression
|
||||
).pos(he.position),
|
||||
expr
|
||||
).pos(s.position))
|
||||
else
|
||||
Some(s)
|
||||
}
|
||||
case s@Assignment(SeparateBytesExpression(h, VariableExpression(l)), expr) =>
|
||||
if (localsToRemove(l)) Some(Assignment(SeparateBytesExpression(h, BlackHoleExpression), expr))
|
||||
if (localsToRemove(l)) Some(Assignment(
|
||||
SeparateBytesExpression(h, BlackHoleExpression).pos(h.position),
|
||||
expr
|
||||
).pos(s.position))
|
||||
else Some(s)
|
||||
case s@Assignment(SeparateBytesExpression(VariableExpression(h), l), expr) =>
|
||||
if (localsToRemove(h)) Some(Assignment(SeparateBytesExpression(BlackHoleExpression, l), expr))
|
||||
case s@Assignment(SeparateBytesExpression(he@VariableExpression(h), l), expr) =>
|
||||
if (localsToRemove(h)) Some(Assignment(
|
||||
SeparateBytesExpression(BlackHoleExpression, l).pos(he.position), expr
|
||||
).pos(s.position))
|
||||
else Some(s)
|
||||
case s: IfStatement =>
|
||||
Some(s.copy(
|
||||
thenBranch = removeVariables(s.thenBranch, localsToRemove).asInstanceOf[List[ExecutableStatement]],
|
||||
elseBranch = removeVariables(s.elseBranch, localsToRemove).asInstanceOf[List[ExecutableStatement]]))
|
||||
elseBranch = removeVariables(s.elseBranch, localsToRemove).asInstanceOf[List[ExecutableStatement]]).pos(s.position))
|
||||
case s: WhileStatement =>
|
||||
Some(s.copy(
|
||||
body = removeVariables(s.body, localsToRemove).asInstanceOf[List[ExecutableStatement]]))
|
||||
body = removeVariables(s.body, localsToRemove).asInstanceOf[List[ExecutableStatement]]).pos(s.position))
|
||||
case s: DoWhileStatement =>
|
||||
Some(s.copy(
|
||||
body = removeVariables(s.body, localsToRemove).asInstanceOf[List[ExecutableStatement]]))
|
||||
body = removeVariables(s.body, localsToRemove).asInstanceOf[List[ExecutableStatement]]).pos(s.position))
|
||||
case s => Some(s)
|
||||
}
|
||||
|
||||
|
@ -482,7 +482,9 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
|
||||
|
||||
private def outputFunction(bank: String, code: List[T], startFrom: Int, assOut: mutable.ArrayBuffer[String], options: CompilationOptions): Int = {
|
||||
val printLineNumbers = options.flag(CompilationFlag.LineNumbersInAssembly)
|
||||
val sourceInAssembly = options.flag(CompilationFlag.SourceInAssembly)
|
||||
var index = startFrom
|
||||
assOut.append(" ")
|
||||
assOut.append("* = $" + startFrom.toHexString)
|
||||
var lastSource = Option.empty[SourceLine]
|
||||
for (instr <- code) {
|
||||
@ -491,9 +493,18 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
|
||||
lastSource = instr.source
|
||||
if (printLineNumbers) {
|
||||
lastSource match {
|
||||
case Some(SourceLine(moduleName, line)) if line > 0 =>
|
||||
case Some(sl@SourceLine(moduleName, line)) if line > 0 =>
|
||||
if (sourceInAssembly) {
|
||||
assOut.append("; ")
|
||||
}
|
||||
assOut.append(s";line:$line:$moduleName")
|
||||
if (sourceInAssembly) {
|
||||
log.getLine(sl).foreach(l => assOut.append("; " + l))
|
||||
}
|
||||
case _ =>
|
||||
if (sourceInAssembly) {
|
||||
assOut.append("; ")
|
||||
}
|
||||
assOut.append(s";line")
|
||||
}
|
||||
}
|
||||
@ -517,6 +528,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
|
||||
index = emitInstruction(bank, options, index, instr)
|
||||
}
|
||||
if (printLineNumbers && lastSource.isDefined){
|
||||
if (sourceInAssembly) assOut.append("; ")
|
||||
assOut.append(s";line")
|
||||
}
|
||||
index
|
||||
|
@ -64,17 +64,25 @@ object MosInliningCalculator extends AbstractInliningCalculator[AssemblyLine] {
|
||||
|
||||
def inline(code: List[AssemblyLine], inlinedFunctions: Map[String, List[AssemblyLine]], jobContext: JobContext): List[AssemblyLine] = {
|
||||
code.flatMap {
|
||||
case AssemblyLine(Opcode.JSR, AddrMode.Absolute | AddrMode.LongAbsolute, p, Elidability.Elidable, _) if inlinedFunctions.contains(p.toString) =>
|
||||
case callInstr@AssemblyLine(Opcode.JSR, AddrMode.Absolute | AddrMode.LongAbsolute, p, Elidability.Elidable, _) if inlinedFunctions.contains(p.toString) =>
|
||||
val labelPrefix = jobContext.nextLabel("ai")
|
||||
inlinedFunctions(p.toString).map {
|
||||
var inlinedCode = inlinedFunctions(p.toString)
|
||||
if (inlinedCode.forall(_.source.isEmpty)) {
|
||||
inlinedCode = inlinedCode.map(_.copy(source = callInstr.source))
|
||||
}
|
||||
inlinedCode.map {
|
||||
case line@AssemblyLine0(_, _, MemoryAddressConstant(Label(label))) =>
|
||||
val newLabel = MemoryAddressConstant(Label(labelPrefix + label))
|
||||
line.copy(parameter = newLabel)
|
||||
case l => l
|
||||
}
|
||||
case AssemblyLine(Opcode.JMP, AddrMode.Absolute, p, Elidability.Elidable, _) if inlinedFunctions.contains(p.toString) =>
|
||||
case callInstr@AssemblyLine(Opcode.JMP, AddrMode.Absolute, p, Elidability.Elidable, _) if inlinedFunctions.contains(p.toString) =>
|
||||
val labelPrefix = jobContext.nextLabel("ai")
|
||||
inlinedFunctions(p.toString).map {
|
||||
var inlinedCode = inlinedFunctions(p.toString)
|
||||
if (inlinedCode.forall(_.source.isEmpty)) {
|
||||
inlinedCode = inlinedCode.map(_.copy(source = callInstr.source))
|
||||
}
|
||||
inlinedCode.map {
|
||||
case line@AssemblyLine0(_, _, MemoryAddressConstant(Label(label))) =>
|
||||
val newLabel = MemoryAddressConstant(Label(labelPrefix + label))
|
||||
line.copy(parameter = newLabel)
|
||||
|
@ -56,24 +56,34 @@ object Z80InliningCalculator extends AbstractInliningCalculator[ZLine] {
|
||||
|
||||
override def inline(code: List[ZLine], inlinedFunctions: Map[String, List[ZLine]], jobContext: JobContext): List[ZLine] = {
|
||||
code.flatMap {
|
||||
case ZLine(CALL, registers, p, Elidability.Elidable, _) if inlinedFunctions.contains(p.toString) =>
|
||||
case callInstr@ZLine(CALL, registers, p, Elidability.Elidable, _) if inlinedFunctions.contains(p.toString) =>
|
||||
val labelPrefix = jobContext.nextLabel("ai")
|
||||
wrap(registers, jobContext,
|
||||
inlinedFunctions(p.toString).map {
|
||||
wrap(registers, jobContext, {
|
||||
var inlinedCode = inlinedFunctions(p.toString)
|
||||
if (inlinedCode.forall(_.source.isEmpty)) {
|
||||
inlinedCode = inlinedCode.map(_.copy(source = callInstr.source))
|
||||
}
|
||||
inlinedCode.map {
|
||||
case line@ZLine0(_, _, MemoryAddressConstant(Label(label))) =>
|
||||
val newLabel = MemoryAddressConstant(Label(labelPrefix + label))
|
||||
line.copy(parameter = newLabel)
|
||||
case l => l
|
||||
})
|
||||
case ZLine(JP | JR, registers, p, Elidability.Elidable, _) if inlinedFunctions.contains(p.toString) =>
|
||||
}
|
||||
})
|
||||
case callInstr@ZLine(JP | JR, registers, p, Elidability.Elidable, _) if inlinedFunctions.contains(p.toString) =>
|
||||
val labelPrefix = jobContext.nextLabel("ai")
|
||||
wrap(registers, jobContext,
|
||||
inlinedFunctions(p.toString).map {
|
||||
wrap(registers, jobContext, {
|
||||
var inlinedCode = inlinedFunctions(p.toString)
|
||||
if (inlinedCode.forall(_.source.isEmpty)) {
|
||||
inlinedCode = inlinedCode.map(_.copy(source = callInstr.source))
|
||||
}
|
||||
inlinedCode.map {
|
||||
case line@ZLine0(_, _, MemoryAddressConstant(Label(label))) =>
|
||||
val newLabel = MemoryAddressConstant(Label(labelPrefix + label))
|
||||
line.copy(parameter = newLabel)
|
||||
case l => l
|
||||
} :+ ZLine.implied(RET))
|
||||
} :+ ZLine.implied(RET)
|
||||
})
|
||||
case x => List(x)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user