From 7294ec9a3cc1f202ec2c0b0809b1eb6e9a749418 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 15 Sep 2022 01:32:48 +0200 Subject: [PATCH] working on address-of --- .../codegen/experimental/AssignmentGen.kt | 112 +++++++---- .../src/prog8/codegen/experimental/CodeGen.kt | 130 +++++++++---- .../codegen/experimental/ExpressionGen.kt | 184 ++++++++++++------ .../codegen/experimental/VmAssemblyProgram.kt | 18 +- .../prog8/codegen/virtual/AssemblyProgram.kt | 2 +- docs/source/todo.rst | 2 + .../src/prog8/intermediate/IRFileReader.kt | 2 +- .../src/prog8/intermediate/IRFileWriter.kt | 2 +- .../src/prog8/intermediate/IRProgram.kt | 6 +- .../src/prog8/intermediate/Instructions.kt | 5 +- 10 files changed, 316 insertions(+), 147 deletions(-) diff --git a/codeGenExperimental/src/prog8/codegen/experimental/AssignmentGen.kt b/codeGenExperimental/src/prog8/codegen/experimental/AssignmentGen.kt index 15bfe41a6..800f84ade 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/AssignmentGen.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/AssignmentGen.kt @@ -32,7 +32,7 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio assignSelfInMemory(address, assignment.value, assignment) } else if(memory != null) { if(memory.address is PtNumber) - assignSelfInMemory((memory.address as PtNumber).number.toInt(), assignment.value, assignment) + assignSelfInMemoryKnownAddress((memory.address as PtNumber).number.toInt(), assignment.value, assignment) else fallbackAssign(assignment) } else if(array!=null) { @@ -45,7 +45,7 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio } } - private fun assignSelfInMemory( + private fun assignSelfInMemoryKnownAddress( address: Int, value: PtExpression, origAssign: PtAssignment @@ -55,8 +55,8 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio when(value) { is PtIdentifier -> return code // do nothing, x=x null assignment. is PtMachineRegister -> return code // do nothing, reg=reg null assignment - is PtPrefix -> return inplacePrefix(value.operator, vmDt, address, value.position) - is PtBinaryExpression -> return inplaceBinexpr(value.operator, value.right, vmDt, value.type in SignedDatatypes, address, origAssign) + is PtPrefix -> return inplacePrefix(value.operator, vmDt, address, null, value.position) + is PtBinaryExpression -> return inplaceBinexpr(value.operator, value.right, vmDt, value.type in SignedDatatypes, address, null, origAssign) is PtMemoryByte -> { return if (!codeGen.options.compTarget.machine.isIOAddress(address.toUInt())) code // do nothing, mem=mem null assignment. @@ -70,7 +70,28 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio } else -> return fallbackAssign(origAssign) } + } + private fun assignSelfInMemory( + addressOf: String, + value: PtExpression, + origAssign: PtAssignment + ): IRCodeChunk { + val vmDt = codeGen.vmType(value.type) + val code = IRCodeChunk(origAssign.position) + when(value) { + is PtIdentifier -> return code // do nothing, x=x null assignment. + is PtMachineRegister -> return code // do nothing, reg=reg null assignment + is PtPrefix -> return inplacePrefix(value.operator, vmDt, null, addressOf, value.position) + is PtBinaryExpression -> return inplaceBinexpr(value.operator, value.right, vmDt, value.type in SignedDatatypes, null, addressOf, origAssign) + is PtMemoryByte -> { + val tempReg = codeGen.vmRegisters.nextFree() + code += IRCodeInstruction(Opcode.LOADM, vmDt, reg1 = tempReg, labelSymbol = addressOf) + code += IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = tempReg, labelSymbol = addressOf) + return code + } + else -> return fallbackAssign(origAssign) + } } private fun fallbackAssign(origAssign: PtAssignment): IRCodeChunk { @@ -84,36 +105,59 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio operand: PtExpression, vmDt: VmDataType, signed: Boolean, - address: Int, + knownAddress: Int?, + addressOfSymbol: String?, origAssign: PtAssignment ): IRCodeChunk { - when(operator) { - "+" -> return expressionEval.operatorPlusInplace(address, vmDt, operand) - "-" -> return expressionEval.operatorMinusInplace(address, vmDt, operand) - "*" -> return expressionEval.operatorMultiplyInplace(address, vmDt, operand) - "/" -> return expressionEval.operatorDivideInplace(address, vmDt, signed, operand) - "|" -> return expressionEval.operatorOrInplace(address, vmDt, operand) - "&" -> return expressionEval.operatorAndInplace(address, vmDt, operand) - "^" -> return expressionEval.operatorXorInplace(address, vmDt, operand) - "<<" -> return expressionEval.operatorShiftLeftInplace(address, vmDt, operand) - ">>" -> return expressionEval.operatorShiftRightInplace(address, vmDt, signed, operand) - else -> {} + if(knownAddress!=null) { + when (operator) { + "+" -> return expressionEval.operatorPlusInplace(knownAddress, null, vmDt, operand) + "-" -> return expressionEval.operatorMinusInplace(knownAddress, null, vmDt, operand) + "*" -> return expressionEval.operatorMultiplyInplace(knownAddress, null, vmDt, operand) + "/" -> return expressionEval.operatorDivideInplace(knownAddress, null, vmDt, signed, operand) + "|" -> return expressionEval.operatorOrInplace(knownAddress, null, vmDt, operand) + "&" -> return expressionEval.operatorAndInplace(knownAddress, null, vmDt, operand) + "^" -> return expressionEval.operatorXorInplace(knownAddress, null, vmDt, operand) + "<<" -> return expressionEval.operatorShiftLeftInplace(knownAddress, null, vmDt, operand) + ">>" -> return expressionEval.operatorShiftRightInplace(knownAddress, null, vmDt, signed, operand) + else -> {} + } + } else { + addressOfSymbol!! + when (operator) { + "+" -> return expressionEval.operatorPlusInplace(null, addressOfSymbol, vmDt, operand) + "-" -> return expressionEval.operatorMinusInplace(null, addressOfSymbol, vmDt, operand) + "*" -> return expressionEval.operatorMultiplyInplace(null, addressOfSymbol, vmDt, operand) + "/" -> return expressionEval.operatorDivideInplace(null, addressOfSymbol, vmDt, signed, operand) + "|" -> return expressionEval.operatorOrInplace(null, addressOfSymbol, vmDt, operand) + "&" -> return expressionEval.operatorAndInplace(null, addressOfSymbol, vmDt, operand) + "^" -> return expressionEval.operatorXorInplace(null, addressOfSymbol, vmDt, operand) + "<<" -> return expressionEval.operatorShiftLeftInplace(null, addressOfSymbol, vmDt, operand) + ">>" -> return expressionEval.operatorShiftRightInplace(null, addressOfSymbol, vmDt, signed, operand) + else -> {} + } } return fallbackAssign(origAssign) } - private fun inplacePrefix(operator: String, vmDt: VmDataType, address: Int, position: Position): IRCodeChunk { + private fun inplacePrefix(operator: String, vmDt: VmDataType, knownAddress: Int?, addressSymbol: String?, position: Position): IRCodeChunk { val code= IRCodeChunk(position) when(operator) { "+" -> { } "-" -> { - code += IRCodeInstruction(Opcode.NEGM, vmDt, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.NEGM, vmDt, value = knownAddress) + else + IRCodeInstruction(Opcode.NEGM, vmDt, labelSymbol = addressSymbol) } "~" -> { val regMask = codeGen.vmRegisters.nextFree() val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value = mask) - code += IRCodeInstruction(Opcode.XORM, vmDt, reg1=regMask, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.XORM, vmDt, reg1=regMask, value = knownAddress) + else + IRCodeInstruction(Opcode.XORM, vmDt, reg1=regMask, labelSymbol = addressSymbol) } else -> throw AssemblyError("weird prefix operator") } @@ -147,19 +191,19 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio } } if(ident!=null) { - val address = codeGen.addressOf(ident.targetName) + val addressOf = codeGen.addressOf(ident.targetName) code += if(zero) { - IRCodeInstruction(Opcode.STOREZM, vmDt, value = address) + IRCodeInstruction(Opcode.STOREZM, vmDt, labelSymbol = addressOf) } else { if (vmDt == VmDataType.FLOAT) - IRCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, value = address) + IRCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = addressOf) else - IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, value = address) + IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = addressOf) } } else if(array!=null) { val variable = array.variable.targetName - var variableAddr = codeGen.addressOf(variable) + var variableAddrOf = codeGen.addressOf(variable) val itemsize = codeGen.program.memsizer.memorySize(array.type) if(array.variable.type==DataType.UWORD) { @@ -175,38 +219,38 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio resultRegister = codeGen.vmRegisters.nextFree() code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=0) } - code += IRCodeInstruction(Opcode.STOREIX, vmDt, reg1=resultRegister, reg2=idxReg, value = variableAddr) + code += IRCodeInstruction(Opcode.STOREIX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = variableAddrOf) return code } val fixedIndex = constIntValue(array.index) if(zero) { if(fixedIndex!=null) { - variableAddr += fixedIndex*itemsize - code += IRCodeInstruction(Opcode.STOREZM, vmDt, value=variableAddr) + val offset = fixedIndex*itemsize + code += IRCodeInstruction(Opcode.STOREZM, vmDt, labelSymbol = "$variableAddrOf+$offset") } else { val indexReg = codeGen.vmRegisters.nextFree() code += loadIndexReg(array, itemsize, indexReg, array.position) - code += IRCodeInstruction(Opcode.STOREZX, vmDt, reg1=indexReg, value=variableAddr) + code += IRCodeInstruction(Opcode.STOREZX, vmDt, reg1=indexReg, labelSymbol = variableAddrOf) } } else { if(vmDt== VmDataType.FLOAT) { if(fixedIndex!=null) { - variableAddr += fixedIndex*itemsize - code += IRCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, value=variableAddr) + val offset = fixedIndex*itemsize + code += IRCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = "$variableAddrOf+$offset") } else { val indexReg = codeGen.vmRegisters.nextFree() code += loadIndexReg(array, itemsize, indexReg, array.position) - code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, value=variableAddr) + code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, labelSymbol = variableAddrOf) } } else { if(fixedIndex!=null) { - variableAddr += fixedIndex*itemsize - code += IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, value=variableAddr) + val offset = fixedIndex*itemsize + code += IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = "$variableAddrOf+$offset") } else { val indexReg = codeGen.vmRegisters.nextFree() code += loadIndexReg(array, itemsize, indexReg, array.position) - code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, value=variableAddr) + code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, labelSymbol = variableAddrOf) } } } diff --git a/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt b/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt index a214abdfc..5c3c8e1f5 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt @@ -316,7 +316,7 @@ class CodeGen(internal val program: PtProgram, is PtIdentifier -> { val arrayAddress = addressOf(iterable.targetName) val iterableVar = symbolTable.lookup(iterable.targetName) as StStaticVariable - val loopvarAddress = addressOf(loopvar.scopedName) // TODO name? + val loopvarAddress = addressOf(loopvar.scopedName) val indexReg = vmRegisters.nextFree() val tmpReg = vmRegisters.nextFree() val loopLabel = createLabelName() @@ -325,9 +325,9 @@ class CodeGen(internal val program: PtProgram, // iterate over a zero-terminated string code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0) code += IRCodeLabel(loopLabel) - code += IRCodeInstruction(Opcode.LOADX, VmDataType.BYTE, reg1=tmpReg, reg2=indexReg, value = arrayAddress) + code += IRCodeInstruction(Opcode.LOADX, VmDataType.BYTE, reg1=tmpReg, reg2=indexReg, labelSymbol = arrayAddress) code += IRCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=tmpReg, labelSymbol = endLabel) - code += IRCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1=tmpReg, value = loopvarAddress) + code += IRCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1=tmpReg, labelSymbol = loopvarAddress) code += translateNode(forLoop.statements) code += IRCodeInstruction(Opcode.INC, VmDataType.BYTE, reg1=indexReg) code += IRCodeInstruction(Opcode.JUMP, labelSymbol = loopLabel) @@ -342,16 +342,16 @@ class CodeGen(internal val program: PtProgram, code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0) code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=lengthReg, value=lengthBytes) code += IRCodeLabel(loopLabel) - code += IRCodeInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, value=arrayAddress) - code += IRCodeInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, value = loopvarAddress) + code += IRCodeInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=arrayAddress) + code += IRCodeInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, labelSymbol = loopvarAddress) code += translateNode(forLoop.statements) code += addConstReg(VmDataType.BYTE, indexReg, elementSize, iterable.position) code += IRCodeInstruction(Opcode.BNE, VmDataType.BYTE, reg1=indexReg, reg2=lengthReg, labelSymbol = loopLabel) } else if(lengthBytes==256) { code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0) code += IRCodeLabel(loopLabel) - code += IRCodeInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, value=arrayAddress) - code += IRCodeInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, value = loopvarAddress) + code += IRCodeInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=arrayAddress) + code += IRCodeInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, labelSymbol = loopvarAddress) code += translateNode(forLoop.statements) code += addConstReg(VmDataType.BYTE, indexReg, elementSize, iterable.position) code += IRCodeInstruction(Opcode.BNZ, VmDataType.BYTE, reg1=indexReg, labelSymbol = loopLabel) @@ -365,10 +365,7 @@ class CodeGen(internal val program: PtProgram, return code } - internal fun addressOf(targetName: List): Int { - println("TODO: IR SUPPORT FOR ADDRESS-OF $targetName") // TODO address-of - return 4242 - } + internal inline fun addressOf(targetName: List): String = "&"+targetName.joinToString(".") private fun translateForInNonConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): IRCodeChunk { val iterable = forLoop.iterable as PtRange @@ -377,18 +374,18 @@ class CodeGen(internal val program: PtProgram, throw AssemblyError("step 0") val indexReg = vmRegisters.nextFree() val endvalueReg = vmRegisters.nextFree() - val loopvarAddress = addressOf(loopvar.scopedName) // TODO name? + val loopvarAddress = addressOf(loopvar.scopedName) val loopvarDt = vmType(loopvar.dt) val loopLabel = createLabelName() val code = IRCodeChunk(forLoop.position) code += expressionEval.translateExpression(iterable.to, endvalueReg, -1) code += expressionEval.translateExpression(iterable.from, indexReg, -1) - code += IRCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress) + code += IRCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, labelSymbol=loopvarAddress) code += IRCodeLabel(loopLabel) code += translateNode(forLoop.statements) code += addConstMem(loopvarDt, loopvarAddress.toUInt(), step, iterable.position) - code += IRCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress) + code += IRCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, labelSymbol = loopvarAddress) val branchOpcode = if(loopvar.dt in SignedDatatypes) Opcode.BLES else Opcode.BLE code += IRCodeInstruction(branchOpcode, loopvarDt, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel) return code @@ -396,7 +393,7 @@ class CodeGen(internal val program: PtProgram, private fun translateForInConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): IRCodeChunk { val loopLabel = createLabelName() - val loopvarAddress = addressOf(loopvar.scopedName) // TODO name? + val loopvarAddress = addressOf(loopvar.scopedName) val indexReg = vmRegisters.nextFree() val loopvarDt = vmType(loopvar.dt) val iterable = forLoop.iterable as PtRange @@ -417,11 +414,11 @@ class CodeGen(internal val program: PtProgram, endvalueReg = -1 // not used } code += IRCodeInstruction(Opcode.LOAD, loopvarDt, reg1=indexReg, value=rangeStart) - code += IRCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress) + code += IRCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, labelSymbol=loopvarAddress) code += IRCodeLabel(loopLabel) code += translateNode(forLoop.statements) code += addConstMem(loopvarDt, loopvarAddress.toUInt(), step, iterable.position) - code += IRCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress) + code += IRCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, labelSymbol = loopvarAddress) code += if(rangeEndWrapped==0) { IRCodeInstruction(Opcode.BNZ, loopvarDt, reg1 = indexReg, labelSymbol = loopLabel) } else { @@ -504,16 +501,22 @@ class CodeGen(internal val program: PtProgram, return code } - internal fun multiplyByConstFloatInplace(address: Int, factor: Float, position: Position): IRCodeChunk { + internal fun multiplyByConstFloatInplace(knownAddress: Int?, addressOfSymbol: String?, factor: Float, position: Position): IRCodeChunk { val code = IRCodeChunk(position) if(factor==1f) return code if(factor==0f) { - code += IRCodeInstruction(Opcode.STOREZM, VmDataType.FLOAT, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.STOREZM, VmDataType.FLOAT, value = knownAddress) + else + IRCodeInstruction(Opcode.STOREZM, VmDataType.FLOAT, labelSymbol = addressOfSymbol) } else { val factorReg = vmRegisters.nextFreeFloat() code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor) - code += IRCodeInstruction(Opcode.MULM, VmDataType.FLOAT, fpReg1 = factorReg, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.MULM, VmDataType.FLOAT, fpReg1 = factorReg, value = knownAddress) + else + IRCodeInstruction(Opcode.MULM, VmDataType.FLOAT, fpReg1 = factorReg, labelSymbol = addressOfSymbol) } return code } @@ -544,28 +547,40 @@ class CodeGen(internal val program: PtProgram, return code } - internal fun multiplyByConstInplace(dt: VmDataType, address: Int, factor: Int, position: Position): IRCodeChunk { + internal fun multiplyByConstInplace(dt: VmDataType, knownAddress: Int?, addressOfSymbol: String?, factor: Int, position: Position): IRCodeChunk { val code = IRCodeChunk(position) if(factor==1) return code val pow2 = powersOfTwo.indexOf(factor) if(pow2==1) { // just shift 1 bit - code += IRCodeInstruction(Opcode.LSLM, dt, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.LSLM, dt, value = knownAddress) + else + IRCodeInstruction(Opcode.LSLM, dt, labelSymbol = addressOfSymbol) } else if(pow2>=1) { // just shift multiple bits val pow2reg = vmRegisters.nextFree() code += IRCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2) - code += IRCodeInstruction(Opcode.LSLNM, dt, reg1=pow2reg, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.LSLNM, dt, reg1=pow2reg, value=knownAddress) + else + IRCodeInstruction(Opcode.LSLNM, dt, reg1=pow2reg, labelSymbol = addressOfSymbol) } else { if (factor == 0) { - code += IRCodeInstruction(Opcode.STOREZM, dt, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.STOREZM, dt, value=knownAddress) + else + IRCodeInstruction(Opcode.STOREZM, dt, labelSymbol = addressOfSymbol) } else { val factorReg = vmRegisters.nextFree() code += IRCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value = factor) - code += IRCodeInstruction(Opcode.MULM, dt, reg1=factorReg, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.MULM, dt, reg1=factorReg, value = knownAddress) + else + IRCodeInstruction(Opcode.MULM, dt, reg1=factorReg, labelSymbol = addressOfSymbol) } } return code @@ -583,18 +598,24 @@ class CodeGen(internal val program: PtProgram, return code } - internal fun divideByConstFloatInplace(address: Int, factor: Float, position: Position): IRCodeChunk { + internal fun divideByConstFloatInplace(knownAddress: Int?, addressOfSymbol: String?, factor: Float, position: Position): IRCodeChunk { val code = IRCodeChunk(position) if(factor==1f) return code if(factor==0f) { val maxvalueReg = vmRegisters.nextFreeFloat() code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = maxvalueReg, fpValue = Float.MAX_VALUE) - code += IRCodeInstruction(Opcode.STOREM, VmDataType.FLOAT, fpReg1 = maxvalueReg, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.STOREM, VmDataType.FLOAT, fpReg1 = maxvalueReg, value=knownAddress) + else + IRCodeInstruction(Opcode.STOREM, VmDataType.FLOAT, fpReg1 = maxvalueReg, labelSymbol = addressOfSymbol) } else { val factorReg = vmRegisters.nextFreeFloat() code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor) - code += IRCodeInstruction(Opcode.DIVSM, VmDataType.FLOAT, fpReg1 = factorReg, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.DIVSM, VmDataType.FLOAT, fpReg1 = factorReg, value=knownAddress) + else + IRCodeInstruction(Opcode.DIVSM, VmDataType.FLOAT, fpReg1 = factorReg, labelSymbol = addressOfSymbol) } return code } @@ -628,35 +649,58 @@ class CodeGen(internal val program: PtProgram, return code } - internal fun divideByConstInplace(dt: VmDataType, address: Int, factor: Int, signed: Boolean, position: Position): IRCodeChunk { + internal fun divideByConstInplace(dt: VmDataType, knownAddress: Int?, addressOfSymbol: String?, factor: Int, signed: Boolean, position: Position): IRCodeChunk { val code = IRCodeChunk(position) if(factor==1) return code val pow2 = powersOfTwo.indexOf(factor) if(pow2==1 && !signed) { - code += IRCodeInstruction(Opcode.LSRM, dt, value=address) // just simple bit shift + // just simple bit shift + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.LSRM, dt, value=knownAddress) + else + IRCodeInstruction(Opcode.LSRM, dt, labelSymbol = addressOfSymbol) } else if(pow2>=1 && !signed) { // just shift multiple bits val pow2reg = vmRegisters.nextFree() code += IRCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2) - code += if(signed) - IRCodeInstruction(Opcode.ASRNM, dt, reg1=pow2reg, value=address) - else - IRCodeInstruction(Opcode.LSRNM, dt, reg1=pow2reg, value=address) + code += if(signed) { + if(knownAddress!=null) + IRCodeInstruction(Opcode.ASRNM, dt, reg1 = pow2reg, value = knownAddress) + else + IRCodeInstruction(Opcode.ASRNM, dt, reg1 = pow2reg, labelSymbol = addressOfSymbol) + } + else { + if(knownAddress!=null) + IRCodeInstruction(Opcode.LSRNM, dt, reg1 = pow2reg, value = knownAddress) + else + IRCodeInstruction(Opcode.LSRNM, dt, reg1 = pow2reg, labelSymbol = addressOfSymbol) + } } else { if (factor == 0) { val reg = vmRegisters.nextFree() code += IRCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff) - code += IRCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=knownAddress) + else + IRCodeInstruction(Opcode.STOREM, dt, reg1=reg, labelSymbol = addressOfSymbol) } else { val factorReg = vmRegisters.nextFree() code += IRCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor) - code += if(signed) - IRCodeInstruction(Opcode.DIVSM, dt, reg1=factorReg, value=address) - else - IRCodeInstruction(Opcode.DIVM, dt, reg1=factorReg, value=address) + code += if(signed) { + if(knownAddress!=null) + IRCodeInstruction(Opcode.DIVSM, dt, reg1 = factorReg, value = knownAddress) + else + IRCodeInstruction(Opcode.DIVSM, dt, reg1 = factorReg, labelSymbol = addressOfSymbol) + } + else { + if(knownAddress!=null) + IRCodeInstruction(Opcode.DIVM, dt, reg1 = factorReg, value = knownAddress) + else + IRCodeInstruction(Opcode.DIVM, dt, reg1 = factorReg, labelSymbol = addressOfSymbol) + } } } return code @@ -772,7 +816,7 @@ class CodeGen(internal val program: PtProgram, val vmDt = vmType(postIncrDecr.target.type) if(ident!=null) { val address = addressOf(ident.targetName) - code += IRCodeInstruction(operationMem, vmDt, value = address) + code += IRCodeInstruction(operationMem, vmDt, labelSymbol = address) } else if(memory!=null) { if(memory.address is PtNumber) { val address = (memory.address as PtNumber).number.toInt() @@ -792,14 +836,14 @@ class CodeGen(internal val program: PtProgram, val fixedIndex = constIntValue(array.index) if(fixedIndex!=null) { variableAddr += fixedIndex*itemsize - code += IRCodeInstruction(operationMem, vmDt, value=variableAddr) + code += IRCodeInstruction(operationMem, vmDt, labelSymbol=variableAddr) } else { val incReg = vmRegisters.nextFree() val indexReg = vmRegisters.nextFree() code += expressionEval.translateExpression(array.index, indexReg, -1) - code += IRCodeInstruction(Opcode.LOADX, vmDt, reg1=incReg, reg2=indexReg, value=variableAddr) + code += IRCodeInstruction(Opcode.LOADX, vmDt, reg1=incReg, reg2=indexReg, labelSymbol=variableAddr) code += IRCodeInstruction(operationRegister, vmDt, reg1=incReg) - code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1=incReg, reg2=indexReg, value=variableAddr) + code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1=incReg, reg2=indexReg, labelSymbol=variableAddr) } } else throw AssemblyError("weird assigntarget") diff --git a/codeGenExperimental/src/prog8/codegen/experimental/ExpressionGen.kt b/codeGenExperimental/src/prog8/codegen/experimental/ExpressionGen.kt index a3171f6a8..9acd2acb3 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/ExpressionGen.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/ExpressionGen.kt @@ -30,21 +30,21 @@ internal class ExpressionGen(private val codeGen: CodeGen) { } is PtIdentifier -> { val vmDt = codeGen.vmType(expr.type) - val mem = codeGen.addressOf(expr.targetName) + val addrOf = codeGen.addressOf(expr.targetName) code += if (expr.type in PassByValueDatatypes) { if(vmDt==VmDataType.FLOAT) - IRCodeInstruction(Opcode.LOADM, vmDt, fpReg1 = resultFpRegister, value = mem) + IRCodeInstruction(Opcode.LOADM, vmDt, fpReg1 = resultFpRegister, labelSymbol = addrOf) else - IRCodeInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, value = mem) + IRCodeInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, labelSymbol = addrOf) } else { // for strings and arrays etc., load the *address* of the value instead - IRCodeInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, value = mem) + IRCodeInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = addrOf) } } is PtAddressOf -> { val vmDt = codeGen.vmType(expr.type) - val mem = codeGen.addressOf(expr.identifier.targetName) - code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=mem) + val addrOf = codeGen.addressOf(expr.identifier.targetName) + code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, labelSymbol = addrOf) } is PtMemoryByte -> { if(expr.address is PtNumber) { @@ -107,7 +107,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) { val vmDt = codeGen.vmType(arrayIx.type) val code = IRCodeChunk(arrayIx.position) val idxReg = codeGen.vmRegisters.nextFree() - val arrayLocation = codeGen.addressOf(arrayIx.variable.targetName) + val arrayLocationExpr = codeGen.addressOf(arrayIx.variable.targetName) if(arrayIx.variable.type==DataType.UWORD) { // indexing a pointer var instead of a real array or string @@ -116,25 +116,24 @@ internal class ExpressionGen(private val codeGen: CodeGen) { if(arrayIx.index.type!=DataType.UBYTE) throw AssemblyError("non-array var indexing requires bytes index") code += translateExpression(arrayIx.index, idxReg, -1) - code += IRCodeInstruction(Opcode.LOADIX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation) + code += IRCodeInstruction(Opcode.LOADIX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = arrayLocationExpr) return code } if(arrayIx.index is PtNumber) { - // optimized code when index is known - just calculate the memory address here - val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize + val memOffset = ((arrayIx.index as PtNumber).number.toInt() * eltSize).toString() if(vmDt==VmDataType.FLOAT) - code += IRCodeInstruction(Opcode.LOADM, VmDataType.FLOAT, fpReg1=resultFpRegister, value=arrayLocation+memOffset) + code += IRCodeInstruction(Opcode.LOADM, VmDataType.FLOAT, fpReg1=resultFpRegister, labelSymbol = "$arrayLocationExpr+$memOffset") else - code += IRCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=arrayLocation+memOffset) + code += IRCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, labelSymbol = "$arrayLocationExpr+$memOffset") } else { code += translateExpression(arrayIx.index, idxReg, -1) if(eltSize>1) code += codeGen.multiplyByConst(VmDataType.BYTE, idxReg, eltSize, arrayIx.position) if(vmDt==VmDataType.FLOAT) - code += IRCodeInstruction(Opcode.LOADX, VmDataType.FLOAT, fpReg1 = resultFpRegister, reg1=idxReg, value = arrayLocation) + code += IRCodeInstruction(Opcode.LOADX, VmDataType.FLOAT, fpReg1 = resultFpRegister, reg1=idxReg, labelSymbol = arrayLocationExpr) else - code += IRCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation) + code += IRCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = arrayLocationExpr) } return code } @@ -416,16 +415,22 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } - internal fun operatorShiftRightInplace(address: Int, vmDt: VmDataType, signed: Boolean, operand: PtExpression): IRCodeChunk { + internal fun operatorShiftRightInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, signed: Boolean, operand: PtExpression): IRCodeChunk { val code = IRCodeChunk(operand.position) if(codeGen.isOne(operand)) { val opc = if (signed) Opcode.ASRM else Opcode.LSRM - code += IRCodeInstruction(opc, vmDt, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(opc, vmDt, value=knownAddress) + else + IRCodeInstruction(opc, vmDt, labelSymbol = addressOfSymbol) } else { val operandReg = codeGen.vmRegisters.nextFree() code += translateExpression(operand, operandReg, -1) val opc = if (signed) Opcode.ASRNM else Opcode.LSRNM - code += IRCodeInstruction(opc, vmDt, reg1 = operandReg, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(opc, vmDt, reg1 = operandReg, value=knownAddress) + else + IRCodeInstruction(opc, vmDt, reg1 = operandReg, labelSymbol = addressOfSymbol) } return code } @@ -444,14 +449,20 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } - internal fun operatorShiftLeftInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { + internal fun operatorShiftLeftInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { val code = IRCodeChunk(operand.position) if(codeGen.isOne(operand)){ - code += IRCodeInstruction(Opcode.LSLM, vmDt, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.LSLM, vmDt, value=knownAddress) + else + IRCodeInstruction(Opcode.LSLM, vmDt, labelSymbol = addressOfSymbol) } else { val operandReg = codeGen.vmRegisters.nextFree() code += translateExpression(operand, operandReg, -1) - code += IRCodeInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, value=knownAddress) + else + IRCodeInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol) } return code } @@ -470,11 +481,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } - internal fun operatorXorInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { + internal fun operatorXorInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { val code = IRCodeChunk(operand.position) val operandReg = codeGen.vmRegisters.nextFree() code += translateExpression(operand, operandReg, -1) - code += IRCodeInstruction(Opcode.XORM, vmDt, reg1=operandReg, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.XORM, vmDt, reg1=operandReg, value = knownAddress) + else + IRCodeInstruction(Opcode.XORM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol) return code } @@ -492,11 +506,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } - internal fun operatorAndInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { + internal fun operatorAndInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { val code = IRCodeChunk(operand.position) val operandReg = codeGen.vmRegisters.nextFree() code += translateExpression(operand, operandReg, -1) - code += IRCodeInstruction(Opcode.ANDM, vmDt, reg1=operandReg, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.ANDM, vmDt, reg1=operandReg, value=knownAddress) + else + IRCodeInstruction(Opcode.ANDM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol) return code } @@ -514,11 +531,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } - internal fun operatorOrInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { + internal fun operatorOrInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { val code = IRCodeChunk(operand.position) val operandReg = codeGen.vmRegisters.nextFree() code += translateExpression(operand, operandReg, -1) - code += IRCodeInstruction(Opcode.ORM, vmDt, reg1=operandReg, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.ORM, vmDt, reg1=operandReg, value = knownAddress) + else + IRCodeInstruction(Opcode.ORM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol) return code } @@ -585,32 +605,48 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } - internal fun operatorDivideInplace(address: Int, vmDt: VmDataType, signed: Boolean, operand: PtExpression): IRCodeChunk { + internal fun operatorDivideInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, signed: Boolean, operand: PtExpression): IRCodeChunk { val code = IRCodeChunk(operand.position) val constFactorRight = operand as? PtNumber if(vmDt==VmDataType.FLOAT) { if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { val factor = constFactorRight.number.toFloat() - code += codeGen.divideByConstFloatInplace(address, factor, operand.position) + code += codeGen.divideByConstFloatInplace(knownAddress, addressOfSymbol, factor, operand.position) } else { val operandFpReg = codeGen.vmRegisters.nextFreeFloat() code += translateExpression(operand, -1, operandFpReg) - code += if(signed) - IRCodeInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, value=address) - else - IRCodeInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, value=address) + code += if(signed) { + if(knownAddress!=null) + IRCodeInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, value = knownAddress) + else + IRCodeInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, labelSymbol = addressOfSymbol) + } + else { + if(knownAddress!=null) + IRCodeInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, value = knownAddress) + else + IRCodeInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, labelSymbol = addressOfSymbol) + } } } else { if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { val factor = constFactorRight.number.toInt() - code += codeGen.divideByConstInplace(vmDt, address, factor, signed, operand.position) + code += codeGen.divideByConstInplace(vmDt, knownAddress, addressOfSymbol, factor, signed, operand.position) } else { val operandReg = codeGen.vmRegisters.nextFree() code += translateExpression(operand, operandReg, -1) - code += if(signed) - IRCodeInstruction(Opcode.DIVSM, vmDt, reg1=operandReg, value = address) - else - IRCodeInstruction(Opcode.DIVM, vmDt, reg1=operandReg, value = address) + code += if(signed) { + if(knownAddress!=null) + IRCodeInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, value = knownAddress) + else + IRCodeInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, labelSymbol = addressOfSymbol) + } + else { + if(knownAddress!=null) + IRCodeInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, value = knownAddress) + else + IRCodeInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, labelSymbol = addressOfSymbol) + } } } return code @@ -654,26 +690,32 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } - internal fun operatorMultiplyInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { + internal fun operatorMultiplyInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { val code = IRCodeChunk(operand.position) val constFactorRight = operand as? PtNumber if(vmDt==VmDataType.FLOAT) { if(constFactorRight!=null) { val factor = constFactorRight.number.toFloat() - code += codeGen.multiplyByConstFloatInplace(address, factor, constFactorRight.position) + code += codeGen.multiplyByConstFloatInplace(knownAddress, addressOfSymbol, factor, constFactorRight.position) } else { val operandFpReg = codeGen.vmRegisters.nextFreeFloat() code += translateExpression(operand, -1, operandFpReg) - code += IRCodeInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, value = knownAddress) + else + IRCodeInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, labelSymbol = addressOfSymbol) } } else { if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { val factor = constFactorRight.number.toInt() - code += codeGen.multiplyByConstInplace(vmDt, address, factor, constFactorRight.position) + code += codeGen.multiplyByConstInplace(vmDt, knownAddress, addressOfSymbol, factor, constFactorRight.position) } else { val operandReg = codeGen.vmRegisters.nextFree() code += translateExpression(operand, operandReg, -1) - code += IRCodeInstruction(Opcode.MULM, vmDt, reg1=operandReg, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.MULM, vmDt, reg1=operandReg, value = knownAddress) + else + IRCodeInstruction(Opcode.MULM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol) } } return code @@ -717,25 +759,37 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } - internal fun operatorMinusInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { + internal fun operatorMinusInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { val code = IRCodeChunk(operand.position) if(vmDt==VmDataType.FLOAT) { if((operand as? PtNumber)?.number==1.0) { - code += IRCodeInstruction(Opcode.DECM, vmDt, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.DECM, vmDt, value=knownAddress) + else + IRCodeInstruction(Opcode.DECM, vmDt, labelSymbol = addressOfSymbol) } else { val operandFpReg = codeGen.vmRegisters.nextFreeFloat() code += translateExpression(operand, -1, operandFpReg) - code += IRCodeInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, value=knownAddress) + else + IRCodeInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, labelSymbol = addressOfSymbol) } } else { if((operand as? PtNumber)?.number==1.0) { - code += IRCodeInstruction(Opcode.DECM, vmDt, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.DECM, vmDt, value=knownAddress) + else + IRCodeInstruction(Opcode.DECM, vmDt, labelSymbol = addressOfSymbol) } else { val operandReg = codeGen.vmRegisters.nextFree() code += translateExpression(operand, operandReg, -1) - code += IRCodeInstruction(Opcode.SUBM, vmDt, reg1=operandReg, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.SUBM, vmDt, reg1=operandReg, value = knownAddress) + else + IRCodeInstruction(Opcode.SUBM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol) } } return code @@ -787,25 +841,37 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } - internal fun operatorPlusInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { + internal fun operatorPlusInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk { val code = IRCodeChunk(operand.position) if(vmDt==VmDataType.FLOAT) { if((operand as? PtNumber)?.number==1.0) { - code += IRCodeInstruction(Opcode.INCM, vmDt, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.INCM, vmDt, value = knownAddress) + else + IRCodeInstruction(Opcode.INCM, vmDt, labelSymbol = addressOfSymbol) } else { val operandFpReg = codeGen.vmRegisters.nextFreeFloat() code += translateExpression(operand, -1, operandFpReg) - code += IRCodeInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, value = knownAddress) + else + IRCodeInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, labelSymbol = addressOfSymbol) } } else { if((operand as? PtNumber)?.number==1.0) { - code += IRCodeInstruction(Opcode.INCM, vmDt, value = address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.INCM, vmDt, value = knownAddress) + else + IRCodeInstruction(Opcode.INCM, vmDt, labelSymbol = addressOfSymbol) } else { val operandReg = codeGen.vmRegisters.nextFree() code += translateExpression(operand, operandReg, -1) - code += IRCodeInstruction(Opcode.ADDM, vmDt, reg1=operandReg, value=address) + code += if(knownAddress!=null) + IRCodeInstruction(Opcode.ADDM, vmDt, reg1=operandReg, value=knownAddress) + else + IRCodeInstruction(Opcode.ADDM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol) } } return code @@ -819,23 +885,23 @@ internal class ExpressionGen(private val codeGen: CodeGen) { val paramDt = codeGen.vmType(parameter.type) if(codeGen.isZero(arg)) { if (paramDt == VmDataType.FLOAT) { - val mem = codeGen.addressOf(fcall.functionName + parameter.name) - code += IRCodeInstruction(Opcode.STOREZM, paramDt, value = mem) + val addrOf = codeGen.addressOf(fcall.functionName + parameter.name) + code += IRCodeInstruction(Opcode.STOREZM, paramDt, labelSymbol = addrOf) } else { val mem = codeGen.addressOf(fcall.functionName + parameter.name) - code += IRCodeInstruction(Opcode.STOREZM, paramDt, value = mem) + code += IRCodeInstruction(Opcode.STOREZM, paramDt, labelSymbol = mem) } } else { if (paramDt == VmDataType.FLOAT) { val argFpReg = codeGen.vmRegisters.nextFreeFloat() code += translateExpression(arg, -1, argFpReg) - val mem = codeGen.addressOf(fcall.functionName + parameter.name) - code += IRCodeInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, value = mem) + val addrOf = codeGen.addressOf(fcall.functionName + parameter.name) + code += IRCodeInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, labelSymbol = addrOf) } else { val argReg = codeGen.vmRegisters.nextFree() code += translateExpression(arg, argReg, -1) - val mem = codeGen.addressOf(fcall.functionName + parameter.name) - code += IRCodeInstruction(Opcode.STOREM, paramDt, reg1 = argReg, value = mem) + val addrOf = codeGen.addressOf(fcall.functionName + parameter.name) + code += IRCodeInstruction(Opcode.STOREM, paramDt, reg1 = argReg, labelSymbol = addrOf) } } } diff --git a/codeGenExperimental/src/prog8/codegen/experimental/VmAssemblyProgram.kt b/codeGenExperimental/src/prog8/codegen/experimental/VmAssemblyProgram.kt index 5de5d0c84..42f6ade69 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/VmAssemblyProgram.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/VmAssemblyProgram.kt @@ -11,7 +11,7 @@ import kotlin.io.path.div class VmAssemblyProgram(override val name: String, val irProgram: IRProgram): IAssemblyProgram { // TODO once this is working, replace the codeGenVirtual by codeGenExperimental - // after that, remove the intermediate .p8ir file writing + // after that, add an option to the VmRunner to accept an IRProgram object directly and skip this intermediate .p8ir step when -emu is present override fun assemble(options: CompilationOptions): Boolean { @@ -48,7 +48,7 @@ class VmAssemblyProgram(override val name: String, val irProgram: IRProgram): IA out.write("; BLOCK ${block.name} ${block.position}\n") block.inlineAssembly.forEach { asm -> out.write("; ASM ${asm.position}\n") - out.write(asm.asm) + out.write(asm.assembly) out.write("\n") } block.subroutines.forEach { sub -> @@ -56,7 +56,9 @@ class VmAssemblyProgram(override val name: String, val irProgram: IRProgram): IA out.write("_${sub.name}:\n") sub.chunks.forEach { chunk -> if(chunk is IRInlineAsmChunk) { - out.write("; ASM ${chunk.position}\n${chunk.asm}\n") + out.write("; ASM ${chunk.position}\n") + out.write(processInlinedAsm(chunk.assembly, allocations)) + out.write("\n") } else { chunk.lines.forEach { out.writeLine(it) } } @@ -66,7 +68,7 @@ class VmAssemblyProgram(override val name: String, val irProgram: IRProgram): IA block.asmSubroutines.forEach { sub -> out.write("; ASMSUB ${sub.name} ${sub.position}\n") out.write("_${sub.name}:\n") - out.write(sub.assembly) + out.write(processInlinedAsm(sub.assembly, allocations)) out.write("\n; END ASMSUB ${sub.name}\n") } out.write("; END BLOCK ${block.name}\n") @@ -74,6 +76,14 @@ class VmAssemblyProgram(override val name: String, val irProgram: IRProgram): IA } return true } + + private fun processInlinedAsm(asm: String, allocations: VmVariableAllocator): String { + // need to replace &X by address of X. TODO: this actually needs to be done by the vm assembler/loader. Then this can be omitted + return asm.replace("""&[a-zA-Z\d_\.]+""".toRegex()) { matchResult -> + // replace "&X" with the address of X + val name = matchResult.value.substring(1, matchResult.value.length).split('.') + allocations.get(name).toString() } + } } private fun BufferedWriter.writeLine(line: IRCodeLine) { diff --git a/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt b/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt index cbf99b8ca..2bc3e42e1 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt @@ -49,7 +49,7 @@ class AssemblyProgram(override val name: String, private val allocations: Variab is VmCodeLabel -> write("_" + line.name.joinToString(".") + ":\n") is VmCodeInlineAsm -> { val asm = line.assembly.replace("""&[a-zA-Z\d_\.]+""".toRegex()) { matchResult -> - // "&X" -> address of X + // need to replace &X by address of X. TODO: this actually needs to be done by the vm assembler/loader. Then this can be omitted val name = matchResult.value.substring(1, matchResult.value.length).split('.') allocations.get(name).toString() } write(asm+"\n") diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 54c411ebc..416270b57 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,6 +3,8 @@ TODO For next release ^^^^^^^^^^^^^^^^ +- IR: fix superfluous usage of addressOf() +- IR: addressOfSymbol -> just 'symbol' - IR/VM: add address-of support (see CodeGen.addressOf()) syntax = &X - IR/VM: add proper memory mapped variables support - IR/VM: add proper memory slabs support diff --git a/intermediate/src/prog8/intermediate/IRFileReader.kt b/intermediate/src/prog8/intermediate/IRFileReader.kt index e13d9e272..64c13686e 100644 --- a/intermediate/src/prog8/intermediate/IRFileReader.kt +++ b/intermediate/src/prog8/intermediate/IRFileReader.kt @@ -322,7 +322,7 @@ class IRFileReader(outputDir: Path, programName: String) { clobberRegs.toSet(), params, returns, - asm.asm) + asm.assembly) } private fun parseSubroutine(startline: String, lines: Iterator, variables: List): IRSubroutine { diff --git a/intermediate/src/prog8/intermediate/IRFileWriter.kt b/intermediate/src/prog8/intermediate/IRFileWriter.kt index 50beb6dff..020f6523d 100644 --- a/intermediate/src/prog8/intermediate/IRFileWriter.kt +++ b/intermediate/src/prog8/intermediate/IRFileWriter.kt @@ -79,7 +79,7 @@ class IRFileWriter(private val irProgram: IRProgram) { private fun writeInlineAsm(chunk: IRInlineAsmChunk) { out.write("\n") - out.write(chunk.asm.trimStart('\n').trimEnd(' ', '\n')) + out.write(chunk.assembly.trimStart('\n').trimEnd(' ', '\n')) out.write("\n\n") } diff --git a/intermediate/src/prog8/intermediate/IRProgram.kt b/intermediate/src/prog8/intermediate/IRProgram.kt index ff7b87529..5c7024f54 100644 --- a/intermediate/src/prog8/intermediate/IRProgram.kt +++ b/intermediate/src/prog8/intermediate/IRProgram.kt @@ -191,9 +191,9 @@ class IRCodeChunk(position: Position): IRCodeChunkBase(position) { } } -class IRInlineAsmChunk(val asm: String, position: Position): IRCodeChunkBase(position) { +class IRInlineAsmChunk(val assembly: String, position: Position): IRCodeChunkBase(position) { // note: no lines, asm is in the property - override fun isEmpty() = asm.isBlank() - override fun isNotEmpty() = asm.isNotBlank() + override fun isEmpty() = assembly.isBlank() + override fun isNotEmpty() = assembly.isNotBlank() } diff --git a/intermediate/src/prog8/intermediate/Instructions.kt b/intermediate/src/prog8/intermediate/Instructions.kt index 653a039b3..8b3062461 100644 --- a/intermediate/src/prog8/intermediate/Instructions.kt +++ b/intermediate/src/prog8/intermediate/Instructions.kt @@ -477,7 +477,10 @@ data class Instruction( result.add(",") } labelSymbol?.let { - result.add("_" + it.joinToString(".")) + if(labelSymbol[0].startsWith('&')) + result.add(it.joinToString(".")) // address-of something + else + result.add("_" + it.joinToString(".")) } if(result.last() == ",") result.removeLast()