Rework invalid LLVM module reporting
* Dump module to file instead of stderr * Report errors in an exception message instead of stdout (useful when running in Gradle daemon)
This commit is contained in:
committed by
GitHub
parent
c8c07f60b1
commit
134562c1f8
-15
@@ -73,21 +73,6 @@ val IrField.isMainOnlyNonPrimitive get() = when {
|
||||
else -> storageKind == FieldStorageKind.MAIN_THREAD
|
||||
}
|
||||
|
||||
internal fun verifyModule(llvmModule: LLVMModuleRef, current: String = "") {
|
||||
memScoped {
|
||||
val errorRef = allocPointerTo<ByteVar>()
|
||||
val verificationResult = LLVMVerifyModule(
|
||||
llvmModule, LLVMVerifierFailureAction.LLVMPrintMessageAction, errorRef.ptr)
|
||||
LLVMDisposeMessage(errorRef.value)
|
||||
if (verificationResult == 1) {
|
||||
if (current.isNotEmpty())
|
||||
println("Error in $current")
|
||||
LLVMDumpModule(llvmModule)
|
||||
throw Error("Invalid module")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid {
|
||||
val generator = RTTIGenerator(context)
|
||||
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import kotlinx.cinterop.*
|
||||
import llvm.*
|
||||
import java.io.File
|
||||
|
||||
internal fun verifyModule(llvmModule: LLVMModuleRef, current: String = "") = memScoped {
|
||||
val errorRef = allocPointerTo<ByteVar>()
|
||||
errorRef.value = null
|
||||
|
||||
val verificationResult = LLVMVerifyModule(
|
||||
llvmModule,
|
||||
LLVMVerifierFailureAction.LLVMReturnStatusAction,
|
||||
errorRef.ptr
|
||||
)
|
||||
|
||||
val verificationError = convertAndDisposeLlvmMessage(errorRef.value)
|
||||
|
||||
if (verificationResult != 0) {
|
||||
throwModuleVerificationError(llvmModule, current, verificationError)
|
||||
}
|
||||
}
|
||||
|
||||
private fun throwModuleVerificationError(
|
||||
llvmModule: LLVMModuleRef,
|
||||
current: String,
|
||||
verificationError: String?
|
||||
): Nothing {
|
||||
val exceptionMessage = buildString {
|
||||
try {
|
||||
appendModuleVerificationFailureDetails(llvmModule, current, verificationError)
|
||||
} catch (e: Throwable) {
|
||||
appendLine("Failed to make full error message: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
throw Error(exceptionMessage)
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendModuleVerificationFailureDetails(
|
||||
llvmModule: LLVMModuleRef,
|
||||
current: String,
|
||||
verificationError: String?
|
||||
) {
|
||||
appendLine("Invalid LLVM module")
|
||||
|
||||
if (current.isNotEmpty())
|
||||
appendLine("Error in $current")
|
||||
|
||||
appendVerificationError(verificationError)
|
||||
|
||||
val moduleDumpFile = createTempFile("kotlin_native_llvm_module_dump", ".ll")
|
||||
|
||||
dumpModuleAndAppendDetails(llvmModule, moduleDumpFile)
|
||||
|
||||
moduleDumpFile.appendText(verificationError.orEmpty())
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendVerificationError(error: String?) {
|
||||
if (error == null) return
|
||||
|
||||
val lines = error.lines()
|
||||
appendLine("Verification errors:")
|
||||
|
||||
val maxLines = 12
|
||||
|
||||
lines.take(maxLines).forEach {
|
||||
appendLine(" $it")
|
||||
}
|
||||
|
||||
if (lines.size > maxLines) {
|
||||
appendLine(" ... (full error is available at the LLVM module dump file)")
|
||||
}
|
||||
}
|
||||
|
||||
private fun StringBuilder.dumpModuleAndAppendDetails(llvmModule: LLVMModuleRef, moduleDumpFile: File) = memScoped {
|
||||
val errorRef = allocPointerTo<ByteVar>()
|
||||
errorRef.value = null
|
||||
val printedWithErrors = LLVMPrintModuleToFile(llvmModule, moduleDumpFile.absolutePath, errorRef.ptr)
|
||||
|
||||
appendLine()
|
||||
appendLine("LLVM module dump: ${moduleDumpFile.absolutePath}")
|
||||
|
||||
val modulePrintError = convertAndDisposeLlvmMessage(errorRef.value)
|
||||
if (printedWithErrors != 0) {
|
||||
appendLine(" (printed with errors: $modulePrintError)")
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertAndDisposeLlvmMessage(message: CPointer<ByteVar>?): String? =
|
||||
try {
|
||||
message?.toKString()
|
||||
} finally {
|
||||
LLVMDisposeMessage(message)
|
||||
}
|
||||
Reference in New Issue
Block a user