diff --git a/codeGeneration/src/prog8/compiler/target/c64/C64MachineDefinition.kt b/codeGeneration/src/prog8/compiler/target/c64/C64MachineDefinition.kt index 4b7fbbccf..c466b5e28 100644 --- a/codeGeneration/src/prog8/compiler/target/c64/C64MachineDefinition.kt +++ b/codeGeneration/src/prog8/compiler/target/c64/C64MachineDefinition.kt @@ -89,7 +89,6 @@ object C64MachineDefinition: IMachineDefinition { if (options.zeropage == ZeropageType.FULL) { free.addAll(0x04..0xf9) free.add(0xff) - free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1)) free.removeAll(listOf(0xa0, 0xa1, 0xa2, 0x91, 0xc0, 0xc5, 0xcb, 0xf5, 0xf6)) // these are updated by IRQ } else { if (options.zeropage == ZeropageType.KERNALSAFE || options.zeropage == ZeropageType.FLOATSAFE) { @@ -133,13 +132,8 @@ object C64MachineDefinition: IMachineDefinition { free.clear() } } - require(SCRATCH_B1 !in free) - require(SCRATCH_REG !in free) - require(SCRATCH_W1 !in free) - require(SCRATCH_W2 !in free) - for (reserved in options.zpReserved) - reserve(reserved) + removeReservedFromFreePool() } } diff --git a/codeGeneration/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt b/codeGeneration/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt index 2463b183a..29244c4f1 100644 --- a/codeGeneration/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt +++ b/codeGeneration/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt @@ -104,16 +104,13 @@ object CX16MachineDefinition: IMachineDefinition { when (options.zeropage) { ZeropageType.FULL -> { free.addAll(0x22..0xff) - free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1)) } ZeropageType.KERNALSAFE -> { free.addAll(0x22..0x7f) free.addAll(0xa9..0xff) - free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1)) } ZeropageType.BASICSAFE -> { free.addAll(0x22..0x7f) - free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1)) } ZeropageType.DONTUSE -> { free.clear() // don't use zeropage at all @@ -121,13 +118,7 @@ object CX16MachineDefinition: IMachineDefinition { else -> throw CompilerException("for this machine target, zero page type 'floatsafe' is not available. ${options.zeropage}") } - require(SCRATCH_B1 !in free) - require(SCRATCH_REG !in free) - require(SCRATCH_W1 !in free) - require(SCRATCH_W2 !in free) - - for (reserved in options.zpReserved) - reserve(reserved) + removeReservedFromFreePool() } } } diff --git a/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt b/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt index ef35d144b..2d27cb3b4 100644 --- a/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt @@ -19,6 +19,13 @@ abstract class Zeropage(protected val options: CompilationOptions) { val allowedDatatypes = NumericDatatypes + fun removeReservedFromFreePool() { + for (reserved in options.zpReserved) + reserve(reserved) + + free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1)) + } + fun availableBytes() = if(options.zeropage== ZeropageType.DONTUSE) 0 else free.size fun hasByteAvailable() = if(options.zeropage== ZeropageType.DONTUSE) false else free.isNotEmpty() fun availableWords(): Int { diff --git a/compilerInterfaces/test/TestZeropage.kt b/compilerInterfaces/test/TestZeropage.kt index e7a0bd608..7c065777a 100644 --- a/compilerInterfaces/test/TestZeropage.kt +++ b/compilerInterfaces/test/TestZeropage.kt @@ -24,25 +24,24 @@ class TestZeropage { compTarget ) ) - assertEquals(256-4-16, zp.free.size) + assertEquals(256-6-16, zp.free.size) } class DummyCompilationTarget: ICompilationTarget { - override val name: String - get() = TODO("Not yet implemented") + override val name: String = "dummy" override val machine: IMachineDefinition - get() = TODO("Not yet implemented") + get() = throw NotImplementedError("dummy") override fun encodeString(str: String, altEncoding: Boolean): List { - TODO("Not yet implemented") + throw NotImplementedError("dummy") } override fun decodeString(bytes: List, altEncoding: Boolean): String { - TODO("Not yet implemented") + throw NotImplementedError("dummy") } override fun memorySize(dt: DataType): Int { - TODO("Not yet implemented") + throw NotImplementedError("dummy") } } @@ -50,21 +49,13 @@ class TestZeropage { class DummyZeropage(options: CompilationOptions) : Zeropage(options) { override val SCRATCH_B1: Int = 0x10 override val SCRATCH_REG: Int = 0x11 - override val SCRATCH_W1: Int= 0x12 - override val SCRATCH_W2: Int = 0x13 + override val SCRATCH_W1: Int= 0x20 + override val SCRATCH_W2: Int = 0x30 init { free.addAll(0..255) - // TODO should be in class: - free.remove(SCRATCH_B1) - free.remove(SCRATCH_REG) - free.remove(SCRATCH_W1) - free.remove(SCRATCH_W2) - - // TODO should be in class: - for (reserved in options.zpReserved) - reserve(reserved) + removeReservedFromFreePool() } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 2f3b6fd9a..1da019f37 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -4,6 +4,7 @@ TODO For next compiler release (7.2) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - fix the asm-labels problem (github issue #62) +- find a way to optimize if-statement codegen so that "if var & %10000" doesn't use stack & subroutine call, but also that the simple case "if X {...}" remains fast Blocked by Commander-x16 v39 release @@ -15,7 +16,7 @@ Blocked by Commander-x16 v39 release Future ^^^^^^ - get rid of all TODO's in the code -- improve testability further, add more tests, address more questions/issues from the testability discussions. +- improve testability further, add more tests - replace certain uses of inferredType.getOr(DataType.UNDEFINED) by i.getOrElse({ errorhandler }) - see if we can remove more "[InferredType].getOr(DataType.UNDEFINED)" - use more of Result<> and Either<> to handle errors/ nulls better @@ -37,7 +38,6 @@ Future More code optimization ideas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- a way to optimize if-statement codegen so that "if var & %10000" doesn't use stack & subroutine call, but also that the simple case "if X {...}" remains fast - detect variables that are written but never read - mark those as unused too and remove them, such as ``uword unused = memory("unused222", 20)`` - also remove this memory slab allocation - rewrite expression tree evaluation such that it doesn't use an eval stack but flatten the tree into linear code that uses a fixed number of predetermined value 'variables' - this removes the need for the BinExprSplitter (which is problematic now)