Add lowering that will evaluate all intrinsic const expressions

This commit is contained in:
Ivan Kylchik
2021-11-15 17:12:56 +03:00
parent 6a0802a1be
commit d0ab01ad24
4 changed files with 54 additions and 19 deletions
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.evaluate.evaluateConstants
import org.jetbrains.kotlin.fir.backend.generators.*
import org.jetbrains.kotlin.fir.backend.generators.DataClassMembersGenerator
import org.jetbrains.kotlin.fir.declarations.*
@@ -38,6 +37,9 @@ import org.jetbrains.kotlin.ir.PsiIrFileEntry
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
import org.jetbrains.kotlin.ir.interpreter.checker.IrConstTransformer
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.*
@@ -424,6 +426,13 @@ class Fir2IrConverter(
}
companion object {
private fun evaluateConstants(irModuleFragment: IrModuleFragment) {
val interpreter = IrInterpreter(irModuleFragment.irBuiltins)
irModuleFragment.files.forEach {
it.transformChildren(IrConstTransformer(interpreter, it, mode = EvaluationMode.ONLY_BUILTINS), null)
}
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun createModuleFragment(
session: FirSession,
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2019 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.backend.common.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
import org.jetbrains.kotlin.ir.interpreter.checker.IrConstTransformer
val constEvaluationPhase = makeIrModulePhase(
::ConstEvaluationLowering,
name = "ConstEvaluationLowering",
description = "Evaluate functions that are marked as `Foldable`"
)
class ConstEvaluationLowering(val context: CommonBackendContext) : FileLoweringPass {
val interpreter = IrInterpreter(context.irBuiltIns)
override fun lower(irFile: IrFile) {
irFile.transformChildren(IrConstTransformer(interpreter, irFile, mode = EvaluationMode.ONLY_INTRINSIC_CONST), null)
}
}
@@ -407,6 +407,7 @@ private fun buildJvmLoweringPhases(
validateIrBeforeLowering then
processOptionalAnnotationsPhase then
expectDeclarationsRemovingPhase then
constEvaluationPhase then
serializeIrPhase then
scriptsToClassesPhase then
fileClassPhase then
@@ -1,36 +1,32 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2021 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.fir.backend.evaluate
package org.jetbrains.kotlin.ir.interpreter.checker
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.*
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.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
import org.jetbrains.kotlin.ir.interpreter.checker.IrCompileTimeChecker
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.isPrimitiveArray
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
fun evaluateConstants(irModuleFragment: IrModuleFragment) {
val interpreter = IrInterpreter(irModuleFragment.irBuiltins)
irModuleFragment.files.forEach { it.transformChildren(IrConstTransformer(interpreter, it), null) }
}
//TODO create abstract class that will be common for this and lowering
class IrConstTransformer(private val interpreter: IrInterpreter, private val irFile: IrFile) : IrElementTransformerVoid() {
class IrConstTransformer(
private val interpreter: IrInterpreter, private val irFile: IrFile, private val mode: EvaluationMode
) : IrElementTransformerVoid() {
private fun IrExpression.replaceIfError(original: IrExpression): IrExpression {
return if (this !is IrErrorExpression) this else original
}
override fun visitCall(expression: IrCall): IrExpression {
if (expression.accept(IrCompileTimeChecker(mode = EvaluationMode.ONLY_BUILTINS), null)) {
if (expression.accept(IrCompileTimeChecker(mode = mode), null)) {
return interpreter.interpret(expression, irFile).replaceIfError(expression)
}
return super.visitCall(expression)
@@ -43,7 +39,7 @@ class IrConstTransformer(private val interpreter: IrInterpreter, private val irF
val expression = initializer?.expression ?: return declaration
if (expression is IrConst<*>) return declaration
val isConst = declaration.correspondingPropertySymbol?.owner?.isConst == true
if (isConst && expression.accept(IrCompileTimeChecker(declaration, mode = EvaluationMode.ONLY_BUILTINS), null)) {
if (isConst && expression.accept(IrCompileTimeChecker(declaration, mode), null)) {
initializer.expression = interpreter.interpret(expression, irFile).replaceIfError(expression)
}
@@ -89,7 +85,7 @@ class IrConstTransformer(private val interpreter: IrInterpreter, private val irF
}
private fun IrExpression.transformSingleArg(expectedType: IrType): IrExpression {
if (this.accept(IrCompileTimeChecker(mode = EvaluationMode.ONLY_BUILTINS), null)) {
if (this.accept(IrCompileTimeChecker(mode = mode), null)) {
val const = interpreter.interpret(this, irFile).replaceIfError(this)
return const.convertToConstIfPossible(expectedType)
} else if (this is IrConstructorCall) {
@@ -106,4 +102,4 @@ class IrConstTransformer(private val interpreter: IrInterpreter, private val irF
else -> this.value.toIrConst(type, this.startOffset, this.endOffset)
}
}
}
}