From e914ad6d7b63b0d16d8971600e14223fe450ec68 Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Tue, 31 Jul 2018 18:16:36 +0200 Subject: [PATCH] Move label generation into a separate class --- .../scala/millfork/CompilationOptions.scala | 14 +++- src/main/scala/millfork/JobContext.scala | 9 +++ src/main/scala/millfork/Main.scala | 9 ++- .../assembly/AssemblyOptimization.scala | 4 + .../millfork/assembly/mos/AssemblyLine.scala | 2 +- .../mos/opt/AlwaysGoodOptimizations.scala | 37 +++++----- .../opt/RuleBasedAssemblyOptimization.scala | 4 + .../assembly/mos/opt/SuperOptimizer.scala | 3 +- .../millfork/compiler/AbstractCompiler.scala | 1 - .../compiler/AbstractExpressionCompiler.scala | 2 +- .../compiler/AbstractReturnDispatch.scala | 4 +- .../compiler/AbstractStatementCompiler.scala | 74 +++++++++---------- .../compiler/CompilationContext.scala | 9 ++- .../millfork/compiler/LabelGenerator.scala | 13 ++++ .../millfork/compiler/MacroExpander.scala | 4 +- .../millfork/compiler/mos/BuiltIns.scala | 40 +++++----- .../compiler/mos/DecimalBuiltIns.scala | 6 +- .../millfork/compiler/mos/MosCompiler.scala | 6 -- .../compiler/mos/MosExpressionCompiler.scala | 46 ++++++------ .../compiler/mos/MosMacroExpander.scala | 1 - .../compiler/mos/MosReturnDispatch.scala | 1 - .../compiler/mos/MosStatementCompiler.scala | 4 +- .../compiler/mos/PseudoregisterBuiltIns.scala | 6 +- .../z80/Z80BulkMemoryOperations.scala | 2 +- .../compiler/z80/Z80Comparisons.scala | 2 +- .../millfork/compiler/z80/Z80Compiler.scala | 7 -- .../compiler/z80/Z80ExpressionCompiler.scala | 8 +- .../compiler/z80/Z80MacroExpander.scala | 1 - .../millfork/compiler/z80/Z80Multiply.scala | 12 +-- .../compiler/z80/Z80ReturnDispatch.scala | 1 - .../millfork/compiler/z80/Z80Shifting.scala | 8 +- .../compiler/z80/Z80StatementCompiler.scala | 4 +- src/main/scala/millfork/env/Environment.scala | 18 +++-- .../millfork/output/AbstractAssembler.scala | 2 +- .../output/AbstractInliningCalculator.scala | 3 +- .../output/MosInliningCalculator.scala | 7 +- .../output/Z80InliningCalculator.scala | 17 +++-- .../scala/millfork/test/ZLineSizeSuite.scala | 8 +- src/test/scala/millfork/test/emu/EmuRun.scala | 10 +-- .../scala/millfork/test/emu/EmuZ80Run.scala | 10 +-- .../millfork/test/emu/ShouldNotCompile.scala | 9 +-- 41 files changed, 225 insertions(+), 203 deletions(-) create mode 100644 src/main/scala/millfork/JobContext.scala create mode 100644 src/main/scala/millfork/compiler/LabelGenerator.scala diff --git a/src/main/scala/millfork/CompilationOptions.scala b/src/main/scala/millfork/CompilationOptions.scala index 54bfd414..7c21f583 100644 --- a/src/main/scala/millfork/CompilationOptions.scala +++ b/src/main/scala/millfork/CompilationOptions.scala @@ -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 diff --git a/src/main/scala/millfork/JobContext.scala b/src/main/scala/millfork/JobContext.scala new file mode 100644 index 00000000..e248e194 --- /dev/null +++ b/src/main/scala/millfork/JobContext.scala @@ -0,0 +1,9 @@ +package millfork + +import millfork.compiler.LabelGenerator +import millfork.error.Logger + +/** + * @author Karol Stasiak + */ +case class JobContext(log: Logger, nextLabel: LabelGenerator) diff --git a/src/main/scala/millfork/Main.scala b/src/main/scala/millfork/Main.scala index 7fc85374..3537bbe9 100644 --- a/src/main/scala/millfork/Main.scala +++ b/src/main/scala/millfork/Main.scala @@ -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 { diff --git a/src/main/scala/millfork/assembly/AssemblyOptimization.scala b/src/main/scala/millfork/assembly/AssemblyOptimization.scala index 94d2ec57..9b23665b 100644 --- a/src/main/scala/millfork/assembly/AssemblyOptimization.scala +++ b/src/main/scala/millfork/assembly/AssemblyOptimization.scala @@ -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] { diff --git a/src/main/scala/millfork/assembly/mos/AssemblyLine.scala b/src/main/scala/millfork/assembly/mos/AssemblyLine.scala index a35d6870..4325aaf1 100644 --- a/src/main/scala/millfork/assembly/mos/AssemblyLine.scala +++ b/src/main/scala/millfork/assembly/mos/AssemblyLine.scala @@ -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), diff --git a/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala b/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala index 9008a1e0..4f9eb463 100644 --- a/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala +++ b/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala @@ -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 diff --git a/src/main/scala/millfork/assembly/mos/opt/RuleBasedAssemblyOptimization.scala b/src/main/scala/millfork/assembly/mos/opt/RuleBasedAssemblyOptimization.scala index 97542c14..3c50d3d2 100644 --- a/src/main/scala/millfork/assembly/mos/opt/RuleBasedAssemblyOptimization.scala +++ b/src/main/scala/millfork/assembly/mos/opt/RuleBasedAssemblyOptimization.scala @@ -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) diff --git a/src/main/scala/millfork/assembly/mos/opt/SuperOptimizer.scala b/src/main/scala/millfork/assembly/mos/opt/SuperOptimizer.scala index 7f01e002..ec16d7a3 100644 --- a/src/main/scala/millfork/assembly/mos/opt/SuperOptimizer.scala +++ b/src/main/scala/millfork/assembly/mos/opt/SuperOptimizer.scala @@ -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)) diff --git a/src/main/scala/millfork/compiler/AbstractCompiler.scala b/src/main/scala/millfork/compiler/AbstractCompiler.scala index e97e2676..5aeec494 100644 --- a/src/main/scala/millfork/compiler/AbstractCompiler.scala +++ b/src/main/scala/millfork/compiler/AbstractCompiler.scala @@ -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] } diff --git a/src/main/scala/millfork/compiler/AbstractExpressionCompiler.scala b/src/main/scala/millfork/compiler/AbstractExpressionCompiler.scala index d5b4f1ca..d147e521 100644 --- a/src/main/scala/millfork/compiler/AbstractExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/AbstractExpressionCompiler.scala @@ -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) } diff --git a/src/main/scala/millfork/compiler/AbstractReturnDispatch.scala b/src/main/scala/millfork/compiler/AbstractReturnDispatch.scala index 022af30e..23b6804b 100644 --- a/src/main/scala/millfork/compiler/AbstractReturnDispatch.scala +++ b/src/main/scala/millfork/compiler/AbstractReturnDispatch.scala @@ -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, diff --git a/src/main/scala/millfork/compiler/AbstractStatementCompiler.scala b/src/main/scala/millfork/compiler/AbstractStatementCompiler.scala index 7fadc53e..d915c98c 100644 --- a/src/main/scala/millfork/compiler/AbstractStatementCompiler.scala +++ b/src/main/scala/millfork/compiler/AbstractStatementCompiler.scala @@ -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 } diff --git a/src/main/scala/millfork/compiler/CompilationContext.scala b/src/main/scala/millfork/compiler/CompilationContext.scala index ac72a2ee..4b7b7ef1 100644 --- a/src/main/scala/millfork/compiler/CompilationContext.scala +++ b/src/main/scala/millfork/compiler/CompilationContext.scala @@ -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 } diff --git a/src/main/scala/millfork/compiler/LabelGenerator.scala b/src/main/scala/millfork/compiler/LabelGenerator.scala new file mode 100644 index 00000000..d8c8a859 --- /dev/null +++ b/src/main/scala/millfork/compiler/LabelGenerator.scala @@ -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") +} diff --git a/src/main/scala/millfork/compiler/MacroExpander.scala b/src/main/scala/millfork/compiler/MacroExpander.scala index f299dae2..70eb2f17 100644 --- a/src/main/scala/millfork/compiler/MacroExpander.scala +++ b/src/main/scala/millfork/compiler/MacroExpander.scala @@ -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)) diff --git a/src/main/scala/millfork/compiler/mos/BuiltIns.scala b/src/main/scala/millfork/compiler/mos/BuiltIns.scala index 2a485561..9eccb2ee 100644 --- a/src/main/scala/millfork/compiler/mos/BuiltIns.scala +++ b/src/main/scala/millfork/compiler/mos/BuiltIns.scala @@ -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), diff --git a/src/main/scala/millfork/compiler/mos/DecimalBuiltIns.scala b/src/main/scala/millfork/compiler/mos/DecimalBuiltIns.scala index 7bfe6ac4..c6d10acd 100644 --- a/src/main/scala/millfork/compiler/mos/DecimalBuiltIns.scala +++ b/src/main/scala/millfork/compiler/mos/DecimalBuiltIns.scala @@ -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 { diff --git a/src/main/scala/millfork/compiler/mos/MosCompiler.scala b/src/main/scala/millfork/compiler/mos/MosCompiler.scala index fd232c13..5e612476 100644 --- a/src/main/scala/millfork/compiler/mos/MosCompiler.scala +++ b/src/main/scala/millfork/compiler/mos/MosCompiler.scala @@ -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) diff --git a/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala b/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala index 166a8f27..3616f9e2 100644 --- a/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala @@ -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), diff --git a/src/main/scala/millfork/compiler/mos/MosMacroExpander.scala b/src/main/scala/millfork/compiler/mos/MosMacroExpander.scala index 03dafe37..1a61b23c 100644 --- a/src/main/scala/millfork/compiler/mos/MosMacroExpander.scala +++ b/src/main/scala/millfork/compiler/mos/MosMacroExpander.scala @@ -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]() diff --git a/src/main/scala/millfork/compiler/mos/MosReturnDispatch.scala b/src/main/scala/millfork/compiler/mos/MosReturnDispatch.scala index a0825d07..fa9d303b 100644 --- a/src/main/scala/millfork/compiler/mos/MosReturnDispatch.scala +++ b/src/main/scala/millfork/compiler/mos/MosReturnDispatch.scala @@ -80,5 +80,4 @@ object MosReturnDispatch extends AbstractReturnDispatch[AssemblyLine] { } } - override def nextLabel(prefix: String): String = MosCompiler.nextLabel("di") } diff --git a/src/main/scala/millfork/compiler/mos/MosStatementCompiler.scala b/src/main/scala/millfork/compiler/mos/MosStatementCompiler.scala index c1823e0c..b6a2d03d 100644 --- a/src/main/scala/millfork/compiler/mos/MosStatementCompiler.scala +++ b/src/main/scala/millfork/compiler/mos/MosStatementCompiler.scala @@ -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) } diff --git a/src/main/scala/millfork/compiler/mos/PseudoregisterBuiltIns.scala b/src/main/scala/millfork/compiler/mos/PseudoregisterBuiltIns.scala index 50525edd..e63aa7d9 100644 --- a/src/main/scala/millfork/compiler/mos/PseudoregisterBuiltIns.scala +++ b/src/main/scala/millfork/compiler/mos/PseudoregisterBuiltIns.scala @@ -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), diff --git a/src/main/scala/millfork/compiler/z80/Z80BulkMemoryOperations.scala b/src/main/scala/millfork/compiler/z80/Z80BulkMemoryOperations.scala index e58eedc3..0fb70b6c 100644 --- a/src/main/scala/millfork/compiler/z80/Z80BulkMemoryOperations.scala +++ b/src/main/scala/millfork/compiler/z80/Z80BulkMemoryOperations.scala @@ -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 { diff --git a/src/main/scala/millfork/compiler/z80/Z80Comparisons.scala b/src/main/scala/millfork/compiler/z80/Z80Comparisons.scala index 83a9f2de..8751b878 100644 --- a/src/main/scala/millfork/compiler/z80/Z80Comparisons.scala +++ b/src/main/scala/millfork/compiler/z80/Z80Comparisons.scala @@ -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)) diff --git a/src/main/scala/millfork/compiler/z80/Z80Compiler.scala b/src/main/scala/millfork/compiler/z80/Z80Compiler.scala index 3c0a45da..3b7cab05 100644 --- a/src/main/scala/millfork/compiler/z80/Z80Compiler.scala +++ b/src/main/scala/millfork/compiler/z80/Z80Compiler.scala @@ -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) diff --git a/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala b/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala index 5e2fb811..62694f32 100644 --- a/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala @@ -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), diff --git a/src/main/scala/millfork/compiler/z80/Z80MacroExpander.scala b/src/main/scala/millfork/compiler/z80/Z80MacroExpander.scala index 543a0db2..59bb112a 100644 --- a/src/main/scala/millfork/compiler/z80/Z80MacroExpander.scala +++ b/src/main/scala/millfork/compiler/z80/Z80MacroExpander.scala @@ -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]() diff --git a/src/main/scala/millfork/compiler/z80/Z80Multiply.scala b/src/main/scala/millfork/compiler/z80/Z80Multiply.scala index 080729ee..98594c7a 100644 --- a/src/main/scala/millfork/compiler/z80/Z80Multiply.scala +++ b/src/main/scala/millfork/compiler/z80/Z80Multiply.scala @@ -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), diff --git a/src/main/scala/millfork/compiler/z80/Z80ReturnDispatch.scala b/src/main/scala/millfork/compiler/z80/Z80ReturnDispatch.scala index 9ec839ac..a6fa8d53 100644 --- a/src/main/scala/millfork/compiler/z80/Z80ReturnDispatch.scala +++ b/src/main/scala/millfork/compiler/z80/Z80ReturnDispatch.scala @@ -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, diff --git a/src/main/scala/millfork/compiler/z80/Z80Shifting.scala b/src/main/scala/millfork/compiler/z80/Z80Shifting.scala index 158e2705..3cfd99dd 100644 --- a/src/main/scala/millfork/compiler/z80/Z80Shifting.scala +++ b/src/main/scala/millfork/compiler/z80/Z80Shifting.scala @@ -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) } diff --git a/src/main/scala/millfork/compiler/z80/Z80StatementCompiler.scala b/src/main/scala/millfork/compiler/z80/Z80StatementCompiler.scala index bc1dddc4..f358c7e9 100644 --- a/src/main/scala/millfork/compiler/z80/Z80StatementCompiler.scala +++ b/src/main/scala/millfork/compiler/z80/Z80StatementCompiler.scala @@ -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) diff --git a/src/main/scala/millfork/env/Environment.scala b/src/main/scala/millfork/env/Environment.scala index 6670c7ae..71de7dc9 100644 --- a/src/main/scala/millfork/env/Environment.scala +++ b/src/main/scala/millfork/env/Environment.scala @@ -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 } diff --git a/src/main/scala/millfork/output/AbstractAssembler.scala b/src/main/scala/millfork/output/AbstractAssembler.scala index 8f489238..a92948d8 100644 --- a/src/main/scala/millfork/output/AbstractAssembler.scala +++ b/src/main/scala/millfork/output/AbstractAssembler.scala @@ -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)) diff --git a/src/main/scala/millfork/output/AbstractInliningCalculator.scala b/src/main/scala/millfork/output/AbstractInliningCalculator.scala index da2bf25b..e68bea65 100644 --- a/src/main/scala/millfork/output/AbstractInliningCalculator.scala +++ b/src/main/scala/millfork/output/AbstractInliningCalculator.scala @@ -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) diff --git a/src/main/scala/millfork/output/MosInliningCalculator.scala b/src/main/scala/millfork/output/MosInliningCalculator.scala index 5f79b087..67606ba7 100644 --- a/src/main/scala/millfork/output/MosInliningCalculator.scala +++ b/src/main/scala/millfork/output/MosInliningCalculator.scala @@ -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)) diff --git a/src/main/scala/millfork/output/Z80InliningCalculator.scala b/src/main/scala/millfork/output/Z80InliningCalculator.scala index 63fd240f..7f54c1f3 100644 --- a/src/main/scala/millfork/output/Z80InliningCalculator.scala +++ b/src/main/scala/millfork/output/Z80InliningCalculator.scala @@ -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)) diff --git a/src/test/scala/millfork/test/ZLineSizeSuite.scala b/src/test/scala/millfork/test/ZLineSizeSuite.scala index 30c657cf..38933abb 100644 --- a/src/test/scala/millfork/test/ZLineSizeSuite.scala +++ b/src/test/scala/millfork/test/ZLineSizeSuite.scala @@ -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) diff --git a/src/test/scala/millfork/test/emu/EmuRun.scala b/src/test/scala/millfork/test/emu/EmuRun.scala index dd436795..c3a12d5c 100644 --- a/src/test/scala/millfork/test/emu/EmuRun.scala +++ b/src/test/scala/millfork/test/emu/EmuRun.scala @@ -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) diff --git a/src/test/scala/millfork/test/emu/EmuZ80Run.scala b/src/test/scala/millfork/test/emu/EmuZ80Run.scala index 524f7b68..40d14af7 100644 --- a/src/test/scala/millfork/test/emu/EmuZ80Run.scala +++ b/src/test/scala/millfork/test/emu/EmuZ80Run.scala @@ -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) diff --git a/src/test/scala/millfork/test/emu/ShouldNotCompile.scala b/src/test/scala/millfork/test/emu/ShouldNotCompile.scala index 0c937f5c..05687859 100644 --- a/src/test/scala/millfork/test/emu/ShouldNotCompile.scala +++ b/src/test/scala/millfork/test/emu/ShouldNotCompile.scala @@ -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