diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index 18709e97ce5..51638abfc7b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -20,7 +20,8 @@ import org.jetbrains.kotlin.backend.konan.ir.* internal class CodeGenerator(override val context: Context) : ContextUtils { - fun llvmFunction(function: IrFunction): LLVMValueRef = function.llvmFunction + fun llvmFunction(function: IrFunction): LLVMValueRef = llvmFunctionOrNull(function) ?: error("no function ${function.name} in ${function.file}") + fun llvmFunctionOrNull(function: IrFunction): LLVMValueRef? = function.llvmFunctionOrNull val intPtrType = LLVMIntPtrType(llvmTargetData)!! internal val immOneIntPtrType = LLVMConstInt(intPtrType, 1, 1)!! // Keep in sync with OBJECT_TAG_MASK in C++. @@ -83,9 +84,11 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { return typeInfoValue(constructedClass) } - fun generateLocationInfo(locationInfo: LocationInfo): DILocationRef? { - return LLVMCreateLocation(LLVMGetModuleContext(context.llvmModule), locationInfo.line, locationInfo.column, locationInfo.scope) - } + fun generateLocationInfo(locationInfo: LocationInfo): DILocationRef? = if (locationInfo.inlinedAt != null) + LLVMCreateLocationInlinedAt(LLVMGetModuleContext(context.llvmModule), locationInfo.line, locationInfo.column, + locationInfo.scope, generateLocationInfo(locationInfo.inlinedAt)) + else + LLVMCreateLocation(LLVMGetModuleContext(context.llvmModule), locationInfo.line, locationInfo.column, locationInfo.scope) val objCDataGenerator = when (context.config.target.family) { Family.IOS, Family.OSX -> ObjCDataGenerator(this) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index 0dc5dd235cd..928886e5a42 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -15,6 +15,8 @@ import org.jetbrains.kotlin.descriptors.konan.CompiledKonanModuleOrigin import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.util.file +import org.jetbrains.kotlin.ir.util.fqNameSafe import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.konan.library.resolver.TopologicalLibraryOrder @@ -155,6 +157,9 @@ internal interface ContextUtils : RuntimeAware { * It may be declared as external function prototype. */ val IrFunction.llvmFunction: LLVMValueRef + get() = llvmFunctionOrNull ?: error("$name in $file/${parent.fqNameSafe}") + + val IrFunction.llvmFunctionOrNull: LLVMValueRef? get() { assert(this.isReal) @@ -162,7 +167,7 @@ internal interface ContextUtils : RuntimeAware { context.llvm.externalFunction(this.symbolName, getLlvmFunctionType(this), origin = this.llvmSymbolOrigin) } else { - context.llvmDeclarations.forFunction(this).llvmFunction + context.llvmDeclarations.forFunctionOrNull(this)?.llvmFunction } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt index 159a8627a58..cf212ba0ca3 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt @@ -64,6 +64,8 @@ fun KonanConfig.debugInfoVersion():Int = configuration[KonanConfigKeys.DEBUG_INF internal class DebugInfo internal constructor(override val context: Context):ContextUtils { val files = mutableMapOf() val subprograms = mutableMapOf() + /* Some functions are inlined on all callsites and body is eliminated by DCE, so there's no LLVM value */ + val inlinedSubprograms = mutableMapOf() var builder: DIBuilderRef? = null var module: DIModuleRef? = null var types = mutableMapOf() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index d7bd2f61104..19672859c5f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -1615,6 +1615,15 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map", startLine, subroutineType) + } + } as DIScopeOpaqueRef + } + } @Suppress("UNCHECKED_CAST") private fun LLVMValueRef.scope(startLine:Int, subroutineType: DISubroutineTypeRef): DIScopeOpaqueRef? { return context.debugInfo.subprograms.getOrPut(this) { - diFunctionScope(name!!, name!!, startLine, subroutineType, this) + diFunctionScope(name!!, name!!, startLine, subroutineType).also { + DIFunctionAddSubprogram(this@scope, it) + } } as DIScopeOpaqueRef } - private fun diFunctionScope(name: String, linkageName: String, startLine: Int, subroutineType: DISubroutineTypeRef, functionLlvmValue: LLVMValueRef): DISubprogramRef { - @Suppress("UNCHECKED_CAST") - val diFunction = DICreateFunction( + + @Suppress("UNCHECKED_CAST") + private fun diFunctionScope(name: String, linkageName: String, startLine: Int, subroutineType: DISubroutineTypeRef) = DICreateFunction( builder = context.debugInfo.builder, scope = (currentCodeContext.fileScope() as FileScope).file.file() as DIScopeOpaqueRef, name = name, @@ -1857,10 +1881,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map, private val staticFields: Map, private val unique: Map) { - fun forFunction(function: IrFunction) = functions[function] ?: - error("${function.descriptor} in ${function.parent.fqNameSafe}") + fun forFunction(function: IrFunction) = forFunctionOrNull(function) ?: with(function){error("$name in $file/${parent.fqNameSafe}")} + fun forFunctionOrNull(function: IrFunction) = functions[function] fun forClass(irClass: IrClass) = classes[irClass] ?: error(irClass.descriptor.toString()) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageInstrumentation.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageInstrumentation.kt index be7b6c80fcf..5241b6075ea 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageInstrumentation.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageInstrumentation.kt @@ -45,7 +45,7 @@ internal class LLVMCoverageInstrumentation( // Each profiled function should have a global with its name in a specific format. private fun createFunctionNameGlobal(function: IrFunction): LLVMValueRef { - val name = context.llvmDeclarations.forFunction(function).llvmFunction.name + val name = function.llvmFunction.name val pgoFunctionName = LLVMCreatePGOFunctionNameVar(function.llvmFunction, name)!! return LLVMConstBitCast(pgoFunctionName, int8TypePtr)!! }