[K2] Add new class to keep track of evaluated const by IrInterpreter

This commit is contained in:
Ivan Kylchik
2023-03-14 19:48:05 +01:00
committed by Space Team
parent 297b6ae64b
commit 37c3dff0c5
7 changed files with 79 additions and 11 deletions
@@ -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<Boolean>("Ignore errors from IrConstTransformer")
@JvmField
val EVALUATED_CONST_TRACKER =
CompilerConfigurationKey.create<EvaluatedConstTracker>("Keeps track of all evaluated by IrInterpreter constants")
}
var CompilerConfiguration.languageVersionSettings: LanguageVersionSettings
@@ -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,
)
@@ -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)
}
}
@@ -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)
}
@@ -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")
}
}
}
}
@@ -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)
}
@@ -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<Pair<Int, Int>, 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]
}
}