[K/N] Support -Xsave-llvm-ir-after compiler option
This commit is contained in:
@@ -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)
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+17
-11
@@ -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>) {
|
||||
|
||||
+1
-1
@@ -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")
|
||||
|
||||
+16
-2
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user