diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 08766012a..5136f9e9e 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -102,7 +102,7 @@ import prog8.codegen.cpu6502.assignment.* "popw" -> funcPopW(firstReturnRegister ?: RegisterOrPair.AY) "popl" -> funcPopL() "popf" -> funcPopF() - else -> throw AssemblyError("missing asmgen for builtin func ${fcall.name}") + else -> throw AssemblyError("sizeof must have been replaced with a constant ${fcall.position}") } } diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index 4aab12dfa..0c99027fe 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -71,9 +71,9 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe "popw" -> funcPopW() "popl" -> funcPopL() "popf" -> funcPopF() - "sizeof" -> throw AssemblyError("sizeof must have been replaced with a constant") - "offsetof" -> throw AssemblyError("offsetof must have been replaced with a constant") - else -> throw AssemblyError("missing builtinfunc for ${call.name}") + "sizeof" -> throw AssemblyError("sizeof must have been replaced with a constant ${call.position}") + "offsetof" -> throw AssemblyError("offsetof must have been replaced with a constant ${call.position}") + else -> throw AssemblyError("missing builtinfunc for ${call.name} ${call.position}") } } diff --git a/codeOptimizers/src/prog8/optimizer/ConstantFoldingOptimizer.kt b/codeOptimizers/src/prog8/optimizer/ConstantFoldingOptimizer.kt index 181135840..57a71e2ca 100644 --- a/codeOptimizers/src/prog8/optimizer/ConstantFoldingOptimizer.kt +++ b/codeOptimizers/src/prog8/optimizer/ConstantFoldingOptimizer.kt @@ -534,6 +534,13 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors: } override fun after(decl: VarDecl, parent: Node): Iterable { + if (decl.type == VarDeclType.CONST && decl.datatype.isPointer) { + val sizer = program.memsizer + if (decl.datatype.size(sizer) > 1) { + errors.err("pointer variables with data type size > 1 cannot be const", decl.position) + } + } + val numval = decl.value as? NumericLiteral if(decl.type== VarDeclType.CONST && numval!=null) { val valueDt = numval.inferType(program) diff --git a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt index 30e52a92f..a76140147 100644 --- a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt +++ b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt @@ -26,6 +26,7 @@ class VarConstantValueTypeAdjuster( val cv = expr.constValue(program) if (cv != null) return cv if (expr is MemorySlabRef) return expr + if (expr is IFunctionCall && expr.isMemoryCall) return expr return null } @@ -92,7 +93,7 @@ class VarConstantValueTypeAdjuster( } } val declValue = if (decl.value != null) getConstantInitializer(decl.value!!) else null - if (declValue != null) { + if (declValue != null && canBeMadeConst(decl)) { // variable is never written to, so it can be replaced with a constant, IF the value is a constant errors.info("variable '${decl.name}' is never written to and was made const", decl.position) val const = VarDecl.builder(decl.datatype, decl.position) @@ -107,7 +108,7 @@ class VarConstantValueTypeAdjuster( } } } else { - if (singleAssignment.origin == AssignmentOrigin.VARINIT && isConstantInitializer(singleAssignment.value)) { + if (singleAssignment.origin == AssignmentOrigin.VARINIT && isConstantInitializer(singleAssignment.value) && canBeMadeConst(decl)) { if(reads.isEmpty()) { if(decl.names.size>1) { errors.info("unused variable '${decl.name}'", decl.position) @@ -140,6 +141,9 @@ class VarConstantValueTypeAdjuster( return noModifications } + private fun canBeMadeConst(decl: VarDecl): Boolean = + if (decl.datatype.isPointer) decl.datatype.size(program.memsizer) <= 1 else true + override fun after(range: RangeExpression, parent: Node): Iterable { val from = range.from.constValue(program)?.number val to = range.to.constValue(program)?.number diff --git a/compiler/test/TestPointerArithmeticScaling.kt b/compiler/test/TestPointerArithmeticScaling.kt index 32dd4bdfa..256003336 100644 --- a/compiler/test/TestPointerArithmeticScaling.kt +++ b/compiler/test/TestPointerArithmeticScaling.kt @@ -33,69 +33,6 @@ class TestPointerArithmeticScaling : FunSpec({ (assignments[2].value as NumericLiteral).number.toInt() shouldBe 0x100a } - test("const pointer arithmetic scaling - uword (scale 2)") { - val src = $$""" - %option no_sysinit - main { - const ^^uword p = $1000 - sub start() { - cx16.r0 = p + 5 ; should be $1000 + 5*2 = $100a - cx16.r1 = p - 2 ; should be $1000 - 2*2 = $0ffc - cx16.r2 = &p[10] ; should be $1000 + 10*2 = $1014 - } - } - """.trimIndent() - val result = compileText(Cx16Target(), true, src, outputDir)!! - val startSub = result.compilerAst.entrypoint - val assignments = startSub.statements.filterIsInstance() - - (assignments[0].value as NumericLiteral).number.toInt() shouldBe 0x100a - (assignments[1].value as NumericLiteral).number.toInt() shouldBe 0x0ffc - (assignments[2].value as NumericLiteral).number.toInt() shouldBe 0x1014 - } - - test("const pointer arithmetic scaling - long (scale 4)") { - val src = $$""" - %option no_sysinit - main { - const ^^long p = $1000 - sub start() { - cx16.r0 = p + 5 ; should be $1000 + 5*4 = $1014 - cx16.r1 = p - 2 ; should be $1000 - 2*4 = $0ff8 - cx16.r2 = &p[10] ; should be $1000 + 10*4 = $1028 - } - } - """.trimIndent() - val result = compileText(Cx16Target(), true, src, outputDir)!! - val startSub = result.compilerAst.entrypoint - val assignments = startSub.statements.filterIsInstance() - - (assignments[0].value as NumericLiteral).number.toInt() shouldBe 0x1014 - (assignments[1].value as NumericLiteral).number.toInt() shouldBe 0x0ff8 - (assignments[2].value as NumericLiteral).number.toInt() shouldBe 0x1028 - } - - test("const pointer arithmetic scaling - float (scale 5)") { - val src = $$""" - %option no_sysinit - main { - const ^^float p = $1000 - sub start() { - cx16.r0 = p + 3 ; should be $1000 + 3*5 = $100f - cx16.r1 = p - 1 ; should be $1000 - 1*5 = $0ffb - cx16.r2 = &p[3] ; should be $1000 + 3*5 = $100f - } - } - """.trimIndent() - val result = compileText(Cx16Target(), true, src, outputDir)!! - val startSub = result.compilerAst.entrypoint - val assignments = startSub.statements.filterIsInstance() - - (assignments[0].value as NumericLiteral).number.toInt() shouldBe 0x100f - (assignments[1].value as NumericLiteral).number.toInt() shouldBe 0x0ffb - (assignments[2].value as NumericLiteral).number.toInt() shouldBe 0x100f - } - test("non-const pointer arithmetic scaling - ubyte (scale 1)") { val src = $$""" %option no_sysinit diff --git a/compiler/test/TestPointerFolding.kt b/compiler/test/TestPointerFolding.kt deleted file mode 100644 index c69804ae4..000000000 --- a/compiler/test/TestPointerFolding.kt +++ /dev/null @@ -1,216 +0,0 @@ -package prog8tests.compiler - -import io.kotest.assertions.withClue -import io.kotest.core.spec.style.FunSpec -import io.kotest.engine.spec.tempdir -import io.kotest.matchers.shouldBe -import io.kotest.matchers.shouldNotBe -import io.kotest.matchers.types.instanceOf -import prog8.ast.IFunctionCall -import prog8.ast.Node -import prog8.ast.expressions.DirectMemoryRead -import prog8.ast.expressions.Expression -import prog8.ast.expressions.FunctionCallExpression -import prog8.ast.expressions.NumericLiteral -import prog8.ast.statements.FunctionCallStatement -import prog8.ast.statements.VarDecl -import prog8.ast.statements.VarDeclType -import prog8.ast.walk.AstModification -import prog8.ast.walk.AstWalker -import prog8.code.target.VMTarget -import prog8tests.helpers.ErrorReporterForTests -import prog8tests.helpers.compileText - -class TestPointerFolding : FunSpec({ - val outputDir = tempdir().toPath() - - test("pointer arithmetic constant folding") { - val src = """ - %import textio - main { - const ^^uword bptr = ${'$'}2000 - const ^^ubyte byteptr = ${'$'}2000 - const ^^float fptr = ${'$'}4000 - const ^^long lptr = ${'$'}3000 - - sub start() { - uword p1 - uword p2 - uword p3 - uword p4 - uword p5 - uword p6 - uword p7 - uword b1 - ubyte b2 - p1 = bptr - p2 = bptr + 4 - p3 = bptr - 2 - p4 = 10 + byteptr - p5 = fptr + 2 - p6 = lptr + 1 - p7 = byteptr + sizeof(float) - b1 = bptr[${'$'}1000] - b2 = byteptr[${'$'}1000] - - txt.print_uw(p1) - txt.print_uw(p2) - txt.print_uw(p3) - txt.print_uw(p4) - txt.print_uw(p5) - txt.print_uw(p6) - txt.print_uw(p7) - txt.print_uw(b1) - txt.print_ub(b2) - } - } - """.trimIndent() - - val errors = ErrorReporterForTests() - val result = compileText(VMTarget(), true, src, outputDir, errors = errors) - withClue("Compiler errors: " + errors.errors.joinToString("\n")) { - result shouldNotBe null - } - val program = result!!.compilerAst - - val allCalls = mutableListOf() - val allDirectReads = mutableListOf() - val walker = object: AstWalker() { - override fun after(functionCallExpr: FunctionCallExpression, parent: Node): Iterable { - allCalls.add(functionCallExpr) - return noModifications - } - override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable { - allCalls.add(functionCallStatement) - return noModifications - } - override fun after(memread: DirectMemoryRead, parent: Node): Iterable { - allDirectReads.add(memread) - return noModifications - } - } - walker.visit(program) - - fun findPrintArgument(index: Int): Expression { - val calls = allCalls.filter { it.target.nameInSource.last() == "print_uw" || it.target.nameInSource.last() == "print_ub" } - return calls[index].args[0] - } - - // p1 = bptr -> folded to $2000 (8192) - val p1Value = findPrintArgument(0) - p1Value shouldBe instanceOf() - (p1Value as NumericLiteral).number shouldBe 8192.0 - - // p2 = bptr + 4 -> folded to $2000 + 4*2 = $2008 (8200) - val p2Value = findPrintArgument(1) - p2Value shouldBe instanceOf() - (p2Value as NumericLiteral).number shouldBe 8200.0 - - // p3 = bptr - 2 -> folded to $2000 - 2*2 = $1ffc (8188) - val p3Value = findPrintArgument(2) - p3Value shouldBe instanceOf() - (p3Value as NumericLiteral).number shouldBe 8188.0 - - // p4 = 10 + byteptr -> folded to $2000 + 10*1 = $200a (8202) - val p4Value = findPrintArgument(3) - p4Value shouldBe instanceOf() - (p4Value as NumericLiteral).number shouldBe 8202.0 - - // p5 = fptr + 2 -> folded to $4000 + 2*8 = $4010 (16400) on VMTarget - val p5Value = findPrintArgument(4) - p5Value shouldBe instanceOf() - (p5Value as NumericLiteral).number shouldBe 16400.0 - - // p6 = lptr + 1 -> folded to $3000 + 1*4 = $3004 (12292) - val p6Value = findPrintArgument(5) - p6Value shouldBe instanceOf() - (p6Value as NumericLiteral).number shouldBe 12292.0 - - // p7 = byteptr + sizeof(float) -> folded to $2000 + 8 = $2008 (8200) - val p7Value = findPrintArgument(6) - p7Value shouldBe instanceOf() - (p7Value as NumericLiteral).number shouldBe 8200.0 - - // b1 = bptr[$1000] -> folded to peekw at $2000 + $1000*2 = $4000 (16384) - val b1Call = allCalls.find { it.target.nameInSource.last() == "peekw" } - b1Call shouldNotBe null - val b1Addr = b1Call!!.args[0] - b1Addr shouldBe instanceOf() - (b1Addr as NumericLiteral).number shouldBe 16384.0 - - // b2 = byteptr[$1000] -> folded to DirectMemoryRead(peek) at $2000 + $1000*1 = $3000 (12288) - val b2Read = allDirectReads.firstOrNull() - b2Read shouldNotBe null - val b2Addr = b2Read!!.addressExpression - b2Addr shouldBe instanceOf() - (b2Addr as NumericLiteral).number shouldBe 12288.0 - } - - test("automatic conversion of non-const pointer to const") { - val src = """ - %import textio - %import floats - main { - ^^ubyte modulePtr = ${'$'}1000 - - sub start() { - ^^uword localPtr1 = ${'$'}2000 - ^^float localPtr2 - localPtr2 = ${'$'}3000 - - txt.print_ub(modulePtr[0]) - txt.print_uw(localPtr1[0]) - txt.print_f(localPtr2[0]) - - ; subsequent pointer arithmetic on converted constants should also be folded - uword p_math = localPtr1 + 5 - txt.print_uw(p_math) - } - } - """.trimIndent() - - val errors = ErrorReporterForTests() - val result = compileText(VMTarget(), true, src, tempdir().toPath(), errors = errors) - withClue("Compiler errors: " + errors.errors.joinToString("\n")) { - result shouldNotBe null - } - val program = result!!.compilerAst - - val varDecls = mutableListOf() - val allCalls = mutableListOf() - val walker = object: AstWalker() { - override fun after(decl: VarDecl, parent: Node): Iterable { - varDecls.add(decl) - return noModifications - } - override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable { - allCalls.add(functionCallStatement) - return noModifications - } - } - walker.visit(program) - - val mPtr = varDecls.find { it.name == "modulePtr" }!! - mPtr.type shouldBe VarDeclType.CONST - - val lPtr1 = varDecls.find { it.name == "localPtr1" }!! - lPtr1.type shouldBe VarDeclType.CONST - - val lPtr2 = varDecls.find { it.name == "localPtr2" }!! - lPtr2.type shouldBe VarDeclType.CONST - - // verify pointer arithmetic folding: localPtr1 ($2000) + 5*2 = $200a (8202) - val mathCalls = allCalls.filter { it.target.nameInSource.last() == "print_uw" } - // mathCalls[0] is print_uw(localPtr1[0]) -> peekw(8192) - // mathCalls[1] is print_uw(p_math) -> print_uw(8202) - val mathArg = mathCalls[1].args[0] - mathArg shouldBe instanceOf() - (mathArg as NumericLiteral).number shouldBe 8202.0 - - // also verify that the indexing was folded to a peek with literal address - val indexingCall = mathCalls[0].args[0] as FunctionCallExpression - indexingCall.target.nameInSource.last() shouldBe "peekw" - indexingCall.args[0] shouldBe instanceOf() - (indexingCall.args[0] as NumericLiteral).number shouldBe 8192.0 - } -}) diff --git a/compiler/test/TestPointers.kt b/compiler/test/TestPointers.kt index b36883122..51d261f04 100644 --- a/compiler/test/TestPointers.kt +++ b/compiler/test/TestPointers.kt @@ -696,15 +696,12 @@ main { compileText(C64Target(), false, src, outputDir) shouldNotBe null } - test("const pointer works correctly") { + test("const ubyte pointer works correctly") { val src=""" main { sub start() { - const ^^uword cptr = 8192 const ^^ubyte cbyteptr = 53248 - ; test reading the pointers - cx16.r0 = cptr cx16.r1 = cbyteptr } }""" @@ -2529,12 +2526,12 @@ main { cx16 { %option merge - const ^^word pword4 = &cx16.r4 + const ^^byte pword4 = &cx16.r4 } player { alias sxPtr = cx16.pword4 - const ^^word zxPtr = &cx16.r6 + const ^^byte zxPtr = &cx16.r6 sub test() { sxPtr^^ = -99 ; aliased assignment @@ -2557,14 +2554,12 @@ player { val cond = ifCond.element as BinaryExpression val left = cond.left as TypecastExpression val right = cond.right as TypecastExpression - left.type shouldBe DataType.WORD - right.type shouldBe DataType.WORD - val leftpeek = left.expression as FunctionCallExpression - val rightpeek = right.expression as FunctionCallExpression - leftpeek.target.nameInSource shouldBe listOf("peekw") - rightpeek.target.nameInSource shouldBe listOf("peekw") - (leftpeek.args[0] as IdentifierReference).nameInSource shouldBe listOf("zxPtr") - (rightpeek.args[0] as IdentifierReference).nameInSource shouldBe listOf("cx16","pword4") + left.type shouldBe DataType.BYTE + right.type shouldBe DataType.BYTE + val leftpeek = left.expression as DirectMemoryRead + val rightpeek = right.expression as DirectMemoryRead + (leftpeek.addressExpression as IdentifierReference).nameInSource shouldBe listOf("zxPtr") + (rightpeek.addressExpression as IdentifierReference).nameInSource shouldBe listOf("cx16","pword4") } test("assigning field with same name should not confuse compiler") { @@ -2817,7 +2812,7 @@ main { %import textio main { const uword mp = memory("works", 100, 0) - const ^^long longs = memory("chunkoflongs", 2000, 0) + ^^long longs = memory("chunkoflongs", 2000, 0) sub start() { txt.print_uwhex(mp, true) txt.print_uwhex(longs, true) diff --git a/compiler/test/ast/TestConst.kt b/compiler/test/ast/TestConst.kt index 218e0a65b..2279c8fc6 100644 --- a/compiler/test/ast/TestConst.kt +++ b/compiler/test/ast/TestConst.kt @@ -7,8 +7,10 @@ import io.kotest.matchers.shouldNotBe import io.kotest.matchers.string.shouldContain import io.kotest.matchers.types.instanceOf import prog8.ast.expressions.* -import prog8.ast.statements.* import prog8.ast.statements.Assignment +import prog8.ast.statements.Return +import prog8.ast.statements.VarDecl +import prog8.ast.statements.VarDeclType import prog8.code.core.BaseDataType import prog8.code.core.Position import prog8.code.target.C64Target @@ -726,10 +728,10 @@ main { compileText(C64Target(), false, src, outputDir, writeAssembly = true) shouldNotBe null } - test("const pointer arithmetic folding") { + test("const pointer arithmetic folding (byte type)") { val source = """ main { - const ^^uword bptr = $2000 + const ^^ubyte bptr = $2000 sub start() { uword ptr2 = bptr + $10 cx16.r2 = ptr2 @@ -742,16 +744,14 @@ main { val value = vardecl.value value shouldNotBe null value shouldBe instanceOf() - (value as NumericLiteral).number.toInt() shouldBe 0x2020 // Scaled: $2000 + $10*2 = $2020 + (value as NumericLiteral).number.toInt() shouldBe 0x2010 } - test("const pointer indexing folding") { + test("const pointer indexing folding (byte type)") { val source = """ main { - const ^^uword bptr = $2000 const ^^ubyte byteptr = $2000 sub start() { - cx16.r0 = bptr[$1000] cx16.r1L = byteptr[$1000] } } @@ -760,17 +760,6 @@ main { val startSub = result.compilerAst.entrypoint val assignments = startSub.statements.filterIsInstance() - // cx16.r0 = bptr[$1000] -> should be peekw($4000) - val assign1 = assignments.find { (it.target.toExpression() as? IdentifierReference)?.nameInSource == listOf("cx16", "r0") }!! - var value1 = assign1.value - if (value1 is TypecastExpression) value1 = value1.expression - if (value1 is FunctionCallExpression) { - value1.target.nameInSource shouldBe listOf("peekw") - (value1.args[0] as NumericLiteral).number.toInt() shouldBe 0x4000 - } else { - ((value1 as DirectMemoryRead).addressExpression as NumericLiteral).number.toInt() shouldBe 0x4000 - } - // cx16.r1L = byteptr[$1000] -> should be peek($3000) val assign2 = assignments.find { (it.target.toExpression() as? IdentifierReference)?.nameInSource == listOf("cx16", "r1L") }!! var value2 = assign2.value @@ -783,10 +772,10 @@ main { } } - test("const pointer address-of folding") { + test("const pointer address-of folding (byte type)") { val source = """ main { - const ^^uword bptr = $2000 + const ^^ubyte bptr = $2000 sub start() { uword addr = &bptr[$1000] cx16.r2 = addr @@ -799,7 +788,7 @@ main { val value = vardecl.value value shouldNotBe null value shouldBe instanceOf() - (value as NumericLiteral).number.toInt() shouldBe 0x4000 + (value as NumericLiteral).number.toInt() shouldBe 0x3000 } }) diff --git a/compiler/test/ast/TestPointerConstPromotion.kt b/compiler/test/ast/TestPointerConstPromotion.kt new file mode 100644 index 000000000..ba28e4baa --- /dev/null +++ b/compiler/test/ast/TestPointerConstPromotion.kt @@ -0,0 +1,76 @@ +package prog8tests.ast + +import io.kotest.core.spec.style.FunSpec +import io.kotest.engine.spec.tempdir +import io.kotest.matchers.shouldBe +import io.kotest.matchers.string.shouldContain +import prog8.ast.statements.VarDecl +import prog8.ast.statements.VarDeclType +import prog8.code.target.VMTarget +import prog8tests.helpers.ErrorReporterForTests +import prog8tests.helpers.compileText + +class TestPointerConstPromotion : FunSpec({ + val outputDir = tempdir().toPath() + + test("pointer constant promotion scenarios") { + val src = """ + %zeropage basicsafe + %option no_sysinit + main { + sub start() { + ^^uword ptr1 = 4444 ; size 2 > 1, no promotion + ^^ubyte ptr2 = 5555 ; size 1, promotion + uword mem1 = memory("mem1", 10, 0) ; not a pointer, promotion + ^^uword mem1b = memory("mem2", 10, 0) ; size 2 > 1, no promotion + ^^ubyte mem3 = memory("mem3", 10, 0) ; size 1, promotion + + cx16.r0 = ptr1 + cx16.r1 = ptr2 as uword + cx16.r2 = mem1 + cx16.r3 = mem1b + cx16.r4 = mem3 as uword + } + } + """.trimIndent() + val result = compileText(VMTarget(), true, src, outputDir)!! + val mainSub = result.compilerAst.entrypoint + val decls = mainSub.statements.filterIsInstance().associateBy { it.name } + + decls["ptr1"]?.type shouldBe VarDeclType.VAR + decls["ptr2"]?.type shouldBe VarDeclType.CONST + decls["mem1"]?.type shouldBe VarDeclType.CONST + decls["mem1b"]?.type shouldBe VarDeclType.VAR + decls["mem3"]?.type shouldBe VarDeclType.CONST + } + + test("explicit const pointer to >1 byte type gives error") { + val src = """ + main { + sub start() { + const ^^uword ptr1b = 4444 + cx16.r0 = ptr1b + } + } + """.trimIndent() + val errors = ErrorReporterForTests() + compileText(VMTarget(), false, src, outputDir, errors = errors) + errors.errors.size shouldBe 1 + errors.errors[0] shouldContain "pointer variables with data type size > 1 cannot be const" + } + + test("explicit const pointer to >1 byte type (memory) gives error") { + val src = """ + main { + sub start() { + const ^^uword mem2 = memory("mem2", 10, 0) + cx16.r0 = mem2 + } + } + """.trimIndent() + val errors = ErrorReporterForTests() + compileText(VMTarget(), false, src, outputDir, errors = errors) + errors.errors.size shouldBe 1 + errors.errors[0] shouldContain "pointer variables with data type size > 1 cannot be const" + } +}) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 663679563..8161a34a7 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,6 +1,9 @@ TODO ==== +add test case that checks the same things as todo.p8 regarding const pointers + + Regressions after the latest commit: - examples/cx16/landscape.p8 is LARGER after terrain was turned into a const (see details at bottom) - examples/cx16/charfade.p8 is broken when the 'palette' pointer variable is a const (either by putting const in the source code or letting it be const-optimized) diff --git a/examples/test.p8 b/examples/test.p8 index e5af3eb5e..ec49a5e77 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -3,10 +3,21 @@ main { sub start() { - const uword mem1 = memory("mem1", 10, 0) - const uword mem2 = memory("mem2", 10, 0) - uword[2] arr = [mem1, mem2] - @(arr[0]) = 111 - @(arr[1]) = 222 + ^^uword ptr1 = 4444 ; should NOT be made const because of data type size >1 + const ^^uword ptr1b = 4444 ; should give ERROR about not able to make const because of data type size >1 + ^^ubyte ptr2 = 5555 ; should be made CONST because data type sizse == 1 + + uword mem1 = memory("mem1", 10, 0) ; should be made CONST because data type sizse == 1 + ^^uword mem1b = memory("mem2", 10, 0) ; should NOT be made const because of data type size >1 + const ^^uword mem2 = memory("mem2", 10, 0) ; should give ERROR about not able to make const because of data type size >1 + ^^ubyte mem3 = memory("mem3", 10, 0) ; should be made CONST because data type sizse == 1 + + cx16.r0 = ptr1 + cx16.r1 = ptr1b + cx16.r2 = ptr2 + cx16.r3 = mem1 + cx16.r4 = mem1b + cx16.r5 = mem2 + cx16.r6 = mem3 } }