diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterConfiguration.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterConfiguration.kt index 0a181e07777..187aef56f51 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterConfiguration.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterConfiguration.kt @@ -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, ) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrInterpreterCommonChecker.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrInterpreterCommonChecker.kt index 2280ef99422..27c7e0be10a 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrInterpreterCommonChecker.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrInterpreterCommonChecker.kt @@ -122,9 +122,6 @@ class IrInterpreterCommonChecker : IrInterpreterChecker { } override fun visitConst(expression: IrConst<*>, data: IrInterpreterCheckerData): Boolean { - if (!data.interpreterConfiguration.inlineNanVal) { - return !expression.isNaN() - } return true } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Lowerings.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Lowerings.kt index 92f1f881128..ee79017e175 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Lowerings.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Lowerings.kt @@ -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", diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index e17a0972c4c..2b76888fe7e 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -1843,6 +1843,22 @@ internal class CodeGeneratorVisitor( private fun evaluateStringConst(value: IrConst) = 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 */ @@ -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) - 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()) } } diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 86237e7d2dc..3d28701a3c5 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -4298,7 +4298,6 @@ interopTest("interop_globals") { } interopTest("interop_macros") { - disabled = isK2(project) // KT-56041 source = "interop/basics/macros.kt" interop = 'cmacros' } diff --git a/kotlin-native/backend.native/tests/interop/basics/macros.kt b/kotlin-native/backend.native/tests/interop/basics/macros.kt index 6a15b8598d5..b7947131531 100644 --- a/kotlin-native/backend.native/tests/interop/basics/macros.kt +++ b/kotlin-native/backend.native/tests/interop/basics/macros.kt @@ -60,7 +60,7 @@ fun main(args: Array) { 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()) } }