mirror of
https://github.com/irmen/prog8.git
synced 2024-11-22 15:33:02 +00:00
refactor and fix the way memory addresses are checked to be in IO space or regular ram
This commit is contained in:
parent
4f5d36a84d
commit
b334d89715
@ -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) {
|
||||
zeropage = C64Zeropage(compilerOptions)
|
||||
|
@ -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) {
|
||||
zeropage = CX16Zeropage(compilerOptions)
|
||||
|
@ -69,7 +69,6 @@ class AsmGenSymbolsTests: StringSpec({
|
||||
val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test"))
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
.addModule(module)
|
||||
module.linkIntoProgram(program)
|
||||
return program
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.compilerinterface.CompilationOptions
|
||||
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() {
|
||||
@ -97,7 +97,7 @@ X = BinExpr X = LeftExpr
|
||||
|
||||
private fun isSimpleTarget(target: AssignTarget) =
|
||||
if (target.identifier!=null || target.memoryAddress!=null)
|
||||
target.isInRegularRAMof(compTarget.machine)
|
||||
!target.isIOAddress(compTarget.machine)
|
||||
else
|
||||
false
|
||||
|
||||
|
@ -12,7 +12,7 @@ import prog8.ast.walk.IAstModification
|
||||
import prog8.compilerinterface.CallGraph
|
||||
import prog8.compilerinterface.ICompilationTarget
|
||||
import prog8.compilerinterface.IErrorReporter
|
||||
import prog8.compilerinterface.isInRegularRAMof
|
||||
import prog8.compilerinterface.isIOAddress
|
||||
|
||||
|
||||
class UnusedCodeRemover(private val program: Program,
|
||||
@ -121,7 +121,7 @@ class UnusedCodeRemover(private val program: Program,
|
||||
it.parent.parent as AssignTarget
|
||||
else null
|
||||
}.filter {
|
||||
it.isInRegularRAMof(compTarget.machine)
|
||||
!it.isIOAddress(compTarget.machine)
|
||||
}
|
||||
if(assignTargets.size==usages.size) {
|
||||
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 assign2 = stmtPairs[1] as? Assignment
|
||||
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())))
|
||||
// only remove the second assignment if its value is a simple expression!
|
||||
when(assign2.value) {
|
||||
|
@ -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.
|
||||
if(!assignment.isAugmentable
|
||||
&& assignment.target.identifier != null
|
||||
&& assignment.target.isInRegularRAMof(options.compTarget.machine)) {
|
||||
&& !assignment.target.isIOAddress(options.compTarget.machine)) {
|
||||
val binExpr = assignment.value as? BinaryExpression
|
||||
|
||||
if(binExpr!=null && binExpr.inferType(program).istype(DataType.FLOAT) && !options.optimizeFloatExpressions)
|
||||
|
@ -12,8 +12,9 @@ import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.NumericLiteralValue
|
||||
import prog8.ast.expressions.PrefixExpression
|
||||
import prog8.ast.statements.*
|
||||
import prog8.compiler.printAst
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.compilerinterface.isInRegularRAMof
|
||||
import prog8.compilerinterface.isIOAddress
|
||||
import prog8.parser.SourceCode
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
@ -22,80 +23,132 @@ import prog8tests.helpers.DummyStringEncoder
|
||||
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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") {
|
||||
|
||||
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)
|
||||
memexpr = NumericLiteralValue.optimalInteger(0xeeee, Position.DUMMY)
|
||||
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe false
|
||||
|
||||
memexpr = NumericLiteralValue.optimalInteger(0xd000, 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
|
||||
|
||||
memexpr = NumericLiteralValue.optimalInteger(0xffff, 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 memexpr = IdentifierReference(listOf("address"), 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 subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
|
||||
module.linkIntoProgram(program)
|
||||
wrapWithProgram(listOf(decl, assignment))
|
||||
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
|
||||
target = createTestProgramForMemoryRefViaVar(program, 0xd020, VarDeclType.VAR)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe false
|
||||
target = createTestProgramForMemoryRefViaVar(program, 0x1000, VarDeclType.CONST)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe true
|
||||
target = createTestProgramForMemoryRefViaVar(program, 0xd020, VarDeclType.CONST)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe false
|
||||
target = createTestProgramForMemoryRefViaVar(program, 0x1000, VarDeclType.MEMORY)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe false
|
||||
test("identifier mapped to IO memory on C64") {
|
||||
var target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.VAR)
|
||||
target.isIOAddress(C64Target.machine) shouldBe false
|
||||
target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.VAR)
|
||||
target.isIOAddress(C64Target.machine) shouldBe false
|
||||
target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.CONST)
|
||||
target.isIOAddress(C64Target.machine) shouldBe false
|
||||
target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.CONST)
|
||||
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") {
|
||||
val memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY), Position.DUMMY)
|
||||
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe false
|
||||
test("memory expression mapped to IO memory on C64\"") {
|
||||
var memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY), 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 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 target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, 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 program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
.addModule(module)
|
||||
module.linkIntoProgram(program)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe true
|
||||
target.isIOAddress(C64Target.machine) shouldBe false
|
||||
}
|
||||
|
||||
test("testInValidRamC64_memmap_variable") {
|
||||
test("memory mapped variable not in mapped IO ram on C64") {
|
||||
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 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 program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
.addModule(module)
|
||||
module.linkIntoProgram(program)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe true
|
||||
target.isIOAddress(C64Target.machine) shouldBe false
|
||||
}
|
||||
|
||||
test("testNotInValidRamC64_memmap_variable") {
|
||||
test("memory mapped variable in mapped IO ram on C64") {
|
||||
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 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 program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
.addModule(module)
|
||||
module.linkIntoProgram(program)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe false
|
||||
target.isIOAddress(C64Target.machine) shouldBe true
|
||||
}
|
||||
|
||||
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 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)
|
||||
@ -142,11 +192,10 @@ class TestMemory: FunSpec({
|
||||
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
.addModule(module)
|
||||
module.linkIntoProgram(program)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe true
|
||||
target.isIOAddress(C64Target.machine) shouldBe false
|
||||
}
|
||||
|
||||
test("testInValidRamC64_array_memmapped") {
|
||||
test("memory mapped array not in mapped IO ram") {
|
||||
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 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 program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
.addModule(module)
|
||||
module.linkIntoProgram(program)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe true
|
||||
target.isIOAddress(C64Target.machine) shouldBe false
|
||||
}
|
||||
|
||||
test("testNotValidRamC64_array_memmapped") {
|
||||
val address = 0xe000
|
||||
test("memory mapped array in mapped IO ram") {
|
||||
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 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)
|
||||
@ -170,7 +218,6 @@ class TestMemory: FunSpec({
|
||||
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
.addModule(module)
|
||||
module.linkIntoProgram(program)
|
||||
target.isInRegularRAMof(C64Target.machine) shouldBe false
|
||||
target.isIOAddress(C64Target.machine) shouldBe true
|
||||
}
|
||||
})
|
||||
|
@ -290,11 +290,6 @@ open class Module(final override var statements: MutableList<Statement>,
|
||||
statements.forEach {it.linkParents(this)}
|
||||
}
|
||||
|
||||
fun linkIntoProgram(program: Program) {
|
||||
this.program = program
|
||||
linkParents(program.namespace)
|
||||
}
|
||||
|
||||
override val definingScope: INameScope
|
||||
get() = program.namespace
|
||||
override fun replaceChildNode(node: Node, replacement: Node) {
|
||||
|
@ -41,7 +41,8 @@ class Program(val name: String,
|
||||
require(null == _modules.firstOrNull { it.name == module.name })
|
||||
{ "module '${module.name}' already present" }
|
||||
_modules.add(module)
|
||||
module.linkIntoProgram(this)
|
||||
module.program = this
|
||||
module.linkParents(namespace)
|
||||
return this
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,26 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid
|
||||
}
|
||||
|
||||
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: AstWalker, parent: Node)= visitor.visit(this, parent)
|
||||
|
||||
|
@ -8,47 +8,45 @@ import prog8.ast.expressions.RangeExpr
|
||||
import prog8.ast.statements.AssignTarget
|
||||
import kotlin.math.abs
|
||||
|
||||
fun AssignTarget.isInRegularRAMof(machine: IMachineDefinition): Boolean {
|
||||
fun AssignTarget.isIOAddress(machine: IMachineDefinition): Boolean {
|
||||
val memAddr = memoryAddress
|
||||
val arrayIdx = arrayindexed
|
||||
val ident = identifier
|
||||
when {
|
||||
memAddr != null -> {
|
||||
val addr = memAddr.addressExpression.constValue(definingModule.program)
|
||||
if(addr!=null)
|
||||
return machine.isIOAddress(addr.number.toInt())
|
||||
return when (memAddr.addressExpression) {
|
||||
is NumericLiteralValue -> {
|
||||
machine.isRegularRAMaddress((memAddr.addressExpression as NumericLiteralValue).number.toInt())
|
||||
}
|
||||
is IdentifierReference -> {
|
||||
val program = definingModule.program
|
||||
val decl = (memAddr.addressExpression as IdentifierReference).targetVarDecl(program)
|
||||
if ((decl?.type == VarDeclType.VAR || decl?.type == VarDeclType.CONST) && decl.value is NumericLiteralValue)
|
||||
machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt())
|
||||
val decl = (memAddr.addressExpression as IdentifierReference).targetVarDecl(definingModule.program)
|
||||
val result = if ((decl?.type == VarDeclType.MEMORY || decl?.type == VarDeclType.CONST) && decl.value is NumericLiteralValue)
|
||||
machine.isIOAddress((decl.value as NumericLiteralValue).number.toInt())
|
||||
else
|
||||
false
|
||||
result
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
arrayIdx != null -> {
|
||||
val program = definingModule.program
|
||||
val targetStmt = arrayIdx.arrayvar.targetVarDecl(program)
|
||||
val targetStmt = arrayIdx.arrayvar.targetVarDecl(definingModule.program)
|
||||
return if (targetStmt?.type == VarDeclType.MEMORY) {
|
||||
val addr = targetStmt.value as? NumericLiteralValue
|
||||
if (addr != null)
|
||||
machine.isRegularRAMaddress(addr.number.toInt())
|
||||
machine.isIOAddress(addr.number.toInt())
|
||||
else
|
||||
false
|
||||
} else true
|
||||
} else false
|
||||
}
|
||||
ident != null -> {
|
||||
val program = definingModule.program
|
||||
val decl = ident.targetVarDecl(program) ?: throw FatalAstException("invalid identifier ${ident.nameInSource}")
|
||||
val decl = ident.targetVarDecl(definingModule.program) ?: throw FatalAstException("invalid identifier ${ident.nameInSource}")
|
||||
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
|
||||
true
|
||||
false
|
||||
}
|
||||
else -> return true
|
||||
else -> return false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,5 +32,5 @@ interface IMachineDefinition {
|
||||
|
||||
fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String>
|
||||
fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path)
|
||||
fun isRegularRAMaddress(address: Int): Boolean
|
||||
fun isIOAddress(address: Int): Boolean
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ Future
|
||||
- use UByte instead of Short
|
||||
- simplifyConditionalExpression() should not split expression if it still results in stack-based evaluation
|
||||
- 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!
|
||||
- while-expression should now also get the simplifyConditionalExpression() treatment
|
||||
- fix the asm-labels problem (github issue #62)
|
||||
|
Loading…
Reference in New Issue
Block a user