cleaning up AsmGen interface

This commit is contained in:
Irmen de Jong 2022-02-06 17:07:03 +01:00
parent f538c9f0c3
commit 6bdd81623f
18 changed files with 154 additions and 81 deletions

View File

@ -26,8 +26,7 @@ const val subroutineFloatEvalResultVar2 = "prog8_float_eval_result2"
class AsmGen6502(internal val program: Program, class AsmGen6502(internal val program: Program,
internal val errors: IErrorReporter, internal val errors: IErrorReporter,
internal val options: CompilationOptions, internal val options: CompilationOptions): IAssemblyGenerator {
internal val outputDir: Path): IAssemblyGenerator {
// for expressions and augmented assignments: // for expressions and augmented assignments:
val optimizedByteMultiplications = setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40,50,80,100) val optimizedByteMultiplications = setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40,50,80,100)
@ -76,7 +75,7 @@ class AsmGen6502(internal val program: Program,
slaballocations() slaballocations()
footer() footer()
val output = outputDir.resolve("${program.name}.asm") val output = options.outputDir.resolve("${program.name}.asm")
if(options.optimize) { if(options.optimize) {
val separateLines = assemblyLines.flatMapTo(mutableListOf()) { it.split('\n') } val separateLines = assemblyLines.flatMapTo(mutableListOf()) { it.split('\n') }
assemblyLines.clear() assemblyLines.clear()
@ -90,7 +89,7 @@ class AsmGen6502(internal val program: Program,
} }
return if(errors.noErrors()) return if(errors.noErrors())
AssemblyProgram(program.name, outputDir, compTarget.name) AssemblyProgram(program.name, options.outputDir, compTarget.name)
else { else {
errors.report() errors.report()
return null return null
@ -1591,7 +1590,7 @@ $repeatLabel lda $counterVar
TODO("%asmbinary inside non-library, non-filesystem module") TODO("%asmbinary inside non-library, non-filesystem module")
val sourcePath = Path(stmt.definingModule.source.origin) val sourcePath = Path(stmt.definingModule.source.origin)
val includedPath = sourcePath.resolveSibling(includedName) val includedPath = sourcePath.resolveSibling(includedName)
val pathForAssembler = outputDir // #54: 64tass needs the path *relative to the .asm file* val pathForAssembler = options.outputDir // #54: 64tass needs the path *relative to the .asm file*
.toAbsolutePath() .toAbsolutePath()
.relativize(includedPath.toAbsolutePath()) .relativize(includedPath.toAbsolutePath())
.normalize() // avoid assembler warnings (-Wportable; only some, not all) .normalize() // avoid assembler warnings (-Wportable; only some, not all)

View File

@ -5,18 +5,16 @@ import prog8.compilerinterface.CompilationOptions
import prog8.compilerinterface.IAssemblyGenerator import prog8.compilerinterface.IAssemblyGenerator
import prog8.compilerinterface.IAssemblyProgram import prog8.compilerinterface.IAssemblyProgram
import prog8.compilerinterface.IErrorReporter import prog8.compilerinterface.IErrorReporter
import java.nio.file.Path
class ExperimentalAsmGen6502(internal val program: Program, class ExperimentalAsmGen6502(internal val program: Program,
internal val errors: IErrorReporter, internal val errors: IErrorReporter,
internal val options: CompilationOptions, internal val options: CompilationOptions
internal val outputDir: Path
): IAssemblyGenerator { ): IAssemblyGenerator {
override fun compileToAssembly(): IAssemblyProgram? { override fun compileToAssembly(): IAssemblyProgram? {
println("\n** experimental 65(c)02 code generator **\n") println("\n** experimental 65(c)02 code generator **\n")
println("..todo: create assembly code..") println("..todo: create assembly code into ${options.outputDir.toAbsolutePath()}..")
return AssemblyProgram("dummy") return AssemblyProgram("dummy")
} }
} }

View File

@ -1,20 +1,18 @@
package prog8.codegen.target package prog8.codegen.target
import prog8.ast.base.ByteDatatypes
import prog8.ast.base.DataType
import prog8.ast.base.PassByReferenceDatatypes
import prog8.ast.base.WordDatatypes
import prog8.ast.expressions.Expression import prog8.ast.expressions.Expression
import prog8.ast.statements.RegisterOrStatusflag import prog8.ast.statements.RegisterOrStatusflag
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.codegen.target.c128.C128MachineDefinition import prog8.codegen.target.c128.C128MachineDefinition
import prog8.codegen.target.cbm.CbmMemorySizer
import prog8.codegen.target.cbm.asmsub6502ArgsEvalOrder import prog8.codegen.target.cbm.asmsub6502ArgsEvalOrder
import prog8.codegen.target.cbm.asmsub6502ArgsHaveRegisterClobberRisk import prog8.codegen.target.cbm.asmsub6502ArgsHaveRegisterClobberRisk
import prog8.compilerinterface.ICompilationTarget import prog8.compilerinterface.ICompilationTarget
import prog8.compilerinterface.IMemSizer
import prog8.compilerinterface.IStringEncoding import prog8.compilerinterface.IStringEncoding
object C128Target: ICompilationTarget, IStringEncoding by Encoder { object C128Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by CbmMemorySizer {
override val name = "c128" override val name = "c128"
override val machine = C128MachineDefinition() override val machine = C128MachineDefinition()
@ -22,13 +20,4 @@ object C128Target: ICompilationTarget, IStringEncoding by Encoder {
asmsub6502ArgsEvalOrder(sub) asmsub6502ArgsEvalOrder(sub)
override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>, paramRegisters: List<RegisterOrStatusflag>) = override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>, paramRegisters: List<RegisterOrStatusflag>) =
asmsub6502ArgsHaveRegisterClobberRisk(args, paramRegisters) asmsub6502ArgsHaveRegisterClobberRisk(args, paramRegisters)
override fun memorySize(dt: DataType): Int {
return when(dt) {
in ByteDatatypes -> 1
in WordDatatypes, in PassByReferenceDatatypes -> 2
DataType.FLOAT -> machine.FLOAT_MEM_SIZE
else -> Int.MIN_VALUE
}
}
} }

View File

@ -1,20 +1,18 @@
package prog8.codegen.target package prog8.codegen.target
import prog8.ast.base.ByteDatatypes
import prog8.ast.base.DataType
import prog8.ast.base.PassByReferenceDatatypes
import prog8.ast.base.WordDatatypes
import prog8.ast.expressions.Expression import prog8.ast.expressions.Expression
import prog8.ast.statements.RegisterOrStatusflag import prog8.ast.statements.RegisterOrStatusflag
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.codegen.target.c64.C64MachineDefinition import prog8.codegen.target.c64.C64MachineDefinition
import prog8.codegen.target.cbm.CbmMemorySizer
import prog8.codegen.target.cbm.asmsub6502ArgsEvalOrder import prog8.codegen.target.cbm.asmsub6502ArgsEvalOrder
import prog8.codegen.target.cbm.asmsub6502ArgsHaveRegisterClobberRisk import prog8.codegen.target.cbm.asmsub6502ArgsHaveRegisterClobberRisk
import prog8.compilerinterface.ICompilationTarget import prog8.compilerinterface.ICompilationTarget
import prog8.compilerinterface.IMemSizer
import prog8.compilerinterface.IStringEncoding import prog8.compilerinterface.IStringEncoding
object C64Target: ICompilationTarget, IStringEncoding by Encoder { object C64Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by CbmMemorySizer {
override val name = "c64" override val name = "c64"
override val machine = C64MachineDefinition() override val machine = C64MachineDefinition()
@ -22,13 +20,4 @@ object C64Target: ICompilationTarget, IStringEncoding by Encoder {
asmsub6502ArgsEvalOrder(sub) asmsub6502ArgsEvalOrder(sub)
override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>, paramRegisters: List<RegisterOrStatusflag>) = override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>, paramRegisters: List<RegisterOrStatusflag>) =
asmsub6502ArgsHaveRegisterClobberRisk(args, paramRegisters) asmsub6502ArgsHaveRegisterClobberRisk(args, paramRegisters)
override fun memorySize(dt: DataType): Int {
return when(dt) {
in ByteDatatypes -> 1
in WordDatatypes, in PassByReferenceDatatypes -> 2
DataType.FLOAT -> machine.FLOAT_MEM_SIZE
else -> Int.MIN_VALUE
}
}
} }

View File

@ -1,20 +1,18 @@
package prog8.codegen.target package prog8.codegen.target
import prog8.ast.base.ByteDatatypes
import prog8.ast.base.DataType
import prog8.ast.base.PassByReferenceDatatypes
import prog8.ast.base.WordDatatypes
import prog8.ast.expressions.Expression import prog8.ast.expressions.Expression
import prog8.ast.statements.RegisterOrStatusflag import prog8.ast.statements.RegisterOrStatusflag
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.codegen.target.cbm.CbmMemorySizer
import prog8.codegen.target.cbm.asmsub6502ArgsEvalOrder import prog8.codegen.target.cbm.asmsub6502ArgsEvalOrder
import prog8.codegen.target.cbm.asmsub6502ArgsHaveRegisterClobberRisk import prog8.codegen.target.cbm.asmsub6502ArgsHaveRegisterClobberRisk
import prog8.codegen.target.cx16.CX16MachineDefinition import prog8.codegen.target.cx16.CX16MachineDefinition
import prog8.compilerinterface.ICompilationTarget import prog8.compilerinterface.ICompilationTarget
import prog8.compilerinterface.IMemSizer
import prog8.compilerinterface.IStringEncoding import prog8.compilerinterface.IStringEncoding
object Cx16Target: ICompilationTarget, IStringEncoding by Encoder { object Cx16Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by CbmMemorySizer {
override val name = "cx16" override val name = "cx16"
override val machine = CX16MachineDefinition() override val machine = CX16MachineDefinition()
@ -22,14 +20,4 @@ object Cx16Target: ICompilationTarget, IStringEncoding by Encoder {
asmsub6502ArgsEvalOrder(sub) asmsub6502ArgsEvalOrder(sub)
override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>, paramRegisters: List<RegisterOrStatusflag>) = override fun asmsubArgsHaveRegisterClobberRisk(args: List<Expression>, paramRegisters: List<RegisterOrStatusflag>) =
asmsub6502ArgsHaveRegisterClobberRisk(args, paramRegisters) asmsub6502ArgsHaveRegisterClobberRisk(args, paramRegisters)
override fun memorySize(dt: DataType): Int {
return when(dt) {
in ByteDatatypes -> 1
in WordDatatypes, in PassByReferenceDatatypes -> 2
DataType.FLOAT -> machine.FLOAT_MEM_SIZE
else -> Int.MIN_VALUE
}
}
} }

View File

@ -0,0 +1,31 @@
package prog8.codegen.target.cbm
import prog8.ast.base.*
import prog8.ast.expressions.StringLiteralValue
import prog8.ast.statements.VarDecl
import prog8.compilerinterface.IMemSizer
internal object CbmMemorySizer: IMemSizer {
override fun memorySize(dt: DataType): Int {
return when(dt) {
in ByteDatatypes -> 1
in WordDatatypes, in PassByReferenceDatatypes -> 2
DataType.FLOAT -> Mflpt5.FLOAT_MEM_SIZE
else -> Int.MIN_VALUE
}
}
override fun memorySize(decl: VarDecl): Int {
return when(decl.type) {
VarDeclType.CONST -> 0
VarDeclType.VAR, VarDeclType.MEMORY -> {
when(val dt = decl.datatype) {
in NumericDatatypes -> return memorySize(dt)
in ArrayDatatypes -> decl.arraysize!!.constIndex()!! * memorySize(ArrayToElementTypes.getValue(dt))
DataType.STR -> (decl.value as StringLiteralValue).value.length + 1
else -> 0
}
}
}
}
}

View File

@ -75,6 +75,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult {
asmQuiet = args.quietAssembler asmQuiet = args.quietAssembler
asmListfile = args.asmListfile asmListfile = args.asmListfile
experimentalCodegen = args.experimentalCodegen experimentalCodegen = args.experimentalCodegen
outputDir = args.outputDir.normalize()
} }
program = programresult program = programresult
importedFiles = imported importedFiles = imported
@ -97,7 +98,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult {
// printProgram(program) // printProgram(program)
if (args.writeAssembly) { if (args.writeAssembly) {
when (val result = writeAssembly(program, args.errors, args.outputDir, compilationOptions)) { when (val result = writeAssembly(program, args.errors, compilationOptions)) {
is WriteAssemblyResult.Ok -> programName = result.filename is WriteAssemblyResult.Ok -> programName = result.filename
is WriteAssemblyResult.Fail -> { is WriteAssemblyResult.Fail -> {
System.err.println(result.error) System.err.println(result.error)
@ -339,7 +340,6 @@ private sealed class WriteAssemblyResult {
private fun writeAssembly(program: Program, private fun writeAssembly(program: Program,
errors: IErrorReporter, errors: IErrorReporter,
outputDir: Path,
compilerOptions: CompilationOptions compilerOptions: CompilationOptions
): WriteAssemblyResult { ): WriteAssemblyResult {
// asm generation directly from the Ast // asm generation directly from the Ast
@ -350,11 +350,7 @@ private fun writeAssembly(program: Program,
// printProgram(program) // printProgram(program)
compilerOptions.compTarget.machine.initializeZeropage(compilerOptions) compilerOptions.compTarget.machine.initializeZeropage(compilerOptions)
val assembly = asmGeneratorFor( val assembly = asmGeneratorFor(program, errors, compilerOptions).compileToAssembly()
program,
errors,
compilerOptions,
outputDir).compileToAssembly()
errors.report() errors.report()
return if(assembly!=null && errors.noErrors()) { return if(assembly!=null && errors.noErrors()) {
@ -378,15 +374,14 @@ internal fun asmGeneratorFor(
program: Program, program: Program,
errors: IErrorReporter, errors: IErrorReporter,
options: CompilationOptions, options: CompilationOptions,
outputDir: Path
): IAssemblyGenerator ): IAssemblyGenerator
{ {
if(options.experimentalCodegen) { if(options.experimentalCodegen) {
if (options.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02)) if (options.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02))
return ExperimentalAsmGen6502(program, errors, options, outputDir) return ExperimentalAsmGen6502(program, errors, options)
} else { } else {
if (options.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02)) if (options.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02))
return AsmGen6502(program, errors, options, outputDir) return AsmGen6502(program, errors, options)
} }
throw NotImplementedError("no asm generator for cpu ${options.compTarget.machine.cpu}") throw NotImplementedError("no asm generator for cpu ${options.compTarget.machine.cpu}")

View File

@ -10,16 +10,23 @@ import prog8.ast.statements.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
import prog8.compilerinterface.AssemblyError import prog8.compilerinterface.*
import prog8.compilerinterface.CompilationOptions
import prog8.compilerinterface.IErrorReporter
import prog8.compilerinterface.isIOAddress
import prog8.optimizer.getTempVarName import prog8.optimizer.getTempVarName
internal class BeforeAsmAstChanger(val program: Program, private val options: CompilationOptions, internal class BeforeAsmAstChanger(val program: Program, private val options: CompilationOptions,
private val errors: IErrorReporter private val errors: IErrorReporter
) : AstWalker() { ) : AstWalker() {
private val allBlockVars = mutableMapOf<Block, MutableSet<VarDecl>>()
private val allSubroutineVars = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
// internal lateinit var allocation: IVariableAllocation
//
// override fun after(program: Program): Iterable<IAstModification> {
// allocation = VariableAllocation(allBlockVars, allSubroutineVars)
// allocation.dump(program.memsizer)
// return super.after(program)
// }
override fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> { override fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> {
throw FatalAstException("break should have been replaced by goto $breakStmt") throw FatalAstException("break should have been replaced by goto $breakStmt")
} }
@ -58,6 +65,25 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
if (decl.type == VarDeclType.VAR && decl.value != null && decl.datatype in NumericDatatypes) if (decl.type == VarDeclType.VAR && decl.value != null && decl.datatype in NumericDatatypes)
throw FatalAstException("vardecls for variables, with initial numerical value, should have been rewritten as plain vardecl + assignment $decl") throw FatalAstException("vardecls for variables, with initial numerical value, should have been rewritten as plain vardecl + assignment $decl")
} }
if(decl.type==VarDeclType.VAR) {
when(val scope=decl.definingScope) {
is Block -> {
val blockVars = allBlockVars[scope] ?: mutableSetOf()
blockVars.add(decl)
allBlockVars[scope] = blockVars
}
is Subroutine -> {
val subroutineVars = allSubroutineVars[scope] ?: mutableSetOf()
subroutineVars.add(decl)
allSubroutineVars[scope] = subroutineVars
}
else -> {
throw FatalAstException("var can only occur in subroutine or block scope")
}
}
}
return noModifications return noModifications
} }
@ -370,4 +396,29 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
return modifications return modifications
} }
} }
internal class VariableAllocation(
override val blockVars: Map<Block, Set<VarDecl>>,
override val subroutineVars: Map<Subroutine, Set<VarDecl>>) : IVariableAllocation
{
override fun dump(memsizer: IMemSizer) {
println("ALL BLOCK VARS:")
blockVars.forEach { (block, vars) ->
val totalsize = vars.sumOf { memsizer.memorySize(it) }
println("BLOCK: ${block.name} total size: $totalsize")
vars.forEach {
println(" ${it.datatype} ${it.name} ${it.position}")
}
}
println("ALL SUBROUTINE VARS:")
subroutineVars.forEach { (sub, vars) ->
val totalsize = vars.sumOf { memsizer.memorySize(it) }
println("SUBROUTINE: ${sub.name} total size: $totalsize")
vars.forEach {
println(" ${it.datatype} ${it.name} ${it.position}")
}
}
}
}

View File

@ -300,7 +300,7 @@ class TestOptimization: FunSpec({
expr.right.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UWORD expr.right.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UWORD
expr.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UBYTE expr.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UBYTE
val options = CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, true, C64Target) val options = CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, true, C64Target, outputDir= outputDir)
result.program.processAstBeforeAsmGeneration(options, ErrorReporterForTests()) result.program.processAstBeforeAsmGeneration(options, ErrorReporterForTests())
// assignment is now split into: // assignment is now split into:

View File

@ -79,7 +79,7 @@ class TestAsmGenSymbols: StringSpec({
val errors = ErrorReporterForTests() val errors = ErrorReporterForTests()
val options = CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, true, C64Target) val options = CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, true, C64Target)
options.compTarget.machine.zeropage = C64Zeropage(options) options.compTarget.machine.zeropage = C64Zeropage(options)
val asmgen = AsmGen6502(program, errors, options, Path.of("")) val asmgen = AsmGen6502(program, errors, options)
return asmgen return asmgen
} }

View File

@ -8,6 +8,7 @@ import prog8.ast.expressions.InferredTypes
import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.statements.RegisterOrStatusflag import prog8.ast.statements.RegisterOrStatusflag
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.statements.VarDecl
import prog8.compilerinterface.* import prog8.compilerinterface.*
internal val DummyFunctions = object : IBuiltinFunctions { internal val DummyFunctions = object : IBuiltinFunctions {
@ -24,6 +25,7 @@ internal val DummyFunctions = object : IBuiltinFunctions {
internal val DummyMemsizer = object : IMemSizer { internal val DummyMemsizer = object : IMemSizer {
override fun memorySize(dt: DataType) = 0 override fun memorySize(dt: DataType) = 0
override fun memorySize(decl: VarDecl) = 0
} }
internal val DummyStringEncoder = object : IStringEncoding { internal val DummyStringEncoder = object : IStringEncoding {
@ -69,4 +71,8 @@ internal val DummyCompilationTarget = object : ICompilationTarget {
override fun memorySize(dt: DataType): Int { override fun memorySize(dt: DataType): Int {
throw NotImplementedError("dummy") throw NotImplementedError("dummy")
} }
override fun memorySize(decl: VarDecl): Int {
throw NotImplementedError("dummy")
}
} }

View File

@ -85,8 +85,8 @@ internal fun generateAssembly(
program: Program, program: Program,
options: CompilationOptions? = null options: CompilationOptions? = null
): IAssemblyProgram? { ): IAssemblyProgram? {
val coptions = options ?: CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, true, C64Target) val coptions = options ?: CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, true, C64Target, outputDir = outputDir)
coptions.compTarget.machine.zeropage = C64Zeropage(coptions) coptions.compTarget.machine.zeropage = C64Zeropage(coptions)
val asmgen = AsmGen6502(program, ErrorReporterForTests(), coptions, outputDir) val asmgen = AsmGen6502(program, ErrorReporterForTests(), coptions)
return asmgen.compileToAssembly() return asmgen.compileToAssembly()
} }

View File

@ -1,6 +1,7 @@
package prog8.compilerinterface package prog8.compilerinterface
import prog8.ast.base.DataType import prog8.ast.base.DataType
import prog8.ast.statements.VarDecl
// note: this is a separate interface in the compilerAst module because // note: this is a separate interface in the compilerAst module because
@ -8,4 +9,5 @@ import prog8.ast.base.DataType
interface IMemSizer { interface IMemSizer {
fun memorySize(dt: DataType): Int fun memorySize(dt: DataType): Int
fun memorySize(decl: VarDecl): Int
} }

View File

@ -1,5 +1,8 @@
package prog8.compilerinterface package prog8.compilerinterface
import java.nio.file.Path
import kotlin.io.path.Path
enum class OutputType { enum class OutputType {
RAW, RAW,
PRG PRG
@ -32,5 +35,7 @@ class CompilationOptions(val output: OutputType,
var dontReinitGlobals: Boolean = false, var dontReinitGlobals: Boolean = false,
var asmQuiet: Boolean = false, var asmQuiet: Boolean = false,
var asmListfile: Boolean = false, var asmListfile: Boolean = false,
var experimentalCodegen: Boolean = false var experimentalCodegen: Boolean = false,
) var outputDir: Path = Path("")
) {
}

View File

@ -0,0 +1,12 @@
package prog8.compilerinterface
import prog8.ast.statements.Block
import prog8.ast.statements.Subroutine
import prog8.ast.statements.VarDecl
interface IVariableAllocation {
fun dump(memsizer: IMemSizer)
val blockVars: Map<Block, Set<VarDecl>>
val subroutineVars: Map<Subroutine, Set<VarDecl>>
}

View File

@ -3,7 +3,7 @@ TODO
For next release For next release
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
... fix the concurrent modification issue on zeropage when running unit tests in parallel -> don't use static objects anymore
Need help with Need help with
@ -22,12 +22,11 @@ Blocked by an official Commander-x16 r39 release
Future Things and Ideas Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
Ast modifications done in AsmGen, that should be done BEFORE calling asmgen (so that it doesn't have to modify the Ast any longer): Ast modifications done in AsmGen, that should be done BEFORE calling asmgen (so that it doesn't have to modify the Ast any longer):
- block2asm: removes init-assignments to no longer output the initialization assignments as regular statements (is done separately in block initialization routine)
- block2asm: removes init-assignments to no longer output the initialization assignments as regular statements (is done separately in block initialization routine) - block2asm: after vardecls2asm it clears the vardecl.value of all variables
- block2asm: after vardecls2asm it clears the vardecl.value of all variables - Maybe don't rely on vardecls at all any longer but figure out the variable allocations (including ZP allocations) beforehand
- Maybe don't rely on vardecls at all any longer but figure out the variable allocations (including ZP allocations) beforehand and pass that via a new datastructure to asmgen? So that asmgen is no longer tasked with doing the allocations.
and pass that via a new datastructure to asmgen? So that asmgen is no longer tasked with doing the allocations. This could perhaps make it easer for the codegen as well to deal with sections, if any, in the future.
This could perhaps make it easer for the codegen as well to deal with sections, if any, in the future.
- remove support for old @"screencodes" string encoding syntax (parser+code+docs) - remove support for old @"screencodes" string encoding syntax (parser+code+docs)
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type - allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type

View File

@ -22,13 +22,22 @@ main {
foobar() foobar()
startval1++ startval1++
mainglobal1++ mainglobal1++
start2()
sub start2() {
uword @shared startval1 = 2002
ubyte[2] @shared barr
uword[2] @shared warr
uword[] @shared warr2 = [1,2]
}
} }
asmsub derp() { asmsub derp() {
} }
sub foobar() { sub foobar() {
uword @shared startval1 = 2002
uword @shared mainglobal1 = 2002
txt.print("foobar\n") txt.print("foobar\n")
} }
} }