fix pointer[i].field compiler crash

This commit is contained in:
Irmen de Jong
2025-08-02 05:29:16 +02:00
parent ea8935a346
commit 647cd0fbe1
4 changed files with 93 additions and 33 deletions

View File

@@ -1624,28 +1624,62 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val right = binExpr.right as? PtIdentifier val right = binExpr.right as? PtIdentifier
require(binExpr.operator=="." && left!=null && right!=null) {"invalid dereference expression ${binExpr.position}"} require(binExpr.operator=="." && left!=null && right!=null) {"invalid dereference expression ${binExpr.position}"}
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
val field: Pair<DataType, UInt>
val pointerReg: Int
var extraFieldOffset = 0
if(left.type.isStructInstance) {
// indexing on a pointer directly
// fetch pointer address, determine struct and field, add index * structsize
if(left.variable!=null) {
val pointerTr = translateExpression(left.variable!!)
result += pointerTr.chunks
pointerReg = pointerTr.resultReg
} else if(left.pointerderef!=null) {
TODO("get pointer from deref $left")
} else {
throw AssemblyError("weird arrayindexer $left")
}
val struct = left.type.subType!! as StStruct
val constindex = left.index as? PtNumber
if(constindex!=null) {
extraFieldOffset = struct.size.toInt() * constindex.number.toInt()
} else {
val (chunks, indexReg) = codeGen.loadIndexReg(left.index, struct.size.toInt(), true, false)
result += chunks
addInstr(result, IRInstruction(Opcode.ADDR, IRDataType.WORD, reg1 = pointerReg, reg2 = indexReg), null)
}
field = struct.getField(right.name, codeGen.program.memsizer)
} else {
// indexing on an array with pointers
// fetch the pointer from the array, determine the struct & field
val indexedTr = translateExpression(left) val indexedTr = translateExpression(left)
result += indexedTr.chunks result += indexedTr.chunks
val pointerReg = indexedTr.resultReg pointerReg = indexedTr.resultReg
val struct = left.type.dereference().subType as? StStruct val struct = left.type.dereference().subType as? StStruct
require(indexedTr.dt == IRDataType.WORD && struct != null) require(indexedTr.dt == IRDataType.WORD && struct != null)
val field = struct.getField(right.name, this.codeGen.program.memsizer) field = struct.getField(right.name, codeGen.program.memsizer)
val vmDt = irType(field.first) }
// add field offset to pointer and load the value into the result register
val fieldVmDt = irType(field.first)
var resultFpReg = -1 var resultFpReg = -1
var resultReg = -1 var resultReg = -1
if(vmDt==IRDataType.FLOAT) if (fieldVmDt == IRDataType.FLOAT)
resultFpReg = codeGen.registers.next(IRDataType.FLOAT) resultFpReg = codeGen.registers.next(IRDataType.FLOAT)
else else
resultReg = codeGen.registers.next(vmDt) resultReg = codeGen.registers.next(fieldVmDt)
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.ADD, IRDataType.WORD, reg1 = pointerReg, immediate = field.second.toInt()) it += IRInstruction(Opcode.ADD, IRDataType.WORD, reg1 = pointerReg, immediate = field.second.toInt() + extraFieldOffset)
it += if(vmDt==IRDataType.FLOAT) it += if (fieldVmDt == IRDataType.FLOAT)
IRInstruction(Opcode.LOADI, IRDataType.FLOAT, fpReg1 = resultFpReg, reg1 = pointerReg) IRInstruction(Opcode.LOADI, IRDataType.FLOAT, fpReg1 = resultFpReg, reg1 = pointerReg)
else else
IRInstruction(Opcode.LOADI, vmDt, reg1 = resultReg, reg2 = pointerReg) IRInstruction(Opcode.LOADI, fieldVmDt, reg1 = resultReg, reg2 = pointerReg)
} }
return ExpressionCodeResult(result, vmDt, resultReg, resultFpReg) return ExpressionCodeResult(result, fieldVmDt, resultReg, resultFpReg)
} }
internal fun traverseRestOfDerefChainToCalculateFinalAddress(targetPointerDeref: PtPointerDeref, pointerReg: Int): Pair<IRCodeChunks, UInt> { internal fun traverseRestOfDerefChainToCalculateFinalAddress(targetPointerDeref: PtPointerDeref, pointerReg: Int): Pair<IRCodeChunks, UInt> {

View File

@@ -389,22 +389,6 @@ _after:
// this will be further modified elsewhere // this will be further modified elsewhere
val ident = IdentifierReference(right.chain, right.position) val ident = IdentifierReference(right.chain, right.position)
return listOf(IAstModification.ReplaceNode(expr.right, ident, expr)) return listOf(IAstModification.ReplaceNode(expr.right, ident, expr))
// TODO hmmm , replace cx16.r1 = listarray[2]^^.value with a temp pointer var to contain the indexed value
// val assign = expr.parent as? Assignment
// if(assign!=null) {
// val ptrDt = expr.left.inferType(program).getOrUndef()
// val pointerVar = VarDecl.createAuto(ptrDt)
// val pointerIdent = IdentifierReference(pointerVar.name.split("."), expr.position)
// val tgt = AssignTarget(pointerIdent, null, null, null, false, null, position = expr.position)
// val assignPtr = Assignment(tgt, expr.left, AssignmentOrigin.USERCODE, expr.position)
// val derefValue = PtrDereference(pointerIdent.nameInSource + right.chain, false, expr.position)
// return listOf(
// IAstModification.InsertBefore(assign, assignPtr, assign.parent as IStatementContainer),
// IAstModification.ReplaceNode(assign.value, derefValue, assign),
// IAstModification.InsertFirst(pointerVar, expr.definingSubroutine!!)
// )
// }
} }
} }

View File

@@ -1,7 +1,6 @@
TODO TODO
==== ====
fix ^^Node nodes / cx16.r0L = nodes[2].weight compiler crash
disallow ^^str disallow ^^str

View File

@@ -1,12 +1,55 @@
%import textio
main { main {
struct Node { struct Node {
^^Node next
ubyte weight ubyte weight
} }
^^Node nodes ^^Node nodes = 2000
sub start() { sub start() {
cx16.r0L = nodes[2].weight ;TODO fix this compiler crash init()
cx16.r0L = nodes[2].weight
cx16.r1L = thing.things[2].weight
txt.print_ub(cx16.r0L)
txt.spc()
txt.print_ub(cx16.r1L)
txt.nl()
cx16.r9L = 3
cx16.r0L = nodes[cx16.r9L].weight
cx16.r1L = thing.things[cx16.r9L].weight
txt.print_ub(cx16.r0L)
txt.spc()
txt.print_ub(cx16.r1L)
txt.nl()
} }
sub init() {
sys.memset(2000, 100, 99)
sys.memset(3000, 100, 99)
; NNW NNW NNW NNW
@(2000+2) = 11
@(2000+5) = 22
@(2000+8) = 33
@(2000+11) = 44
@(3000+2) = 101
@(3000+5) = 102
@(3000+8) = 103
@(3000+11) = 104
}
}
thing {
struct Thing {
^^Thing next
ubyte weight
}
^^Thing things = 3000
} }