refactor and fix the way memory addresses are checked to be in IO space or regular ram

This commit is contained in:
Irmen de Jong 2021-11-18 22:47:58 +01:00
parent 4f5d36a84d
commit b334d89715
13 changed files with 155 additions and 96 deletions

View File

@ -56,7 +56,7 @@ object C64MachineDefinition: IMachineDefinition {
} }
} }
override fun isRegularRAMaddress(address: Int): Boolean = address<0xa000 || address in 0xc000..0xcfff override fun isIOAddress(address: Int): Boolean = address==0 || address==1 || address in 0xd000..0xdfff
override fun initializeZeropage(compilerOptions: CompilationOptions) { override fun initializeZeropage(compilerOptions: CompilationOptions) {
zeropage = C64Zeropage(compilerOptions) zeropage = C64Zeropage(compilerOptions)

View File

@ -67,7 +67,7 @@ object CX16MachineDefinition: IMachineDefinition {
} }
} }
override fun isRegularRAMaddress(address: Int): Boolean = address < 0x9f00 || address in 0xa000..0xbfff override fun isIOAddress(address: Int): Boolean = address==0 || address==1 || address in 0x9f00..0x9fff
override fun initializeZeropage(compilerOptions: CompilationOptions) { override fun initializeZeropage(compilerOptions: CompilationOptions) {
zeropage = CX16Zeropage(compilerOptions) zeropage = CX16Zeropage(compilerOptions)

View File

@ -69,7 +69,6 @@ class AsmGenSymbolsTests: StringSpec({
val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test")) val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
.addModule(module) .addModule(module)
module.linkIntoProgram(program)
return program return program
} }

View File

@ -15,7 +15,7 @@ import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.compilerinterface.CompilationOptions import prog8.compilerinterface.CompilationOptions
import prog8.compilerinterface.ICompilationTarget import prog8.compilerinterface.ICompilationTarget
import prog8.compilerinterface.isInRegularRAMof import prog8.compilerinterface.isIOAddress
class BinExprSplitter(private val program: Program, private val options: CompilationOptions, private val compTarget: ICompilationTarget) : AstWalker() { class BinExprSplitter(private val program: Program, private val options: CompilationOptions, private val compTarget: ICompilationTarget) : AstWalker() {
@ -97,7 +97,7 @@ X = BinExpr X = LeftExpr
private fun isSimpleTarget(target: AssignTarget) = private fun isSimpleTarget(target: AssignTarget) =
if (target.identifier!=null || target.memoryAddress!=null) if (target.identifier!=null || target.memoryAddress!=null)
target.isInRegularRAMof(compTarget.machine) !target.isIOAddress(compTarget.machine)
else else
false false

View File

@ -12,7 +12,7 @@ import prog8.ast.walk.IAstModification
import prog8.compilerinterface.CallGraph import prog8.compilerinterface.CallGraph
import prog8.compilerinterface.ICompilationTarget import prog8.compilerinterface.ICompilationTarget
import prog8.compilerinterface.IErrorReporter import prog8.compilerinterface.IErrorReporter
import prog8.compilerinterface.isInRegularRAMof import prog8.compilerinterface.isIOAddress
class UnusedCodeRemover(private val program: Program, class UnusedCodeRemover(private val program: Program,
@ -121,7 +121,7 @@ class UnusedCodeRemover(private val program: Program,
it.parent.parent as AssignTarget it.parent.parent as AssignTarget
else null else null
}.filter { }.filter {
it.isInRegularRAMof(compTarget.machine) !it.isIOAddress(compTarget.machine)
} }
if(assignTargets.size==usages.size) { if(assignTargets.size==usages.size) {
errors.warn("removing unused variable '${decl.name}'", decl.position) errors.warn("removing unused variable '${decl.name}'", decl.position)
@ -147,7 +147,7 @@ class UnusedCodeRemover(private val program: Program,
val assign1 = stmtPairs[0] as? Assignment val assign1 = stmtPairs[0] as? Assignment
val assign2 = stmtPairs[1] as? Assignment val assign2 = stmtPairs[1] as? Assignment
if (assign1 != null && assign2 != null && !assign2.isAugmentable) { if (assign1 != null && assign2 != null && !assign2.isAugmentable) {
if (assign1.target.isSameAs(assign2.target, program) && assign1.target.isInRegularRAMof(compTarget.machine)) { if (assign1.target.isSameAs(assign2.target, program) && !assign1.target.isIOAddress(compTarget.machine)) {
if(assign2.target.identifier==null || !assign2.value.referencesIdentifier(*(assign2.target.identifier!!.nameInSource.toTypedArray()))) if(assign2.target.identifier==null || !assign2.value.referencesIdentifier(*(assign2.target.identifier!!.nameInSource.toTypedArray())))
// only remove the second assignment if its value is a simple expression! // only remove the second assignment if its value is a simple expression!
when(assign2.value) { when(assign2.value) {

View File

@ -32,7 +32,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
// But it can only be done if the target variable IS NOT OCCURRING AS AN OPERAND ITSELF. // But it can only be done if the target variable IS NOT OCCURRING AS AN OPERAND ITSELF.
if(!assignment.isAugmentable if(!assignment.isAugmentable
&& assignment.target.identifier != null && assignment.target.identifier != null
&& assignment.target.isInRegularRAMof(options.compTarget.machine)) { && !assignment.target.isIOAddress(options.compTarget.machine)) {
val binExpr = assignment.value as? BinaryExpression val binExpr = assignment.value as? BinaryExpression
if(binExpr!=null && binExpr.inferType(program).istype(DataType.FLOAT) && !options.optimizeFloatExpressions) if(binExpr!=null && binExpr.inferType(program).istype(DataType.FLOAT) && !options.optimizeFloatExpressions)

View File

@ -12,8 +12,9 @@ import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.expressions.PrefixExpression import prog8.ast.expressions.PrefixExpression
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.compiler.printAst
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target
import prog8.compilerinterface.isInRegularRAMof import prog8.compilerinterface.isIOAddress
import prog8.parser.SourceCode import prog8.parser.SourceCode
import prog8tests.helpers.DummyFunctions import prog8tests.helpers.DummyFunctions
import prog8tests.helpers.DummyMemsizer import prog8tests.helpers.DummyMemsizer
@ -22,80 +23,132 @@ import prog8tests.helpers.DummyStringEncoder
class TestMemory: FunSpec({ class TestMemory: FunSpec({
test("testInValidRamC64_memory_addresses") { fun wrapWithProgram(statements: List<Statement>): Program {
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
val subroutine = Subroutine("test", mutableListOf(), emptyList(), statements.toMutableList(), false, Position.DUMMY)
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
program.addModule(module)
return program
}
var memexpr = NumericLiteralValue.optimalInteger(0x0000, Position.DUMMY) test("assignment target not in mapped IO space C64") {
var memexpr = NumericLiteralValue.optimalInteger(0x0002, Position.DUMMY)
var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
target.isInRegularRAMof(C64Target.machine) shouldBe true var assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe false
memexpr = NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY) memexpr = NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
target.isInRegularRAMof(C64Target.machine) shouldBe true assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe false
memexpr = NumericLiteralValue.optimalInteger(0x9fff, Position.DUMMY) memexpr = NumericLiteralValue.optimalInteger(0x9fff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
target.isInRegularRAMof(C64Target.machine) shouldBe true assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe false
memexpr = NumericLiteralValue.optimalInteger(0xa000, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe false
memexpr = NumericLiteralValue.optimalInteger(0xc000, Position.DUMMY) memexpr = NumericLiteralValue.optimalInteger(0xc000, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
target.isInRegularRAMof(C64Target.machine) shouldBe true assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe false
memexpr = NumericLiteralValue.optimalInteger(0xcfff, Position.DUMMY) memexpr = NumericLiteralValue.optimalInteger(0xcfff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
target.isInRegularRAMof(C64Target.machine) shouldBe true assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
} wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe false
test("testNotInValidRamC64_memory_addresses") { memexpr = NumericLiteralValue.optimalInteger(0xeeee, Position.DUMMY)
var memexpr = NumericLiteralValue.optimalInteger(0xa000, Position.DUMMY)
var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
target.isInRegularRAMof(C64Target.machine) shouldBe false
memexpr = NumericLiteralValue.optimalInteger(0xafff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
target.isInRegularRAMof(C64Target.machine) shouldBe false assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
memexpr = NumericLiteralValue.optimalInteger(0xd000, Position.DUMMY) target.isIOAddress(C64Target.machine) shouldBe false
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
target.isInRegularRAMof(C64Target.machine) shouldBe false
memexpr = NumericLiteralValue.optimalInteger(0xffff, Position.DUMMY) memexpr = NumericLiteralValue.optimalInteger(0xffff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
target.isInRegularRAMof(C64Target.machine) shouldBe false assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe false
} }
fun createTestProgramForMemoryRefViaVar(program: Program, address: Int, vartype: VarDeclType): AssignTarget { test("assign target in mapped IO space C64") {
var memexpr = NumericLiteralValue.optimalInteger(0x0000, Position.DUMMY)
var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
var assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe true
memexpr = NumericLiteralValue.optimalInteger(0x0001, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe true
memexpr = NumericLiteralValue.optimalInteger(0xd000, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe true
memexpr = NumericLiteralValue.optimalInteger(0xdfff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe true
}
fun createTestProgramForMemoryRefViaVar(address: Int, vartype: VarDeclType): AssignTarget {
val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY)
val memexpr = IdentifierReference(listOf("address"), Position.DUMMY) val memexpr = IdentifierReference(listOf("address"), Position.DUMMY)
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) wrapWithProgram(listOf(decl, assignment))
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
module.linkIntoProgram(program)
return target return target
} }
test("testInValidRamC64_memory_identifiers") {
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
var target = createTestProgramForMemoryRefViaVar(program, 0x1000, VarDeclType.VAR)
target.isInRegularRAMof(C64Target.machine) shouldBe true test("identifier mapped to IO memory on C64") {
target = createTestProgramForMemoryRefViaVar(program, 0xd020, VarDeclType.VAR) var target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.VAR)
target.isInRegularRAMof(C64Target.machine) shouldBe false target.isIOAddress(C64Target.machine) shouldBe false
target = createTestProgramForMemoryRefViaVar(program, 0x1000, VarDeclType.CONST) target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.VAR)
target.isInRegularRAMof(C64Target.machine) shouldBe true target.isIOAddress(C64Target.machine) shouldBe false
target = createTestProgramForMemoryRefViaVar(program, 0xd020, VarDeclType.CONST) target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.CONST)
target.isInRegularRAMof(C64Target.machine) shouldBe false target.isIOAddress(C64Target.machine) shouldBe false
target = createTestProgramForMemoryRefViaVar(program, 0x1000, VarDeclType.MEMORY) target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.CONST)
target.isInRegularRAMof(C64Target.machine) shouldBe false target.isIOAddress(C64Target.machine) shouldBe true
target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.MEMORY)
target.isIOAddress(C64Target.machine) shouldBe false
target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.MEMORY)
target.isIOAddress(C64Target.machine) shouldBe true
} }
test("testInValidRamC64_memory_expression") { test("memory expression mapped to IO memory on C64\"") {
val memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY), Position.DUMMY) var memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY), Position.DUMMY)
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
target.isInRegularRAMof(C64Target.machine) shouldBe false var assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
target.isIOAddress(C64Target.machine) shouldBe false
memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0xd020, Position.DUMMY), Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
printAst(target.definingModule.program)
target.isIOAddress(C64Target.machine) shouldBe true
} }
test("testInValidRamC64_variable") { test("regular variable not in mapped IO ram on C64") {
val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY) val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY)
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
@ -103,11 +156,10 @@ class TestMemory: FunSpec({
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
.addModule(module) .addModule(module)
module.linkIntoProgram(program) target.isIOAddress(C64Target.machine) shouldBe false
target.isInRegularRAMof(C64Target.machine) shouldBe true
} }
test("testInValidRamC64_memmap_variable") { test("memory mapped variable not in mapped IO ram on C64") {
val address = 0x1000 val address = 0x1000
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY)
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
@ -116,11 +168,10 @@ class TestMemory: FunSpec({
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
.addModule(module) .addModule(module)
module.linkIntoProgram(program) target.isIOAddress(C64Target.machine) shouldBe false
target.isInRegularRAMof(C64Target.machine) shouldBe true
} }
test("testNotInValidRamC64_memmap_variable") { test("memory mapped variable in mapped IO ram on C64") {
val address = 0xd020 val address = 0xd020
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY)
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
@ -129,11 +180,10 @@ class TestMemory: FunSpec({
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
.addModule(module) .addModule(module)
module.linkIntoProgram(program) target.isIOAddress(C64Target.machine) shouldBe true
target.isInRegularRAMof(C64Target.machine) shouldBe false
} }
test("testInValidRamC64_array") { test("array not in mapped IO ram") {
val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY) val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY)
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
@ -142,11 +192,10 @@ class TestMemory: FunSpec({
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
.addModule(module) .addModule(module)
module.linkIntoProgram(program) target.isIOAddress(C64Target.machine) shouldBe false
target.isInRegularRAMof(C64Target.machine) shouldBe true
} }
test("testInValidRamC64_array_memmapped") { test("memory mapped array not in mapped IO ram") {
val address = 0x1000 val address = 0x1000
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY)
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
@ -156,12 +205,11 @@ class TestMemory: FunSpec({
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
.addModule(module) .addModule(module)
module.linkIntoProgram(program) target.isIOAddress(C64Target.machine) shouldBe false
target.isInRegularRAMof(C64Target.machine) shouldBe true
} }
test("testNotValidRamC64_array_memmapped") { test("memory mapped array in mapped IO ram") {
val address = 0xe000 val address = 0xd800
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY)
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
@ -170,7 +218,6 @@ class TestMemory: FunSpec({
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
.addModule(module) .addModule(module)
module.linkIntoProgram(program) target.isIOAddress(C64Target.machine) shouldBe true
target.isInRegularRAMof(C64Target.machine) shouldBe false
} }
}) })

View File

@ -290,11 +290,6 @@ open class Module(final override var statements: MutableList<Statement>,
statements.forEach {it.linkParents(this)} statements.forEach {it.linkParents(this)}
} }
fun linkIntoProgram(program: Program) {
this.program = program
linkParents(program.namespace)
}
override val definingScope: INameScope override val definingScope: INameScope
get() = program.namespace get() = program.namespace
override fun replaceChildNode(node: Node, replacement: Node) { override fun replaceChildNode(node: Node, replacement: Node) {

View File

@ -41,7 +41,8 @@ class Program(val name: String,
require(null == _modules.firstOrNull { it.name == module.name }) require(null == _modules.firstOrNull { it.name == module.name })
{ "module '${module.name}' already present" } { "module '${module.name}' already present" }
_modules.add(module) _modules.add(module)
module.linkIntoProgram(this) module.program = this
module.linkParents(namespace)
return this return this
} }

View File

@ -94,7 +94,26 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid
} }
override fun copy() = PrefixExpression(operator, expression.copy(), position) override fun copy() = PrefixExpression(operator, expression.copy(), position)
override fun constValue(program: Program): NumericLiteralValue? = null override fun constValue(program: Program): NumericLiteralValue? {
val constval = expression.constValue(program) ?: return null
return when(operator) {
"+" -> constval
"-" -> when (constval.type) {
in IntegerDatatypes -> NumericLiteralValue.optimalInteger(-constval.number.toInt(), constval.position)
DataType.FLOAT -> NumericLiteralValue(DataType.FLOAT, -constval.number, constval.position)
else -> throw ExpressionError("can only take negative of int or float", constval.position)
}
"~" -> when (constval.type) {
DataType.BYTE -> NumericLiteralValue(DataType.BYTE, constval.number.toInt().inv().toDouble(), constval.position)
DataType.UBYTE -> NumericLiteralValue(DataType.UBYTE, (constval.number.toInt().inv() and 255).toDouble(), constval.position)
DataType.WORD -> NumericLiteralValue(DataType.WORD, constval.number.toInt().inv().toDouble(), constval.position)
DataType.UWORD -> NumericLiteralValue(DataType.UWORD, (constval.number.toInt().inv() and 65535).toDouble(), constval.position)
else -> throw ExpressionError("can only take bitwise inversion of int", constval.position)
}
"not" -> NumericLiteralValue.fromBoolean(constval.number == 0.0, constval.position)
else -> throw FatalAstException("invalid operator")
}
}
override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)

View File

@ -8,47 +8,45 @@ import prog8.ast.expressions.RangeExpr
import prog8.ast.statements.AssignTarget import prog8.ast.statements.AssignTarget
import kotlin.math.abs import kotlin.math.abs
fun AssignTarget.isInRegularRAMof(machine: IMachineDefinition): Boolean { fun AssignTarget.isIOAddress(machine: IMachineDefinition): Boolean {
val memAddr = memoryAddress val memAddr = memoryAddress
val arrayIdx = arrayindexed val arrayIdx = arrayindexed
val ident = identifier val ident = identifier
when { when {
memAddr != null -> { memAddr != null -> {
val addr = memAddr.addressExpression.constValue(definingModule.program)
if(addr!=null)
return machine.isIOAddress(addr.number.toInt())
return when (memAddr.addressExpression) { return when (memAddr.addressExpression) {
is NumericLiteralValue -> {
machine.isRegularRAMaddress((memAddr.addressExpression as NumericLiteralValue).number.toInt())
}
is IdentifierReference -> { is IdentifierReference -> {
val program = definingModule.program val decl = (memAddr.addressExpression as IdentifierReference).targetVarDecl(definingModule.program)
val decl = (memAddr.addressExpression as IdentifierReference).targetVarDecl(program) val result = if ((decl?.type == VarDeclType.MEMORY || decl?.type == VarDeclType.CONST) && decl.value is NumericLiteralValue)
if ((decl?.type == VarDeclType.VAR || decl?.type == VarDeclType.CONST) && decl.value is NumericLiteralValue) machine.isIOAddress((decl.value as NumericLiteralValue).number.toInt())
machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt())
else else
false false
result
} }
else -> false else -> false
} }
} }
arrayIdx != null -> { arrayIdx != null -> {
val program = definingModule.program val targetStmt = arrayIdx.arrayvar.targetVarDecl(definingModule.program)
val targetStmt = arrayIdx.arrayvar.targetVarDecl(program)
return if (targetStmt?.type == VarDeclType.MEMORY) { return if (targetStmt?.type == VarDeclType.MEMORY) {
val addr = targetStmt.value as? NumericLiteralValue val addr = targetStmt.value as? NumericLiteralValue
if (addr != null) if (addr != null)
machine.isRegularRAMaddress(addr.number.toInt()) machine.isIOAddress(addr.number.toInt())
else else
false false
} else true } else false
} }
ident != null -> { ident != null -> {
val program = definingModule.program val decl = ident.targetVarDecl(definingModule.program) ?: throw FatalAstException("invalid identifier ${ident.nameInSource}")
val decl = ident.targetVarDecl(program) ?: throw FatalAstException("invalid identifier ${ident.nameInSource}")
return if (decl.type == VarDeclType.MEMORY && decl.value is NumericLiteralValue) return if (decl.type == VarDeclType.MEMORY && decl.value is NumericLiteralValue)
machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt()) machine.isIOAddress((decl.value as NumericLiteralValue).number.toInt())
else else
true false
} }
else -> return true else -> return false
} }
} }

View File

@ -32,5 +32,5 @@ interface IMachineDefinition {
fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String>
fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path) fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path)
fun isRegularRAMaddress(address: Int): Boolean fun isIOAddress(address: Int): Boolean
} }

View File

@ -23,7 +23,7 @@ Future
- use UByte instead of Short - use UByte instead of Short
- simplifyConditionalExpression() should not split expression if it still results in stack-based evaluation - simplifyConditionalExpression() should not split expression if it still results in stack-based evaluation
- remove special code generation for while and util expression - remove special code generation for while and util expression
by rewriting while and until expressions into if+jump (consider them syntactic sugar) by rewriting while and until expressions into if+jump (just consider them syntactic sugar)
but the result should not produce larger code ofcourse! but the result should not produce larger code ofcourse!
- while-expression should now also get the simplifyConditionalExpression() treatment - while-expression should now also get the simplifyConditionalExpression() treatment
- fix the asm-labels problem (github issue #62) - fix the asm-labels problem (github issue #62)