[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") {
|
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, )
|
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.common.messages.AnalyzerWithCompilerReport
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
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.*
|
||||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
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.IrModuleToJsTransformerTmp
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
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 org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||||
import java.io.File
|
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 class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
|
||||||
|
abstract val useIncrementalCompiler: Boolean
|
||||||
|
|
||||||
override fun stdlibFile(): File = File("libraries/stdlib/js-ir/build/classes/kotlin/js/main").absoluteFile
|
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) {
|
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>) {
|
override fun buildBinaryAndRun(mainModuleKlibFile: File, libraries: Collection<File>) {
|
||||||
val project = environment.project
|
val configuration = environment.configuration.copy()
|
||||||
val configuration = environment.configuration
|
|
||||||
|
|
||||||
configuration.put(JSConfigurationKeys.PARTIAL_LINKAGE, true)
|
configuration.put(JSConfigurationKeys.PARTIAL_LINKAGE, true)
|
||||||
configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
||||||
configuration.put(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION, true)
|
configuration.put(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION, true)
|
||||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, MAIN_MODULE_NAME)
|
configuration.put(CommonConfigurationKeys.MODULE_NAME, MAIN_MODULE_NAME)
|
||||||
|
|
||||||
val kLib = MainModule.Klib(mainModuleKlibFile.path)
|
val compilationOutputs = if (useIncrementalCompiler)
|
||||||
val moduleStructure = ModulesStructure(project, kLib, configuration, libraries.map { it.path }, emptyList())
|
buildBinaryWithIC(configuration, mainModuleKlibFile, libraries)
|
||||||
|
else
|
||||||
val ir = compile(
|
buildBinaryNoIC(configuration, mainModuleKlibFile, libraries)
|
||||||
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 binariesDir = File(buildDir, BIN_DIR_NAME).also { it.mkdirs() }
|
val binariesDir = File(buildDir, BIN_DIR_NAME).also { it.mkdirs() }
|
||||||
|
|
||||||
val binaries = ArrayList<File>(libraries.size)
|
val binaries = ArrayList<File>(libraries.size)
|
||||||
|
|
||||||
for ((name, code) in dceOutput.dependencies) {
|
for ((name, code) in compilationOutputs.dependencies) {
|
||||||
val depBinary = binariesDir.binJsFile(name)
|
val depBinary = binariesDir.binJsFile(name)
|
||||||
depBinary.parentFile?.let { if (!it.exists()) it.mkdirs() }
|
depBinary.parentFile?.let { if (!it.exists()) it.mkdirs() }
|
||||||
depBinary.writeText(code.jsCode)
|
depBinary.writeText(code.jsCode)
|
||||||
@@ -88,12 +86,73 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val mainBinary = binariesDir.binJsFile(MAIN_MODULE_NAME)
|
val mainBinary = binariesDir.binJsFile(MAIN_MODULE_NAME)
|
||||||
mainBinary.writeText(dceOutput.jsCode)
|
mainBinary.writeText(compilationOutputs.jsCode)
|
||||||
binaries.add(mainBinary)
|
binaries.add(mainBinary)
|
||||||
|
|
||||||
executeAndCheckBinaries(MAIN_MODULE_NAME, binaries)
|
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> {
|
private fun KotlinCoreEnvironment.createPsiFiles(sourceDir: File): List<KtFile> {
|
||||||
val psiManager = PsiManager.getInstance(project)
|
val psiManager = PsiManager.getInstance(project)
|
||||||
val fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL) as CoreLocalFileSystem
|
val fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL) as CoreLocalFileSystem
|
||||||
@@ -112,10 +171,11 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
|
|||||||
val checker = V8IrJsTestChecker
|
val checker = V8IrJsTestChecker
|
||||||
|
|
||||||
val filePaths = dependencies.map { it.canonicalPath }
|
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 {
|
companion object {
|
||||||
private const val BIN_DIR_NAME = "_bins_js"
|
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")
|
@TestMetadata("compiler/testData/klibABI")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
public class JsKLibABITestCaseGenerated extends AbstractJsKLibABITestCase {
|
public class JsKLibABINoICTestCaseGenerated extends AbstractJsKLibABINoICTestCase {
|
||||||
private void runTest(String testDataFilePath) throws Exception {
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
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