1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-05 09:28:54 +00:00

Move label generation into a separate class

This commit is contained in:
Karol Stasiak 2018-07-31 18:16:36 +02:00
parent f929e396df
commit e914ad6d7b
41 changed files with 225 additions and 203 deletions

View File

@ -1,15 +1,25 @@
package millfork
import millfork.error.{Logger, ConsoleLogger}
import millfork.compiler.LabelGenerator
import millfork.error.{ConsoleLogger, Logger}
/**
* @author Karol Stasiak
*/
case class CompilationOptions(platform: Platform, commandLineFlags: Map[CompilationFlag.Value, Boolean], outputFileName: Option[String], zpRegisterSize: Int, log: Logger) {
case class CompilationOptions(platform: Platform,
commandLineFlags: Map[CompilationFlag.Value, Boolean],
outputFileName: Option[String],
zpRegisterSize: Int,
jobContext: JobContext) {
import CompilationFlag._
import Cpu._
@inline
def log: Logger = jobContext.log
@inline
def nextLabel: LabelGenerator = jobContext.nextLabel
val flags: Map[CompilationFlag.Value, Boolean] = CompilationFlag.values.map { f =>
f -> commandLineFlags.getOrElse(f, platform.flagOverrides.getOrElse(f, Cpu.defaultFlags(platform.cpu)(f)))
}.toMap

View File

@ -0,0 +1,9 @@
package millfork
import millfork.compiler.LabelGenerator
import millfork.error.Logger
/**
* @author Karol Stasiak
*/
case class JobContext(log: Logger, nextLabel: LabelGenerator)

View File

@ -9,9 +9,10 @@ import millfork.assembly.mos.opt._
import millfork.assembly.z80.opt.Z80OptimizationPresets
import millfork.buildinfo.BuildInfo
import millfork.cli.{CliParser, CliStatus}
import millfork.compiler.LabelGenerator
import millfork.compiler.mos.MosCompiler
import millfork.env.Environment
import millfork.error.{Logger, ConsoleLogger}
import millfork.error.{ConsoleLogger, Logger}
import millfork.node.StandardCallGraph
import millfork.output._
import millfork.parser.{MosSourceLoadingQueue, ZSourceLoadingQueue}
@ -80,7 +81,7 @@ object Main {
errorReporting.info("No platform selected, defaulting to `c64`")
"c64"
}, c.features)
val options = CompilationOptions(platform, c.flags, c.outputFileName, c.zpRegisterSize.getOrElse(platform.zpRegisterSize), errorReporting)
val options = CompilationOptions(platform, c.flags, c.outputFileName, c.zpRegisterSize.getOrElse(platform.zpRegisterSize), JobContext(errorReporting, new LabelGenerator))
errorReporting.debug("Effective flags: ")
options.flags.toSeq.sortBy(_._1).foreach{
case (f, b) => errorReporting.debug(f" $f%-30s : $b%s")
@ -162,7 +163,7 @@ object Main {
}
val callGraph = new StandardCallGraph(program, options.log)
val env = new Environment(None, "", platform.cpuFamily, options.log)
val env = new Environment(None, "", platform.cpuFamily, options.jobContext)
env.collectDeclarations(program, options)
val assemblyOptimizations = optLevel match {
@ -213,7 +214,7 @@ object Main {
}
val callGraph = new StandardCallGraph(program, options.log)
val env = new Environment(None, "", platform.cpuFamily, options.log)
val env = new Environment(None, "", platform.cpuFamily, options.jobContext)
env.collectDeclarations(program, options)
val assemblyOptimizations = optLevel match {

View File

@ -1,6 +1,7 @@
package millfork.assembly
import millfork.CompilationOptions
import millfork.compiler.LabelGenerator
import millfork.env.{NormalFunction, ThingInMemory}
import millfork.error.Logger
import millfork.node.NiceFunctionProperty
@ -12,7 +13,10 @@ case class OptimizationContext(options: CompilationOptions,
labelMap: Map[String, Int],
zreg: Option[ThingInMemory],
niceFunctionProperties: Set[(NiceFunctionProperty, String)]) {
@inline
def log: Logger = options.log
@inline
def nextLabel: LabelGenerator = options.nextLabel
}
trait AssemblyOptimization[T <: AbstractCode] {

View File

@ -380,7 +380,7 @@ object AssemblyLine {
List(AssemblyLine.immediate(opcode, 0))
} else if (opcodesForZeroedOrSignExtendedVariableOperation(opcode)) {
if (variable.typ.isSigned) {
val label = MosCompiler.nextLabel("sx")
val label = ctx.nextLabel("sx")
AssemblyLine.variable(ctx, LDA, variable, variable.typ.size - 1) ++ List(
AssemblyLine.immediate(ORA, 0x7f),
AssemblyLine.relative(BMI, label),

View File

@ -17,12 +17,9 @@ import millfork.env._
//noinspection ZeroIndexToHead
object AlwaysGoodOptimizations {
val counter = new AtomicInteger(30000)
val LdxAddrModes = Set(Immediate, Absolute, ZeroPage, ZeroPageY, AbsoluteY)
val LdyAddrModes = Set(Immediate, Absolute, ZeroPage, ZeroPageX, AbsoluteX)
def getNextLabel(prefix: String) = f".$prefix%s__${counter.getAndIncrement()}%05d"
private def jvmFix(r: => RuleBasedAssemblyOptimization): RuleBasedAssemblyOptimization = r
val PointlessMath = jvmFix(new RuleBasedAssemblyOptimization("Pointless math",
@ -1725,8 +1722,8 @@ object AlwaysGoodOptimizations {
needsFlowInfo = FlowInfoRequirement.BothFlows,
(Elidable & HasOpcode(LDA) & HasImmediate(0) & HasClear(State.D)) ~
(Elidable & HasOpcode(ADC) & MatchAddrMode(1) & MatchParameter(2) & HasAddrModeIn(ZeroPage, ZeroPageX, Absolute, AbsoluteX)) ~
(Elidable & HasOpcode(STA) & MatchAddrMode(1) & MatchParameter(2) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { code =>
val label = getNextLabel("ah")
(Elidable & HasOpcode(STA) & MatchAddrMode(1) & MatchParameter(2) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { (code, ctx) =>
val label = ctx.nextLabel("ah")
List(
AssemblyLine.relative(BCC, label),
code.last.copy(opcode = INC),
@ -1734,8 +1731,8 @@ object AlwaysGoodOptimizations {
},
(Elidable & HasOpcode(LDA) & MatchAddrMode(1) & MatchParameter(2) & HasAddrModeIn(ZeroPage, ZeroPageX, Absolute, AbsoluteX)) ~
(Elidable & HasOpcode(ADC) & HasImmediate(0) & HasClear(State.D)) ~
(Elidable & HasOpcode(STA) & MatchAddrMode(1) & MatchParameter(2) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { code =>
val label = getNextLabel("ah")
(Elidable & HasOpcode(STA) & MatchAddrMode(1) & MatchParameter(2) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { (code, ctx) =>
val label = ctx.nextLabel("ah")
List(
AssemblyLine.relative(BCC, label),
code.last.copy(opcode = INC),
@ -1753,8 +1750,8 @@ object AlwaysGoodOptimizations {
},
(Elidable & HasOpcode(TXA) & HasClear(State.D)) ~
(Elidable & HasOpcode(ADC) & HasImmediate(0)) ~
(Elidable & HasOpcode(TAX) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { code =>
val label = getNextLabel("ah")
(Elidable & HasOpcode(TAX) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { (code, ctx) =>
val label = ctx.nextLabel("ah")
List(
AssemblyLine.relative(BCC, label),
AssemblyLine.implied(INX),
@ -1762,8 +1759,8 @@ object AlwaysGoodOptimizations {
},
(Elidable & HasOpcode(TYA) & HasClear(State.D)) ~
(Elidable & HasOpcode(ADC) & HasImmediate(0)) ~
(Elidable & HasOpcode(TAY) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { code =>
val label = getNextLabel("ah")
(Elidable & HasOpcode(TAY) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { (code, ctx) =>
val label = ctx.nextLabel("ah")
List(
AssemblyLine.relative(BCC, label),
AssemblyLine.implied(INY),
@ -1796,8 +1793,8 @@ object AlwaysGoodOptimizations {
(Linear & Not(ChangesNAndZ) & Not(HasOpcode(CLC)) & Not(ChangesA)).* ~
(Elidable & HasOpcode(CLC) & HasClear(State.D)) ~
(Elidable & HasOpcode(ADC) & MatchAddrMode(0) & MatchParameter(1) & HasAddrModeIn(ZeroPage, ZeroPageX, Absolute, AbsoluteX)) ~
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.V, State.Z, State.N, State.A)) ~~> { code =>
val label = getNextLabel("in")
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.V, State.Z, State.N, State.A)) ~~> { (code, ctx) =>
val label = ctx.nextLabel("in")
code.take(code.length - 3) ++ List(
AssemblyLine.relative(BEQ, label),
code.last.copy(opcode = INC),
@ -1807,8 +1804,8 @@ object AlwaysGoodOptimizations {
(HasOpcode(ANC) & HasImmediate(1)) ~
(Linear & Not(ChangesNAndZ) & Not(ChangesA) & (Not(ChangesC) | HasOpcode(CLC))).* ~
(Elidable & HasOpcode(ADC) & MatchAddrMode(0) & MatchParameter(1) & HasClear(State.D) & HasAddrModeIn(ZeroPage, ZeroPageX, Absolute, AbsoluteX)) ~
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.V, State.Z, State.N, State.A)) ~~> { code =>
val label = getNextLabel("in")
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.V, State.Z, State.N, State.A)) ~~> { (code, ctx) =>
val label = ctx.nextLabel("in")
code.head.copy(opcode = AND) :: code.take(code.length - 2).tail ++ List(
AssemblyLine.relative(BEQ, label),
code.last.copy(opcode = INC),
@ -2234,7 +2231,7 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(TXA)) ~
(Elidable & HasOpcode(ADC) & MatchAddrMode(2) & MatchParameter(3) & Not(ConcernsX) & DoesNotConcernMemoryAt(0, 1)) ~
(Elidable & HasOpcode(STA) & MatchAddrMode(2) & MatchParameter(3) & Not(ConcernsX) & DoesntMatterWhatItDoesWith(State.C, State.N, State.V, State.Z)) ~~> { (code, ctx) =>
val label = getNextLabel("in")
val label = ctx.nextLabel("in")
List(
code(1), // BCC
code(8).copy(opcode = INC),
@ -2256,7 +2253,7 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(TXA)) ~
(Elidable & HasOpcode(ADC) & MatchAddrMode(2) & MatchParameter(3) & Not(ConcernsX) & DoesNotConcernMemoryAt(0, 1)) ~
(Elidable & HasOpcode(STA) & MatchAddrMode(2) & MatchParameter(3) & Not(ConcernsX) & DoesntMatterWhatItDoesWith(State.C, State.N, State.V, State.Z)) ~~> { (code, ctx) =>
val label = getNextLabel("in")
val label = ctx.nextLabel("in")
List(
code(1), // BCC
code(8).copy(opcode = INC),
@ -2275,7 +2272,7 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & Not(ConcernsX)) ~
(Elidable & HasOpcode(STX) & MatchAddrMode(2) & MatchParameter(3) & DoesNotConcernMemoryAt(0, 1) & Not(HasAddrMode(ZeroPageY)) &
DoesntMatterWhatItDoesWith(State.X, State.A, State.C, State.V)) ~~> { (code, ctx) =>
val label = getNextLabel("in")
val label = ctx.nextLabel("in")
List(
code(4), // STA
code.head.copy(opcode = LDA), // LDX
@ -2289,7 +2286,7 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & Not(ConcernsX)) ~
(Elidable & HasOpcode(STX) & MatchAddrMode(2) & MatchParameter(3) & DoesNotConcernMemoryAt(0, 1) & Not(HasAddrMode(ZeroPageY)) &
DoesntMatterWhatItDoesWith(State.X, State.A, State.C, State.V)) ~~> { (code, ctx) =>
val label = getNextLabel("in")
val label = ctx.nextLabel("in")
List(
code(4), // STA
AssemblyLine.immediate(ADC, 0),
@ -2308,7 +2305,7 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(TXA)) ~
(Elidable & HasOpcodeIn(ORA, EOR) & MatchAddrMode(2) & MatchParameter(3) & Not(ConcernsX) & DoesNotConcernMemoryAt(0, 1)) ~
(Elidable & HasOpcode(STA) & MatchAddrMode(2) & MatchParameter(3) & Not(ConcernsX) & DoesntMatterWhatItDoesWith(State.C, State.N, State.V, State.Z)) ~~>{ (code, ctx) =>
val label = getNextLabel("in")
val label = ctx.nextLabel("in")
List(
code(4), //EOR/ORA
code(5), //STA

View File

@ -4,6 +4,7 @@ import millfork.CompilationOptions
import millfork.assembly._
import millfork.assembly.mos._
import millfork.assembly.opt.SingleStatus
import millfork.compiler.LabelGenerator
import millfork.env._
import millfork.error.{FatalErrorReporting, Logger}
import millfork.node.{MosNiceFunctionProperty, NiceFunctionProperty}
@ -85,7 +86,10 @@ class AssemblyMatchingContext(val compilationOptions: CompilationOptions,
val labelMap: Map[String, Int],
val zeropageRegister: Option[ThingInMemory],
val niceFunctionProperties: Set[(NiceFunctionProperty, String)]) {
@inline
def log: Logger = compilationOptions.log
@inline
def nextLabel: LabelGenerator = compilationOptions.nextLabel
def functionChangesA(name: String): Boolean = !niceFunctionProperties(MosNiceFunctionProperty.DoesntChangeA -> name)

View File

@ -3,6 +3,7 @@ package millfork.assembly.mos.opt
import millfork.{CompilationFlag, CompilationOptions, OptimizationPresets}
import millfork.assembly.{AssemblyOptimization, OptimizationContext}
import millfork.assembly.mos.{AddrMode, AssemblyLine, Opcode}
import millfork.compiler.LabelGenerator
import millfork.env.NormalFunction
import millfork.error.{ConsoleLogger, ErrorsOnlyLogger}
@ -56,7 +57,7 @@ object SuperOptimizer extends AssemblyOptimization[AssemblyLine] {
)
val optionsForMeasurements = options.copy(
commandLineFlags = options.commandLineFlags + (CompilationFlag.InternalCurrentlyOptimizingForMeasurement -> true),
log = new ErrorsOnlyLogger(options.log)
jobContext = options.jobContext.copy(log = new ErrorsOnlyLogger(options.log))
)
val optimizationContextForMeasurements = optimizationContext.copy(options = optionsForMeasurements)
val quicklyCleanedCode = quickScrub.foldLeft(code)((c, o) => o.optimize(m, c, optimizationContextForMeasurements))

View File

@ -6,6 +6,5 @@ import millfork.assembly.AbstractCode
* @author Karol Stasiak
*/
abstract class AbstractCompiler[T <: AbstractCode] {
def nextLabel(prefix: String): String
def compile(ctx: CompilationContext): List[T]
}

View File

@ -28,7 +28,7 @@ class AbstractExpressionCompiler[T <: AbstractCode] {
}
def callingContext(ctx: CompilationContext, v: MemoryVariable): CompilationContext = {
val result = new Environment(Some(ctx.env), "", ctx.options.platform.cpuFamily, ctx.log)
val result = new Environment(Some(ctx.env), "", ctx.options.platform.cpuFamily, ctx.jobContext)
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), ctx.options)
ctx.copy(env = result)
}

View File

@ -120,7 +120,7 @@ abstract class AbstractReturnDispatch[T <: AbstractCode] {
val env = ctx.env.root
val b = env.get[VariableType]("byte")
val label = nextLabel("di")
val label = ctx.nextLabel("di")
val paramArrays = stmt.params.indices.map { ix =>
val a = InitializedArray(label + "$" + ix + ".array", None, (paramMins(ix) to paramMaxes(ix)).map { key =>
map(key)._2.lift(ix).getOrElse(LiteralExpression(0, 1))
@ -132,8 +132,6 @@ abstract class AbstractReturnDispatch[T <: AbstractCode] {
compileImpl(ctx, stmt, label, actualMin, actualMax, paramArrays, paramMins, map)
}
def nextLabel(prefix: String): String
def compileImpl(ctx: CompilationContext,
stmt: ReturnDispatchStatement,
label: String,

View File

@ -19,8 +19,6 @@ abstract class AbstractStatementCompiler[T <: AbstractCode] {
def compile(ctx: CompilationContext, statement: ExecutableStatement): List[T]
def nextLabel(prefix: String): String
def labelChunk(labelName: String): List[T]
def jmpChunk(labelName: String): List[T] = jmpChunk(Label(labelName))
@ -34,10 +32,10 @@ abstract class AbstractStatementCompiler[T <: AbstractCode] {
def areBlocksLarge(blocks: List[T]*): Boolean
def compileWhileStatement(ctx: CompilationContext, s: WhileStatement): List[T] = {
val start = nextLabel("wh")
val middle = nextLabel("he")
val inc = nextLabel("fp")
val end = nextLabel("ew")
val start = ctx.nextLabel("wh")
val middle = ctx.nextLabel("he")
val inc = ctx.nextLabel("fp")
val end = ctx.nextLabel("ew")
val condType = AbstractExpressionCompiler.getExpressionType(ctx, s.condition)
val bodyBlock = compile(ctx.addLabels(s.labels, Label(end), Label(inc)), s.body)
val incrementBlock = compile(ctx.addLabels(s.labels, Label(end), Label(inc)), s.increment)
@ -71,9 +69,9 @@ abstract class AbstractStatementCompiler[T <: AbstractCode] {
}
def compileDoWhileStatement(ctx: CompilationContext, s: DoWhileStatement): List[T] = {
val start = nextLabel("do")
val inc = nextLabel("fp")
val end = nextLabel("od")
val start = ctx.nextLabel("do")
val inc = ctx.nextLabel("fp")
val end = ctx.nextLabel("od")
val condType = AbstractExpressionCompiler.getExpressionType(ctx, s.condition)
val bodyBlock = compile(ctx.addLabels(s.labels, Label(end), Label(inc)), s.body)
val incrementBlock = compile(ctx.addLabels(s.labels, Label(end), Label(inc)), s.increment)
@ -136,13 +134,13 @@ abstract class AbstractStatementCompiler[T <: AbstractCode] {
(f.direction, startEvaluated, endEvaluated) match {
case (ForDirection.Until | ForDirection.ParallelUntil, Some(NumericConstant(s, ssize)), Some(NumericConstant(e, _))) if s == e - 1 =>
val end = nextLabel("of")
val end = ctx.nextLabel("of")
compile(ctx.addLabels(names, Label(end), Label(end)), Assignment(vex, f.start).pos(p) :: f.body) ++ labelChunk(end)
case (ForDirection.Until | ForDirection.ParallelUntil, Some(NumericConstant(s, ssize)), Some(NumericConstant(e, _))) if s >= e =>
Nil
case (ForDirection.To | ForDirection.ParallelTo, Some(NumericConstant(s, ssize)), Some(NumericConstant(e, _))) if s == e =>
val end = nextLabel("of")
val end = ctx.nextLabel("of")
compile(ctx.addLabels(names, Label(end), Label(end)), Assignment(vex, f.start).pos(p) :: f.body) ++ labelChunk(end)
case (ForDirection.To | ForDirection.ParallelTo, Some(NumericConstant(s, ssize)), Some(NumericConstant(e, _))) if s > e =>
Nil
@ -166,7 +164,7 @@ abstract class AbstractStatementCompiler[T <: AbstractCode] {
))
case (ForDirection.DownTo, Some(NumericConstant(s, ssize)), Some(NumericConstant(e, esize))) if s == e =>
val end = nextLabel("of")
val end = ctx.nextLabel("of")
compile(ctx.addLabels(names, Label(end), Label(end)), Assignment(vex, LiteralExpression(s, ssize)).pos(p) :: f.body) ++ labelChunk(end)
case (ForDirection.DownTo, Some(NumericConstant(s, ssize)), Some(NumericConstant(e, esize))) if s < e =>
Nil
@ -288,39 +286,39 @@ abstract class AbstractStatementCompiler[T <: AbstractCode] {
case (Nil, _) =>
val conditionBlock = compileExpressionForBranching(ctx, s.condition, NoBranching)
if (largeElseBlock) {
val middle = nextLabel("el")
val end = nextLabel("fi")
val middle = ctx.nextLabel("el")
val end = ctx.nextLabel("fi")
List(conditionBlock, branchChunk(jumpIfFalse, middle), jmpChunk(end), labelChunk(middle), elseBlock, labelChunk(end)).flatten
} else {
val end = nextLabel("fi")
val end = ctx.nextLabel("fi")
List(conditionBlock, branchChunk(jumpIfTrue, end), elseBlock, labelChunk(end)).flatten
}
case (_, Nil) =>
val conditionBlock = compileExpressionForBranching(ctx, s.condition, NoBranching)
if (largeThenBlock) {
val middle = nextLabel("th")
val end = nextLabel("fi")
val middle = ctx.nextLabel("th")
val end = ctx.nextLabel("fi")
List(conditionBlock, branchChunk(jumpIfTrue, middle), jmpChunk(end), labelChunk(middle), thenBlock, labelChunk(end)).flatten
} else {
val end = nextLabel("fi")
val end = ctx.nextLabel("fi")
List(conditionBlock, branchChunk(jumpIfFalse, end), thenBlock, labelChunk(end)).flatten
}
case _ =>
val conditionBlock = compileExpressionForBranching(ctx, s.condition, NoBranching)
if (largeThenBlock) {
if (largeElseBlock) {
val middleT = nextLabel("th")
val middleE = nextLabel("el")
val end = nextLabel("fi")
val middleT = ctx.nextLabel("th")
val middleE = ctx.nextLabel("el")
val end = ctx.nextLabel("fi")
List(conditionBlock, branchChunk(jumpIfTrue, middleT), jmpChunk(middleE), labelChunk(middleT), thenBlock, jmpChunk(end), labelChunk(middleE), elseBlock, labelChunk(end)).flatten
} else {
val middle = nextLabel("th")
val end = nextLabel("fi")
val middle = ctx.nextLabel("th")
val end = ctx.nextLabel("fi")
List(conditionBlock, branchChunk(jumpIfTrue, middle), elseBlock, jmpChunk(end), labelChunk(middle), thenBlock, labelChunk(end)).flatten
}
} else {
val middle = nextLabel("el")
val end = nextLabel("fi")
val middle = ctx.nextLabel("el")
val end = ctx.nextLabel("fi")
List(conditionBlock, branchChunk(jumpIfFalse, middle), thenBlock, jmpChunk(end), labelChunk(middle), elseBlock, labelChunk(end)).flatten
}
}
@ -330,43 +328,43 @@ abstract class AbstractStatementCompiler[T <: AbstractCode] {
compileExpressionForBranching(ctx, s.condition, NoBranching)
case (Nil, _) =>
if (largeElseBlock) {
val middle = nextLabel("el")
val end = nextLabel("fi")
val middle = ctx.nextLabel("el")
val end = ctx.nextLabel("fi")
val conditionBlock = compileExpressionForBranching(ctx, s.condition, BranchIfFalse(middle))
List(conditionBlock, jmpChunk(end), labelChunk(middle), elseBlock, labelChunk(end)).flatten
} else {
val end = nextLabel("fi")
val end = ctx.nextLabel("fi")
val conditionBlock = compileExpressionForBranching(ctx, s.condition, BranchIfTrue(end))
List(conditionBlock, elseBlock, labelChunk(end)).flatten
}
case (_, Nil) =>
if (largeThenBlock) {
val middle = nextLabel("th")
val end = nextLabel("fi")
val middle = ctx.nextLabel("th")
val end = ctx.nextLabel("fi")
val conditionBlock = compileExpressionForBranching(ctx, s.condition, BranchIfTrue(middle))
List(conditionBlock, jmpChunk(end), labelChunk(middle), thenBlock, labelChunk(end)).flatten
} else {
val end = nextLabel("fi")
val end = ctx.nextLabel("fi")
val conditionBlock = compileExpressionForBranching(ctx, s.condition, BranchIfFalse(end))
List(conditionBlock, thenBlock, labelChunk(end)).flatten
}
case _ =>
if (largeThenBlock) {
if (largeElseBlock) {
val middleT = nextLabel("th")
val middleE = nextLabel("el")
val end = nextLabel("fi")
val middleT = ctx.nextLabel("th")
val middleE = ctx.nextLabel("el")
val end = ctx.nextLabel("fi")
val conditionBlock = compileExpressionForBranching(ctx, s.condition, BranchIfTrue(middleT))
List(conditionBlock, jmpChunk(middleE), labelChunk(middleT), thenBlock, jmpChunk(end), labelChunk(middleE), elseBlock, labelChunk(end)).flatten
} else {
val middle = nextLabel("th")
val end = nextLabel("fi")
val middle = ctx.nextLabel("th")
val end = ctx.nextLabel("fi")
val conditionBlock = compileExpressionForBranching(ctx, s.condition, BranchIfTrue(middle))
List(conditionBlock, elseBlock, jmpChunk(end), labelChunk(middle), thenBlock, labelChunk(end)).flatten
}
} else {
val middle = nextLabel("el")
val end = nextLabel("fi")
val middle = ctx.nextLabel("el")
val end = ctx.nextLabel("fi")
val conditionBlock = compileExpressionForBranching(ctx, s.condition, BranchIfFalse(middle))
List(conditionBlock, thenBlock, jmpChunk(end), labelChunk(middle), elseBlock, labelChunk(end)).flatten
}

View File

@ -3,7 +3,7 @@ package millfork.compiler
import millfork.env.{Environment, Label, NormalFunction}
import millfork.error.Logger
import millfork.node.NiceFunctionProperty
import millfork.{CompilationFlag, CompilationOptions}
import millfork.{CompilationFlag, CompilationOptions, JobContext}
/**
* @author Karol Stasiak
@ -16,7 +16,7 @@ case class CompilationContext(env: Environment,
breakLabels: Map[String, Label] = Map(),
continueLabels: Map[String, Label] = Map()){
def withInlinedEnv(environment: Environment, newLabel: String): CompilationContext = {
val newEnv = new Environment(Some(env), newLabel, environment.cpuFamily, log)
val newEnv = new Environment(Some(env), newLabel, environment.cpuFamily, jobContext)
newEnv.things ++= environment.things
copy(env = newEnv)
}
@ -36,5 +36,10 @@ case class CompilationContext(env: Environment,
def neverCheckArrayBounds: CompilationContext =
this.copy(options = options.copy(commandLineFlags = options.commandLineFlags + (CompilationFlag.CheckIndexOutOfBounds -> false)))
@inline
def jobContext: JobContext = options.jobContext
@inline
def log: Logger = options.log
@inline
def nextLabel: LabelGenerator = options.nextLabel
}

View File

@ -0,0 +1,13 @@
package millfork.compiler
import java.util.concurrent.atomic.AtomicLong
/**
* @author Karol Stasiak
*/
class LabelGenerator {
private val labelCounter = new AtomicLong
def apply(prefix: String): String = "." + prefix + "__" + labelCounter.incrementAndGet().formatted("%05d")
}

View File

@ -12,8 +12,6 @@ import millfork.node.{MosRegister, _}
*/
abstract class MacroExpander[T <: AbstractCode] {
def nextLabel(prefix: String): String
def prepareAssemblyParams(ctx: CompilationContext, assParams: List[AssemblyParam], params: List[Expression], code: List[ExecutableStatement]): (List[T], List[ExecutableStatement])
def replaceVariable(stmt: Statement, paramName: String, target: Expression): Statement = {
@ -77,7 +75,7 @@ abstract class MacroExpander[T <: AbstractCode] {
case MosAssemblyStatement(LABEL, _, VariableExpression(l), _) => Some(l)
case _ => None
}.toSet
val labelPrefix = nextLabel("il")
val labelPrefix = ctx.nextLabel("il")
paramPreparation -> actualCode.map {
case s@MosAssemblyStatement(_, _, VariableExpression(v), _) if localLabels(v) =>
s.copy(expression = VariableExpression(labelPrefix + v))

View File

@ -201,8 +201,8 @@ object BuiltIns {
case _ =>
val compileCounter = MosExpressionCompiler.preserveRegisterIfNeeded(ctx, MosRegister.A,
MosExpressionCompiler.compile(ctx, r, Some(b -> RegisterVariable(MosRegister.X, b)), NoBranching))
val labelSkip = MosCompiler.nextLabel("ss")
val labelRepeat = MosCompiler.nextLabel("sr")
val labelSkip = ctx.nextLabel("ss")
val labelRepeat = ctx.nextLabel("sr")
val loop = List(
AssemblyLine.relative(BEQ, labelSkip),
AssemblyLine.label(labelRepeat),
@ -297,8 +297,8 @@ object BuiltIns {
val compileCounter = MosExpressionCompiler.preserveRegisterIfNeeded(ctx, MosRegister.A,
MosExpressionCompiler.compile(ctx, rhs, Some(b -> RegisterVariable(register, b)), NoBranching))
val labelSkip = MosCompiler.nextLabel("ss")
val labelRepeat = MosCompiler.nextLabel("sr")
val labelSkip = ctx.nextLabel("ss")
val labelRepeat = ctx.nextLabel("sr")
if (ctx.options.flags(CompilationFlag.EmitNative65816Opcodes)) {
targetBytes match {
@ -438,7 +438,7 @@ object BuiltIns {
case ComparisonType.LessOrEqualUnsigned =>
List(AssemblyLine.relative(BCC, Label(label)), AssemblyLine.relative(BEQ, Label(label)))
case ComparisonType.GreaterUnsigned =>
val x = MosCompiler.nextLabel("co")
val x = ctx.nextLabel("co")
List(
AssemblyLine.relative(BEQ, x),
AssemblyLine.relative(BCS, Label(label)),
@ -451,7 +451,7 @@ object BuiltIns {
case ComparisonType.LessOrEqualSigned =>
List(AssemblyLine.relative(BMI, Label(label)), AssemblyLine.relative(BEQ, Label(label)))
case ComparisonType.GreaterSigned =>
val x = MosCompiler.nextLabel("co")
val x = ctx.nextLabel("co")
List(
AssemblyLine.relative(BEQ, x),
AssemblyLine.relative(BPL, Label(label)),
@ -538,7 +538,7 @@ object BuiltIns {
compactEqualityComparison match {
case Some(code) => code :+ AssemblyLine.relative(BEQ, Label(x))
case None =>
val innerLabel = MosCompiler.nextLabel("cp")
val innerLabel = ctx.nextLabel("cp")
cmpTo(LDA, ll) ++
cmpTo(CMP, rl) ++
List(AssemblyLine.relative(BNE, innerLabel)) ++
@ -562,7 +562,7 @@ object BuiltIns {
}
case ComparisonType.LessUnsigned =>
val innerLabel = MosCompiler.nextLabel("cp")
val innerLabel = ctx.nextLabel("cp")
cmpTo(LDA, lh) ++
cmpTo(CMP, rh) ++
List(
@ -575,7 +575,7 @@ object BuiltIns {
AssemblyLine.label(innerLabel))
case ComparisonType.LessOrEqualUnsigned =>
val innerLabel = MosCompiler.nextLabel("cp")
val innerLabel = ctx.nextLabel("cp")
cmpTo(LDA, rh) ++
cmpTo(CMP, lh) ++
List(AssemblyLine.relative(BCC, innerLabel),
@ -586,7 +586,7 @@ object BuiltIns {
AssemblyLine.label(innerLabel))
case ComparisonType.GreaterUnsigned =>
val innerLabel = MosCompiler.nextLabel("cp")
val innerLabel = ctx.nextLabel("cp")
cmpTo(LDA, rh) ++
cmpTo(CMP, lh) ++
List(AssemblyLine.relative(BCC, Label(x)),
@ -597,7 +597,7 @@ object BuiltIns {
AssemblyLine.label(innerLabel))
case ComparisonType.GreaterOrEqualUnsigned =>
val innerLabel = MosCompiler.nextLabel("cp")
val innerLabel = ctx.nextLabel("cp")
cmpTo(LDA, lh) ++
cmpTo(CMP, rh) ++
List(AssemblyLine.relative(BCC, innerLabel),
@ -660,7 +660,7 @@ object BuiltIns {
case _ =>
effectiveComparisonType match {
case ComparisonType.Equal =>
val innerLabel = MosCompiler.nextLabel("cp")
val innerLabel = ctx.nextLabel("cp")
val bytewise = l.zip(r).map{
case (cmpL, cmpR) => cmpTo(LDA, cmpL) ++ cmpTo(CMP, cmpR)
}
@ -838,7 +838,7 @@ object BuiltIns {
case Nil => Nil
case x :: Nil => staTo(DEC, x)
case x :: xs =>
val label = MosCompiler.nextLabel("de")
val label = ctx.nextLabel("de")
staTo(LDA, x) ++
List(AssemblyLine.relative(BNE, label)) ++
doDec(xs) ++
@ -867,7 +867,7 @@ object BuiltIns {
}
}
}
val label = MosCompiler.nextLabel("in")
val label = ctx.nextLabel("in")
return staTo(INC, targetBytes.head) ++ targetBytes.tail.flatMap(l => AssemblyLine.relative(BNE, label)::staTo(INC, l)) :+ AssemblyLine.label(label)
case Some(NumericConstant(-1, _)) if canUseIncDec && subtract =>
if (ctx.options.flags(CompilationFlag.Emit65CE02Opcodes)) {
@ -886,7 +886,7 @@ object BuiltIns {
}
}
}
val label = MosCompiler.nextLabel("in")
val label = ctx.nextLabel("in")
return staTo(INC, targetBytes.head) ++ targetBytes.tail.flatMap(l => AssemblyLine.relative(BNE, label)::staTo(INC, l)) :+ AssemblyLine.label(label)
case Some(NumericConstant(1, _)) if canUseIncDec && subtract =>
if (ctx.options.flags(CompilationFlag.Emit65CE02Opcodes)) {
@ -905,7 +905,7 @@ object BuiltIns {
}
}
}
val label = MosCompiler.nextLabel("de")
val label = ctx.nextLabel("de")
return doDec(targetBytes)
case Some(NumericConstant(-1, _)) if canUseIncDec && !subtract =>
if (ctx.options.flags(CompilationFlag.Emit65CE02Opcodes)) {
@ -924,7 +924,7 @@ object BuiltIns {
}
}
}
val label = MosCompiler.nextLabel("de")
val label = ctx.nextLabel("de")
return doDec(targetBytes)
case Some(constant) =>
addendSize = targetSize
@ -1053,7 +1053,7 @@ object BuiltIns {
} else {
if (i >= addendSize) {
if (addendType.isSigned) {
val label = MosCompiler.nextLabel("sx")
val label = ctx.nextLabel("sx")
buffer += AssemblyLine.implied(TXA)
if (i == addendSize) {
buffer += AssemblyLine.immediate(ORA, 0x7f)
@ -1176,7 +1176,7 @@ object BuiltIns {
}
} else {
if (paramType.isSigned) {
val label = MosCompiler.nextLabel("sx")
val label = ctx.nextLabel("sx")
buffer += AssemblyLine.implied(TXA)
if (i == paramSize) {
buffer += AssemblyLine.immediate(ORA, 0x7f)
@ -1233,7 +1233,7 @@ object BuiltIns {
if (i < variable.typ.size) {
AssemblyLine.variable(ctx, CMP, variable, i)
} else if (variable.typ.isSigned) {
val label = MosCompiler.nextLabel("sx")
val label = ctx.nextLabel("sx")
AssemblyLine.variable(ctx, LDA, variable, variable.typ.size - 1) ++ List(
AssemblyLine.immediate(ORA, 0x7F),
AssemblyLine.relative(BMI, label),

View File

@ -43,11 +43,11 @@ object DecimalBuiltIns {
}
private def shiftOrRotateAccumulatorRight(ctx: CompilationContext, rotate: Boolean, preserveCarry: Boolean) = {
val skipHiDigit = MosCompiler.nextLabel("ds")
val skipLoDigit = MosCompiler.nextLabel("ds")
val skipHiDigit = ctx.nextLabel("ds")
val skipLoDigit = ctx.nextLabel("ds")
val cmos = ctx.options.flags(CompilationFlag.EmitCmosOpcodes)
if (preserveCarry) {
val constantLabel = MosCompiler.nextLabel("c8")
val constantLabel = ctx.nextLabel("c8")
val bit = if (cmos) {
AssemblyLine.immediate(BIT, 8)
} else {

View File

@ -1,7 +1,5 @@
package millfork.compiler.mos
import java.util.concurrent.atomic.AtomicLong
import millfork.CompilationFlag
import millfork.assembly.mos.Opcode._
import millfork.assembly.mos._
@ -15,10 +13,6 @@ import millfork.env._
object MosCompiler extends AbstractCompiler[AssemblyLine] {
private val labelCounter = new AtomicLong
def nextLabel(prefix: String): String = "." + prefix + "__" + labelCounter.incrementAndGet().formatted("%05d")
override def compile(ctx: CompilationContext): List[AssemblyLine] = {
ctx.env.nameCheck(ctx.function.code)
val chunk = MosStatementCompiler.compile(ctx, ctx.function.code)

View File

@ -326,7 +326,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
exprType.size match {
case 1 => if (exprType.isSigned) {
AssemblyLine.variable(ctx, LDA, source) ++ List(
AssemblyLine.implied(PHA)) ++ signExtendA() ++ List(
AssemblyLine.implied(PHA)) ++ signExtendA(ctx) ++ List(
AssemblyLine.implied(XBA),
AssemblyLine.implied(PLA))
} else List(AssemblyLine.immediate(LDX, 0), AssemblyLine.implied(XBA)) ++ AssemblyLine.variable(ctx, LDA, source) :+ AssemblyLine.immediate(LDX, 0)
@ -340,7 +340,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
exprType.size match {
case 1 => if (exprType.isSigned) {
AssemblyLine.variable(ctx, LDA, source) ++ List(
AssemblyLine.implied(PHA)) ++ signExtendA() ++ List(
AssemblyLine.implied(PHA)) ++ signExtendA(ctx) ++ List(
AssemblyLine.implied(TAX),
AssemblyLine.implied(PLA))
} else AssemblyLine.variable(ctx, LDA, source) :+ AssemblyLine.immediate(LDX, 0)
@ -351,7 +351,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
exprType.size match {
case 1 => if (exprType.isSigned) {
AssemblyLine.variable(ctx, LDA, source) ++ List(
AssemblyLine.implied(PHA)) ++ signExtendA() ++ List(
AssemblyLine.implied(PHA)) ++ signExtendA(ctx) ++ List(
AssemblyLine.implied(TAY),
AssemblyLine.implied(PLA))
} else {
@ -363,7 +363,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case RegisterVariable(MosRegister.XA, _) =>
exprType.size match {
case 1 => if (exprType.isSigned) {
AssemblyLine.variable(ctx, LDX, source) ++ List(AssemblyLine.implied(TXA)) ++ signExtendA()
AssemblyLine.variable(ctx, LDX, source) ++ List(AssemblyLine.implied(TXA)) ++ signExtendA(ctx)
} else
AssemblyLine.variable(ctx, LDX, source) :+ AssemblyLine.immediate(LDA, 0)
case 2 =>
@ -372,7 +372,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case RegisterVariable(MosRegister.YA, _) =>
exprType.size match {
case 1 => if (exprType.isSigned) {
AssemblyLine.variable(ctx, LDY, source) ++ List(AssemblyLine.implied(TYA)) ++ signExtendA()
AssemblyLine.variable(ctx, LDY, source) ++ List(AssemblyLine.implied(TYA)) ++ signExtendA(ctx)
} else
AssemblyLine.variable(ctx, LDY, source) :+ AssemblyLine.immediate(LDA, 0)
case 2 =>
@ -386,7 +386,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
val copyFromLo = List.tabulate(exprType.size)(i => AssemblyLine.variable(ctx, LDA, source, i) ++ AssemblyLine.variable(ctx, STA, target, i))
val copy = if (shouldCopyFromHiToLo(source.toAddress, target.toAddress)) copyFromLo.reverse else copyFromLo
val extend = if (exprType.size == target.typ.size) Nil else if (exprType.isSigned) {
signExtendA() ++ List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.variable(ctx, STA, target, i + exprType.size)).flatten
signExtendA(ctx) ++ List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.variable(ctx, STA, target, i + exprType.size)).flatten
} else {
AssemblyLine.immediate(LDA, 0) ::
List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.variable(ctx, STA, target, i + exprType.size)).flatten
@ -400,7 +400,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
} else {
val copy = List.tabulate(exprType.size)(i => AssemblyLine.variable(ctx, LDA, source, i) :+ AssemblyLine.absoluteX(STA, target.baseOffset + ctx.extraStackOffset + i))
val extend = if (exprType.size == target.typ.size) Nil else if (exprType.isSigned) {
signExtendA() ++ List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.absoluteX(STA, target.baseOffset + ctx.extraStackOffset + i + exprType.size))
signExtendA(ctx) ++ List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.absoluteX(STA, target.baseOffset + ctx.extraStackOffset + i + exprType.size))
} else {
AssemblyLine.immediate(LDA, 0) ::
List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.absoluteX(STA, target.baseOffset + ctx.extraStackOffset + i + exprType.size))
@ -419,7 +419,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
List(
AssemblyLine.implied(TSX),
AssemblyLine.absoluteX(LDA, offset + ctx.extraStackOffset),
AssemblyLine.implied(PHA)) ++ signExtendA() ++ List(
AssemblyLine.implied(PHA)) ++ signExtendA(ctx) ++ List(
AssemblyLine.implied(TAX),
AssemblyLine.implied(PLA))
} else List(
@ -437,7 +437,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case RegisterVariable(MosRegister.AY, _) =>
exprType.size match {
case 1 => if (exprType.isSigned) {
val label = MosCompiler.nextLabel("sx")
val label = ctx.nextLabel("sx")
??? // TODO
} else {
List(
@ -455,7 +455,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case RegisterVariable(MosRegister.YA, _) =>
exprType.size match {
case 1 => if (exprType.isSigned) {
val label = MosCompiler.nextLabel("sx")
val label = ctx.nextLabel("sx")
??? // TODO
} else {
List(
@ -475,7 +475,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
} else {
val copy = List.tabulate(exprType.size)(i => AssemblyLine.absoluteX(LDA, offset + ctx.extraStackOffset + i) :: AssemblyLine.variable(ctx, STA, target, i))
val extend = if (exprType.size == target.typ.size) Nil else if (exprType.isSigned) {
signExtendA() ++ List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.variable(ctx, STA, target, i + exprType.size)).flatten
signExtendA(ctx) ++ List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.variable(ctx, STA, target, i + exprType.size)).flatten
} else {
AssemblyLine.immediate(LDA, 0) ::
List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.variable(ctx, STA, target, i + exprType.size)).flatten
@ -490,7 +490,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
val copyFromLo = List.tabulate(exprType.size)(i => List(AssemblyLine.absoluteX(LDA, offset + ctx.extraStackOffset + i), AssemblyLine.absoluteX(STA, target.baseOffset + i)))
val copy = if (shouldCopyFromHiToLo(NumericConstant(source.baseOffset, 2), NumericConstant(target.baseOffset, 2))) copyFromLo.reverse else copyFromLo
val extend = if (exprType.size == target.typ.size) Nil else if (exprType.isSigned) {
signExtendA() ++ List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.absoluteX(STA, target.baseOffset + ctx.extraStackOffset + i + exprType.size))
signExtendA(ctx) ++ List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.absoluteX(STA, target.baseOffset + ctx.extraStackOffset + i + exprType.size))
} else {
AssemblyLine.immediate(LDA, 0) ::
List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.absoluteX(STA, target.baseOffset + ctx.extraStackOffset + i + exprType.size))
@ -523,7 +523,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
AssemblyLine.variable(ctx, STA, target)
}
else if (target.typ.isSigned) {
AssemblyLine.variable(ctx, STA, target) ++ signExtendA() ++
AssemblyLine.variable(ctx, STA, target) ++ signExtendA(ctx) ++
List.tabulate(target.typ.size - 1)(i => AssemblyLine.variable(ctx, STA, target, i + 1)).flatten
} else {
AssemblyLine.variable(ctx, STA, target) ++
@ -697,7 +697,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
val compilation = compile(ctx, param, Some(MosExpressionCompiler.getExpressionType(ctx, param) -> RegisterVariable(MosRegister.AX, w)), BranchSpec.None)
if (hi) {
if (typ.size == 2) compilation :+ AssemblyLine.implied(TXA)
else if (typ.isSigned) compilation ++ signExtendA()
else if (typ.isSigned) compilation ++ signExtendA(ctx)
else List(AssemblyLine.immediate(LDA, 0))
} else compilation
}
@ -720,7 +720,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case _ =>
ctx.log.warn("Unspecified nonet operation, results might be unpredictable", expr.position)
}
val label = MosCompiler.nextLabel("no")
val label = ctx.nextLabel("no")
compile(ctx, params.head, Some(b -> RegisterVariable(MosRegister.A, b)), BranchSpec.None) ++ List(
AssemblyLine.immediate(LDX, 0),
AssemblyLine.relative(BCC, label),
@ -734,7 +734,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case BranchIfFalse(_) =>
params.flatMap(compile(ctx, _, exprTypeAndVariable, branches))
case _ =>
val skip = MosCompiler.nextLabel("an")
val skip = ctx.nextLabel("an")
params.init.flatMap(compile(ctx, _, exprTypeAndVariable, BranchIfFalse(skip))) ++
compile(ctx, params.last, exprTypeAndVariable, branches) ++
List(AssemblyLine.label(skip))
@ -745,7 +745,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case BranchIfTrue(_) =>
params.flatMap(compile(ctx, _, exprTypeAndVariable, branches))
case _ =>
val skip = MosCompiler.nextLabel("or")
val skip = ctx.nextLabel("or")
params.init.flatMap(compile(ctx, _, exprTypeAndVariable, BranchIfTrue(skip))) ++
compile(ctx, params.last, exprTypeAndVariable, branches) ++
List(AssemblyLine.label(skip))
@ -1189,7 +1189,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
AssemblyLine.variable(ctx, STA, v)
case s if s > 1 =>
if (t.isSigned) {
AssemblyLine.variable(ctx, STA, v) ++ signExtendA() ++ List.tabulate(s - 1)(i => AssemblyLine.variable(ctx, STA, v, i + 1)).flatten
AssemblyLine.variable(ctx, STA, v) ++ signExtendA(ctx) ++ List.tabulate(s - 1)(i => AssemblyLine.variable(ctx, STA, v, i + 1)).flatten
} else {
AssemblyLine.variable(ctx, STA, v) ++ List(AssemblyLine.immediate(LDA, 0)) ++
List.tabulate(s - 1)(i => AssemblyLine.variable(ctx, STA, v, i + 1)).flatten
@ -1206,7 +1206,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
AssemblyLine.variable(ctx, STA, v) ++
AssemblyLine.variable(ctx, STX, v, 1) ++
List(AssemblyLine.implied(TXA)) ++
signExtendA() ++
signExtendA(ctx) ++
List.tabulate(s - 2)(i => AssemblyLine.variable(ctx, STA, v, i + 2)).flatten
} else {
AssemblyLine.variable(ctx, STA, v) ++ AssemblyLine.variable(ctx, STX, v, 1) ++ List(
@ -1224,7 +1224,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
List(
AssemblyLine.implied(TSX),
AssemblyLine.absoluteX(STA, v.baseOffset + ctx.extraStackOffset)) ++
signExtendA() ++
signExtendA(ctx) ++
List.tabulate(s - 1)(i => AssemblyLine.absoluteX(STA, v.baseOffset + ctx.extraStackOffset + i + 1))
} else {
List(
@ -1293,7 +1293,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case _ =>
}
if (arrayLength > 0 && arrayLength < 255) {
val label = MosCompiler.nextLabel("bc")
val label = ctx.nextLabel("bc")
val compare = register match {
case MosRegister.A => CMP
case MosRegister.X => CPX
@ -1311,8 +1311,8 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
}
}
private def signExtendA(): List[AssemblyLine] = {
val label = MosCompiler.nextLabel("sx")
private def signExtendA(ctx: CompilationContext): List[AssemblyLine] = {
val label = ctx.nextLabel("sx")
List(
AssemblyLine.immediate(ORA, 0x7F),
AssemblyLine.relative(BMI, label),

View File

@ -10,7 +10,6 @@ import millfork.node._
* @author Karol Stasiak
*/
object MosMacroExpander extends MacroExpander[AssemblyLine] {
override def nextLabel(prefix: String): String = MosCompiler.nextLabel(prefix)
override def prepareAssemblyParams(ctx: CompilationContext, assParams: List[AssemblyParam], params: List[Expression], code: List[ExecutableStatement]): (List[AssemblyLine], List[ExecutableStatement]) = {
var paramPreparation = List[AssemblyLine]()

View File

@ -80,5 +80,4 @@ object MosReturnDispatch extends AbstractReturnDispatch[AssemblyLine] {
}
}
override def nextLabel(prefix: String): String = MosCompiler.nextLabel("di")
}

View File

@ -176,7 +176,7 @@ object MosStatementCompiler extends AbstractStatementCompiler[AssemblyLine] {
env.lookupFunction(name, params.map(p => MosExpressionCompiler.getExpressionType(ctx, p) -> p)) match {
case Some(i: MacroFunction) =>
val (paramPreparation, inlinedStatements) = MosMacroExpander.inlineFunction(ctx, i, params, e.position)
paramPreparation ++ compile(ctx.withInlinedEnv(i.environment, MosCompiler.nextLabel("en")), inlinedStatements)
paramPreparation ++ compile(ctx.withInlinedEnv(i.environment, ctx.nextLabel("en")), inlinedStatements)
case _ =>
MosExpressionCompiler.compile(ctx, e, None, NoBranching)
}
@ -308,8 +308,6 @@ object MosStatementCompiler extends AbstractStatementCompiler[AssemblyLine] {
AssemblyLine.implied(TSX) :: (List.fill(m.stackVariablesSize)(AssemblyLine.implied(INX)) :+ AssemblyLine.implied(TXS)) // this TXS is fine, it won't appear in 65816 code
}
override def nextLabel(prefix: String): String = MosCompiler.nextLabel(prefix)
override def getStatementPreprocessor(ctx: CompilationContext, statements: List[ExecutableStatement]): AbstractStatementPreprocessor =
new MosStatementPreprocessor(ctx, statements)
}

View File

@ -26,7 +26,7 @@ object PseudoregisterBuiltIns {
val typ = MosExpressionCompiler.getExpressionType(ctx, v)
if (typ.size == 1 && !typ.isSigned) {
val bytePart = MosExpressionCompiler.compile(ctx, v, Some(b -> RegisterVariable(MosRegister.A, b)), BranchSpec.None)
val label = MosCompiler.nextLabel("ah")
val label = ctx.nextLabel("ah")
return bytePart ++ List(
AssemblyLine.implied(CLC),
AssemblyLine.immediate(ADC, constPart.loByte),
@ -216,8 +216,8 @@ object PseudoregisterBuiltIns {
else List(AssemblyLine.implied(PLA), AssemblyLine.implied(TAX))
)
}
val labelRepeat = MosCompiler.nextLabel("sr")
val labelSkip = MosCompiler.nextLabel("ss")
val labelRepeat = ctx.nextLabel("sr")
val labelSkip = ctx.nextLabel("ss")
if (ctx.options.flag(CompilationFlag.EmitNative65816Opcodes)) {
compileCounterAndPrepareFirstParam ++ List(
AssemblyLine.relative(BEQ, labelSkip),

View File

@ -391,7 +391,7 @@ object Z80BulkMemoryOperations {
Z80ExpressionCompiler.stashHLIfChanged(ctx, extraInitializationPair._2)
}
val label = Z80Compiler.nextLabel("me")
val label = ctx.nextLabel("me")
val body = if (ldr.isDefined && ctx.options.flag(CompilationFlag.EmitZ80Opcodes)) {
List(ZLine.implied(ldr.get))
} else {

View File

@ -197,7 +197,7 @@ object Z80Comparisons {
val calculateRight = Z80ExpressionCompiler.compileByteReads(ctx, r, size, ZExpressionTarget.BC)
val preserveHl = isBytesFromHL(calculateLeft)
val preserveBc = isBytesFromBC(calculateRight)
val innerLabel = Z80Compiler.nextLabel("cp")
val innerLabel = ctx.nextLabel("cp")
val (jump, epilogue) = (compType, branches) match {
case (Equal, BranchIfTrue(label)) =>
ZLine.jump(innerLabel, IfFlagClear(ZFlag.Z)) -> ZLine.jump(label, IfFlagSet(ZFlag.Z))

View File

@ -1,12 +1,9 @@
package millfork.compiler.z80
import java.util.concurrent.atomic.AtomicLong
import millfork.CompilationFlag
import millfork.assembly.z80.ZLine
import millfork.compiler.{AbstractCompiler, CompilationContext}
import millfork.env.{Label, NormalParamSignature}
import millfork.error.ConsoleLogger
import millfork.node.ZRegister
/**
@ -14,10 +11,6 @@ import millfork.node.ZRegister
*/
object Z80Compiler extends AbstractCompiler[ZLine] {
private val labelCounter = new AtomicLong
override def nextLabel(prefix: String): String = "." + prefix + "__" + labelCounter.incrementAndGet().formatted("%05d")
override def compile(ctx: CompilationContext): List[ZLine] = {
ctx.env.nameCheck(ctx.function.code)
val chunk = Z80StatementCompiler.compile(ctx, ctx.function.code)

View File

@ -159,7 +159,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
def targetifyA(ctx: CompilationContext, target: ZExpressionTarget.Value, lines: List[ZLine], isSigned: Boolean): List[ZLine] = {
def toWord(h: ZRegister.Value, l: ZRegister.Value) = {
lines ++ (if (isSigned) {
val label = Z80Compiler.nextLabel("sx")
val label = ctx.nextLabel("sx")
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)) {
List(
ZLine.ld8(l, ZRegister.A),
@ -554,7 +554,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
case BranchIfFalse(_) =>
params.flatMap(compile(ctx, _, target, branches))
case _ =>
val skip = Z80Compiler.nextLabel("an")
val skip = ctx.nextLabel("an")
params.init.flatMap(compile(ctx, _, target, BranchIfFalse(skip))) ++
compile(ctx, params.last, target, branches) ++
List(ZLine.label(skip))
@ -565,7 +565,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
case BranchIfTrue(_) =>
params.flatMap(compile(ctx, _, target, branches))
case _ =>
val skip = Z80Compiler.nextLabel("or")
val skip = ctx.nextLabel("or")
params.init.flatMap(compile(ctx, _, target, BranchIfTrue(skip))) ++
compile(ctx, params.last, target, branches) ++
List(ZLine.label(skip))
@ -1011,7 +1011,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
private def signExtendHighestByte(ctx: CompilationContext, hiRegister: ZRegister.Value): List[ZLine] = {
val prefix = if (hiRegister == ZRegister.A) Nil else List(ZLine.ld8(ZRegister.A, hiRegister))
val label = Z80Compiler.nextLabel("sx")
val label = ctx.nextLabel("sx")
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)) {
prefix ++ List(
ZLine.imm8(OR, 0x7f),

View File

@ -12,7 +12,6 @@ import millfork.node._
* @author Karol Stasiak
*/
object Z80MacroExpander extends MacroExpander[ZLine] {
override def nextLabel(prefix: String): String = Z80Compiler.nextLabel(prefix)
override def prepareAssemblyParams(ctx: CompilationContext, assParams: List[AssemblyParam], params: List[Expression], code: List[ExecutableStatement]): (List[ZLine], List[ExecutableStatement]) = {
var paramPreparation = List[ZLine]()

View File

@ -19,9 +19,9 @@ object Z80Multiply {
import ZRegister._
import ZLine._
if(ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)) {
val lblAdd = Z80Compiler.nextLabel("mu")
val lblLoop = Z80Compiler.nextLabel("mu")
val lblStart = Z80Compiler.nextLabel("mu")
val lblAdd = ctx.nextLabel("mu")
val lblLoop = ctx.nextLabel("mu")
val lblStart = ctx.nextLabel("mu")
List(
ld8(E, A),
ldImm8(A, 0),
@ -36,9 +36,9 @@ object Z80Multiply {
jumpR(ctx, lblLoop, IfFlagClear(ZFlag.Z)))
} else {
// TODO: optimize
val lblAdd = Z80Compiler.nextLabel("mu")
val lblLoop = Z80Compiler.nextLabel("mu")
val lblStart = Z80Compiler.nextLabel("mu")
val lblAdd = ctx.nextLabel("mu")
val lblLoop = ctx.nextLabel("mu")
val lblStart = ctx.nextLabel("mu")
List(
ld8(E, A),
ldImm8(C, 0),

View File

@ -12,7 +12,6 @@ import scala.collection.mutable
* @author Karol Stasiak
*/
object Z80ReturnDispatch extends AbstractReturnDispatch[ZLine] {
override def nextLabel(prefix: String): String = Z80Compiler.nextLabel("di")
override def compileImpl(ctx: CompilationContext,
stmt: ReturnDispatchStatement,

View File

@ -44,7 +44,7 @@ object Z80Shifting {
val calcCount = Z80ExpressionCompiler.compile8BitTo(ctx, rhs, ZRegister.B)
val l = Z80ExpressionCompiler.stashBCIfChanged(ctx, Z80ExpressionCompiler.compileToA(ctx, lhs))
val loopBody = op :: fixAfterShiftIfNeeded(extendedOps, left, 1)
val label = Z80Compiler.nextLabel("sh")
val label = ctx.nextLabel("sh")
calcCount ++ l ++ List(ZLine.label(label)) ++ loopBody ++ ZLine.djnz(ctx, label)
}
}
@ -120,7 +120,7 @@ object Z80Shifting {
val calcCount = Z80ExpressionCompiler.compile8BitTo(ctx, rhs, ZRegister.B)
val l = Z80ExpressionCompiler.stashBCIfChanged(ctx, Z80ExpressionCompiler.compileToA(ctx, lhs))
val loopBody = ZLine.register(op, ZRegister.A) :: fixAfterShiftIfNeeded(extendedOps, left, 1)
val label = Z80Compiler.nextLabel("sh")
val label = ctx.nextLabel("sh")
calcCount ++ l ++ List(ZLine.label(label)) ++ loopBody ++ ZLine.djnz(ctx, label) ++ Z80ExpressionCompiler.storeA(ctx, lhs, signedSource = false)
}
}
@ -200,7 +200,7 @@ object Z80Shifting {
ZLine.ld8(ZRegister.L, ZRegister.A))
}
}
val label = Z80Compiler.nextLabel("sh")
val label = ctx.nextLabel("sh")
calcCount ++ l ++ List(ZLine.label(label)) ++ loopBody ++ ZLine.djnz(ctx, label)
}
}
@ -270,7 +270,7 @@ object Z80Shifting {
case Some(NumericConstant(n, _)) =>
List.fill(n.toInt)(shiftOne).flatten
case _ =>
val label = Z80Compiler.nextLabel("sh")
val label = ctx.nextLabel("sh")
val calcCount = Z80ExpressionCompiler.compile8BitTo(ctx, rhs, ZRegister.B)
calcCount ++ List(ZLine.label(label)) ++ shiftOne ++ ZLine.djnz(ctx, label)
}

View File

@ -148,7 +148,7 @@ object Z80StatementCompiler extends AbstractStatementCompiler[ZLine] {
env.lookupFunction(name, params.map(p => Z80ExpressionCompiler.getExpressionType(ctx, p) -> p)) match {
case Some(i: MacroFunction) =>
val (paramPreparation, inlinedStatements) = Z80MacroExpander.inlineFunction(ctx, i, params, e.position)
paramPreparation ++ compile(ctx.withInlinedEnv(i.environment, Z80Compiler.nextLabel("en")), inlinedStatements)
paramPreparation ++ compile(ctx.withInlinedEnv(i.environment, ctx.nextLabel("en")), inlinedStatements)
case _ =>
Z80ExpressionCompiler.compile(ctx, e, ZExpressionTarget.NOTHING)
}
@ -245,8 +245,6 @@ object Z80StatementCompiler extends AbstractStatementCompiler[ZLine] {
def areBlocksLarge(blocks: List[ZLine]*): Boolean = false
override def nextLabel(prefix: String): String = Z80Compiler.nextLabel(prefix)
override def compileExpressionForBranching(ctx: CompilationContext, expr: Expression, branching: BranchSpec): List[ZLine] =
Z80ExpressionCompiler.compile(ctx, expr, ZExpressionTarget.NOTHING, branching)

View File

@ -1,11 +1,10 @@
package millfork.env
import java.util.concurrent.atomic.AtomicLong
import millfork.assembly.BranchingOpcodeMapping
import millfork.{CompilationFlag, CompilationOptions, Cpu, CpuFamily}
import millfork._
import millfork.assembly.mos.Opcode
import millfork.assembly.z80.{IfFlagClear, IfFlagSet, ZFlag}
import millfork.compiler.LabelGenerator
import millfork.error.Logger
import millfork.node._
import millfork.output.{AllocationLocation, CompiledMemory, VariableAllocator}
@ -17,8 +16,12 @@ import scala.collection.mutable
* @author Karol Stasiak
*/
//noinspection NotImplementedCode
class Environment(val parent: Option[Environment], val prefix: String, val cpuFamily: CpuFamily.Value, val log: Logger) {
class Environment(val parent: Option[Environment], val prefix: String, val cpuFamily: CpuFamily.Value, val jobContext: JobContext) {
@inline
def log: Logger = jobContext.log
@inline
def nextLabel: LabelGenerator = jobContext.nextLabel
private var baseStackOffset: Int = cpuFamily match {
case CpuFamily.M6502 => 0x101
@ -31,7 +34,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
}
def genRelativeVariable(constant: Constant, typ: Type, zeropage: Boolean): RelativeVariable = {
val variable = RelativeVariable(".rv__" + Environment.relVarId.incrementAndGet().formatted("%06d"), constant, typ, zeropage = zeropage, declaredBank = None /*TODO*/)
val variable = RelativeVariable(nextLabel("rv"), constant, typ, zeropage = zeropage, declaredBank = None /*TODO*/)
addThing(variable, None)
variable
}
@ -45,7 +48,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
m.environment.getAllPrefixedThings
case _ => Map[String, Thing]()
}.fold(things.toMap)(_ ++ _)
val e = new Environment(None, "", cpuFamily, log)
val e = new Environment(None, "", cpuFamily, jobContext)
e.things.clear()
e.things ++= allThings
e
@ -685,7 +688,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
log.error(s"Non-macro function `$name` cannot have inlinable parameters", stmt.position)
}
val env = new Environment(Some(this), name + "$", cpuFamily, log)
val env = new Environment(Some(this), name + "$", cpuFamily, jobContext)
stmt.params.foreach(p => env.registerParameter(p, options))
val params = if (stmt.assembly) {
AssemblyParamSignature(stmt.params.map {
@ -1242,5 +1245,4 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
object Environment {
val predefinedFunctions = Set("not", "hi", "lo", "nonet")
val relVarId = new AtomicLong
}

View File

@ -473,7 +473,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
injectLabels(labelMap, inliningCalculator.inline(
compiler.compile(CompilationContext(env = f.environment, function = f, extraStackOffset = 0, options = options, niceFunctionProperties = niceFunctionProperties)),
inlinedFunctions,
compiler))
options.jobContext))
unoptimizedCodeSize += unoptimized.map(_.sizeInBytes).sum
val code = optimizations.foldLeft(unoptimized) { (c, opt) =>
opt.optimize(f, c, OptimizationContext(options, labelMap, env.maybeGet[ThingInMemory]("__reg"), niceFunctionProperties))

View File

@ -1,5 +1,6 @@
package millfork.output
import millfork.JobContext
import millfork.assembly.AbstractCode
import millfork.assembly.mos.Opcode
import millfork.assembly.z80.ZOpcode
@ -13,7 +14,7 @@ import scala.collection.mutable
*/
abstract class AbstractInliningCalculator[T <: AbstractCode] {
def codeForInlining(fname: String, functionsAlreadyKnownToBeNonInlineable: Set[String], code: List[T]): Option[List[T]]
def inline(code: List[T], inlinedFunctions: Map[String, List[T]], compiler: AbstractCompiler[T]): List[T]
def inline(code: List[T], inlinedFunctions: Map[String, List[T]], jobContext: JobContext): List[T]
private val sizes = Seq(64, 64, 8, 6, 5, 5, 4)

View File

@ -1,5 +1,6 @@
package millfork.output
import millfork.JobContext
import millfork.assembly.mos.Opcode._
import millfork.assembly.mos.{AddrMode, _}
import millfork.compiler.AbstractCompiler
@ -42,10 +43,10 @@ object MosInliningCalculator extends AbstractInliningCalculator[AssemblyLine] {
Some(result)
}
def inline(code: List[AssemblyLine], inlinedFunctions: Map[String, List[AssemblyLine]], compiler: AbstractCompiler[AssemblyLine]): List[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, true) if inlinedFunctions.contains(p.toString) =>
val labelPrefix = compiler.nextLabel("ai")
val labelPrefix = jobContext.nextLabel("ai")
inlinedFunctions(p.toString).map {
case line@AssemblyLine(_, _, MemoryAddressConstant(Label(label)), _) =>
val newLabel = MemoryAddressConstant(Label(labelPrefix + label))
@ -53,7 +54,7 @@ object MosInliningCalculator extends AbstractInliningCalculator[AssemblyLine] {
case l => l
}
case AssemblyLine(Opcode.JMP, AddrMode.Absolute, p, true) if inlinedFunctions.contains(p.toString) =>
val labelPrefix = compiler.nextLabel("ai")
val labelPrefix = jobContext.nextLabel("ai")
inlinedFunctions(p.toString).map {
case line@AssemblyLine(_, _, MemoryAddressConstant(Label(label)), _) =>
val newLabel = MemoryAddressConstant(Label(labelPrefix + label))

View File

@ -1,5 +1,6 @@
package millfork.output
import millfork.JobContext
import millfork.assembly.z80._
import millfork.compiler.AbstractCompiler
import millfork.env._
@ -41,22 +42,22 @@ object Z80InliningCalculator extends AbstractInliningCalculator[ZLine] {
Some(result)
}
def wrap(registers: ZRegisters, compiler: AbstractCompiler[ZLine], lines: List[ZLine]): List[ZLine] = registers match {
def wrap(registers: ZRegisters, jobContext: JobContext, lines: List[ZLine]): List[ZLine] = registers match {
case NoRegisters => lines
case IfFlagClear(flag) =>
val label = compiler.nextLabel("ai")
val label = jobContext.nextLabel("ai")
ZLine.jump(label, IfFlagSet(flag)) :: (lines :+ ZLine.label(label))
case IfFlagSet(flag) =>
val label = compiler.nextLabel("ai")
val label = jobContext.nextLabel("ai")
ZLine.jump(label, IfFlagClear(flag)) :: (lines :+ ZLine.label(label))
case _ => throw new IllegalArgumentException("registers")
}
override def inline(code: List[ZLine], inlinedFunctions: Map[String, List[ZLine]], compiler: AbstractCompiler[ZLine]): List[ZLine] = {
override def inline(code: List[ZLine], inlinedFunctions: Map[String, List[ZLine]], jobContext: JobContext): List[ZLine] = {
code.flatMap {
case ZLine(CALL, registers, p, true) if inlinedFunctions.contains(p.toString) =>
val labelPrefix = compiler.nextLabel("ai")
wrap(registers, compiler,
val labelPrefix = jobContext.nextLabel("ai")
wrap(registers, jobContext,
inlinedFunctions(p.toString).map {
case line@ZLine(_, _, MemoryAddressConstant(Label(label)), _) =>
val newLabel = MemoryAddressConstant(Label(labelPrefix + label))
@ -64,8 +65,8 @@ object Z80InliningCalculator extends AbstractInliningCalculator[ZLine] {
case l => l
})
case ZLine(JP | JR, registers, p, true) if inlinedFunctions.contains(p.toString) =>
val labelPrefix = compiler.nextLabel("ai")
wrap(registers, compiler,
val labelPrefix = jobContext.nextLabel("ai")
wrap(registers, jobContext,
inlinedFunctions(p.toString).map {
case line@ZLine(_, _, MemoryAddressConstant(Label(label)), _) =>
val newLabel = MemoryAddressConstant(Label(labelPrefix + label))

View File

@ -1,7 +1,8 @@
package millfork.test
import millfork.{CompilationOptions, Cpu, CpuFamily}
import millfork.{CompilationOptions, Cpu, CpuFamily, JobContext}
import millfork.assembly.z80.{LocalVariableAddressViaIX, NoRegisters, ZLine}
import millfork.compiler.LabelGenerator
import millfork.env.{Constant, Environment, NumericConstant}
import millfork.output.Z80Assembler
import millfork.test.emu._
@ -14,8 +15,9 @@ import org.scalatest.{FunSuite, Matchers}
class ZLineSizeSuite extends FunSuite with Matchers {
private def runCase(line: ZLine): Unit = {
val platform = EmuPlatform.get(Cpu.Z80)
val env = new Environment(None, "", CpuFamily.I80, TestErrorReporting.log)
val options = CompilationOptions(platform, Map(), None, 0, TestErrorReporting.log)
val jobContext = JobContext(TestErrorReporting.log, new LabelGenerator)
val env = new Environment(None, "", CpuFamily.I80, jobContext)
val options = CompilationOptions(platform, Map(), None, 0, jobContext)
val correctSize = new Z80Assembler(null, env, platform).emitInstruction("default", options, 0x100, line) - 0x100
val guessedSize = line.sizeInBytes
guessedSize should equal(correctSize)

View File

@ -9,7 +9,7 @@ import com.loomcom.symon.{Bus, Cpu, CpuState}
import fastparse.core.Parsed.{Failure, Success}
import millfork.assembly.AssemblyOptimization
import millfork.assembly.mos.AssemblyLine
import millfork.compiler.CompilationContext
import millfork.compiler.{CompilationContext, LabelGenerator}
import millfork.compiler.mos.MosCompiler
import millfork.env.{Environment, InitializedArray, InitializedMemoryVariable, NormalFunction}
import millfork.error.{ConsoleLogger, Logger}
@ -17,7 +17,7 @@ import millfork.node.StandardCallGraph
import millfork.node.opt.NodeOptimization
import millfork.output.{MemoryBank, MosAssembler}
import millfork.parser.{MosParser, Preprocessor}
import millfork.{CompilationFlag, CompilationOptions, CpuFamily}
import millfork.{CompilationFlag, CompilationOptions, CpuFamily, JobContext}
import org.scalatest.Matchers
import scala.collection.JavaConverters._
@ -113,7 +113,7 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization],
CompilationFlag.OptimizeForSpeed -> blastProcessing,
CompilationFlag.OptimizeForSonicSpeed -> blastProcessing
// CompilationFlag.CheckIndexOutOfBounds -> true,
), None, 2, log)
), None, 2, JobContext(log, new LabelGenerator))
log.hasErrors = false
log.verbosity = 999
var effectiveSource = source
@ -131,7 +131,7 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization],
// prepare
val program = nodeOptimizations.foldLeft(unoptimized)((p, opt) => p.applyNodeOptimization(opt, options))
val callGraph = new StandardCallGraph(program, log)
val env = new Environment(None, "", CpuFamily.M6502, log)
val env = new Environment(None, "", CpuFamily.M6502, options.jobContext)
env.collectDeclarations(program, options)
val hasOptimizations = assemblyOptimizations.nonEmpty
@ -151,7 +151,7 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization],
// compile
val env2 = new Environment(None, "", CpuFamily.M6502, log)
val env2 = new Environment(None, "", CpuFamily.M6502, options.jobContext)
env2.collectDeclarations(program, options)
val assembler = new MosAssembler(program, env2, platform)
val output = assembler.assemble(callGraph, assemblyOptimizations, options)

View File

@ -7,14 +7,14 @@ import eu.rekawek.coffeegb.gpu.Gpu
import fastparse.core.Parsed.{Failure, Success}
import millfork.assembly.AssemblyOptimization
import millfork.assembly.z80.ZLine
import millfork.compiler.CompilationContext
import millfork.compiler.{CompilationContext, LabelGenerator}
import millfork.env.{Environment, InitializedArray, InitializedMemoryVariable, NormalFunction}
import millfork.error.ConsoleLogger
import millfork.node.StandardCallGraph
import millfork.node.opt.NodeOptimization
import millfork.output.{MemoryBank, Z80Assembler}
import millfork.parser.{Preprocessor, Z80Parser}
import millfork.{CompilationFlag, CompilationOptions, CpuFamily}
import millfork.{CompilationFlag, CompilationOptions, CpuFamily, JobContext}
import millfork.compiler.z80.Z80Compiler
import org.scalatest.Matchers
@ -40,7 +40,7 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio
CompilationFlag.InlineFunctions -> this.inline,
CompilationFlag.EmitIllegals -> (cpu == millfork.Cpu.Z80),
CompilationFlag.LenientTextEncoding -> true)
val options = CompilationOptions(platform, millfork.Cpu.defaultFlags(cpu).map(_ -> true).toMap ++ extraFlags, None, 0, log)
val options = CompilationOptions(platform, millfork.Cpu.defaultFlags(cpu).map(_ -> true).toMap ++ extraFlags, None, 0, JobContext(log, new LabelGenerator))
log.hasErrors = false
log.verbosity = 999
var effectiveSource = source
@ -56,7 +56,7 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio
// prepare
val program = nodeOptimizations.foldLeft(unoptimized)((p, opt) => p.applyNodeOptimization(opt, options))
val callGraph = new StandardCallGraph(program, log)
val env = new Environment(None, "", CpuFamily.I80, log)
val env = new Environment(None, "", CpuFamily.I80, options.jobContext)
env.collectDeclarations(program, options)
val hasOptimizations = assemblyOptimizations.nonEmpty
@ -76,7 +76,7 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio
// compile
val env2 = new Environment(None, "", CpuFamily.I80, log)
val env2 = new Environment(None, "", CpuFamily.I80, options.jobContext)
env2.collectDeclarations(program, options)
val assembler = new Z80Assembler(program, env2, platform)
val output = assembler.assemble(callGraph, assemblyOptimizations, options)

View File

@ -4,13 +4,12 @@ import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Paths}
import fastparse.core.Parsed.{Failure, Success}
import millfork.compiler.CompilationContext
import millfork.compiler.{CompilationContext, LabelGenerator}
import millfork.compiler.mos.MosCompiler
import millfork.env.{Environment, InitializedArray, InitializedMemoryVariable, NormalFunction}
import millfork.error.{ConsoleLogger, FatalErrorReporting}
import millfork.node.StandardCallGraph
import millfork.parser.{MosParser, Preprocessor}
import millfork.{CompilationFlag, CompilationOptions, Cpu, CpuFamily}
import millfork._
import org.scalatest.Matchers
import scala.collection.JavaConverters._
@ -29,7 +28,7 @@ object ShouldNotCompile extends Matchers {
val log = TestErrorReporting.log
println(source)
val platform = EmuPlatform.get(cpu)
val options = CompilationOptions(platform, Map(CompilationFlag.LenientTextEncoding -> true), None, platform.zpRegisterSize, log)
val options = CompilationOptions(platform, Map(CompilationFlag.LenientTextEncoding -> true), None, platform.zpRegisterSize, JobContext(log, new LabelGenerator))
log.hasErrors = false
log.verbosity = 999
var effectiveSource = source
@ -46,7 +45,7 @@ object ShouldNotCompile extends Matchers {
// prepare
val callGraph = new StandardCallGraph(program, log)
val cpuFamily = CpuFamily.forType(cpu)
val env = new Environment(None, "", cpuFamily, log)
val env = new Environment(None, "", cpuFamily, options.jobContext)
env.collectDeclarations(program, options)
var unoptimizedSize = 0L