diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index c32d0003a..734e1cac1 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -142,13 +142,15 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express // calculate the assignment value if (vmDt == IRDataType.FLOAT) { resultFpRegister = codeGen.registers.nextFreeFloat() - result += expressionEval.translateExpression(assignment.value, -1, resultFpRegister) + val tr = expressionEval.translateExpression(assignment.value, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) } else { resultRegister = if (assignment.value is PtMachineRegister) { (assignment.value as PtMachineRegister).register } else { val reg = codeGen.registers.nextFree() - result += expressionEval.translateExpression(assignment.value, reg, -1) + val tr = expressionEval.translateExpression(assignment.value, reg, -1) + addToResult(result, tr, reg, -1) reg } } @@ -176,7 +178,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express if(array.index.type!=DataType.UBYTE) throw AssemblyError("non-array var indexing requires bytes index") val idxReg = codeGen.registers.nextFree() - result += expressionEval.translateExpression(array.index, idxReg, -1) + val tr = expressionEval.translateExpression(array.index, idxReg, -1) + addToResult(result, tr, idxReg, -1) val code = IRCodeChunk(null, null) if(zero) { // there's no STOREZIX instruction @@ -232,7 +235,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express result += chunk } else { val addressReg = codeGen.registers.nextFree() - result += expressionEval.translateExpression(memory.address, addressReg, -1) + val tr = expressionEval.translateExpression(memory.address, addressReg, -1) + addToResult(result, tr, addressReg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZI, vmDt, reg1=addressReg) } } } else { @@ -241,7 +245,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express result += chunk } else { val addressReg = codeGen.registers.nextFree() - result += expressionEval.translateExpression(memory.address, addressReg, -1) + val tr = expressionEval.translateExpression(memory.address, addressReg, -1) + addToResult(result, tr, addressReg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressReg) } } } @@ -253,7 +258,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express } private fun loadIndexReg(array: PtArrayIndexer, itemsize: Int, indexReg: Int): IRCodeChunks { - return if(itemsize==1) { + val tr = if(itemsize==1) { expressionEval.translateExpression(array.index, indexReg, -1) } else { val mult = PtBinaryExpression("*", DataType.UBYTE, array.position) @@ -261,5 +266,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express mult.children += PtNumber(DataType.UBYTE, itemsize.toDouble(), array.position) expressionEval.translateExpression(mult, indexReg, -1) } + require(tr.resultReg==indexReg && tr.resultFpReg==-1) // TODO weg + return tr.chunks } } \ No newline at end of file diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index ce18f7b33..6713828ed 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -9,48 +9,113 @@ import prog8.intermediate.* internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGen: ExpressionGen) { - fun translate(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks { - return when(call.name) { - "any" -> funcAny(call, resultRegister) - "all" -> funcAll(call, resultRegister) - "abs" -> funcAbs(call, resultRegister) - "cmp" -> funcCmp(call) - "sgn" -> funcSgn(call, resultRegister) - "sqrt16" -> funcSqrt16(call, resultRegister) - "pop" -> funcPop(call) - "popw" -> funcPopw(call) - "push" -> funcPush(call) - "pushw" -> funcPushw(call) + fun translate(call: PtBuiltinFunctionCall): ExpressionCodeResult { + when(call.name) { + "any" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcAny(call, resultRegister), IRDataType.BYTE, resultRegister, -1) + } + "all" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcAll(call, resultRegister), IRDataType.BYTE, resultRegister, -1) + } + "abs" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcAbs(call, resultRegister), codeGen.irType(call.args[0].type), resultRegister, -1) + } + "cmp" -> { + return ExpressionCodeResult(funcCmp(call), codeGen.irType(call.args[0].type), -1, -1) + } + "sgn" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcSgn(call, resultRegister), codeGen.irType(call.type), resultRegister, -1) + } + "sqrt16" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcSqrt16(call, resultRegister), IRDataType.WORD, resultRegister, -1) + } + "pop" -> { + return ExpressionCodeResult(funcPop(call), IRDataType.BYTE, -1, -1) + } + "popw" -> { + return ExpressionCodeResult(funcPopw(call), IRDataType.WORD, -1, -1) + } + "push" -> { + return ExpressionCodeResult(funcPush(call), IRDataType.BYTE, -1, -1) + } + "pushw" -> { + return ExpressionCodeResult(funcPushw(call), IRDataType.BYTE,-1, -1) + } "rsave", "rsavex", "rrestore", - "rrestorex" -> emptyList() // vm doesn't have registers to save/restore + "rrestorex" -> { + return ExpressionCodeResult.EMPTY // vm doesn't have registers to save/restore + } "callfar" -> throw AssemblyError("callfar() is for cx16 target only") - "msb" -> funcMsb(call, resultRegister) - "lsb" -> funcLsb(call, resultRegister) - "memory" -> funcMemory(call, resultRegister) - "peek" -> funcPeek(call, resultRegister) - "peekw" -> funcPeekW(call, resultRegister) - "poke" -> funcPoke(call) - "pokew" -> funcPokeW(call) - "pokemon" -> emptyList() - "mkword" -> funcMkword(call, resultRegister) - "sort" -> funcSort(call) - "reverse" -> funcReverse(call) - "rol" -> funcRolRor(Opcode.ROXL, call, resultRegister) - "ror" -> funcRolRor(Opcode.ROXR, call, resultRegister) - "rol2" -> funcRolRor(Opcode.ROL, call, resultRegister) - "ror2" -> funcRolRor(Opcode.ROR, call, resultRegister) + "msb" -> return funcMsb(call) + "lsb" -> return funcLsb(call) + "memory" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcMemory(call, resultRegister), IRDataType.WORD, resultRegister, -1) + } + "peek" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcPeek(call, resultRegister), IRDataType.BYTE, resultRegister, -1) + } + "peekw" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcPeekW(call, resultRegister), IRDataType.WORD, resultRegister, -1) + } + "poke" -> { + return ExpressionCodeResult(funcPoke(call), IRDataType.BYTE, -1, -1) + } + "pokew" -> { + return ExpressionCodeResult(funcPokeW(call), IRDataType.BYTE,-1, -1) + } + "pokemon" -> { + return ExpressionCodeResult(emptyList(), IRDataType.BYTE, -1, -1) + } + "mkword" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcMkword(call, resultRegister), IRDataType.WORD, resultRegister, -1) + } + "sort" -> { + return ExpressionCodeResult(funcSort(call), IRDataType.BYTE, -1, -1) + } + "reverse" -> { + return ExpressionCodeResult(funcReverse(call), IRDataType.BYTE, -1, -1) + } + "rol" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcRolRor(Opcode.ROXL, call, resultRegister), codeGen.irType(call.args[0].type), resultRegister, -1) + } + "ror" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcRolRor(Opcode.ROXR, call, resultRegister), codeGen.irType(call.args[0].type), resultRegister, -1) + } + "rol2" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcRolRor(Opcode.ROL, call, resultRegister), codeGen.irType(call.args[0].type), resultRegister, -1) + } + "ror2" -> { + val resultRegister = codeGen.registers.nextFree() + return ExpressionCodeResult(funcRolRor(Opcode.ROR, call, resultRegister), codeGen.irType(call.args[0].type), resultRegister, -1) + } else -> throw AssemblyError("missing builtinfunc for ${call.name}") } } + // TODO let all funcs return ExpressionCodeResult as well + private fun funcCmp(call: PtBuiltinFunctionCall): IRCodeChunks { val leftRegister = codeGen.registers.nextFree() val rightRegister = codeGen.registers.nextFree() val result = mutableListOf() - result += exprGen.translateExpression(call.args[0], leftRegister, -1) - result += exprGen.translateExpression(call.args[1], rightRegister, -1) + var tr = exprGen.translateExpression(call.args[0], leftRegister, -1) + addToResult(result, tr, leftRegister, -1) + tr = exprGen.translateExpression(call.args[1], rightRegister, -1) + addToResult(result, tr, rightRegister, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.CMP, codeGen.irType(call.args[0].type), reg1=leftRegister, reg2=rightRegister) } @@ -70,7 +135,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe else -> throw IllegalArgumentException("weird type") } val result = mutableListOf() - result += exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1) + val tr = exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1) + addToResult(result, tr, SyscallRegisterBase, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = SyscallRegisterBase+1, value = array.length) it += IRInstruction(Opcode.SYSCALL, value = syscall.number) @@ -93,7 +159,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe else -> throw IllegalArgumentException("weird type") } val result = mutableListOf() - result += exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1) + val tr = exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1) + addToResult(result, tr, SyscallRegisterBase, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = SyscallRegisterBase+1, value = array.length) it += IRInstruction(Opcode.SYSCALL, value = syscall.number) @@ -107,7 +174,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val sourceDt = call.args.single().type val result = mutableListOf() if(sourceDt!=DataType.UWORD) { - result += exprGen.translateExpression(call.args[0], resultRegister, -1) + val tr = exprGen.translateExpression(call.args[0], resultRegister, -1) + addToResult(result, tr, resultRegister, -1) when (sourceDt) { DataType.UBYTE -> { result += IRCodeChunk(null, null).also { @@ -146,7 +214,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe private fun funcSgn(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks { val reg = codeGen.registers.nextFree() val result = mutableListOf() - result += exprGen.translateExpression(call.args.single(), reg, -1) + val tr = exprGen.translateExpression(call.args.single(), reg, -1) + addToResult(result, tr, reg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.SGN, codeGen.irType(call.type), reg1 = resultRegister, reg2 = reg) } @@ -156,7 +225,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe private fun funcSqrt16(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks { val reg = codeGen.registers.nextFree() val result = mutableListOf() - result += exprGen.translateExpression(call.args.single(), reg, -1) + val tr = exprGen.translateExpression(call.args.single(), reg, -1) + addToResult(result, tr, reg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.SQRT, IRDataType.WORD, reg1=resultRegister, reg2=reg) } @@ -184,7 +254,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe private fun funcPush(call: PtBuiltinFunctionCall): IRCodeChunks { val result = mutableListOf() val reg = codeGen.registers.nextFree() - result += exprGen.translateExpression(call.args.single(), reg, -1) + val tr = exprGen.translateExpression(call.args.single(), reg, -1) + addToResult(result, tr, reg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.PUSH, IRDataType.BYTE, reg1=reg) } @@ -194,7 +265,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe private fun funcPushw(call: PtBuiltinFunctionCall): IRCodeChunks { val result = mutableListOf() val reg = codeGen.registers.nextFree() - result += exprGen.translateExpression(call.args.single(), reg, -1) + val tr = exprGen.translateExpression(call.args.single(), reg, -1) + addToResult(result, tr, reg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1 = reg) } @@ -212,7 +284,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe else -> throw IllegalArgumentException("weird type to reverse") } val result = mutableListOf() - result += exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1) + val tr = exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1) + addToResult(result, tr, SyscallRegisterBase, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = SyscallRegisterBase+1, value = array.length) it += IRInstruction(Opcode.SYSCALL, value = syscall.number) @@ -234,7 +307,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe else -> throw IllegalArgumentException("weird type to sort") } val result = mutableListOf() - result += exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1) + val tr = exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1) + addToResult(result, tr, SyscallRegisterBase, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = SyscallRegisterBase+1, value = array.length) it += IRInstruction(Opcode.SYSCALL, value = syscall.number) @@ -245,8 +319,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe private fun funcMkword(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks { val msbReg = codeGen.registers.nextFree() val result = mutableListOf() - result += exprGen.translateExpression(call.args[0], msbReg, -1) - result += exprGen.translateExpression(call.args[1], resultRegister, -1) + var tr = exprGen.translateExpression(call.args[0], msbReg, -1) + addToResult(result, tr, msbReg, -1) + tr = exprGen.translateExpression(call.args[1], resultRegister, -1) + addToResult(result, tr, resultRegister, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1 = resultRegister, reg2 = msbReg) } @@ -263,7 +339,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } } else { val addressReg = codeGen.registers.nextFree() - result += exprGen.translateExpression(call.args[0], addressReg, -1) + val tr = exprGen.translateExpression(call.args[0], addressReg, -1) + addToResult(result, tr, addressReg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZI, IRDataType.WORD, reg1 = addressReg) } @@ -272,14 +349,17 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val valueReg = codeGen.registers.nextFree() if (call.args[0] is PtNumber) { val address = (call.args[0] as PtNumber).number.toInt() - result += exprGen.translateExpression(call.args[1], valueReg, -1) + val tr = exprGen.translateExpression(call.args[1], valueReg, -1) + addToResult(result, tr, valueReg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, IRDataType.WORD, reg1 = valueReg, value = address) } } else { val addressReg = codeGen.registers.nextFree() - result += exprGen.translateExpression(call.args[0], addressReg, -1) - result += exprGen.translateExpression(call.args[1], valueReg, -1) + var tr = exprGen.translateExpression(call.args[0], addressReg, -1) + addToResult(result, tr, addressReg, -1) + tr = exprGen.translateExpression(call.args[1], valueReg, -1) + addToResult(result, tr, valueReg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREI, IRDataType.WORD, reg1 = valueReg, reg2 = addressReg) } @@ -298,7 +378,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } } else { val addressReg = codeGen.registers.nextFree() - result += exprGen.translateExpression(call.args[0], addressReg, -1) + val tr = exprGen.translateExpression(call.args[0], addressReg, -1) + addToResult(result, tr, addressReg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZI, IRDataType.BYTE, reg1 = addressReg) } @@ -307,14 +388,17 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val valueReg = codeGen.registers.nextFree() if (call.args[0] is PtNumber) { val address = (call.args[0] as PtNumber).number.toInt() - result += exprGen.translateExpression(call.args[1], valueReg, -1) + val tr = exprGen.translateExpression(call.args[1], valueReg, -1) + addToResult(result, tr, valueReg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = valueReg, value = address) } } else { val addressReg = codeGen.registers.nextFree() - result += exprGen.translateExpression(call.args[0], addressReg, -1) - result += exprGen.translateExpression(call.args[1], valueReg, -1) + var tr = exprGen.translateExpression(call.args[0], addressReg, -1) + addToResult(result, tr, addressReg, -1) + tr = exprGen.translateExpression(call.args[1], valueReg, -1) + addToResult(result, tr, valueReg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREI, IRDataType.BYTE, reg1 = valueReg, reg2 = addressReg) } @@ -332,7 +416,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } } else { val addressReg = codeGen.registers.nextFree() - result += exprGen.translateExpression(call.args.single(), addressReg, -1) + val tr = exprGen.translateExpression(call.args.single(), addressReg, -1) + addToResult(result, tr, addressReg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADI, IRDataType.WORD, reg1 = resultRegister, reg2 = addressReg) } @@ -349,7 +434,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } } else { val addressReg = codeGen.registers.nextFree() - result += exprGen.translateExpression(call.args.single(), addressReg, -1) + val tr = exprGen.translateExpression(call.args.single(), addressReg, -1) + addToResult(result, tr, addressReg, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOADI, IRDataType.BYTE, reg1 = resultRegister, reg2 = addressReg) } @@ -364,25 +450,29 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe return listOf(code) } - private fun funcLsb(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks { + private fun funcLsb(call: PtBuiltinFunctionCall): ExpressionCodeResult { + val resultRegister = codeGen.registers.nextFree() return exprGen.translateExpression(call.args.single(), resultRegister, -1) // note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here. } - private fun funcMsb(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks { + private fun funcMsb(call: PtBuiltinFunctionCall): ExpressionCodeResult { val result = mutableListOf() - result += exprGen.translateExpression(call.args.single(), resultRegister, -1) + val resultRegister = codeGen.registers.nextFree() + val tr = exprGen.translateExpression(call.args.single(), resultRegister, -1) + addToResult(result, tr, resultRegister, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.MSIG, IRDataType.BYTE, reg1 = resultRegister, reg2 = resultRegister) } // note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here. - return result + return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) } private fun funcRolRor(opcode: Opcode, call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks { val vmDt = codeGen.irType(call.args[0].type) val result = mutableListOf() - result += exprGen.translateExpression(call.args[0], resultRegister, -1) + val tr = exprGen.translateExpression(call.args[0], resultRegister, -1) + addToResult(result, tr, resultRegister, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(opcode, vmDt, reg1 = resultRegister) } diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 06f44e9ab..bff25e4dd 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -10,9 +10,16 @@ import prog8.code.core.PassByValueDatatypes import prog8.code.core.SignedDatatypes import prog8.intermediate.* +internal class ExpressionCodeResult(val chunks: IRCodeChunks, val dt: IRDataType, val resultReg: Int, val resultFpReg: Int) { + constructor(chunks: IRCodeChunk, dt: IRDataType, resultReg: Int, resultFpReg: Int) : this(listOf(chunks), dt, resultReg, resultFpReg) + + companion object { + val EMPTY: ExpressionCodeResult = ExpressionCodeResult(emptyList(), IRDataType.BYTE, -1, -1) + } +} internal class ExpressionGen(private val codeGen: IRCodeGen) { - fun translateExpression(expr: PtExpression, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { + fun translateExpression(expr: PtExpression, resultRegister: Int, resultFpRegister: Int): ExpressionCodeResult { require(codeGen.registers.peekNext() > resultRegister || resultRegister >= SyscallRegisterBase) { "no more registers for expression ${expr.position}" } @@ -26,33 +33,40 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { val vmDt = codeGen.irType(expr.type) val code = IRCodeChunk(null, null) code += IRInstruction(Opcode.LOADR, vmDt, reg1=resultRegister, reg2=expr.register) - listOf(code) + ExpressionCodeResult(code, vmDt, resultRegister, -1) } else { - emptyList() + ExpressionCodeResult.EMPTY } } is PtNumber -> { val vmDt = codeGen.irType(expr.type) val code = IRCodeChunk(null, null) - code += if(vmDt==IRDataType.FLOAT) - IRInstruction(Opcode.LOAD, vmDt, fpReg1 = resultFpRegister, fpValue = expr.number.toFloat()) - else - IRInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=expr.number.toInt()) - listOf(code) + if(vmDt==IRDataType.FLOAT) { + code += IRInstruction(Opcode.LOAD, vmDt, fpReg1 = resultFpRegister, fpValue = expr.number.toFloat()) + ExpressionCodeResult(code, vmDt,-1, resultFpRegister) + } + else { + code += IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, value = expr.number.toInt()) + ExpressionCodeResult(code, vmDt, resultRegister, -1) + } } is PtIdentifier -> { val vmDt = codeGen.irType(expr.type) val code = IRCodeChunk(null, null) - code += if (expr.type in PassByValueDatatypes) { - if(vmDt==IRDataType.FLOAT) - IRInstruction(Opcode.LOADM, vmDt, fpReg1 = resultFpRegister, labelSymbol = expr.name) - else - IRInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, labelSymbol = expr.name) + if (expr.type in PassByValueDatatypes) { + if(vmDt==IRDataType.FLOAT) { + code += IRInstruction(Opcode.LOADM, vmDt, fpReg1 = resultFpRegister, labelSymbol = expr.name) + ExpressionCodeResult(code, vmDt, -1, resultFpRegister) + } + else { + code += IRInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, labelSymbol = expr.name) + ExpressionCodeResult(code, vmDt, resultRegister, -1) + } } else { // for strings and arrays etc., load the *address* of the value instead - IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = expr.name) + code += IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = expr.name) + ExpressionCodeResult(code, vmDt, resultRegister, -1) } - listOf(code) } is PtAddressOf -> { val vmDt = codeGen.irType(expr.type) @@ -60,7 +74,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { // note: LOAD gets you the address of the symbol, whereas LOADM would get you the value stored at that location val code = IRCodeChunk(null, null) code += IRInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, labelSymbol = symbol) - listOf(code) + ExpressionCodeResult(code, vmDt, resultRegister, -1) } is PtMemoryByte -> { val result = mutableListOf() @@ -69,16 +83,17 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addInstr(result, IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=resultRegister, value = address), null) } else { val addressRegister = codeGen.registers.nextFree() - result += translateExpression(expr.address, addressRegister, -1) + val translated = translateExpression(expr.address, addressRegister, -1) + addToResult(result, translated, addressRegister, -1) addInstr(result, IRInstruction(Opcode.LOADI, IRDataType.BYTE, reg1=resultRegister, reg2=addressRegister), null) } - result + ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) } is PtTypeCast -> translate(expr, resultRegister, resultFpRegister) is PtPrefix -> translate(expr, resultRegister, resultFpRegister) is PtArrayIndexer -> translate(expr, resultRegister, resultFpRegister) is PtBinaryExpression -> translate(expr, resultRegister, resultFpRegister) - is PtBuiltinFunctionCall -> codeGen.translateBuiltinFunc(expr, resultRegister) + is PtBuiltinFunctionCall -> codeGen.translateBuiltinFunc(expr) is PtFunctionCall -> translate(expr, resultRegister, resultFpRegister) is PtContainmentCheck -> translate(expr, resultRegister, resultFpRegister) is PtRange, @@ -88,14 +103,17 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } } - private fun translate(check: PtContainmentCheck, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { + private fun translate(check: PtContainmentCheck, resultRegister: Int, resultFpRegister: Int): ExpressionCodeResult { val result = mutableListOf() - result += translateExpression(check.element, resultRegister, -1) // load the element to check in resultRegister + var translated = translateExpression(check.element, resultRegister, -1) // load the element to check in resultRegister + addToResult(result, translated, resultRegister, -1) val iterable = codeGen.symbolTable.flat.getValue(check.iterable.name) as StStaticVariable when(iterable.dt) { DataType.STR -> { - result += translateExpression(check.element, SyscallRegisterBase, -1) - result += translateExpression(check.iterable, SyscallRegisterBase+1, -1) + translated = translateExpression(check.element, SyscallRegisterBase, -1) + addToResult(result, translated, SyscallRegisterBase, -1) + translated = translateExpression(check.iterable, SyscallRegisterBase+1, -1) + addToResult(result, translated, SyscallRegisterBase+1, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.STRING_CONTAINS.number) if(resultRegister!=0) @@ -103,8 +121,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } } DataType.ARRAY_UB, DataType.ARRAY_B -> { - result += translateExpression(check.element, SyscallRegisterBase, -1) - result += translateExpression(check.iterable, SyscallRegisterBase+1, -1) + translated = translateExpression(check.element, SyscallRegisterBase, -1) + addToResult(result, translated, SyscallRegisterBase, -1) + translated = translateExpression(check.iterable, SyscallRegisterBase+1, -1) + addToResult(result, translated, SyscallRegisterBase+1, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=SyscallRegisterBase+2, value = iterable.length!!) it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.BYTEARRAY_CONTAINS.number) @@ -113,8 +133,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } } DataType.ARRAY_UW, DataType.ARRAY_W -> { - result += translateExpression(check.element, SyscallRegisterBase, -1) - result += translateExpression(check.iterable, SyscallRegisterBase+1, -1) + translated = translateExpression(check.element, SyscallRegisterBase, -1) + addToResult(result, translated, SyscallRegisterBase, -1) + translated = translateExpression(check.iterable, SyscallRegisterBase+1, -1) + addToResult(result, translated, SyscallRegisterBase+1, -1) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=SyscallRegisterBase+2, value = iterable.length!!) it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.WORDARRAY_CONTAINS.number) @@ -125,10 +147,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { DataType.ARRAY_F -> throw AssemblyError("containment check in float-array not supported") else -> throw AssemblyError("weird iterable dt ${iterable.dt} for ${check.iterable.name}") } - return result + return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) } - private fun translate(arrayIx: PtArrayIndexer, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { + private fun translate(arrayIx: PtArrayIndexer, resultRegister: Int, resultFpRegister: Int): ExpressionCodeResult { val eltSize = codeGen.program.memsizer.memorySize(arrayIx.type) val vmDt = codeGen.irType(arrayIx.type) val result = mutableListOf() @@ -141,9 +163,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { throw AssemblyError("non-array var indexing requires bytes dt") if(arrayIx.index.type!=DataType.UBYTE) throw AssemblyError("non-array var indexing requires bytes index") - result += translateExpression(arrayIx.index, idxReg, -1) + val translated = translateExpression(arrayIx.index, idxReg, -1) + addToResult(result, translated, idxReg, -1) addInstr(result, IRInstruction(Opcode.LOADIX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = arrayVarSymbol), null) - return result + return ExpressionCodeResult(result, vmDt, resultRegister, resultFpRegister) } if(arrayIx.index is PtNumber) { @@ -153,7 +176,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { else addInstr(result, IRInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, labelSymbol = "$arrayVarSymbol+$memOffset"), null) } else { - result += translateExpression(arrayIx.index, idxReg, -1) + val translated = translateExpression(arrayIx.index, idxReg, -1) + addToResult(result, translated, idxReg, -1) if(eltSize>1) result += codeGen.multiplyByConst(IRDataType.BYTE, idxReg, eltSize) if(vmDt==IRDataType.FLOAT) @@ -161,12 +185,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { else addInstr(result, IRInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = arrayVarSymbol), null) } - return result + return ExpressionCodeResult(result, vmDt, resultRegister, resultFpRegister) } - private fun translate(expr: PtPrefix, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { + private fun translate(expr: PtPrefix, resultRegister: Int, resultFpRegister: Int): ExpressionCodeResult { val result = mutableListOf() - result += translateExpression(expr.value, resultRegister, resultFpRegister) + val translated = translateExpression(expr.value, resultRegister, resultFpRegister) + addToResult(result, translated, resultRegister, resultFpRegister) val vmDt = codeGen.irType(expr.type) when(expr.operator) { "+" -> { } @@ -182,21 +207,25 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } else -> throw AssemblyError("weird prefix operator") } - return result + return ExpressionCodeResult(result, vmDt, resultRegister, resultFpRegister) } - private fun translate(cast: PtTypeCast, predefinedResultRegister: Int, predefinedResultFpRegister: Int): IRCodeChunks { + private fun translate(cast: PtTypeCast, resultRegister: Int, resultFpRegister: Int): ExpressionCodeResult { if(cast.type==cast.value.type) - return emptyList() + return ExpressionCodeResult.EMPTY val result = mutableListOf() - val actualResultFpReg = if(predefinedResultFpRegister>=0) predefinedResultFpRegister else codeGen.registers.nextFreeFloat() - val actualResultReg = if(predefinedResultRegister>=0) predefinedResultRegister else codeGen.registers.nextFree() - if(cast.value.type==DataType.FLOAT) { + val actualResultFpReg = if(resultFpRegister>=0) resultFpRegister else codeGen.registers.nextFreeFloat() + val actualResultReg = if(resultRegister>=0) resultRegister else codeGen.registers.nextFree() + result += if(cast.value.type==DataType.FLOAT) { // a cast from float to integer, so evaluate the value into a float register first - result += translateExpression(cast.value, -1, actualResultFpReg) + val translated = translateExpression(cast.value, -1, actualResultFpReg) + require(translated.resultReg==-1 && translated.resultFpReg==actualResultFpReg) + translated.chunks + } else { + val translated = translateExpression(cast.value, actualResultReg, -1) + require(translated.resultReg==actualResultReg && translated.resultFpReg==-1) + translated.chunks } - else - result += translateExpression(cast.value, actualResultReg, -1) when(cast.type) { DataType.UBYTE -> { when(cast.value.type) { @@ -258,13 +287,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } else -> throw AssemblyError("weird cast type") } - return result + return ExpressionCodeResult(result, codeGen.irType(cast.type), actualResultReg, actualResultFpReg) } - private fun translate(binExpr: PtBinaryExpression, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { + private fun translate(binExpr: PtBinaryExpression, resultRegister: Int, resultFpRegister: Int): ExpressionCodeResult { val vmDt = codeGen.irType(binExpr.left.type) val signed = binExpr.left.type in SignedDatatypes - return when(binExpr.operator) { + // TODO fix the operator methods return type as well + val code = when(binExpr.operator) { "+" -> operatorPlus(binExpr, vmDt, resultRegister, resultFpRegister) "-" -> operatorMinus(binExpr, vmDt, resultRegister, resultFpRegister) "*" -> operatorMultiply(binExpr, vmDt, resultRegister, resultFpRegister) @@ -283,657 +313,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { ">=" -> operatorGreaterThan(binExpr, vmDt, resultRegister, signed, true) else -> throw AssemblyError("weird operator ${binExpr.operator}") } + return ExpressionCodeResult(code, vmDt, resultRegister, resultFpRegister) } - private fun operatorGreaterThan( - binExpr: PtBinaryExpression, - vmDt: IRDataType, - resultRegister: Int, - signed: Boolean, - greaterEquals: Boolean - ): IRCodeChunks { - val result = mutableListOf() - if(vmDt==IRDataType.FLOAT) { - val leftFpReg = codeGen.registers.nextFreeFloat() - val rightFpReg = codeGen.registers.nextFreeFloat() - val zeroRegister = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, -1, leftFpReg) - result += translateExpression(binExpr.right, -1, rightFpReg) - addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg), null) - addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroRegister, value=0), null) - val ins = if (signed) { - if (greaterEquals) Opcode.SGES else Opcode.SGTS - } else { - if (greaterEquals) Opcode.SGE else Opcode.SGT - } - addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister), null) - } else { - if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) { - result += translateExpression(binExpr.left, SyscallRegisterBase, -1) - result += translateExpression(binExpr.right, SyscallRegisterBase+1, -1) - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number) - if(resultRegister!=0) - it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0) - it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = 0) - it += if (greaterEquals) - IRInstruction(Opcode.SGES, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1) - else - IRInstruction(Opcode.SGTS, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1) - } - } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - val ins = if (signed) { - if (greaterEquals) Opcode.SGES else Opcode.SGTS - } else { - if (greaterEquals) Opcode.SGE else Opcode.SGT - } - addInstr(result, IRInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) - } - } - return result - } - - private fun operatorLessThan( - binExpr: PtBinaryExpression, - vmDt: IRDataType, - resultRegister: Int, - signed: Boolean, - lessEquals: Boolean - ): IRCodeChunks { - val result = mutableListOf() - if(vmDt==IRDataType.FLOAT) { - val leftFpReg = codeGen.registers.nextFreeFloat() - val rightFpReg = codeGen.registers.nextFreeFloat() - val zeroRegister = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, -1, leftFpReg) - result += translateExpression(binExpr.right, -1, rightFpReg) - addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg), null) - addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroRegister, value=0), null) - val ins = if (signed) { - if (lessEquals) Opcode.SLES else Opcode.SLTS - } else { - if (lessEquals) Opcode.SLE else Opcode.SLT - } - addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister), null) - } else { - if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) { - result += translateExpression(binExpr.left, SyscallRegisterBase, -1) - result += translateExpression(binExpr.right, SyscallRegisterBase+1, -1) - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number) - if(resultRegister!=0) - it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0) - it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = 0) - it += if (lessEquals) - IRInstruction(Opcode.SLES, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1) - else - IRInstruction(Opcode.SLTS, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1) - } - } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - val ins = if (signed) { - if (lessEquals) Opcode.SLES else Opcode.SLTS - } else { - if (lessEquals) Opcode.SLE else Opcode.SLT - } - addInstr(result, IRInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) - } - } - return result - } - - private fun operatorEquals(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int, notEquals: Boolean): IRCodeChunks { - val result = mutableListOf() - if(vmDt==IRDataType.FLOAT) { - val leftFpReg = codeGen.registers.nextFreeFloat() - val rightFpReg = codeGen.registers.nextFreeFloat() - result += translateExpression(binExpr.left, -1, leftFpReg) - result += translateExpression(binExpr.right, -1, rightFpReg) - if (notEquals) { - addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg), null) - } else { - val label = codeGen.createLabelName() - val valueReg = codeGen.registers.nextFree() - addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=1), null) - addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=valueReg, fpReg1 = leftFpReg, fpReg2 = rightFpReg), null) - addInstr(result, IRInstruction(Opcode.BZ, IRDataType.BYTE, reg1=valueReg, labelSymbol = label), null) - addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=0), null) - result += IRCodeChunk(label, null) - } - } else { - if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) { - result += translateExpression(binExpr.left, SyscallRegisterBase, -1) - result += translateExpression(binExpr.right, SyscallRegisterBase+1, -1) - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number) - if(resultRegister!=0) - it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0) - if (!notEquals) - it += IRInstruction(Opcode.INV, vmDt, reg1 = resultRegister) - it += IRInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value = 1) - } - } else { - if(constValue(binExpr.right)==0.0) { - result += translateExpression(binExpr.left, resultRegister, -1) - val opcode = if (notEquals) Opcode.SNZ else Opcode.SZ - addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = resultRegister), null) - } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ - addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) - } - } - } - return result - } - - private fun operatorShiftRight(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int, signed: Boolean): IRCodeChunks { - val result = mutableListOf() - if(codeGen.isOne(binExpr.right)) { - result += translateExpression(binExpr.left, resultRegister, -1) - val opc = if (signed) Opcode.ASR else Opcode.LSR - addInstr(result, IRInstruction(opc, vmDt, reg1 = resultRegister), null) - } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - val opc = if (signed) Opcode.ASRN else Opcode.LSRN - addInstr(result, IRInstruction(opc, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) - } - return result - } - - internal fun operatorShiftRightInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks { - val result = mutableListOf() - if(codeGen.isOne(operand)) { - val opc = if (signed) Opcode.ASRM else Opcode.LSRM - val ins = if(knownAddress!=null) - IRInstruction(opc, vmDt, value=knownAddress) - else - IRInstruction(opc, vmDt, labelSymbol = symbol) - addInstr(result, ins, null) - } else { - val operandReg = codeGen.registers.nextFree() - result += translateExpression(operand, operandReg, -1) - val opc = if (signed) Opcode.ASRNM else Opcode.LSRNM - val ins = if(knownAddress!=null) - IRInstruction(opc, vmDt, reg1 = operandReg, value=knownAddress) - else - IRInstruction(opc, vmDt, reg1 = operandReg, labelSymbol = symbol) - addInstr(result, ins, null) - } - return result - } - - private fun operatorShiftLeft(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks { - val result = mutableListOf() - if(codeGen.isOne(binExpr.right)){ - result += translateExpression(binExpr.left, resultRegister, -1) - addInstr(result, IRInstruction(Opcode.LSL, vmDt, reg1=resultRegister), null) - } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - addInstr(result, IRInstruction(Opcode.LSLN, vmDt, reg1=resultRegister, rightResultReg), null) - } - return result - } - - internal fun operatorShiftLeftInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { - val result = mutableListOf() - if(codeGen.isOne(operand)){ - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.LSLM, vmDt, value=knownAddress) - else - IRInstruction(Opcode.LSLM, vmDt, labelSymbol = symbol) - , null) - } else { - val operandReg = codeGen.registers.nextFree() - result += translateExpression(operand, operandReg, -1) - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, value=knownAddress) - else - IRInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, labelSymbol = symbol) - ,null) - } - return result - } - - private fun operatorXor(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks { - val result = mutableListOf() - if(binExpr.right is PtNumber) { - result += translateExpression(binExpr.left, resultRegister, -1) - addInstr(result, IRInstruction(Opcode.XOR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()), null) - } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - addInstr(result, IRInstruction(Opcode.XORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) - } - return result - } - - internal fun operatorXorInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { - val result = mutableListOf() - val operandReg = codeGen.registers.nextFree() - result += translateExpression(operand, operandReg, -1) - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.XORM, vmDt, reg1=operandReg, value = knownAddress) - else - IRInstruction(Opcode.XORM, vmDt, reg1=operandReg, labelSymbol = symbol) - ,null) - return result - } - - private fun operatorAnd(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks { - val result = mutableListOf() - if(binExpr.right is PtNumber) { - result += translateExpression(binExpr.left, resultRegister, -1) - addInstr(result, IRInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()), null) - } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - addInstr(result, IRInstruction(Opcode.ANDR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) - } - return result - } - - internal fun operatorAndInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { - val result = mutableListOf() - val operandReg = codeGen.registers.nextFree() - result += translateExpression(operand, operandReg, -1) - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.ANDM, vmDt, reg1=operandReg, value=knownAddress) - else - IRInstruction(Opcode.ANDM, vmDt, reg1=operandReg, labelSymbol = symbol) - ,null) - return result - } - - private fun operatorOr(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks { - val result = mutableListOf() - if(binExpr.right is PtNumber) { - result += translateExpression(binExpr.left, resultRegister, -1) - addInstr(result, IRInstruction(Opcode.OR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()), null) - } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - addInstr(result, IRInstruction(Opcode.ORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) - } - return result - } - - internal fun operatorOrInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { - val result = mutableListOf() - val operandReg = codeGen.registers.nextFree() - result += translateExpression(operand, operandReg, -1) - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.ORM, vmDt, reg1=operandReg, value = knownAddress) - else - IRInstruction(Opcode.ORM, vmDt, reg1=operandReg, labelSymbol = symbol) - , null) - return result - } - - private fun operatorModulo(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks { - require(vmDt!=IRDataType.FLOAT) {"floating-point modulo not supported ${binExpr.position}"} - val result = mutableListOf() - val rightResultReg = codeGen.registers.nextFree() - if(binExpr.right is PtNumber) { - result += translateExpression(binExpr.left, resultRegister, -1) - addInstr(result, IRInstruction(Opcode.MOD, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()), null) - } else { - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - addInstr(result, IRInstruction(Opcode.MODR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) - } - return result - } - - private fun operatorDivide(binExpr: PtBinaryExpression, - vmDt: IRDataType, - resultRegister: Int, - resultFpRegister: Int, - signed: Boolean): IRCodeChunks { - val result = mutableListOf() - val constFactorRight = binExpr.right as? PtNumber - if(vmDt==IRDataType.FLOAT) { - if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { - result += translateExpression(binExpr.left, -1, resultFpRegister) - val factor = constFactorRight.number.toFloat() - result += codeGen.divideByConstFloat(resultFpRegister, factor) - } else { - val rightResultFpReg = codeGen.registers.nextFreeFloat() - result += translateExpression(binExpr.left, -1, resultFpRegister) - result += translateExpression(binExpr.right, -1, rightResultFpReg) - addInstr(result, if(signed) - IRInstruction(Opcode.DIVSR, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg) - else - IRInstruction(Opcode.DIVR, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg) - , null) - } - } else { - if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { - result += translateExpression(binExpr.left, resultRegister, -1) - val factor = constFactorRight.number.toInt() - result += codeGen.divideByConst(vmDt, resultRegister, factor, signed) - } else { - val rightResultReg = codeGen.registers.nextFree() - if(binExpr.right is PtNumber) { - result += translateExpression(binExpr.left, resultRegister, -1) - addInstr(result, if (signed) - IRInstruction(Opcode.DIVS, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()) - else - IRInstruction(Opcode.DIV, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()) - , null) - } else { - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - addInstr(result, if (signed) - IRInstruction(Opcode.DIVSR, vmDt, reg1 = resultRegister, reg2 = rightResultReg) - else - IRInstruction(Opcode.DIVR, vmDt, reg1 = resultRegister, reg2 = rightResultReg) - , null) - } - } - } - return result - } - - internal fun operatorDivideInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks { - val result = mutableListOf() - val constFactorRight = operand as? PtNumber - if(vmDt==IRDataType.FLOAT) { - if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { - val factor = constFactorRight.number.toFloat() - result += codeGen.divideByConstFloatInplace(knownAddress, symbol, factor) - } else { - val operandFpReg = codeGen.registers.nextFreeFloat() - result += translateExpression(operand, -1, operandFpReg) - val ins = if(signed) { - if(knownAddress!=null) - IRInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, value = knownAddress) - else - IRInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol) - } - else { - if(knownAddress!=null) - IRInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, value = knownAddress) - else - IRInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol) - } - addInstr(result, ins, null) - } - } else { - if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { - val factor = constFactorRight.number.toInt() - result += codeGen.divideByConstInplace(vmDt, knownAddress, symbol, factor, signed) - } else { - val operandReg = codeGen.registers.nextFree() - result += translateExpression(operand, operandReg, -1) - val ins = if(signed) { - if(knownAddress!=null) - IRInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, value = knownAddress) - else - IRInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, labelSymbol = symbol) - } - else { - if(knownAddress!=null) - IRInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, value = knownAddress) - else - IRInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, labelSymbol = symbol) - } - addInstr(result, ins, null) - } - } - return result - } - - private fun operatorMultiply(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { - val result = mutableListOf() - val constFactorLeft = binExpr.left as? PtNumber - val constFactorRight = binExpr.right as? PtNumber - if(vmDt==IRDataType.FLOAT) { - if(constFactorLeft!=null) { - result += translateExpression(binExpr.right, -1, resultFpRegister) - val factor = constFactorLeft.number.toFloat() - result += codeGen.multiplyByConstFloat(resultFpRegister, factor) - } else if(constFactorRight!=null) { - result += translateExpression(binExpr.left, -1, resultFpRegister) - val factor = constFactorRight.number.toFloat() - result += codeGen.multiplyByConstFloat(resultFpRegister, factor) - } else { - val rightResultFpReg = codeGen.registers.nextFreeFloat() - result += translateExpression(binExpr.left, -1, resultFpRegister) - result += translateExpression(binExpr.right, -1, rightResultFpReg) - addInstr(result, IRInstruction(Opcode.MULR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg), null) - } - } else { - if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) { - result += translateExpression(binExpr.right, resultRegister, -1) - val factor = constFactorLeft.number.toInt() - result += codeGen.multiplyByConst(vmDt, resultRegister, factor) - } else if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { - result += translateExpression(binExpr.left, resultRegister, -1) - val factor = constFactorRight.number.toInt() - result += codeGen.multiplyByConst(vmDt, resultRegister, factor) - } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - addInstr(result, IRInstruction(Opcode.MULR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) - } - } - return result - } - - internal fun operatorMultiplyInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { - val result = mutableListOf() - val constFactorRight = operand as? PtNumber - if(vmDt==IRDataType.FLOAT) { - if(constFactorRight!=null) { - val factor = constFactorRight.number.toFloat() - result += codeGen.multiplyByConstFloatInplace(knownAddress, symbol, factor) - } else { - val operandFpReg = codeGen.registers.nextFreeFloat() - result += translateExpression(operand, -1, operandFpReg) - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, value = knownAddress) - else - IRInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol) - , null) - } - } else { - if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { - val factor = constFactorRight.number.toInt() - result += codeGen.multiplyByConstInplace(vmDt, knownAddress, symbol, factor) - } else { - val operandReg = codeGen.registers.nextFree() - result += translateExpression(operand, operandReg, -1) - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.MULM, vmDt, reg1=operandReg, value = knownAddress) - else - IRInstruction(Opcode.MULM, vmDt, reg1=operandReg, labelSymbol = symbol) - , null) - } - } - return result - } - - private fun operatorMinus(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { - val result = mutableListOf() - if(vmDt==IRDataType.FLOAT) { - if((binExpr.right as? PtNumber)?.number==1.0) { - result += translateExpression(binExpr.left, -1, resultFpRegister) - addInstr(result, IRInstruction(Opcode.DEC, vmDt, fpReg1 = resultFpRegister), null) - } - else { - if(binExpr.right is PtNumber) { - result += translateExpression(binExpr.left, -1, resultFpRegister) - addInstr(result, IRInstruction(Opcode.SUB, vmDt, fpReg1 = resultFpRegister, fpValue = (binExpr.right as PtNumber).number.toFloat()), null) - } else { - val rightResultFpReg = codeGen.registers.nextFreeFloat() - result += translateExpression(binExpr.left, -1, resultFpRegister) - result += translateExpression(binExpr.right, -1, rightResultFpReg) - addInstr(result, IRInstruction(Opcode.SUBR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg), null) - } - } - } else { - if((binExpr.right as? PtNumber)?.number==1.0) { - result += translateExpression(binExpr.left, resultRegister, -1) - addInstr(result, IRInstruction(Opcode.DEC, vmDt, reg1=resultRegister), null) - } - else { - if(binExpr.right is PtNumber) { - result += translateExpression(binExpr.left, resultRegister, -1) - addInstr(result, IRInstruction(Opcode.SUB, vmDt, reg1 = resultRegister, value = (binExpr.right as PtNumber).number.toInt()), null) - } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - addInstr(result, IRInstruction(Opcode.SUBR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) - } - } - } - return result - } - - internal fun operatorMinusInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { - val result = mutableListOf() - if(vmDt==IRDataType.FLOAT) { - if((operand as? PtNumber)?.number==1.0) { - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.DECM, vmDt, value=knownAddress) - else - IRInstruction(Opcode.DECM, vmDt, labelSymbol = symbol) - , null) - } - else { - val operandFpReg = codeGen.registers.nextFreeFloat() - result += translateExpression(operand, -1, operandFpReg) - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, value=knownAddress) - else - IRInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, labelSymbol = symbol) - , null) - } - } else { - if((operand as? PtNumber)?.number==1.0) { - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.DECM, vmDt, value=knownAddress) - else - IRInstruction(Opcode.DECM, vmDt, labelSymbol = symbol) - , null) - } - else { - val operandReg = codeGen.registers.nextFree() - result += translateExpression(operand, operandReg, -1) - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.SUBM, vmDt, reg1=operandReg, value = knownAddress) - else - IRInstruction(Opcode.SUBM, vmDt, reg1=operandReg, labelSymbol = symbol) - , null) - } - } - return result - } - - private fun operatorPlus(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { - val result = mutableListOf() - if(vmDt==IRDataType.FLOAT) { - if((binExpr.left as? PtNumber)?.number==1.0) { - result += translateExpression(binExpr.right, -1, resultFpRegister) - addInstr(result, IRInstruction(Opcode.INC, vmDt, fpReg1=resultFpRegister), null) - } - else if((binExpr.right as? PtNumber)?.number==1.0) { - result += translateExpression(binExpr.left, -1, resultFpRegister) - addInstr(result, IRInstruction(Opcode.INC, vmDt, fpReg1=resultFpRegister), null) - } - else { - if(binExpr.right is PtNumber) { - result += translateExpression(binExpr.left, -1, resultFpRegister) - addInstr(result, IRInstruction(Opcode.ADD, vmDt, fpReg1 = resultFpRegister, fpValue = (binExpr.right as PtNumber).number.toFloat()), null) - } else { - val rightResultFpReg = codeGen.registers.nextFreeFloat() - result += translateExpression(binExpr.left, -1, resultFpRegister) - result += translateExpression(binExpr.right, -1, rightResultFpReg) - addInstr(result, IRInstruction(Opcode.ADDR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg), null) - } - } - } else { - if((binExpr.left as? PtNumber)?.number==1.0) { - result += translateExpression(binExpr.right, resultRegister, -1) - addInstr(result, IRInstruction(Opcode.INC, vmDt, reg1=resultRegister), null) - } - else if((binExpr.right as? PtNumber)?.number==1.0) { - result += translateExpression(binExpr.left, resultRegister, -1) - addInstr(result, IRInstruction(Opcode.INC, vmDt, reg1=resultRegister), null) - } - else { - if(binExpr.right is PtNumber) { - result += translateExpression(binExpr.left, resultRegister, -1) - addInstr(result, IRInstruction(Opcode.ADD, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()), null) - } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - addInstr(result, IRInstruction(Opcode.ADDR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) - } - } - } - return result - } - - internal fun operatorPlusInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { - val result = mutableListOf() - if(vmDt==IRDataType.FLOAT) { - if((operand as? PtNumber)?.number==1.0) { - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.INCM, vmDt, value = knownAddress) - else - IRInstruction(Opcode.INCM, vmDt, labelSymbol = symbol) - , null) - } - else { - val operandFpReg = codeGen.registers.nextFreeFloat() - result += translateExpression(operand, -1, operandFpReg) - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, value = knownAddress) - else - IRInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, labelSymbol = symbol) - , null) - } - } else { - if((operand as? PtNumber)?.number==1.0) { - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.INCM, vmDt, value = knownAddress) - else - IRInstruction(Opcode.INCM, vmDt, labelSymbol = symbol) - , null) - } - else { - val operandReg = codeGen.registers.nextFree() - result += translateExpression(operand, operandReg, -1) - addInstr(result, if(knownAddress!=null) - IRInstruction(Opcode.ADDM, vmDt, reg1=operandReg, value=knownAddress) - else - IRInstruction(Opcode.ADDM, vmDt, reg1=operandReg, labelSymbol = symbol) - , null) - } - } - return result - } - - fun translate(fcall: PtFunctionCall, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { + fun translate(fcall: PtFunctionCall, resultRegister: Int, resultFpRegister: Int): ExpressionCodeResult { when (val callTarget = codeGen.symbolTable.flat.getValue(fcall.name)) { is StSub -> { val result = mutableListOf() @@ -945,11 +328,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } else { if (paramDt == IRDataType.FLOAT) { val argFpReg = codeGen.registers.nextFreeFloat() - result += translateExpression(arg, -1, argFpReg) + val translated = translateExpression(arg, -1, argFpReg) + addToResult(result, translated, -1, argFpReg) addInstr(result, IRInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, labelSymbol = symbol), null) } else { val argReg = codeGen.registers.nextFree() - result += translateExpression(arg, argReg, -1) + val translated = translateExpression(arg, argReg, -1) + addToResult(result, translated, argReg, -1) addInstr(result, IRInstruction(Opcode.STOREM, paramDt, reg1 = argReg, labelSymbol = symbol), null) } } @@ -962,7 +347,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { else addInstr(result, IRInstruction(Opcode.CALLRVAL, codeGen.irType(fcall.type), reg1=resultRegister, labelSymbol=fcall.name), null) } - return result + return ExpressionCodeResult(result, if(fcall.void) IRDataType.BYTE else codeGen.irType(fcall.type), resultRegister, resultFpRegister) } is StRomSub -> { val result = mutableListOf() @@ -975,7 +360,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { if (paramDt == IRDataType.FLOAT) throw AssemblyError("doesn't support float register argument in asm romsub") val argReg = codeGen.registers.nextFree() - result += translateExpression(arg, argReg, -1) + val translated = translateExpression(arg, argReg, -1) + addToResult(result, translated, argReg, -1) addInstr(result, IRInstruction(Opcode.STORECPU, paramDt, reg1 = argReg, labelSymbol = paramRegStr), null) } } @@ -1010,12 +396,743 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } } } - return result + return ExpressionCodeResult(result, if(fcall.void) IRDataType.BYTE else codeGen.irType(fcall.type), resultRegister, resultFpRegister) } else -> throw AssemblyError("invalid node type") } } + private fun operatorGreaterThan( + binExpr: PtBinaryExpression, + vmDt: IRDataType, + resultRegister: Int, + signed: Boolean, + greaterEquals: Boolean + ): IRCodeChunks { + val result = mutableListOf() + if(vmDt==IRDataType.FLOAT) { + val leftFpReg = codeGen.registers.nextFreeFloat() + val rightFpReg = codeGen.registers.nextFreeFloat() + val zeroRegister = codeGen.registers.nextFree() + var translated = translateExpression(binExpr.left, -1, leftFpReg) + addToResult(result, translated, -1, leftFpReg) + translated = translateExpression(binExpr.right, -1, rightFpReg) + addToResult(result, translated, -1, rightFpReg) + addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg), null) + addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroRegister, value=0), null) + val ins = if (signed) { + if (greaterEquals) Opcode.SGES else Opcode.SGTS + } else { + if (greaterEquals) Opcode.SGE else Opcode.SGT + } + addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister), null) + } else { + if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) { + var translated = translateExpression(binExpr.left, SyscallRegisterBase, -1) + addToResult(result, translated, SyscallRegisterBase, -1) + translated = translateExpression(binExpr.right, SyscallRegisterBase+1, -1) + addToResult(result, translated, SyscallRegisterBase+1, -1) + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number) + if(resultRegister!=0) + it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0) + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = 0) + it += if (greaterEquals) + IRInstruction(Opcode.SGES, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1) + else + IRInstruction(Opcode.SGTS, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1) + } + } else { + val rightResultReg = codeGen.registers.nextFree() + var translated = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, translated, resultRegister, -1) + translated = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, translated, rightResultReg, -1) + val ins = if (signed) { + if (greaterEquals) Opcode.SGES else Opcode.SGTS + } else { + if (greaterEquals) Opcode.SGE else Opcode.SGT + } + addInstr(result, IRInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } + } + return result + } + + private fun operatorLessThan( + binExpr: PtBinaryExpression, + vmDt: IRDataType, + resultRegister: Int, + signed: Boolean, + lessEquals: Boolean + ): IRCodeChunks { + val result = mutableListOf() + if(vmDt==IRDataType.FLOAT) { + val leftFpReg = codeGen.registers.nextFreeFloat() + val rightFpReg = codeGen.registers.nextFreeFloat() + val zeroRegister = codeGen.registers.nextFree() + var tr = translateExpression(binExpr.left, -1, leftFpReg) + addToResult(result, tr, -1, leftFpReg) + tr = translateExpression(binExpr.right, -1, rightFpReg) + addToResult(result, tr, -1, rightFpReg) + addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg), null) + addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroRegister, value=0), null) + val ins = if (signed) { + if (lessEquals) Opcode.SLES else Opcode.SLTS + } else { + if (lessEquals) Opcode.SLE else Opcode.SLT + } + addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister), null) + } else { + if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) { + var tr = translateExpression(binExpr.left, SyscallRegisterBase, -1) + addToResult(result, tr, SyscallRegisterBase, -1) + tr = translateExpression(binExpr.right, SyscallRegisterBase+1, -1) + addToResult(result, tr, SyscallRegisterBase+1, -1) + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number) + if(resultRegister!=0) + it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0) + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = 0) + it += if (lessEquals) + IRInstruction(Opcode.SLES, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1) + else + IRInstruction(Opcode.SLTS, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1) + } + } else { + val rightResultReg = codeGen.registers.nextFree() + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + val ins = if (signed) { + if (lessEquals) Opcode.SLES else Opcode.SLTS + } else { + if (lessEquals) Opcode.SLE else Opcode.SLT + } + addInstr(result, IRInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } + } + return result + } + + private fun operatorEquals(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int, notEquals: Boolean): IRCodeChunks { + val result = mutableListOf() + if(vmDt==IRDataType.FLOAT) { + val leftFpReg = codeGen.registers.nextFreeFloat() + val rightFpReg = codeGen.registers.nextFreeFloat() + var tr = translateExpression(binExpr.left, -1, leftFpReg) + addToResult(result, tr, -1, leftFpReg) + tr = translateExpression(binExpr.right, -1, rightFpReg) + addToResult(result, tr, -1, rightFpReg) + if (notEquals) { + addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg), null) + } else { + val label = codeGen.createLabelName() + val valueReg = codeGen.registers.nextFree() + addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=1), null) + addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=valueReg, fpReg1 = leftFpReg, fpReg2 = rightFpReg), null) + addInstr(result, IRInstruction(Opcode.BZ, IRDataType.BYTE, reg1=valueReg, labelSymbol = label), null) + addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=0), null) + result += IRCodeChunk(label, null) + } + } else { + if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) { + var tr = translateExpression(binExpr.left, SyscallRegisterBase, -1) + addToResult(result, tr, SyscallRegisterBase, -1) + tr = translateExpression(binExpr.right, SyscallRegisterBase+1, -1) + addToResult(result, tr, SyscallRegisterBase+1, -1) + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number) + if(resultRegister!=0) + it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0) + if (!notEquals) + it += IRInstruction(Opcode.INV, vmDt, reg1 = resultRegister) + it += IRInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value = 1) + } + } else { + if(constValue(binExpr.right)==0.0) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + val opcode = if (notEquals) Opcode.SNZ else Opcode.SZ + addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = resultRegister), null) + } else { + val rightResultReg = codeGen.registers.nextFree() + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ + addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } + } + } + return result + } + + private fun operatorShiftRight(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int, signed: Boolean): IRCodeChunks { + val result = mutableListOf() + if(codeGen.isOne(binExpr.right)) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + val opc = if (signed) Opcode.ASR else Opcode.LSR + addInstr(result, IRInstruction(opc, vmDt, reg1 = resultRegister), null) + } else { + val rightResultReg = codeGen.registers.nextFree() + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + val opc = if (signed) Opcode.ASRN else Opcode.LSRN + addInstr(result, IRInstruction(opc, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } + return result + } + + internal fun operatorShiftRightInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks { + val result = mutableListOf() + if(codeGen.isOne(operand)) { + val opc = if (signed) Opcode.ASRM else Opcode.LSRM + val ins = if(knownAddress!=null) + IRInstruction(opc, vmDt, value=knownAddress) + else + IRInstruction(opc, vmDt, labelSymbol = symbol) + addInstr(result, ins, null) + } else { + val operandReg = codeGen.registers.nextFree() + val tr = translateExpression(operand, operandReg, -1) + addToResult(result, tr, operandReg, -1) + val opc = if (signed) Opcode.ASRNM else Opcode.LSRNM + val ins = if(knownAddress!=null) + IRInstruction(opc, vmDt, reg1 = operandReg, value=knownAddress) + else + IRInstruction(opc, vmDt, reg1 = operandReg, labelSymbol = symbol) + addInstr(result, ins, null) + } + return result + } + + private fun operatorShiftLeft(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks { + val result = mutableListOf() + if(codeGen.isOne(binExpr.right)){ + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + addInstr(result, IRInstruction(Opcode.LSL, vmDt, reg1=resultRegister), null) + } else { + val rightResultReg = codeGen.registers.nextFree() + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + addInstr(result, IRInstruction(Opcode.LSLN, vmDt, reg1=resultRegister, rightResultReg), null) + } + return result + } + + internal fun operatorShiftLeftInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { + val result = mutableListOf() + if(codeGen.isOne(operand)){ + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.LSLM, vmDt, value=knownAddress) + else + IRInstruction(Opcode.LSLM, vmDt, labelSymbol = symbol) + , null) + } else { + val operandReg = codeGen.registers.nextFree() + val tr = translateExpression(operand, operandReg, -1) + addToResult(result, tr, operandReg, -1) + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, value=knownAddress) + else + IRInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, labelSymbol = symbol) + ,null) + } + return result + } + + private fun operatorXor(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks { + val result = mutableListOf() + if(binExpr.right is PtNumber) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + addInstr(result, IRInstruction(Opcode.XOR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()), null) + } else { + val rightResultReg = codeGen.registers.nextFree() + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + addInstr(result, IRInstruction(Opcode.XORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } + return result + } + + internal fun operatorXorInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { + val result = mutableListOf() + val operandReg = codeGen.registers.nextFree() + val tr = translateExpression(operand, operandReg, -1) + addToResult(result, tr, operandReg, -1) + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.XORM, vmDt, reg1=operandReg, value = knownAddress) + else + IRInstruction(Opcode.XORM, vmDt, reg1=operandReg, labelSymbol = symbol) + ,null) + return result + } + + private fun operatorAnd(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks { + val result = mutableListOf() + if(binExpr.right is PtNumber) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + addInstr(result, IRInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()), null) + } else { + val rightResultReg = codeGen.registers.nextFree() + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr= translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + addInstr(result, IRInstruction(Opcode.ANDR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } + return result + } + + internal fun operatorAndInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { + val result = mutableListOf() + val operandReg = codeGen.registers.nextFree() + val tr = translateExpression(operand, operandReg, -1) + addToResult(result, tr, operandReg, -1) + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.ANDM, vmDt, reg1=operandReg, value=knownAddress) + else + IRInstruction(Opcode.ANDM, vmDt, reg1=operandReg, labelSymbol = symbol) + ,null) + return result + } + + private fun operatorOr(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks { + val result = mutableListOf() + if(binExpr.right is PtNumber) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + addInstr(result, IRInstruction(Opcode.OR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()), null) + } else { + val rightResultReg = codeGen.registers.nextFree() + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + addInstr(result, IRInstruction(Opcode.ORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } + return result + } + + internal fun operatorOrInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { + val result = mutableListOf() + val operandReg = codeGen.registers.nextFree() + val tr = translateExpression(operand, operandReg, -1) + addToResult(result, tr, operandReg, -1) + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.ORM, vmDt, reg1=operandReg, value = knownAddress) + else + IRInstruction(Opcode.ORM, vmDt, reg1=operandReg, labelSymbol = symbol) + , null) + return result + } + + private fun operatorModulo(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks { + require(vmDt!=IRDataType.FLOAT) {"floating-point modulo not supported ${binExpr.position}"} + val result = mutableListOf() + val rightResultReg = codeGen.registers.nextFree() + if(binExpr.right is PtNumber) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + addInstr(result, IRInstruction(Opcode.MOD, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()), null) + } else { + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + addInstr(result, IRInstruction(Opcode.MODR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } + return result + } + + private fun operatorDivide(binExpr: PtBinaryExpression, + vmDt: IRDataType, + resultRegister: Int, + resultFpRegister: Int, + signed: Boolean): IRCodeChunks { + val result = mutableListOf() + val constFactorRight = binExpr.right as? PtNumber + if(vmDt==IRDataType.FLOAT) { + if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { + val tr = translateExpression(binExpr.left, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + val factor = constFactorRight.number.toFloat() + result += codeGen.divideByConstFloat(resultFpRegister, factor) + } else { + val rightResultFpReg = codeGen.registers.nextFreeFloat() + var tr = translateExpression(binExpr.left, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + tr = translateExpression(binExpr.right, -1, rightResultFpReg) + addToResult(result, tr, -1, rightResultFpReg) + addInstr(result, if(signed) + IRInstruction(Opcode.DIVSR, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg) + else + IRInstruction(Opcode.DIVR, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg) + , null) + } + } else { + if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + val factor = constFactorRight.number.toInt() + result += codeGen.divideByConst(vmDt, resultRegister, factor, signed) + } else { + val rightResultReg = codeGen.registers.nextFree() + if(binExpr.right is PtNumber) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + addInstr(result, if (signed) + IRInstruction(Opcode.DIVS, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()) + else + IRInstruction(Opcode.DIV, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()) + , null) + } else { + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + addInstr(result, if (signed) + IRInstruction(Opcode.DIVSR, vmDt, reg1 = resultRegister, reg2 = rightResultReg) + else + IRInstruction(Opcode.DIVR, vmDt, reg1 = resultRegister, reg2 = rightResultReg) + , null) + } + } + } + return result + } + + internal fun operatorDivideInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks { + val result = mutableListOf() + val constFactorRight = operand as? PtNumber + if(vmDt==IRDataType.FLOAT) { + if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { + val factor = constFactorRight.number.toFloat() + result += codeGen.divideByConstFloatInplace(knownAddress, symbol, factor) + } else { + val operandFpReg = codeGen.registers.nextFreeFloat() + val tr = translateExpression(operand, -1, operandFpReg) + addToResult(result, tr, -1, operandFpReg) + val ins = if(signed) { + if(knownAddress!=null) + IRInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, value = knownAddress) + else + IRInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol) + } + else { + if(knownAddress!=null) + IRInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, value = knownAddress) + else + IRInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol) + } + addInstr(result, ins, null) + } + } else { + if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { + val factor = constFactorRight.number.toInt() + result += codeGen.divideByConstInplace(vmDt, knownAddress, symbol, factor, signed) + } else { + val operandReg = codeGen.registers.nextFree() + val tr = translateExpression(operand, operandReg, -1) + addToResult(result, tr, operandReg, -1) + val ins = if(signed) { + if(knownAddress!=null) + IRInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, value = knownAddress) + else + IRInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, labelSymbol = symbol) + } + else { + if(knownAddress!=null) + IRInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, value = knownAddress) + else + IRInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, labelSymbol = symbol) + } + addInstr(result, ins, null) + } + } + return result + } + + private fun operatorMultiply(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { + val result = mutableListOf() + val constFactorLeft = binExpr.left as? PtNumber + val constFactorRight = binExpr.right as? PtNumber + if(vmDt==IRDataType.FLOAT) { + if(constFactorLeft!=null) { + val tr = translateExpression(binExpr.right, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + val factor = constFactorLeft.number.toFloat() + result += codeGen.multiplyByConstFloat(resultFpRegister, factor) + } else if(constFactorRight!=null) { + val tr = translateExpression(binExpr.left, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + val factor = constFactorRight.number.toFloat() + result += codeGen.multiplyByConstFloat(resultFpRegister, factor) + } else { + val rightResultFpReg = codeGen.registers.nextFreeFloat() + var tr = translateExpression(binExpr.left, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + tr = translateExpression(binExpr.right, -1, rightResultFpReg) + addToResult(result, tr, -1, rightResultFpReg) + addInstr(result, IRInstruction(Opcode.MULR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg), null) + } + } else { + if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) { + val tr = translateExpression(binExpr.right, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + val factor = constFactorLeft.number.toInt() + result += codeGen.multiplyByConst(vmDt, resultRegister, factor) + } else if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + val factor = constFactorRight.number.toInt() + result += codeGen.multiplyByConst(vmDt, resultRegister, factor) + } else { + val rightResultReg = codeGen.registers.nextFree() + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + addInstr(result, IRInstruction(Opcode.MULR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } + } + return result + } + + internal fun operatorMultiplyInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { + val result = mutableListOf() + val constFactorRight = operand as? PtNumber + if(vmDt==IRDataType.FLOAT) { + if(constFactorRight!=null) { + val factor = constFactorRight.number.toFloat() + result += codeGen.multiplyByConstFloatInplace(knownAddress, symbol, factor) + } else { + val operandFpReg = codeGen.registers.nextFreeFloat() + val tr = translateExpression(operand, -1, operandFpReg) + addToResult(result, tr, -1, operandFpReg) + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, value = knownAddress) + else + IRInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol) + , null) + } + } else { + if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { + val factor = constFactorRight.number.toInt() + result += codeGen.multiplyByConstInplace(vmDt, knownAddress, symbol, factor) + } else { + val operandReg = codeGen.registers.nextFree() + val tr = translateExpression(operand, operandReg, -1) + addToResult(result, tr, operandReg, -1) + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.MULM, vmDt, reg1=operandReg, value = knownAddress) + else + IRInstruction(Opcode.MULM, vmDt, reg1=operandReg, labelSymbol = symbol) + , null) + } + } + return result + } + + private fun operatorMinus(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { + val result = mutableListOf() + if(vmDt==IRDataType.FLOAT) { + if((binExpr.right as? PtNumber)?.number==1.0) { + val tr = translateExpression(binExpr.left, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + addInstr(result, IRInstruction(Opcode.DEC, vmDt, fpReg1 = resultFpRegister), null) + } + else { + if(binExpr.right is PtNumber) { + val tr = translateExpression(binExpr.left, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + addInstr(result, IRInstruction(Opcode.SUB, vmDt, fpReg1 = resultFpRegister, fpValue = (binExpr.right as PtNumber).number.toFloat()), null) + } else { + val rightResultFpReg = codeGen.registers.nextFreeFloat() + var tr = translateExpression(binExpr.left, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + tr = translateExpression(binExpr.right, -1, rightResultFpReg) + addToResult(result, tr, -1, rightResultFpReg) + addInstr(result, IRInstruction(Opcode.SUBR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg), null) + } + } + } else { + if((binExpr.right as? PtNumber)?.number==1.0) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + addInstr(result, IRInstruction(Opcode.DEC, vmDt, reg1=resultRegister), null) + } + else { + if(binExpr.right is PtNumber) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + addInstr(result, IRInstruction(Opcode.SUB, vmDt, reg1 = resultRegister, value = (binExpr.right as PtNumber).number.toInt()), null) + } else { + val rightResultReg = codeGen.registers.nextFree() + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + addInstr(result, IRInstruction(Opcode.SUBR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } + } + } + return result + } + + internal fun operatorMinusInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { + val result = mutableListOf() + if(vmDt==IRDataType.FLOAT) { + if((operand as? PtNumber)?.number==1.0) { + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.DECM, vmDt, value=knownAddress) + else + IRInstruction(Opcode.DECM, vmDt, labelSymbol = symbol) + , null) + } + else { + val operandFpReg = codeGen.registers.nextFreeFloat() + val tr = translateExpression(operand, -1, operandFpReg) + addToResult(result, tr, -1, operandFpReg) + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, value=knownAddress) + else + IRInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, labelSymbol = symbol) + , null) + } + } else { + if((operand as? PtNumber)?.number==1.0) { + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.DECM, vmDt, value=knownAddress) + else + IRInstruction(Opcode.DECM, vmDt, labelSymbol = symbol) + , null) + } + else { + val operandReg = codeGen.registers.nextFree() + val tr = translateExpression(operand, operandReg, -1) + addToResult(result, tr, operandReg, -1) + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.SUBM, vmDt, reg1=operandReg, value = knownAddress) + else + IRInstruction(Opcode.SUBM, vmDt, reg1=operandReg, labelSymbol = symbol) + , null) + } + } + return result + } + + private fun operatorPlus(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { + val result = mutableListOf() + if(vmDt==IRDataType.FLOAT) { + if((binExpr.left as? PtNumber)?.number==1.0) { + val tr = translateExpression(binExpr.right, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + addInstr(result, IRInstruction(Opcode.INC, vmDt, fpReg1=resultFpRegister), null) + } + else if((binExpr.right as? PtNumber)?.number==1.0) { + val tr = translateExpression(binExpr.left, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + addInstr(result, IRInstruction(Opcode.INC, vmDt, fpReg1=resultFpRegister), null) + } + else { + if(binExpr.right is PtNumber) { + val tr = translateExpression(binExpr.left, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + addInstr(result, IRInstruction(Opcode.ADD, vmDt, fpReg1 = resultFpRegister, fpValue = (binExpr.right as PtNumber).number.toFloat()), null) + } else { + val rightResultFpReg = codeGen.registers.nextFreeFloat() + var tr = translateExpression(binExpr.left, -1, resultFpRegister) + addToResult(result, tr, -1, resultFpRegister) + tr = translateExpression(binExpr.right, -1, rightResultFpReg) + addToResult(result, tr, -1, rightResultFpReg) + addInstr(result, IRInstruction(Opcode.ADDR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg), null) + } + } + } else { + if((binExpr.left as? PtNumber)?.number==1.0) { + val tr = translateExpression(binExpr.right, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + addInstr(result, IRInstruction(Opcode.INC, vmDt, reg1=resultRegister), null) + } + else if((binExpr.right as? PtNumber)?.number==1.0) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + addInstr(result, IRInstruction(Opcode.INC, vmDt, reg1=resultRegister), null) + } + else { + if(binExpr.right is PtNumber) { + val tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + addInstr(result, IRInstruction(Opcode.ADD, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()), null) + } else { + val rightResultReg = codeGen.registers.nextFree() + var tr = translateExpression(binExpr.left, resultRegister, -1) + addToResult(result, tr, resultRegister, -1) + tr = translateExpression(binExpr.right, rightResultReg, -1) + addToResult(result, tr, rightResultReg, -1) + addInstr(result, IRInstruction(Opcode.ADDR, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } + } + } + return result + } + + internal fun operatorPlusInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { + val result = mutableListOf() + if(vmDt==IRDataType.FLOAT) { + if((operand as? PtNumber)?.number==1.0) { + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.INCM, vmDt, value = knownAddress) + else + IRInstruction(Opcode.INCM, vmDt, labelSymbol = symbol) + , null) + } + else { + val operandFpReg = codeGen.registers.nextFreeFloat() + val tr = translateExpression(operand, -1, operandFpReg) + addToResult(result, tr, -1, operandFpReg) + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, value = knownAddress) + else + IRInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, labelSymbol = symbol) + , null) + } + } else { + if((operand as? PtNumber)?.number==1.0) { + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.INCM, vmDt, value = knownAddress) + else + IRInstruction(Opcode.INCM, vmDt, labelSymbol = symbol) + , null) + } + else { + val operandReg = codeGen.registers.nextFree() + val tr = translateExpression(operand, operandReg, -1) + addToResult(result, tr, operandReg, -1) + addInstr(result, if(knownAddress!=null) + IRInstruction(Opcode.ADDM, vmDt, reg1=operandReg, value=knownAddress) + else + IRInstruction(Opcode.ADDM, vmDt, reg1=operandReg, labelSymbol = symbol) + , null) + } + } + return result + } + } @@ -1024,3 +1141,23 @@ internal fun addInstr(code: MutableList, instr: IRInstruction, it += instr } } + +internal fun addToResult( + result: MutableList, + codeResult: ExpressionCodeResult, + requiredResultReg: Int, + requiredResultFpReg: Int +) { + if(requiredResultReg!=-1) require(requiredResultFpReg==-1) + if(requiredResultFpReg!=-1) require(requiredResultReg==-1) + + if(requiredResultReg>=0 && requiredResultReg!=codeResult.resultReg) { + println("RESULT REG DIFFERENCE: GOT ${codeResult.resultReg} WANTED $requiredResultReg ${codeResult.dt}") + codeResult.chunks.last().instructions += IRInstruction(Opcode.LOADR, codeResult.dt, reg1=requiredResultReg, reg2=codeResult.resultReg) + } + if(requiredResultFpReg>=0 && requiredResultFpReg!=codeResult.resultFpReg) { + println("RESULT FPREG DIFFERENCE: GOT ${codeResult.resultFpReg} WANTED $requiredResultFpReg ${codeResult.dt}") + codeResult.chunks.last().instructions += IRInstruction(Opcode.LOADR, IRDataType.FLOAT, fpReg1 = requiredResultReg, fpReg2 = codeResult.resultReg) + } + result += codeResult.chunks +} diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index 549f4a543..d28b1efc9 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -238,8 +238,15 @@ class IRCodeGen( is PtAssignment -> assignmentGen.translate(node) is PtAugmentedAssign -> assignmentGen.translate(node) is PtNodeGroup -> translateGroup(node.children) - is PtBuiltinFunctionCall -> translateBuiltinFunc(node, 0) - is PtFunctionCall -> expressionEval.translate(node, 0, 0) + is PtBuiltinFunctionCall -> { + val result = translateBuiltinFunc(node) + result.chunks // it's not an expression so no result value. + } + is PtFunctionCall -> { + val result = expressionEval.translate(node, 0, 0) + require(result.resultReg==0 && result.resultFpReg==0) // TODO weg + result.chunks + } is PtNop -> emptyList() is PtReturn -> translate(node) is PtJump -> translate(node) @@ -398,7 +405,8 @@ class IRCodeGen( val valueReg = registers.nextFree() val choiceReg = registers.nextFree() val valueDt = irType(whenStmt.value.type) - result += expressionEval.translateExpression(whenStmt.value, valueReg, -1) + val tr = expressionEval.translateExpression(whenStmt.value, valueReg, -1) + addToResult(result, tr, valueReg, -1) val choices = whenStmt.choices.children.map {it as PtWhenChoice } val endLabel = createLabelName() for (choice in choices) { @@ -523,8 +531,10 @@ class IRCodeGen( val loopLabel = createLabelName() val result = mutableListOf() - result += expressionEval.translateExpression(iterable.to, endvalueReg, -1) - result += expressionEval.translateExpression(iterable.from, indexReg, -1) + var tr = expressionEval.translateExpression(iterable.to, endvalueReg, -1) + addToResult(result, tr, endvalueReg, -1) + tr = expressionEval.translateExpression(iterable.from, indexReg, -1) + addToResult(result, tr, indexReg, -1) val labelAfterFor = createLabelName() val greaterOpcode = if(loopvarDt in SignedDatatypes) Opcode.BGTS else Opcode.BGT @@ -909,8 +919,10 @@ class IRCodeGen( val leftFpRegNum = registers.nextFreeFloat() val rightFpRegNum = registers.nextFreeFloat() val compResultReg = registers.nextFree() - result += expressionEval.translateExpression(ifElse.condition.left, -1, leftFpRegNum) - result += expressionEval.translateExpression(ifElse.condition.right, -1, rightFpRegNum) + var tr = expressionEval.translateExpression(ifElse.condition.left, -1, leftFpRegNum) + addToResult(result, tr, -1, leftFpRegNum) + tr = expressionEval.translateExpression(ifElse.condition.right, -1, rightFpRegNum) + addToResult(result, tr, -1, rightFpRegNum) result += IRCodeChunk(null,null).also { it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftFpRegNum, fpReg2 = rightFpRegNum) val gotoOpcode = when (ifElse.condition.operator) { @@ -932,8 +944,10 @@ class IRCodeGen( } else { val leftRegNum = registers.nextFree() val rightRegNum = registers.nextFree() - result += expressionEval.translateExpression(ifElse.condition.left, leftRegNum, -1) - result += expressionEval.translateExpression(ifElse.condition.right, rightRegNum, -1) + var tr = expressionEval.translateExpression(ifElse.condition.left, leftRegNum, -1) + addToResult(result, tr, leftRegNum, -1) + tr = expressionEval.translateExpression(ifElse.condition.right, rightRegNum, -1) + addToResult(result, tr, rightRegNum, -1) val opcode: Opcode val firstReg: Int val secondReg: Int @@ -992,7 +1006,8 @@ class IRCodeGen( val leftFpReg = registers.nextFreeFloat() val rightFpReg = registers.nextFreeFloat() compResultReg = registers.nextFree() - result += expressionEval.translateExpression(ifElse.condition.left, -1, leftFpReg) + val tr = expressionEval.translateExpression(ifElse.condition.left, -1, leftFpReg) + addToResult(result, tr, -1, leftFpReg) result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = rightFpReg, fpValue = 0f) it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftFpReg, fpReg2 = rightFpReg) @@ -1010,7 +1025,8 @@ class IRCodeGen( // integer comparisons branchDt = irDtLeft compResultReg = registers.nextFree() - result += expressionEval.translateExpression(ifElse.condition.left, compResultReg, -1) + val tr = expressionEval.translateExpression(ifElse.condition.left, compResultReg, -1) + addToResult(result, tr, compResultReg, -1) elseBranch = when (ifElse.condition.operator) { "==" -> Opcode.BNZ "!=" -> Opcode.BZ @@ -1049,12 +1065,13 @@ class IRCodeGen( val elseBranchSecondReg: Int val branchDt: IRDataType if(irDtLeft==IRDataType.FLOAT) { - branchDt = IRDataType.BYTE val leftFpRegNum = registers.nextFreeFloat() val rightFpRegNum = registers.nextFreeFloat() val compResultReg = registers.nextFree() - result += expressionEval.translateExpression(ifElse.condition.left, -1, leftFpRegNum) - result += expressionEval.translateExpression(ifElse.condition.right, -1, rightFpRegNum) + var tr = expressionEval.translateExpression(ifElse.condition.left, -1, leftFpRegNum) + addToResult(result, tr, -1, leftFpRegNum) + tr = expressionEval.translateExpression(ifElse.condition.right, -1, rightFpRegNum) + addToResult(result, tr, -1, rightFpRegNum) addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftFpRegNum, fpReg2 = rightFpRegNum), null) val elseBranch = when (ifElse.condition.operator) { "==" -> Opcode.BNZ @@ -1086,8 +1103,10 @@ class IRCodeGen( branchDt = irDtLeft val leftRegNum = registers.nextFree() val rightRegNum = registers.nextFree() - result += expressionEval.translateExpression(ifElse.condition.left, leftRegNum, -1) - result += expressionEval.translateExpression(ifElse.condition.right, rightRegNum, -1) + var tr = expressionEval.translateExpression(ifElse.condition.left, leftRegNum, -1) + addToResult(result, tr, leftRegNum, -1) + tr = expressionEval.translateExpression(ifElse.condition.right, rightRegNum, -1) + addToResult(result, tr, rightRegNum, -1) when (ifElse.condition.operator) { "==" -> { elseBranchOpcode = Opcode.BNE @@ -1178,7 +1197,8 @@ class IRCodeGen( } else { val incReg = registers.nextFree() val addressReg = registers.nextFree() - result += expressionEval.translateExpression(memory.address, addressReg, -1) + val tr = expressionEval.translateExpression(memory.address, addressReg, -1) + addToResult(result, tr, addressReg, -1) val chunk = IRCodeChunk(null, null) chunk += IRInstruction(Opcode.LOADI, irDt, reg1 = incReg, reg2 = addressReg) chunk += IRInstruction(operationRegister, irDt, reg1 = incReg) @@ -1195,7 +1215,8 @@ class IRCodeGen( } else { val incReg = registers.nextFree() val indexReg = registers.nextFree() - result += expressionEval.translateExpression(array.index, indexReg, -1) + val tr = expressionEval.translateExpression(array.index, indexReg, -1) + addToResult(result, tr, indexReg, -1) val chunk = IRCodeChunk(null, null) chunk += IRInstruction(Opcode.LOADX, irDt, reg1=incReg, reg2=indexReg, labelSymbol=variable) chunk += IRInstruction(operationRegister, irDt, reg1=incReg) @@ -1223,7 +1244,8 @@ class IRCodeGen( val counterReg = registers.nextFree() val irDt = irType(repeat.count.type) val result = mutableListOf() - result += expressionEval.translateExpression(repeat.count, counterReg, -1) + val tr = expressionEval.translateExpression(repeat.count, counterReg, -1) + addToResult(result, tr, counterReg, -1) addInstr(result, IRInstruction(Opcode.BZ, irDt, reg1=counterReg, labelSymbol = skipRepeatLabel), null) result += labelFirstChunk(translateNode(repeat.statements), repeatLabel) val chunk = IRCodeChunk(null, null) @@ -1264,12 +1286,14 @@ class IRCodeGen( } else { if(value.type==DataType.FLOAT) { val reg = registers.nextFreeFloat() - result += expressionEval.translateExpression(value, -1, reg) + val tr = expressionEval.translateExpression(value, -1, reg) + addToResult(result, tr, -1, reg) addInstr(result, IRInstruction(Opcode.RETURNREG, IRDataType.FLOAT, fpReg1 = reg), null) } else { val reg = registers.nextFree() - result += expressionEval.translateExpression(value, reg, -1) + val tr = expressionEval.translateExpression(value, reg, -1) + addToResult(result, tr, reg, -1) addInstr(result, IRInstruction(Opcode.RETURNREG, irType(value.type) , reg1=reg), null) } } @@ -1363,8 +1387,8 @@ class IRCodeGen( return "prog8_label_gen_$labelSequenceNumber" } - internal fun translateBuiltinFunc(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks = - builtinFuncGen.translate(call, resultRegister) + internal fun translateBuiltinFunc(call: PtBuiltinFunctionCall): ExpressionCodeResult + = builtinFuncGen.translate(call) internal fun isZero(expression: PtExpression): Boolean = expression is PtNumber && expression.number==0.0