IR: small optimization

This commit is contained in:
Irmen de Jong 2023-04-05 20:48:20 +02:00
parent befe0fff2a
commit c4f53fe525
5 changed files with 168 additions and 146 deletions

View File

@ -72,25 +72,25 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
private fun assignVarAugmented(symbol: String, assignment: PtAugmentedAssign): IRCodeChunks { private fun assignVarAugmented(symbol: String, assignment: PtAugmentedAssign): IRCodeChunks {
val value = assignment.value val value = assignment.value
val valueVmDt = codeGen.irType(value.type) val targetDt = codeGen.irType(assignment.target.type)
return when (assignment.operator) { return when (assignment.operator) {
"+=" -> expressionEval.operatorPlusInplace(null, symbol, valueVmDt, value) "+=" -> expressionEval.operatorPlusInplace(null, symbol, targetDt, value)
"-=" -> expressionEval.operatorMinusInplace(null, symbol, valueVmDt, value) "-=" -> expressionEval.operatorMinusInplace(null, symbol, targetDt, value)
"*=" -> expressionEval.operatorMultiplyInplace(null, symbol, valueVmDt, value) "*=" -> expressionEval.operatorMultiplyInplace(null, symbol, targetDt, value)
"/=" -> expressionEval.operatorDivideInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value) "/=" -> expressionEval.operatorDivideInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
"|=" -> expressionEval.operatorOrInplace(null, symbol, valueVmDt, value) "|=" -> expressionEval.operatorOrInplace(null, symbol, targetDt, value)
"&=" -> expressionEval.operatorAndInplace(null, symbol, valueVmDt, value) "&=" -> expressionEval.operatorAndInplace(null, symbol, targetDt, value)
"^=" -> expressionEval.operatorXorInplace(null, symbol, valueVmDt, value) "^=" -> expressionEval.operatorXorInplace(null, symbol, targetDt, value)
"<<=" -> expressionEval.operatorShiftLeftInplace(null, symbol, valueVmDt, value) "<<=" -> expressionEval.operatorShiftLeftInplace(null, symbol, targetDt, value)
">>=" -> expressionEval.operatorShiftRightInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value) ">>=" -> expressionEval.operatorShiftRightInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
"%=" -> expressionEval.operatorModuloInplace(null, symbol, valueVmDt, value) "%=" -> expressionEval.operatorModuloInplace(null, symbol, targetDt, value)
"==" -> expressionEval.operatorEqualsInplace(null, symbol, valueVmDt, value) "==" -> expressionEval.operatorEqualsInplace(null, symbol, targetDt, value)
"!=" -> expressionEval.operatorNotEqualsInplace(null, symbol, valueVmDt, value) "!=" -> expressionEval.operatorNotEqualsInplace(null, symbol, targetDt, value)
"<" -> expressionEval.operatorLessInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value) "<" -> expressionEval.operatorLessInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
">" -> expressionEval.operatorGreaterInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value) ">" -> expressionEval.operatorGreaterInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
"<=" -> expressionEval.operatorLessEqualInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value) "<=" -> expressionEval.operatorLessEqualInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
">=" -> expressionEval.operatorGreaterEqualInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value) ">=" -> expressionEval.operatorGreaterEqualInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
in PrefixOperators -> inplacePrefix(assignment.operator, valueVmDt, null, symbol) in PrefixOperators -> inplacePrefix(assignment.operator, targetDt, null, symbol)
else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}") else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}")
} }
} }

View File

@ -268,7 +268,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
actualResultReg2 = tr.resultReg actualResultReg2 = tr.resultReg
addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.BYTE, reg1 = actualResultReg2), null) addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.BYTE, reg1 = actualResultReg2), null)
} }
DataType.WORD -> { } DataType.WORD -> {
actualResultReg2 = tr.resultReg
}
DataType.FLOAT -> { DataType.FLOAT -> {
actualResultReg2 = codeGen.registers.nextFree() actualResultReg2 = codeGen.registers.nextFree()
addInstr(result, IRInstruction(Opcode.FTOUW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null) addInstr(result, IRInstruction(Opcode.FTOUW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
@ -288,7 +290,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
actualResultReg2 = tr.resultReg actualResultReg2 = tr.resultReg
addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.BYTE, reg1 = actualResultReg2), null) addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.BYTE, reg1 = actualResultReg2), null)
} }
DataType.UWORD -> { } DataType.UWORD -> {
actualResultReg2 = tr.resultReg
}
DataType.FLOAT -> { DataType.FLOAT -> {
actualResultReg2 = codeGen.registers.nextFree() actualResultReg2 = codeGen.registers.nextFree()
addInstr(result, IRInstruction(Opcode.FTOSW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null) addInstr(result, IRInstruction(Opcode.FTOSW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
@ -316,6 +320,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
else -> throw AssemblyError("weird cast type") else -> throw AssemblyError("weird cast type")
} }
return ExpressionCodeResult(result, codeGen.irType(cast.type), actualResultReg2, actualResultFpReg2) return ExpressionCodeResult(result, codeGen.irType(cast.type), actualResultReg2, actualResultFpReg2)
} }
@ -556,17 +561,17 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val rightTr = translateExpression(binExpr.right) val rightTr = translateExpression(binExpr.right)
addToResult(result, rightTr, -1, rightTr.resultFpReg) addToResult(result, rightTr, -1, rightTr.resultFpReg)
val resultRegister = codeGen.registers.nextFree() val resultRegister = codeGen.registers.nextFree()
if (notEquals) {
addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
} else {
val label = codeGen.createLabelName()
val valueReg = codeGen.registers.nextFree() val valueReg = codeGen.registers.nextFree()
val label = codeGen.createLabelName()
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=1), null) addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=1), null)
addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=valueReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null) addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=valueReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
if (notEquals) {
addInstr(result, IRInstruction(Opcode.BNZ, IRDataType.BYTE, reg1=valueReg, labelSymbol = label), null)
} else {
addInstr(result, IRInstruction(Opcode.BZ, IRDataType.BYTE, reg1=valueReg, labelSymbol = label), null) addInstr(result, IRInstruction(Opcode.BZ, IRDataType.BYTE, reg1=valueReg, labelSymbol = label), null)
}
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=0), null) addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=0), null)
result += IRCodeChunk(label, null) result += IRCodeChunk(label, null)
}
return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1)
} else { } else {
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) { if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
@ -1208,152 +1213,171 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
fun operatorEqualsInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { fun operatorEqualsInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
val result = mutableListOf<IRCodeChunkBase>() return if(vmDt==IRDataType.FLOAT) {
val tr = translateExpression(operand) createInplaceFloatComparison(knownAddress, symbol, operand, Opcode.SEQ)
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=valueReg, reg2=tr.resultReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress)
}
} else { } else {
// symbol = symbol == operand createInplaceComparison(knownAddress, symbol, vmDt, operand, Opcode.SEQ)
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=valueReg, reg2=tr.resultReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol)
} }
} }
return result
}
fun operatorNotEqualsInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks { fun operatorNotEqualsInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
val result = mutableListOf<IRCodeChunkBase>() return if(vmDt==IRDataType.FLOAT) {
val tr = translateExpression(operand) createInplaceFloatComparison(knownAddress, symbol, operand, Opcode.SNE)
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=valueReg, reg2=tr.resultReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress)
}
} else { } else {
// symbol = symbol != operand createInplaceComparison(knownAddress, symbol, vmDt, operand, Opcode.SNE)
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=valueReg, reg2=tr.resultReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol)
} }
}
return result
} }
fun operatorGreaterInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks { 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 val opcode = if(signed) Opcode.SGTS else Opcode.SGT
if(knownAddress!=null) { return if(vmDt==IRDataType.FLOAT) {
// @(address) = @(address) > operand createInplaceFloatComparison(knownAddress, symbol, operand, opcode)
val valueReg = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress)
}
} else { } else {
// symbol = symbol > operand createInplaceComparison(knownAddress, symbol, vmDt, operand, opcode)
val valueReg = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol)
} }
} }
return result
}
fun operatorLessInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks { 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 val opcode = if(signed) Opcode.SLTS else Opcode.SLT
if(knownAddress!=null) { return if(vmDt==IRDataType.FLOAT) {
// @(address) = @(address) < operand createInplaceFloatComparison(knownAddress, symbol, operand, opcode)
val valueReg = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress)
}
} else { } else {
// symbol = symbol < operand createInplaceComparison(knownAddress, symbol, vmDt, operand, opcode)
val valueReg = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol)
} }
} }
return result
}
fun operatorGreaterEqualInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks { 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 val opcode = if(signed) Opcode.SGES else Opcode.SGE
if(knownAddress!=null) { return if(vmDt==IRDataType.FLOAT) {
// @(address) = @(address) > operand createInplaceFloatComparison(knownAddress, symbol, operand, opcode)
} else {
createInplaceComparison(knownAddress, symbol, vmDt, operand, opcode)
}
}
fun operatorLessEqualInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
val opcode = if(signed) Opcode.SLES else Opcode.SLE
return if(vmDt==IRDataType.FLOAT) {
createInplaceFloatComparison(knownAddress, symbol, operand, opcode)
} else {
createInplaceComparison(knownAddress, symbol, vmDt, operand, opcode)
}
}
private fun createInplaceComparison(
knownAddress: Int?,
symbol: String?,
vmDt: IRDataType,
operand: PtExpression,
compareAndSetOpcode: Opcode
): MutableList<IRCodeChunkBase> {
val result = mutableListOf<IRCodeChunkBase>()
val valueReg = codeGen.registers.nextFree() val valueReg = codeGen.registers.nextFree()
if(operand is PtNumber) {
val numberReg = codeGen.registers.nextFree()
if (knownAddress != null) {
// in-place modify a memory location
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress) it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, value = knownAddress)
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg) it += IRInstruction(Opcode.LOAD, vmDt, reg1=numberReg, value=operand.number.toInt())
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress) it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = valueReg, reg2 = numberReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueReg, value = knownAddress)
} }
} else { } else {
// symbol = symbol > operand // in-place modify a symbol (variable)
val valueReg = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol) it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, labelSymbol = symbol)
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg) it += IRInstruction(Opcode.LOAD, vmDt, reg1=numberReg, value=operand.number.toInt())
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol) it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = valueReg, reg2 = numberReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueReg, labelSymbol = symbol)
}
}
} else {
val tr = translateExpression(operand)
addToResult(result, tr, tr.resultReg, -1)
if (knownAddress != null) {
// in-place modify a memory location
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, value = knownAddress)
it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = valueReg, reg2 = tr.resultReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueReg, value = knownAddress)
}
} else {
// in-place modify a symbol (variable)
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, labelSymbol = symbol)
it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = valueReg, reg2 = tr.resultReg)
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueReg, labelSymbol = symbol)
}
} }
} }
return result return result
} }
fun operatorLessEqualInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks { private fun createInplaceFloatComparison(
knownAddress: Int?,
symbol: String?,
operand: PtExpression,
compareAndSetOpcode: Opcode
): MutableList<IRCodeChunkBase> {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
val tr = translateExpression(operand) val valueReg = codeGen.registers.nextFreeFloat()
addToResult(result, tr, tr.resultReg, -1) val cmpReg = codeGen.registers.nextFree()
val opcode = if(signed) Opcode.SLES else Opcode.SLE val zeroReg = codeGen.registers.nextFree()
if(knownAddress!=null) { if(operand is PtNumber) {
// @(address) = @(address) > operand val numberReg = codeGen.registers.nextFreeFloat()
val valueReg = codeGen.registers.nextFree() if (knownAddress != null) {
// in-place modify a memory location
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress) it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, value = knownAddress)
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg) it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, fpValue = operand.number.toFloat())
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress) it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg)
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, value=0)
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpReg, reg2=zeroReg)
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, value=knownAddress)
} }
} else { } else {
// symbol = symbol > operand // in-place modify a symbol (variable)
val valueReg = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol) it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg) it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, fpValue = operand.number.toFloat())
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol) it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg)
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, value=0)
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpReg, reg2=zeroReg)
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
}
}
} else {
val tr = translateExpression(operand)
addToResult(result, tr, -1, tr.resultFpReg)
if (knownAddress != null) {
// in-place modify a memory location
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, value = knownAddress)
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = tr.resultFpReg)
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, value=0)
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpReg, reg2=zeroReg)
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, value=knownAddress)
}
} else {
// in-place modify a symbol (variable)
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = tr.resultFpReg)
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, value=0)
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpReg, reg2=zeroReg)
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
}
} }
} }
return result return result
} }
} }

View File

@ -410,8 +410,14 @@ private fun createAssemblyAndAssemble(program: PtProgram,
else else
throw NotImplementedError("no code generator for cpu ${compilerOptions.compTarget.machine.cpu}") throw NotImplementedError("no code generator for cpu ${compilerOptions.compTarget.machine.cpu}")
if(compilerOptions.useNewExprCode) if(compilerOptions.useNewExprCode) {
if(compilerOptions.compTarget.machine.cpu !in arrayOf(CpuType.CPU6502, CpuType.CPU65c02)) {
// the IR code gen backend has its own, better, version of dealing with binary expressions.
throw IllegalArgumentException("'newexpr' expression rewrite should not be used with compilation target ${compilerOptions.compTarget.name}")
}
transformNewExpressions(program) transformNewExpressions(program)
}
// printAst(program, true) { println(it) } // printAst(program, true) { println(it) }

View File

@ -163,6 +163,6 @@ main {
compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null
compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null
compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null
compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null // no newexpr for IR targets: compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null
} }
}) })

View File

@ -1,19 +1,11 @@
TODO TODO
==== ====
For next minor release For next minor release
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
newxpr vm: vm/bsieve.p8 has wrong result
once everything works, disable -newexpr option for IR/virtual target because that already works without eval stack
and creates far superior code without the newexpr flattening.
IR (normal): fix reg1 out of bounds crash in compiler/test/comparisons/test_compares.p8
... ...
For 9.0 major changes For 9.0 major changes
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
- get rid of the disknumber parameter everywhere in diskio, make it a configurable variable that defaults to 8. - get rid of the disknumber parameter everywhere in diskio, make it a configurable variable that defaults to 8.