Support -Xg0 compiler flag (#3154)
Enables generation of partial debug information (e.g. useful for crash reports symbolication). Supposed to avoid affecting '-opt' optimization quality.
This commit is contained in:
committed by
GitHub
parent
8ad8529611
commit
5cb8d97e2a
@@ -150,6 +150,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
put(LIST_TARGETS, arguments.listTargets)
|
||||
put(OPTIMIZATION, arguments.optimization)
|
||||
put(DEBUG, arguments.debug)
|
||||
put(LIGHT_DEBUG, arguments.lightDebug)
|
||||
put(STATIC_FRAMEWORK, selectFrameworkType(configuration, arguments, outputKind))
|
||||
|
||||
put(PRINT_IR, arguments.printIr)
|
||||
|
||||
@@ -133,6 +133,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
|
||||
)
|
||||
var frameworkImportHeaders: Array<String>? = null
|
||||
|
||||
@Argument(value = "-Xg0", description = "Add light debug information")
|
||||
var lightDebug: Boolean = false
|
||||
|
||||
@Argument(value = "-Xprint-bitcode", deprecatedName = "--print_bitcode", description = "Print llvm bitcode")
|
||||
var printBitCode: Boolean = false
|
||||
|
||||
|
||||
+2
@@ -428,6 +428,8 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
fun shouldProfilePhases() = config.phaseConfig.needProfiling
|
||||
|
||||
fun shouldContainDebugInfo() = config.debug
|
||||
fun shouldContainLocationDebugInfo() = shouldContainDebugInfo() || config.lightDebug
|
||||
fun shouldContainAnyDebugInfo() = shouldContainDebugInfo() || shouldContainLocationDebugInfo()
|
||||
|
||||
fun shouldOptimize() = config.configuration.getBoolean(KonanConfigKeys.OPTIMIZATION)
|
||||
|
||||
|
||||
+2
@@ -44,7 +44,9 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
|
||||
val infoArgsOnly = configuration.kotlinSourceRoots.isEmpty() && !linkOnly
|
||||
|
||||
// TODO: debug info generation mode and debug/release variant selection probably requires some refactoring.
|
||||
val debug: Boolean get() = configuration.getBoolean(KonanConfigKeys.DEBUG)
|
||||
val lightDebug: Boolean get() = configuration.getBoolean(KonanConfigKeys.LIGHT_DEBUG)
|
||||
|
||||
val memoryModel: MemoryModel get() = configuration.get(KonanConfigKeys.MEMORY_MODEL)!!
|
||||
|
||||
|
||||
+2
@@ -44,6 +44,8 @@ class KonanConfigKeys {
|
||||
= CompilerConfigurationKey.create("library file paths")
|
||||
val LIBRARY_VERSION: CompilerConfigurationKey<String?>
|
||||
= CompilerConfigurationKey.create("library version")
|
||||
val LIGHT_DEBUG: CompilerConfigurationKey<Boolean>
|
||||
= CompilerConfigurationKey.create("add light debug information")
|
||||
val LINKER_ARGS: CompilerConfigurationKey<List<String>>
|
||||
= CompilerConfigurationKey.create("additional linker arguments")
|
||||
val LIST_PHASES: CompilerConfigurationKey<Boolean>
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ internal class Linker(val context: Context) {
|
||||
private val linker = platform.linker
|
||||
private val target = context.config.target
|
||||
private val optimize = context.shouldOptimize()
|
||||
private val debug = context.config.debug
|
||||
private val debug = context.config.debug || context.config.lightDebug
|
||||
|
||||
// Ideally we'd want to have
|
||||
// #pragma weak main = Konan_main
|
||||
|
||||
+1
-1
@@ -210,7 +210,7 @@ internal val finalizeDebugInfoPhase = makeKonanModuleOpPhase(
|
||||
name = "FinalizeDebugInfo",
|
||||
description = "Finalize debug info",
|
||||
op = { context, _ ->
|
||||
if (context.shouldContainDebugInfo()) {
|
||||
if (context.shouldContainAnyDebugInfo()) {
|
||||
DIFinalize(context.debugInfo.builder)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -673,7 +673,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
}
|
||||
|
||||
internal fun debugLocation(startLocationInfo: LocationInfo, endLocation: LocationInfo?): DILocationRef? {
|
||||
if (!context.shouldContainDebugInfo()) return null
|
||||
if (!context.shouldContainLocationDebugInfo()) return null
|
||||
update(currentBlock, startLocationInfo, endLocation)
|
||||
val debugLocation = codegen.generateLocationInfo(startLocationInfo)
|
||||
currentPositionHolder.setBuilderDebugLocation(debugLocation)
|
||||
@@ -880,7 +880,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
}
|
||||
|
||||
fun resetDebugLocation() {
|
||||
if (!context.shouldContainDebugInfo()) return
|
||||
if (!context.shouldContainLocationDebugInfo()) return
|
||||
currentPositionHolder.resetBuilderDebugLocation()
|
||||
}
|
||||
|
||||
@@ -1057,12 +1057,12 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
}
|
||||
|
||||
fun resetBuilderDebugLocation() {
|
||||
if (!context.shouldContainDebugInfo()) return
|
||||
if (!context.shouldContainLocationDebugInfo()) return
|
||||
LLVMBuilderResetDebugLocation(builder)
|
||||
}
|
||||
|
||||
fun setBuilderDebugLocation(debugLocation: DILocationRef?) {
|
||||
if (!context.shouldContainDebugInfo()) return
|
||||
if (!context.shouldContainLocationDebugInfo()) return
|
||||
LLVMBuilderSetDebugLocation(builder, debugLocation)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ internal fun String?.toFileAndFolder():FileAndFolder {
|
||||
}
|
||||
|
||||
internal fun generateDebugInfoHeader(context: Context) {
|
||||
if (context.shouldContainDebugInfo()) {
|
||||
if (context.shouldContainAnyDebugInfo()) {
|
||||
val path = context.config.outputFile
|
||||
.toFileAndFolder()
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
||||
+8
-8
@@ -608,7 +608,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
|
||||
private val scope by lazy {
|
||||
if (!context.shouldContainDebugInfo())
|
||||
if (!context.shouldContainLocationDebugInfo())
|
||||
return@lazy null
|
||||
declaration?.scope() ?: llvmFunction!!.scope(0, subroutineType(context, codegen.llvmTargetData, listOf(context.irBuiltIns.intType)))
|
||||
}
|
||||
@@ -672,7 +672,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
|
||||
private fun IrFunction.location(start: Boolean) =
|
||||
if (context.shouldContainDebugInfo() && startOffset != UNDEFINED_OFFSET) LocationInfo(
|
||||
if (context.shouldContainLocationDebugInfo() && startOffset != UNDEFINED_OFFSET) LocationInfo(
|
||||
scope = scope()!!,
|
||||
line = if (start) startLine() else endLine(),
|
||||
column = if (start) startColumn() else endColumn())
|
||||
@@ -1600,7 +1600,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
* Note: DILexicalBlocks aren't nested, they should be scoped with the parent function.
|
||||
*/
|
||||
private val scope by lazy {
|
||||
if (!context.shouldContainDebugInfo() || returnableBlock.startOffset == UNDEFINED_OFFSET)
|
||||
if (!context.shouldContainLocationDebugInfo() || returnableBlock.startOffset == UNDEFINED_OFFSET)
|
||||
return@lazy null
|
||||
val lexicalBlockFile = DICreateLexicalBlockFile(context.debugInfo.builder, functionScope()!!.scope(), super.file.file())
|
||||
DICreateLexicalBlock(context.debugInfo.builder, lexicalBlockFile, super.file.file(), returnableBlock.startLine(), returnableBlock.startColumn())!!
|
||||
@@ -1619,7 +1619,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private val scope by lazy {
|
||||
if (!context.shouldContainDebugInfo())
|
||||
if (!context.shouldContainLocationDebugInfo())
|
||||
return@lazy null
|
||||
file.file() as DIScopeOpaqueRef?
|
||||
}
|
||||
@@ -1734,16 +1734,16 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
private fun updateBuilderDebugLocation(element: IrElement) {
|
||||
if (!context.shouldContainDebugInfo() || currentCodeContext.functionScope() == null || element.startLocation == null) return
|
||||
if (!context.shouldContainLocationDebugInfo() || currentCodeContext.functionScope() == null || element.startLocation == null) return
|
||||
functionGenerationContext.debugLocation(element.startLocation!!, element.endLocation!!)
|
||||
}
|
||||
|
||||
private val IrElement.startLocation: LocationInfo?
|
||||
get() = if (!context.shouldContainDebugInfo() || startOffset == UNDEFINED_OFFSET) null
|
||||
get() = if (!context.shouldContainLocationDebugInfo() || startOffset == UNDEFINED_OFFSET) null
|
||||
else currentCodeContext.location(startLine(), startColumn())
|
||||
|
||||
private val IrElement.endLocation: LocationInfo?
|
||||
get() = if (!context.shouldContainDebugInfo() || startOffset == UNDEFINED_OFFSET) null
|
||||
get() = if (!context.shouldContainLocationDebugInfo() || startOffset == UNDEFINED_OFFSET) null
|
||||
else currentCodeContext.location(endLine(), endColumn())
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -1807,7 +1807,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun IrFunction.scope(startLine:Int): DIScopeOpaqueRef? {
|
||||
if (codegen.isExternal(this) || !context.shouldContainDebugInfo())
|
||||
if (codegen.isExternal(this) || !context.shouldContainLocationDebugInfo())
|
||||
return null
|
||||
val functionLlvmValue = codegen.llvmFunctionOrNull(this)
|
||||
return if (functionLlvmValue != null) {
|
||||
|
||||
@@ -132,6 +132,7 @@ open class MacOSBasedLinker(targetProperties: AppleConfigurables)
|
||||
|
||||
private val libtool = "$absoluteTargetToolchain/usr/bin/libtool"
|
||||
private val linker = "$absoluteTargetToolchain/usr/bin/ld"
|
||||
private val strip = "$absoluteTargetToolchain/usr/bin/strip"
|
||||
private val dsymutil = "$absoluteLlvmHome/bin/llvm-dsymutil"
|
||||
|
||||
private fun provideCompilerRtLibrary(libraryName: String): String? {
|
||||
@@ -177,7 +178,10 @@ open class MacOSBasedLinker(targetProperties: AppleConfigurables)
|
||||
+libraries
|
||||
})
|
||||
val dynamic = kind == LinkerOutputKind.DYNAMIC_LIBRARY
|
||||
return listOf(Command(linker).apply {
|
||||
|
||||
val result = mutableListOf<Command>()
|
||||
|
||||
result += Command(linker).apply {
|
||||
+"-demangle"
|
||||
+listOf("-dynamic", "-arch", arch)
|
||||
+osVersionMinFlags
|
||||
@@ -192,7 +196,17 @@ open class MacOSBasedLinker(targetProperties: AppleConfigurables)
|
||||
+libraries
|
||||
+linkerArgs
|
||||
+rpath(dynamic)
|
||||
}) + if (debug) listOf(dsymUtilCommand(executable, outputDsymBundle)) else emptyList()
|
||||
}
|
||||
|
||||
// TODO: revise debug information handling.
|
||||
if (debug) {
|
||||
result += dsymUtilCommand(executable, outputDsymBundle)
|
||||
if (optimize) {
|
||||
result += Command(strip, "-S", executable)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun rpath(dynamic: Boolean): List<String> = listOfNotNull(
|
||||
|
||||
Reference in New Issue
Block a user