[Native] Forbid to inline NaN values during const evaluation

This commit is contained in:
Ivan Kylchik
2023-06-23 10:56:15 +02:00
committed by Space Team
parent 8e42ccaccb
commit a4b8ab8199
3 changed files with 17 additions and 1 deletions
@@ -15,6 +15,7 @@ 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(
@@ -25,4 +26,5 @@ data class IrInterpreterConfiguration(
val printOnlyExceptionMessage: Boolean = false,
val collapseStackTraceFromJDK: Boolean = true,
val inlineConstVal: Boolean = true,
val inlineNanVal: Boolean = true,
)
@@ -116,7 +116,15 @@ class IrInterpreterCommonChecker : IrInterpreterChecker {
return body.kind == IrSyntheticBodyKind.ENUM_VALUES || body.kind == IrSyntheticBodyKind.ENUM_VALUEOF
}
private fun IrConst<*>.isNaN(): Boolean {
return this.kind == IrConstKind.Double && IrConstKind.Double.valueOf(this).isNaN() ||
this.kind == IrConstKind.Float && IrConstKind.Float.valueOf(this).isNaN()
}
override fun visitConst(expression: IrConst<*>, data: IrInterpreterCheckerData): Boolean {
if (!data.interpreterConfiguration.inlineNanVal) {
return !expression.isNaN()
}
return true
}
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.backend.konan.lower.UnboxInlineLowering
import org.jetbrains.kotlin.backend.konan.optimizations.KonanBCEForLoopBodyTransformer
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -493,7 +494,12 @@ private val objectClassesPhase = createFileLoweringPhase(
)
private val constEvaluationPhase = createFileLoweringPhase(
lowering = ::ConstEvaluationLowering,
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)
ConstEvaluationLowering(context, configuration = configuration)
},
name = "ConstEvaluationLowering",
description = "Evaluate functions that are marked as `IntrinsicConstEvaluation`",
prerequisite = setOf(inlinePhase)