[IR][JS] Partial linkage: Support KLIB ABI compat tests w/ and w/o IC
This commit is contained in:
committed by
Space Team
parent
afcf78ac94
commit
6f8c2a36f9
@@ -43,7 +43,12 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
|
||||
testGroup("js/js.tests/tests-gen", "compiler/testData") {
|
||||
testClass<AbstractJsKLibABITestCase> {
|
||||
testClass<AbstractJsKLibABIWithICTestCase> {
|
||||
model("klibABI/", pattern = "^([^_](.+))$", targetBackend = TargetBackend.JS_IR, recursive = false, )
|
||||
}
|
||||
}
|
||||
testGroup("js/js.tests/tests-gen", "compiler/testData") {
|
||||
testClass<AbstractJsKLibABINoICTestCase> {
|
||||
model("klibABI/", pattern = "^([^_](.+))$", targetBackend = TargetBackend.JS_IR, recursive = false, )
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,11 @@ import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.ir.backend.js.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.CacheUpdater
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.JsExecutableProducer
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformerTmp
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
@@ -28,7 +31,17 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractJsKLibABIWithICTestCase : AbstractJsKLibABITestCase() {
|
||||
override val useIncrementalCompiler get() = true
|
||||
}
|
||||
|
||||
abstract class AbstractJsKLibABINoICTestCase : AbstractJsKLibABITestCase() {
|
||||
override val useIncrementalCompiler get() = false
|
||||
}
|
||||
|
||||
abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
|
||||
abstract val useIncrementalCompiler: Boolean
|
||||
|
||||
override fun stdlibFile(): File = File("libraries/stdlib/js-ir/build/classes/kotlin/js/main").absoluteFile
|
||||
|
||||
override fun buildKlib(moduleName: String, moduleSourceDir: File, moduleDependencies: Collection<File>, klibFile: File) {
|
||||
@@ -50,37 +63,22 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
|
||||
}
|
||||
|
||||
override fun buildBinaryAndRun(mainModuleKlibFile: File, libraries: Collection<File>) {
|
||||
val project = environment.project
|
||||
val configuration = environment.configuration
|
||||
val configuration = environment.configuration.copy()
|
||||
|
||||
configuration.put(JSConfigurationKeys.PARTIAL_LINKAGE, true)
|
||||
configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
||||
configuration.put(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION, true)
|
||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, MAIN_MODULE_NAME)
|
||||
|
||||
val kLib = MainModule.Klib(mainModuleKlibFile.path)
|
||||
val moduleStructure = ModulesStructure(project, kLib, configuration, libraries.map { it.path }, emptyList())
|
||||
|
||||
val ir = compile(
|
||||
moduleStructure,
|
||||
PhaseConfig(jsPhases),
|
||||
IrFactoryImplForJsIC(WholeWorldStageController()),
|
||||
exportedDeclarations = setOf(FqName("box")),
|
||||
granularity = JsGenerationGranularity.PER_MODULE,
|
||||
icCompatibleIr2Js = true
|
||||
)
|
||||
|
||||
val transformer = IrModuleToJsTransformerTmp(ir.context, emptyList())
|
||||
|
||||
val compiledResult = transformer.generateModule(ir.allModules, setOf(TranslationMode.FULL_DCE_MINIMIZED_NAMES), false)
|
||||
|
||||
val dceOutput = compiledResult.outputs[TranslationMode.FULL_DCE_MINIMIZED_NAMES] ?: error("No DCE output")
|
||||
val compilationOutputs = if (useIncrementalCompiler)
|
||||
buildBinaryWithIC(configuration, mainModuleKlibFile, libraries)
|
||||
else
|
||||
buildBinaryNoIC(configuration, mainModuleKlibFile, libraries)
|
||||
|
||||
val binariesDir = File(buildDir, BIN_DIR_NAME).also { it.mkdirs() }
|
||||
|
||||
val binaries = ArrayList<File>(libraries.size)
|
||||
|
||||
for ((name, code) in dceOutput.dependencies) {
|
||||
for ((name, code) in compilationOutputs.dependencies) {
|
||||
val depBinary = binariesDir.binJsFile(name)
|
||||
depBinary.parentFile?.let { if (!it.exists()) it.mkdirs() }
|
||||
depBinary.writeText(code.jsCode)
|
||||
@@ -88,12 +86,73 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
|
||||
}
|
||||
|
||||
val mainBinary = binariesDir.binJsFile(MAIN_MODULE_NAME)
|
||||
mainBinary.writeText(dceOutput.jsCode)
|
||||
mainBinary.writeText(compilationOutputs.jsCode)
|
||||
binaries.add(mainBinary)
|
||||
|
||||
executeAndCheckBinaries(MAIN_MODULE_NAME, binaries)
|
||||
}
|
||||
|
||||
private fun buildBinaryWithIC(
|
||||
configuration: CompilerConfiguration,
|
||||
mainModuleKlibFile: File,
|
||||
libraries: Collection<File>
|
||||
): CompilationOutputs {
|
||||
fun cacheDir(library: File): File = buildDir.resolve("libs-cache").resolve(library.name).apply { mkdirs() }
|
||||
|
||||
val cacheUpdater = CacheUpdater(
|
||||
mainModule = mainModuleKlibFile.absolutePath,
|
||||
allModules = libraries.map { it.absolutePath },
|
||||
icCachePaths = libraries.map { cacheDir(it).absolutePath },
|
||||
compilerConfiguration = configuration,
|
||||
irFactory = { IrFactoryImplForJsIC(WholeWorldStageController()) },
|
||||
mainArguments = null,
|
||||
compilerInterfaceFactory = { mainModule, cfg -> JsIrCompilerWithIC(mainModule, cfg, setOf(BOX_FUN_FQN)) }
|
||||
)
|
||||
val icCaches = cacheUpdater.actualizeCaches()
|
||||
|
||||
val mainModuleName = icCaches.last().moduleExternalName
|
||||
val jsExecutableProducer = JsExecutableProducer(
|
||||
mainModuleName = mainModuleName,
|
||||
moduleKind = configuration[JSConfigurationKeys.MODULE_KIND]!!,
|
||||
sourceMapsInfo = SourceMapsInfo.from(configuration),
|
||||
caches = icCaches,
|
||||
relativeRequirePath = true
|
||||
)
|
||||
|
||||
return jsExecutableProducer.buildExecutable(multiModule = true, outJsProgram = true) {}
|
||||
}
|
||||
|
||||
private fun buildBinaryNoIC(
|
||||
configuration: CompilerConfiguration,
|
||||
mainModuleKlibFile: File,
|
||||
libraries: Collection<File>
|
||||
): CompilationOutputs {
|
||||
val klib = MainModule.Klib(mainModuleKlibFile.path)
|
||||
val moduleStructure = ModulesStructure(environment.project, klib, configuration, libraries.map { it.path }, emptyList())
|
||||
|
||||
val ir = compile(
|
||||
moduleStructure,
|
||||
PhaseConfig(jsPhases),
|
||||
IrFactoryImplForJsIC(WholeWorldStageController()),
|
||||
exportedDeclarations = setOf(BOX_FUN_FQN),
|
||||
granularity = JsGenerationGranularity.PER_MODULE,
|
||||
icCompatibleIr2Js = true
|
||||
)
|
||||
|
||||
val transformer = IrModuleToJsTransformerTmp(
|
||||
backendContext = ir.context,
|
||||
mainArguments = emptyList()
|
||||
)
|
||||
|
||||
val compiledResult = transformer.generateModule(
|
||||
modules = ir.allModules,
|
||||
modes = setOf(TranslationMode.FULL_DCE_MINIMIZED_NAMES),
|
||||
relativeRequirePath = false
|
||||
)
|
||||
|
||||
return compiledResult.outputs[TranslationMode.FULL_DCE_MINIMIZED_NAMES] ?: error("No DCE output")
|
||||
}
|
||||
|
||||
private fun KotlinCoreEnvironment.createPsiFiles(sourceDir: File): List<KtFile> {
|
||||
val psiManager = PsiManager.getInstance(project)
|
||||
val fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL) as CoreLocalFileSystem
|
||||
@@ -112,10 +171,11 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
|
||||
val checker = V8IrJsTestChecker
|
||||
|
||||
val filePaths = dependencies.map { it.canonicalPath }
|
||||
checker.check(filePaths, mainModuleName, null, "box", "OK", withModuleSystem = false)
|
||||
checker.check(filePaths, mainModuleName, null, BOX_FUN_FQN.asString(), "OK", withModuleSystem = false)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val BIN_DIR_NAME = "_bins_js"
|
||||
private val BOX_FUN_FQN = FqName("box")
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import java.util.regex.Pattern;
|
||||
@TestMetadata("compiler/testData/klibABI")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class JsKLibABITestCaseGenerated extends AbstractJsKLibABITestCase {
|
||||
public class JsKLibABINoICTestCaseGenerated extends AbstractJsKLibABINoICTestCase {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.js.test;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.GenerateJsTestsKt}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/testData/klibABI")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class JsKLibABIWithICTestCaseGenerated extends AbstractJsKLibABIWithICTestCase {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInKlibABI() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/klibABI"), Pattern.compile("^([^_](.+))$"), null, TargetBackend.JS_IR, false);
|
||||
}
|
||||
|
||||
@TestMetadata("removeAbstractFunctionFromAbstractClass")
|
||||
public void testRemoveAbstractFunctionFromAbstractClass() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeAbstractFunctionFromAbstractClass/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeAbstractFunctionFromInterface")
|
||||
public void testRemoveAbstractFunctionFromInterface() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeAbstractFunctionFromInterface/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeAbstractPropertyFromAbstractClass")
|
||||
public void testRemoveAbstractPropertyFromAbstractClass() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeAbstractPropertyFromAbstractClass/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeAbstractPropertyFromInterface")
|
||||
public void testRemoveAbstractPropertyFromInterface() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeAbstractPropertyFromInterface/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeClassAsConstructorCall")
|
||||
public void testRemoveClassAsConstructorCall() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeClassAsConstructorCall/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeClassAsParameterType")
|
||||
public void testRemoveClassAsParameterType() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeClassAsParameterType/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeClassAsReturnType")
|
||||
public void testRemoveClassAsReturnType() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeClassAsReturnType/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeClassAsSuperTypeArgument")
|
||||
public void testRemoveClassAsSuperTypeArgument() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeClassAsSuperTypeArgument/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeClassAsTypeArgument")
|
||||
public void testRemoveClassAsTypeArgument() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeClassAsTypeArgument/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeClassAsVariableType")
|
||||
public void testRemoveClassAsVariableType() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeClassAsVariableType/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeFunction")
|
||||
public void testRemoveFunction() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeFunction/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeInlinedClass")
|
||||
public void testRemoveInlinedClass() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeInlinedClass/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeInlinedFunction")
|
||||
public void testRemoveInlinedFunction() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeInlinedFunction/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeInlinedProperty")
|
||||
public void testRemoveInlinedProperty() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeInlinedProperty/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeOpenFunction")
|
||||
public void testRemoveOpenFunction() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeOpenFunction/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeOpenProperty")
|
||||
public void testRemoveOpenProperty() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeOpenProperty/");
|
||||
}
|
||||
|
||||
@TestMetadata("removeProperty")
|
||||
public void testRemoveProperty() throws Exception {
|
||||
runTest("compiler/testData/klibABI/removeProperty/");
|
||||
}
|
||||
|
||||
@TestMetadata("typeAliasRHSTypeChange")
|
||||
public void testTypeAliasRHSTypeChange() throws Exception {
|
||||
runTest("compiler/testData/klibABI/typeAliasRHSTypeChange/");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user