[K/N] Normalize on nan values in code generator
^KT-56041
This commit is contained in:
committed by
Space Team
parent
6417f6456f
commit
858f432807
-2
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
* 'true' - interpreter will construct object and initialize its properties despite the fact it is not marked as compile time;
|
||||
* 'false' - interpreter will create a representation of empty object, that can be used to get const properties
|
||||
* @param inlineConstVal tell the interpreter that value of const property can be inlined instead of getter call
|
||||
* @param inlineNanVal allows to inline values of `Double.NaN` and `Float.NaN`
|
||||
*/
|
||||
// TODO maybe create some sort of builder
|
||||
data class IrInterpreterConfiguration(
|
||||
@@ -26,5 +25,4 @@ data class IrInterpreterConfiguration(
|
||||
val printOnlyExceptionMessage: Boolean = false,
|
||||
val collapseStackTraceFromJDK: Boolean = true,
|
||||
val inlineConstVal: Boolean = true,
|
||||
val inlineNanVal: Boolean = true,
|
||||
)
|
||||
|
||||
-3
@@ -122,9 +122,6 @@ class IrInterpreterCommonChecker : IrInterpreterChecker {
|
||||
}
|
||||
|
||||
override fun visitConst(expression: IrConst<*>, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!data.interpreterConfiguration.inlineNanVal) {
|
||||
return !expression.isNaN()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -489,9 +489,7 @@ private val objectClassesPhase = createFileLoweringPhase(
|
||||
|
||||
private val constEvaluationPhase = createFileLoweringPhase(
|
||||
lowering = { context: Context ->
|
||||
// NaN constants has inconsistencies between IR and metadata representation,
|
||||
// so inlining them can lead to incorrect behaviour. Check KT-53258 for details.
|
||||
val configuration = IrInterpreterConfiguration(printOnlyExceptionMessage = true, inlineNanVal = false)
|
||||
val configuration = IrInterpreterConfiguration(printOnlyExceptionMessage = true)
|
||||
ConstEvaluationLowering(context, configuration = configuration)
|
||||
},
|
||||
name = "ConstEvaluationLowering",
|
||||
|
||||
+18
-2
@@ -1843,6 +1843,22 @@ internal class CodeGeneratorVisitor(
|
||||
private fun evaluateStringConst(value: IrConst<String>) =
|
||||
codegen.staticData.kotlinStringLiteral(value.value)
|
||||
|
||||
/**
|
||||
* Normalizing nans to single value is useful for build reproducibility.
|
||||
*
|
||||
* It's possible that it can lead to some bad consequences for interop libraries,
|
||||
* for which exact nan value is important. We are not aware of the existence of
|
||||
* any such useful library, at least on priority targets.
|
||||
*
|
||||
* On the other side, the semantics of exact cases, NaN values should be not normalized, is unclear.
|
||||
* E.g., in previous implementation, storing constant to another constant could change the exact bit pattern.
|
||||
*
|
||||
* So for now, we would just normalize all NaN constants. At least this leads to predictable result
|
||||
* useful in almost all cases.
|
||||
*/
|
||||
private fun Float.normalizeNan() = if (isNaN()) Float.NaN else this
|
||||
private fun Double.normalizeNan() = if (isNaN()) Double.NaN else this
|
||||
|
||||
private fun evaluateConst(value: IrConst<*>): ConstValue {
|
||||
context.log{"evaluateConst : ${ir2string(value)}"}
|
||||
/* This suppression against IrConst<String> */
|
||||
@@ -1856,8 +1872,8 @@ internal class CodeGeneratorVisitor(
|
||||
IrConstKind.Int -> llvm.constInt32(value.value as Int)
|
||||
IrConstKind.Long -> llvm.constInt64(value.value as Long)
|
||||
IrConstKind.String -> evaluateStringConst(value as IrConst<String>)
|
||||
IrConstKind.Float -> llvm.constFloat32(value.value as Float)
|
||||
IrConstKind.Double -> llvm.constFloat64(value.value as Double)
|
||||
IrConstKind.Float -> llvm.constFloat32((value.value as Float).normalizeNan())
|
||||
IrConstKind.Double -> llvm.constFloat64((value.value as Double).normalizeNan())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4298,7 +4298,6 @@ interopTest("interop_globals") {
|
||||
}
|
||||
|
||||
interopTest("interop_macros") {
|
||||
disabled = isK2(project) // KT-56041
|
||||
source = "interop/basics/macros.kt"
|
||||
interop = 'cmacros'
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ fun main(args: Array<String>) {
|
||||
assertEquals(doubleNanBase, 0x7ff8000000000000L)
|
||||
assertEquals(floatNanBase, DEFAULT_FLOAT_NAN.toRawBits())
|
||||
assertEquals(doubleNanBase, DEFAULT_DOUBLE_NAN.toRawBits())
|
||||
assertEquals(floatNanBase or 0x12345, OTHER_FLOAT_NAN.toRawBits())
|
||||
assertEquals(doubleNanBase or 0x123456789abL, OTHER_DOUBLE_NAN.toRawBits())
|
||||
assertEquals(floatNanBase, OTHER_FLOAT_NAN.toRawBits())
|
||||
assertEquals(doubleNanBase, OTHER_DOUBLE_NAN.toRawBits())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user