report free/occupied Zeropage space at end of compilation

This commit is contained in:
Irmen de Jong 2022-02-10 21:36:28 +01:00
parent f7e74b3088
commit c13b7fd883
5 changed files with 89 additions and 78 deletions

View File

@ -39,6 +39,7 @@ internal class ProgramAndVarsGen(
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"}
allocator.allocateZeropageVariables() allocator.allocateZeropageVariables()
header() header()
val allBlocks = program.allBlocks val allBlocks = program.allBlocks
if(allBlocks.first().name != "main") if(allBlocks.first().name != "main")
@ -63,7 +64,8 @@ internal class ProgramAndVarsGen(
asmgen.out("; generated by $ourName on ${LocalDateTime.now().withNano(0)}") asmgen.out("; generated by $ourName on ${LocalDateTime.now().withNano(0)}")
asmgen.out("; assembler syntax is for the 64tasm cross-assembler") asmgen.out("; assembler syntax is for the 64tasm cross-assembler")
asmgen.out("; output options: output=${options.output} launcher=${options.launcher} zp=${options.zeropage}") asmgen.out("; output options: output=${options.output} launcher=${options.launcher} zp=${options.zeropage}")
asmgen.out("\n.cpu '$cpu'\n.enc 'none'\n") asmgen.out("")
asmgen.out(".cpu '$cpu'\n.enc 'none'\n")
program.actualLoadAddress = program.definedLoadAddress program.actualLoadAddress = program.definedLoadAddress
if (program.actualLoadAddress == 0u) // fix load address if (program.actualLoadAddress == 0u) // fix load address
@ -153,7 +155,8 @@ internal class ProgramAndVarsGen(
} }
private fun block2asm(block: Block) { private fun block2asm(block: Block) {
asmgen.out("\n\n; ---- block: '${block.name}' ----") asmgen.out("")
asmgen.out("; ---- block: '${block.name}' ----")
if(block.address!=null) if(block.address!=null)
asmgen.out("* = ${block.address!!.toHex()}") asmgen.out("* = ${block.address!!.toHex()}")
else { else {
@ -172,7 +175,8 @@ internal class ProgramAndVarsGen(
asmsubs2asm(block.statements) asmsubs2asm(block.statements)
nonZpVariables2asm(block) nonZpVariables2asm(block)
asmgen.out("\n; subroutines in this block") asmgen.out("")
asmgen.out("; subroutines in this block")
// First translate regular statements, and then put the subroutines at the end. // First translate regular statements, and then put the subroutines at the end.
// (regular statements = everything except the initialization assignments; // (regular statements = everything except the initialization assignments;
@ -365,7 +369,8 @@ internal class ProgramAndVarsGen(
} }
private fun nonZpVariables2asm(variables: List<IVariablesAndConsts.StaticVariable>) { private fun nonZpVariables2asm(variables: List<IVariablesAndConsts.StaticVariable>) {
asmgen.out("\n; non-zeropage variables") asmgen.out("")
asmgen.out("; non-zeropage variables")
val (stringvars, othervars) = variables.partition { it.type==DataType.STR } val (stringvars, othervars) = variables.partition { it.type==DataType.STR }
stringvars.forEach { stringvars.forEach {
val stringvalue = it.initialValue as StringLiteralValue val stringvalue = it.initialValue as StringLiteralValue

View File

@ -1,9 +1,8 @@
package prog8.codegen.cpu6502 package prog8.codegen.cpu6502
import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.fold
import prog8.ast.base.ArrayDatatypes import com.github.michaelbull.result.onSuccess
import prog8.ast.base.DataType import prog8.ast.base.*
import prog8.ast.base.IntegerDatatypes
import prog8.ast.expressions.StringLiteralValue import prog8.ast.expressions.StringLiteralValue
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.statements.ZeropageWish import prog8.ast.statements.ZeropageWish
@ -41,20 +40,52 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts,
vars.subroutineVars.asSequence().flatMap { it.value } vars.subroutineVars.asSequence().flatMap { it.value }
).toList() ).toList()
val numberOfAllocatableVariables = allVariables.size
val totalAllocatedMemorySize = allVariables.sumOf { memsize(it) }
val varsRequiringZp = allVariables.filter { it.zp == ZeropageWish.REQUIRE_ZEROPAGE } val varsRequiringZp = allVariables.filter { it.zp == ZeropageWish.REQUIRE_ZEROPAGE }
val varsPreferringZp = allVariables.filter { it.zp == ZeropageWish.PREFER_ZEROPAGE } val varsPreferringZp = allVariables.filter { it.zp == ZeropageWish.PREFER_ZEROPAGE }
val varsDontCare = allVariables.filter { it.zp == ZeropageWish.DONTCARE } val varsDontCare = allVariables.filter { it.zp == ZeropageWish.DONTCARE }
val numberOfExplicitNonZpVariables = allVariables.count { it.zp == ZeropageWish.NOT_IN_ZEROPAGE }
require(varsDontCare.size + varsRequiringZp.size + varsPreferringZp.size + numberOfExplicitNonZpVariables == numberOfAllocatableVariables)
var numVariablesAllocatedInZP: Int = 0
var numberOfNonIntegerVariables: Int = 0
varsRequiringZp.forEach { variable -> varsRequiringZp.forEach { variable ->
val numElements = numArrayElements(variable) val numElements = numArrayElements(variable)
val result = zeropage.allocate(variable.scopedname, variable.type, variable.scope, numElements, variable.initialValue, variable.position, errors) val result = zeropage.allocate(
result.onFailure { errors.err(it.message!!, variable.position) } variable.scopedname,
variable.type,
variable.scope,
numElements,
variable.initialValue,
variable.position,
errors
)
result.fold(
success = {
numVariablesAllocatedInZP++
},
failure = {
errors.err(it.message!!, variable.position)
}
)
} }
if(errors.noErrors()) { if(errors.noErrors()) {
varsPreferringZp.forEach { variable -> varsPreferringZp.forEach { variable ->
val numElements = numArrayElements(variable) val numElements = numArrayElements(variable)
zeropage.allocate(variable.scopedname, variable.type, variable.scope, numElements, variable.initialValue, variable.position, errors) val result = zeropage.allocate(
variable.scopedname,
variable.type,
variable.scope,
numElements,
variable.initialValue,
variable.position,
errors
)
result.onSuccess { numVariablesAllocatedInZP++ }
// no need to check for allocation error, if there is one, just allocate in normal system ram. // no need to check for allocation error, if there is one, just allocate in normal system ram.
} }
@ -63,14 +94,40 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts,
if(errors.noErrors()) { if(errors.noErrors()) {
for (variable in varsDontCare) { for (variable in varsDontCare) {
if(variable.type in IntegerDatatypes) { if(variable.type in IntegerDatatypes) {
val numElements = numArrayElements(variable) if(zeropage.free.isEmpty()) {
zeropage.allocate(variable.scopedname, variable.type, variable.scope, numElements, variable.initialValue, variable.position, errors)
if(zeropage.free.isEmpty())
break break
} } else {
val numElements = numArrayElements(variable)
val result = zeropage.allocate(
variable.scopedname,
variable.type,
variable.scope,
numElements,
variable.initialValue,
variable.position,
errors
)
result.onSuccess { numVariablesAllocatedInZP++ }
}
} else
numberOfNonIntegerVariables++
} }
} }
} }
println(" number of allocated vars: $numberOfAllocatableVariables total size: $totalAllocatedMemorySize")
println(" put into zeropage: $numVariablesAllocatedInZP, non-zp allocatable: ${numberOfNonIntegerVariables+numberOfExplicitNonZpVariables}")
println(" zeropage free space: ${zeropage.free.size} bytes")
}
private fun memsize(variable: IVariablesAndConsts.StaticVariable): Int {
return when(variable.type) {
in NumericDatatypes ->
options.compTarget.memorySize(variable.type)
in ArrayDatatypes -> variable.arraysize!! * options.compTarget.memorySize(ArrayToElementTypes.getValue(variable.type))
DataType.STR -> (variable.initialValue as StringLiteralValue).value.length + 1
else -> 0
}
} }
internal fun isZpVar(scopedName: List<String>) = scopedName in zeropage.variables internal fun isZpVar(scopedName: List<String>) = scopedName in zeropage.variables

View File

@ -112,31 +112,31 @@ fun compileProgram(args: CompilerArguments): CompilationResult {
println("\nTotal compilation+assemble time: ${round(seconds*100.0)/100.0} sec.") 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("\n\u001b[91m") // bright red
System.err.println("${px.position.toClickableStr()} parse error: ${px.message}".trim()) System.err.println("${px.position.toClickableStr()} parse error: ${px.message}".trim())
System.err.print("\u001b[0m") // reset System.err.print("\u001b[0m") // reset
} catch (ac: AbortCompilation) { } catch (ac: AbortCompilation) {
if(!ac.message.isNullOrEmpty()) { if(!ac.message.isNullOrEmpty()) {
System.err.print("\u001b[91m") // bright red System.err.print("\n\u001b[91m") // bright red
System.err.println(ac.message) System.err.println(ac.message)
System.err.print("\u001b[0m") // reset System.err.print("\u001b[0m") // reset
} }
} catch (nsf: NoSuchFileException) { } catch (nsf: NoSuchFileException) {
System.err.print("\u001b[91m") // bright red System.err.print("\n\u001b[91m") // bright red
System.err.println("File not found: ${nsf.message}") System.err.println("File not found: ${nsf.message}")
System.err.print("\u001b[0m") // reset System.err.print("\u001b[0m") // reset
} catch (ax: AstException) { } catch (ax: AstException) {
System.err.print("\u001b[91m") // bright red System.err.print("\n\u001b[91m") // bright red
System.err.println(ax.toString()) System.err.println(ax.toString())
System.err.print("\u001b[0m") // reset System.err.print("\u001b[0m") // reset
} catch (x: Exception) { } catch (x: Exception) {
print("\u001b[91m") // bright red print("\n\u001b[91m") // bright red
println("\n* internal error *") println("\n* internal error *")
print("\u001b[0m") // reset print("\u001b[0m") // reset
System.out.flush() System.out.flush()
throw x throw x
} catch (x: NotImplementedError) { } catch (x: NotImplementedError) {
print("\u001b[91m") // bright red print("\n\u001b[91m") // bright red
println("\n* internal error: missing feature/code *") println("\n* internal error: missing feature/code *")
print("\u001b[0m") // reset print("\u001b[0m") // reset
System.out.flush() System.out.flush()

View File

@ -3,7 +3,7 @@ TODO
For next release For next release
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
- make it so that subroutine parameters as variables can again be allocated in ZP, if there's still space ...
Need help with Need help with

View File

@ -1,63 +1,12 @@
%import floats
%import textio
%zeropage basicsafe %zeropage basicsafe
main { main {
ubyte @zp mainglobal1=10
float @shared fl1 = floats.TWOPI
uword @shared m1 = memory("ee", 200, 0)
uword [2] nullwords
ubyte [2] nullbytes
uword [2] valuewords = [1111,22222]
ubyte [2] valuebytes = [111,222]
str name = "irmen"
uword [2] @requirezp zpnullwords
ubyte [2] @requirezp zpnullbytes
uword [2] @requirezp zpvaluewords = [11111,22222]
ubyte [2] @requirezp zpvaluebytes = [111,222]
str @requirezp zpname = "irmenzp"
sub start() { sub start() {
prog8_lib.P8ZP_SCRATCH_B1 = 1 cx16.r0=0
prog8_lib.P8ZP_SCRATCH_W1 = 1111 void routine22(1,2,3,4,5)
str alsoname = "also name" }
txt.print(alsoname)
txt.print(zpname)
txt.print("internedstring")
txt.spc()
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()
txt.print_ub(nullbytes[1])
txt.nl()
txt.print_uw(valuewords[1])
txt.nl()
txt.print_ub(valuebytes[1])
txt.nl()
txt.print(name)
txt.nl()
txt.nl()
txt.print_uw(zpnullwords[1])
txt.nl()
txt.print_ub(zpnullbytes[1])
txt.nl()
txt.print_uw(zpvaluewords[1])
txt.nl()
txt.print_ub(zpvaluebytes[1])
txt.nl()
txt.print(zpname)
txt.nl()
sub routine22(ubyte aa1, ubyte aa2, ubyte aa3, ubyte aa4, ubyte aa5) -> ubyte {
return aa1+aa2+aa3+aa4+aa5
} }
} }