From 2725c4ad4d2e0706a7598cdb122767ccb4eef48c Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 12 Feb 2022 00:15:52 +0100 Subject: [PATCH] slight tweaks to zp and allocator --- .../src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt | 7 +++---- .../src/prog8/codegen/cpu6502/VariableAllocator.kt | 12 +++++------- compiler/test/ZeropageTests.kt | 14 +++++++------- .../src/prog8/compilerinterface/Zeropage.kt | 7 ++----- docs/source/todo.rst | 2 ++ examples/test.p8 | 8 +++++--- 6 files changed, 24 insertions(+), 26 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt index 65128960b..b19aac89d 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt @@ -297,10 +297,9 @@ internal class ProgramAndVarsGen( } } - val zp = zeropage // 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 arrayVarsWithInitInZp = zp.variables.filter { it.value.dt in ArrayDatatypes && it.value.initialArrayValue!=null } + val stringVarsWithInitInZp = allocator.zeropageVars.filter { it.value.dt==DataType.STR && it.value.initialStringValue!=null } + val arrayVarsWithInitInZp = allocator.zeropageVars.filter { it.value.dt in ArrayDatatypes && it.value.initialArrayValue!=null } if(stringVarsWithInitInZp.isNotEmpty() || arrayVarsWithInitInZp.isNotEmpty()) { asmgen.out("; zp str and array initializations") stringVarsWithInitInZp.forEach { @@ -352,7 +351,7 @@ internal class ProgramAndVarsGen( } 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) { 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 diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/VariableAllocator.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/VariableAllocator.kt index 703d35255..ae1bcbb0c 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/VariableAllocator.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/VariableAllocator.kt @@ -8,10 +8,7 @@ import prog8.ast.base.IntegerDatatypes import prog8.ast.expressions.StringLiteral import prog8.ast.statements.Subroutine import prog8.ast.statements.ZeropageWish -import prog8.compilerinterface.CompilationOptions -import prog8.compilerinterface.IErrorReporter -import prog8.compilerinterface.IVariablesAndConsts -import prog8.compilerinterface.ZeropageType +import prog8.compilerinterface.* internal class VariableAllocator(private val vars: IVariablesAndConsts, @@ -23,6 +20,7 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts, private val memorySlabsInternal = mutableMapOf>() internal val memorySlabs: Map> = memorySlabsInternal internal val globalFloatConsts = mutableMapOf() // all float values in the entire program (value -> varname) + internal val zeropageVars: Map, Zeropage.ZpAllocation> = zeropage.allocatedVariables internal fun getMemorySlab(name: String) = memorySlabsInternal[name] 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") } - internal fun isZpVar(scopedName: List) = scopedName in zeropage.variables + internal fun isZpVar(scopedName: List) = scopedName in zeropage.allocatedVariables private fun numArrayElements(variable: IVariablesAndConsts.StaticVariable) = when(variable.type) { @@ -129,7 +127,7 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts, else -> null } - fun subroutineExtra(sub: Subroutine): SubroutineExtraAsmInfo { + internal fun subroutineExtra(sub: Subroutine): SubroutineExtraAsmInfo { var extra = subroutineExtras[sub] return if(extra==null) { extra = SubroutineExtraAsmInfo() @@ -140,7 +138,7 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts, extra } - fun getFloatAsmConst(number: Double): String { + internal fun getFloatAsmConst(number: Double): String { val asmName = globalFloatConsts[number] if(asmName!=null) return asmName diff --git a/compiler/test/ZeropageTests.kt b/compiler/test/ZeropageTests.kt index 3adfb78dd..370f94b13 100644 --- a/compiler/test/ZeropageTests.kt +++ b/compiler/test/ZeropageTests.kt @@ -264,12 +264,12 @@ class TestCx16Zeropage: FunSpec({ test("preallocated zp vars") { val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, cx16target)) - zp1.variables[listOf("test")] shouldBe null - zp1.variables[listOf("cx16", "r0")] shouldNotBe null - zp1.variables[listOf("cx16", "r15")] shouldNotBe null - zp1.variables[listOf("cx16", "r0L")] shouldNotBe null - zp1.variables[listOf("cx16", "r15L")] shouldNotBe null - zp1.variables[listOf("cx16", "r0sH")] shouldNotBe null - zp1.variables[listOf("cx16", "r15sH")] shouldNotBe null + zp1.allocatedVariables[listOf("test")] shouldBe null + zp1.allocatedVariables[listOf("cx16", "r0")] shouldNotBe null + zp1.allocatedVariables[listOf("cx16", "r15")] shouldNotBe null + zp1.allocatedVariables[listOf("cx16", "r0L")] shouldNotBe null + zp1.allocatedVariables[listOf("cx16", "r15L")] shouldNotBe null + zp1.allocatedVariables[listOf("cx16", "r0sH")] shouldNotBe null + zp1.allocatedVariables[listOf("cx16", "r15sH")] shouldNotBe null } }) diff --git a/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt b/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt index 576013b3f..623f71a5d 100644 --- a/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt @@ -29,9 +29,7 @@ abstract class Zeropage(protected val options: CompilationOptions) { // the variables allocated into Zeropage. // name (scoped) ==> pair of address to (Datatype + bytesize) - protected val allocatedVariables = mutableMapOf, ZpAllocation>() - private val allocations = mutableMapOf, DataType>>() - val variables: Map, ZpAllocation> = allocatedVariables + val allocatedVariables = mutableMapOf, ZpAllocation>() val free = mutableListOf() // subclasses must set this to the appropriate free locations. @@ -61,7 +59,7 @@ abstract class Zeropage(protected val options: CompilationOptions) { position: Position?, errors: IErrorReporter): Result, 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) 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, initValue: Expression?, originalScope: INameScope): UInt { require(size>=0) free.removeAll(address until address+size.toUInt()) - allocations[address] = name to datatype if(name.isNotEmpty()) { 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 diff --git a/docs/source/todo.rst b/docs/source/todo.rst index b4a46295f..d1c85f2fc 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -27,6 +27,7 @@ Compiler: - 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 - 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 - 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. @@ -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 - 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 + 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. - introduce byte-index operator to avoid index multiplications in loops over arrays? see github issue #4 diff --git a/examples/test.p8 b/examples/test.p8 index 645df3f2e..9bb9c6235 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -2,8 +2,10 @@ main { sub start() { - uword zzz = memory("sdfasdf", 100, 0) - str @shared foobar = "zsdfzsdf" - str @shared foobar2 = sc:"zsdfzsdf" + ubyte @shared xx + + if xx==1 or xx==2 or xx==3 { + xx++ + } } }