[K/N] Support -Xsave-llvm-ir-after compiler option

This commit is contained in:
Pavel Kunyavskiy
2021-12-20 14:07:12 +03:00
committed by Space
parent 0689d74353
commit c97f4a4d20
7 changed files with 49 additions and 20 deletions
@@ -182,7 +182,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
arguments.manifestFile ?.let{ put(MANIFEST_FILE, it) }
arguments.runtimeFile ?.let{ put(RUNTIME_FILE, it) }
arguments.temporaryFilesDir?.let { put(TEMPORARY_FILES_DIR, it) }
put(SAVE_LLVM_IR, arguments.saveLlvmIr)
put(SAVE_LLVM_IR, arguments.saveLlvmIrAfter.toList())
put(LIST_TARGETS, arguments.listTargets)
put(OPTIMIZATION, arguments.optimization)
@@ -255,8 +255,8 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
@Argument(value = "-Xtemporary-files-dir", deprecatedName = "--temporary_files_dir", valueDescription = "<path>", description = "Save temporary files to the given directory")
var temporaryFilesDir: String? = null
@Argument(value = "-Xsave-llvm-ir", description = "Save result of Kotlin IR to LLVM IR translation to the temporary files directory.")
var saveLlvmIr: Boolean = false
@Argument(value = "-Xsave-llvm-ir-after", description = "Save result of Kotlin IR to LLVM IR translation to the temporary files directory.")
var saveLlvmIrAfter: Array<String> = emptyArray()
@Argument(value = "-Xverify-bitcode", deprecatedName = "--verify_bitcode", description = "Verify llvm bitcode after each method")
var verifyBitCode: Boolean = false
@@ -9,10 +9,13 @@ import kotlinx.cinterop.memScoped
import kotlinx.cinterop.ptr
import kotlinx.cinterop.toKStringFromUtf8
import llvm.*
import org.jetbrains.kotlin.backend.common.phaser.ActionState
import org.jetbrains.kotlin.backend.common.phaser.BeforeOrAfter
import org.jetbrains.kotlin.backend.common.serialization.KlibIrVersion
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.backend.konan.llvm.*
import org.jetbrains.kotlin.backend.konan.llvm.objc.linkObjC
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.konan.CURRENT
import org.jetbrains.kotlin.konan.CompilerVersion
import org.jetbrains.kotlin.konan.file.isBitcode
@@ -47,6 +50,20 @@ val CompilerOutputKind.involvesLinkStage: Boolean
val CompilerOutputKind.isCache: Boolean
get() = (this == CompilerOutputKind.STATIC_CACHE || this == CompilerOutputKind.DYNAMIC_CACHE)
internal fun llvmIrDumpCallback(state: ActionState, module: IrModuleFragment, context: Context) {
module.let{}
if (state.beforeOrAfter == BeforeOrAfter.AFTER && state.phase.name in context.configuration.getList(KonanConfigKeys.SAVE_LLVM_IR)) {
val moduleName: String = memScoped {
val sizeVar = alloc<size_tVar>()
LLVMGetModuleIdentifier(context.llvmModule, sizeVar.ptr)!!.toKStringFromUtf8()
}
val output = context.config.tempFiles.create("$moduleName.${state.phase.name}", ".ll")
if (LLVMPrintModuleToFile(context.llvmModule, output.absolutePath, null) != 0) {
error("Can't dump LLVM IR to ${output.absolutePath}")
}
}
}
internal fun produceCStubs(context: Context) {
val llvmModule = context.llvmModule!!
context.cStubsManager.compile(
@@ -56,17 +73,6 @@ internal fun produceCStubs(context: Context) {
).forEach {
parseAndLinkBitcodeFile(context, llvmModule, it.absolutePath)
}
// TODO: Consider adding LLVM_IR compiler output kind.
if (context.configuration.getBoolean(KonanConfigKeys.SAVE_LLVM_IR)) {
val moduleName: String = memScoped {
val sizeVar = alloc<size_tVar>()
LLVMGetModuleIdentifier(context.llvmModule, sizeVar.ptr)!!.toKStringFromUtf8()
}
val output = context.config.tempFiles.create(moduleName,".ll")
if (LLVMPrintModuleToFile(context.llvmModule, output.absolutePath, null) != 0) {
error("Can't dump LLVM IR to ${output.absolutePath}")
}
}
}
private fun linkAllDependencies(context: Context, generatedBitcodeFiles: List<String>) {
@@ -134,7 +134,7 @@ class KonanConfigKeys {
= CompilerConfigurationKey.create("target we compile for")
val TEMPORARY_FILES_DIR: CompilerConfigurationKey<String?>
= CompilerConfigurationKey.create("directory for temporary files")
val SAVE_LLVM_IR: CompilerConfigurationKey<Boolean>
val SAVE_LLVM_IR: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("save LLVM IR")
val VERIFY_BITCODE: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("verify bitcode")
@@ -1,5 +1,11 @@
package org.jetbrains.kotlin.backend.konan
import kotlinx.cinterop.alloc
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.ptr
import kotlinx.cinterop.toKStringFromUtf8
import llvm.LLVMGetModuleIdentifier
import llvm.LLVMPrintModuleToFile
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.lower.StringConcatenationLowering
@@ -20,8 +26,16 @@ import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
private val validateAll = false
private val filePhaseActions = if (validateAll) setOf(defaultDumper, ::fileValidationCallback) else setOf(defaultDumper)
private val modulePhaseActions = if (validateAll) setOf(defaultDumper, ::moduleValidationCallback) else setOf(defaultDumper)
private val filePhaseActions = setOfNotNull(
defaultDumper,
::fileValidationCallback.takeIf { validateAll }
)
private val modulePhaseActions = setOfNotNull(
defaultDumper,
::llvmIrDumpCallback,
::moduleValidationCallback.takeIf { validateAll }
)
private fun makeKonanFileLoweringPhase(
lowering: (Context) -> FileLoweringPass,
@@ -5955,7 +5955,7 @@ pluginTest("runtime_basic_init", "nopPlugin") {
Task fileCheckTest(String name, Closure<FileCheckTest> configureClosure) {
return project.tasks.create(name, FileCheckTest) { task ->
task.configure(configureClosure)
task.llvmIr = project.file("$testOutputFileCheck/$name/$target/out.ll")
task.llvmIr = project.file("$testOutputFileCheck/$name/$target/out.${task.phaseToCheck}.ll")
if (task.enabled) {
konanArtifacts {
def lib = task.interop
@@ -5971,7 +5971,8 @@ Task fileCheckTest(String name, Closure<FileCheckTest> configureClosure) {
srcFiles task.annotatedSource
baseDir "$testOutputFileCheck/$name"
extraOpts project.globalTestArgs
extraOpts "-Xtemporary-files-dir=$testOutputFileCheck/$name/$target", "-Xsave-llvm-ir"
extraOpts "-Xtemporary-files-dir=$testOutputFileCheck/$name/$target"
extraOpts "-Xsave-llvm-ir-after=${task.phaseToCheck}"
if (lib != null) {
libraries {
artifact lib
@@ -5984,7 +5985,9 @@ Task fileCheckTest(String name, Closure<FileCheckTest> configureClosure) {
srcFiles task.annotatedSource
baseDir "$testOutputFileCheck/$name"
extraOpts project.globalTestArgs
extraOpts "-Xtemporary-files-dir=$testOutputFileCheck/$name/$target", "-Xsave-llvm-ir", "-Xmeaningful-bridge-names"
extraOpts "-Xtemporary-files-dir=$testOutputFileCheck/$name/$target", "-Xmeaningful-bridge-names"
extraOpts "-Xsave-llvm-ir-after=${task.phaseToCheck}"
if (lib != null) {
libraries {
artifact lib
@@ -61,6 +61,12 @@ open class FileCheckTest : DefaultTask() {
@Optional
var checkPrefix: String? = null
/**
* Compiler pipeline phase name, after which check should be done
*/
@Input
var phaseToCheck: String = "CStubs"
/**
* Should we generate framework instead of an executable?
* This option is useful for, well, checking framework-specific code.