[klib tool] Add option to print ir
Dumping the IR from a klib is useful for debugging klib compilations. ^KT-58877
This commit is contained in:
+21
-2
@@ -196,14 +196,14 @@ fun main() {
|
||||
// Klib contents tests
|
||||
testGroup("native/native.tests/tests-gen", "native/native.tests/testData") {
|
||||
testClass<AbstractNativeKlibContentsTest>(
|
||||
suiteTestClassName = "NativeKLibContentsTestGenerated"
|
||||
suiteTestClassName = "NativeKlibContentsTestGenerated"
|
||||
) {
|
||||
model("klibContents", pattern = "^([^_](.+)).kt$", recursive = true)
|
||||
}
|
||||
}
|
||||
testGroup("native/native.tests/tests-gen", "native/native.tests/testData") {
|
||||
testClass<AbstractNativeKlibContentsTest>(
|
||||
suiteTestClassName = "FirNativeKLibContentsTestGenerated",
|
||||
suiteTestClassName = "FirNativeKlibContentsTestGenerated",
|
||||
annotations = listOf(
|
||||
*frontendFir()
|
||||
)
|
||||
@@ -212,6 +212,25 @@ fun main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Klib ir tests
|
||||
testGroup("native/native.tests/tests-gen", "native/native.tests/testData") {
|
||||
testClass<AbstractNativeKlibIrTest>(
|
||||
suiteTestClassName = "NativeKlibIrTestGenerated",
|
||||
) {
|
||||
model("klibIr", pattern = "^([^_](.+)).kt$", recursive = true)
|
||||
}
|
||||
}
|
||||
testGroup("native/native.tests/tests-gen", "native/native.tests/testData") {
|
||||
testClass<AbstractNativeKlibIrTest>(
|
||||
suiteTestClassName = "FirNativeKlibIrTestGenerated",
|
||||
annotations = listOf(
|
||||
*frontendFir()
|
||||
)
|
||||
) {
|
||||
model("klibIr", pattern = "^([^_](.+)).kt$", recursive = true)
|
||||
}
|
||||
}
|
||||
|
||||
// LLDB integration tests.
|
||||
testGroup("native/native.tests/tests-gen", "native/native.tests/testData") {
|
||||
testClass<AbstractNativeBlackBoxTest>(
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.konan.blackboxtest.support.runner.TestRunChecks
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.Binaries
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.CacheMode
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.KotlinNativeTargets
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.PipelineType
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.Timeouts
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
||||
import org.jetbrains.kotlin.test.Directives
|
||||
@@ -36,7 +37,7 @@ import org.jetbrains.kotlin.compatibility.binary.TestModule as TModule
|
||||
abstract class AbstractNativeKlibEvolutionTest : AbstractNativeSimpleTest() {
|
||||
// Const evaluation tests muted for FIR because FIR does const propagation.
|
||||
private fun isIgnoredTest(filePath: String): Boolean {
|
||||
if (!this::class.java.simpleName.startsWith("Fir"))
|
||||
if (testRunSettings.get<PipelineType>() != PipelineType.K2)
|
||||
return false
|
||||
|
||||
val fileName = filePath.substringAfterLast('/')
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.konan.blackboxtest
|
||||
|
||||
import com.intellij.testFramework.TestDataFile
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.PackageName
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCaseId
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCompilerArgs
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestFile
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestKind
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestModule
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestRunnerType
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult.Companion.assertSuccess
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.TestRunChecks
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.KotlinNativeClassLoader
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.PipelineType
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.Timeouts
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.getAbsoluteFile
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.getIr
|
||||
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertEqualsToFile
|
||||
import org.junit.jupiter.api.Tag
|
||||
import java.io.File
|
||||
|
||||
@Tag("klib")
|
||||
abstract class AbstractNativeKlibIrTest : AbstractNativeSimpleTest() {
|
||||
protected fun runTest(@TestDataFile testPath: String) {
|
||||
val testPathFull = getAbsoluteFile(testPath)
|
||||
muteTestIfNecessary(testPathFull)
|
||||
|
||||
val testCase: TestCase = generateTestCaseWithSingleSource(
|
||||
testPathFull,
|
||||
listOf("-Xklib-relative-path-base=${testPathFull.parent}")
|
||||
)
|
||||
val testCompilationResult: TestCompilationResult.Success<out TestCompilationArtifact.KLIB> = compileToLibrary(testCase)
|
||||
|
||||
val testPathNoExtension = testPathFull.canonicalPath.substringBeforeLast(".")
|
||||
|
||||
val firSpecificExt =
|
||||
if (testRunSettings.get<PipelineType>() == PipelineType.K2 && !firIdentical(testPathFull))
|
||||
".fir"
|
||||
else ""
|
||||
|
||||
val expectedContentsNoSig = File("$testPathNoExtension.ir$firSpecificExt.txt")
|
||||
assertIrMatchesExpected(testCompilationResult, expectedContentsNoSig, printSignatures = false)
|
||||
|
||||
val expectedContentsWithSig = File("$testPathNoExtension.sig.ir$firSpecificExt.txt")
|
||||
assertIrMatchesExpected(testCompilationResult, expectedContentsWithSig, printSignatures = true)
|
||||
}
|
||||
|
||||
private fun assertIrMatchesExpected(
|
||||
compilationResult: TestCompilationResult<out TestCompilationArtifact.KLIB>,
|
||||
expectedContents: File,
|
||||
printSignatures: Boolean
|
||||
) {
|
||||
val artifact = compilationResult.assertSuccess().resultingArtifact
|
||||
val kotlinNativeClassLoader = testRunSettings.get<KotlinNativeClassLoader>()
|
||||
val klibIr = artifact.getIr(kotlinNativeClassLoader.classLoader, printSignatures)
|
||||
assertEqualsToFile(expectedContents, klibIr)
|
||||
}
|
||||
|
||||
private fun generateTestCaseWithSingleSource(source: File, extraArgs: List<String>): TestCase {
|
||||
val moduleName: String = source.name
|
||||
val module = TestModule.Exclusive(moduleName, emptySet(), emptySet(), emptySet())
|
||||
module.files += TestFile.createCommitted(source, module)
|
||||
|
||||
return TestCase(
|
||||
id = TestCaseId.Named(moduleName),
|
||||
kind = TestKind.STANDALONE,
|
||||
modules = setOf(module),
|
||||
freeCompilerArgs = TestCompilerArgs(extraArgs),
|
||||
nominalPackageName = PackageName.EMPTY,
|
||||
checks = TestRunChecks.Default(testRunSettings.get<Timeouts>().executionTimeout),
|
||||
extras = TestCase.WithTestRunnerExtras(TestRunnerType.DEFAULT)
|
||||
).apply {
|
||||
initialize(null, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -309,6 +309,9 @@ internal fun AbstractNativeSimpleTest.muteTestIfNecessary(testDataFileContents:
|
||||
Assumptions.assumeFalse(mutedWhenValues.any { it == pipelineType.mutedOption.name })
|
||||
}
|
||||
|
||||
internal fun AbstractNativeSimpleTest.firIdentical(testDataFile: File) =
|
||||
InTextDirectivesUtils.isDirectiveDefined(FileUtil.loadFile(testDataFile), TestDirectives.FIR_IDENTICAL.name)
|
||||
|
||||
internal fun AbstractNativeSimpleTest.freeCompilerArgs(testDataFile: File) = freeCompilerArgs(FileUtil.loadFile(testDataFile))
|
||||
internal fun AbstractNativeSimpleTest.freeCompilerArgs(testDataFileContents: String) =
|
||||
directiveValues(testDataFileContents, TestDirectives.FREE_COMPILER_ARGS.name)
|
||||
|
||||
+4
@@ -140,6 +140,10 @@ internal object TestDirectives : SimpleDirectivesContainer() {
|
||||
Usage: // MUTED_WHEN: [K1, K2]
|
||||
In native simple tests, specify the pipeline types to mute the test""".trimIndent(),
|
||||
)
|
||||
|
||||
val FIR_IDENTICAL by directive(
|
||||
description = "Test behavior should be identical for FIR testing"
|
||||
)
|
||||
}
|
||||
|
||||
internal enum class TestKind {
|
||||
|
||||
+16
-3
@@ -6,14 +6,27 @@
|
||||
package org.jetbrains.kotlin.konan.blackboxtest.support.util
|
||||
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact
|
||||
import java.io.File
|
||||
|
||||
internal fun TestCompilationArtifact.KLIB.getContents(kotlinNativeClassLoader: ClassLoader): String {
|
||||
private fun invokeKlibTool(kotlinNativeClassLoader: ClassLoader, klibFile: File, functionName: String, vararg args: Any): String {
|
||||
val libraryClass = Class.forName("org.jetbrains.kotlin.cli.klib.Library", true, kotlinNativeClassLoader)
|
||||
val entryPoint = libraryClass.declaredMethods.single { it.name == "contents" }
|
||||
val entryPoint = libraryClass.declaredMethods.single { it.name == functionName }
|
||||
val lib = libraryClass.getDeclaredConstructor(String::class.java, String::class.java, String::class.java)
|
||||
.newInstance(klibFile.canonicalPath, null, "host")
|
||||
|
||||
val output = StringBuilder()
|
||||
entryPoint.invoke(lib, output, false)
|
||||
entryPoint.invoke(lib, output, *args)
|
||||
return output.toString()
|
||||
|
||||
}
|
||||
|
||||
internal fun TestCompilationArtifact.KLIB.getContents(kotlinNativeClassLoader: ClassLoader): String {
|
||||
return invokeKlibTool(kotlinNativeClassLoader, klibFile, "contents", false)
|
||||
}
|
||||
|
||||
internal fun TestCompilationArtifact.KLIB.getIr(
|
||||
kotlinNativeClassLoader: ClassLoader,
|
||||
printSignatures: Boolean = false,
|
||||
): String {
|
||||
return invokeKlibTool(kotlinNativeClassLoader, klibFile, "ir", printSignatures)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user