mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
IR: more optimal branch instructions for comparisons against zero
This commit is contained in:
parent
025183602f
commit
dc316fd7b4
@ -16,32 +16,28 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
return translateRegularAssign(assignment)
|
return translateRegularAssign(assignment)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun translate(augmentedAssign: PtAugmentedAssign): IRCodeChunks {
|
internal fun translate(augAssign: PtAugmentedAssign): IRCodeChunks {
|
||||||
if(augmentedAssign.target.children.single() is PtMachineRegister)
|
if(augAssign.target.children.single() is PtMachineRegister)
|
||||||
throw AssemblyError("assigning to a register should be done by just evaluating the expression into resultregister")
|
throw AssemblyError("assigning to a register should be done by just evaluating the expression into resultregister")
|
||||||
|
|
||||||
return translateInplaceAssign(augmentedAssign)
|
val ident = augAssign.target.identifier
|
||||||
}
|
val memory = augAssign.target.memory
|
||||||
|
val array = augAssign.target.array
|
||||||
private fun translateInplaceAssign(assignment: PtAugmentedAssign): IRCodeChunks {
|
|
||||||
val ident = assignment.target.identifier
|
|
||||||
val memory = assignment.target.memory
|
|
||||||
val array = assignment.target.array
|
|
||||||
|
|
||||||
return if(ident!=null) {
|
return if(ident!=null) {
|
||||||
assignVarAugmented(ident.name, assignment)
|
assignVarAugmented(ident.name, augAssign)
|
||||||
} else if(memory != null) {
|
} else if(memory != null) {
|
||||||
if(memory.address is PtNumber)
|
if(memory.address is PtNumber)
|
||||||
assignMemoryAugmented((memory.address as PtNumber).number.toInt(), assignment)
|
assignMemoryAugmented((memory.address as PtNumber).number.toInt(), augAssign)
|
||||||
else
|
else
|
||||||
fallbackAssign(assignment)
|
fallbackAssign(augAssign)
|
||||||
} else if(array!=null) {
|
} else if(array!=null) {
|
||||||
// NOTE: naive fallback assignment here will sometimes generate code that loads the index value multiple times
|
// NOTE: naive fallback assignment here will sometimes generate code that loads the index value multiple times
|
||||||
// in a register. It's way too much work to optimize that here - instead, we trust that the generated IL assembly
|
// in a register. It's way too much work to optimize that here - instead, we trust that the generated IL assembly
|
||||||
// will be optimized later and have the double assignments removed.
|
// will be optimized later and have the double assignments removed.
|
||||||
fallbackAssign(assignment)
|
fallbackAssign(augAssign)
|
||||||
} else {
|
} else {
|
||||||
fallbackAssign(assignment)
|
fallbackAssign(augAssign)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,66 +127,70 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
|
|
||||||
private fun translateRegularAssign(assignment: PtAssignment): IRCodeChunks {
|
private fun translateRegularAssign(assignment: PtAssignment): IRCodeChunks {
|
||||||
// note: assigning array and string values is done via an explicit memcopy/stringcopy function call.
|
// note: assigning array and string values is done via an explicit memcopy/stringcopy function call.
|
||||||
val ident = assignment.target.identifier
|
val targetIdent = assignment.target.identifier
|
||||||
val memory = assignment.target.memory
|
val targetMemory = assignment.target.memory
|
||||||
val array = assignment.target.array
|
val targetArray = assignment.target.array
|
||||||
val vmDt = codeGen.irType(assignment.value.type)
|
val vmDt = codeGen.irType(assignment.value.type)
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
var resultRegister = -1
|
|
||||||
var resultFpRegister = -1
|
var valueRegister = -1
|
||||||
|
var valueFpRegister = -1
|
||||||
val zero = codeGen.isZero(assignment.value)
|
val zero = codeGen.isZero(assignment.value)
|
||||||
if(!zero) {
|
if(!zero) {
|
||||||
// calculate the assignment value
|
// calculate the assignment value
|
||||||
if (vmDt == IRDataType.FLOAT) {
|
if (vmDt == IRDataType.FLOAT) {
|
||||||
val tr = expressionEval.translateExpression(assignment.value)
|
val tr = expressionEval.translateExpression(assignment.value)
|
||||||
resultFpRegister = tr.resultFpReg
|
valueFpRegister = tr.resultFpReg
|
||||||
addToResult(result, tr, -1, tr.resultFpReg)
|
addToResult(result, tr, -1, valueFpRegister)
|
||||||
} else {
|
} else {
|
||||||
resultRegister = if (assignment.value is PtMachineRegister) {
|
if (assignment.value is PtMachineRegister) {
|
||||||
(assignment.value as PtMachineRegister).register
|
valueRegister = (assignment.value as PtMachineRegister).register
|
||||||
} else {
|
} else {
|
||||||
val tr = expressionEval.translateExpression(assignment.value)
|
val tr = expressionEval.translateExpression(assignment.value)
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
valueRegister = tr.resultReg
|
||||||
tr.resultReg
|
addToResult(result, tr, valueRegister, -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(ident!=null) {
|
|
||||||
|
if(targetIdent!=null) {
|
||||||
val instruction = if(zero) {
|
val instruction = if(zero) {
|
||||||
IRInstruction(Opcode.STOREZM, vmDt, labelSymbol = ident.name)
|
IRInstruction(Opcode.STOREZM, vmDt, labelSymbol = targetIdent.name)
|
||||||
} else {
|
} else {
|
||||||
if (vmDt == IRDataType.FLOAT)
|
if (vmDt == IRDataType.FLOAT) {
|
||||||
IRInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = ident.name)
|
IRInstruction(Opcode.STOREM, vmDt, fpReg1 = valueFpRegister, labelSymbol = targetIdent.name)
|
||||||
|
}
|
||||||
else
|
else
|
||||||
IRInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = ident.name)
|
IRInstruction(Opcode.STOREM, vmDt, reg1 = valueRegister, labelSymbol = targetIdent.name)
|
||||||
}
|
}
|
||||||
result += IRCodeChunk(null, null).also { it += instruction }
|
result += IRCodeChunk(null, null).also { it += instruction }
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
else if(array!=null) {
|
else if(targetArray!=null) {
|
||||||
val variable = array.variable.name
|
val variable = targetArray.variable.name
|
||||||
val itemsize = codeGen.program.memsizer.memorySize(array.type)
|
val itemsize = codeGen.program.memsizer.memorySize(targetArray.type)
|
||||||
|
|
||||||
if(array.variable.type==DataType.UWORD) {
|
if(targetArray.variable.type==DataType.UWORD) {
|
||||||
// indexing a pointer var instead of a real array or string
|
// indexing a pointer var instead of a real array or string
|
||||||
if(itemsize!=1)
|
if(itemsize!=1)
|
||||||
throw AssemblyError("non-array var indexing requires bytes dt")
|
throw AssemblyError("non-array var indexing requires bytes dt")
|
||||||
if(array.index.type!=DataType.UBYTE)
|
if(targetArray.index.type!=DataType.UBYTE)
|
||||||
throw AssemblyError("non-array var indexing requires bytes index")
|
throw AssemblyError("non-array var indexing requires bytes index")
|
||||||
val idxTr = expressionEval.translateExpression(array.index)
|
val tr = expressionEval.translateExpression(targetArray.index)
|
||||||
addToResult(result, idxTr, idxTr.resultReg, -1)
|
val idxReg = tr.resultReg
|
||||||
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
val code = IRCodeChunk(null, null)
|
val code = IRCodeChunk(null, null)
|
||||||
if(zero) {
|
if(zero) {
|
||||||
// there's no STOREZIX instruction
|
// there's no STOREZIX instruction
|
||||||
resultRegister = codeGen.registers.nextFree()
|
valueRegister = codeGen.registers.nextFree()
|
||||||
code += IRInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=0)
|
code += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegister, value=0)
|
||||||
}
|
}
|
||||||
code += IRInstruction(Opcode.STOREIX, vmDt, reg1=resultRegister, reg2=idxTr.resultReg, labelSymbol = variable)
|
code += IRInstruction(Opcode.STOREIX, vmDt, reg1=valueRegister, reg2=idxReg, labelSymbol = variable)
|
||||||
result += code
|
result += code
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
val fixedIndex = constIntValue(array.index)
|
val fixedIndex = constIntValue(targetArray.index)
|
||||||
if(zero) {
|
if(zero) {
|
||||||
if(fixedIndex!=null) {
|
if(fixedIndex!=null) {
|
||||||
val offset = fixedIndex*itemsize
|
val offset = fixedIndex*itemsize
|
||||||
@ -198,53 +198,55 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
result += chunk
|
result += chunk
|
||||||
} else {
|
} else {
|
||||||
val indexReg = codeGen.registers.nextFree()
|
val indexReg = codeGen.registers.nextFree()
|
||||||
result += loadIndexReg(array, itemsize, indexReg)
|
result += loadIndexReg(targetArray, itemsize, indexReg)
|
||||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZX, vmDt, reg1=indexReg, labelSymbol = variable) }
|
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZX, vmDt, reg1=indexReg, labelSymbol = variable) }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(vmDt== IRDataType.FLOAT) {
|
if(vmDt== IRDataType.FLOAT) {
|
||||||
if(fixedIndex!=null) {
|
if(fixedIndex!=null) {
|
||||||
val offset = fixedIndex*itemsize
|
val offset = fixedIndex*itemsize
|
||||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = "$variable+$offset") }
|
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, vmDt, fpReg1 = valueFpRegister, labelSymbol = "$variable+$offset") }
|
||||||
result += chunk
|
result += chunk
|
||||||
} else {
|
} else {
|
||||||
val indexReg = codeGen.registers.nextFree()
|
val indexReg = codeGen.registers.nextFree()
|
||||||
result += loadIndexReg(array, itemsize, indexReg)
|
result += loadIndexReg(targetArray, itemsize, indexReg)
|
||||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREX, vmDt, reg1 = indexReg, fpReg1 = resultFpRegister, labelSymbol = variable) }
|
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREX, vmDt, reg1 = indexReg, fpReg1 = valueFpRegister, labelSymbol = variable) }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(fixedIndex!=null) {
|
if(fixedIndex!=null) {
|
||||||
val offset = fixedIndex*itemsize
|
val offset = fixedIndex*itemsize
|
||||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = "$variable+$offset") }
|
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueRegister, labelSymbol = "$variable+$offset") }
|
||||||
result += chunk
|
result += chunk
|
||||||
} else {
|
} else {
|
||||||
val indexReg = codeGen.registers.nextFree()
|
val indexReg = codeGen.registers.nextFree()
|
||||||
result += loadIndexReg(array, itemsize, indexReg)
|
result += loadIndexReg(targetArray, itemsize, indexReg)
|
||||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, labelSymbol = variable) }
|
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREX, vmDt, reg1 = valueRegister, reg2=indexReg, labelSymbol = variable) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
else if(memory!=null) {
|
else if(targetMemory!=null) {
|
||||||
require(vmDt== IRDataType.BYTE) { "must be byte type ${memory.position}"}
|
require(vmDt== IRDataType.BYTE) { "must be byte type ${targetMemory.position}"}
|
||||||
if(zero) {
|
if(zero) {
|
||||||
if(memory.address is PtNumber) {
|
if(targetMemory.address is PtNumber) {
|
||||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZM, vmDt, value=(memory.address as PtNumber).number.toInt()) }
|
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZM, vmDt, value=(targetMemory.address as PtNumber).number.toInt()) }
|
||||||
result += chunk
|
result += chunk
|
||||||
} else {
|
} else {
|
||||||
val tr = expressionEval.translateExpression(memory.address)
|
val tr = expressionEval.translateExpression(targetMemory.address)
|
||||||
|
val addressReg = tr.resultReg
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZI, vmDt, reg1=tr.resultReg) }
|
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZI, vmDt, reg1=addressReg) }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(memory.address is PtNumber) {
|
if(targetMemory.address is PtNumber) {
|
||||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt()) }
|
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueRegister, value=(targetMemory.address as PtNumber).number.toInt()) }
|
||||||
result += chunk
|
result += chunk
|
||||||
} else {
|
} else {
|
||||||
val tr = expressionEval.translateExpression(memory.address)
|
val tr = expressionEval.translateExpression(targetMemory.address)
|
||||||
|
val addressReg = tr.resultReg
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=tr.resultReg) }
|
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREI, vmDt, reg1=valueRegister, reg2=addressReg) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -937,57 +937,100 @@ class IRCodeGen(
|
|||||||
else
|
else
|
||||||
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = goto.identifier!!.name)
|
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = goto.identifier!!.name)
|
||||||
}
|
}
|
||||||
|
return result
|
||||||
} else {
|
} else {
|
||||||
val leftTr = expressionEval.translateExpression(ifElse.condition.left)
|
val rightConst = ifElse.condition.right.asConstInteger()
|
||||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
return if(rightConst==0)
|
||||||
val rightTr = expressionEval.translateExpression(ifElse.condition.right)
|
ifZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
|
||||||
require(rightTr.resultReg!=leftTr.resultReg)
|
else {
|
||||||
addToResult(result, rightTr, rightTr.resultReg, -1)
|
ifNonZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
|
||||||
val opcode: Opcode
|
|
||||||
val firstReg: Int
|
|
||||||
val secondReg: Int
|
|
||||||
when (ifElse.condition.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)
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ifZeroIntThenJump(
|
||||||
|
result: MutableList<IRCodeChunkBase>,
|
||||||
|
ifElse: PtIfElse,
|
||||||
|
signed: Boolean,
|
||||||
|
irDtLeft: IRDataType,
|
||||||
|
goto: PtJump
|
||||||
|
): MutableList<IRCodeChunkBase> {
|
||||||
|
val leftTr = expressionEval.translateExpression(ifElse.condition.left)
|
||||||
|
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||||
|
val opcode = when (ifElse.condition.operator) {
|
||||||
|
"==" -> Opcode.BZ
|
||||||
|
"!=" -> Opcode.BNZ
|
||||||
|
"<" -> if (signed) Opcode.BLZS else throw AssemblyError("unsigned < 0 shouldn't occur in codegen")
|
||||||
|
">" -> if (signed) Opcode.BGZS else throw AssemblyError("unsigned > 0 shouldn't occur in codegen")
|
||||||
|
"<=" -> if (signed) Opcode.BLEZS else throw AssemblyError("unsigned <= 0 shouldn't occur in codegen")
|
||||||
|
">=" -> if (signed) Opcode.BGEZS else throw AssemblyError("unsigned >= 0 shouldn't occur in codegen")
|
||||||
|
else -> throw AssemblyError("invalid comparison operator")
|
||||||
|
}
|
||||||
|
if (goto.address != null)
|
||||||
|
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, value = goto.address?.toInt()), null)
|
||||||
|
else if (goto.generatedLabel != null)
|
||||||
|
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, labelSymbol = goto.generatedLabel), null)
|
||||||
|
else
|
||||||
|
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, labelSymbol = goto.identifier!!.name), null)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ifNonZeroIntThenJump(
|
||||||
|
result: MutableList<IRCodeChunkBase>,
|
||||||
|
ifElse: PtIfElse,
|
||||||
|
signed: Boolean,
|
||||||
|
irDtLeft: IRDataType,
|
||||||
|
goto: PtJump
|
||||||
|
): MutableList<IRCodeChunkBase> {
|
||||||
|
val leftTr = expressionEval.translateExpression(ifElse.condition.left)
|
||||||
|
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||||
|
val rightTr = expressionEval.translateExpression(ifElse.condition.right)
|
||||||
|
require(rightTr.resultReg!=leftTr.resultReg)
|
||||||
|
addToResult(result, rightTr, rightTr.resultReg, -1)
|
||||||
|
val opcode: Opcode
|
||||||
|
val firstReg: Int
|
||||||
|
val secondReg: Int
|
||||||
|
when (ifElse.condition.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)
|
||||||
|
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
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ main {
|
|||||||
val irProgram = IRFileReader().read(virtfile)
|
val irProgram = IRFileReader().read(virtfile)
|
||||||
val start = irProgram.blocks[0].children[0] as IRSubroutine
|
val start = irProgram.blocks[0].children[0] as IRSubroutine
|
||||||
val instructions = start.chunks.flatMap { c->c.instructions }
|
val instructions = start.chunks.flatMap { c->c.instructions }
|
||||||
instructions.size shouldBe 18
|
instructions.size shouldBe 13
|
||||||
instructions.last().opcode shouldBe Opcode.RETURN
|
instructions.last().opcode shouldBe Opcode.RETURN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user