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