fix pointer value assignment (not dereferencing the actual pointer)

This commit is contained in:
Irmen de Jong
2025-04-26 21:09:42 +02:00
parent 803e6bd81a
commit cca27faa3b
4 changed files with 35 additions and 37 deletions
@@ -511,7 +511,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
else if(targetPointerDeref!=null) {
val pointerTr = expressionEval.translateExpression(targetPointerDeref.start)
result += pointerTr.chunks
result += expressionEval.traverseDerefChainToCalculateFinalAddress(targetPointerDeref, pointerTr.resultReg)
result += expressionEval.traverseDerefChainToCalculateFinalAddress(targetPointerDeref, pointerTr.resultReg, targetPointerDeref.type.isPointer)
val instr = when {
targetPointerDeref.type.isByteOrBool -> {
@@ -533,7 +533,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
IRInstruction(Opcode.STOREI, IRDataType.FLOAT, fpReg1 = valueRegister, reg1 = pointerTr.resultReg)
}
targetPointerDeref.type.isPointer -> {
TODO()
// stores value into the pointer itself
if(zero)
IRInstruction(Opcode.STOREZI, IRDataType.WORD, reg1 = pointerTr.resultReg)
else
@@ -100,7 +100,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val result = mutableListOf<IRCodeChunkBase>()
val tr = translateExpression(deref.start)
result += tr.chunks
result += traverseDerefChainToCalculateFinalAddress(deref, tr.resultReg)
result += traverseDerefChainToCalculateFinalAddress(deref, tr.resultReg, false)
when {
deref.type.isByteOrBool -> {
val resultReg = codeGen.registers.next(IRDataType.BYTE)
@@ -118,7 +118,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
return ExpressionCodeResult(result, IRDataType.FLOAT, -1, resultReg)
}
deref.type.isPointer -> {
// just return the pointer value itself, a word adress
// just return the value of the pointer, a word adress
return ExpressionCodeResult(result, IRDataType.WORD, tr.resultReg, -1)
}
else -> throw AssemblyError("unsupported dereference type ${deref.type}")
@@ -240,7 +240,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
require(vmDt==IRDataType.WORD)
val pointerTr = translateExpression(expr.dereference!!.start)
result += pointerTr.chunks
result += traverseDerefChainToCalculateFinalAddress(expr.dereference!!, pointerTr.resultReg)
result += traverseDerefChainToCalculateFinalAddress(expr.dereference!!, pointerTr.resultReg, false)
addInstr(result, IRInstruction(Opcode.LOADR, IRDataType.WORD, reg1 = resultRegister, reg2 = pointerTr.resultReg), null)
}
return ExpressionCodeResult(result, vmDt, resultRegister, -1)
@@ -1483,23 +1483,27 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
}
internal fun traverseDerefChainToCalculateFinalAddress(targetPointerDeref: PtPointerDeref, pointerReg: Int): IRCodeChunks {
internal fun traverseDerefChainToCalculateFinalAddress(targetPointerDeref: PtPointerDeref, pointerReg: Int, getLastPointerItselfInsteadOfItsValue: Boolean): IRCodeChunks {
if(getLastPointerItselfInsteadOfItsValue)
require(targetPointerDeref.field==null)
val result = mutableListOf<IRCodeChunkBase>()
var struct: StStruct? = null
if(targetPointerDeref.start.type.subIdentifier!=null)
struct = codeGen.symbolTable.lookup(targetPointerDeref.start.type.subIdentifier!!.joinToString(".")) as StStruct
if(targetPointerDeref.chain.isNotEmpty()) {
// traverse deref chain
for(deref in targetPointerDeref.chain) {
for((idx, deref) in targetPointerDeref.chain.withIndex()) {
val fieldinfo = struct!!.getField(deref, codeGen.program.memsizer)
struct = codeGen.symbolTable.lookup(fieldinfo.first.subIdentifier!!.joinToString(".")) as StStruct
// get new pointer from field
val newPointerReg = codeGen.registers.next(IRDataType.WORD)
result += IRCodeChunk(null, null).also {
// TODO IR instruction LOADI should allow reg1 and reg2 to be the same, so we can remove the extra 'newPointerReg'.
it += IRInstruction(Opcode.ADD, IRDataType.WORD, reg1 = pointerReg, immediate = fieldinfo.second)
it += IRInstruction(Opcode.LOADI, IRDataType.WORD, reg1 = newPointerReg, reg2 = pointerReg)
it += IRInstruction(Opcode.LOADR, IRDataType.WORD, reg1 = pointerReg, reg2 = newPointerReg)
if (!getLastPointerItselfInsteadOfItsValue || idx<targetPointerDeref.chain.size-1) {
// TODO IR instruction LOADI should allow reg1 and reg2 to be the same, so we can remove the extra 'newPointerReg'.
it += IRInstruction(Opcode.LOADI, IRDataType.WORD, reg1 = newPointerReg, reg2 = pointerReg)
it += IRInstruction(Opcode.LOADR, IRDataType.WORD, reg1 = pointerReg, reg2 = newPointerReg)
}
}
}
}