tweak how zp varnames are stored

This commit is contained in:
Irmen de Jong
2022-01-15 17:05:34 +01:00
parent 0f0f40bff3
commit fe51698579
5 changed files with 80 additions and 80 deletions

View File

@@ -110,7 +110,7 @@ class AsmGen(private val program: Program,
.filterIsInstance<VarDecl>() .filterIsInstance<VarDecl>()
.filter { it.type==VarDeclType.VAR } .filter { it.type==VarDeclType.VAR }
.toSet() .toSet()
.map { it to it.scopedName.joinToString(".") } .map { it to it.scopedName }
val varsRequiringZp = allVariables.filter { it.first.zeropage==ZeropageWish.REQUIRE_ZEROPAGE } val varsRequiringZp = allVariables.filter { it.first.zeropage==ZeropageWish.REQUIRE_ZEROPAGE }
val varsPreferringZp = allVariables val varsPreferringZp = allVariables
.filter { it.first.zeropage==ZeropageWish.PREFER_ZEROPAGE } .filter { it.first.zeropage==ZeropageWish.PREFER_ZEROPAGE }
@@ -332,14 +332,14 @@ class AsmGen(private val program: Program,
for(variable in variables) { for(variable in variables) {
if(blockname=="prog8_lib" && variable.name.startsWith("P8ZP_SCRATCH_")) if(blockname=="prog8_lib" && variable.name.startsWith("P8ZP_SCRATCH_"))
continue // the "hooks" to the temp vars are not generated as new variables continue // the "hooks" to the temp vars are not generated as new variables
val fullName = variable.scopedName.joinToString(".") val scopedName = variable.scopedName
val zpAlloc = zeropage.allocatedZeropageVariable(fullName) val zpAlloc = zeropage.allocatedZeropageVariable(scopedName)
if (zpAlloc == null) { if (zpAlloc == null) {
// This var is not on the ZP yet. Attempt to move it there if it's an integer type // This var is not on the ZP yet. Attempt to move it there if it's an integer type
if(variable.zeropage != ZeropageWish.NOT_IN_ZEROPAGE && if(variable.zeropage != ZeropageWish.NOT_IN_ZEROPAGE &&
variable.datatype in IntegerDatatypes variable.datatype in IntegerDatatypes
&& options.zeropage != ZeropageType.DONTUSE) { && options.zeropage != ZeropageType.DONTUSE) {
val result = zeropage.allocate(fullName, variable.datatype, null, null, errors) val result = zeropage.allocate(scopedName, variable.datatype, null, null, errors)
errors.report() errors.report()
result.fold( result.fold(
success = { address -> out("${variable.name} = $address\t; zp ${variable.datatype}") }, success = { address -> out("${variable.name} = $address\t; zp ${variable.datatype}") },
@@ -483,7 +483,7 @@ class AsmGen(private val program: Program,
val vars = statements.asSequence() val vars = statements.asSequence()
.filterIsInstance<VarDecl>() .filterIsInstance<VarDecl>()
.filter { .filter {
it.type==VarDeclType.VAR && zeropage.allocatedZeropageVariable(it.scopedName.joinToString("."))==null it.type==VarDeclType.VAR && zeropage.allocatedZeropageVariable(it.scopedName)==null
} }
val encodedstringVars = vars val encodedstringVars = vars
@@ -500,8 +500,7 @@ class AsmGen(private val program: Program,
val blockname = inBlock?.name val blockname = inBlock?.name
vars.filter{ it.datatype != DataType.STR }.sortedBy { it.datatype }.forEach { vars.filter{ it.datatype != DataType.STR }.sortedBy { it.datatype }.forEach {
val scopedname = it.scopedName.joinToString(".") if(!isZpVar(it.scopedName)) {
if(!isZpVar(scopedname)) {
if(blockname!="prog8_lib" || !it.name.startsWith("P8ZP_SCRATCH_")) // the "hooks" to the temp vars are not generated as new variables if(blockname!="prog8_lib" || !it.name.startsWith("P8ZP_SCRATCH_")) // the "hooks" to the temp vars are not generated as new variables
vardecl2asm(it) vardecl2asm(it)
} }
@@ -689,9 +688,8 @@ class AsmGen(private val program: Program,
} }
is VarDecl -> { is VarDecl -> {
val sourceName = asmVariableName(pointervar) val sourceName = asmVariableName(pointervar)
val scopedName = target.scopedName.joinToString(".")
if (isTargetCpu(CpuType.CPU65c02)) { if (isTargetCpu(CpuType.CPU65c02)) {
return if (isZpVar(scopedName)) { return if (isZpVar(target.scopedName)) {
// pointervar is already in the zero page, no need to copy // pointervar is already in the zero page, no need to copy
out(" lda ($sourceName)") out(" lda ($sourceName)")
sourceName sourceName
@@ -705,7 +703,7 @@ class AsmGen(private val program: Program,
"P8ZP_SCRATCH_W1" "P8ZP_SCRATCH_W1"
} }
} else { } else {
return if (isZpVar(scopedName)) { return if (isZpVar(target.scopedName)) {
// pointervar is already in the zero page, no need to copy // pointervar is already in the zero page, no need to copy
out(" ldy #0 | lda ($sourceName),y") out(" ldy #0 | lda ($sourceName),y")
sourceName sourceName
@@ -728,9 +726,8 @@ class AsmGen(private val program: Program,
internal fun storeAIntoPointerVar(pointervar: IdentifierReference) { internal fun storeAIntoPointerVar(pointervar: IdentifierReference) {
val sourceName = asmVariableName(pointervar) val sourceName = asmVariableName(pointervar)
val vardecl = pointervar.targetVarDecl(program)!! val vardecl = pointervar.targetVarDecl(program)!!
val scopedName = vardecl.scopedName.joinToString(".")
if (isTargetCpu(CpuType.CPU65c02)) { if (isTargetCpu(CpuType.CPU65c02)) {
if (isZpVar(scopedName)) { if (isZpVar(vardecl.scopedName)) {
// pointervar is already in the zero page, no need to copy // pointervar is already in the zero page, no need to copy
out(" sta ($sourceName)") out(" sta ($sourceName)")
} else { } else {
@@ -742,7 +739,7 @@ class AsmGen(private val program: Program,
sta (P8ZP_SCRATCH_W2)""") sta (P8ZP_SCRATCH_W2)""")
} }
} else { } else {
if (isZpVar(scopedName)) { if (isZpVar(vardecl.scopedName)) {
// pointervar is already in the zero page, no need to copy // pointervar is already in the zero page, no need to copy
out(" ldy #0 | sta ($sourceName),y") out(" ldy #0 | sta ($sourceName),y")
} else { } else {
@@ -1464,7 +1461,7 @@ $repeatLabel lda $counterVar
val counterVar = makeLabel("counter") val counterVar = makeLabel("counter")
when(dt) { when(dt) {
DataType.UBYTE, DataType.UWORD -> { DataType.UBYTE, DataType.UWORD -> {
val result = zeropage.allocate(counterVar, dt, null, stmt.position, errors) val result = zeropage.allocate(listOf(counterVar), dt, null, stmt.position, errors)
result.fold( result.fold(
success = { zpvar -> asmInfo.extraVars.add(Triple(dt, counterVar, zpvar.first)) }, success = { zpvar -> asmInfo.extraVars.add(Triple(dt, counterVar, zpvar.first)) },
failure = { asmInfo.extraVars.add(Triple(dt, counterVar, null)) } // allocate normally failure = { asmInfo.extraVars.add(Triple(dt, counterVar, null)) } // allocate normally
@@ -1726,12 +1723,12 @@ $label nop""")
} }
} }
internal fun isZpVar(scopedName: String): Boolean = internal fun isZpVar(scopedName: List<String>): Boolean =
zeropage.allocatedZeropageVariable(scopedName)!=null zeropage.allocatedZeropageVariable(scopedName)!=null
internal fun isZpVar(variable: IdentifierReference): Boolean { internal fun isZpVar(variable: IdentifierReference): Boolean {
val vardecl = variable.targetVarDecl(program)!! val vardecl = variable.targetVarDecl(program)!!
return zeropage.allocatedZeropageVariable(vardecl.scopedName.joinToString("."))!=null return zeropage.allocatedZeropageVariable(vardecl.scopedName)!=null
} }
internal fun jmp(asmLabel: String) { internal fun jmp(asmLabel: String) {

View File

@@ -291,7 +291,7 @@ $loopLabel sty $indexVar
} }
if(length>=16) { if(length>=16) {
// allocate index var on ZP if possible // allocate index var on ZP if possible
val result = asmgen.zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors) val result = asmgen.zeropage.allocate(listOf(indexVar), DataType.UBYTE, null, stmt.position, asmgen.errors)
result.fold( result.fold(
success = { zpAddr-> asmgen.out("""$indexVar = $zpAddr ; auto zp UBYTE""") }, success = { zpAddr-> asmgen.out("""$indexVar = $zpAddr ; auto zp UBYTE""") },
failure = { asmgen.out("$indexVar .byte 0") } failure = { asmgen.out("$indexVar .byte 0") }
@@ -332,7 +332,7 @@ $loopLabel sty $indexVar
} }
if(length>=16) { if(length>=16) {
// allocate index var on ZP if possible // allocate index var on ZP if possible
val result = asmgen.zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors) val result = asmgen.zeropage.allocate(listOf(indexVar), DataType.UBYTE, null, stmt.position, asmgen.errors)
result.fold( result.fold(
success = { zpAddr-> asmgen.out("""$indexVar = $zpAddr ; auto zp UBYTE""") }, success = { zpAddr-> asmgen.out("""$indexVar = $zpAddr ; auto zp UBYTE""") },
failure = { asmgen.out("$indexVar .byte 0") } failure = { asmgen.out("$indexVar .byte 0") }

View File

@@ -40,12 +40,12 @@ class CX16Zeropage(options: CompilationOptions) : Zeropage(options) {
removeReservedFromFreePool() removeReservedFromFreePool()
for(reg in 0..15) { for(reg in 0..15) {
allocatedVariables["cx16.r${reg}"] = ((2+reg*2).toUInt() to 2) to DataType.UWORD // cx16.r0 .. cx16.r15 allocatedVariables[listOf("cx16", "r${reg}")] = ((2+reg*2).toUInt() to 2) to DataType.UWORD // cx16.r0 .. cx16.r15
allocatedVariables["cx16.r${reg}s"] = ((2+reg*2).toUInt() to 2) to DataType.WORD // cx16.r0s .. cx16.r15s allocatedVariables[listOf("cx16", "r${reg}s")] = ((2+reg*2).toUInt() to 2) to DataType.WORD // cx16.r0s .. cx16.r15s
allocatedVariables["cx16.r${reg}L"] = ((2+reg*2).toUInt() to 1) to DataType.UBYTE // cx16.r0L .. cx16.r15L allocatedVariables[listOf("cx16", "r${reg}L")] = ((2+reg*2).toUInt() to 1) to DataType.UBYTE // cx16.r0L .. cx16.r15L
allocatedVariables["cx16.r${reg}H"] = ((3+reg*2).toUInt() to 1) to DataType.UBYTE // cx16.r0H .. cx16.r15H allocatedVariables[listOf("cx16", "r${reg}H")] = ((3+reg*2).toUInt() to 1) to DataType.UBYTE // cx16.r0H .. cx16.r15H
allocatedVariables["cx16.r${reg}sL"] = ((2+reg*2).toUInt() to 1) to DataType.BYTE // cx16.r0sL .. cx16.r15sL allocatedVariables[listOf("cx16", "r${reg}sL")] = ((2+reg*2).toUInt() to 1) to DataType.BYTE // cx16.r0sL .. cx16.r15sL
allocatedVariables["cx16.r${reg}sH"] = ((3+reg*2).toUInt() to 1) to DataType.BYTE // cx16.r0sH .. cx16.r15sH allocatedVariables[listOf("cx16", "r${reg}sH")] = ((3+reg*2).toUInt() to 1) to DataType.BYTE // cx16.r0sH .. cx16.r15sH
} }
} }

View File

@@ -95,26 +95,26 @@ class TestC64Zeropage: FunSpec({
test("testNames") { test("testNames") {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, C64Target)) val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, C64Target))
var result = zp.allocate("", DataType.UBYTE, null, null, errors) var result = zp.allocate(emptyList(), DataType.UBYTE, null, null, errors)
result.onFailure { fail(it.toString()) } result.onFailure { fail(it.toString()) }
result = zp.allocate("", DataType.UBYTE, null, null, errors) result = zp.allocate(emptyList(), DataType.UBYTE, null, null, errors)
result.onFailure { fail(it.toString()) } result.onFailure { fail(it.toString()) }
result = zp.allocate("varname", DataType.UBYTE, null, null, errors) result = zp.allocate(listOf("varname"), DataType.UBYTE, null, null, errors)
result.onFailure { fail(it.toString()) } result.onFailure { fail(it.toString()) }
shouldThrow<IllegalArgumentException> { zp.allocate("varname", DataType.UBYTE, null, null, errors) } shouldThrow<IllegalArgumentException> { zp.allocate(listOf("varname"), DataType.UBYTE, null, null, errors) }
result = zp.allocate("varname2", DataType.UBYTE, null, null, errors) result = zp.allocate(listOf("varname2"), DataType.UBYTE, null, null, errors)
result.onFailure { fail(it.toString()) } result.onFailure { fail(it.toString()) }
} }
test("testZpFloatEnable") { test("testZpFloatEnable") {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target))
var result = zp.allocate("", DataType.FLOAT, null, null, errors) var result = zp.allocate(emptyList(), DataType.FLOAT, null, null, errors)
result.expectError { "should be allocation error due to disabled floats" } result.expectError { "should be allocation error due to disabled floats" }
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, false, C64Target)) val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, false, C64Target))
result = zp2.allocate("", DataType.FLOAT, null, null, errors) result = zp2.allocate(emptyList(), DataType.FLOAT, null, null, errors)
result.expectError { "should be allocation error due to disabled ZP use" } result.expectError { "should be allocation error due to disabled ZP use" }
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false, C64Target)) val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false, C64Target))
zp3.allocate("", DataType.FLOAT, null, null, errors) zp3.allocate(emptyList(), DataType.FLOAT, null, null, errors)
} }
test("testZpModesWithFloats") { test("testZpModesWithFloats") {
@@ -136,7 +136,7 @@ class TestC64Zeropage: FunSpec({
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, false, C64Target)) val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, false, C64Target))
println(zp.free) println(zp.free)
zp.availableBytes() shouldBe 0 zp.availableBytes() shouldBe 0
val result = zp.allocate("", DataType.BYTE, null, null, errors) val result = zp.allocate(emptyList(), DataType.BYTE, null, null, errors)
result.expectError { "expected error due to disabled ZP use" } result.expectError { "expected error due to disabled ZP use" }
} }
@@ -149,9 +149,9 @@ class TestC64Zeropage: FunSpec({
zp3.availableBytes() shouldBe 125 zp3.availableBytes() shouldBe 125
val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target))
zp4.availableBytes() shouldBe 239 zp4.availableBytes() shouldBe 239
zp4.allocate("test", DataType.UBYTE, null, null, errors) zp4.allocate(listOf("test"), DataType.UBYTE, null, null, errors)
zp4.availableBytes() shouldBe 238 zp4.availableBytes() shouldBe 238
zp4.allocate("test2", DataType.UBYTE, null, null, errors) zp4.allocate(listOf("test2"), DataType.UBYTE, null, null, errors)
zp4.availableBytes() shouldBe 237 zp4.availableBytes() shouldBe 237
} }
@@ -182,19 +182,19 @@ class TestC64Zeropage: FunSpec({
zp.hasByteAvailable() shouldBe true zp.hasByteAvailable() shouldBe true
zp.hasWordAvailable() shouldBe true zp.hasWordAvailable() shouldBe true
var result = zp.allocate("", DataType.FLOAT, null, null, errors) var result = zp.allocate(emptyList(), DataType.FLOAT, null, null, errors)
result.expectError { "expect allocation error: in regular zp there aren't 5 sequential bytes free" } result.expectError { "expect allocation error: in regular zp there aren't 5 sequential bytes free" }
for (i in 0 until zp.availableBytes()) { for (i in 0 until zp.availableBytes()) {
val result = zp.allocate("", DataType.UBYTE, null, null, errors) val alloc = zp.allocate(emptyList(), DataType.UBYTE, null, null, errors)
result.getOrElse { throw it } alloc.getOrElse { throw it }
} }
zp.availableBytes() shouldBe 0 zp.availableBytes() shouldBe 0
zp.hasByteAvailable() shouldBe false zp.hasByteAvailable() shouldBe false
zp.hasWordAvailable() shouldBe false zp.hasWordAvailable() shouldBe false
result = zp.allocate("", DataType.UBYTE, null, null, errors) result = zp.allocate(emptyList(), DataType.UBYTE, null, null, errors)
result.expectError { "expected allocation error" } result.expectError { "expected allocation error" }
result = zp.allocate("", DataType.UWORD, null, null, errors) result = zp.allocate(emptyList(), DataType.UWORD, null, null, errors)
result.expectError { "expected allocation error" } result.expectError { "expected allocation error" }
} }
@@ -203,47 +203,47 @@ class TestC64Zeropage: FunSpec({
zp.availableBytes() shouldBe 239 zp.availableBytes() shouldBe 239
zp.hasByteAvailable() shouldBe true zp.hasByteAvailable() shouldBe true
zp.hasWordAvailable() shouldBe true zp.hasWordAvailable() shouldBe true
var result = zp.allocate("", DataType.UWORD, null, null, errors) var result = zp.allocate(emptyList(), DataType.UWORD, null, null, errors)
val loc = result.getOrElse { throw it } .first val loc = result.getOrElse { throw it } .first
loc shouldBeGreaterThan 3u loc shouldBeGreaterThan 3u
loc shouldNotBeIn zp.free loc shouldNotBeIn zp.free
val num = zp.availableBytes() / 2 val num = zp.availableBytes() / 2
for(i in 0..num-3) { for(i in 0..num-3) {
zp.allocate("", DataType.UWORD, null, null, errors) zp.allocate(emptyList(), DataType.UWORD, null, null, errors)
} }
zp.availableBytes() shouldBe 5 zp.availableBytes() shouldBe 5
// can't allocate because no more sequential bytes, only fragmented // can't allocate because no more sequential bytes, only fragmented
result = zp.allocate("", DataType.UWORD, null, null, errors) result = zp.allocate(emptyList(), DataType.UWORD, null, null, errors)
result.expectError { "should give allocation error" } result.expectError { "should give allocation error" }
for(i in 0..4) { for(i in 0..4) {
zp.allocate("", DataType.UBYTE, null, null, errors) zp.allocate(emptyList(), DataType.UBYTE, null, null, errors)
} }
zp.availableBytes() shouldBe 0 zp.availableBytes() shouldBe 0
zp.hasByteAvailable() shouldBe false zp.hasByteAvailable() shouldBe false
zp.hasWordAvailable() shouldBe false zp.hasWordAvailable() shouldBe false
result = zp.allocate("", DataType.UBYTE, null, null, errors) result = zp.allocate(emptyList(), DataType.UBYTE, null, null, errors)
result.expectError { "should give allocation error" } result.expectError { "should give allocation error" }
} }
test("testEfficientAllocation") { test("testEfficientAllocation") {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target)) val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target))
zp.availableBytes() shouldBe 18 zp.availableBytes() shouldBe 18
zp.allocate("", DataType.WORD, null, null, errors ).getOrElse{throw it}.first shouldBe 0x04u zp.allocate(emptyList(), DataType.WORD, null, null, errors ).getOrElse{throw it}.first shouldBe 0x04u
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0x06u zp.allocate(emptyList(), DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0x06u
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0x0au zp.allocate(emptyList(), DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0x0au
zp.allocate("", DataType.UWORD, null, null, errors).getOrElse{throw it}.first shouldBe 0x9bu zp.allocate(emptyList(), DataType.UWORD, null, null, errors).getOrElse{throw it}.first shouldBe 0x9bu
zp.allocate("", DataType.UWORD, null, null, errors).getOrElse{throw it}.first shouldBe 0x9eu zp.allocate(emptyList(), DataType.UWORD, null, null, errors).getOrElse{throw it}.first shouldBe 0x9eu
zp.allocate("", DataType.UWORD, null, null, errors).getOrElse{throw it}.first shouldBe 0xa5u zp.allocate(emptyList(), DataType.UWORD, null, null, errors).getOrElse{throw it}.first shouldBe 0xa5u
zp.allocate("", DataType.UWORD, null, null, errors).getOrElse{throw it}.first shouldBe 0xb0u zp.allocate(emptyList(), DataType.UWORD, null, null, errors).getOrElse{throw it}.first shouldBe 0xb0u
zp.allocate("", DataType.UWORD, null, null, errors).getOrElse{throw it}.first shouldBe 0xbeu zp.allocate(emptyList(), DataType.UWORD, null, null, errors).getOrElse{throw it}.first shouldBe 0xbeu
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0x0eu zp.allocate(emptyList(), DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0x0eu
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0x92u zp.allocate(emptyList(), DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0x92u
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0x96u zp.allocate(emptyList(), DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0x96u
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0xf9u zp.allocate(emptyList(), DataType.UBYTE, null, null, errors).getOrElse{throw it}.first shouldBe 0xf9u
zp.availableBytes() shouldBe 0 zp.availableBytes() shouldBe 0
} }
@@ -273,9 +273,9 @@ class TestCx16Zeropage: FunSpec({
zp2.availableBytes() shouldBe 175 zp2.availableBytes() shouldBe 175
val zp3 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, Cx16Target)) val zp3 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, Cx16Target))
zp3.availableBytes() shouldBe 216 zp3.availableBytes() shouldBe 216
zp3.allocate("test", DataType.UBYTE, null, null, errors) zp3.allocate(listOf("test"), DataType.UBYTE, null, null, errors)
zp3.availableBytes() shouldBe 215 zp3.availableBytes() shouldBe 215
zp3.allocate("test2", DataType.UBYTE, null, null, errors) zp3.allocate(listOf("test2"), DataType.UBYTE, null, null, errors)
zp3.availableBytes() shouldBe 214 zp3.availableBytes() shouldBe 214
} }
@@ -291,12 +291,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.allocatedZeropageVariable("test") shouldBe null zp1.allocatedZeropageVariable(listOf("test")) shouldBe null
zp1.allocatedZeropageVariable("cx16.r0") shouldNotBe null zp1.allocatedZeropageVariable(listOf("cx16", "r0")) shouldNotBe null
zp1.allocatedZeropageVariable("cx16.r15") shouldNotBe null zp1.allocatedZeropageVariable(listOf("cx16", "r15")) shouldNotBe null
zp1.allocatedZeropageVariable("cx16.r0L") shouldNotBe null zp1.allocatedZeropageVariable(listOf("cx16", "r0L")) shouldNotBe null
zp1.allocatedZeropageVariable("cx16.r15L") shouldNotBe null zp1.allocatedZeropageVariable(listOf("cx16", "r15L")) shouldNotBe null
zp1.allocatedZeropageVariable("cx16.r0sH") shouldNotBe null zp1.allocatedZeropageVariable(listOf("cx16", "r0sH")) shouldNotBe null
zp1.allocatedZeropageVariable("cx16.r15sH") shouldNotBe null zp1.allocatedZeropageVariable(listOf("cx16", "r15sH")) shouldNotBe null
} }
}) })

View File

@@ -17,7 +17,12 @@ abstract class Zeropage(protected val options: CompilationOptions) {
abstract val SCRATCH_W2 : UInt // temp storage 2 for a word $fb+$fc abstract val SCRATCH_W2 : UInt // temp storage 2 for a word $fb+$fc
private val allocations = mutableMapOf<UInt, Pair<String, DataType>>() // the variables allocated into Zeropage.
// name (scoped) ==> pair of (address and bytesize) and DataType
// TODO switch the pair around
protected val allocatedVariables = mutableMapOf<List<String>, Pair<Pair<UInt, Int>, DataType>>()
private val allocations = mutableMapOf<UInt, Pair<List<String>, DataType>>()
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.
fun removeReservedFromFreePool() { fun removeReservedFromFreePool() {
@@ -36,8 +41,8 @@ abstract class Zeropage(protected val options: CompilationOptions) {
return free.windowed(2).any { it[0] == it[1] - 1u } return free.windowed(2).any { it[0] == it[1] - 1u }
} }
fun allocate(scopedname: String, datatype: DataType, arraySize: Int?, position: Position?, errors: IErrorReporter): Result<Pair<UInt, Int>, ZeropageAllocationError> { fun allocate(name: List<String>, datatype: DataType, arraySize: Int?, position: Position?, errors: IErrorReporter): Result<Pair<UInt, Int>, ZeropageAllocationError> {
require(scopedname.isEmpty() || !allocations.values.any { it.first==scopedname } ) {"scopedname can't be allocated twice"} require(name.isEmpty() || !allocations.values.any { it.first==name } ) {"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"))
@@ -50,7 +55,7 @@ abstract class Zeropage(protected val options: CompilationOptions) {
if(position!=null) if(position!=null)
errors.warn("allocating a large value in zeropage; str/array $memsize bytes", position) errors.warn("allocating a large value in zeropage; str/array $memsize bytes", position)
else else
errors.warn("$scopedname: allocating a large value in zeropage; str/array $memsize bytes", Position.DUMMY) errors.warn("$name: allocating a large value in zeropage; str/array $memsize bytes", Position.DUMMY)
memsize memsize
} }
DataType.FLOAT -> { DataType.FLOAT -> {
@@ -59,7 +64,7 @@ abstract class Zeropage(protected val options: CompilationOptions) {
if(position!=null) if(position!=null)
errors.warn("allocating a large value in zeropage; float $memsize bytes", position) errors.warn("allocating a large value in zeropage; float $memsize bytes", position)
else else
errors.warn("$scopedname: allocating a large value in zeropage; float $memsize bytes", Position.DUMMY) errors.warn("$name: allocating a large value in zeropage; float $memsize bytes", Position.DUMMY)
memsize memsize
} else return Err(ZeropageAllocationError("floating point option not enabled")) } else return Err(ZeropageAllocationError("floating point option not enabled"))
} }
@@ -71,13 +76,13 @@ abstract class Zeropage(protected val options: CompilationOptions) {
if(size==1) { if(size==1) {
for(candidate in free.minOrNull()!! .. free.maxOrNull()!!+1u) { for(candidate in free.minOrNull()!! .. free.maxOrNull()!!+1u) {
if(oneSeparateByteFree(candidate)) if(oneSeparateByteFree(candidate))
return Ok(Pair(makeAllocation(candidate, 1, datatype, scopedname), 1)) return Ok(Pair(makeAllocation(candidate, 1, datatype, name), 1))
} }
return Ok(Pair(makeAllocation(free[0], 1, datatype, scopedname), 1)) return Ok(Pair(makeAllocation(free[0], 1, datatype, name), 1))
} }
for(candidate in free.minOrNull()!! .. free.maxOrNull()!!+1u) { for(candidate in free.minOrNull()!! .. free.maxOrNull()!!+1u) {
if (sequentialFree(candidate, size)) if (sequentialFree(candidate, size))
return Ok(Pair(makeAllocation(candidate, size, datatype, scopedname), size)) return Ok(Pair(makeAllocation(candidate, size, datatype, name), size))
} }
} }
} }
@@ -87,11 +92,11 @@ abstract class Zeropage(protected val options: CompilationOptions) {
private fun reserve(range: UIntRange) = free.removeAll(range) private fun reserve(range: UIntRange) = free.removeAll(range)
private fun makeAllocation(address: UInt, size: Int, datatype: DataType, name: String?): UInt { private fun makeAllocation(address: UInt, size: Int, datatype: DataType, name: List<String>): UInt {
require(size>=0) require(size>=0)
free.removeAll(address until address+size.toUInt()) free.removeAll(address until address+size.toUInt())
allocations[address] = (name ?: "<unnamed>") to datatype allocations[address] = name to datatype
if(name!=null) if(name.isNotEmpty())
allocatedVariables[name] = (address to size) to datatype allocatedVariables[name] = (address to size) to datatype
return address return address
} }
@@ -102,7 +107,5 @@ abstract class Zeropage(protected val options: CompilationOptions) {
return free.containsAll((address until address+size.toUInt()).toList()) return free.containsAll((address until address+size.toUInt()).toList())
} }
fun allocatedZeropageVariable(scopedname: String): Pair<Pair<UInt, Int>, DataType>? = allocatedVariables[scopedname] fun allocatedZeropageVariable(name: List<String>): Pair<Pair<UInt, Int>, DataType>? = allocatedVariables[name]
protected val allocatedVariables = mutableMapOf<String, Pair<Pair<UInt, Int>, DataType>>()
} }