implement missing operators in IR code gen

This commit is contained in:
Irmen de Jong
2023-03-31 23:55:24 +02:00
parent 2d85fd093e
commit 47d0f0ea40
5 changed files with 540 additions and 232 deletions

View File

@@ -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)

View File

@@ -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
}
} }

View File

@@ -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 {

View File

@@ -4,6 +4,9 @@ TODO
For next minor release For next minor release
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
newexpr: fix fallbackAssign() and loadIndexReg()
... ...

View File

@@ -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