mirror of
https://github.com/irmen/prog8.git
synced 2024-10-25 00:24:16 +00:00
cleaning up AsmGen interface
This commit is contained in:
parent
f538c9f0c3
commit
6bdd81623f
@ -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)
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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}")
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,3 +397,28 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
}
|
||||||
}
|
}
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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("")
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
@ -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>>
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user