From 70f195598e959622f610ab2fb3cc3211a7e76abc Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Thu, 12 Oct 2023 18:32:08 +0200 Subject: [PATCH] [FIR2IR] Don't run interpreter's preprocessors on fir2ir stage In IR interpreter we have "preprocessors". Preprocessor is a transformer that changes IR expressions in a way that we can interpret them at least partially. We have two places where interpretation is happening: 1. Right after fir2ir where we evaluate only strictly necessary expression for `const val` and annotations. 2. In lowering for every backend where we are doing some constant folding. Earlier, to avoid double work, we didn't launch preprocessors in backend if we were using K2. But this approach breaks compilation for MPP projects where one module is compiled with K1 into klib and the overall project is compiled with K2. On the backend side, we are mistakenly assuming that preprocessors were launched, but they were not. The solution is to run preprocessors only on the backend side. If we think about it, interpretation on fir2ir doesn't require any preprocessing because we are working only with expressions that are correct and must be fully evaluated. #KT-62126 Fixed --- .../common/lower/ConstEvaluationLowering.kt | 7 +----- .../transformer/IrConstTransformer.kt | 24 ++++++++++--------- .../library/a.kt | 10 ++++++++ .../constEvaluationWithDifferentLV/output.txt | 4 ++++ .../src/empty.txt | 0 ...tCompileKotlinAgainstCustomBinariesTest.kt | 8 +++++++ 6 files changed, 36 insertions(+), 17 deletions(-) create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/constEvaluationWithDifferentLV/library/a.kt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/constEvaluationWithDifferentLV/output.txt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/constEvaluationWithDifferentLV/src/empty.txt 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 e6d320db6a3..ef8ba2be431 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 @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode -import org.jetbrains.kotlin.ir.interpreter.transformer.preprocessForConstTransformer import org.jetbrains.kotlin.ir.interpreter.transformer.runConstOptimizations class ConstEvaluationLowering( @@ -27,11 +26,7 @@ class ConstEvaluationLowering( private val mode = EvaluationMode.ONLY_INTRINSIC_CONST override fun lower(irFile: IrFile) { - val useFir = context.configuration[CommonConfigurationKeys.USE_FIR] == true - val preprocessedFile = if (useFir) irFile else irFile.preprocessForConstTransformer(interpreter, mode) - preprocessedFile.runConstOptimizations( - interpreter, mode, evaluatedConstTracker, inlineConstTracker, suppressErrors - ) + irFile.runConstOptimizations(interpreter, mode, evaluatedConstTracker, inlineConstTracker, suppressErrors) } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstTransformer.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstTransformer.kt index 76def66f26f..113e978f097 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstTransformer.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstTransformer.kt @@ -40,23 +40,21 @@ fun IrFile.transformConst( onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> }, suppressExceptions: Boolean = false, ) { - val preprocessedFile = this.preprocessForConstTransformer(interpreter, mode) - val checker = IrInterpreterCommonChecker() val irConstExpressionTransformer = IrConstOnlyNecessaryTransformer( - interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions + interpreter, this, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions ) - preprocessedFile.transform(irConstExpressionTransformer, IrConstTransformer.Data()) + this.transform(irConstExpressionTransformer, IrConstTransformer.Data()) val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer( - interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions + interpreter, this, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions ) - preprocessedFile.transform(irConstDeclarationAnnotationTransformer, IrConstTransformer.Data()) + this.transform(irConstDeclarationAnnotationTransformer, IrConstTransformer.Data()) val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer( - interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions + interpreter, this, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions ) - preprocessedFile.transform(irConstTypeAnnotationTransformer, IrConstTransformer.Data()) + this.transform(irConstTypeAnnotationTransformer, IrConstTransformer.Data()) } fun IrFile.runConstOptimizations( @@ -66,14 +64,18 @@ fun IrFile.runConstOptimizations( inlineConstTracker: InlineConstTracker? = null, suppressExceptions: Boolean = false, ) { + val preprocessedFile = this.preprocessForConstTransformer(interpreter, mode) + val checker = IrInterpreterCommonChecker() val irConstExpressionTransformer = IrConstAllTransformer( - interpreter, this, mode, checker, evaluatedConstTracker, inlineConstTracker, { _, _, _ -> }, { _, _, _ -> }, suppressExceptions + interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, + { _, _, _ -> }, { _, _, _ -> }, + suppressExceptions ) - this.transform(irConstExpressionTransformer, IrConstTransformer.Data()) + preprocessedFile.transform(irConstExpressionTransformer, IrConstTransformer.Data()) } -fun IrFile.preprocessForConstTransformer( +private fun IrFile.preprocessForConstTransformer( interpreter: IrInterpreter, mode: EvaluationMode, ): IrFile { diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/constEvaluationWithDifferentLV/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/constEvaluationWithDifferentLV/library/a.kt new file mode 100644 index 00000000000..0a03116a2f9 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/constEvaluationWithDifferentLV/library/a.kt @@ -0,0 +1,10 @@ +package lib + +public class Plot { + public val layout: Int = 0 +} + +public fun plotFun(plot: Plot): String { + val mustBeOptimizedByCompiler = plot::layout.name + return mustBeOptimizedByCompiler +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/constEvaluationWithDifferentLV/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/constEvaluationWithDifferentLV/output.txt new file mode 100644 index 00000000000..538bb7afbb1 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/constEvaluationWithDifferentLV/output.txt @@ -0,0 +1,4 @@ +info: produce executable: $TMP_DIR$/usage.js +info: cache directory: null +info: executable production duration: [time] +OK diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/constEvaluationWithDifferentLV/src/empty.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/constEvaluationWithDifferentLV/src/empty.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.kt index 32f99044f65..0e9dd7a6de3 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.kt @@ -712,6 +712,14 @@ abstract class AbstractCompileKotlinAgainstCustomBinariesTest : AbstractKotlinCo output.lines().filterNot { "argument -Xexpect-actual-linker is deprecated" in it }.joinToString("\n") } + fun testConstEvaluationWithDifferentLV() { + val library = compileJsLibrary("library", additionalOptions = listOf("-language-version", "1.9")) + compileKotlin( + "src", File(tmpdir, "usage.js"), emptyList(), K2JSCompiler(), + additionalOptions = listOf("-Xinclude=${library.absolutePath}", "-Xir-produce-js"), + ) + } + private fun doTestAnonymousObjectTypeMetadata( extraCommandLineArguments: List = emptyList(), filterOutput: (String) -> String = { output -> output }