fix ptr errors

This commit is contained in:
Irmen de Jong
2025-05-19 20:06:31 +02:00
parent f0b791452e
commit f70341df1b
9 changed files with 42 additions and 21 deletions

3
.gitignore vendored
View File

@@ -7,10 +7,13 @@ build/
dist/
output/
out/
out-new/
out-old/
.*cache/
*.directory
*.prg
*.bin
*.p8ir
*.labels.txt
*.vm.txt
*.vice-mon-list

View File

@@ -202,6 +202,17 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
}
}
fun dereference(): DataType {
require(isPointer || isUnsignedWord)
return when {
isUnsignedWord -> forDt(BaseDataType.UBYTE)
sub!=null -> forDt(sub)
subType!=null -> DataType(BaseDataType.STRUCT_INSTANCE, null, subType)
subTypeFromAntlr!=null -> DataType(BaseDataType.STRUCT_INSTANCE, null, null, subTypeFromAntlr)
else -> throw IllegalArgumentException("cannot dereference this pointer type")
}
}
override fun toString(): String = when(base) {
BaseDataType.ARRAY -> {
when(sub) {

View File

@@ -166,10 +166,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
}
override fun visit(deref: PtrDereference) {
val first = deref.identifier.targetStatement()
if(first==null)
errors.undefined(deref.identifier.nameInSource, deref.identifier.position)
if(deref.field!=null) {
// check chain and field
val dt = deref.identifier.inferType(program).getOrUndef()
@@ -191,10 +187,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
if(fieldDt==null) {
errors.err("unknown field '${deref.field}' in struct '${struct.name}'", deref.position)
}
} else {
if (first !is VarDecl || !first.datatype.isStructInstance) {
errors.err("cannot find struct type", deref.identifier.position)
}
}
}

View File

@@ -507,6 +507,18 @@ _after:
return listOf(IAstModification.ReplaceNode(deref, memread, parent))
}
}
if(deref.chain.isEmpty() && deref.field==null) {
val expr = deref.parent as? BinaryExpression
if (expr != null && expr.operator == ".") {
if (expr.left is IdentifierReference && expr.right === deref) {
// replace (a) . (b^^) by (a.b)^^
val identifier = IdentifierReference((expr.left as IdentifierReference).nameInSource + deref.identifier.nameInSource, expr.left.position)
val replacement = PtrDereference(identifier, emptyList(), null, deref.position)
return listOf(IAstModification.ReplaceNode(expr, replacement, expr.parent))
}
}
}
return noModifications
}

View File

@@ -393,9 +393,9 @@ main {
val dr1 = (st[3] as Assignment).target.pointerDereference!!
val dr2 = (st[4] as Assignment).value as PtrDereference
val dr3 = (st[6] as Assignment).value as PtrDereference
val dr4 = (st[7] as Assignment).value as PtrDereference
val dr5 = (st[8] as Assignment).target.pointerDereference!!
val dr3 = (st[7] as Assignment).value as PtrDereference
val dr4 = (st[8] as Assignment).value as PtrDereference
val dr5 = (st[9] as Assignment).target.pointerDereference!!
dr0.identifier.nameInSource shouldBe listOf("l1", "s")
dr0.chain.size shouldBe 0

View File

@@ -1631,7 +1631,7 @@ class PtrIndexedDereference(val indexed: ArrayIndexedExpression, override val po
val vardecl = indexed.arrayvar.targetVarDecl()
if(vardecl!=null &&vardecl.datatype.isPointer) {
if(vardecl.datatype.sub!=null)
return InferredTypes.knownFor(vardecl.datatype.sub!!)
return InferredTypes.knownFor(vardecl.datatype.dereference())
TODO("cannot determine type of dereferenced indexed pointer(?) that is not a pointer to a basic type")
}
@@ -1641,7 +1641,7 @@ class PtrIndexedDereference(val indexed: ArrayIndexedExpression, override val po
dt.isUndefined -> InferredTypes.unknown()
dt.isUnsignedWord -> InferredTypes.knownFor(BaseDataType.UBYTE)
dt.isPointer -> {
return if(dt.sub!=null) InferredTypes.knownFor(dt.sub!!)
return if(dt.sub!=null) InferredTypes.knownFor(dt.dereference())
else InferredTypes.unknown()
}
else -> InferredTypes.unknown()
@@ -1657,6 +1657,8 @@ class PtrIndexedDereference(val indexed: ArrayIndexedExpression, override val po
}
class PtrDereference(val identifier: IdentifierReference, val chain: List<String>, val field: String?, override val position: Position) : Expression() {
// TODO why both identifier and chain?
override lateinit var parent: Node
override fun linkParents(parent: Node) {
@@ -1674,7 +1676,7 @@ class PtrDereference(val identifier: IdentifierReference, val chain: List<String
if(first==null)
return InferredTypes.unknown()
if(first is StructFieldRef) {
return InferredTypes.knownFor(first.type)
return InferredTypes.knownFor(first.type.dereference())
}
val vardecl = identifier.targetVarDecl()
if(vardecl==null || vardecl.datatype.isUndefined || (!vardecl.datatype.isPointer && !vardecl.datatype.isStructInstance) )
@@ -1683,7 +1685,7 @@ class PtrDereference(val identifier: IdentifierReference, val chain: List<String
if(chain.isEmpty()) {
return if(field==null) {
require(vardecl.datatype.sub!=null) { "can only dereference a pointer to a simple datatype " }
InferredTypes.knownFor(vardecl.datatype.sub!!)
InferredTypes.knownFor(vardecl.datatype.dereference())
} else {
// lookup struct field type
val struct = vardecl.datatype.subType as StructDecl
@@ -1691,7 +1693,7 @@ class PtrDereference(val identifier: IdentifierReference, val chain: List<String
if (fieldDt == null)
InferredTypes.unknown()
else
InferredTypes.knownFor(fieldDt)
InferredTypes.knownFor(fieldDt.dereference())
}
} else {
// lookup type of field at the end of a dereference chain
@@ -1705,13 +1707,13 @@ class PtrDereference(val identifier: IdentifierReference, val chain: List<String
struct = fieldDt.subType as StructDecl
}
if(field==null) {
return InferredTypes.knownFor(DataType.pointer(struct))
return InferredTypes.knownFor(DataType.structInstance(struct))
}
val fieldDt = struct.getFieldType(field)
return if(fieldDt==null)
InferredTypes.unknown()
else
InferredTypes.knownFor(fieldDt)
InferredTypes.knownFor(fieldDt.dereference())
}
}

View File

@@ -53,8 +53,9 @@ STRUCTS and TYPED POINTERS
- DONE: fix _msb/_lsb storage of the split-words pointer-arrays
- DONE: what about static initialization of an array of struct pointers? -> impossible right now because the pointer values are not constants.
- DONE: make typeForAddressOf() be even more specific about the typed pointers it returns for the address-of operator.
- fix ptr indexed problems (see todo.p8)
- fix ptr problems in re.p8
- Can we now get rid of PtPointerIndexedDeref ? Both for expression (value) as assigntarget? All code for translate(idxderef: PtPointerIndexedDeref) in ExpressionGen?
- why does PtrDereference have both identifier and chain property? what goes where? is the distinction needed?
- add unit tests for all changes (pointers and structs)
- 6502 codegen: remove checks in checkForPointerTypesOn6502()
- 6502 codegen should warn about writing to initialized struct instances when using romable code, like with arrays "can only be used as read-only in ROMable code"

View File

@@ -5,7 +5,7 @@ main {
}
sub start() {
^^List l1 = List()
cx16.r1 = l1.s^^ ; TODO fix "undefined symbol" error (and fix the unit test too)
cx16.r1 = l1.s^^
}
}

View File

@@ -414,7 +414,7 @@ class PtPointerDeref(type: DataType, val chain: List<String>, val field: String?
get() = children.single() as PtExpression
init {
require(!type.isUndefined)
require(!type.isUndefined && !type.isPointer) { "no support for pointer to pointer" }
}
}