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:
SvyatoslavScherbina
2019-08-01 12:24:49 +03:00
committed by GitHub
parent 8ad8529611
commit 5cb8d97e2a
11 changed files with 41 additions and 17 deletions
@@ -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
@@ -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)
@@ -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)!!
@@ -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>
@@ -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
@@ -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)
}
}
@@ -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)
}
}
@@ -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")
@@ -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(