diff --git a/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt b/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt index a88c4a3c2..4a6265fd9 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt @@ -21,6 +21,7 @@ class ExperiCodeGen: ICodeGeneratorBackend { // but you can also use the Intermediate Representation to build a codegen on: val irCodeGen = IRCodeGen(program, symbolTable, options, errors) val irProgram = irCodeGen.generate() + irProgram.verifyRegisterTypes(irCodeGen.registerTypes()) // this stub only writes the IR program to disk but doesn't generate anything else. IRFileWriter(irProgram, null).write() diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index e9cd72cb1..7e2c99393 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -139,7 +139,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express val result = mutableListOf() if(constAddress==null && memory!=null) { - val register = codeGen.registers.next() + val register = codeGen.registers.next(vmDt) val tr = expressionEval.translateExpression(memory.address) addToResult(result, tr, tr.resultReg, -1) when(operator) { @@ -163,7 +163,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express "-" -> addInstr(result, IRInstruction(Opcode.NEGM, vmDt, address = constAddress, labelSymbol = symbol), null) "~" -> addInstr(result, IRInstruction(Opcode.INVM, vmDt, address = constAddress, labelSymbol = symbol), null) "not" -> { - val regMask = codeGen.registers.next() + val regMask = codeGen.registers.next(vmDt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=regMask, immediate = 1) it += IRInstruction(Opcode.XORM, vmDt, reg1=regMask, address = constAddress, labelSymbol = symbol) @@ -202,8 +202,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express addInstr(result, IRInstruction(Opcode.NEGM, IRDataType.BYTE, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex), skipCarryLabel) } else { val indexReg = loadIndex() - val registerLsb = codeGen.registers.next() - val registerMsb = codeGen.registers.next() + val registerLsb = codeGen.registers.next(IRDataType.BYTE) + val registerMsb = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1 = registerLsb, reg2 = indexReg, labelSymbol = array.variable.name+"_lsb") it += IRInstruction(Opcode.NEG, IRDataType.BYTE, reg1 = registerLsb) @@ -225,7 +225,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express addInstr(result, IRInstruction(Opcode.INVM, IRDataType.BYTE, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex), null) } else { val indexReg = loadIndex() - val register = codeGen.registers.next() + val register = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1 = register, reg2 = indexReg, labelSymbol = array.variable.name+"_lsb") it += IRInstruction(Opcode.INV, IRDataType.BYTE, reg1 = register) @@ -250,7 +250,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express addInstr(result, IRInstruction(Opcode.NEGM, vmDt, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize), null) } else { val indexReg = loadIndex() - val register = codeGen.registers.next() + val register = codeGen.registers.next(vmDt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADX, vmDt, reg1 = register, reg2 = indexReg, labelSymbol = array.variable.name) it += IRInstruction(Opcode.NEG, vmDt, reg1 = register) @@ -263,7 +263,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express addInstr(result, IRInstruction(Opcode.INVM, vmDt, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize), null) } else { val indexReg = loadIndex() - val register = codeGen.registers.next() + val register = codeGen.registers.next(vmDt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADX, vmDt, reg1 = register, reg2 = indexReg, labelSymbol = array.variable.name) it += IRInstruction(Opcode.INV, vmDt, reg1 = register) @@ -272,7 +272,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express } } "not" -> { - val register = codeGen.registers.next() + val register = codeGen.registers.next(vmDt) if(constIndex!=null) { result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=register, immediate = 1) @@ -321,7 +321,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express if (assignment.value is PtIrRegister) { valueRegister = (assignment.value as PtIrRegister).register if(extendByteToWord) { - valueRegister = codeGen.registers.next() + valueRegister = codeGen.registers.next(IRDataType.WORD) addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=valueRegister, reg2=(assignment.value as PtIrRegister).register), null) } } else { @@ -329,7 +329,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express valueRegister = tr.resultReg addToResult(result, tr, valueRegister, -1) if(extendByteToWord) { - valueRegister = codeGen.registers.next() + valueRegister = codeGen.registers.next(IRDataType.WORD) val opcode = if(assignment.value.type.isSigned) Opcode.EXTS else Opcode.EXT addInstr(result, IRInstruction(opcode, IRDataType.BYTE, reg1=valueRegister, reg2=tr.resultReg), null) } @@ -397,7 +397,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express if(fixedIndex!=null) { val chunk = IRCodeChunk(null, null).also { if(targetArray.splitWords) { - val lsbmsbReg = codeGen.registers.next() + val lsbmsbReg = codeGen.registers.next(IRDataType.BYTE) it += IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1 = lsbmsbReg, reg2 = valueRegister) it += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = lsbmsbReg, immediate = arrayLength, labelSymbol = "${variable}_lsb", symbolOffset = fixedIndex) it += IRInstruction(Opcode.MSIG, IRDataType.BYTE, reg1 = lsbmsbReg, reg2 = valueRegister) @@ -412,7 +412,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express result += code result += IRCodeChunk(null, null).also { if(targetArray.splitWords) { - val lsbmsbReg = codeGen.registers.next() + val lsbmsbReg = codeGen.registers.next(IRDataType.BYTE) it += IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1 = lsbmsbReg, reg2 = valueRegister) it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1 = lsbmsbReg, reg2=indexReg, immediate = arrayLength, labelSymbol = "${variable}_lsb") it += IRInstruction(Opcode.MSIG, IRDataType.BYTE, reg1 = lsbmsbReg, reg2 = valueRegister) @@ -451,7 +451,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express if((ptrWithOffset.right as? PtNumber)?.number?.toInt() in 0..255) { // STOREIX only works with byte index. val ptrName = (ptrWithOffset.left as PtIdentifier).name - val offsetReg = codeGen.registers.next() + val offsetReg = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = ptrWithOffset.right.asConstInteger()) it += IRInstruction(Opcode.STOREIX, IRDataType.BYTE, reg1=valueRegister, reg2=offsetReg, labelSymbol = ptrName) @@ -510,8 +510,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express val eltSize = codeGen.program.memsizer.memorySize(array.type, null) if(constIndex!=null && constValue!=null) { if(array.splitWords) { - val valueRegLsb = codeGen.registers.next() - val valueRegMsb = codeGen.registers.next() + val valueRegLsb = codeGen.registers.next(IRDataType.BYTE) + val valueRegMsb = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegLsb, immediate=constValue and 255) it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegMsb, immediate=constValue shr 8) @@ -519,7 +519,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express it += IRInstruction(Opcode.ANDM, vmDt, reg1=valueRegMsb, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex) } } else { - val valueReg = codeGen.registers.next() + val valueReg = codeGen.registers.next(vmDt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueReg, immediate=constValue) it += IRInstruction(Opcode.ANDM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) @@ -550,8 +550,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express val eltSize = codeGen.program.memsizer.memorySize(array.type, null) if(constIndex!=null && constValue!=null) { if(array.splitWords) { - val valueRegLsb = codeGen.registers.next() - val valueRegMsb = codeGen.registers.next() + val valueRegLsb = codeGen.registers.next(IRDataType.BYTE) + val valueRegMsb = codeGen.registers.next(IRDataType.BYTE) + require(vmDt==IRDataType.BYTE) { "ehh do we need a word or a byte type here?"} result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegLsb, immediate=constValue and 255) it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegMsb, immediate=constValue shr 8) @@ -559,7 +560,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express it += IRInstruction(Opcode.ANDM, vmDt, reg1=valueRegMsb, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex) } } else { - val valueReg = codeGen.registers.next() + val valueReg = codeGen.registers.next(vmDt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueReg, immediate=constValue) it += IRInstruction(Opcode.ANDM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) @@ -576,7 +577,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express val tr = expressionEval.translateExpression(operand) if(!operand.isSimple()) { // short-circuit LEFT and RIGHT --> if LEFT then RIGHT else LEFT (== if !LEFT then LEFT else RIGHT) - val inplaceReg = codeGen.registers.next() + val inplaceReg = codeGen.registers.next(vmDt) val shortcutLabel = codeGen.createLabelName() result += IRCodeChunk(null, null).also { it += if(constAddress!=null) @@ -610,8 +611,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express val eltSize = codeGen.program.memsizer.memorySize(array.type, null) if(constIndex!=null && constValue!=null) { if(array.splitWords) { - val valueRegLsb = codeGen.registers.next() - val valueRegMsb = codeGen.registers.next() + val valueRegLsb = codeGen.registers.next(IRDataType.BYTE) + val valueRegMsb = codeGen.registers.next(IRDataType.BYTE) + require(vmDt==IRDataType.BYTE) { "ehh do we need a word or a byte type here?"} result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegLsb, immediate=constValue and 255) it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegMsb, immediate=constValue shr 8) @@ -619,7 +621,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express it += IRInstruction(Opcode.ORM, vmDt, reg1=valueRegMsb, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex) } } else { - val valueReg = codeGen.registers.next() + val valueReg = codeGen.registers.next(vmDt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueReg, immediate=constValue) it += IRInstruction(Opcode.ORM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) @@ -650,8 +652,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express val eltSize = codeGen.program.memsizer.memorySize(array.type, null) if(constIndex!=null && constValue!=null) { if(array.splitWords) { - val valueRegLsb = codeGen.registers.next() - val valueRegMsb = codeGen.registers.next() + val valueRegLsb = codeGen.registers.next(IRDataType.BYTE) + val valueRegMsb = codeGen.registers.next(IRDataType.BYTE) + require(vmDt==IRDataType.BYTE) { "ehh do we need a word or a byte type here?"} result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegLsb, immediate=constValue and 255) it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegMsb, immediate=constValue shr 8) @@ -659,7 +662,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express it += IRInstruction(Opcode.ORM, vmDt, reg1=valueRegMsb, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex) } } else { - val valueReg = codeGen.registers.next() + val valueReg = codeGen.registers.next(vmDt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueReg, immediate=constValue) it += IRInstruction(Opcode.ORM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) @@ -676,7 +679,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express val tr = expressionEval.translateExpression(operand) if(!operand.isSimple()) { // short-circuit LEFT or RIGHT --> if LEFT then LEFT else RIGHT - val inplaceReg = codeGen.registers.next() + val inplaceReg = codeGen.registers.next(vmDt) val shortcutLabel = codeGen.createLabelName() result += IRCodeChunk(null, null).also { it += if(constAddress!=null) @@ -768,7 +771,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express val constValue = operand.asConstInteger() if(constIndex!=null && constValue!=null) { if(constValue!=1) { - val valueReg=codeGen.registers.next() + val valueReg=codeGen.registers.next(eltDt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, eltDt, reg1=valueReg, immediate = constValue) it += IRInstruction(Opcode.MULM, eltDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) @@ -826,7 +829,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express if(constValue==1) { addInstr(result, IRInstruction(Opcode.DECM, eltDt, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize), null) } else { - val valueReg=codeGen.registers.next() + val valueReg=codeGen.registers.next(eltDt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, eltDt, reg1=valueReg, immediate = constValue) it += IRInstruction(Opcode.SUBM, eltDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) @@ -889,7 +892,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express if(constIndex!=null) { val skip = codeGen.createLabelName() if(constValue==1) { - val lsbReg = codeGen.registers.next() + val lsbReg = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lsbReg, labelSymbol = array.variable.name+"_lsb", symbolOffset = constIndex) it += IRInstruction(Opcode.BSTNE, labelSymbol = skip) @@ -919,7 +922,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express if(constValue==1) { addInstr(result, IRInstruction(Opcode.INCM, elementDt, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize), null) } else { - val valueReg=codeGen.registers.next() + val valueReg=codeGen.registers.next(elementDt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, elementDt, reg1=valueReg, immediate = constValue) it += IRInstruction(Opcode.ADDM, elementDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) @@ -1054,8 +1057,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express val eltSize = codeGen.program.memsizer.memorySize(array.type, null) if(constIndex!=null && constValue!=null) { if(array.splitWords) { - val valueRegLsb = codeGen.registers.next() - val valueRegMsb = codeGen.registers.next() + val valueRegLsb = codeGen.registers.next(IRDataType.BYTE) + val valueRegMsb = codeGen.registers.next(IRDataType.BYTE) + require(vmDt==IRDataType.BYTE) { "ehh do we need a word or a byte type here?"} result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegLsb, immediate=constValue and 255) it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegMsb, immediate=constValue shr 8) @@ -1063,7 +1067,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express it += IRInstruction(Opcode.XORM, vmDt, reg1=valueRegMsb, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex) } } else { - val valueReg = codeGen.registers.next() + val valueReg = codeGen.registers.next(vmDt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueReg, immediate=constValue) it += IRInstruction(Opcode.XORM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) @@ -1095,7 +1099,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express return null // TODO("optimized memory in-place %"") val result = mutableListOf() - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(vmDt) if(operand is PtNumber) { val number = operand.number.toInt() if (constAddress != null) { diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index 057dcac31..454684d3c 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -59,7 +59,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe ExpressionCodeResult(result, resultType, -1, resultFpReg) } else { - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(resultType) addInstr(result, IRInstruction(Opcode.SQUARE, resultType, reg1 = resultReg, reg2 = valueTr.resultReg), null) ExpressionCodeResult(result, resultType, resultReg, -1) } @@ -73,7 +73,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe return if(call.void) ExpressionCodeResult(result, IRDataType.BYTE, -1, -1) else - ExpressionCodeResult(result, IRDataType.WORD, codeGen.registers.next(), -1) // TODO actually the result is returned in CPU registers AY... + ExpressionCodeResult(result, IRDataType.WORD, codeGen.registers.next(IRDataType.WORD), -1) // TODO actually the result is returned in CPU registers AY... } private fun funcCallfar(call: PtBuiltinFunctionCall): ExpressionCodeResult { @@ -123,7 +123,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe addToResult(result, tr, tr.resultReg, -1) addInstr(result, IRInstruction(Opcode.DIVMOD, type, reg1 = tr.resultReg, immediate = divident.number.toInt()), null) divisionReg = tr.resultReg - remainderReg = codeGen.registers.next() + remainderReg = codeGen.registers.next(type) } else { val numTr = exprGen.translateExpression(number) addToResult(result, numTr, numTr.resultReg, -1) @@ -148,7 +148,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val right = exprGen.translateExpression(call.args[1]) addToResult(result, left, left.resultReg, -1) addToResult(result, right, right.resultReg, -1) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) result += codeGen.makeSyscall(IMSyscall.COMPARE_STRINGS, listOf(IRDataType.WORD to left.resultReg, IRDataType.WORD to right.resultReg), IRDataType.BYTE to resultReg) return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) } @@ -177,7 +177,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe when (sourceDt.base) { BaseDataType.BYTE -> { val notNegativeLabel = codeGen.createLabelName() - val compareReg = codeGen.registers.next() + val compareReg = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=compareReg, reg2=tr.resultReg) it += IRInstruction(Opcode.BSTPOS, labelSymbol = notNegativeLabel) @@ -188,7 +188,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } BaseDataType.WORD -> { val notNegativeLabel = codeGen.createLabelName() - val compareReg = codeGen.registers.next() + val compareReg = codeGen.registers.next(IRDataType.WORD) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADR, IRDataType.WORD, reg1=compareReg, reg2=tr.resultReg) it += IRInstruction(Opcode.BSTPOS, labelSymbol = notNegativeLabel) @@ -209,7 +209,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe private fun funcSgn(call: PtBuiltinFunctionCall): ExpressionCodeResult { val result = mutableListOf() val tr = exprGen.translateExpression(call.args.single()) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(tr.dt) if(tr.dt==IRDataType.FLOAT) { addToResult(result, tr, -1, tr.resultFpReg) @@ -232,7 +232,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe when(dt.base) { BaseDataType.UBYTE -> { addToResult(result, tr, tr.resultReg, -1) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.SQRT, IRDataType.BYTE, reg1=resultReg, reg2=tr.resultReg) } @@ -240,7 +240,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } BaseDataType.UWORD -> { addToResult(result, tr, tr.resultReg, -1) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.WORD) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.SQRT, IRDataType.WORD, reg1=resultReg, reg2=tr.resultReg) } @@ -260,7 +260,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe private fun funcMkword(call: PtBuiltinFunctionCall): ExpressionCodeResult { val result = mutableListOf() - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.WORD) if((call.args[0] as? PtNumber)?.number == 0.0) { // msb is 0, use EXT val lsbTr = exprGen.translateExpression(call.args[1]) @@ -422,7 +422,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } } else { if (call.args[0] is PtNumber) { - val resultRegister = codeGen.registers.next() + val resultRegister = codeGen.registers.next(dt) val address = (call.args[0] as PtNumber).number.toInt() result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADM, dt, reg1 = resultRegister, address = address) @@ -431,7 +431,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } else { val tr = exprGen.translateExpression(call.args.single()) addToResult(result, tr, tr.resultReg, -1) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(dt) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADI, dt, reg1 = resultReg, reg2 = tr.resultReg) } @@ -473,7 +473,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } return if(address is PtNumber) { - val resultRegister = codeGen.registers.next() + val resultRegister = codeGen.registers.next(IRDataType.BYTE) val addressNum = address.number.toInt() result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1 = resultRegister, address = addressNum) @@ -483,7 +483,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } else { val addressTr = exprGen.translateExpression(address) addToResult(result, addressTr, addressTr.resultReg, -1) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADI, IRDataType.BYTE, reg1 = resultReg, reg2 = addressTr.resultReg) } @@ -496,7 +496,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe private fun funcMemory(call: PtBuiltinFunctionCall): ExpressionCodeResult { val name = (call.args[0] as PtString).value val code = IRCodeChunk(null, null) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.WORD) code += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=resultReg, labelSymbol = "prog8_slabs.prog8_memoryslab_$name") return ExpressionCodeResult(code, IRDataType.BYTE, resultReg, -1) } @@ -505,7 +505,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val result = mutableListOf() val tr = exprGen.translateExpression(call.args.single()) addToResult(result, tr, tr.resultReg, -1) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1 = resultReg, reg2 = tr.resultReg), null) // note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here. return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) @@ -515,7 +515,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val result = mutableListOf() val tr = exprGen.translateExpression(call.args.single()) addToResult(result, tr, tr.resultReg, -1) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) addInstr(result, IRInstruction(Opcode.MSIG, IRDataType.BYTE, reg1 = resultReg, reg2 = tr.resultReg), null) // note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here. return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) @@ -548,9 +548,9 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val arr = (arg as? PtArrayIndexer) val index = arr?.index?.asConstInteger() if(arr!=null && index!=null) { + val variable = arr.variable.name if(arr.splitWords) TODO("IR rol/ror on split words array") - val variable = arr.variable.name val offset = codeGen.program.memsizer.memorySize(arr.type, index) addInstr(result, IRInstruction(opcodeMemAndReg.first, vmDt, labelSymbol = variable, symbolOffset = offset), null) return ExpressionCodeResult(result, vmDt, -1, -1) @@ -581,7 +581,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe is PtIdentifier -> { if(isConstZeroValue) { result += IRCodeChunk(null, null).also { - val pointerReg = codeGen.registers.next() + val pointerReg = codeGen.registers.next(IRDataType.WORD) it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1 = pointerReg, labelSymbol = target.name) if (msb) it += IRInstruction(Opcode.INC, IRDataType.WORD, reg1 = pointerReg) @@ -591,7 +591,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val valueTr = exprGen.translateExpression(call.args[1]) addToResult(result, valueTr, valueTr.resultReg, -1) result += IRCodeChunk(null, null).also { - val pointerReg = codeGen.registers.next() + val pointerReg = codeGen.registers.next(IRDataType.WORD) it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1 = pointerReg, labelSymbol = target.name) if (msb) it += IRInstruction(Opcode.INC, IRDataType.WORD, reg1 = pointerReg) @@ -606,7 +606,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val varName = target.variable.name + if(msb) "_msb" else "_lsb" if(isConstZeroValue) { if(constIndex!=null) { - val offsetReg = codeGen.registers.next() + val offsetReg = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = constIndex) it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1=offsetReg, labelSymbol = varName) @@ -622,7 +622,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val valueTr = exprGen.translateExpression(call.args[1]) addToResult(result, valueTr, valueTr.resultReg, -1) if(constIndex!=null) { - val offsetReg = codeGen.registers.next() + val offsetReg = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = constIndex) it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=valueTr.resultReg, reg2=offsetReg, labelSymbol = varName) @@ -641,7 +641,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val constIndex = target.index.asConstInteger() if(isConstZeroValue) { if(constIndex!=null) { - val offsetReg = codeGen.registers.next() + val offsetReg = codeGen.registers.next(IRDataType.BYTE) val offset = eltSize*constIndex + if(msb) 1 else 0 result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = offset) @@ -662,7 +662,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val valueTr = exprGen.translateExpression(call.args[1]) addToResult(result, valueTr, valueTr.resultReg, -1) if(constIndex!=null) { - val offsetReg = codeGen.registers.next() + val offsetReg = codeGen.registers.next(IRDataType.BYTE) val offset = eltSize*constIndex + if(msb) 1 else 0 result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = offset) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index bd7147579..74d3932fa 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -33,7 +33,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } is PtBool -> { val code = IRCodeChunk(null, null) - val resultRegister = codeGen.registers.next() + val resultRegister = codeGen.registers.next(IRDataType.BYTE) code += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = resultRegister, immediate = expr.asInt()) ExpressionCodeResult(code, IRDataType.BYTE, resultRegister, -1) } @@ -46,7 +46,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { ExpressionCodeResult(code, vmDt,-1, resultFpRegister) } else { - val resultRegister = codeGen.registers.next() + val resultRegister = codeGen.registers.next(vmDt) code += IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, immediate = expr.number.toInt()) ExpressionCodeResult(code, vmDt, resultRegister, -1) } @@ -61,7 +61,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { ExpressionCodeResult(code, vmDt, -1, resultFpRegister) } else { - val resultRegister = codeGen.registers.next() + val resultRegister = codeGen.registers.next(vmDt) code += IRInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, labelSymbol = expr.name) ExpressionCodeResult(code, vmDt, resultRegister, -1) } @@ -69,7 +69,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { // for strings and arrays etc., load the *address* of the value instead // for arrays this could mean a split word array, in which case we take the address of the _lsb array which comes first val vmDt = if(expr.type.isUndefined) IRDataType.WORD else irType(expr.type) - val resultRegister = codeGen.registers.next() + val resultRegister = codeGen.registers.next(vmDt) val labelsymbol = if(expr.type.isSplitWordArray) expr.name+"_lsb" else expr.name code += IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = labelsymbol) ExpressionCodeResult(code, vmDt, resultRegister, -1) @@ -162,7 +162,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { val symbol = expr.identifier.name // note: LOAD gets you the address of the symbol, whereas LOADM would get you the value stored at that location val result = mutableListOf() - val resultRegister = codeGen.registers.next() + val resultRegister = codeGen.registers.next(vmDt) fun loadAddressOfArrayLabel(reg: Int) { if (expr.isMsbForSplitArray) { @@ -177,7 +177,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { if(expr.isFromArrayElement) { val indexTr = translateExpression(expr.arrayIndexExpr!!) addToResult(result, indexTr, indexTr.resultReg, -1) - val indexWordReg = codeGen.registers.next() + val indexWordReg = codeGen.registers.next(IRDataType.WORD) addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=indexWordReg, reg2=indexTr.resultReg), null) if(expr.identifier.type.isUnsignedWord) { require(!expr.isMsbForSplitArray) @@ -203,7 +203,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { private fun translate(mem: PtMemoryByte): ExpressionCodeResult { val result = mutableListOf() - val resultRegister = codeGen.registers.next() + val resultRegister = codeGen.registers.next(IRDataType.BYTE) val constAddress = mem.address as? PtNumber if(constAddress!=null) { @@ -216,7 +216,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { if((ptrWithOffset.right as? PtNumber)?.number?.toInt() in 0..255) { // LOADIX only works with byte index. val ptrName = (ptrWithOffset.left as PtIdentifier).name - val offsetReg = codeGen.registers.next() + val offsetReg = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = ptrWithOffset.right.asConstInteger()) it += IRInstruction(Opcode.LOADIX, IRDataType.BYTE, reg1=resultRegister, reg2=offsetReg, labelSymbol = ptrName) @@ -261,7 +261,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { val endLabel = codeGen.createLabelName() val elementTr = translateExpression(check.needle) addToResult(result, elementTr, elementTr.resultReg, -1) - val boolResultRegister = if(elementDt.isByteOrBool) elementTr.resultReg else codeGen.registers.next() + val boolResultRegister = if(elementDt.isByteOrBool) elementTr.resultReg else codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { for(value in haystack){ it += IRInstruction(Opcode.CMPI, irType(elementDt), elementTr.resultReg, immediate = value) @@ -287,7 +287,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addToResult(result, elementTr, elementTr.resultReg, -1) val iterableTr = translateExpression(haystackVar) addToResult(result, iterableTr, iterableTr.resultReg, -1) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) result += codeGen.makeSyscall(IMSyscall.STRING_CONTAINS, listOf(IRDataType.BYTE to elementTr.resultReg, IRDataType.WORD to iterableTr.resultReg), IRDataType.BYTE to resultReg) addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1=resultReg, immediate = 0), null) return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) @@ -298,10 +298,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addToResult(result, elementTr, elementTr.resultReg, -1) val iterableTr = translateExpression(haystackVar) addToResult(result, iterableTr, iterableTr.resultReg, -1) - val lengthReg = codeGen.registers.next() + val lengthReg = codeGen.registers.next(IRDataType.BYTE) val iterableLength = codeGen.symbolTable.getLength(haystackVar.name) addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=lengthReg, immediate = iterableLength!!), null) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) result += codeGen.makeSyscall(IMSyscall.BYTEARRAY_CONTAINS, listOf(IRDataType.BYTE to elementTr.resultReg, IRDataType.WORD to iterableTr.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to resultReg) addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1=resultReg, immediate = 0), null) return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) @@ -312,10 +312,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addToResult(result, elementTr, elementTr.resultReg, -1) val iterableTr = translateExpression(haystackVar) addToResult(result, iterableTr, iterableTr.resultReg, -1) - val lengthReg = codeGen.registers.next() + val lengthReg = codeGen.registers.next(IRDataType.BYTE) val iterableLength = codeGen.symbolTable.getLength(haystackVar.name) addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=lengthReg, immediate = iterableLength!!), null) - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) result += codeGen.makeSyscall(IMSyscall.WORDARRAY_CONTAINS, listOf(IRDataType.WORD to elementTr.resultReg, IRDataType.WORD to iterableTr.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to resultReg) addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1=resultReg, immediate = 0), null) return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) @@ -326,8 +326,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addToResult(result, elementTr, -1, elementTr.resultFpReg) val iterableTr = translateExpression(haystackVar) addToResult(result, iterableTr, iterableTr.resultReg, -1) - val lengthReg = codeGen.registers.next() - val resultReg = codeGen.registers.next() + val lengthReg = codeGen.registers.next(IRDataType.BYTE) + val resultReg = codeGen.registers.next(IRDataType.BYTE) val iterableLength = codeGen.symbolTable.getLength(haystackVar.name) addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=lengthReg, immediate = iterableLength!!), null) result += codeGen.makeSyscall(IMSyscall.FLOATARRAY_CONTAINS, listOf(IRDataType.FLOAT to elementTr.resultFpReg, IRDataType.WORD to iterableTr.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to resultReg) @@ -347,12 +347,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { if(arrayIx.splitWords) { require(vmDt==IRDataType.WORD) - resultRegister = codeGen.registers.next() - val finalResultReg = codeGen.registers.next() + resultRegister = codeGen.registers.next(IRDataType.BYTE) + val finalResultReg = codeGen.registers.next(IRDataType.WORD) if(arrayIx.index is PtNumber) { val memOffset = (arrayIx.index as PtNumber).number.toInt() result += IRCodeChunk(null, null).also { - val tmpRegMsb = codeGen.registers.next() + val tmpRegMsb = codeGen.registers.next(IRDataType.BYTE) it += IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=tmpRegMsb, labelSymbol= "${arrayVarSymbol}_msb", symbolOffset = memOffset) it += IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=resultRegister, labelSymbol= "${arrayVarSymbol}_lsb", symbolOffset = memOffset) it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=finalResultReg, reg2=tmpRegMsb, reg3=resultRegister) @@ -361,7 +361,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { val tr = translateExpression(arrayIx.index) addToResult(result, tr, tr.resultReg, -1) result += IRCodeChunk(null, null).also { - val tmpRegMsb = codeGen.registers.next() + val tmpRegMsb = codeGen.registers.next(IRDataType.BYTE) it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=tmpRegMsb, reg2 = tr.resultReg, labelSymbol= "${arrayVarSymbol}_msb") it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=resultRegister, reg2 = tr.resultReg, labelSymbol= "${arrayVarSymbol}_lsb") it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=finalResultReg, reg2=tmpRegMsb, reg3=resultRegister) @@ -378,7 +378,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addInstr(result, IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1=resultFpRegister, labelSymbol = arrayVarSymbol, symbolOffset = memOffset), null) } else { - resultRegister = codeGen.registers.next() + resultRegister = codeGen.registers.next(vmDt) addInstr(result, IRInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, labelSymbol = arrayVarSymbol, symbolOffset = memOffset), null) } } else { @@ -391,7 +391,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addInstr(result, IRInstruction(Opcode.LOADX, IRDataType.FLOAT, fpReg1 = resultFpRegister, reg1=tr.resultReg, labelSymbol = arrayVarSymbol), null) } else { - resultRegister = codeGen.registers.next() + resultRegister = codeGen.registers.next(vmDt) addInstr(result, IRInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=tr.resultReg, labelSymbol = arrayVarSymbol), null) } } @@ -443,7 +443,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { actualResultReg2 =loadStatusAsBooleanResult(Opcode.BSTNE, result) } valueDt.isFloat -> { - actualResultReg2 = codeGen.registers.next() + actualResultReg2 = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.SGN, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg) it += IRInstruction(Opcode.AND, IRDataType.BYTE, reg1=actualResultReg2, immediate = 1) @@ -458,11 +458,11 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { actualResultReg2 = tr.resultReg } BaseDataType.UWORD, BaseDataType.WORD -> { - actualResultReg2 = codeGen.registers.next() + actualResultReg2 = codeGen.registers.next(IRDataType.BYTE) addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null) } BaseDataType.FLOAT -> { - actualResultReg2 = codeGen.registers.next() + actualResultReg2 = codeGen.registers.next(IRDataType.BYTE) addInstr(result, IRInstruction(Opcode.FTOUB, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null) } else -> throw AssemblyError("weird cast value type") @@ -474,11 +474,11 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { actualResultReg2 = tr.resultReg } BaseDataType.UWORD, BaseDataType.WORD -> { - actualResultReg2 = codeGen.registers.next() + actualResultReg2 = codeGen.registers.next(IRDataType.BYTE) addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null) } BaseDataType.FLOAT -> { - actualResultReg2 = codeGen.registers.next() + actualResultReg2 = codeGen.registers.next(IRDataType.BYTE) addInstr(result, IRInstruction(Opcode.FTOSB, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null) } else -> throw AssemblyError("weird cast value type") @@ -488,19 +488,19 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { when(valueDt.base) { BaseDataType.BYTE -> { // byte -> uword: sign extend - actualResultReg2 = codeGen.registers.next() + actualResultReg2 = codeGen.registers.next(IRDataType.WORD) addInstr(result, IRInstruction(Opcode.EXTS, type = IRDataType.BYTE, reg1 = actualResultReg2, reg2 = tr.resultReg), null) } BaseDataType.BOOL, BaseDataType.UBYTE -> { // ubyte -> uword: sign extend - actualResultReg2 = codeGen.registers.next() + actualResultReg2 = codeGen.registers.next(IRDataType.WORD) addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.BYTE, reg1 = actualResultReg2, reg2 = tr.resultReg), null) } BaseDataType.WORD -> { actualResultReg2 = tr.resultReg } BaseDataType.FLOAT -> { - actualResultReg2 = codeGen.registers.next() + actualResultReg2 = codeGen.registers.next(IRDataType.WORD) addInstr(result, IRInstruction(Opcode.FTOUW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null) } else -> throw AssemblyError("weird cast value type") @@ -510,19 +510,19 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { when(valueDt.base) { BaseDataType.BYTE -> { // byte -> word: sign extend - actualResultReg2 = codeGen.registers.next() + actualResultReg2 = codeGen.registers.next(IRDataType.WORD) addInstr(result, IRInstruction(Opcode.EXTS, type = IRDataType.BYTE, reg1 = actualResultReg2, reg2=tr.resultReg), null) } BaseDataType.BOOL, BaseDataType.UBYTE -> { // byte -> word: sign extend - actualResultReg2 = codeGen.registers.next() + actualResultReg2 = codeGen.registers.next(IRDataType.WORD) addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.BYTE, reg1 = actualResultReg2, reg2=tr.resultReg), null) } BaseDataType.UWORD -> { actualResultReg2 = tr.resultReg } BaseDataType.FLOAT -> { - actualResultReg2 = codeGen.registers.next() + actualResultReg2 = codeGen.registers.next(IRDataType.WORD) addInstr(result, IRInstruction(Opcode.FTOSW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null) } else -> throw AssemblyError("weird cast value type") @@ -637,10 +637,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { // return value (always singular for normal Subs) val returnRegSpec = if(fcall.void) null else { val returnIrType = irType(callTarget.returnType!!) - if(returnIrType==IRDataType.FLOAT) - FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.next(IRDataType.FLOAT), null) - else - FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.next(), null) + FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.next(returnIrType), null) } // create the call addInstr(result, IRInstruction(Opcode.CALL, labelSymbol = fcall.name, @@ -696,12 +693,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { else { val returns = callTarget.returns[0] val returnIrType = irType(returns.type) - if (returnIrType == IRDataType.FLOAT) - FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.next(IRDataType.FLOAT), returns.register) - else { - val returnRegister = codeGen.registers.next() - FunctionCallArgs.RegSpec(returnIrType, returnRegister, returns.register) - } + FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.next(returnIrType), returns.register) } } // create the call @@ -731,7 +723,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { // assign status flag bit to the return value register finalReturnRegister = returnRegSpec.registerNum if(finalReturnRegister<0) - finalReturnRegister = codeGen.registers.next() + finalReturnRegister = codeGen.registers.next(returnRegSpec.dt) when(statusFlagResult) { Statusflag.Pc -> { result += IRCodeChunk(null, null).also { @@ -817,13 +809,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } "sys.pop" -> { // pop byte - val popReg = codeGen.registers.next() + val popReg = codeGen.registers.next(IRDataType.BYTE) addInstr(chunk, IRInstruction(Opcode.POP, IRDataType.BYTE, reg1=popReg), null) return ExpressionCodeResult(chunk, IRDataType.BYTE, popReg, -1) } "sys.popw" -> { // pop word - val popReg = codeGen.registers.next() + val popReg = codeGen.registers.next(IRDataType.WORD) addInstr(chunk, IRInstruction(Opcode.POP, IRDataType.WORD, reg1=popReg), null) return ExpressionCodeResult(chunk, IRDataType.WORD, popReg, -1) } @@ -852,7 +844,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { ): ExpressionCodeResult { // return multiple values val returnRegisters = callTarget.returns.map { - val regnum = if(it.type.isFloat) codeGen.registers.next(IRDataType.FLOAT) else codeGen.registers.next() + val regnum = codeGen.registers.next(irType(it.type)) FunctionCallArgs.RegSpec(irType(it.type), regnum, it.register) } // create the call @@ -888,12 +880,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addToResult(result, leftTr, -1, leftTr.resultFpReg) val rightTr = translateExpression(binExpr.right) addToResult(result, rightTr, -1, rightTr.resultFpReg) - val resultRegister = codeGen.registers.next() + val resultRegister = codeGen.registers.next(IRDataType.BYTE) addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null) addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1=resultRegister, immediate = 0), null) val other = codeGen.createLabelName() val after = codeGen.createLabelName() - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) // TODO can this be done more efficiently? also see operatorLessThan if(greaterEquals) { result += IRCodeChunk(null, null).also { @@ -944,12 +936,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addToResult(result, leftTr, -1, leftTr.resultFpReg) val rightTr = translateExpression(binExpr.right) addToResult(result, rightTr, -1, rightTr.resultFpReg) - val resultRegister = codeGen.registers.next() + val resultRegister = codeGen.registers.next(IRDataType.BYTE) addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null) addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1=resultRegister, immediate = 0), null) val other = codeGen.createLabelName() val after = codeGen.createLabelName() - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) // TODO can this be done more efficiently? also see operatorGreaterThan if(lessEquals) { result += IRCodeChunk(null, null).also { @@ -995,8 +987,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addToResult(result, leftTr, -1, leftTr.resultFpReg) val rightTr = translateExpression(binExpr.right) addToResult(result, rightTr, -1, rightTr.resultFpReg) - val resultRegister = codeGen.registers.next() - val valueReg = codeGen.registers.next() + val resultRegister = codeGen.registers.next(IRDataType.BYTE) + val valueReg = codeGen.registers.next(IRDataType.BYTE) val label = codeGen.createLabelName() result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 0) @@ -1038,7 +1030,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { // TODO this used to be a single instruction like SCC, SCS, SZ etc but those were problematic val other = codeGen.createLabelName() val after = codeGen.createLabelName() - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(branchForTrue, labelSymbol = other) it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = resultReg, immediate = 0) @@ -1053,7 +1045,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { // TODO this used to be a single instruction like SCC, SCS, SZ etc but those were problematic val other = codeGen.createLabelName() val after = codeGen.createLabelName() - val resultReg = codeGen.registers.next() + val resultReg = codeGen.registers.next(IRDataType.BYTE) result += IRCodeChunk(null, null).also { it += IRInstruction(branchForTrue, dt, reg1=reg1, reg2=reg2, labelSymbol = other) it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = resultReg, immediate = 0) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index b69868d26..577433329 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -471,8 +471,8 @@ class IRCodeGen( require(forLoop.variable.name == loopvar.scopedName) val iterableLength = symbolTable.getLength(iterable.name) val loopvarSymbol = forLoop.variable.name - val indexReg = registers.next() - val tmpReg = registers.next() + val indexReg = registers.next(IRDataType.BYTE) + val tmpReg = registers.next(IRDataType.BYTE) val loopLabel = createLabelName() val endLabel = createLabelName() when { @@ -498,9 +498,9 @@ class IRCodeGen( throw AssemblyError("weird dt") addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=indexReg, immediate = 0), null) result += IRCodeChunk(loopLabel, null).also { - val tmpRegLsb = registers.next() - val tmpRegMsb = registers.next() - val concatReg = registers.next() + val tmpRegLsb = registers.next(IRDataType.BYTE) + val tmpRegMsb = registers.next(IRDataType.BYTE) + val concatReg = registers.next(IRDataType.WORD) it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=tmpRegMsb, reg2=indexReg, labelSymbol=iterable.name+"_msb") it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=tmpRegLsb, reg2=indexReg, labelSymbol=iterable.name+"_lsb") it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=concatReg, reg2=tmpRegMsb, reg3=tmpRegLsb) @@ -636,7 +636,6 @@ class IRCodeGen( val loopLabel = createLabelName() require(forLoop.variable.name == loopvar.scopedName) val loopvarSymbol = forLoop.variable.name - val indexReg = registers.next() val loopvarDt = when(loopvar) { is StMemVar -> loopvar.dt is StStaticVariable -> loopvar.dt @@ -652,6 +651,7 @@ class IRCodeGen( val rangeEndExclusiveWrapped = if(loopvarDtIr==IRDataType.BYTE) rangeEndExclusiveUntyped and 255 else rangeEndExclusiveUntyped and 65535 val result = mutableListOf() val chunk = IRCodeChunk(null, null) + val indexReg = registers.next(loopvarDtIr) chunk += IRInstruction(Opcode.LOAD, loopvarDtIr, reg1=indexReg, immediate = iterable.first) chunk += IRInstruction(Opcode.STOREM, loopvarDtIr, reg1=indexReg, labelSymbol=loopvarSymbol) result += chunk @@ -744,7 +744,7 @@ class IRCodeGen( } } else -> { - val valueReg = registers.next() + val valueReg = registers.next(dt) if(value>0) { code += IRInstruction(Opcode.LOAD, dt, reg1=valueReg, immediate = value) code += if(knownAddress!=null) @@ -807,7 +807,7 @@ class IRCodeGen( } else if(pow2>=1) { // just shift multiple bits - val pow2reg = registers.next() + val pow2reg = registers.next(IRDataType.BYTE) code += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=pow2reg, immediate = pow2) code += IRInstruction(Opcode.LSLN, dt, reg1=reg, reg2=pow2reg) } else { @@ -834,7 +834,7 @@ class IRCodeGen( } else if(pow2>=1) { // just shift multiple bits - val pow2reg = registers.next() + val pow2reg = registers.next(dt) code += IRInstruction(Opcode.LOAD, dt, reg1=pow2reg, immediate = pow2) code += if(knownAddress!=null) IRInstruction(Opcode.LSLNM, dt, reg1=pow2reg, address = knownAddress) @@ -848,7 +848,7 @@ class IRCodeGen( IRInstruction(Opcode.STOREZM, dt, labelSymbol = symbol) } else { - val factorReg = registers.next() + val factorReg = registers.next(dt) code += IRInstruction(Opcode.LOAD, dt, reg1=factorReg, immediate = factor) code += if(knownAddress!=null) IRInstruction(Opcode.MULM, dt, reg1=factorReg, address = knownAddress) @@ -905,7 +905,7 @@ class IRCodeGen( code += IRInstruction(Opcode.ASR, dt, reg1=reg) } else { // just shift multiple bits (signed) - val pow2reg = registers.next() + val pow2reg = registers.next(IRDataType.BYTE) code += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=pow2reg, immediate = pow2) code += IRInstruction(Opcode.ASRN, dt, reg1=reg, reg2=pow2reg) } @@ -915,7 +915,7 @@ class IRCodeGen( code += IRInstruction(Opcode.LSR, dt, reg1=reg) } else { // just shift multiple bits (unsigned) - val pow2reg = registers.next() + val pow2reg = registers.next(IRDataType.BYTE) code += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = pow2reg, immediate = pow2) code += IRInstruction(Opcode.LSRN, dt, reg1 = reg, reg2 = pow2reg) } @@ -951,7 +951,7 @@ class IRCodeGen( IRInstruction(Opcode.ASRM, dt, labelSymbol = symbol) } else { // just shift multiple bits (signed) - val pow2reg = registers.next() + val pow2reg = registers.next(dt) code += IRInstruction(Opcode.LOAD, dt, reg1 = pow2reg, immediate = pow2) code += if (knownAddress != null) IRInstruction(Opcode.ASRNM, dt, reg1 = pow2reg, address = knownAddress) @@ -968,7 +968,7 @@ class IRCodeGen( } else { // just shift multiple bits (unsigned) - val pow2reg = registers.next() + val pow2reg = registers.next(dt) code += IRInstruction(Opcode.LOAD, dt, reg1=pow2reg, immediate = pow2) code += if(knownAddress!=null) IRInstruction(Opcode.LSRNM, dt, reg1 = pow2reg, address = knownAddress) @@ -982,7 +982,7 @@ class IRCodeGen( { // regular div if (factor == 0) { - val reg = registers.next() + val reg = registers.next(dt) code += IRInstruction(Opcode.LOAD, dt, reg1=reg, immediate = 0xffff) code += if(knownAddress!=null) IRInstruction(Opcode.STOREM, dt, reg1=reg, address = knownAddress) @@ -990,7 +990,7 @@ class IRCodeGen( IRInstruction(Opcode.STOREM, dt, reg1=reg, labelSymbol = symbol) } else { - val factorReg = registers.next() + val factorReg = registers.next(dt) code += IRInstruction(Opcode.LOAD, dt, reg1=factorReg, immediate = factor) code += if(signed) { if(knownAddress!=null) @@ -1036,7 +1036,7 @@ class IRCodeGen( addToResult(result, rightTr, -1, rightTr.resultFpReg) var afterIfLabel = "" result += IRCodeChunk(null, null).also { - val compResultReg = registers.next() + val compResultReg = registers.next(IRDataType.BYTE) it += IRInstruction( Opcode.FCOMP, IRDataType.FLOAT, @@ -1398,7 +1398,7 @@ class IRCodeGen( addToResult(result, leftTr, -1, leftTr.resultFpReg) val rightTr = expressionEval.translateExpression(condition.right) addToResult(result, rightTr, -1, rightTr.resultFpReg) - val compResultReg = registers.next() + val compResultReg = registers.next(IRDataType.BYTE) addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1 = compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null) val elseBranch: Opcode var useCmpi = false // for the branch opcodes that have been converted to CMPI + BSTxx form already @@ -1690,7 +1690,7 @@ class IRCodeGen( val result = mutableListOf() if(constRepeats==65536) { // make use of the word wrap around to count to 65536 - val resultRegister = registers.next() + val resultRegister = registers.next(IRDataType.WORD) addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=resultRegister, immediate = 0), null) result += labelFirstChunk(translateNode(repeat.statements), repeatLabel) result += IRCodeChunk(null, null).also { @@ -1890,4 +1890,6 @@ class IRCodeGen( it += IRInstruction(Opcode.SYSCALL, immediate = syscall.number, fcallArgs = FunctionCallArgs(args, returnSpec)) } } + + fun registerTypes(): Map = registers.getTypes() } diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt index 3ea8770e7..e0cfd7e84 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt @@ -355,20 +355,6 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) { return changed } - private fun regUsages(register: Int): Map { - val chunks = mutableMapOf() - irprog.foreachSub { sub -> - sub.chunks.forEach { chunk -> - val used = chunk.usedRegisters() - val numUsages = used.readRegs.getOrDefault(register, 0) + used.writeRegs.getOrDefault(register, 0) - if(numUsages>0) { - chunks[chunk] = numUsages - } - } - } - return chunks - } - private fun removeUselessArithmetic(chunk: IRCodeChunk, indexedInstructions: List>): Boolean { // note: this is hard to solve for the non-immediate instructions atm because the values are loaded into registers first var changed = false diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/RegisterPool.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/RegisterPool.kt index 4f2c8bbe9..880ac385f 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/RegisterPool.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/RegisterPool.kt @@ -4,21 +4,20 @@ import prog8.code.core.AssemblyError import prog8.intermediate.IRDataType internal class RegisterPool { - private var nextRegister: Int=1 - private val registerTypes: MutableMap = mutableMapOf() - // everything from 99000 onwards is reserved for special purposes: // 99000 - 99099 : WORD registers for syscall arguments and response value(s) // 99100 - 99199 : BYTE registers for syscall arguments and response value(s) + private var nextRegister: Int=1 + private val registerTypes: MutableMap = mutableMapOf() - fun next(): Int { - if(nextRegister>=99000) - throw AssemblyError("register pool depleted") - val result = nextRegister - // registerTypes[result] = type // TODO: make callers of this one supply the integer type they want as well and register it here - nextRegister++ - return result + fun getTypes(): Map = registerTypes + + init { + for(i in 99000..99099) + registerTypes[i] = IRDataType.WORD + for(i in 99100..99199) + registerTypes[i] = IRDataType.BYTE } fun next(type: IRDataType): Int { diff --git a/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt index 8eb528dbc..c69fb905d 100644 --- a/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt @@ -19,12 +19,18 @@ class VmCodeGen: ICodeGeneratorBackend { ): IAssemblyProgram { val irCodeGen = IRCodeGen(program, symbolTable, options, errors) val irProgram = irCodeGen.generate() + + irProgram.verifyRegisterTypes(irCodeGen.registerTypes()) + return VmAssemblyProgram(irProgram.name, irProgram) } } -internal class VmAssemblyProgram(override val name: String, internal val irProgram: IRProgram): IAssemblyProgram { +internal class VmAssemblyProgram( + override val name: String, + internal val irProgram: IRProgram +): IAssemblyProgram { override fun assemble(options: CompilationOptions, errors: IErrorReporter): Boolean { // the VM reads the IR file from disk. diff --git a/compiler/res/prog8lib/virtual/floats.p8 b/compiler/res/prog8lib/virtual/floats.p8 index 1d853f98c..5f8cbd1df 100644 --- a/compiler/res/prog8lib/virtual/floats.p8 +++ b/compiler/res/prog8lib/virtual/floats.p8 @@ -48,8 +48,8 @@ sub tostr(float value) -> str { load.w r99000,floats.tostr.buffer loadm.f fr99000,floats.tostr.value syscall 34 (r99000.w, fr99000.f) - load.w r0,floats.tostr.buffer - returnr.w r0 + load.w r99000,floats.tostr.buffer + returnr.w r99000 }} } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 97d3e0ee9..5c16d7e1a 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -46,7 +46,6 @@ Future Things and Ideas IR/VM ----- - getting it in shape for code generation...: the IR file should be able to encode every detail about a prog8 program (the VM doesn't have to actually be able to run all of it though!) -- registerPool should have separate pools, one for byte and word registers each (and 1 for floats)? - add BZ and BNZ instructions? To replace CMPI #0 + Branch? - fix TODO("IR rol/ror on split words array") - fix "<< in array" / ">> in array" diff --git a/examples/test.p8 b/examples/test.p8 index e23538e19..7751e737c 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,55 +4,7 @@ main { sub start() { - ubyte bb, index - uword ww - index=2 - - ww = 1234 - cx16.r0=10000 - - cx16.r0 -= ww - txt.print_uw(cx16.r0) ; 7532 + txt.print_uw(cx16.r0) txt.nl() - cx16.r0 += ww - txt.print_uw(cx16.r0) ; 10000 - txt.nl() - cx16.r0 &= ww - txt.print_uw(cx16.r0) ; 10000 - txt.nl() - -; bb += tabb[index] -; bb -= index -; bb -= tabb[index] -; bb &= tabb[index] -; bb |= tabb[index] -; bb ^= tabb[index] -; bb *= tabb[index] -; -; cx16.r0L = bb + tabb[index] -; cx16.r1L = bb - index -; cx16.r2L = bb - tabb[index] -; cx16.r3L = bb & tabb[index] -; cx16.r4L = bb | tabb[index] -; cx16.r5L = bb ^ tabb[index] -; cx16.r6L = bb * tabb[index] - -; ww += tabw[index] -; ww -= tabw[index] -; ww &= tabw[index] -; ww |= tabw[index] -; ww ^= tabw[index] -; ww *= tabw[index] -; -; cx16.r0 = ww + tabw[index] -; cx16.r1 = ww - cx16.r0 -; cx16.r2 = ww - tabw[index] -; cx16.r3 = ww & tabw[index] -; cx16.r4 = ww | tabw[index] -; cx16.r5 = ww ^ tabw[index] -; cx16.r6 = ww * tabw[index] - - ubyte[] tabb = [11,22,33,44,55,66] - uword[] tabw = [111,222,333,444,555,666] } } diff --git a/intermediate/src/prog8/intermediate/IRFileWriter.kt b/intermediate/src/prog8/intermediate/IRFileWriter.kt index d686c58bf..b8fd1aa92 100644 --- a/intermediate/src/prog8/intermediate/IRFileWriter.kt +++ b/intermediate/src/prog8/intermediate/IRFileWriter.kt @@ -19,9 +19,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) { private var numChunks = 0 private var numInstr = 0 - fun write(): Path { - println("Writing intermediate representation to $outfile") xml.writeStartDocument("utf-8", "1.0") xml.writeEndDocument() diff --git a/intermediate/src/prog8/intermediate/IRProgram.kt b/intermediate/src/prog8/intermediate/IRProgram.kt index 8b98cedc2..cddaa5ecd 100644 --- a/intermediate/src/prog8/intermediate/IRProgram.kt +++ b/intermediate/src/prog8/intermediate/IRProgram.kt @@ -368,6 +368,24 @@ class IRProgram(val name: String, } } } + + fun verifyRegisterTypes(registerTypes: Map) { + for(block in blocks) { + for(bc in block.children) { + when(bc) { + is IRAsmSubroutine -> bc.usedRegisters().validate(registerTypes, null) + is IRCodeChunk -> bc.usedRegisters().validate(registerTypes, bc) + is IRInlineAsmChunk -> bc.usedRegisters().validate(registerTypes, bc) + is IRInlineBinaryChunk -> bc.usedRegisters().validate(registerTypes, bc) + is IRSubroutine -> { + for(sc in bc.chunks) { + sc.usedRegisters().validate(registerTypes, sc) + } + } + } + } + } + } } class IRBlock( @@ -551,6 +569,15 @@ class RegistersUsed( fun used(register: Int) = register in readRegs || register in writeRegs fun usedFp(fpRegister: Int) = fpRegister in readFpRegs || fpRegister in writeFpRegs + + fun validate(allowed: Map, chunk: IRCodeChunkBase?) { + for((reg, type) in regsTypes) { + if(allowed[reg]==null) + throw IllegalArgumentException("Reg type mismatch for register $reg type $type: no type known. CodeChunk=$chunk label ${chunk?.label}") + if(allowed[reg]!=type) + throw IllegalArgumentException("Reg type mismatch for register $reg type $type: expected ${allowed[reg]}. CodeChunk=$chunk label ${chunk?.label}") + } + } } private fun registersUsedInAssembly(isIR: Boolean, assembly: String): RegistersUsed {