Native: Handle integer overflow on div/rem of Int.MIN_VALUE by -1
^KT-45136
This commit is contained in:
+37
-17
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.ir.expressions.*
|
|||||||
import org.jetbrains.kotlin.ir.types.getClass
|
import org.jetbrains.kotlin.ir.types.getClass
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
import org.jetbrains.kotlin.ir.util.findAnnotation
|
import org.jetbrains.kotlin.ir.util.findAnnotation
|
||||||
import org.jetbrains.kotlin.ir.util.isSuspend
|
|
||||||
|
|
||||||
internal enum class IntrinsicType {
|
internal enum class IntrinsicType {
|
||||||
PLUS,
|
PLUS,
|
||||||
@@ -630,27 +629,48 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FunctionGenerationContext.emitSignedDiv(args: List<LLVMValueRef>): LLVMValueRef {
|
private fun FunctionGenerationContext.emitSignedDiv(args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
val (first, second) = args
|
val (dividend, divisor) = args
|
||||||
if (!second.type.isFloatingPoint()) {
|
val divisorType = divisor.type
|
||||||
emitThrowIfZero(second)
|
return if (!divisorType.isFloatingPoint()) {
|
||||||
}
|
emitThrowIfZero(divisor)
|
||||||
return if (first.type.isFloatingPoint()) {
|
emitSignedDivisionWithOverflow(dividend, divisor, divisorType, retZeroOnOverflow = false) {
|
||||||
LLVMBuildFDiv(builder, first, second, "")
|
LLVMBuildSDiv(builder, dividend, divisor, "")!!
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LLVMBuildSDiv(builder, first, second, "")
|
LLVMBuildFDiv(builder, dividend, divisor, "")!!
|
||||||
}!!
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FunctionGenerationContext.emitSignedRem(args: List<LLVMValueRef>): LLVMValueRef {
|
private fun FunctionGenerationContext.emitSignedRem(args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
val (first, second) = args
|
val (dividend, divisor) = args
|
||||||
if (!second.type.isFloatingPoint()) {
|
val divisorType = divisor.type
|
||||||
emitThrowIfZero(second)
|
return if (!divisorType.isFloatingPoint()) {
|
||||||
}
|
emitThrowIfZero(divisor)
|
||||||
return if (first.type.isFloatingPoint()) {
|
emitSignedDivisionWithOverflow(dividend, divisor, divisorType, retZeroOnOverflow = true) {
|
||||||
LLVMBuildFRem(builder, first, second, "")
|
LLVMBuildSRem(builder, dividend, divisor, "")!!
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LLVMBuildSRem(builder, first, second, "")
|
LLVMBuildFRem(builder, dividend, divisor, "")!!
|
||||||
}!!
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun FunctionGenerationContext.emitSignedDivisionWithOverflow(
|
||||||
|
dividend: LLVMValueRef,
|
||||||
|
divisor: LLVMValueRef,
|
||||||
|
type: LLVMTypeRef,
|
||||||
|
retZeroOnOverflow: Boolean,
|
||||||
|
nonOverflowValue: () -> LLVMValueRef
|
||||||
|
): LLVMValueRef {
|
||||||
|
val minValue = when (val sizeInBits = type.sizeInBits()) {
|
||||||
|
32 -> LLVMConstInt(type, Int.MIN_VALUE.toLong(), 1)!!
|
||||||
|
64 -> LLVMConstInt(type, Long.MIN_VALUE, 1)!!
|
||||||
|
else -> error("Unsupported signed integer division argument width: $sizeInBits")
|
||||||
|
}
|
||||||
|
|
||||||
|
val minusOne = LLVMConstInt(type, -1, 1)!!
|
||||||
|
val overflowValue = if (retZeroOnOverflow) Zero(type).llvm else minValue
|
||||||
|
|
||||||
|
return ifThenElse(and(icmpEq(dividend, minValue), icmpEq(divisor, minusOne)), overflowValue, nonOverflowValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FunctionGenerationContext.emitUnsignedDiv(args: List<LLVMValueRef>): LLVMValueRef {
|
private fun FunctionGenerationContext.emitUnsignedDiv(args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
|
|||||||
Reference in New Issue
Block a user