mirror of
https://github.com/irmen/prog8.git
synced 2025-11-23 14:17:51 +00:00
fix pointer[i].field compiler crash
This commit is contained in:
@@ -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 indexedTr = translateExpression(left)
|
val field: Pair<DataType, UInt>
|
||||||
result += indexedTr.chunks
|
val pointerReg: Int
|
||||||
val pointerReg = indexedTr.resultReg
|
var extraFieldOffset = 0
|
||||||
val struct = left.type.dereference().subType as? StStruct
|
|
||||||
require(indexedTr.dt== IRDataType.WORD && struct!=null)
|
if(left.type.isStructInstance) {
|
||||||
val field = struct.getField(right.name, this.codeGen.program.memsizer)
|
|
||||||
val vmDt = irType(field.first)
|
// 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)
|
||||||
|
result += indexedTr.chunks
|
||||||
|
pointerReg = indexedTr.resultReg
|
||||||
|
val struct = left.type.dereference().subType as? StStruct
|
||||||
|
require(indexedTr.dt == IRDataType.WORD && struct != null)
|
||||||
|
field = struct.getField(right.name, codeGen.program.memsizer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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> {
|
||||||
|
|||||||
@@ -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!!)
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
fix ^^Node nodes / cx16.r0L = nodes[2].weight compiler crash
|
|
||||||
disallow ^^str
|
disallow ^^str
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user