Add debug info to some ObjCExport bridges (#3237)
to fix inlined frames decoding.
This commit is contained in:
committed by
GitHub
parent
746dcfdb7a
commit
65e6f85dc1
+5
@@ -155,6 +155,11 @@ private inline fun <R> generateFunctionBody(
|
|||||||
functionGenerationContext.resetDebugLocation()
|
functionGenerationContext.resetDebugLocation()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun FunctionGenerationContext.initBridgeDebugInfo() {
|
||||||
|
val location = setupBridgeDebugInfo(context, function) ?: return
|
||||||
|
debugLocation(location, location)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There're cases when we don't need end position or it is meaningless.
|
* There're cases when we don't need end position or it is meaningless.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+31
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
|
|
||||||
import kotlinx.cinterop.allocArrayOf
|
import kotlinx.cinterop.allocArrayOf
|
||||||
import kotlinx.cinterop.memScoped
|
import kotlinx.cinterop.memScoped
|
||||||
|
import kotlinx.cinterop.reinterpret
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import org.jetbrains.kotlin.ir.SourceManager.FileEntry
|
import org.jetbrains.kotlin.ir.SourceManager.FileEntry
|
||||||
@@ -81,6 +82,10 @@ internal class DebugInfo internal constructor(override val context: Context):Con
|
|||||||
val otherLlvmType = LLVMPointerType(LLVMInt64Type(), 0)!!
|
val otherLlvmType = LLVMPointerType(LLVMInt64Type(), 0)!!
|
||||||
val otherTypeSize = LLVMSizeOfTypeInBits(llvmTargetData, otherLlvmType)
|
val otherTypeSize = LLVMSizeOfTypeInBits(llvmTargetData, otherLlvmType)
|
||||||
val otherTypeAlignment = LLVMPreferredAlignmentOfType(llvmTargetData, otherLlvmType)
|
val otherTypeAlignment = LLVMPreferredAlignmentOfType(llvmTargetData, otherLlvmType)
|
||||||
|
|
||||||
|
val compilerGeneratedFile by lazy {
|
||||||
|
DICreateFile(builder, "<compiler-generated>", "")!!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -250,3 +255,29 @@ internal fun subroutineType(context: Context, llvmTargetData: LLVMTargetDataRef,
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private fun dwarfPointerType(context: Context, type: DITypeOpaqueRef) =
|
private fun dwarfPointerType(context: Context, type: DITypeOpaqueRef) =
|
||||||
DICreatePointerType(context.debugInfo.builder, type) as DITypeOpaqueRef
|
DICreatePointerType(context.debugInfo.builder, type) as DITypeOpaqueRef
|
||||||
|
|
||||||
|
internal fun setupBridgeDebugInfo(context: Context, function: LLVMValueRef): LocationInfo? {
|
||||||
|
if (!context.shouldContainLocationDebugInfo()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val file = context.debugInfo.compilerGeneratedFile
|
||||||
|
|
||||||
|
// TODO: can we share the scope among all bridges?
|
||||||
|
val scope: DIScopeOpaqueRef = DICreateFunction(
|
||||||
|
builder = context.debugInfo.builder,
|
||||||
|
scope = file.reinterpret(),
|
||||||
|
name = function.name,
|
||||||
|
linkageName = function.name,
|
||||||
|
file = file,
|
||||||
|
lineNo = 0,
|
||||||
|
type = subroutineType(context, context.llvm.runtime.targetData, emptyList()), // TODO: use proper type.
|
||||||
|
isLocal = 0,
|
||||||
|
isDefinition = 1,
|
||||||
|
scopeLine = 0
|
||||||
|
)!!.also {
|
||||||
|
DIFunctionAddSubprogram(function, it)
|
||||||
|
}.reinterpret()
|
||||||
|
|
||||||
|
return LocationInfo(scope, 1, 0)
|
||||||
|
}
|
||||||
|
|||||||
+10
-3
@@ -535,7 +535,7 @@ private inline fun ObjCExportCodeGenerator.generateObjCImpBy(
|
|||||||
genBody()
|
genBody()
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMSetLinkage(result, LLVMLinkage.LLVMPrivateLinkage)
|
LLVMSetLinkage(result, LLVMLinkage.LLVMInternalLinkage)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,7 +555,7 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
|||||||
) = if (target == null) {
|
) = if (target == null) {
|
||||||
generateAbstractObjCImp(methodBridge)
|
generateAbstractObjCImp(methodBridge)
|
||||||
} else {
|
} else {
|
||||||
generateObjCImp(methodBridge) { args, resultLifetime, exceptionHandler ->
|
generateObjCImp(methodBridge, isDirect = !isVirtual) { args, resultLifetime, exceptionHandler ->
|
||||||
val llvmTarget = if (!isVirtual) {
|
val llvmTarget = if (!isVirtual) {
|
||||||
codegen.llvmFunction(target)
|
codegen.llvmFunction(target)
|
||||||
} else {
|
} else {
|
||||||
@@ -568,12 +568,19 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
|||||||
|
|
||||||
private fun ObjCExportCodeGenerator.generateObjCImp(
|
private fun ObjCExportCodeGenerator.generateObjCImp(
|
||||||
methodBridge: MethodBridge,
|
methodBridge: MethodBridge,
|
||||||
|
isDirect: Boolean,
|
||||||
callKotlin: FunctionGenerationContext.(
|
callKotlin: FunctionGenerationContext.(
|
||||||
args: List<LLVMValueRef>,
|
args: List<LLVMValueRef>,
|
||||||
resultLifetime: Lifetime,
|
resultLifetime: Lifetime,
|
||||||
exceptionHandler: ExceptionHandler
|
exceptionHandler: ExceptionHandler
|
||||||
) -> LLVMValueRef?
|
) -> LLVMValueRef?
|
||||||
): LLVMValueRef = generateObjCImpBy(methodBridge) {
|
): LLVMValueRef = generateObjCImpBy(methodBridge) {
|
||||||
|
if (isDirect) {
|
||||||
|
// Consider this call inlinable. If it is inlined into a bridge with no debug information,
|
||||||
|
// lldb will not decode the inlined frame even if the callee has debug information.
|
||||||
|
initBridgeDebugInfo()
|
||||||
|
// TODO: consider adding debug info to other bridges.
|
||||||
|
}
|
||||||
|
|
||||||
val returnType = methodBridge.returnBridge
|
val returnType = methodBridge.returnBridge
|
||||||
|
|
||||||
@@ -674,7 +681,7 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
|||||||
private fun ObjCExportCodeGenerator.generateObjCImpForArrayConstructor(
|
private fun ObjCExportCodeGenerator.generateObjCImpForArrayConstructor(
|
||||||
target: IrConstructor,
|
target: IrConstructor,
|
||||||
methodBridge: MethodBridge
|
methodBridge: MethodBridge
|
||||||
): LLVMValueRef = generateObjCImp(methodBridge) { args, resultLifetime, exceptionHandler ->
|
): LLVMValueRef = generateObjCImp(methodBridge, isDirect = true) { args, resultLifetime, exceptionHandler ->
|
||||||
val arrayInstance = callFromBridge(
|
val arrayInstance = callFromBridge(
|
||||||
context.llvm.allocArrayFunction,
|
context.llvm.allocArrayFunction,
|
||||||
listOf(target.constructedClass.llvmTypeInfoPtr, args.first()),
|
listOf(target.constructedClass.llvmTypeInfoPtr, args.first()),
|
||||||
|
|||||||
Reference in New Issue
Block a user