From 37c3dff0c56a1c6ee111c4e3a2790afc79b0dd59 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Tue, 14 Mar 2023 19:48:05 +0100 Subject: [PATCH] [K2] Add new class to keep track of evaluated const by IrInterpreter --- .../kotlin/config/CommonConfigurationKeys.kt | 5 ++++ .../kotlin/fir/backend/Fir2IrConfiguration.kt | 4 ++- .../kotlin/fir/backend/Fir2IrConverter.kt | 5 +++- .../common/lower/ConstEvaluationLowering.kt | 8 ++++-- .../kotlin/ir/interpreter/IrTreeBuildUtils.kt | 25 ++++++++++++++++++ .../interpreter/checker/IrConstTransformer.kt | 17 +++++++----- .../kotlin/constant/EvaluatedConstTracker.kt | 26 +++++++++++++++++++ 7 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 core/compiler.common/src/org/jetbrains/kotlin/constant/EvaluatedConstTracker.kt diff --git a/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt b/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt index 894433fa172..afd8e3225a2 100644 --- a/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt +++ b/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.config +import org.jetbrains.kotlin.constant.EvaluatedConstTracker import org.jetbrains.kotlin.incremental.components.EnumWhenTracker import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.InlineConstTracker @@ -91,6 +92,10 @@ object CommonConfigurationKeys { @JvmField val IGNORE_CONST_OPTIMIZATION_ERRORS = CompilerConfigurationKey.create("Ignore errors from IrConstTransformer") + + @JvmField + val EVALUATED_CONST_TRACKER = + CompilerConfigurationKey.create("Keeps track of all evaluated by IrInterpreter constants") } var CompilerConfiguration.languageVersionSettings: LanguageVersionSettings diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConfiguration.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConfiguration.kt index 7b17576cf8c..7b4bac4c0c2 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConfiguration.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConfiguration.kt @@ -17,8 +17,10 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.constant.EvaluatedConstTracker data class Fir2IrConfiguration( val languageVersionSettings: LanguageVersionSettings, - val linkViaSignatures: Boolean + val linkViaSignatures: Boolean, + val evaluatedConstTracker: EvaluatedConstTracker? = null, ) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index b5704cbdfe6..2da0f6b2a1e 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -432,7 +432,10 @@ class Fir2IrConverter( val interpreter = IrInterpreter(IrInterpreterEnvironment(irModuleFragment.irBuiltins, configuration)) val mode = if (intrinsicConstEvaluation) EvaluationMode.ONLY_INTRINSIC_CONST else EvaluationMode.ONLY_BUILTINS irModuleFragment.files.forEach { - it.transformChildren(IrConstTransformer(interpreter, it, mode = mode), null) + val transformer = IrConstTransformer( + interpreter, it, mode = mode + ) + it.transformChildren(transformer, null) } } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/ConstEvaluationLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/ConstEvaluationLowering.kt index cd52e62d575..584e197c252 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/ConstEvaluationLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/ConstEvaluationLowering.kt @@ -24,11 +24,15 @@ class ConstEvaluationLowering( private val onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> }, private val onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> }, ) : FileLoweringPass { - val interpreter = IrInterpreter(IrInterpreterEnvironment(context.irBuiltIns, configuration), emptyMap()) + private val interpreter = IrInterpreter(IrInterpreterEnvironment(context.irBuiltIns, configuration), emptyMap()) + private val evaluatedConstTracker = context.configuration[CommonConfigurationKeys.EVALUATED_CONST_TRACKER] override fun lower(irFile: IrFile) { val transformer = IrConstTransformer( - interpreter, irFile, mode = EvaluationMode.ONLY_INTRINSIC_CONST, onWarning, onError, suppressErrors + interpreter, irFile, + mode = EvaluationMode.ONLY_INTRINSIC_CONST, + evaluatedConstTracker, + onWarning, onError, suppressErrors ) irFile.transformChildren(transformer, null) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrTreeBuildUtils.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrTreeBuildUtils.kt index f000ce3e6ad..77c81a10658 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrTreeBuildUtils.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrTreeBuildUtils.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.interpreter import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.UnsignedType +import org.jetbrains.kotlin.constant.* import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibility @@ -178,3 +179,27 @@ internal fun IrBuiltIns.emptyArrayConstructor(arrayType: IrType): IrConstructorC } return constructorCall } + +internal fun IrConst<*>.toConstantValue(): ConstantValue<*> { + val constType = this.type.makeNotNull().removeAnnotations() + return when (this.type.getPrimitiveType()) { + PrimitiveType.BOOLEAN -> BooleanValue(this.value as Boolean) + PrimitiveType.CHAR -> CharValue(this.value as Char) + PrimitiveType.BYTE -> ByteValue((this.value as Number).toByte()) + PrimitiveType.SHORT -> ShortValue((this.value as Number).toShort()) + PrimitiveType.INT -> IntValue((this.value as Number).toInt()) + PrimitiveType.FLOAT -> FloatValue((this.value as Number).toFloat()) + PrimitiveType.LONG -> LongValue((this.value as Number).toLong()) + PrimitiveType.DOUBLE -> DoubleValue((this.value as Number).toDouble()) + null -> when (constType.getUnsignedType()) { + UnsignedType.UBYTE -> UByteValue((this.value as Number).toByte()) + UnsignedType.USHORT -> UShortValue((this.value as Number).toShort()) + UnsignedType.UINT -> UIntValue((this.value as Number).toInt()) + UnsignedType.ULONG -> ULongValue((this.value as Number).toLong()) + null -> when { + constType.isString() -> StringValue(this.value as String) + else -> error("Cannot convert IrConst ${this.render()} to ConstantValue") + } + } + } +} diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrConstTransformer.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrConstTransformer.kt index 9e6eec72346..9fcf929dfc7 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrConstTransformer.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrConstTransformer.kt @@ -5,20 +5,17 @@ package org.jetbrains.kotlin.ir.interpreter.checker +import org.jetbrains.kotlin.constant.ErrorValue +import org.jetbrains.kotlin.constant.EvaluatedConstTracker import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer -import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase -import org.jetbrains.kotlin.ir.declarations.IrField -import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrStringConcatenationImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl -import org.jetbrains.kotlin.ir.interpreter.IrInterpreter -import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration +import org.jetbrains.kotlin.ir.interpreter.* import org.jetbrains.kotlin.ir.interpreter.isPrimitiveArray -import org.jetbrains.kotlin.ir.interpreter.toIrConst import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -29,6 +26,7 @@ class IrConstTransformer( private val interpreter: IrInterpreter, private val irFile: IrFile, private val mode: EvaluationMode, + private val evaluatedConstTracker: EvaluatedConstTracker? = null, private val onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> }, private val onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> }, private val suppressExceptions: Boolean = false, @@ -77,6 +75,11 @@ class IrConstTransformer( throw AssertionError("Error occurred while optimizing an expression:\n${this.dump()}", e) } + evaluatedConstTracker?.save( + this.startOffset, this.endOffset, + constant = if (result is IrErrorExpression) ErrorValue.create(result.description) + else (result as IrConst<*>).toConstantValue() + ) return if (failAsError) result.reportIfError(this) else result.warningIfError(this) } diff --git a/core/compiler.common/src/org/jetbrains/kotlin/constant/EvaluatedConstTracker.kt b/core/compiler.common/src/org/jetbrains/kotlin/constant/EvaluatedConstTracker.kt new file mode 100644 index 00000000000..eef2589d339 --- /dev/null +++ b/core/compiler.common/src/org/jetbrains/kotlin/constant/EvaluatedConstTracker.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.constant + +import java.util.concurrent.ConcurrentHashMap + +abstract class EvaluatedConstTracker { + abstract fun save(start: Int, end: Int, constant: ConstantValue<*>) + abstract fun load(start: Int, end: Int): ConstantValue<*>? +} + +class DefaultEvaluatedConstTracker : EvaluatedConstTracker() { + private val storage = ConcurrentHashMap, ConstantValue<*>>() + + override fun save(start: Int, end: Int, constant: ConstantValue<*>) { + storage[start to end] = constant + } + + override fun load(start: Int, end: Int): ConstantValue<*>? { + return storage[start to end] + } +} +