mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
fixes for address-of uword pointer array expressions
This commit is contained in:
parent
69075376dc
commit
fdbbd181ea
@ -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 -> '?'
|
||||
|
@ -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 -> {}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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>()
|
||||
}
|
||||
})
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
2 unit tests that are failing.
|
||||
Mark had a compiler crash FatalAstException: invalid dt.
|
||||
|
||||
IR: optimize funcRolRor()
|
||||
|
Loading…
x
Reference in New Issue
Block a user