mirror of
https://github.com/irmen/prog8.git
synced 2026-04-19 20:16:51 +00:00
new IR call and return instructions to deal with returnregisters
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user