fix wrong result for short-circuit boolean and/or on the virtual target

This commit is contained in:
Irmen de Jong committed 2026-10-17 01:43:08 +02:00
1 parent 99ff5768c5
commit 5e83c44300
4 files changed
+129 -8

No files matched your search

@@ -1561,6 +1561,26 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
}
/**
* Emit the branch that decides if the short-circuit evaluation of a boolean `or`/`and` has to
* skip its right hand side: [branchWhenZeroTrue] selects if the branch is taken when the left
* hand side value in the register is zero (false) instead of when it is non-zero (true).
* The status bits have to be set from that register first, because only CMP/CMPI/SGN/BITTST do
* that on targets that don't honor CpuType.statusBitsOnMultiByteOps, and the value can also come
* straight from a load or a register move.
*/
private fun addShortCircuitBranch(result: MutableList<IRCodeChunkBase>, leftTr: ExpressionCodeResult, shortcutLabel: String, branchWhenZeroTrue: Boolean) {
val lastInstr = leftTr.chunks.lastOrNull()?.instructions?.lastOrNull()
val skipCmpi = codeGen.options.compTarget.cpu.statusBitsOnMultiByteOps
&& lastInstr != null
&& lastInstr.opcode in OpcodesThatSetStatusbits
if (!skipCmpi) {
addInstr(result, IRInstructions.compareImmediate(IRDataType.BYTE, leftTr.resultReg, 0), null)
}
val branchOpcode = if (branchWhenZeroTrue) Opcode.BSTEQ else Opcode.BSTNE
addInstr(result, IRInstructions.branch(branchOpcode, codeLabel(shortcutLabel)), null)
}
private fun operatorAnd(binExpr: PtBinaryExpression, vmDt: IRDataType, bitwise: Boolean): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>()
if(!bitwise && !binExpr.right.isSimple()) {
@@ -1568,7 +1588,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val leftTr = translateExpression(binExpr.left)
addToResult(result, leftTr, leftTr.resultReg, -1)
val shortcutLabel = codeGen.createLabelName()
addInstr(result, IRInstructions.branch(Opcode.BSTEQ, codeLabel(shortcutLabel)), null)
addShortCircuitBranch(result, leftTr, shortcutLabel, branchWhenZeroTrue = true)
val rightTr = translateExpression(binExpr.right)
addToResult(result, rightTr, leftTr.resultReg, -1)
result += IRCodeChunk(shortcutLabel, null)
@@ -1602,7 +1622,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val leftTr = translateExpression(binExpr.left)
addToResult(result, leftTr, leftTr.resultReg, -1)
val shortcutLabel = codeGen.createLabelName()
addInstr(result, IRInstructions.branch(Opcode.BSTNE, codeLabel(shortcutLabel)), null)
addShortCircuitBranch(result, leftTr, shortcutLabel, branchWhenZeroTrue = false)
val rightTr = translateExpression(binExpr.right)
addToResult(result, rightTr, leftTr.resultReg, -1)
result += IRCodeChunk(shortcutLabel, null)