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) {
|
override fun initializeZeropage(compilerOptions: CompilationOptions) {
|
||||||
zeropage = C64Zeropage(compilerOptions)
|
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) {
|
override fun initializeZeropage(compilerOptions: CompilationOptions) {
|
||||||
zeropage = CX16Zeropage(compilerOptions)
|
zeropage = CX16Zeropage(compilerOptions)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user