This commit is contained in:
Irmen de Jong 2022-02-09 15:45:47 +01:00
parent f3c52c409f
commit 98b2855b9c
12 changed files with 287 additions and 258 deletions

View File

@ -211,7 +211,7 @@ class AsmGen(internal val program: Program,
private fun fixNameSymbols(name: String): String {
val name2 = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names
return name2.replace("prog8_lib.P8ZP_SCRATCH_", "P8ZP_SCRATCH_") // take care of the 'hooks' to the temp vars
return name2.replace("prog8_lib.P8ZP_SCRATCH_", "P8ZP_SCRATCH_") // take care of the 'hooks' to the temp vars -> reference zp symbols directly
}
internal fun saveRegisterLocal(register: CpuRegister, scope: Subroutine) {

View File

@ -166,7 +166,7 @@ internal class ProgramGen(
zeropagevars2asm(vardecls)
memdefs2asmVars(vardecls, block)
memdefs2asmAsmsubs(block.statements.filterIsInstance<Subroutine>())
vardecls2asm(vardecls, block)
vardecls2asm(vardecls)
vardecls.forEach {
if(it.type== VarDeclType.VAR && it.datatype in NumericDatatypes)
@ -278,7 +278,7 @@ internal class ProgramGen(
asmgen.out("$subroutineFloatEvalResultVar1 .byte 0,0,0,0,0")
if(asmGenInfo.usedFloatEvalResultVar2)
asmgen.out("$subroutineFloatEvalResultVar2 .byte 0,0,0,0,0")
vardecls2asm(vardecls, null)
vardecls2asm(vardecls)
asmgen.out(" .pend\n")
}
}
@ -472,11 +472,10 @@ internal class ProgramGen(
vardecls
.filter { it.type==VarDeclType.MEMORY || it.type==VarDeclType.CONST }
.forEach { mv ->
if(blockname!="prog8_lib" || !mv.name.startsWith("P8ZP_SCRATCH_")) // the "hooks" to the temp vars are not generated as new variables
if(mv.value is NumericLiteralValue)
asmgen.out(" ${mv.name} = ${(mv.value as NumericLiteralValue).number.toHex()}")
else
asmgen.out(" ${mv.name} = ${asmgen.asmVariableName((mv.value as AddressOf).identifier)}")
if(mv.value is NumericLiteralValue)
asmgen.out(" ${mv.name} = ${(mv.value as NumericLiteralValue).number.toHex()}")
else
asmgen.out(" ${mv.name} = ${asmgen.asmVariableName((mv.value as AddressOf).identifier)}")
}
}
@ -493,7 +492,7 @@ internal class ProgramGen(
}
}
private fun vardecls2asm(vardecls: List<VarDecl>, inBlock: Block?) {
private fun vardecls2asm(vardecls: List<VarDecl>) {
asmgen.out("\n; non-zeropage variables")
val vars = vardecls.filter {
it.type==VarDeclType.VAR
@ -504,15 +503,10 @@ internal class ProgramGen(
vars.filter { it.datatype == DataType.STR && shouldActuallyOutputStringVar(it) }
.forEach { outputStringvar(it) }
// non-string variables
val blockname = inBlock?.name
vars.filter{ it.datatype != DataType.STR }.sortedBy { it.datatype }.forEach {
require(it.zeropage!= ZeropageWish.REQUIRE_ZEROPAGE)
if(!asmgen.isZpVar(it.scopedName)) {
if(blockname!="prog8_lib" || !it.name.startsWith("P8ZP_SCRATCH_")) // the "hooks" to the temp vars are not generated as new variables
vardecl2asm(it)
}
if(!asmgen.isZpVar(it.scopedName))
vardecl2asm(it)
}
}

View File

@ -30,25 +30,11 @@ internal class VariableAllocator(val vars: IVariablesAndConsts, val errors: IErr
if(options.zeropage== ZeropageType.DONTUSE)
return
val allVariables = (
vars.blockVars.asSequence().flatMap { it.value }.map {it.origVar to it.origVar.scopedName} +
vars.subroutineVars.asSequence().flatMap { it.value }.map {it.origVar to it.origVar.scopedName})
.toList()
// TODO now some HACKS to get rid of some unused vars in Petaxian - otherwise the executable gets larger than $45e8
.filterNot { it.second.last() == "tbl" } // TODO HACK -- NOT REALLY NECESSARY, BUT OLD CallGraph DIDN'T CONTAIN IT EITHER
.filterNot { it.second.last() in setOf("retval_interm_w", "retval_interm_b", "retval_interm_w2", "retval_interm_b2") } // TODO HACK TO REMOVE THESE UNUSED VARS
val zeropage = options.compTarget.machine.zeropage
fun numArrayElements(vardecl: VarDecl): Int? = when(vardecl.datatype) {
DataType.STR -> {
(vardecl.value as StringLiteralValue).value.length
}
in ArrayDatatypes -> {
vardecl.arraysize!!.constIndex()
}
else -> null
}
val allVariables = (
vars.blockVars.asSequence().flatMap { it.value }.map {it.origVar to it.origVar.scopedName} +
vars.subroutineVars.asSequence().flatMap { it.value }.map {it.origVar to it.origVar.scopedName})
.toList()
val varsRequiringZp = allVariables.filter { it.first.zeropage == ZeropageWish.REQUIRE_ZEROPAGE }
val varsPreferringZp = allVariables.filter { it.first.zeropage == ZeropageWish.PREFER_ZEROPAGE }
@ -82,6 +68,16 @@ internal class VariableAllocator(val vars: IVariablesAndConsts, val errors: IErr
}
}
private fun numArrayElements(vardecl: VarDecl): Int? = when(vardecl.datatype) {
DataType.STR -> {
(vardecl.value as StringLiteralValue).value.length
}
in ArrayDatatypes -> {
vardecl.arraysize!!.constIndex()
}
else -> null
}
fun subroutineExtra(sub: Subroutine): SubroutineExtraAsmInfo {
var extra = subroutineExtras[sub]
return if(extra==null) {

View File

@ -344,7 +344,8 @@ private fun writeAssembly(program: Program,
): WriteAssemblyResult {
// asm generation directly from the Ast
compilerOptions.compTarget.machine.initializeZeropage(compilerOptions)
val variables = program.processAstBeforeAsmGeneration(compilerOptions, errors)
val variables = VariableExtractor().extractVars(program)
program.processAstBeforeAsmGeneration(compilerOptions, errors)
errors.report()
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")

View File

@ -13,7 +13,6 @@ import prog8.ast.walk.IAstModification
import prog8.compilerinterface.CompilationOptions
import prog8.compilerinterface.IErrorReporter
import prog8.compilerinterface.IStringEncoding
import prog8.compilerinterface.IVariablesAndConsts
internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: CompilationOptions) {
@ -24,7 +23,7 @@ internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: Compila
checker.visit(this)
}
internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationOptions, errors: IErrorReporter): IVariablesAndConsts {
internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationOptions, errors: IErrorReporter) {
val fixer = BeforeAsmAstChanger(this, compilerOptions, errors)
fixer.visit(this)
while(errors.noErrors() && fixer.applyModifications()>0) {
@ -35,7 +34,6 @@ internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationO
while(errors.noErrors() && cleaner.applyModifications()>0) {
cleaner.visit(this)
}
return fixer.variables
}
internal fun Program.reorderStatements(errors: IErrorReporter, options: CompilationOptions) {

View File

@ -10,25 +10,11 @@ import prog8.ast.walk.IAstVisitor
import prog8.compilerinterface.*
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
) : AstWalker() {
private val allBlockVars = mutableMapOf<Block, MutableSet<VarDecl>>()
private val allBlockConsts = mutableMapOf<Block, MutableSet<VarDecl>>()
private val allBlockMemoryvars = mutableMapOf<Block, MutableSet<VarDecl>>()
private val allSubroutineVars = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
private val allSubroutineConsts = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
private val allSubroutineMemoryvars = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
internal lateinit var variables: IVariablesAndConsts
override fun after(program: Program): Iterable<IAstModification> {
variables = VariablesAndConsts(
allBlockVars, allBlockConsts, allBlockMemoryvars,
allSubroutineVars, allSubroutineConsts, allSubroutineMemoryvars)
return super.after(program)
}
override fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> {
throw FatalAstException("break should have been replaced by goto $breakStmt")
}
@ -68,66 +54,6 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
throw FatalAstException("vardecls for variables, with initial numerical value, should have been rewritten as plain vardecl + assignment $decl")
}
val scope=decl.definingScope
when (decl.type) {
VarDeclType.VAR -> {
if(decl.origin!=VarDeclOrigin.SUBROUTINEPARAM) {
when (scope) {
is Block -> {
val decls = allBlockVars[scope] ?: mutableSetOf()
decls.add(decl)
allBlockVars[scope] = decls
}
is Subroutine -> {
val decls = allSubroutineVars[scope] ?: mutableSetOf()
decls.add(decl)
allSubroutineVars[scope] = decls
}
else -> {
throw FatalAstException("var can only occur in subroutine or block scope")
}
}
}
}
VarDeclType.CONST -> {
when(scope) {
is Block -> {
val decls = allBlockConsts[scope] ?: mutableSetOf()
decls.add(decl)
allBlockConsts[scope] = decls
}
is Subroutine -> {
val decls = allSubroutineConsts[scope] ?: mutableSetOf()
decls.add(decl)
allSubroutineConsts[scope] = decls
}
else -> {
throw FatalAstException("var can only occur in subroutine or block scope")
}
}
}
VarDeclType.MEMORY -> {
when(scope) {
is Block -> {
val decls = allBlockMemoryvars[scope] ?: mutableSetOf()
decls.add(decl)
allBlockMemoryvars[scope] = decls
}
is Subroutine -> {
val decls = allSubroutineMemoryvars[scope] ?: mutableSetOf()
decls.add(decl)
allSubroutineMemoryvars[scope] = decls
}
else -> {
throw FatalAstException("var can only occur in subroutine or block scope")
}
}
}
else -> {
throw FatalAstException("invalid var type")
}
}
// TODO get rid of the vardecl inside the ast - codegen should depend on the IVariableAllocation object
// return listOf(IAstModification.Remove(decl, parent as IStatementContainer))
return noModifications
@ -443,140 +369,3 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
}
}
internal class VariablesAndConsts (
astBlockVars: Map<Block, Set<VarDecl>>,
astBlockConsts: Map<Block, Set<VarDecl>>,
astBlockMemvars: Map<Block, Set<VarDecl>>,
astSubroutineVars: Map<Subroutine, Set<VarDecl>>,
astSubroutineConsts: Map<Subroutine, Set<VarDecl>>,
astSubroutineMemvars: Map<Subroutine, Set<VarDecl>>
) : IVariablesAndConsts
{
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 {
val bv = astBlockVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticBlockVariable>() }
val bc = astBlockConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
val bmv = astBlockMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
val sv = astSubroutineVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticSubroutineVariable>() }
val sc = astSubroutineConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
val smv = astSubroutineMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
astBlockVars.forEach { (block, decls) ->
val vars = bv.getValue(block)
vars.addAll(decls.map {
IVariablesAndConsts.StaticBlockVariable(it.datatype, it.name, it.value, it.zeropage, it.position, it)
})
}
astBlockConsts.forEach { (block, decls) ->
bc.getValue(block).addAll(
decls.map {
IVariablesAndConsts.ConstantNumberSymbol(
it.datatype,
it.name,
(it.value as NumericLiteralValue).number,
it.position
)
})
}
astBlockMemvars.forEach { (block, decls) ->
bmv.getValue(block).addAll(
decls.map {
IVariablesAndConsts.MemoryMappedVariable(
it.datatype,
it.name,
(it.value as NumericLiteralValue).number.toUInt(),
it.position
)
})
}
astSubroutineVars.forEach { (sub, decls) ->
val vars = sv.getValue(sub)
vars.addAll(decls.map {
IVariablesAndConsts.StaticSubroutineVariable(it.datatype, it.name, it.zeropage, it.position, it)
})
}
astSubroutineConsts.forEach { (sub, decls) ->
sc.getValue(sub).addAll(
decls.map {
IVariablesAndConsts.ConstantNumberSymbol(
it.datatype,
it.name,
(it.value as NumericLiteralValue).number,
it.position
)
})
}
astSubroutineMemvars.forEach { (sub, decls) ->
smv.getValue(sub).addAll(
decls.map {
IVariablesAndConsts.MemoryMappedVariable(
it.datatype,
it.name,
(it.value as NumericLiteralValue).number.toUInt(),
it.position
)
})
}
blockVars = bv
blockConsts = bc
blockMemvars = bmv
subroutineVars = sv
subroutineConsts = sc
subroutineMemvars = smv
}
override fun dump(memsizer: IMemSizer) {
println("\nALL BLOCK VARS:")
blockVars.forEach { (block, vars) ->
val totalsize = vars.sumOf { memsizer.memorySize(it.origVar) }
println("BLOCK: ${block.name} total size: $totalsize")
vars.forEach {
println(" ${it.type} ${it.name} = ${it.initialValue} ${it.position}")
}
}
println("\nALL BLOCK CONSTS:")
blockConsts.forEach { (block, vars) ->
println("BLOCK: ${block.name}")
vars.forEach {
println(" ${it.type} ${it.name} = ${it.value} ${it.position}")
}
}
println("\nALL BLOCK MEMORYVARS:")
blockMemvars.forEach { (block, vars) ->
println("BLOCK: ${block.name}")
vars.forEach {
println(" ${it.type} ${it.name} = ${it.address.toHex()} ${it.position}")
}
}
println("\nALL SUBROUTINE VARS:")
subroutineVars.forEach { (sub, vars) ->
val totalsize = vars.sumOf { memsizer.memorySize(it.origVar) }
println("SUBROUTINE: ${sub.name} total size: $totalsize")
vars.forEach {
println(" ${it.type} ${it.name} ${it.position}")
}
}
println("\nALL SUBROUTINE CONSTS:")
subroutineConsts.forEach { (sub, vars) ->
println("SUBROUTINE: ${sub.name}")
vars.forEach {
println(" ${it.type} ${it.name} = ${it.value} ${it.position}")
}
}
println("\nALL SUBROUTINE MEMORYVARS:")
subroutineMemvars.forEach { (sub, vars) ->
println("SUBROUTINE: ${sub.name}")
vars.forEach {
println(" ${it.type} ${it.name} = ${it.address.toHex()} ${it.position}")
}
}
}
}

View File

@ -0,0 +1,235 @@
package prog8.compiler.astprocessing
import prog8.ast.Program
import prog8.ast.base.FatalAstException
import prog8.ast.base.VarDeclType
import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.statements.Block
import prog8.ast.statements.Subroutine
import prog8.ast.statements.VarDecl
import prog8.ast.statements.VarDeclOrigin
import prog8.ast.toHex
import prog8.ast.walk.IAstVisitor
import prog8.compilerinterface.IMemSizer
import prog8.compilerinterface.IVariablesAndConsts
internal class VariableExtractor: IAstVisitor {
private val allBlockVars = mutableMapOf<Block, MutableSet<VarDecl>>()
private val allBlockConsts = mutableMapOf<Block, MutableSet<VarDecl>>()
private val allBlockMemoryvars = mutableMapOf<Block, MutableSet<VarDecl>>()
private val allSubroutineVars = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
private val allSubroutineConsts = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
private val allSubroutineMemoryvars = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
fun extractVars(program: Program): IVariablesAndConsts {
this.visit(program)
return VariablesAndConsts(
allBlockVars, allBlockConsts, allBlockMemoryvars,
allSubroutineVars, allSubroutineConsts, allSubroutineMemoryvars)
}
override fun visit(decl: VarDecl) {
val scope=decl.definingScope
when (decl.type) {
VarDeclType.VAR -> {
if(decl.origin!= VarDeclOrigin.SUBROUTINEPARAM) {
when (scope) {
is Block -> {
val decls = allBlockVars[scope] ?: mutableSetOf()
decls.add(decl)
allBlockVars[scope] = decls
}
is Subroutine -> {
val decls = allSubroutineVars[scope] ?: mutableSetOf()
decls.add(decl)
allSubroutineVars[scope] = decls
}
else -> {
throw FatalAstException("var can only occur in subroutine or block scope")
}
}
}
}
VarDeclType.CONST -> {
when(scope) {
is Block -> {
val decls = allBlockConsts[scope] ?: mutableSetOf()
decls.add(decl)
allBlockConsts[scope] = decls
}
is Subroutine -> {
val decls = allSubroutineConsts[scope] ?: mutableSetOf()
decls.add(decl)
allSubroutineConsts[scope] = decls
}
else -> {
throw FatalAstException("var can only occur in subroutine or block scope")
}
}
}
VarDeclType.MEMORY -> {
when(scope) {
is Block -> {
val decls = allBlockMemoryvars[scope] ?: mutableSetOf()
decls.add(decl)
allBlockMemoryvars[scope] = decls
}
is Subroutine -> {
val decls = allSubroutineMemoryvars[scope] ?: mutableSetOf()
decls.add(decl)
allSubroutineMemoryvars[scope] = decls
}
else -> {
throw FatalAstException("var can only occur in subroutine or block scope")
}
}
}
else -> {
throw FatalAstException("invalid var type")
}
}
super.visit(decl)
}
}
internal class VariablesAndConsts (
astBlockVars: Map<Block, Set<VarDecl>>,
astBlockConsts: Map<Block, Set<VarDecl>>,
astBlockMemvars: Map<Block, Set<VarDecl>>,
astSubroutineVars: Map<Subroutine, Set<VarDecl>>,
astSubroutineConsts: Map<Subroutine, Set<VarDecl>>,
astSubroutineMemvars: Map<Subroutine, Set<VarDecl>>
) : IVariablesAndConsts
{
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 {
val bv = astBlockVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticBlockVariable>() }
val bc = astBlockConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
val bmv = astBlockMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
val sv = astSubroutineVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticSubroutineVariable>() }
val sc = astSubroutineConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
val smv = astSubroutineMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
astBlockVars.forEach { (block, decls) ->
val vars = bv.getValue(block)
vars.addAll(decls.map {
IVariablesAndConsts.StaticBlockVariable(it.datatype, it.name, it.value, it.zeropage, it.position, it)
})
}
astBlockConsts.forEach { (block, decls) ->
bc.getValue(block).addAll(
decls.map {
IVariablesAndConsts.ConstantNumberSymbol(
it.datatype,
it.name,
(it.value as NumericLiteralValue).number,
it.position
)
})
}
astBlockMemvars.forEach { (block, decls) ->
val vars = bmv.getValue(block)
for(decl in decls) {
// make sure the 'stubs' for the scratch variables in zeropage are not included as normal variables
if(!decl.name.startsWith("P8ZP_SCRATCH_")) {
vars.add(
IVariablesAndConsts.MemoryMappedVariable(
decl.datatype,
decl.name,
(decl.value as NumericLiteralValue).number.toUInt(),
decl.position
)
)
}
}
}
astSubroutineVars.forEach { (sub, decls) ->
val vars = sv.getValue(sub)
vars.addAll(decls.map {
IVariablesAndConsts.StaticSubroutineVariable(it.datatype, it.name, it.zeropage, it.position, it)
})
}
astSubroutineConsts.forEach { (sub, decls) ->
sc.getValue(sub).addAll(
decls.map {
IVariablesAndConsts.ConstantNumberSymbol(
it.datatype,
it.name,
(it.value as NumericLiteralValue).number,
it.position
)
})
}
astSubroutineMemvars.forEach { (sub, decls) ->
smv.getValue(sub).addAll(
decls.map {
IVariablesAndConsts.MemoryMappedVariable(
it.datatype,
it.name,
(it.value as NumericLiteralValue).number.toUInt(),
it.position
)
})
}
blockVars = bv
blockConsts = bc
blockMemvars = bmv
subroutineVars = sv
subroutineConsts = sc
subroutineMemvars = smv
}
override fun dump(memsizer: IMemSizer) {
println("\nALL BLOCK VARS:")
blockVars.forEach { (block, vars) ->
val totalsize = vars.sumOf { memsizer.memorySize(it.origVar) }
println("BLOCK: ${block.name} total size: $totalsize")
vars.forEach {
println(" ${it.type} ${it.name} = ${it.initialValue} ${it.position}")
}
}
println("\nALL BLOCK CONSTS:")
blockConsts.forEach { (block, vars) ->
println("BLOCK: ${block.name}")
vars.forEach {
println(" ${it.type} ${it.name} = ${it.value} ${it.position}")
}
}
println("\nALL BLOCK MEMORYVARS:")
blockMemvars.forEach { (block, vars) ->
println("BLOCK: ${block.name}")
vars.forEach {
println(" ${it.type} ${it.name} = ${it.address.toHex()} ${it.position}")
}
}
println("\nALL SUBROUTINE VARS:")
subroutineVars.forEach { (sub, vars) ->
val totalsize = vars.sumOf { memsizer.memorySize(it.origVar) }
println("SUBROUTINE: ${sub.name} total size: $totalsize")
vars.forEach {
println(" ${it.type} ${it.name} ${it.position}")
}
}
println("\nALL SUBROUTINE CONSTS:")
subroutineConsts.forEach { (sub, vars) ->
println("SUBROUTINE: ${sub.name}")
vars.forEach {
println(" ${it.type} ${it.name} = ${it.value} ${it.position}")
}
}
println("\nALL SUBROUTINE MEMORYVARS:")
subroutineMemvars.forEach { (sub, vars) ->
println("SUBROUTINE: ${sub.name}")
vars.forEach {
println(" ${it.type} ${it.name} = ${it.address.toHex()} ${it.position}")
}
}
}
}

View File

@ -16,6 +16,7 @@ import prog8.ast.base.Position
import prog8.ast.expressions.*
import prog8.ast.statements.*
import prog8.codegen.target.C64Target
import prog8.compiler.astprocessing.VariableExtractor
import prog8.compiler.astprocessing.processAstBeforeAsmGeneration
import prog8.compiler.printProgram
import prog8.compilerinterface.CompilationOptions
@ -289,6 +290,7 @@ class TestOptimization: FunSpec({
}
"""
val result = compileText(C64Target(), false, src, writeAssembly = false).assertSuccess()
val variables = VariableExtractor().extractVars(result.program)
// bb = (( not bb as uword) or not ww)
val bbAssign = result.program.entrypoint.statements.last() as Assignment
@ -301,7 +303,7 @@ class TestOptimization: FunSpec({
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 allocation = result.program.processAstBeforeAsmGeneration(options, ErrorReporterForTests())
result.program.processAstBeforeAsmGeneration(options, ErrorReporterForTests())
// assignment is now split into:
// bb = not bb
@ -326,7 +328,7 @@ class TestOptimization: FunSpec({
((bbAssigns1expr.right as PrefixExpression).expression as? IdentifierReference)?.nameInSource shouldBe listOf("ww")
bbAssigns1expr.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UBYTE
val asm = generateAssembly(result.program, allocation, options)
val asm = generateAssembly(result.program, variables, options)
asm shouldNotBe null
asm!!.name.shouldNotBeBlank()
}

View File

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

View File

@ -4,6 +4,7 @@ import prog8.ast.Node
import prog8.ast.expressions.NumericLiteralValue
import kotlin.io.path.Path
import kotlin.io.path.absolute
import kotlin.io.path.div
/**************************** AST Data classes ****************************/
@ -191,7 +192,10 @@ object ParentSentinel : Node {
data class Position(val file: String, val line: Int, val startCol: Int, val endCol: Int) {
override fun toString(): String = "[$file: line $line col ${startCol+1}-${endCol+1}]"
fun toClickableStr(): String = "(${Path("").absolute()}/$file:$line:$startCol)"
fun toClickableStr(): String {
val path = (Path("") / file).absolute().normalize()
return "($path:$line:$startCol)"
}
companion object {
val DUMMY = Position("<dummy>", 0, 0, 0)

View File

@ -4,11 +4,13 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- programGen: don't generate variables from the VarDecl nodes, use allocator/zeropage tables
after that is done:
- (newvaralloc) UnusedCodeRemover after(decl: VarDecl): fix that vars defined in a library can also safely be removed if unused. Currently this breaks programs such as textelite (due to diskio.save().end_address ?)
- remove hacks in VariableAllocator
- check that retval_interm_* are not in the varallocation if they're not used
- make it so that subroutine parameters as variables can again be allocated in ZP, if there's still space
- wormfood became a lot larger??? why??? (and chess a little bit larger, but usually program size is down)
- check: are prog8_lib.P8ZP_SCRATCH emitted again from prog8_lib.p8 source, or do we only have the correct hardcoded redefines.
Need help with

View File

@ -18,6 +18,14 @@ main {
sub start() {
prog8_lib.P8ZP_SCRATCH_B1 = 1
prog8_lib.P8ZP_SCRATCH_W1 = 1111
txt.print_uwhex(&prog8_lib.P8ZP_SCRATCH_B1, true)
txt.spc()
txt.print_uwhex(&prog8_lib.P8ZP_SCRATCH_W1, true)
txt.spc()
txt.print_uwhex(&prog8_lib.P8ZP_SCRATCH_W2, true)
txt.nl()
txt.print_uw(nullwords[1])
txt.nl()