fix certain value copying through pointer dereferences

This commit is contained in:
Irmen de Jong committed 2026-03-16 00:10:47 +01:00
1 parent decfbfc8cc
commit 8be0cd3c19
6 files changed
+59 -15

No files matched your search

+1 -1
View File
@@ -212,7 +212,7 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
}
fun dereference(): DataType {
require(isPointer || isUnsignedWord)
require(isPointer || isUnsignedWord) { "cannot dereference non-pointer type ${this}"}
return when {
isUnsignedWord -> forDt(BaseDataType.UBYTE)
sub!=null -> forDt(sub)
@@ -2254,7 +2254,7 @@ internal class AstChecker(private val program: Program,
if(symbol==null)
errors.undefined(deref.chain.take(1), position=deref.position)
else
errors.err("unable to determine type of dereferenced pointer expression", deref.position)
errors.err("unable to determine type of dereferenced pointer expression, make sure it dereferences an actual pointer type", deref.position)
}
super.visit(deref)
@@ -974,9 +974,18 @@ _after:
val sourcePtr = assignment.value as PtrDereference
val targetDt = targetPtr.inferType(program)
if (targetDt == sourcePtr.inferType(program)) {
val sourceAddress = IdentifierReference(sourcePtr.chain, assignment.position)
val targetAddress = IdentifierReference(targetPtr.chain, assignment.position)
val sourceAddress: Expression
val targetAddress: Expression
if(!targetPtr.derefLast) {
val targetIdentifier = IdentifierReference(targetPtr.chain, assignment.position)
targetAddress = AddressOf(targetIdentifier, null, null, false, false, assignment.position)
} else
targetAddress = IdentifierReference(targetPtr.chain, assignment.position)
if(!sourcePtr.derefLast) {
val sourceIdentifier = IdentifierReference(sourcePtr.chain, assignment.position)
sourceAddress = AddressOf(sourceIdentifier, null, null, false, false, assignment.position)
} else
sourceAddress = IdentifierReference(sourcePtr.chain, assignment.position)
val copy = when {
targetDt.isLong -> FunctionCallStatement(
IdentifierReference(listOf("prog8_lib_copylong"), assignment.position),
@@ -553,6 +553,19 @@ data class AddressOf(var identifier: IdentifierReference?, var arrayIndex: Array
require(replacement is ArrayIndex)
arrayIndex = replacement
}
node===dereference -> {
if(replacement is IdentifierReference) {
identifier = replacement
dereference = null
} else if(replacement is ArrayIndex) {
arrayIndex = replacement
dereference = null
} else if(replacement is PtrDereference) {
dereference = replacement
} else {
throw FatalAstException("invalid replace $node")
}
}
else -> {
throw FatalAstException("invalid replace, no child node $node")
}
@@ -1785,7 +1798,18 @@ class PtrDereference(
override fun inferType(program: Program): InferredTypes.InferredType {
fun resultType(dt: DataType?) = if(dt==null) InferredTypes.unknown() else InferredTypes.knownFor(if(derefLast) dt.dereference() else dt)
fun resultType(dt: DataType?): InferredTypes.InferredType {
return if (dt == null) InferredTypes.unknown()
else {
if(derefLast) {
if(dt.isPointer || dt.isUnsignedWord)
InferredTypes.knownFor(dt.dereference())
else
InferredTypes.unknown()
} else
InferredTypes.knownFor(dt)
}
}
val target = definingScope.lookup(chain) ?: return InferredTypes.unknown()
return when (target) {
+1 -2
View File
@@ -26,12 +26,12 @@ Future Things and Ideas
- structs: properly fix the symbol name prefix hack in StStruct.sameas(), see github issue 198
- struct/ptr: support const pointers (simple and struct types) (make sure to change codegen properly in all cases, change remark about this limitation in docs too)
- struct/ptr: implement the remaining TODOs in PointerAssignmentsGen.
- struct/ptr: optimize the float copying in assignIndexedPointer() (also word and long?)
- struct/ptr: optimize augmented assignments to indexed pointer targets like sprptr[2]^^.y++ (these are now not performend in-place but as a regular assignment)
- struct/ptr: implement even more struct instance assignments (via memcopy) in CodeDesugarer (see the TODO) (add to documentation as well, paragraph 'Structs')
- struct/ptr: support @nosplit pointer arrays?
- struct/ptr: support pointer to pointer?
- struct/ptr: support for typed function pointers? (&routine could be typed by default as well then)
- struct/ptr: optimize the long pointer deref in assignPointerDerefExpression() so that it doesnt require a temp assignment all the time
- struct/ptr: really fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator"
- struct/ptr: (later, nasty parser problem:) support chaining pointer dereference on function calls that return a pointer. (type checking now fails on stuff like func().field and func().next.field)
- make memory mapped variables support more constant expressions such as: &uword MyHigh = &mylong1+2 (see github issue #192)
@@ -50,7 +50,6 @@ Future Things and Ideas
- Kotlin: can we use inline value classes in certain spots? (domain types instead of primitives)
- Kotlin: can private setters / backing fields be used? (internal mutableList, external List)
- add float support to the configurable compiler targets. Restrictions: just have "cbm-style floats" as an option (to that it can slot into the current float codegen), where all you have to specify is the addresses of AYINT and GIVAYF and FADDT and all their friends.
- Improve the SublimeText syntax file for prog8, you can also install this for 'bat': https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
- Change scoping rules for qualified symbols so that they don't always start from the root but behave like other programming languages (look in local scope first), maybe only when qualified symbol starts with '.' such as: .local.value = 33
- something to reduce the need to use fully qualified names all the time. 'with' ? Or 'using <prefix>'?
- Improve register load order in subroutine call args assignments:
+19 -7
View File
@@ -1,18 +1,30 @@
%import textio
%zeropage basicsafe
%option no_sysinit
main {
sub start() {
long[] larray = [111111, 222222, 333333, 444444]
test(larray)
struct Node {
bool x
word y
long lvar
}
sub test(^^long lv) {
txt.print_l(lv^^)
sub start() {
^^Node nodeptr1 = ^^Node : [false, 1111, 1111111]
^^Node nodeptr2 = ^^Node : [false, 2222, 2222222]
long @shared lvar = 333333
txt.print_l(nodeptr1^^.lvar)
txt.spc()
lv++
txt.print_l(lv^^)
txt.print_l(nodeptr2^^.lvar)
txt.nl()
nodeptr1^^.lvar = nodeptr2^^.lvar
txt.print_l(nodeptr1^^.lvar)
txt.spc()
txt.print_l(nodeptr2^^.lvar)
txt.nl()
}
}