mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
report free/occupied Zeropage space at end of compilation
This commit is contained in:
parent
f7e74b3088
commit
c13b7fd883
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user