From 3b0d7ea960b60998b7e9d132248c4dc796da9f00 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 8 Nov 2023 22:04:41 +0100 Subject: [PATCH] better const-evaluation of addressOf a memory mapped variable --- .../optimizer/ConstantIdentifierReplacer.kt | 16 ++++++++++++++-- compiler/test/ast/TestVariousCompilerAst.kt | 13 +++++++++++++ .../src/prog8/ast/expressions/AstExpressions.kt | 10 +++++++++- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt index 6f1bc8f33..a1208b55d 100644 --- a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt +++ b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt @@ -251,7 +251,16 @@ internal class ConstantIdentifierReplacer(private val program: Program, private return noModifications } - if(decl.type== VarDeclType.CONST || decl.type== VarDeclType.VAR) { + if(decl.isArray && decl.type==VarDeclType.MEMORY) { + val memaddr = decl.value?.constValue(program) + if(memaddr!=null && memaddr !== decl.value) { + return listOf(IAstModification.SetExpression( + { decl.value = it }, memaddr, decl + )) + } + } + + if(decl.type==VarDeclType.CONST || decl.type==VarDeclType.VAR) { if(decl.isArray){ val arraysize = decl.arraysize if(arraysize==null) { @@ -291,8 +300,11 @@ internal class ConstantIdentifierReplacer(private val program: Program, private } private fun createConstArrayInitializerValue(decl: VarDecl): ArrayLiteral? { - // convert the initializer range expression from a range or int, to an actual array. + if(decl.type==VarDeclType.MEMORY) + return null // memory mapped arrays can never have an initializer value other than the address where they're mapped. + + // convert the initializer range expression from a range or int, to an actual array. when(decl.datatype) { DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_W_SPLIT, DataType.ARRAY_UW_SPLIT -> { val rangeExpr = decl.value as? RangeExpression diff --git a/compiler/test/ast/TestVariousCompilerAst.kt b/compiler/test/ast/TestVariousCompilerAst.kt index 16b66ff48..a6918bc28 100644 --- a/compiler/test/ast/TestVariousCompilerAst.kt +++ b/compiler/test/ast/TestVariousCompilerAst.kt @@ -366,5 +366,18 @@ main { compileText(VMTarget(), optimize=false, src, writeAssembly=false, errors = errors) shouldBe null errors.errors.single() shouldContain "cannot use byte value" } + + test("const eval of address-of a memory mapped variable") { + val src = """ +main { + sub start() { + &ubyte mappedvar = 1000 + cx16.r0 = &mappedvar + &ubyte[8] array = &mappedvar + cx16.r0 = &array + } +}""" + compileText(VMTarget(), optimize=false, src, writeAssembly=false) shouldNotBe null + } }) diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 8cdfeccdd..b3f79a3c8 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -395,7 +395,15 @@ data class AddressOf(var identifier: IdentifierReference, var arrayIndex: ArrayI } override fun copy() = AddressOf(identifier.copy(), arrayIndex?.copy(), position) - override fun constValue(program: Program): NumericLiteral? = null + override fun constValue(program: Program): NumericLiteral? { + val target = this.identifier.targetStatement(program) as? VarDecl + if(target?.type==VarDeclType.MEMORY) { + val address = target.value?.constValue(program) + if(address!=null) + return NumericLiteral(DataType.UWORD, address.number, position) + } + return null + } override fun referencesIdentifier(nameInSource: List) = identifier.nameInSource==nameInSource || arrayIndex?.referencesIdentifier(nameInSource)==true override fun inferType(program: Program) = InferredTypes.knownFor(DataType.UWORD) override fun accept(visitor: IAstVisitor) = visitor.visit(this)