mirror of
https://github.com/irmen/prog8.git
synced 2025-02-20 03:29:01 +00:00
some naming changes and cleanups
This commit is contained in:
parent
10de7dc1f9
commit
101fb0b8aa
@ -23,8 +23,9 @@ const val subroutineFloatEvalResultVar1 = "prog8_float_eval_result1"
|
|||||||
const val subroutineFloatEvalResultVar2 = "prog8_float_eval_result2"
|
const val subroutineFloatEvalResultVar2 = "prog8_float_eval_result2"
|
||||||
|
|
||||||
|
|
||||||
class AsmGen6502(internal val program: Program,
|
class AsmGen(internal val program: Program,
|
||||||
internal val errors: IErrorReporter,
|
internal val errors: IErrorReporter,
|
||||||
|
internal val variables: IVariablesAndConsts,
|
||||||
internal val options: CompilationOptions): IAssemblyGenerator {
|
internal val options: CompilationOptions): IAssemblyGenerator {
|
||||||
|
|
||||||
// for expressions and augmented assignments:
|
// for expressions and augmented assignments:
|
||||||
@ -54,6 +55,8 @@ class AsmGen6502(internal val program: Program,
|
|||||||
|
|
||||||
println("Generating assembly code... ")
|
println("Generating assembly code... ")
|
||||||
|
|
||||||
|
// TODO variables.dump(program.memsizer)
|
||||||
|
|
||||||
val allInitializers = blockVariableInitializers.asSequence().flatMap { it.value }
|
val allInitializers = blockVariableInitializers.asSequence().flatMap { it.value }
|
||||||
require(allInitializers.all { it.origin==AssignmentOrigin.VARINIT }) {"all block-level assignments must be a variable initializer"}
|
require(allInitializers.all { it.origin==AssignmentOrigin.VARINIT }) {"all block-level assignments must be a variable initializer"}
|
||||||
|
|
||||||
@ -285,7 +288,7 @@ class AsmGen6502(internal val program: Program,
|
|||||||
// first translate regular statements, and then put the subroutines at the end.
|
// first translate regular statements, and then put the subroutines at the end.
|
||||||
val (subroutine, stmts) = statements.partition { it is Subroutine }
|
val (subroutine, stmts) = statements.partition { it is Subroutine }
|
||||||
stmts.forEach { translate(it) }
|
stmts.forEach { translate(it) }
|
||||||
subroutine.forEach { translateSubroutine(it as Subroutine) }
|
subroutine.forEach { translate(it) }
|
||||||
|
|
||||||
if(!options.dontReinitGlobals) {
|
if(!options.dontReinitGlobals) {
|
||||||
// generate subroutine to initialize block-level (global) variables
|
// generate subroutine to initialize block-level (global) variables
|
@ -17,7 +17,7 @@ import prog8.compilerinterface.CpuType
|
|||||||
import prog8.compilerinterface.FSignature
|
import prog8.compilerinterface.FSignature
|
||||||
|
|
||||||
|
|
||||||
internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen6502, private val assignAsmGen: AssignmentAsmGen) {
|
internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val assignAsmGen: AssignmentAsmGen) {
|
||||||
|
|
||||||
internal fun translateFunctioncallExpression(fcall: FunctionCallExpression, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
|
internal fun translateFunctioncallExpression(fcall: FunctionCallExpression, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
|
||||||
translateFunctioncall(fcall, func, discardResult = false, resultToStack = resultToStack, resultRegister = resultRegister)
|
translateFunctioncall(fcall, func, discardResult = false, resultToStack = resultToStack, resultRegister = resultRegister)
|
||||||
|
@ -11,7 +11,7 @@ import prog8.compilerinterface.BuiltinFunctions
|
|||||||
import prog8.compilerinterface.CpuType
|
import prog8.compilerinterface.CpuType
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
internal class ExpressionsAsmGen(private val program: Program, private val asmgen: AsmGen6502, private val functioncallAsmGen: FunctionCallAsmGen) {
|
internal class ExpressionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val functioncallAsmGen: FunctionCallAsmGen) {
|
||||||
|
|
||||||
@Deprecated("avoid calling this as it generates slow evalstack based code")
|
@Deprecated("avoid calling this as it generates slow evalstack based code")
|
||||||
internal fun translateExpression(expression:Expression) {
|
internal fun translateExpression(expression:Expression) {
|
||||||
|
@ -12,7 +12,7 @@ import prog8.ast.toHex
|
|||||||
import prog8.compilerinterface.AssemblyError
|
import prog8.compilerinterface.AssemblyError
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen6502) {
|
internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
||||||
|
|
||||||
internal fun translate(stmt: ForLoop) {
|
internal fun translate(stmt: ForLoop) {
|
||||||
val iterableDt = stmt.iterable.inferType(program)
|
val iterableDt = stmt.iterable.inferType(program)
|
||||||
|
@ -17,7 +17,7 @@ import prog8.compilerinterface.AssemblyError
|
|||||||
import prog8.compilerinterface.CpuType
|
import prog8.compilerinterface.CpuType
|
||||||
|
|
||||||
|
|
||||||
internal class FunctionCallAsmGen(private val program: Program, private val asmgen: AsmGen6502) {
|
internal class FunctionCallAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
||||||
|
|
||||||
internal fun translateFunctionCallStatement(stmt: IFunctionCall) {
|
internal fun translateFunctionCallStatement(stmt: IFunctionCall) {
|
||||||
saveXbeforeCall(stmt)
|
saveXbeforeCall(stmt)
|
||||||
|
@ -9,7 +9,7 @@ import prog8.ast.toHex
|
|||||||
import prog8.compilerinterface.AssemblyError
|
import prog8.compilerinterface.AssemblyError
|
||||||
|
|
||||||
|
|
||||||
internal class PostIncrDecrAsmGen(private val program: Program, private val asmgen: AsmGen6502) {
|
internal class PostIncrDecrAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
||||||
internal fun translate(stmt: PostIncrDecr) {
|
internal fun translate(stmt: PostIncrDecr) {
|
||||||
val incr = stmt.operator=="++"
|
val incr = stmt.operator=="++"
|
||||||
val targetIdent = stmt.target.identifier
|
val targetIdent = stmt.target.identifier
|
||||||
|
@ -4,7 +4,7 @@ import prog8.ast.Program
|
|||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.codegen.cpu6502.AsmGen6502
|
import prog8.codegen.cpu6502.AsmGen
|
||||||
import prog8.compilerinterface.AssemblyError
|
import prog8.compilerinterface.AssemblyError
|
||||||
import prog8.compilerinterface.IMemSizer
|
import prog8.compilerinterface.IMemSizer
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ internal enum class SourceStorageKind {
|
|||||||
|
|
||||||
internal class AsmAssignTarget(val kind: TargetStorageKind,
|
internal class AsmAssignTarget(val kind: TargetStorageKind,
|
||||||
private val program: Program,
|
private val program: Program,
|
||||||
private val asmgen: AsmGen6502,
|
private val asmgen: AsmGen,
|
||||||
val datatype: DataType,
|
val datatype: DataType,
|
||||||
val scope: Subroutine?,
|
val scope: Subroutine?,
|
||||||
private val variableAsmName: String? = null,
|
private val variableAsmName: String? = null,
|
||||||
@ -56,7 +56,7 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromAstAssignment(assign: Assignment, program: Program, asmgen: AsmGen6502): AsmAssignTarget {
|
fun fromAstAssignment(assign: Assignment, program: Program, asmgen: AsmGen): AsmAssignTarget {
|
||||||
with(assign.target) {
|
with(assign.target) {
|
||||||
val idt = inferType(program)
|
val idt = inferType(program)
|
||||||
val dt = idt.getOrElse { throw AssemblyError("unknown dt") }
|
val dt = idt.getOrElse { throw AssemblyError("unknown dt") }
|
||||||
@ -82,7 +82,7 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fromRegisters(registers: RegisterOrPair, signed: Boolean, scope: Subroutine?, program: Program, asmgen: AsmGen6502): AsmAssignTarget =
|
fun fromRegisters(registers: RegisterOrPair, signed: Boolean, scope: Subroutine?, program: Program, asmgen: AsmGen): AsmAssignTarget =
|
||||||
when(registers) {
|
when(registers) {
|
||||||
RegisterOrPair.A,
|
RegisterOrPair.A,
|
||||||
RegisterOrPair.X,
|
RegisterOrPair.X,
|
||||||
@ -114,7 +114,7 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
|
|||||||
|
|
||||||
internal class AsmAssignSource(val kind: SourceStorageKind,
|
internal class AsmAssignSource(val kind: SourceStorageKind,
|
||||||
private val program: Program,
|
private val program: Program,
|
||||||
private val asmgen: AsmGen6502,
|
private val asmgen: AsmGen,
|
||||||
val datatype: DataType,
|
val datatype: DataType,
|
||||||
private val variableAsmName: String? = null,
|
private val variableAsmName: String? = null,
|
||||||
val array: ArrayIndexedExpression? = null,
|
val array: ArrayIndexedExpression? = null,
|
||||||
@ -134,9 +134,9 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
|
|||||||
asmgen.asmVariableName(array.arrayvar)
|
asmgen.asmVariableName(array.arrayvar)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromAstSource(indexer: ArrayIndex, program: Program, asmgen: AsmGen6502): AsmAssignSource = fromAstSource(indexer.indexExpr, program, asmgen)
|
fun fromAstSource(indexer: ArrayIndex, program: Program, asmgen: AsmGen): AsmAssignSource = fromAstSource(indexer.indexExpr, program, asmgen)
|
||||||
|
|
||||||
fun fromAstSource(value: Expression, program: Program, asmgen: AsmGen6502): AsmAssignSource {
|
fun fromAstSource(value: Expression, program: Program, asmgen: AsmGen): AsmAssignSource {
|
||||||
val cv = value.constValue(program)
|
val cv = value.constValue(program)
|
||||||
if(cv!=null)
|
if(cv!=null)
|
||||||
return AsmAssignSource(SourceStorageKind.LITERALNUMBER, program, asmgen, cv.type, number = cv)
|
return AsmAssignSource(SourceStorageKind.LITERALNUMBER, program, asmgen, cv.type, number = cv)
|
||||||
|
@ -5,14 +5,14 @@ import prog8.ast.base.*
|
|||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.ast.toHex
|
import prog8.ast.toHex
|
||||||
import prog8.codegen.cpu6502.AsmGen6502
|
import prog8.codegen.cpu6502.AsmGen
|
||||||
import prog8.compilerinterface.AssemblyError
|
import prog8.compilerinterface.AssemblyError
|
||||||
import prog8.compilerinterface.BuiltinFunctions
|
import prog8.compilerinterface.BuiltinFunctions
|
||||||
import prog8.compilerinterface.CpuType
|
import prog8.compilerinterface.CpuType
|
||||||
import prog8.compilerinterface.builtinFunctionReturnType
|
import prog8.compilerinterface.builtinFunctionReturnType
|
||||||
|
|
||||||
|
|
||||||
internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen6502) {
|
internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
||||||
|
|
||||||
private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen)
|
private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen)
|
||||||
|
|
||||||
|
@ -5,14 +5,14 @@ import prog8.ast.base.*
|
|||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.Subroutine
|
import prog8.ast.statements.Subroutine
|
||||||
import prog8.ast.toHex
|
import prog8.ast.toHex
|
||||||
import prog8.codegen.cpu6502.AsmGen6502
|
import prog8.codegen.cpu6502.AsmGen
|
||||||
import prog8.compilerinterface.AssemblyError
|
import prog8.compilerinterface.AssemblyError
|
||||||
import prog8.compilerinterface.CpuType
|
import prog8.compilerinterface.CpuType
|
||||||
|
|
||||||
|
|
||||||
internal class AugmentableAssignmentAsmGen(private val program: Program,
|
internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||||
private val assignmentAsmGen: AssignmentAsmGen,
|
private val assignmentAsmGen: AssignmentAsmGen,
|
||||||
private val asmgen: AsmGen6502
|
private val asmgen: AsmGen
|
||||||
) {
|
) {
|
||||||
fun translate(assign: AsmAssignment) {
|
fun translate(assign: AsmAssignment) {
|
||||||
require(assign.isAugmentable)
|
require(assign.isAugmentable)
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package prog8.codegen.experimental6502
|
||||||
|
|
||||||
|
import prog8.ast.Program
|
||||||
|
import prog8.compilerinterface.*
|
||||||
|
|
||||||
|
class AsmGen(internal val program: Program,
|
||||||
|
internal val errors: IErrorReporter,
|
||||||
|
internal val variables: IVariablesAndConsts,
|
||||||
|
internal val options: CompilationOptions): IAssemblyGenerator {
|
||||||
|
|
||||||
|
override fun compileToAssembly(): IAssemblyProgram? {
|
||||||
|
|
||||||
|
println("\n** experimental 65(c)02 code generator **\n")
|
||||||
|
|
||||||
|
println("..todo: create assembly code into ${options.outputDir.toAbsolutePath()}..")
|
||||||
|
return AssemblyProgram("dummy")
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +0,0 @@
|
|||||||
package prog8.codegen.experimental6502
|
|
||||||
|
|
||||||
import prog8.ast.Program
|
|
||||||
import prog8.compilerinterface.CompilationOptions
|
|
||||||
import prog8.compilerinterface.IAssemblyGenerator
|
|
||||||
import prog8.compilerinterface.IAssemblyProgram
|
|
||||||
import prog8.compilerinterface.IErrorReporter
|
|
||||||
|
|
||||||
class ExperimentalAsmGen6502(internal val program: Program,
|
|
||||||
internal val errors: IErrorReporter,
|
|
||||||
internal val options: CompilationOptions
|
|
||||||
): IAssemblyGenerator {
|
|
||||||
override fun compileToAssembly(): IAssemblyProgram? {
|
|
||||||
|
|
||||||
println("\n** experimental 65(c)02 code generator **\n")
|
|
||||||
|
|
||||||
println("..todo: create assembly code into ${options.outputDir.toAbsolutePath()}..")
|
|
||||||
return AssemblyProgram("dummy")
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,8 +9,6 @@ import prog8.ast.base.Position
|
|||||||
import prog8.ast.expressions.Expression
|
import prog8.ast.expressions.Expression
|
||||||
import prog8.ast.expressions.NumericLiteralValue
|
import prog8.ast.expressions.NumericLiteralValue
|
||||||
import prog8.ast.statements.Directive
|
import prog8.ast.statements.Directive
|
||||||
import prog8.codegen.cpu6502.AsmGen6502
|
|
||||||
import prog8.codegen.experimental6502.ExperimentalAsmGen6502
|
|
||||||
import prog8.codegen.target.C128Target
|
import prog8.codegen.target.C128Target
|
||||||
import prog8.codegen.target.C64Target
|
import prog8.codegen.target.C64Target
|
||||||
import prog8.codegen.target.Cx16Target
|
import prog8.codegen.target.Cx16Target
|
||||||
@ -21,6 +19,7 @@ import prog8.parser.ParseError
|
|||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.io.path.Path
|
import kotlin.io.path.Path
|
||||||
import kotlin.io.path.nameWithoutExtension
|
import kotlin.io.path.nameWithoutExtension
|
||||||
|
import kotlin.math.round
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
|
|
||||||
@ -109,7 +108,8 @@ fun compileProgram(args: CompilerArguments): CompilationResult {
|
|||||||
}
|
}
|
||||||
System.out.flush()
|
System.out.flush()
|
||||||
System.err.flush()
|
System.err.flush()
|
||||||
println("\nTotal compilation+assemble time: ${totalTime / 1000.0} sec.")
|
val seconds = totalTime/1000.0
|
||||||
|
println("\nTotal compilation+assemble time: ${round(seconds*100.0)/100.0} sec.")
|
||||||
return CompilationResult(true, program, programName, compTarget, importedFiles)
|
return CompilationResult(true, program, programName, compTarget, importedFiles)
|
||||||
} catch (px: ParseError) {
|
} catch (px: ParseError) {
|
||||||
System.err.print("\u001b[91m") // bright red
|
System.err.print("\u001b[91m") // bright red
|
||||||
@ -344,14 +344,13 @@ private fun writeAssembly(program: Program,
|
|||||||
): WriteAssemblyResult {
|
): WriteAssemblyResult {
|
||||||
// asm generation directly from the Ast
|
// asm generation directly from the Ast
|
||||||
compilerOptions.compTarget.machine.initializeZeropage(compilerOptions)
|
compilerOptions.compTarget.machine.initializeZeropage(compilerOptions)
|
||||||
program.processAstBeforeAsmGeneration(compilerOptions, errors)
|
val variables = program.processAstBeforeAsmGeneration(compilerOptions, errors)
|
||||||
errors.report()
|
errors.report()
|
||||||
// TODO do something with the VariableAllocation, pass it to the asmgenerator
|
|
||||||
|
|
||||||
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
||||||
// printProgram(program)
|
// printProgram(program)
|
||||||
|
|
||||||
val assembly = asmGeneratorFor(program, errors, compilerOptions).compileToAssembly()
|
val assembly = asmGeneratorFor(program, errors, variables, compilerOptions).compileToAssembly()
|
||||||
errors.report()
|
errors.report()
|
||||||
|
|
||||||
return if(assembly!=null && errors.noErrors()) {
|
return if(assembly!=null && errors.noErrors()) {
|
||||||
@ -371,18 +370,14 @@ fun printProgram(program: Program) {
|
|||||||
println()
|
println()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun asmGeneratorFor(
|
internal fun asmGeneratorFor(program: Program, errors: IErrorReporter, variables: IVariablesAndConsts, options: CompilationOptions): IAssemblyGenerator
|
||||||
program: Program,
|
|
||||||
errors: IErrorReporter,
|
|
||||||
options: CompilationOptions,
|
|
||||||
): 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)
|
return prog8.codegen.experimental6502.AsmGen(program, errors, variables, 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)
|
return prog8.codegen.cpu6502.AsmGen(program, errors, variables, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
throw NotImplementedError("no asm generator for cpu ${options.compTarget.machine.cpu}")
|
throw NotImplementedError("no asm generator for cpu ${options.compTarget.machine.cpu}")
|
||||||
|
@ -13,6 +13,7 @@ import prog8.ast.walk.IAstModification
|
|||||||
import prog8.compilerinterface.CompilationOptions
|
import prog8.compilerinterface.CompilationOptions
|
||||||
import prog8.compilerinterface.IErrorReporter
|
import prog8.compilerinterface.IErrorReporter
|
||||||
import prog8.compilerinterface.IStringEncoding
|
import prog8.compilerinterface.IStringEncoding
|
||||||
|
import prog8.compilerinterface.IVariablesAndConsts
|
||||||
|
|
||||||
|
|
||||||
internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: CompilationOptions) {
|
internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: CompilationOptions) {
|
||||||
@ -23,7 +24,7 @@ internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: Compila
|
|||||||
checker.visit(this)
|
checker.visit(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationOptions, errors: IErrorReporter) {
|
internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationOptions, errors: IErrorReporter): IVariablesAndConsts {
|
||||||
val fixer = BeforeAsmAstChanger(this, compilerOptions, errors)
|
val fixer = BeforeAsmAstChanger(this, compilerOptions, errors)
|
||||||
fixer.visit(this)
|
fixer.visit(this)
|
||||||
while(errors.noErrors() && fixer.applyModifications()>0) {
|
while(errors.noErrors() && fixer.applyModifications()>0) {
|
||||||
@ -34,6 +35,7 @@ internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationO
|
|||||||
while(errors.noErrors() && cleaner.applyModifications()>0) {
|
while(errors.noErrors() && cleaner.applyModifications()>0) {
|
||||||
cleaner.visit(this)
|
cleaner.visit(this)
|
||||||
}
|
}
|
||||||
|
return fixer.variables
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Program.reorderStatements(errors: IErrorReporter, options: CompilationOptions) {
|
internal fun Program.reorderStatements(errors: IErrorReporter, options: CompilationOptions) {
|
||||||
|
@ -20,17 +20,14 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
|
|||||||
private val allSubroutineVars = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
|
private val allSubroutineVars = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
|
||||||
private val allSubroutineConsts = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
|
private val allSubroutineConsts = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
|
||||||
private val allSubroutineMemoryvars = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
|
private val allSubroutineMemoryvars = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
|
||||||
internal lateinit var allocation: IVariableAllocation
|
internal lateinit var variables: IVariablesAndConsts
|
||||||
|
|
||||||
/* TODO complete the use of VariableAllocation and get rid of it from the AsmGen (and that should no longer use vardecl either):
|
|
||||||
override fun after(program: Program): Iterable<IAstModification> {
|
override fun after(program: Program): Iterable<IAstModification> {
|
||||||
allocation = VariableAllocation(options,
|
variables = VariablesAndConsts(
|
||||||
allBlockVars, allBlockConsts, allBlockMemoryvars,
|
allBlockVars, allBlockConsts, allBlockMemoryvars,
|
||||||
allSubroutineVars, allSubroutineConsts, allSubroutineMemoryvars)
|
allSubroutineVars, allSubroutineConsts, allSubroutineMemoryvars)
|
||||||
allocation.dump(program.memsizer)
|
|
||||||
return super.after(program)
|
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")
|
||||||
@ -446,46 +443,39 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class VariableAllocation (
|
internal class VariablesAndConsts (
|
||||||
options: CompilationOptions,
|
|
||||||
astBlockVars: Map<Block, Set<VarDecl>>,
|
astBlockVars: Map<Block, Set<VarDecl>>,
|
||||||
astBlockConsts: Map<Block, Set<VarDecl>>,
|
astBlockConsts: Map<Block, Set<VarDecl>>,
|
||||||
astBlockMemvars: Map<Block, Set<VarDecl>>,
|
astBlockMemvars: Map<Block, Set<VarDecl>>,
|
||||||
astSubroutineVars: Map<Subroutine, Set<VarDecl>>,
|
astSubroutineVars: Map<Subroutine, Set<VarDecl>>,
|
||||||
astSubroutineConsts: Map<Subroutine, Set<VarDecl>>,
|
astSubroutineConsts: Map<Subroutine, Set<VarDecl>>,
|
||||||
astSubroutineMemvars: Map<Subroutine, Set<VarDecl>>
|
astSubroutineMemvars: Map<Subroutine, Set<VarDecl>>
|
||||||
) : IVariableAllocation
|
) : IVariablesAndConsts
|
||||||
{
|
{
|
||||||
override val zeropageVars: Set<IVariableAllocation.ZeropageVariable>
|
override val blockVars: Map<Block, Set<IVariablesAndConsts.StaticBlockVariable>>
|
||||||
override val blockVars: Map<Block, Set<IVariableAllocation.StaticBlockVariable>>
|
override val blockConsts: Map<Block, Set<IVariablesAndConsts.ConstantNumberSymbol>>
|
||||||
override val blockConsts: Map<Block, Set<IVariableAllocation.ConstantNumberSymbol>>
|
override val blockMemvars: Map<Block, Set<IVariablesAndConsts.MemoryMappedVariable>>
|
||||||
override val blockMemvars: Map<Block, Set<IVariableAllocation.MemoryMappedSymbol>>
|
override val subroutineVars: Map<Subroutine, Set<IVariablesAndConsts.StaticSubroutineVariable>>
|
||||||
override val subroutineVars: Map<Subroutine, Set<IVariableAllocation.StaticSubroutineVariable>>
|
override val subroutineConsts: Map<Subroutine, Set<IVariablesAndConsts.ConstantNumberSymbol>>
|
||||||
override val subroutineConsts: Map<Subroutine, Set<IVariableAllocation.ConstantNumberSymbol>>
|
override val subroutineMemvars: Map<Subroutine, Set<IVariablesAndConsts.MemoryMappedVariable>>
|
||||||
override val subroutineMemvars: Map<Subroutine, Set<IVariableAllocation.MemoryMappedSymbol>>
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if(options.zeropage!=ZeropageType.DONTUSE)
|
val bv = astBlockVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticBlockVariable>() }
|
||||||
allocateVarsInZeropage(options.compTarget.machine.zeropage)
|
val bc = astBlockConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
|
||||||
|
val bmv = astBlockMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
|
||||||
val zpv = mutableSetOf<IVariableAllocation.ZeropageVariable>()
|
val sv = astSubroutineVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticSubroutineVariable>() }
|
||||||
val bv = astBlockVars.keys.associateWith { mutableSetOf<IVariableAllocation.StaticBlockVariable>() }
|
val sc = astSubroutineConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
|
||||||
val bc = astBlockConsts.keys.associateWith { mutableSetOf<IVariableAllocation.ConstantNumberSymbol>() }
|
val smv = astSubroutineMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
|
||||||
val bmv = astBlockMemvars.keys.associateWith { mutableSetOf<IVariableAllocation.MemoryMappedSymbol>() }
|
|
||||||
val sv = astSubroutineVars.keys.associateWith { mutableSetOf<IVariableAllocation.StaticSubroutineVariable>() }
|
|
||||||
val sc = astSubroutineConsts.keys.associateWith { mutableSetOf<IVariableAllocation.ConstantNumberSymbol>() }
|
|
||||||
val smv = astSubroutineMemvars.keys.associateWith { mutableSetOf<IVariableAllocation.MemoryMappedSymbol>() }
|
|
||||||
astBlockVars.forEach { (block, decls) ->
|
astBlockVars.forEach { (block, decls) ->
|
||||||
val vars = bv.getValue(block)
|
val vars = bv.getValue(block)
|
||||||
vars.addAll(decls.map {
|
vars.addAll(decls.map {
|
||||||
// TODO make sure the zp-allocated variables are not added here
|
IVariablesAndConsts.StaticBlockVariable(it.datatype, it.name, it.value, it.position, it)
|
||||||
IVariableAllocation.StaticBlockVariable(it.datatype, it.name, it.value, it.position, it)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
astBlockConsts.forEach { (block, decls) ->
|
astBlockConsts.forEach { (block, decls) ->
|
||||||
bc.getValue(block).addAll(
|
bc.getValue(block).addAll(
|
||||||
decls.map {
|
decls.map {
|
||||||
IVariableAllocation.ConstantNumberSymbol(
|
IVariablesAndConsts.ConstantNumberSymbol(
|
||||||
it.datatype,
|
it.datatype,
|
||||||
it.name,
|
it.name,
|
||||||
(it.value as NumericLiteralValue).number,
|
(it.value as NumericLiteralValue).number,
|
||||||
@ -496,7 +486,7 @@ internal class VariableAllocation (
|
|||||||
astBlockMemvars.forEach { (block, decls) ->
|
astBlockMemvars.forEach { (block, decls) ->
|
||||||
bmv.getValue(block).addAll(
|
bmv.getValue(block).addAll(
|
||||||
decls.map {
|
decls.map {
|
||||||
IVariableAllocation.MemoryMappedSymbol(
|
IVariablesAndConsts.MemoryMappedVariable(
|
||||||
it.datatype,
|
it.datatype,
|
||||||
it.name,
|
it.name,
|
||||||
(it.value as NumericLiteralValue).number.toUInt(),
|
(it.value as NumericLiteralValue).number.toUInt(),
|
||||||
@ -507,14 +497,13 @@ internal class VariableAllocation (
|
|||||||
astSubroutineVars.forEach { (sub, decls) ->
|
astSubroutineVars.forEach { (sub, decls) ->
|
||||||
val vars = sv.getValue(sub)
|
val vars = sv.getValue(sub)
|
||||||
vars.addAll(decls.map {
|
vars.addAll(decls.map {
|
||||||
// TODO make sure the zp-allocated variables are not added here
|
IVariablesAndConsts.StaticSubroutineVariable(it.datatype, it.name, it.position, it)
|
||||||
IVariableAllocation.StaticSubroutineVariable(it.datatype, it.name, it.position, it)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
astSubroutineConsts.forEach { (sub, decls) ->
|
astSubroutineConsts.forEach { (sub, decls) ->
|
||||||
sc.getValue(sub).addAll(
|
sc.getValue(sub).addAll(
|
||||||
decls.map {
|
decls.map {
|
||||||
IVariableAllocation.ConstantNumberSymbol(
|
IVariablesAndConsts.ConstantNumberSymbol(
|
||||||
it.datatype,
|
it.datatype,
|
||||||
it.name,
|
it.name,
|
||||||
(it.value as NumericLiteralValue).number,
|
(it.value as NumericLiteralValue).number,
|
||||||
@ -525,7 +514,7 @@ internal class VariableAllocation (
|
|||||||
astSubroutineMemvars.forEach { (sub, decls) ->
|
astSubroutineMemvars.forEach { (sub, decls) ->
|
||||||
smv.getValue(sub).addAll(
|
smv.getValue(sub).addAll(
|
||||||
decls.map {
|
decls.map {
|
||||||
IVariableAllocation.MemoryMappedSymbol(
|
IVariablesAndConsts.MemoryMappedVariable(
|
||||||
it.datatype,
|
it.datatype,
|
||||||
it.name,
|
it.name,
|
||||||
(it.value as NumericLiteralValue).number.toUInt(),
|
(it.value as NumericLiteralValue).number.toUInt(),
|
||||||
@ -533,7 +522,6 @@ internal class VariableAllocation (
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
zeropageVars = zpv
|
|
||||||
blockVars = bv
|
blockVars = bv
|
||||||
blockConsts = bc
|
blockConsts = bc
|
||||||
blockMemvars = bmv
|
blockMemvars = bmv
|
||||||
@ -542,15 +530,7 @@ internal class VariableAllocation (
|
|||||||
subroutineMemvars = smv
|
subroutineMemvars = smv
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun allocateVarsInZeropage(zeropage: Zeropage) {
|
|
||||||
println("TODO: allocate vars on zeropage") // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dump(memsizer: IMemSizer) {
|
override fun dump(memsizer: IMemSizer) {
|
||||||
println("\nALL ZEROPAGE VARS:")
|
|
||||||
zeropageVars.forEach {
|
|
||||||
println(" ${it.type} ${it.scopedname} ${it.position}")
|
|
||||||
}
|
|
||||||
println("\nALL BLOCK VARS:")
|
println("\nALL BLOCK VARS:")
|
||||||
blockVars.forEach { (block, vars) ->
|
blockVars.forEach { (block, vars) ->
|
||||||
val totalsize = vars.sumOf { memsizer.memorySize(it.origVar) }
|
val totalsize = vars.sumOf { memsizer.memorySize(it.origVar) }
|
||||||
|
@ -301,7 +301,7 @@ class TestOptimization: FunSpec({
|
|||||||
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(), outputDir= outputDir)
|
val options = CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, true, C64Target(), outputDir= outputDir)
|
||||||
result.program.processAstBeforeAsmGeneration(options, ErrorReporterForTests())
|
val allocation = result.program.processAstBeforeAsmGeneration(options, ErrorReporterForTests())
|
||||||
|
|
||||||
// assignment is now split into:
|
// assignment is now split into:
|
||||||
// bb = not bb
|
// bb = not bb
|
||||||
@ -326,7 +326,7 @@ class TestOptimization: FunSpec({
|
|||||||
((bbAssigns1expr.right as PrefixExpression).expression as? IdentifierReference)?.nameInSource shouldBe listOf("ww")
|
((bbAssigns1expr.right as PrefixExpression).expression as? IdentifierReference)?.nameInSource shouldBe listOf("ww")
|
||||||
bbAssigns1expr.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UBYTE
|
bbAssigns1expr.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UBYTE
|
||||||
|
|
||||||
val asm = generateAssembly(result.program, options)
|
val asm = generateAssembly(result.program, allocation, options)
|
||||||
asm shouldNotBe null
|
asm shouldNotBe null
|
||||||
asm!!.name.shouldNotBeBlank()
|
asm!!.name.shouldNotBeBlank()
|
||||||
}
|
}
|
||||||
@ -366,7 +366,7 @@ class TestOptimization: FunSpec({
|
|||||||
|
|
||||||
test("asmgen correctly deals with float typecasting in augmented assignment") {
|
test("asmgen correctly deals with float typecasting in augmented assignment") {
|
||||||
val src="""
|
val src="""
|
||||||
%option enable_floats
|
%import floats
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
@ -385,9 +385,7 @@ class TestOptimization: FunSpec({
|
|||||||
(value.left as? IdentifierReference)?.nameInSource shouldBe listOf("ff")
|
(value.left as? IdentifierReference)?.nameInSource shouldBe listOf("ff")
|
||||||
value.right shouldBe instanceOf<TypecastExpression>()
|
value.right shouldBe instanceOf<TypecastExpression>()
|
||||||
|
|
||||||
val asm = generateAssembly(result.program)
|
compileText(C64Target(), optimize=false, src, writeAssembly = true).assertSuccess()
|
||||||
asm shouldNotBe null
|
|
||||||
asm!!.name.shouldNotBeBlank()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test("unused variable removal") {
|
test("unused variable removal") {
|
||||||
|
@ -12,22 +12,18 @@ import prog8.ast.expressions.AddressOf
|
|||||||
import prog8.ast.expressions.IdentifierReference
|
import prog8.ast.expressions.IdentifierReference
|
||||||
import prog8.ast.expressions.NumericLiteralValue
|
import prog8.ast.expressions.NumericLiteralValue
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.codegen.cpu6502.AsmGen6502
|
import prog8.codegen.cpu6502.AsmGen
|
||||||
import prog8.codegen.target.C64Target
|
import prog8.codegen.target.C64Target
|
||||||
import prog8.codegen.target.c64.C64Zeropage
|
import prog8.codegen.target.c64.C64Zeropage
|
||||||
import prog8.compilerinterface.CompilationOptions
|
import prog8.compilerinterface.*
|
||||||
import prog8.compilerinterface.LauncherType
|
|
||||||
import prog8.compilerinterface.OutputType
|
|
||||||
import prog8.compilerinterface.ZeropageType
|
|
||||||
import prog8.parser.SourceCode
|
import prog8.parser.SourceCode
|
||||||
import prog8tests.helpers.DummyFunctions
|
import prog8tests.helpers.DummyFunctions
|
||||||
import prog8tests.helpers.DummyMemsizer
|
import prog8tests.helpers.DummyMemsizer
|
||||||
import prog8tests.helpers.DummyStringEncoder
|
import prog8tests.helpers.DummyStringEncoder
|
||||||
import prog8tests.helpers.ErrorReporterForTests
|
import prog8tests.helpers.ErrorReporterForTests
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
class TestAsmGenSymbols: StringSpec({
|
class TestAsmGenSymbols: StringSpec({
|
||||||
fun createTestProgram(): Program {
|
fun createTestProgram(): Pair<Program, IVariablesAndConsts> {
|
||||||
/*
|
/*
|
||||||
main {
|
main {
|
||||||
|
|
||||||
@ -72,20 +68,42 @@ class TestAsmGenSymbols: StringSpec({
|
|||||||
val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY)
|
val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY)
|
||||||
|
|
||||||
val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test"))
|
val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test"))
|
||||||
return Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder).addModule(module)
|
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder).addModule(module)
|
||||||
|
val variables = object : IVariablesAndConsts {
|
||||||
|
override fun dump(memsizer: IMemSizer) { }
|
||||||
|
override val blockVars: Map<Block, Set<IVariablesAndConsts.StaticBlockVariable>>
|
||||||
|
override val blockConsts: Map<Block, Set<IVariablesAndConsts.ConstantNumberSymbol>>
|
||||||
|
override val blockMemvars: Map<Block, Set<IVariablesAndConsts.MemoryMappedVariable>>
|
||||||
|
override val subroutineVars: Map<Subroutine, Set<IVariablesAndConsts.StaticSubroutineVariable>>
|
||||||
|
override val subroutineConsts: Map<Subroutine, Set<IVariablesAndConsts.ConstantNumberSymbol>>
|
||||||
|
override val subroutineMemvars: Map<Subroutine, Set<IVariablesAndConsts.MemoryMappedVariable>>
|
||||||
|
init {
|
||||||
|
blockVars = mutableMapOf()
|
||||||
|
blockVars[block] = mutableSetOf(IVariablesAndConsts.StaticBlockVariable(varInBlock.datatype, varInBlock.name, varInBlock.value, varInBlock.position, varInBlock))
|
||||||
|
blockConsts = mutableMapOf()
|
||||||
|
blockMemvars = mutableMapOf()
|
||||||
|
subroutineVars = mutableMapOf()
|
||||||
|
subroutineVars[subroutine] = mutableSetOf(
|
||||||
|
IVariablesAndConsts.StaticSubroutineVariable(varInSub.datatype, varInSub.name, varInSub.position, varInSub),
|
||||||
|
IVariablesAndConsts.StaticSubroutineVariable(var2InSub.datatype, var2InSub.name, var2InSub.position, var2InSub)
|
||||||
|
)
|
||||||
|
subroutineConsts = mutableMapOf()
|
||||||
|
subroutineMemvars = mutableMapOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Pair(program, variables)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createTestAsmGen(program: Program): AsmGen6502 {
|
fun createTestAsmGen(program: Program, allocation: IVariablesAndConsts): AsmGen {
|
||||||
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)
|
return AsmGen(program, errors, allocation, options)
|
||||||
return asmgen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"symbol and variable names from strings" {
|
"symbol and variable names from strings" {
|
||||||
val program = createTestProgram()
|
val (program, variables) = createTestProgram()
|
||||||
val asmgen = createTestAsmGen(program)
|
val asmgen = createTestAsmGen(program, variables)
|
||||||
asmgen.asmSymbolName("name") shouldBe "name"
|
asmgen.asmSymbolName("name") shouldBe "name"
|
||||||
asmgen.asmSymbolName("name") shouldBe "name"
|
asmgen.asmSymbolName("name") shouldBe "name"
|
||||||
asmgen.asmSymbolName("<name>") shouldBe "prog8_name"
|
asmgen.asmSymbolName("<name>") shouldBe "prog8_name"
|
||||||
@ -97,8 +115,8 @@ class TestAsmGenSymbols: StringSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
"symbol and variable names from variable identifiers" {
|
"symbol and variable names from variable identifiers" {
|
||||||
val program = createTestProgram()
|
val (program, variables) = createTestProgram()
|
||||||
val asmgen = createTestAsmGen(program)
|
val asmgen = createTestAsmGen(program, variables)
|
||||||
val sub = program.entrypoint
|
val sub = program.entrypoint
|
||||||
|
|
||||||
val localvarIdent = sub.statements.asSequence().filterIsInstance<Assignment>().first { it.value is IdentifierReference }.value as IdentifierReference
|
val localvarIdent = sub.statements.asSequence().filterIsInstance<Assignment>().first { it.value is IdentifierReference }.value as IdentifierReference
|
||||||
@ -117,8 +135,8 @@ class TestAsmGenSymbols: StringSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
"symbol and variable names from label identifiers" {
|
"symbol and variable names from label identifiers" {
|
||||||
val program = createTestProgram()
|
val (program, variables) = createTestProgram()
|
||||||
val asmgen = createTestAsmGen(program)
|
val asmgen = createTestAsmGen(program, variables)
|
||||||
val sub = program.entrypoint
|
val sub = program.entrypoint
|
||||||
|
|
||||||
val localLabelIdent = (sub.statements.asSequence().filterIsInstance<Assignment>().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("locallabel") }.value as AddressOf).identifier
|
val localLabelIdent = (sub.statements.asSequence().filterIsInstance<Assignment>().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("locallabel") }.value as AddressOf).identifier
|
||||||
@ -146,8 +164,8 @@ main {
|
|||||||
prog8_lib.P8ZP_SCRATCH_W1 = 1
|
prog8_lib.P8ZP_SCRATCH_W1 = 1
|
||||||
prog8_lib.P8ZP_SCRATCH_W2 = 1
|
prog8_lib.P8ZP_SCRATCH_W2 = 1
|
||||||
*/
|
*/
|
||||||
val program = createTestProgram()
|
val (program, variables) = createTestProgram()
|
||||||
val asmgen = createTestAsmGen(program)
|
val asmgen = createTestAsmGen(program, variables)
|
||||||
asmgen.asmSymbolName("prog8_lib.P8ZP_SCRATCH_REG") shouldBe "P8ZP_SCRATCH_REG"
|
asmgen.asmSymbolName("prog8_lib.P8ZP_SCRATCH_REG") shouldBe "P8ZP_SCRATCH_REG"
|
||||||
asmgen.asmSymbolName("prog8_lib.P8ZP_SCRATCH_W2") shouldBe "P8ZP_SCRATCH_W2"
|
asmgen.asmSymbolName("prog8_lib.P8ZP_SCRATCH_W2") shouldBe "P8ZP_SCRATCH_W2"
|
||||||
asmgen.asmSymbolName(listOf("prog8_lib","P8ZP_SCRATCH_REG")) shouldBe "P8ZP_SCRATCH_REG"
|
asmgen.asmSymbolName(listOf("prog8_lib","P8ZP_SCRATCH_REG")) shouldBe "P8ZP_SCRATCH_REG"
|
||||||
|
@ -11,7 +11,7 @@ import prog8.ast.statements.Subroutine
|
|||||||
import prog8.ast.statements.VarDecl
|
import prog8.ast.statements.VarDecl
|
||||||
import prog8.compilerinterface.*
|
import prog8.compilerinterface.*
|
||||||
|
|
||||||
internal val DummyFunctions = object : IBuiltinFunctions {
|
internal object DummyFunctions : IBuiltinFunctions {
|
||||||
override val names: Set<String> = emptySet()
|
override val names: Set<String> = emptySet()
|
||||||
override val purefunctionNames: Set<String> = emptySet()
|
override val purefunctionNames: Set<String> = emptySet()
|
||||||
override fun constValue(
|
override fun constValue(
|
||||||
@ -23,12 +23,12 @@ internal val DummyFunctions = object : IBuiltinFunctions {
|
|||||||
override fun returnType(name: String, args: MutableList<Expression>) = InferredTypes.InferredType.unknown()
|
override fun returnType(name: String, args: MutableList<Expression>) = InferredTypes.InferredType.unknown()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val DummyMemsizer = object : IMemSizer {
|
internal object DummyMemsizer : IMemSizer {
|
||||||
override fun memorySize(dt: DataType) = 0
|
override fun memorySize(dt: DataType) = 0
|
||||||
override fun memorySize(decl: VarDecl) = 0
|
override fun memorySize(decl: VarDecl) = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val DummyStringEncoder = object : IStringEncoding {
|
internal object DummyStringEncoder : IStringEncoding {
|
||||||
override fun encodeString(str: String, encoding: Encoding): List<UByte> {
|
override fun encodeString(str: String, encoding: Encoding): List<UByte> {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ internal val DummyStringEncoder = object : IStringEncoding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val AsciiStringEncoder = object : IStringEncoding {
|
internal object AsciiStringEncoder : IStringEncoding {
|
||||||
override fun encodeString(str: String, encoding: Encoding): List<UByte> = str.map { it.code.toUByte() }
|
override fun encodeString(str: String, encoding: Encoding): List<UByte> = str.map { it.code.toUByte() }
|
||||||
|
|
||||||
override fun decodeString(bytes: List<UByte>, encoding: Encoding): String {
|
override fun decodeString(bytes: List<UByte>, encoding: Encoding): String {
|
||||||
@ -46,7 +46,7 @@ internal val AsciiStringEncoder = object : IStringEncoding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val DummyCompilationTarget = object : ICompilationTarget {
|
internal object DummyCompilationTarget : ICompilationTarget {
|
||||||
override val name: String = "dummy"
|
override val name: String = "dummy"
|
||||||
override val machine: IMachineDefinition
|
override val machine: IMachineDefinition
|
||||||
get() = throw NotImplementedError("dummy")
|
get() = throw NotImplementedError("dummy")
|
||||||
|
@ -3,7 +3,7 @@ package prog8tests.helpers
|
|||||||
import io.kotest.assertions.withClue
|
import io.kotest.assertions.withClue
|
||||||
import io.kotest.matchers.shouldBe
|
import io.kotest.matchers.shouldBe
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.codegen.cpu6502.AsmGen6502
|
import prog8.codegen.cpu6502.AsmGen
|
||||||
import prog8.codegen.target.C64Target
|
import prog8.codegen.target.C64Target
|
||||||
import prog8.codegen.target.c64.C64Zeropage
|
import prog8.codegen.target.c64.C64Zeropage
|
||||||
import prog8.compiler.CompilationResult
|
import prog8.compiler.CompilationResult
|
||||||
@ -83,10 +83,11 @@ internal fun compileText(
|
|||||||
|
|
||||||
internal fun generateAssembly(
|
internal fun generateAssembly(
|
||||||
program: Program,
|
program: Program,
|
||||||
|
allocation: IVariablesAndConsts,
|
||||||
options: CompilationOptions? = null
|
options: CompilationOptions? = null
|
||||||
): IAssemblyProgram? {
|
): IAssemblyProgram? {
|
||||||
val coptions = options ?: CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, true, C64Target(), outputDir = outputDir)
|
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)
|
val asmgen = AsmGen(program, ErrorReporterForTests(), allocation, coptions)
|
||||||
return asmgen.compileToAssembly()
|
return asmgen.compileToAssembly()
|
||||||
}
|
}
|
||||||
|
@ -7,21 +7,24 @@ import prog8.ast.statements.Block
|
|||||||
import prog8.ast.statements.Subroutine
|
import prog8.ast.statements.Subroutine
|
||||||
import prog8.ast.statements.VarDecl
|
import prog8.ast.statements.VarDecl
|
||||||
|
|
||||||
|
/**
|
||||||
interface IVariableAllocation {
|
* Experimental attempt for:
|
||||||
|
* A more convenient way to pass variable (and constant values) definitions to the code generator,
|
||||||
|
* so that it doesn't have to scavenge all VerDecl nodes in the AST for this information.
|
||||||
|
*/
|
||||||
|
interface IVariablesAndConsts {
|
||||||
data class ConstantNumberSymbol(val type: DataType, val name: String, val value: Double, val position: Position)
|
data class ConstantNumberSymbol(val type: DataType, val name: String, val value: Double, val position: Position)
|
||||||
data class MemoryMappedSymbol(val type: DataType, val name: String, val address: UInt, val position: Position)
|
data class MemoryMappedVariable(val type: DataType, val name: String, val address: UInt, val position: Position)
|
||||||
data class StaticBlockVariable(val type: DataType, val name: String, val initialValue: Expression?, val position: Position, val origVar: VarDecl) // TODO should get rid of origVar altogether
|
// TODO should get rid of origVar altogether in the following two:
|
||||||
data class StaticSubroutineVariable(val type: DataType, val name: String, val position: Position, val origVar: VarDecl) // TODO should get rid of origVar altogether
|
data class StaticBlockVariable(val type: DataType, val name: String, val initialValue: Expression?, val position: Position, val origVar: VarDecl)
|
||||||
data class ZeropageVariable(val type: DataType, val scopedname: List<String>, val position: Position)
|
data class StaticSubroutineVariable(val type: DataType, val name: String, val position: Position, val origVar: VarDecl)
|
||||||
|
|
||||||
fun dump(memsizer: IMemSizer)
|
fun dump(memsizer: IMemSizer)
|
||||||
|
|
||||||
val zeropageVars: Set<ZeropageVariable> // also present in the Zeropage object after this allocation
|
|
||||||
val blockVars: Map<Block, Set<StaticBlockVariable>>
|
val blockVars: Map<Block, Set<StaticBlockVariable>>
|
||||||
val blockConsts: Map<Block, Set<ConstantNumberSymbol>>
|
val blockConsts: Map<Block, Set<ConstantNumberSymbol>>
|
||||||
val blockMemvars: Map<Block, Set<MemoryMappedSymbol>>
|
val blockMemvars: Map<Block, Set<MemoryMappedVariable>>
|
||||||
val subroutineVars: Map<Subroutine, Set<StaticSubroutineVariable>>
|
val subroutineVars: Map<Subroutine, Set<StaticSubroutineVariable>>
|
||||||
val subroutineConsts: Map<Subroutine, Set<ConstantNumberSymbol>>
|
val subroutineConsts: Map<Subroutine, Set<ConstantNumberSymbol>>
|
||||||
val subroutineMemvars: Map<Subroutine, Set<MemoryMappedSymbol>>
|
val subroutineMemvars: Map<Subroutine, Set<MemoryMappedVariable>>
|
||||||
}
|
}
|
@ -20,12 +20,10 @@ 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 perhaps should not be necessary:
|
||||||
- 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
|
--> Don't rely on vardecls at all any longer but use the new IVariablesAndConsts object passed to the AsmGen, this will solve this item.
|
||||||
and pass that via a new datastructure to asmgen? So that asmgen is no longer tasked with doing the allocations.
|
- block2asm: removes init-assignments to no longer output the initialization assignments as regular statements (is done separately in block initialization routine)
|
||||||
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
|
||||||
@ -54,6 +52,7 @@ Ast modifications done in AsmGen, that should be done BEFORE calling asmgen (so
|
|||||||
Perhaps replace all uses of .proc/.pend by .block/.bend will fix that?
|
Perhaps replace all uses of .proc/.pend by .block/.bend will fix that?
|
||||||
(but we lose the optimizing aspect of the assembler where it strips out unused code.
|
(but we lose the optimizing aspect of the assembler where it strips out unused code.
|
||||||
There's not really a dynamic switch possible as all assembly lib code is static and uses one or the other)
|
There's not really a dynamic switch possible as all assembly lib code is static and uses one or the other)
|
||||||
|
- zig try-based error handling where the V flag could indicate error condition? and/or BRK to jump into monitor on failure? (has to set BRK vector for this)
|
||||||
- get rid of all TODO's in the code ;)
|
- get rid of all TODO's in the code ;)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user