fixes for address-of uword pointer array expressions

This commit is contained in:
Irmen de Jong 2024-01-17 22:51:11 +01:00
parent 69075376dc
commit fdbbd181ea
8 changed files with 74 additions and 44 deletions

View File

@ -198,7 +198,8 @@ private fun PtIdentifier.prefix(parent: PtNode, st: SymbolTable): PtIdentifier {
StNodeType.BLOCK -> 'b'
StNodeType.SUBROUTINE, StNodeType.ROMSUB -> 's'
StNodeType.LABEL -> 'l'
StNodeType.STATICVAR, StNodeType.MEMVAR, StNodeType.CONSTANT -> 'v'
StNodeType.STATICVAR, StNodeType.MEMVAR -> 'v'
StNodeType.CONSTANT -> 'c'
StNodeType.BUILTINFUNC -> 's'
StNodeType.MEMORYSLAB -> 'v'
else -> '?'

View File

@ -2512,7 +2512,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else
program.memsizer.memorySize(arrayDt!!, constIndex) // add arrayIndexExpr * elementsize to the address of the array variable.
} else {
val eltSize = program.memsizer.memorySize(ArrayToElementTypes.getValue(arrayDt!!))
val eltSize = if(arrayDt==DataType.UWORD) 1 else program.memsizer.memorySize(ArrayToElementTypes.getValue(arrayDt!!))
assignExpressionToVariable(arrayIndexExpr, "P8ZP_SCRATCH_W1", DataType.UWORD)
when(eltSize) {
1 -> {}

View File

@ -272,6 +272,14 @@ class VarConstantValueTypeAdjuster(
// This is needed because further constant optimizations depend on those.
internal class ConstantIdentifierReplacer(private val program: Program, private val errors: IErrorReporter, private val compTarget: ICompilationTarget) : AstWalker() {
override fun before(addressOf: AddressOf, parent: Node): Iterable<IAstModification> {
val constValue = addressOf.constValue(program)
if(constValue!=null) {
return listOf(IAstModification.ReplaceNode(addressOf, constValue, parent))
}
return noModifications
}
override fun after(identifier: IdentifierReference, parent: Node): Iterable<IAstModification> {
// replace identifiers that refer to const value, with the value itself
// if it's a simple type and if it's not a left hand side variable
@ -304,16 +312,20 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
listOf(IAstModification.ReplaceNode(arrayIdx, memread, arrayIdx.parent))
}
}
return when (cval.type) {
in NumericDatatypes -> listOf(
IAstModification.ReplaceNode(
identifier,
NumericLiteral(cval.type, cval.number, identifier.position),
identifier.parent
when (cval.type) {
in NumericDatatypes -> {
if(parent is AddressOf)
return noModifications // cannot replace the identifier INSIDE the addr-of here, let's do it later.
return listOf(
IAstModification.ReplaceNode(
identifier,
NumericLiteral(cval.type, cval.number, identifier.position),
identifier.parent
)
)
)
}
in PassByReferenceDatatypes -> throw InternalCompilerException("pass-by-reference type should not be considered a constant")
else -> noModifications
else -> return noModifications
}
} catch (x: UndefinedSymbolError) {
errors.err(x.message, x.position)
@ -321,7 +333,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
}
}
override fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> {
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
// the initializer value can't refer to the variable itself (recursive definition)
if(decl.value?.referencesIdentifier(listOf(decl.name)) == true || decl.arraysize?.indexExpr?.referencesIdentifier(listOf(decl.name)) == true) {
errors.err("recursive var declaration", decl.position)

View File

@ -5,11 +5,11 @@ package prog8.buildversion
*/
const val MAVEN_GROUP = "prog8"
const val MAVEN_NAME = "compiler"
const val VERSION = "9.8-SNAPSHOT"
const val GIT_REVISION = 4335
const val GIT_SHA = "44d82f9190763aa5113a3dce4a7d4623018a1c25"
const val GIT_DATE = "2023-12-28T12:30:07Z"
const val VERSION = "10.0-SNAPSHOT"
const val GIT_REVISION = 4405
const val GIT_SHA = "69075376dc26f06b7422f47529f90577f4213aaf"
const val GIT_DATE = "2024-01-17T20:24:41Z"
const val GIT_BRANCH = "master"
const val BUILD_DATE = "2023-12-28T12:44:26Z"
const val BUILD_UNIX_TIME = 1703767466828L
const val BUILD_DATE = "2024-01-17T21:46:56Z"
const val BUILD_UNIX_TIME = 1705528016840L
const val DIRTY = 1

View File

@ -592,8 +592,10 @@ internal class AstChecker(private val program: Program,
override fun visit(addressOf: AddressOf) {
checkLongType(addressOf)
val variable=addressOf.identifier.targetVarDecl(program)
if(variable!=null && variable.type==VarDeclType.CONST)
errors.err("invalid pointer-of operand type", addressOf.position)
if(variable!=null && variable.type==VarDeclType.CONST && addressOf.arrayIndex==null) errors.err(
"invalid pointer-of operand type",
addressOf.position
)
super.visit(addressOf)
}

View File

@ -4,6 +4,7 @@ import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.types.instanceOf
import prog8.ast.expressions.AddressOf
import prog8.ast.expressions.BinaryExpression
import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteral
@ -15,7 +16,6 @@ import prog8.code.core.DataType
import prog8.code.core.Position
import prog8.code.target.C64Target
import prog8.code.target.Cx16Target
import prog8.code.target.VMTarget
import prog8tests.helpers.compileText
class TestConst: FunSpec({
@ -219,22 +219,6 @@ class TestConst: FunSpec({
(initY2.value as NumericLiteral).number shouldBe 11.0
}
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
const uword HIGH_MEMORY_START = 40960
&uword[20] @shared wa = HIGH_MEMORY_START
}
}"""
compileText(VMTarget(), optimize=false, src, writeAssembly=false) shouldNotBe null
}
test("const pointer variable indexing works") {
val src="""
main {
@ -295,21 +279,48 @@ main {
((st[5] as Assignment).value as NumericLiteral).number shouldBe 0x9e00+2*30
}
test("address of a memory mapped variable") {
val src = """
main {
sub start() {
&ubyte mappedvar = 1000
cx16.r0 = &mappedvar
&ubyte[8] array = &mappedvar
cx16.r0 = &array
const uword HIGH_MEMORY_START = 40960
&uword[20] @shared wa = HIGH_MEMORY_START
}
}"""
val result = compileText(Cx16Target(), optimize=false, src, writeAssembly=true)!!
val st = result.compilerAst.entrypoint.statements
st.size shouldBe 7
val arrayDeclV = (st[2] as VarDecl).value
(arrayDeclV as NumericLiteral).number shouldBe 1000.0
val waDeclV = (st[5] as VarDecl).value
(waDeclV as NumericLiteral).number shouldBe 40960.0
}
test("address of a const uword pointer array expression") {
val src="""
main {
sub start() {
const uword buffer = ${'$'}2000
uword addr = &buffer[2]
uword @shared addr = &buffer[2]
const ubyte width = 100
ubyte @shared i
ubyte @shared j
uword addr2 = &buffer[i * width + j]
uword @shared addr2 = &buffer[i * width + j]
}
}"""
val result = compileText(Cx16Target(), true, src, writeAssembly = false)!!
val result = compileText(Cx16Target(), true, src, writeAssembly = true)!!
val st = result.compilerAst.entrypoint.statements
st.size shouldBe 9999
st.size shouldBe 11
val assignAddr = (st[2] as Assignment).value
(assignAddr as NumericLiteral).number shouldBe 8194.0
val assignAddr2 = ((st[9] as Assignment).value as AddressOf)
assignAddr2.identifier.nameInSource shouldBe listOf("buffer")
assignAddr2.arrayIndex!!.indexExpr shouldBe instanceOf<BinaryExpression>()
}
})

View File

@ -407,13 +407,18 @@ data class AddressOf(var identifier: IdentifierReference, var arrayIndex: ArrayI
override fun copy() = AddressOf(identifier.copy(), arrayIndex?.copy(), position)
override fun constValue(program: Program): NumericLiteral? {
val target = this.identifier.targetStatement(program) as? VarDecl
if(target?.type==VarDeclType.MEMORY) {
if(target?.type==VarDeclType.MEMORY || target?.type==VarDeclType.CONST) {
var address = target.value?.constValue(program)?.number
if(address!=null) {
if(arrayIndex!=null) {
val index = arrayIndex?.constIndex()
if (index != null)
address += program.memsizer.memorySize(target.datatype, index)
if (index != null) {
address += when (target.datatype) {
DataType.UWORD -> index
in ArrayDatatypes -> program.memsizer.memorySize(target.datatype, index)
else -> throw FatalAstException("need array or uword ptr")
}
}
else
return null
}

View File

@ -1,7 +1,6 @@
TODO
====
2 unit tests that are failing.
Mark had a compiler crash FatalAstException: invalid dt.
IR: optimize funcRolRor()