mirror of
https://github.com/irmen/prog8.git
synced 2025-08-16 05:27:31 +00:00
implement missing operators in IR code gen
This commit is contained in:
@@ -48,15 +48,22 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
val value = assignment.value
|
val value = assignment.value
|
||||||
val vmDt = codeGen.irType(value.type)
|
val vmDt = codeGen.irType(value.type)
|
||||||
return when(assignment.operator) {
|
return when(assignment.operator) {
|
||||||
"+" -> expressionEval.operatorPlusInplace(address, null, vmDt, value).chunks
|
"+" -> expressionEval.operatorPlusInplace(address, null, vmDt, value)
|
||||||
"-" -> expressionEval.operatorMinusInplace(address, null, vmDt, value).chunks
|
"-" -> expressionEval.operatorMinusInplace(address, null, vmDt, value)
|
||||||
"*" -> expressionEval.operatorMultiplyInplace(address, null, vmDt, value).chunks
|
"*" -> expressionEval.operatorMultiplyInplace(address, null, vmDt, value)
|
||||||
"/" -> expressionEval.operatorDivideInplace(address, null, vmDt, value.type in SignedDatatypes, value).chunks
|
"/" -> expressionEval.operatorDivideInplace(address, null, vmDt, value.type in SignedDatatypes, value)
|
||||||
"|" -> expressionEval.operatorOrInplace(address, null, vmDt, value).chunks
|
"|" -> expressionEval.operatorOrInplace(address, null, vmDt, value)
|
||||||
"&" -> expressionEval.operatorAndInplace(address, null, vmDt, value).chunks
|
"&" -> expressionEval.operatorAndInplace(address, null, vmDt, value)
|
||||||
"^" -> expressionEval.operatorXorInplace(address, null, vmDt, value).chunks
|
"^" -> expressionEval.operatorXorInplace(address, null, vmDt, value)
|
||||||
"<<" -> expressionEval.operatorShiftLeftInplace(address, null, vmDt, value).chunks
|
"<<" -> expressionEval.operatorShiftLeftInplace(address, null, vmDt, value)
|
||||||
">>" -> expressionEval.operatorShiftRightInplace(address, null, vmDt, value.type in SignedDatatypes, value).chunks
|
">>" -> expressionEval.operatorShiftRightInplace(address, null, vmDt, value.type in SignedDatatypes, value)
|
||||||
|
"%=" -> expressionEval.operatorModuloInplace(address, null, vmDt, value)
|
||||||
|
"==" -> expressionEval.operatorEqualsInplace(address, null, vmDt, value)
|
||||||
|
"!=" -> expressionEval.operatorNotEqualsInplace(address, null, vmDt, value)
|
||||||
|
"<" -> expressionEval.operatorLessInplace(address, null, vmDt, value.type in SignedDatatypes, value)
|
||||||
|
">" -> expressionEval.operatorGreaterInplace(address, null, vmDt, value.type in SignedDatatypes, value)
|
||||||
|
"<=" -> expressionEval.operatorLessEqualInplace(address, null, vmDt, value.type in SignedDatatypes, value)
|
||||||
|
">=" -> expressionEval.operatorGreaterEqualInplace(address, null, vmDt, value.type in SignedDatatypes, value)
|
||||||
in PrefixOperators -> inplacePrefix(assignment.operator, vmDt, address, null)
|
in PrefixOperators -> inplacePrefix(assignment.operator, vmDt, address, null)
|
||||||
|
|
||||||
else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}")
|
else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}")
|
||||||
@@ -67,15 +74,22 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
val value = assignment.value
|
val value = assignment.value
|
||||||
val valueVmDt = codeGen.irType(value.type)
|
val valueVmDt = codeGen.irType(value.type)
|
||||||
return when (assignment.operator) {
|
return when (assignment.operator) {
|
||||||
"+=" -> expressionEval.operatorPlusInplace(null, symbol, valueVmDt, value).chunks
|
"+=" -> expressionEval.operatorPlusInplace(null, symbol, valueVmDt, value)
|
||||||
"-=" -> expressionEval.operatorMinusInplace(null, symbol, valueVmDt, value).chunks
|
"-=" -> expressionEval.operatorMinusInplace(null, symbol, valueVmDt, value)
|
||||||
"*=" -> expressionEval.operatorMultiplyInplace(null, symbol, valueVmDt, value).chunks
|
"*=" -> expressionEval.operatorMultiplyInplace(null, symbol, valueVmDt, value)
|
||||||
"/=" -> expressionEval.operatorDivideInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value).chunks
|
"/=" -> expressionEval.operatorDivideInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
||||||
"|=" -> expressionEval.operatorOrInplace(null, symbol, valueVmDt, value).chunks
|
"|=" -> expressionEval.operatorOrInplace(null, symbol, valueVmDt, value)
|
||||||
"&=" -> expressionEval.operatorAndInplace(null, symbol, valueVmDt, value).chunks
|
"&=" -> expressionEval.operatorAndInplace(null, symbol, valueVmDt, value)
|
||||||
"^=" -> expressionEval.operatorXorInplace(null, symbol, valueVmDt, value).chunks
|
"^=" -> expressionEval.operatorXorInplace(null, symbol, valueVmDt, value)
|
||||||
"<<=" -> expressionEval.operatorShiftLeftInplace(null, symbol, valueVmDt, value).chunks
|
"<<=" -> expressionEval.operatorShiftLeftInplace(null, symbol, valueVmDt, value)
|
||||||
">>=" -> expressionEval.operatorShiftRightInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value).chunks
|
">>=" -> expressionEval.operatorShiftRightInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
||||||
|
"%=" -> expressionEval.operatorModuloInplace(null, symbol, valueVmDt, value)
|
||||||
|
"==" -> expressionEval.operatorEqualsInplace(null, symbol, valueVmDt, value)
|
||||||
|
"!=" -> expressionEval.operatorNotEqualsInplace(null, symbol, valueVmDt, value)
|
||||||
|
"<" -> expressionEval.operatorLessInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
||||||
|
">" -> expressionEval.operatorGreaterInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
||||||
|
"<=" -> expressionEval.operatorLessEqualInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
||||||
|
">=" -> expressionEval.operatorGreaterEqualInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
||||||
in PrefixOperators -> inplacePrefix(assignment.operator, valueVmDt, null, symbol)
|
in PrefixOperators -> inplacePrefix(assignment.operator, valueVmDt, null, symbol)
|
||||||
else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}")
|
else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}")
|
||||||
}
|
}
|
||||||
@@ -84,8 +98,6 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
private fun fallbackAssign(origAssign: PtAugmentedAssign): IRCodeChunks {
|
private fun fallbackAssign(origAssign: PtAugmentedAssign): IRCodeChunks {
|
||||||
if (codeGen.options.slowCodegenWarnings)
|
if (codeGen.options.slowCodegenWarnings)
|
||||||
codeGen.errors.warn("indirect code for in-place assignment", origAssign.position)
|
codeGen.errors.warn("indirect code for in-place assignment", origAssign.position)
|
||||||
val normalAssign = PtAssignment(origAssign.position)
|
|
||||||
normalAssign.add(origAssign.target)
|
|
||||||
val value: PtExpression
|
val value: PtExpression
|
||||||
if(origAssign.operator in PrefixOperators) {
|
if(origAssign.operator in PrefixOperators) {
|
||||||
value = PtPrefix(origAssign.operator, origAssign.value.type, origAssign.value.position)
|
value = PtPrefix(origAssign.operator, origAssign.value.type, origAssign.value.position)
|
||||||
@@ -93,7 +105,21 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
} else {
|
} else {
|
||||||
require(origAssign.operator.endsWith('='))
|
require(origAssign.operator.endsWith('='))
|
||||||
if(codeGen.options.useNewExprCode) {
|
if(codeGen.options.useNewExprCode) {
|
||||||
TODO("use something else than a BinExpr")
|
// X += Y -> temp = X, temp += Y, X = temp
|
||||||
|
val tempvarname = "some_random_tempvar" // TODO create proper tempvar
|
||||||
|
val tempvar = PtIdentifier(tempvarname, origAssign.target.type, origAssign.position)
|
||||||
|
val assign = PtAssignment(origAssign.position)
|
||||||
|
val target = PtAssignTarget(origAssign.position)
|
||||||
|
target.add(tempvar)
|
||||||
|
assign.add(target)
|
||||||
|
assign.add(origAssign.target.children.single())
|
||||||
|
val augAssign = PtAugmentedAssign(origAssign.operator, origAssign.position)
|
||||||
|
augAssign.add(target)
|
||||||
|
augAssign.add(origAssign.value)
|
||||||
|
val assignBack = PtAssignment(origAssign.position)
|
||||||
|
assignBack.add(origAssign.target)
|
||||||
|
assignBack.add(tempvar)
|
||||||
|
return translateRegularAssign(assign) + translate(augAssign) + translateRegularAssign(assignBack)
|
||||||
} else {
|
} else {
|
||||||
value = PtBinaryExpression(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position)
|
value = PtBinaryExpression(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position)
|
||||||
val left: PtExpression = origAssign.target.children.single() as PtExpression
|
val left: PtExpression = origAssign.target.children.single() as PtExpression
|
||||||
@@ -101,6 +127,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
value.add(origAssign.value)
|
value.add(origAssign.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val normalAssign = PtAssignment(origAssign.position)
|
||||||
|
normalAssign.add(origAssign.target)
|
||||||
normalAssign.add(value)
|
normalAssign.add(value)
|
||||||
return translateRegularAssign(normalAssign)
|
return translateRegularAssign(normalAssign)
|
||||||
}
|
}
|
||||||
@@ -262,18 +290,20 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
|
|
||||||
private fun loadIndexReg(array: PtArrayIndexer, itemsize: Int): Pair<IRCodeChunks, Int> {
|
private fun loadIndexReg(array: PtArrayIndexer, itemsize: Int): Pair<IRCodeChunks, Int> {
|
||||||
// returns the code to load the Index into the register, which is also return\ed.
|
// returns the code to load the Index into the register, which is also return\ed.
|
||||||
|
|
||||||
|
if(codeGen.options.useNewExprCode) {
|
||||||
|
TODO("use aug assigns instead of BinExpr to calc proper array index")
|
||||||
|
// return blah
|
||||||
|
}
|
||||||
|
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val tr = if(itemsize==1) {
|
val tr = if(itemsize==1) {
|
||||||
expressionEval.translateExpression(array.index)
|
expressionEval.translateExpression(array.index)
|
||||||
} else {
|
} else {
|
||||||
val mult : PtExpression
|
val mult : PtExpression
|
||||||
if(codeGen.options.useNewExprCode) {
|
mult = PtBinaryExpression("*", DataType.UBYTE, array.position)
|
||||||
TODO("use something else than a BinExpr")
|
mult.children += array.index
|
||||||
} else {
|
mult.children += PtNumber(DataType.UBYTE, itemsize.toDouble(), array.position)
|
||||||
mult = PtBinaryExpression("*", DataType.UBYTE, array.position)
|
|
||||||
mult.children += array.index
|
|
||||||
mult.children += PtNumber(DataType.UBYTE, itemsize.toDouble(), array.position)
|
|
||||||
}
|
|
||||||
expressionEval.translateExpression(mult)
|
expressionEval.translateExpression(mult)
|
||||||
}
|
}
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
|
@@ -925,7 +925,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun operatorAndInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): ExpressionCodeResult {
|
internal fun operatorAndInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val tr = translateExpression(operand)
|
val tr = translateExpression(operand)
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
@@ -934,10 +934,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
else
|
else
|
||||||
IRInstruction(Opcode.ANDM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
IRInstruction(Opcode.ANDM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||||
,null)
|
,null)
|
||||||
return ExpressionCodeResult(result, vmDt, -1, -1)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorOrInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): ExpressionCodeResult {
|
internal fun operatorOrInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val tr = translateExpression(operand)
|
val tr = translateExpression(operand)
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
@@ -946,10 +946,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
else
|
else
|
||||||
IRInstruction(Opcode.ORM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
IRInstruction(Opcode.ORM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||||
, null)
|
, null)
|
||||||
return ExpressionCodeResult(result, vmDt, -1, -1)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorDivideInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): ExpressionCodeResult {
|
internal fun operatorDivideInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val constFactorRight = operand as? PtNumber
|
val constFactorRight = operand as? PtNumber
|
||||||
if(vmDt==IRDataType.FLOAT) {
|
if(vmDt==IRDataType.FLOAT) {
|
||||||
@@ -995,10 +995,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
addInstr(result, ins, null)
|
addInstr(result, ins, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ExpressionCodeResult(result, vmDt, -1, -1)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorMultiplyInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): ExpressionCodeResult {
|
internal fun operatorMultiplyInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val constFactorRight = operand as? PtNumber
|
val constFactorRight = operand as? PtNumber
|
||||||
if(vmDt==IRDataType.FLOAT) {
|
if(vmDt==IRDataType.FLOAT) {
|
||||||
@@ -1028,10 +1028,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
, null)
|
, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ExpressionCodeResult(result, vmDt, -1, -1)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorMinusInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): ExpressionCodeResult {
|
internal fun operatorMinusInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
if(vmDt==IRDataType.FLOAT) {
|
if(vmDt==IRDataType.FLOAT) {
|
||||||
if((operand as? PtNumber)?.number==1.0) {
|
if((operand as? PtNumber)?.number==1.0) {
|
||||||
@@ -1068,10 +1068,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
, null)
|
, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ExpressionCodeResult(result, vmDt, -1, -1)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorPlusInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): ExpressionCodeResult {
|
internal fun operatorPlusInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
if(vmDt==IRDataType.FLOAT) {
|
if(vmDt==IRDataType.FLOAT) {
|
||||||
if((operand as? PtNumber)?.number==1.0) {
|
if((operand as? PtNumber)?.number==1.0) {
|
||||||
@@ -1108,10 +1108,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
, null)
|
, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ExpressionCodeResult(result, vmDt, -1, -1)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorShiftRightInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): ExpressionCodeResult {
|
internal fun operatorShiftRightInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
if(codeGen.isOne(operand)) {
|
if(codeGen.isOne(operand)) {
|
||||||
val opc = if (signed) Opcode.ASRM else Opcode.LSRM
|
val opc = if (signed) Opcode.ASRM else Opcode.LSRM
|
||||||
@@ -1130,10 +1130,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
IRInstruction(opc, vmDt, reg1 = tr.resultReg, labelSymbol = symbol)
|
IRInstruction(opc, vmDt, reg1 = tr.resultReg, labelSymbol = symbol)
|
||||||
addInstr(result, ins, null)
|
addInstr(result, ins, null)
|
||||||
}
|
}
|
||||||
return ExpressionCodeResult(result, vmDt, -1, -1)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorShiftLeftInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): ExpressionCodeResult {
|
internal fun operatorShiftLeftInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
if(codeGen.isOne(operand)){
|
if(codeGen.isOne(operand)){
|
||||||
addInstr(result, if(knownAddress!=null)
|
addInstr(result, if(knownAddress!=null)
|
||||||
@@ -1150,10 +1150,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
IRInstruction(Opcode.LSLNM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
IRInstruction(Opcode.LSLNM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||||
,null)
|
,null)
|
||||||
}
|
}
|
||||||
return ExpressionCodeResult(result, vmDt, -1, -1)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorXorInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): ExpressionCodeResult {
|
internal fun operatorXorInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val tr = translateExpression(operand)
|
val tr = translateExpression(operand)
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
@@ -1162,9 +1162,198 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
else
|
else
|
||||||
IRInstruction(Opcode.XORM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
IRInstruction(Opcode.XORM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||||
,null)
|
,null)
|
||||||
return ExpressionCodeResult(result, vmDt, -1, -1)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun operatorModuloInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
|
val resultReg = codeGen.registers.nextFree()
|
||||||
|
if(operand is PtNumber) {
|
||||||
|
val number = operand.number.toInt()
|
||||||
|
if (knownAddress != null) {
|
||||||
|
// @(address) = @(address) %= operand
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = resultReg, value = knownAddress)
|
||||||
|
it += IRInstruction(Opcode.MOD, vmDt, reg1 = resultReg, value = number)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = resultReg, value = knownAddress)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// symbol = symbol %= operand
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = resultReg, labelSymbol = symbol)
|
||||||
|
it += IRInstruction(Opcode.MOD, vmDt, reg1 = resultReg, value = number)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = resultReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val tr = translateExpression(operand)
|
||||||
|
result += tr.chunks
|
||||||
|
if (knownAddress != null) {
|
||||||
|
// @(address) = @(address) %= operand
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = resultReg, value = knownAddress)
|
||||||
|
it += IRInstruction(Opcode.MODR, vmDt, reg1 = resultReg, reg2 = tr.resultReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = resultReg, value = knownAddress)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// symbol = symbol %= operand
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = resultReg, labelSymbol = symbol)
|
||||||
|
it += IRInstruction(Opcode.MODR, vmDt, reg1 = resultReg, reg2 = tr.resultReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = resultReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun operatorEqualsInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
|
val tr = translateExpression(operand)
|
||||||
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
|
if(knownAddress!=null) {
|
||||||
|
// @(address) = @(address) == operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
||||||
|
it += IRInstruction(Opcode.SEQ, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, value=knownAddress)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// symbol = symbol == operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
||||||
|
it += IRInstruction(Opcode.SEQ, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun operatorNotEqualsInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
|
val tr = translateExpression(operand)
|
||||||
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
|
if(knownAddress!=null) {
|
||||||
|
// @(address) = @(address) != operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
||||||
|
it += IRInstruction(Opcode.SNE, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, value=knownAddress)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// symbol = symbol != operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
||||||
|
it += IRInstruction(Opcode.SNE, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun operatorGreaterInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
||||||
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
|
val tr = translateExpression(operand)
|
||||||
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
|
val opcode = if(signed) Opcode.SGTS else Opcode.SGT
|
||||||
|
if(knownAddress!=null) {
|
||||||
|
// @(address) = @(address) > operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
||||||
|
it += IRInstruction(opcode, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, value=knownAddress)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// symbol = symbol > operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
||||||
|
it += IRInstruction(opcode, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun operatorLessInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
||||||
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
|
val tr = translateExpression(operand)
|
||||||
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
|
val opcode = if(signed) Opcode.SLTS else Opcode.SLT
|
||||||
|
if(knownAddress!=null) {
|
||||||
|
// @(address) = @(address) < operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
||||||
|
it += IRInstruction(opcode, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, value=knownAddress)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// symbol = symbol < operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
||||||
|
it += IRInstruction(opcode, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun operatorGreaterEqualInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
||||||
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
|
val tr = translateExpression(operand)
|
||||||
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
|
val opcode = if(signed) Opcode.SGES else Opcode.SGE
|
||||||
|
if(knownAddress!=null) {
|
||||||
|
// @(address) = @(address) > operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
||||||
|
it += IRInstruction(opcode, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, value=knownAddress)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// symbol = symbol > operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
||||||
|
it += IRInstruction(opcode, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun operatorLessEqualInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
||||||
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
|
val tr = translateExpression(operand)
|
||||||
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
|
val opcode = if(signed) Opcode.SLES else Opcode.SLE
|
||||||
|
if(knownAddress!=null) {
|
||||||
|
// @(address) = @(address) > operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
||||||
|
it += IRInstruction(opcode, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, value=knownAddress)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// symbol = symbol > operand
|
||||||
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
||||||
|
it += IRInstruction(opcode, vmDt, reg1=tr.resultReg, reg2=valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -912,67 +912,83 @@ class IRCodeGen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
throw AssemblyError("weird condition node: $condition")
|
// if X --> meaning: if X!=0
|
||||||
|
require(options.useNewExprCode)
|
||||||
|
val irDt = irType(condition.type)
|
||||||
|
val signed = condition.type in SignedDatatypes
|
||||||
|
return if(goto!=null && ifElse.elseScope.children.isEmpty()) {
|
||||||
|
translateIfFollowedByJustGoto(ifElse, goto, irDt, signed)
|
||||||
|
} else {
|
||||||
|
translateIfElseNonZeroComparison(ifElse, irDt, signed)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun translateIfFollowedByJustGoto(ifElse: PtIfElse, goto: PtJump, irDtLeft: IRDataType, signed: Boolean): MutableList<IRCodeChunkBase> {
|
private fun translateIfFollowedByJustGoto(ifElse: PtIfElse, goto: PtJump, irDtLeft: IRDataType, signed: Boolean): MutableList<IRCodeChunkBase> {
|
||||||
val condition = ifElse.condition as PtBinaryExpression
|
val conditionBinExpr = ifElse.condition as? PtBinaryExpression
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
if (irDtLeft == IRDataType.FLOAT) {
|
if(conditionBinExpr==null) {
|
||||||
val leftTr = expressionEval.translateExpression(condition.left)
|
if(irDtLeft==IRDataType.FLOAT)
|
||||||
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
throw AssemblyError("condition value should not be float")
|
||||||
val rightTr = expressionEval.translateExpression(condition.right)
|
ifNonZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
|
||||||
addToResult(result, rightTr, -1, rightTr.resultFpReg)
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
val compResultReg = registers.nextFree()
|
|
||||||
it += IRInstruction(
|
|
||||||
Opcode.FCOMP,
|
|
||||||
IRDataType.FLOAT,
|
|
||||||
reg1 = compResultReg,
|
|
||||||
fpReg1 = leftTr.resultFpReg,
|
|
||||||
fpReg2 = rightTr.resultFpReg
|
|
||||||
)
|
|
||||||
val gotoOpcode = when (condition.operator) {
|
|
||||||
"==" -> Opcode.BZ
|
|
||||||
"!=" -> Opcode.BNZ
|
|
||||||
"<" -> Opcode.BLEZS
|
|
||||||
">" -> Opcode.BGEZS
|
|
||||||
"<=" -> Opcode.BLZS
|
|
||||||
">=" -> Opcode.BGZS
|
|
||||||
else -> throw AssemblyError("weird operator")
|
|
||||||
}
|
|
||||||
it += if (goto.address != null)
|
|
||||||
IRInstruction(
|
|
||||||
gotoOpcode,
|
|
||||||
IRDataType.BYTE,
|
|
||||||
reg1 = compResultReg,
|
|
||||||
value = goto.address?.toInt()
|
|
||||||
)
|
|
||||||
else if (goto.generatedLabel != null)
|
|
||||||
IRInstruction(
|
|
||||||
gotoOpcode,
|
|
||||||
IRDataType.BYTE,
|
|
||||||
reg1 = compResultReg,
|
|
||||||
labelSymbol = goto.generatedLabel
|
|
||||||
)
|
|
||||||
else
|
|
||||||
IRInstruction(
|
|
||||||
gotoOpcode,
|
|
||||||
IRDataType.BYTE,
|
|
||||||
reg1 = compResultReg,
|
|
||||||
labelSymbol = goto.identifier!!.name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return result
|
return result
|
||||||
} else {
|
} else {
|
||||||
val rightConst = condition.right.asConstInteger()
|
if (irDtLeft == IRDataType.FLOAT) {
|
||||||
return if (rightConst == 0)
|
val leftTr = expressionEval.translateExpression(conditionBinExpr.left)
|
||||||
ifZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
|
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
||||||
else {
|
val rightTr = expressionEval.translateExpression(conditionBinExpr.right)
|
||||||
ifNonZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
|
addToResult(result, rightTr, -1, rightTr.resultFpReg)
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
val compResultReg = registers.nextFree()
|
||||||
|
it += IRInstruction(
|
||||||
|
Opcode.FCOMP,
|
||||||
|
IRDataType.FLOAT,
|
||||||
|
reg1 = compResultReg,
|
||||||
|
fpReg1 = leftTr.resultFpReg,
|
||||||
|
fpReg2 = rightTr.resultFpReg
|
||||||
|
)
|
||||||
|
val gotoOpcode = when (conditionBinExpr.operator) {
|
||||||
|
"==" -> Opcode.BZ
|
||||||
|
"!=" -> Opcode.BNZ
|
||||||
|
"<" -> Opcode.BLEZS
|
||||||
|
">" -> Opcode.BGEZS
|
||||||
|
"<=" -> Opcode.BLZS
|
||||||
|
">=" -> Opcode.BGZS
|
||||||
|
else -> throw AssemblyError("weird operator")
|
||||||
|
}
|
||||||
|
it += if (goto.address != null)
|
||||||
|
IRInstruction(
|
||||||
|
gotoOpcode,
|
||||||
|
IRDataType.BYTE,
|
||||||
|
reg1 = compResultReg,
|
||||||
|
value = goto.address?.toInt()
|
||||||
|
)
|
||||||
|
else if (goto.generatedLabel != null)
|
||||||
|
IRInstruction(
|
||||||
|
gotoOpcode,
|
||||||
|
IRDataType.BYTE,
|
||||||
|
reg1 = compResultReg,
|
||||||
|
labelSymbol = goto.generatedLabel
|
||||||
|
)
|
||||||
|
else
|
||||||
|
IRInstruction(
|
||||||
|
gotoOpcode,
|
||||||
|
IRDataType.BYTE,
|
||||||
|
reg1 = compResultReg,
|
||||||
|
labelSymbol = goto.identifier!!.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} else {
|
||||||
|
val rightConst = conditionBinExpr.right.asConstInteger()
|
||||||
|
if (rightConst == 0)
|
||||||
|
ifZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
|
||||||
|
else {
|
||||||
|
ifNonZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -983,7 +999,7 @@ class IRCodeGen(
|
|||||||
signed: Boolean,
|
signed: Boolean,
|
||||||
irDtLeft: IRDataType,
|
irDtLeft: IRDataType,
|
||||||
goto: PtJump
|
goto: PtJump
|
||||||
): MutableList<IRCodeChunkBase> {
|
) {
|
||||||
val condition = ifElse.condition as PtBinaryExpression
|
val condition = ifElse.condition as PtBinaryExpression
|
||||||
val leftTr = expressionEval.translateExpression(condition.left)
|
val leftTr = expressionEval.translateExpression(condition.left)
|
||||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||||
@@ -1002,7 +1018,6 @@ class IRCodeGen(
|
|||||||
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, labelSymbol = goto.generatedLabel), null)
|
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, labelSymbol = goto.generatedLabel), null)
|
||||||
else
|
else
|
||||||
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, labelSymbol = goto.identifier!!.name), null)
|
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, labelSymbol = goto.identifier!!.name), null)
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ifNonZeroIntThenJump(
|
private fun ifNonZeroIntThenJump(
|
||||||
@@ -1011,57 +1026,67 @@ class IRCodeGen(
|
|||||||
signed: Boolean,
|
signed: Boolean,
|
||||||
irDtLeft: IRDataType,
|
irDtLeft: IRDataType,
|
||||||
goto: PtJump
|
goto: PtJump
|
||||||
): MutableList<IRCodeChunkBase> {
|
) {
|
||||||
val condition = ifElse.condition as PtBinaryExpression
|
val conditionBinExpr = ifElse.condition as? PtBinaryExpression
|
||||||
val leftTr = expressionEval.translateExpression(condition.left)
|
if(conditionBinExpr==null) {
|
||||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
val tr = expressionEval.translateExpression(ifElse.condition)
|
||||||
val rightTr = expressionEval.translateExpression(condition.right)
|
result += tr.chunks
|
||||||
addToResult(result, rightTr, rightTr.resultReg, -1)
|
if (goto.address != null)
|
||||||
val opcode: Opcode
|
addInstr(result, IRInstruction(Opcode.BNZ, irDtLeft, reg1 = tr.resultReg, value = goto.address?.toInt()), null)
|
||||||
val firstReg: Int
|
else if (goto.generatedLabel != null)
|
||||||
val secondReg: Int
|
addInstr(result, IRInstruction(Opcode.BNZ, irDtLeft, reg1 = tr.resultReg, labelSymbol = goto.generatedLabel), null)
|
||||||
when (condition.operator) {
|
else
|
||||||
"==" -> {
|
addInstr(result, IRInstruction(Opcode.BNZ, irDtLeft, reg1 = tr.resultReg, labelSymbol = goto.identifier!!.name), null)
|
||||||
opcode = Opcode.BEQ
|
} else {
|
||||||
firstReg = leftTr.resultReg
|
val leftTr = expressionEval.translateExpression(conditionBinExpr.left)
|
||||||
secondReg = rightTr.resultReg
|
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||||
|
val rightTr = expressionEval.translateExpression(conditionBinExpr.right)
|
||||||
|
addToResult(result, rightTr, rightTr.resultReg, -1)
|
||||||
|
val opcode: Opcode
|
||||||
|
val firstReg: Int
|
||||||
|
val secondReg: Int
|
||||||
|
when (conditionBinExpr.operator) {
|
||||||
|
"==" -> {
|
||||||
|
opcode = Opcode.BEQ
|
||||||
|
firstReg = leftTr.resultReg
|
||||||
|
secondReg = rightTr.resultReg
|
||||||
|
}
|
||||||
|
"!=" -> {
|
||||||
|
opcode = Opcode.BNE
|
||||||
|
firstReg = leftTr.resultReg
|
||||||
|
secondReg = rightTr.resultReg
|
||||||
|
}
|
||||||
|
"<" -> {
|
||||||
|
// swapped '>'
|
||||||
|
opcode = if (signed) Opcode.BGTS else Opcode.BGT
|
||||||
|
firstReg = rightTr.resultReg
|
||||||
|
secondReg = leftTr.resultReg
|
||||||
|
}
|
||||||
|
">" -> {
|
||||||
|
opcode = if (signed) Opcode.BGTS else Opcode.BGT
|
||||||
|
firstReg = leftTr.resultReg
|
||||||
|
secondReg = rightTr.resultReg
|
||||||
|
}
|
||||||
|
"<=" -> {
|
||||||
|
// swapped '>='
|
||||||
|
opcode = if (signed) Opcode.BGES else Opcode.BGE
|
||||||
|
firstReg = rightTr.resultReg
|
||||||
|
secondReg = leftTr.resultReg
|
||||||
|
}
|
||||||
|
">=" -> {
|
||||||
|
opcode = if (signed) Opcode.BGES else Opcode.BGE
|
||||||
|
firstReg = leftTr.resultReg
|
||||||
|
secondReg = rightTr.resultReg
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("invalid comparison operator")
|
||||||
}
|
}
|
||||||
"!=" -> {
|
if (goto.address != null)
|
||||||
opcode = Opcode.BNE
|
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, reg2 = secondReg, value = goto.address?.toInt()), null)
|
||||||
firstReg = leftTr.resultReg
|
else if (goto.generatedLabel != null)
|
||||||
secondReg = rightTr.resultReg
|
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, reg2 = secondReg, labelSymbol = goto.generatedLabel), null)
|
||||||
}
|
else
|
||||||
"<" -> {
|
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, reg2 = secondReg, labelSymbol = goto.identifier!!.name), null)
|
||||||
// swapped '>'
|
|
||||||
opcode = if (signed) Opcode.BGTS else Opcode.BGT
|
|
||||||
firstReg = rightTr.resultReg
|
|
||||||
secondReg = leftTr.resultReg
|
|
||||||
}
|
|
||||||
">" -> {
|
|
||||||
opcode = if (signed) Opcode.BGTS else Opcode.BGT
|
|
||||||
firstReg = leftTr.resultReg
|
|
||||||
secondReg = rightTr.resultReg
|
|
||||||
}
|
|
||||||
"<=" -> {
|
|
||||||
// swapped '>='
|
|
||||||
opcode = if (signed) Opcode.BGES else Opcode.BGE
|
|
||||||
firstReg = rightTr.resultReg
|
|
||||||
secondReg = leftTr.resultReg
|
|
||||||
}
|
|
||||||
">=" -> {
|
|
||||||
opcode = if (signed) Opcode.BGES else Opcode.BGE
|
|
||||||
firstReg = leftTr.resultReg
|
|
||||||
secondReg = rightTr.resultReg
|
|
||||||
}
|
|
||||||
else -> throw AssemblyError("invalid comparison operator")
|
|
||||||
}
|
}
|
||||||
if (goto.address != null)
|
|
||||||
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, reg2 = secondReg, value = goto.address?.toInt()), null)
|
|
||||||
else if (goto.generatedLabel != null)
|
|
||||||
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, reg2 = secondReg, labelSymbol = goto.generatedLabel), null)
|
|
||||||
else
|
|
||||||
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, reg2 = secondReg, labelSymbol = goto.identifier!!.name), null)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateIfElseZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks {
|
private fun translateIfElseZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks {
|
||||||
@@ -1131,106 +1156,160 @@ class IRCodeGen(
|
|||||||
val elseBranchFirstReg: Int
|
val elseBranchFirstReg: Int
|
||||||
val elseBranchSecondReg: Int
|
val elseBranchSecondReg: Int
|
||||||
val branchDt: IRDataType
|
val branchDt: IRDataType
|
||||||
val condition = ifElse.condition as PtBinaryExpression
|
val condition = ifElse.condition as? PtBinaryExpression
|
||||||
if(irDtLeft==IRDataType.FLOAT) {
|
if(condition==null) {
|
||||||
val leftTr = expressionEval.translateExpression(condition.left)
|
if(irDtLeft==IRDataType.FLOAT)
|
||||||
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
throw AssemblyError("condition value should not be float")
|
||||||
val rightTr = expressionEval.translateExpression(condition.right)
|
val tr = expressionEval.translateExpression(ifElse.condition)
|
||||||
addToResult(result, rightTr, -1, rightTr.resultFpReg)
|
result += tr.chunks
|
||||||
val compResultReg = registers.nextFree()
|
|
||||||
addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
|
|
||||||
val elseBranch = when (condition.operator) {
|
|
||||||
"==" -> Opcode.BNZ
|
|
||||||
"!=" -> Opcode.BZ
|
|
||||||
"<" -> Opcode.BGEZS
|
|
||||||
">" -> Opcode.BLEZS
|
|
||||||
"<=" -> Opcode.BGZS
|
|
||||||
">=" -> Opcode.BLZS
|
|
||||||
else -> throw AssemblyError("weird operator")
|
|
||||||
}
|
|
||||||
if(ifElse.elseScope.children.isNotEmpty()) {
|
if(ifElse.elseScope.children.isNotEmpty()) {
|
||||||
// if and else parts
|
|
||||||
val elseLabel = createLabelName()
|
val elseLabel = createLabelName()
|
||||||
val afterIfLabel = createLabelName()
|
val afterIfLabel = createLabelName()
|
||||||
addInstr(result, IRInstruction(elseBranch, IRDataType.BYTE, reg1=compResultReg, labelSymbol = elseLabel), null)
|
addInstr(result, IRInstruction(Opcode.BZ, irDtLeft, reg1=tr.resultReg, labelSymbol = elseLabel), null)
|
||||||
result += translateNode(ifElse.ifScope)
|
result += translateNode(ifElse.ifScope)
|
||||||
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null)
|
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null)
|
||||||
result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel)
|
result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel)
|
||||||
result += IRCodeChunk(afterIfLabel, null)
|
result += IRCodeChunk(afterIfLabel, null)
|
||||||
} else {
|
} else {
|
||||||
// only if part
|
|
||||||
val afterIfLabel = createLabelName()
|
val afterIfLabel = createLabelName()
|
||||||
addInstr(result, IRInstruction(elseBranch, IRDataType.BYTE, reg1=compResultReg, labelSymbol = afterIfLabel), null)
|
addInstr(result, IRInstruction(Opcode.BZ, irDtLeft, reg1=tr.resultReg, labelSymbol = afterIfLabel), null)
|
||||||
result += translateNode(ifElse.ifScope)
|
result += translateNode(ifElse.ifScope)
|
||||||
result += IRCodeChunk(afterIfLabel, null)
|
result += IRCodeChunk(afterIfLabel, null)
|
||||||
}
|
}
|
||||||
|
return result
|
||||||
} else {
|
} else {
|
||||||
// integer comparisons
|
if (irDtLeft == IRDataType.FLOAT) {
|
||||||
branchDt = irDtLeft
|
val leftTr = expressionEval.translateExpression(condition.left)
|
||||||
val leftTr = expressionEval.translateExpression(condition.left)
|
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
||||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
val rightTr = expressionEval.translateExpression(condition.right)
|
||||||
val rightTr = expressionEval.translateExpression(condition.right)
|
addToResult(result, rightTr, -1, rightTr.resultFpReg)
|
||||||
addToResult(result, rightTr, rightTr.resultReg, -1)
|
val compResultReg = registers.nextFree()
|
||||||
when (condition.operator) {
|
addInstr(
|
||||||
"==" -> {
|
result,
|
||||||
elseBranchOpcode = Opcode.BNE
|
IRInstruction(
|
||||||
elseBranchFirstReg = leftTr.resultReg
|
Opcode.FCOMP,
|
||||||
elseBranchSecondReg = rightTr.resultReg
|
IRDataType.FLOAT,
|
||||||
|
reg1 = compResultReg,
|
||||||
|
fpReg1 = leftTr.resultFpReg,
|
||||||
|
fpReg2 = rightTr.resultFpReg
|
||||||
|
),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
val elseBranch = when (condition.operator) {
|
||||||
|
"==" -> Opcode.BNZ
|
||||||
|
"!=" -> Opcode.BZ
|
||||||
|
"<" -> Opcode.BGEZS
|
||||||
|
">" -> Opcode.BLEZS
|
||||||
|
"<=" -> Opcode.BGZS
|
||||||
|
">=" -> Opcode.BLZS
|
||||||
|
else -> throw AssemblyError("weird operator")
|
||||||
}
|
}
|
||||||
"!=" -> {
|
if (ifElse.elseScope.children.isNotEmpty()) {
|
||||||
elseBranchOpcode = Opcode.BEQ
|
// if and else parts
|
||||||
elseBranchFirstReg = leftTr.resultReg
|
val elseLabel = createLabelName()
|
||||||
elseBranchSecondReg = rightTr.resultReg
|
val afterIfLabel = createLabelName()
|
||||||
|
addInstr(
|
||||||
|
result,
|
||||||
|
IRInstruction(elseBranch, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = elseLabel),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
result += translateNode(ifElse.ifScope)
|
||||||
|
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null)
|
||||||
|
result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel)
|
||||||
|
result += IRCodeChunk(afterIfLabel, null)
|
||||||
|
} else {
|
||||||
|
// only if part
|
||||||
|
val afterIfLabel = createLabelName()
|
||||||
|
addInstr(
|
||||||
|
result,
|
||||||
|
IRInstruction(elseBranch, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = afterIfLabel),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
result += translateNode(ifElse.ifScope)
|
||||||
|
result += IRCodeChunk(afterIfLabel, null)
|
||||||
}
|
}
|
||||||
"<" -> {
|
|
||||||
// else part when left >= right
|
|
||||||
elseBranchOpcode = if (signed) Opcode.BGES else Opcode.BGE
|
|
||||||
elseBranchFirstReg = leftTr.resultReg
|
|
||||||
elseBranchSecondReg = rightTr.resultReg
|
|
||||||
}
|
|
||||||
">" -> {
|
|
||||||
// else part when left <= right --> right >= left
|
|
||||||
elseBranchOpcode = if (signed) Opcode.BGES else Opcode.BGE
|
|
||||||
elseBranchFirstReg = rightTr.resultReg
|
|
||||||
elseBranchSecondReg = leftTr.resultReg
|
|
||||||
}
|
|
||||||
"<=" -> {
|
|
||||||
// else part when left > right
|
|
||||||
elseBranchOpcode = if (signed) Opcode.BGTS else Opcode.BGT
|
|
||||||
elseBranchFirstReg = leftTr.resultReg
|
|
||||||
elseBranchSecondReg = rightTr.resultReg
|
|
||||||
}
|
|
||||||
">=" -> {
|
|
||||||
// else part when left < right --> right > left
|
|
||||||
elseBranchOpcode = if (signed) Opcode.BGTS else Opcode.BGT
|
|
||||||
elseBranchFirstReg = rightTr.resultReg
|
|
||||||
elseBranchSecondReg = leftTr.resultReg
|
|
||||||
}
|
|
||||||
else -> throw AssemblyError("invalid comparison operator")
|
|
||||||
}
|
|
||||||
if(ifElse.elseScope.children.isNotEmpty()) {
|
|
||||||
// if and else parts
|
|
||||||
val elseLabel = createLabelName()
|
|
||||||
val afterIfLabel = createLabelName()
|
|
||||||
addInstr(result, IRInstruction(elseBranchOpcode, branchDt,
|
|
||||||
reg1=elseBranchFirstReg, reg2=elseBranchSecondReg,
|
|
||||||
labelSymbol = elseLabel), null)
|
|
||||||
result += translateNode(ifElse.ifScope)
|
|
||||||
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null)
|
|
||||||
result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel)
|
|
||||||
result += IRCodeChunk(afterIfLabel, null)
|
|
||||||
} else {
|
} else {
|
||||||
// only if part
|
// integer comparisons
|
||||||
val afterIfLabel = createLabelName()
|
branchDt = irDtLeft
|
||||||
addInstr(result, IRInstruction(elseBranchOpcode, branchDt,
|
val leftTr = expressionEval.translateExpression(condition.left)
|
||||||
reg1=elseBranchFirstReg, reg2=elseBranchSecondReg,
|
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||||
labelSymbol = afterIfLabel), null)
|
val rightTr = expressionEval.translateExpression(condition.right)
|
||||||
result += translateNode(ifElse.ifScope)
|
addToResult(result, rightTr, rightTr.resultReg, -1)
|
||||||
result += IRCodeChunk(afterIfLabel, null)
|
when (condition.operator) {
|
||||||
}
|
"==" -> {
|
||||||
}
|
elseBranchOpcode = Opcode.BNE
|
||||||
|
elseBranchFirstReg = leftTr.resultReg
|
||||||
|
elseBranchSecondReg = rightTr.resultReg
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
"!=" -> {
|
||||||
|
elseBranchOpcode = Opcode.BEQ
|
||||||
|
elseBranchFirstReg = leftTr.resultReg
|
||||||
|
elseBranchSecondReg = rightTr.resultReg
|
||||||
|
}
|
||||||
|
|
||||||
|
"<" -> {
|
||||||
|
// else part when left >= right
|
||||||
|
elseBranchOpcode = if (signed) Opcode.BGES else Opcode.BGE
|
||||||
|
elseBranchFirstReg = leftTr.resultReg
|
||||||
|
elseBranchSecondReg = rightTr.resultReg
|
||||||
|
}
|
||||||
|
|
||||||
|
">" -> {
|
||||||
|
// else part when left <= right --> right >= left
|
||||||
|
elseBranchOpcode = if (signed) Opcode.BGES else Opcode.BGE
|
||||||
|
elseBranchFirstReg = rightTr.resultReg
|
||||||
|
elseBranchSecondReg = leftTr.resultReg
|
||||||
|
}
|
||||||
|
|
||||||
|
"<=" -> {
|
||||||
|
// else part when left > right
|
||||||
|
elseBranchOpcode = if (signed) Opcode.BGTS else Opcode.BGT
|
||||||
|
elseBranchFirstReg = leftTr.resultReg
|
||||||
|
elseBranchSecondReg = rightTr.resultReg
|
||||||
|
}
|
||||||
|
|
||||||
|
">=" -> {
|
||||||
|
// else part when left < right --> right > left
|
||||||
|
elseBranchOpcode = if (signed) Opcode.BGTS else Opcode.BGT
|
||||||
|
elseBranchFirstReg = rightTr.resultReg
|
||||||
|
elseBranchSecondReg = leftTr.resultReg
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> throw AssemblyError("invalid comparison operator")
|
||||||
|
}
|
||||||
|
if (ifElse.elseScope.children.isNotEmpty()) {
|
||||||
|
// if and else parts
|
||||||
|
val elseLabel = createLabelName()
|
||||||
|
val afterIfLabel = createLabelName()
|
||||||
|
addInstr(
|
||||||
|
result, IRInstruction(
|
||||||
|
elseBranchOpcode, branchDt,
|
||||||
|
reg1 = elseBranchFirstReg, reg2 = elseBranchSecondReg,
|
||||||
|
labelSymbol = elseLabel
|
||||||
|
), null
|
||||||
|
)
|
||||||
|
result += translateNode(ifElse.ifScope)
|
||||||
|
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null)
|
||||||
|
result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel)
|
||||||
|
result += IRCodeChunk(afterIfLabel, null)
|
||||||
|
} else {
|
||||||
|
// only if part
|
||||||
|
val afterIfLabel = createLabelName()
|
||||||
|
addInstr(
|
||||||
|
result, IRInstruction(
|
||||||
|
elseBranchOpcode, branchDt,
|
||||||
|
reg1 = elseBranchFirstReg, reg2 = elseBranchSecondReg,
|
||||||
|
labelSymbol = afterIfLabel
|
||||||
|
), null
|
||||||
|
)
|
||||||
|
result += translateNode(ifElse.ifScope)
|
||||||
|
result += IRCodeChunk(afterIfLabel, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(postIncrDecr: PtPostIncrDecr): IRCodeChunks {
|
private fun translate(postIncrDecr: PtPostIncrDecr): IRCodeChunks {
|
||||||
|
@@ -4,6 +4,9 @@ TODO
|
|||||||
|
|
||||||
For next minor release
|
For next minor release
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
newexpr: fix fallbackAssign() and loadIndexReg()
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,9 +1,16 @@
|
|||||||
%import textio
|
%import textio
|
||||||
|
%import floats
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
|
ubyte xx=100
|
||||||
|
ubyte yy=21
|
||||||
|
|
||||||
|
xx %= yy
|
||||||
|
txt.print_ub(xx)
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
ubyte ub1 = 100
|
ubyte ub1 = 100
|
||||||
ubyte ub2 = 13
|
ubyte ub2 = 13
|
||||||
|
Reference in New Issue
Block a user