new IR call and return instructions to deal with returnregisters

This commit is contained in:
Irmen de Jong
2023-03-12 21:54:59 +01:00
parent 39132327cc
commit 78a097585d
15 changed files with 115 additions and 58 deletions
@@ -954,17 +954,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
}
}
addInstr(result, IRInstruction(Opcode.CALL, labelSymbol=fcall.name), null)
if(fcall.type==DataType.FLOAT) {
if (!fcall.void && resultFpRegister != 0) {
// Call convention: result value is in fr0, so put it in the required register instead.
addInstr(result, IRInstruction(Opcode.LOADR, IRDataType.FLOAT, fpReg1 = resultFpRegister, fpReg2 = 0), null)
}
} else {
if (!fcall.void && resultRegister != 0) {
// Call convention: result value is in r0, so put it in the required register instead.
addInstr(result, IRInstruction(Opcode.LOADR, codeGen.irType(fcall.type), reg1 = resultRegister, reg2 = 0), null)
}
if(fcall.void)
addInstr(result, IRInstruction(Opcode.CALL, labelSymbol=fcall.name), null)
else {
if(fcall.type==DataType.FLOAT)
addInstr(result, IRInstruction(Opcode.CALLRVAL, IRDataType.FLOAT, fpReg1=resultFpRegister, labelSymbol=fcall.name), null)
else
addInstr(result, IRInstruction(Opcode.CALLRVAL, codeGen.irType(fcall.type), reg1=resultRegister, labelSymbol=fcall.name), null)
}
return result
}
@@ -983,6 +979,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
addInstr(result, IRInstruction(Opcode.STORECPU, paramDt, reg1 = argReg, labelSymbol = paramRegStr), null)
}
}
// just a regular call without using Vm register call convention: the value is returned in CPU registers!
addInstr(result, IRInstruction(Opcode.CALL, value=callTarget.address.toInt()), null)
if(!fcall.void) {
when(callTarget.returns.size) {
@@ -68,6 +68,7 @@ class IRCodeGen(
}
if(options.optimize) {
// TODO integrate into peephole optimizer above
val opt = IROptimizer(irProg)
opt.optimize()
}
@@ -1265,14 +1266,20 @@ class IRCodeGen(
private fun translate(ret: PtReturn): IRCodeChunks {
val result = mutableListOf<IRCodeChunkBase>()
val value = ret.value
if(value!=null) {
// Call Convention: return value is always returned in r0 (or fr0 if float)
result += if(value.type==DataType.FLOAT)
expressionEval.translateExpression(value, -1, 0)
else
expressionEval.translateExpression(value, 0, -1)
if(value==null) {
addInstr(result, IRInstruction(Opcode.RETURN), null)
} else {
if(value.type==DataType.FLOAT) {
val reg = registers.nextFreeFloat()
result += expressionEval.translateExpression(value, -1, reg)
addInstr(result, IRInstruction(Opcode.RETURNREG, IRDataType.FLOAT, fpReg1 = reg), null)
}
else {
val reg = registers.nextFree()
result += expressionEval.translateExpression(value, reg, -1)
addInstr(result, IRInstruction(Opcode.RETURNREG, irType(value.type) , reg1=reg), null)
}
}
addInstr(result, IRInstruction(Opcode.RETURN), null)
return result
}
@@ -175,7 +175,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
}
}
// remove useless RETURN
if(ins.opcode == Opcode.RETURN && idx>0) {
if(idx>0 && (ins.opcode == Opcode.RETURN || ins.opcode==Opcode.RETURNREG)) {
val previous = chunk.instructions[idx-1] as? IRInstruction
if(previous?.opcode in OpcodesThatJump) {
chunk.instructions.removeAt(idx)
@@ -5,6 +5,7 @@ import prog8.intermediate.SyscallRegisterBase
internal class RegisterPool {
// reserve 0,1,2 for return values of subroutine calls and syscalls
// TODO set this back to 0 once 'resultRegister' has been removed everywhere?
private var firstFree: Int=3
private var firstFreeFloat: Int=3
@@ -2,6 +2,8 @@ package prog8.iroptimizer
import prog8.intermediate.*
// TODO integrate into peephole optimizer
internal class IROptimizer(val program: IRProgram) {
fun optimize() {
program.blocks.forEach { block ->
@@ -36,7 +38,7 @@ internal class IROptimizer(val program: IRProgram) {
val i1 = first.value
val i2 = second.value
// replace call + return --> jump
if(i1.opcode==Opcode.CALL && i2.opcode==Opcode.RETURN) {
if((i1.opcode==Opcode.CALL || i1.opcode==Opcode.CALLRVAL) && i2.opcode==Opcode.RETURN) {
elt.instructions[first.index] = IRInstruction(Opcode.JUMP, value=i1.value, labelSymbol = i1.labelSymbol, branchTarget = i1.branchTarget)
elt.instructions[second.index] = IRInstruction(Opcode.NOP)
if(second.index==elt.instructions.size-1) {