slight tweaks to zp and allocator

This commit is contained in:
Irmen de Jong 2022-02-12 00:15:52 +01:00
parent c8cd6e9460
commit 2725c4ad4d
6 changed files with 24 additions and 26 deletions

View File

@ -297,10 +297,9 @@ internal class ProgramAndVarsGen(
} }
} }
val zp = zeropage
// string and array variables in zeropage that have initializer value, should be initialized // string and array variables in zeropage that have initializer value, should be initialized
val stringVarsWithInitInZp = zp.variables.filter { it.value.dt==DataType.STR && it.value.initialStringValue!=null } val stringVarsWithInitInZp = allocator.zeropageVars.filter { it.value.dt==DataType.STR && it.value.initialStringValue!=null }
val arrayVarsWithInitInZp = zp.variables.filter { it.value.dt in ArrayDatatypes && it.value.initialArrayValue!=null } val arrayVarsWithInitInZp = allocator.zeropageVars.filter { it.value.dt in ArrayDatatypes && it.value.initialArrayValue!=null }
if(stringVarsWithInitInZp.isNotEmpty() || arrayVarsWithInitInZp.isNotEmpty()) { if(stringVarsWithInitInZp.isNotEmpty() || arrayVarsWithInitInZp.isNotEmpty()) {
asmgen.out("; zp str and array initializations") asmgen.out("; zp str and array initializations")
stringVarsWithInitInZp.forEach { stringVarsWithInitInZp.forEach {
@ -352,7 +351,7 @@ internal class ProgramAndVarsGen(
} }
private fun zeropagevars2asm(scope: INameScope) { private fun zeropagevars2asm(scope: INameScope) {
val zpVariables = zeropage.variables.filter { it.value.originalScope==scope } val zpVariables = allocator.zeropageVars.filter { it.value.originalScope==scope }
for ((scopedName, zpvar) in zpVariables) { for ((scopedName, zpvar) in zpVariables) {
if (scopedName.size == 2 && scopedName[0] == "cx16" && scopedName[1][0] == 'r' && scopedName[1][1].isDigit()) if (scopedName.size == 2 && scopedName[0] == "cx16" && scopedName[1][0] == 'r' && scopedName[1][1].isDigit())
continue // The 16 virtual registers of the cx16 are not actual variables in zp, they're memory mapped continue // The 16 virtual registers of the cx16 are not actual variables in zp, they're memory mapped

View File

@ -8,10 +8,7 @@ import prog8.ast.base.IntegerDatatypes
import prog8.ast.expressions.StringLiteral import prog8.ast.expressions.StringLiteral
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.statements.ZeropageWish import prog8.ast.statements.ZeropageWish
import prog8.compilerinterface.CompilationOptions import prog8.compilerinterface.*
import prog8.compilerinterface.IErrorReporter
import prog8.compilerinterface.IVariablesAndConsts
import prog8.compilerinterface.ZeropageType
internal class VariableAllocator(private val vars: IVariablesAndConsts, internal class VariableAllocator(private val vars: IVariablesAndConsts,
@ -23,6 +20,7 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts,
private val memorySlabsInternal = mutableMapOf<String, Pair<UInt, UInt>>() private val memorySlabsInternal = mutableMapOf<String, Pair<UInt, UInt>>()
internal val memorySlabs: Map<String, Pair<UInt, UInt>> = memorySlabsInternal internal val memorySlabs: Map<String, Pair<UInt, UInt>> = memorySlabsInternal
internal val globalFloatConsts = mutableMapOf<Double, String>() // all float values in the entire program (value -> varname) internal val globalFloatConsts = mutableMapOf<Double, String>() // all float values in the entire program (value -> varname)
internal val zeropageVars: Map<List<String>, Zeropage.ZpAllocation> = zeropage.allocatedVariables
internal fun getMemorySlab(name: String) = memorySlabsInternal[name] internal fun getMemorySlab(name: String) = memorySlabsInternal[name]
internal fun allocateMemorySlab(name: String, size: UInt, align: UInt) { internal fun allocateMemorySlab(name: String, size: UInt, align: UInt) {
@ -120,7 +118,7 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts,
println(" zeropage free space: ${zeropage.free.size} bytes") println(" zeropage free space: ${zeropage.free.size} bytes")
} }
internal fun isZpVar(scopedName: List<String>) = scopedName in zeropage.variables internal fun isZpVar(scopedName: List<String>) = scopedName in zeropage.allocatedVariables
private fun numArrayElements(variable: IVariablesAndConsts.StaticVariable) = private fun numArrayElements(variable: IVariablesAndConsts.StaticVariable) =
when(variable.type) { when(variable.type) {
@ -129,7 +127,7 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts,
else -> null else -> null
} }
fun subroutineExtra(sub: Subroutine): SubroutineExtraAsmInfo { internal fun subroutineExtra(sub: Subroutine): SubroutineExtraAsmInfo {
var extra = subroutineExtras[sub] var extra = subroutineExtras[sub]
return if(extra==null) { return if(extra==null) {
extra = SubroutineExtraAsmInfo() extra = SubroutineExtraAsmInfo()
@ -140,7 +138,7 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts,
extra extra
} }
fun getFloatAsmConst(number: Double): String { internal fun getFloatAsmConst(number: Double): String {
val asmName = globalFloatConsts[number] val asmName = globalFloatConsts[number]
if(asmName!=null) if(asmName!=null)
return asmName return asmName

View File

@ -264,12 +264,12 @@ class TestCx16Zeropage: FunSpec({
test("preallocated zp vars") { test("preallocated zp vars") {
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, cx16target)) val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, cx16target))
zp1.variables[listOf("test")] shouldBe null zp1.allocatedVariables[listOf("test")] shouldBe null
zp1.variables[listOf("cx16", "r0")] shouldNotBe null zp1.allocatedVariables[listOf("cx16", "r0")] shouldNotBe null
zp1.variables[listOf("cx16", "r15")] shouldNotBe null zp1.allocatedVariables[listOf("cx16", "r15")] shouldNotBe null
zp1.variables[listOf("cx16", "r0L")] shouldNotBe null zp1.allocatedVariables[listOf("cx16", "r0L")] shouldNotBe null
zp1.variables[listOf("cx16", "r15L")] shouldNotBe null zp1.allocatedVariables[listOf("cx16", "r15L")] shouldNotBe null
zp1.variables[listOf("cx16", "r0sH")] shouldNotBe null zp1.allocatedVariables[listOf("cx16", "r0sH")] shouldNotBe null
zp1.variables[listOf("cx16", "r15sH")] shouldNotBe null zp1.allocatedVariables[listOf("cx16", "r15sH")] shouldNotBe null
} }
}) })

View File

@ -29,9 +29,7 @@ abstract class Zeropage(protected val options: CompilationOptions) {
// the variables allocated into Zeropage. // the variables allocated into Zeropage.
// name (scoped) ==> pair of address to (Datatype + bytesize) // name (scoped) ==> pair of address to (Datatype + bytesize)
protected val allocatedVariables = mutableMapOf<List<String>, ZpAllocation>() val allocatedVariables = mutableMapOf<List<String>, ZpAllocation>()
private val allocations = mutableMapOf<UInt, Pair<List<String>, DataType>>()
val variables: Map<List<String>, ZpAllocation> = allocatedVariables
val free = mutableListOf<UInt>() // subclasses must set this to the appropriate free locations. val free = mutableListOf<UInt>() // subclasses must set this to the appropriate free locations.
@ -61,7 +59,7 @@ abstract class Zeropage(protected val options: CompilationOptions) {
position: Position?, position: Position?,
errors: IErrorReporter): Result<Pair<UInt, Int>, ZeropageAllocationError> { errors: IErrorReporter): Result<Pair<UInt, Int>, ZeropageAllocationError> {
require(name.isEmpty() || !allocations.values.any { it.first==name } ) {"name can't be allocated twice"} require(name.isEmpty() || name !in allocatedVariables) {"name can't be allocated twice"}
if(options.zeropage== ZeropageType.DONTUSE) if(options.zeropage== ZeropageType.DONTUSE)
return Err(ZeropageAllocationError("zero page usage has been disabled")) return Err(ZeropageAllocationError("zero page usage has been disabled"))
@ -114,7 +112,6 @@ abstract class Zeropage(protected val options: CompilationOptions) {
private fun makeAllocation(address: UInt, size: Int, datatype: DataType, name: List<String>, initValue: Expression?, originalScope: INameScope): UInt { private fun makeAllocation(address: UInt, size: Int, datatype: DataType, name: List<String>, initValue: Expression?, originalScope: INameScope): UInt {
require(size>=0) require(size>=0)
free.removeAll(address until address+size.toUInt()) free.removeAll(address until address+size.toUInt())
allocations[address] = name to datatype
if(name.isNotEmpty()) { if(name.isNotEmpty()) {
allocatedVariables[name] = when(datatype) { allocatedVariables[name] = when(datatype) {
in NumericDatatypes -> ZpAllocation(address, datatype, size, originalScope, null, null) // numerical variables in zeropage never have an initial value here because they are set in separate initializer assignments in NumericDatatypes -> ZpAllocation(address, datatype, size, originalScope, null, null) // numerical variables in zeropage never have an initial value here because they are set in separate initializer assignments

View File

@ -27,6 +27,7 @@ Compiler:
- 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
- unify FunctioncallExpression + FunctioncallStatement and PipeExpression + Pipe statement classes, may require moving Expression/Statement into interfaces instead of abstract base classes - unify FunctioncallExpression + FunctioncallStatement and PipeExpression + Pipe statement classes, may require moving Expression/Statement into interfaces instead of abstract base classes
- for the pipe operator: recognise a placeholder (``?`` or ``%`` or ``_``) in a non-unary function call to allow non-unary functions in the chain; ``4 |> mkword(?, $44) |> print_uw`` - for the pipe operator: recognise a placeholder (``?`` or ``%`` or ``_``) in a non-unary function call to allow non-unary functions in the chain; ``4 |> mkword(?, $44) |> print_uw``
OR: change pipe syntax and require function call, but always have implicit first argument added.
- for the pipe operator: make it 100% syntactic sugar so there's no need for asm codegen like translatePipeExpression - for the pipe operator: make it 100% syntactic sugar so there's no need for asm codegen like translatePipeExpression
- make it possible to inline non-asmsub routines that just contain a single statement (return, functioncall, assignment) - make it possible to inline non-asmsub routines that just contain a single statement (return, functioncall, assignment)
but this requires all identifiers in the inlined expression to be changed to fully scoped names. but this requires all identifiers in the inlined expression to be changed to fully scoped names.
@ -69,5 +70,6 @@ Optimizations:
- translateFunctioncall() in BuiltinFunctionsAsmGen: should be able to assign parameters to a builtin function directly from register(s), this will make the use of a builtin function in a pipe expression more efficient without using a temporary variable - translateFunctioncall() in BuiltinFunctionsAsmGen: should be able to assign parameters to a builtin function directly from register(s), this will make the use of a builtin function in a pipe expression more efficient without using a temporary variable
- translateNormalAssignment() -> better code gen for assigning boolean comparison expressions - translateNormalAssignment() -> better code gen for assigning boolean comparison expressions
- when a for loop's loopvariable isn't referenced in the body, and the iterations are known, replace the loop by a repeatloop - when a for loop's loopvariable isn't referenced in the body, and the iterations are known, replace the loop by a repeatloop
but we have no efficient way right now to see if the body references a variable.
- automatically convert if statements that test for multiple values (if X==1 or X==2..) to if X in [1,2,..] statements, instead of just a warning. - automatically convert if statements that test for multiple values (if X==1 or X==2..) to if X in [1,2,..] statements, instead of just a warning.
- introduce byte-index operator to avoid index multiplications in loops over arrays? see github issue #4 - introduce byte-index operator to avoid index multiplications in loops over arrays? see github issue #4

View File

@ -2,8 +2,10 @@
main { main {
sub start() { sub start() {
uword zzz = memory("sdfasdf", 100, 0) ubyte @shared xx
str @shared foobar = "zsdfzsdf"
str @shared foobar2 = sc:"zsdfzsdf" if xx==1 or xx==2 or xx==3 {
xx++
}
} }
} }