From db1a1b029aaa1c3898b361b7ffe02fa91237a2b8 Mon Sep 17 00:00:00 2001 From: Vasily Levchenko Date: Thu, 3 Aug 2017 13:19:31 +0300 Subject: [PATCH] [codegen][debug info][dwarf] (var) variable inspection in debugger support - debug location metainformation attached to stack allcated slots. - python bindings to work such variables. --- .../backend/konan/llvm/CodeGenerator.kt | 45 ++++- .../kotlin/backend/konan/llvm/DebugUtils.kt | 106 ++++++----- .../kotlin/backend/konan/llvm/Dwarf.kt | 164 +++++++++++++++++- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 20 +-- .../backend/konan/llvm/VariableManager.kt | 22 ++- .../src/dwarf/include/dwarf_util.kt.pp | 6 + llvmDebugInfoC/src/main/cpp/DebugInfoC.cpp | 13 +- llvmDebugInfoC/src/main/include/DebugInfoC.h | 3 +- llvmDebugInfoC/src/scripts/konan_lldb.py | 35 ++++ 9 files changed, 324 insertions(+), 90 deletions(-) create mode 100644 llvmDebugInfoC/src/scripts/konan_lldb.py 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 38f3dc1e70e..60587c9cd9a 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 @@ -24,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.types.KotlinType internal class CodeGenerator(override val context: Context) : ContextUtils { @@ -110,9 +109,10 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, get() = (functionDescriptor as? ClassConstructorDescriptor)?.constructedClass private var returnSlot: LLVMValueRef? = null private var slotsPhi: LLVMValueRef? = null - private var slotCount = 0 + private var slotCount = 1 private var localAllocs = 0 private var arenaSlot: LLVMValueRef? = null + private val slotToVariableLocation = mutableMapOf() private val prologueBb = basicBlockInFunction("prologue", startLocation) private val localsInitBb = basicBlockInFunction("locals_init", startLocation) @@ -142,15 +142,31 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, return result } - fun alloca(type: LLVMTypeRef?, name: String = ""): LLVMValueRef { + fun alloca(type: LLVMTypeRef?, name: String = "", variableLocation: VariableDebugLocation? = null): LLVMValueRef { if (isObjectType(type!!)) { appendingTo(localsInitBb) { - return gep(slotsPhi!!, Int32(slotCount++).llvm, name) + val slotAddress = gep(slotsPhi!!, Int32(slotCount).llvm, name) + variableLocation?.let { + slotToVariableLocation[slotCount] = it + } + slotCount++ + return slotAddress } } appendingTo(prologueBb) { - return LLVMBuildAlloca(builder, type, name)!! + val slotAddress = LLVMBuildAlloca(builder, type, name)!! + variableLocation?.let { + DIInsertDeclaration( + builder = codegen.context.debugInfo.builder, + value = slotAddress, + localVariable = it.localVariable, + location = it.location, + bb = prologueBb, + expr = null, + exprCount = 0) + } + return slotAddress } } @@ -179,7 +195,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, fun loadSlot(address: LLVMValueRef, isVar: Boolean, name: String = ""): LLVMValueRef { val value = LLVMBuildLoad(builder, address, name)!! if (isObjectRef(value) && isVar) { - val slot = alloca(LLVMTypeOf(value)) + val slot = alloca(LLVMTypeOf(value), variableLocation = null) storeAnyLocal(value, slot) } return value @@ -465,9 +481,6 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, } positionAtEnd(localsInitBb) slotsPhi = phi(kObjHeaderPtrPtr) - // First slot can be assigned to keep pointer to frame local arena. - slotCount = 1 - localAllocs = 0 // Is removed by DCE trivially, if not needed. arenaSlot = intToPtr( or(ptrToInt(slotsPhi, codegen.intPtrType), codegen.immOneIntPtrType), kObjHeaderPtrPtr) @@ -491,6 +504,20 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, Int1(0).llvm)) } addPhiIncoming(slotsPhi!!, prologueBb to slots) + val slotOffset = pointerSize * slotCount + memScoped { + slotToVariableLocation.forEach { slot, variable -> + val expr = longArrayOf(DwarfOp.DW_OP_minus.value, slotOffset + pointerSize * slot.toLong()).toCValues() + DIInsertDeclaration( + builder = codegen.context.debugInfo.builder, + value = slotsPhi, + localVariable = variable.localVariable, + location = variable.location, + bb = prologueBb, + expr = expr, + exprCount = 2) + } + } br(localsInitBb) } 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 cb73a5c45f8..0d1a32ca338 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 @@ -20,15 +20,14 @@ import kotlinx.cinterop.allocArrayOf import kotlinx.cinterop.memScoped import llvm.* import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.KonanConfigKeys import org.jetbrains.kotlin.backend.konan.KonanVersion import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.SourceManager.FileEntry import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils @@ -104,23 +103,23 @@ internal fun generateDebugInfoHeader(context: Context) { val path = context.config.outputFile .toFileAndFolder() - - context.debugInfo.module = DICreateModule( - builder = context.debugInfo.builder, - scope = context.llvmModule as DIScopeOpaqueRef, - name = path.path(), + @Suppress("UNCHECKED_CAST") + context.debugInfo.module = DICreateModule( + builder = context.debugInfo.builder, + scope = context.llvmModule as DIScopeOpaqueRef, + name = path.path(), configurationMacro = "", - includePath = "", - iSysRoot = "") + includePath = "", + iSysRoot = "") context.debugInfo.compilationModule = DICreateCompilationUnit( - builder = context.debugInfo.builder, - lang = DwarfLanguage.DW_LANG_Kotlin.value, - File = path.file, - dir = path.folder, - producer = DWARF.producer, + builder = context.debugInfo.builder, + lang = DwarfLanguage.DW_LANG_Kotlin.value, + File = path.file, + dir = path.folder, + producer = DWARF.producer, isOptimized = 0, - flags = "", - rv = DWARF.runtimeVersion) + flags = "", + rv = DWARF.runtimeVersion) /* TODO: figure out what here 2 means: * * 0:b-backend-dwarf:minamoto@minamoto-osx(0)# cat /dev/null | clang -xc -S -emit-llvm -g -o - - @@ -152,39 +151,35 @@ internal fun generateDebugInfoHeader(context: Context) { @Suppress("UNCHECKED_CAST") internal fun KotlinType.dwarfType(context:Context, targetData:LLVMTargetDataRef): DITypeOpaqueRef { - return when { - KotlinBuiltIns.isPrimitiveType(this) -> debugInfoBaseType(context, targetData, this.getJetTypeFqName(false), llvmType(context), encoding(context).value.toInt()) + when { + KotlinBuiltIns.isPrimitiveType(this) -> return debugInfoBaseType(context, targetData, this.getJetTypeFqName(false), llvmType(context), encoding(context).value.toInt()) KotlinBuiltIns.isArray(this) -> { val arrayElementType = context.builtIns.getArrayElementType(this) - DICreateArrayType(context.debugInfo.builder, arrayElementType.size(context), arrayElementType.alignment(context), + return DICreateArrayType(context.debugInfo.builder, arrayElementType.size(context), arrayElementType.alignment(context), arrayElementType.diType(context, targetData), 1) as DITypeOpaqueRef } else -> { val classDescriptor = TypeUtils.getClassDescriptor(this) - if (classDescriptor != null) { - /** - * Ideally we'd use [KotlinType.typeInfoSymbolName] here , by type could be not - * exportable. - */ - DICreateStructType( - refBuilder = context.debugInfo.builder, - scope = context.debugInfo.compilationModule as DIScopeOpaqueRef, - name = "ktype:${classDescriptor.fqNameSafe}", - file = null, - lineNumber = 0, - sizeInBits = 0, - alignInBits = 0, - flags = DWARF.flagsForwardDeclaration, - derivedFrom = null, - elements = null, - elementsCount = 0, - refPlace = null)!! as DITypeOpaqueRef - } - else if (TypeUtils.isTypeParameter(this)){ - //TODO: Type parameter, how to deal with if? - debugInfoBaseType(context, targetData, this.toString(), llvmType(context), encoding(context).value.toInt()) - } else { - TODO("$this: Does this case really exist?") + return when { + classDescriptor != null -> { + val type = DICreateStructType( + refBuilder = context.debugInfo.builder, + scope = context.debugInfo.compilationModule as DIScopeOpaqueRef, + name = "ObjHeader", + file = null, + lineNumber = 0, + sizeInBits = 0, + alignInBits = 0, + flags = DWARF.flagsForwardDeclaration, + derivedFrom = null, + elements = null, + elementsCount = 0, + refPlace = null)!! as DITypeOpaqueRef + dwarfPointerType(context, type) + } + TypeUtils.isTypeParameter(this) -> //TODO: Type parameter, how to deal with if? + debugInfoBaseType(context, targetData, this.toString(), llvmType(context), encoding(context).value.toInt()) + else -> TODO("$this: Does this case really exist?") } } } @@ -215,17 +210,16 @@ internal fun KotlinType.alignment(context:Context) = context.debugInfo.llvmTypeA internal fun KotlinType.llvmType(context:Context): LLVMTypeRef = context.debugInfo.llvmTypes.getOrDefault(this, context.debugInfo.otherLlvmType) private fun or(v:T, vararg p:(T)->Boolean):Boolean = p.any{it(v)} -internal fun KotlinType.encoding(context:Context):DwarfTypeKind { - return when { - this in context.debugInfo.intTypes -> DwarfTypeKind.DW_ATE_signed - this in context.debugInfo.realTypes -> DwarfTypeKind.DW_ATE_float - KotlinBuiltIns.isBoolean(this) -> DwarfTypeKind.DW_ATE_boolean - KotlinBuiltIns.isChar(this) -> DwarfTypeKind.DW_ATE_unsigned - (!KotlinBuiltIns.isPrimitiveType(this)) -> DwarfTypeKind.DW_ATE_address - else -> TODO(toString()) - } - } +internal fun KotlinType.encoding(context:Context):DwarfTypeKind = when { + this in context.debugInfo.intTypes -> DwarfTypeKind.DW_ATE_signed + this in context.debugInfo.realTypes -> DwarfTypeKind.DW_ATE_float + KotlinBuiltIns.isBoolean(this) -> DwarfTypeKind.DW_ATE_boolean + KotlinBuiltIns.isChar(this) -> DwarfTypeKind.DW_ATE_unsigned + (!KotlinBuiltIns.isPrimitiveType(this)) -> DwarfTypeKind.DW_ATE_address + else -> TODO(toString()) +} + internal fun alignTo(value:Long, align:Long):Long = (value + align - 1) / align * align internal fun FunctionDescriptor.subroutineType(context: Context, llvmTargetData: LLVMTargetDataRef): DISubroutineTypeRef { @@ -242,5 +236,9 @@ private fun KotlinType.referenceOrValue(context: Context, llvmTargetData: LLVMTa return if (KotlinBuiltIns.isPrimitiveType(this)) refType else - DICreateReferenceType(context.debugInfo.builder, refType) as DITypeOpaqueRef + dwarfPointerType(context, refType) } + +@Suppress("UNCHECKED_CAST") +private fun dwarfPointerType(context: Context, type: DITypeOpaqueRef) = + DICreatePointerType(context.debugInfo.builder, type) as DITypeOpaqueRef diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Dwarf.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Dwarf.kt index d39640e4a59..2d0ce18d16f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Dwarf.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Dwarf.kt @@ -97,7 +97,8 @@ internal enum class DwarfTag(val value:Int) { DW_TAG_BORLAND_Delphi_set(0xb003), DW_TAG_BORLAND_Delphi_variant(0xb004), } - internal enum class DwarfTypeKind(val value:Byte) { + +internal enum class DwarfTypeKind(val value:Byte) { DW_ATE_address(0x01), DW_ATE_boolean(0x02), DW_ATE_complex_float(0x03), @@ -115,6 +116,167 @@ internal enum class DwarfTag(val value:Int) { DW_ATE_decimal_float(0x0f), DW_ATE_UTF(0x10), } + +internal enum class DwarfOp(val value:Long) { + DW_OP_addr(0x03), + DW_OP_deref(0x06), + DW_OP_const1u(0x08), + DW_OP_const1s(0x09), + DW_OP_const2u(0x0a), + DW_OP_const2s(0x0b), + DW_OP_const4u(0x0c), + DW_OP_const4s(0x0d), + DW_OP_const8u(0x0e), + DW_OP_const8s(0x0f), + DW_OP_constu(0x10), + DW_OP_consts(0x11), + DW_OP_dup(0x12), + DW_OP_drop(0x13), + DW_OP_over(0x14), + DW_OP_pick(0x15), + DW_OP_swap(0x16), + DW_OP_rot(0x17), + DW_OP_xderef(0x18), + DW_OP_abs(0x19), + DW_OP_and(0x1a), + DW_OP_div(0x1b), + DW_OP_minus(0x1c), + DW_OP_mod(0x1d), + DW_OP_mul(0x1e), + DW_OP_neg(0x1f), + DW_OP_not(0x20), + DW_OP_or(0x21), + DW_OP_plus(0x22), + DW_OP_plus_uconst(0x23), + DW_OP_shl(0x24), + DW_OP_shr(0x25), + DW_OP_shra(0x26), + DW_OP_xor(0x27), + DW_OP_skip(0x2f), + DW_OP_bra(0x28), + DW_OP_eq(0x29), + DW_OP_ge(0x2a), + DW_OP_gt(0x2b), + DW_OP_le(0x2c), + DW_OP_lt(0x2d), + DW_OP_ne(0x2e), + DW_OP_lit0(0x30), + DW_OP_lit1(0x31), + DW_OP_lit2(0x32), + DW_OP_lit3(0x33), + DW_OP_lit4(0x34), + DW_OP_lit5(0x35), + DW_OP_lit6(0x36), + DW_OP_lit7(0x37), + DW_OP_lit8(0x38), + DW_OP_lit9(0x39), + DW_OP_lit10(0x3a), + DW_OP_lit11(0x3b), + DW_OP_lit12(0x3c), + DW_OP_lit13(0x3d), + DW_OP_lit14(0x3e), + DW_OP_lit15(0x3f), + DW_OP_lit16(0x40), + DW_OP_lit17(0x41), + DW_OP_lit18(0x42), + DW_OP_lit19(0x43), + DW_OP_lit20(0x44), + DW_OP_lit21(0x45), + DW_OP_lit22(0x46), + DW_OP_lit23(0x47), + DW_OP_lit24(0x48), + DW_OP_lit25(0x49), + DW_OP_lit26(0x4a), + DW_OP_lit27(0x4b), + DW_OP_lit28(0x4c), + DW_OP_lit29(0x4d), + DW_OP_lit30(0x4e), + DW_OP_lit31(0x4f), + DW_OP_reg0(0x50), + DW_OP_reg1(0x51), + DW_OP_reg2(0x52), + DW_OP_reg3(0x53), + DW_OP_reg4(0x54), + DW_OP_reg5(0x55), + DW_OP_reg6(0x56), + DW_OP_reg7(0x57), + DW_OP_reg8(0x58), + DW_OP_reg9(0x59), + DW_OP_reg10(0x5a), + DW_OP_reg11(0x5b), + DW_OP_reg12(0x5c), + DW_OP_reg13(0x5d), + DW_OP_reg14(0x5e), + DW_OP_reg15(0x5f), + DW_OP_reg16(0x60), + DW_OP_reg17(0x61), + DW_OP_reg18(0x62), + DW_OP_reg19(0x63), + DW_OP_reg20(0x64), + DW_OP_reg21(0x65), + DW_OP_reg22(0x66), + DW_OP_reg23(0x67), + DW_OP_reg24(0x68), + DW_OP_reg25(0x69), + DW_OP_reg26(0x6a), + DW_OP_reg27(0x6b), + DW_OP_reg28(0x6c), + DW_OP_reg29(0x6d), + DW_OP_reg30(0x6e), + DW_OP_reg31(0x6f), + DW_OP_breg0(0x70), + DW_OP_breg1(0x71), + DW_OP_breg2(0x72), + DW_OP_breg3(0x73), + DW_OP_breg4(0x74), + DW_OP_breg5(0x75), + DW_OP_breg6(0x76), + DW_OP_breg7(0x77), + DW_OP_breg8(0x78), + DW_OP_breg9(0x79), + DW_OP_breg10(0x7a), + DW_OP_breg11(0x7b), + DW_OP_breg12(0x7c), + DW_OP_breg13(0x7d), + DW_OP_breg14(0x7e), + DW_OP_breg15(0x7f), + DW_OP_breg16(0x80), + DW_OP_breg17(0x81), + DW_OP_breg18(0x82), + DW_OP_breg19(0x83), + DW_OP_breg20(0x84), + DW_OP_breg21(0x85), + DW_OP_breg22(0x86), + DW_OP_breg23(0x87), + DW_OP_breg24(0x88), + DW_OP_breg25(0x89), + DW_OP_breg26(0x8a), + DW_OP_breg27(0x8b), + DW_OP_breg28(0x8c), + DW_OP_breg29(0x8d), + DW_OP_breg30(0x8e), + DW_OP_breg31(0x8f), + DW_OP_regx(0x90), + DW_OP_fbreg(0x91), + DW_OP_bregx(0x92), + DW_OP_piece(0x93), + DW_OP_deref_size(0x94), + DW_OP_xderef_size(0x95), + DW_OP_nop(0x96), + DW_OP_push_object_address(0x97), + DW_OP_call2(0x98), + DW_OP_call4(0x99), + DW_OP_call_ref(0x9a), + DW_OP_form_tls_address(0x9b), + DW_OP_call_frame_cfa(0x9c), + DW_OP_bit_piece(0x9d), + DW_OP_implicit_value(0x9e), + DW_OP_stack_value(0x9f), + DW_OP_GNU_push_tls_address(0xe0), + DW_OP_GNU_addr_index(0xfb), + DW_OP_GNU_const_index(0xfc), +} + internal enum class DwarfLanguage(val value:Int) { DW_LANG_C89(0x0001), DW_LANG_C(0x0002), 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 2a6bee18223..ead9debdbf3 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 @@ -208,7 +208,7 @@ internal interface CodeContext { * Declares the variable. * @return index of declared variable. */ - fun genDeclareVariable(descriptor: VariableDescriptor, value: LLVMValueRef?): Int + fun genDeclareVariable(descriptor: VariableDescriptor, value: LLVMValueRef?, variableLocation: VariableDebugLocation?): Int /** * @return index of variable declared before, or -1 if no such variable has been declared yet. @@ -276,7 +276,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: MapcreateReferenceType( + llvm::dwarf::DW_TAG_pointer_type, + llvm::unwrap(refType))); +} + DISubroutineTypeRef DICreateSubroutineType(DIBuilderRef builder, DITypeOpaqueRef* types, unsigned typesCount) { @@ -212,11 +218,14 @@ DIExpressionRef DICreateEmptyExpression(DIBuilderRef builder) { return llvm::wrap(llvm::unwrap(builder)->createExpression()); } -void DIInsertDeclarationWithEmptyExpression(DIBuilderRef builder, LLVMValueRef value, DILocalVariableRef localVariable, DILocationRef location, LLVMBasicBlockRef bb) { +void DIInsertDeclaration(DIBuilderRef builder, LLVMValueRef value, DILocalVariableRef localVariable, DILocationRef location, LLVMBasicBlockRef bb, int64_t *expr, uint64_t exprCount) { auto di_builder = llvm::unwrap(builder); + std::vector expression; + for (uint64_t i = 0; i < exprCount; ++i) + expression.push_back(expr[i]); di_builder->insertDeclare(llvm::unwrap(value), llvm::unwrap(localVariable), - di_builder->createExpression(), + di_builder->createExpression(expression), llvm::unwrap(location), llvm::unwrap(bb)); } diff --git a/llvmDebugInfoC/src/main/include/DebugInfoC.h b/llvmDebugInfoC/src/main/include/DebugInfoC.h index c5e6f850335..69cbde2415d 100644 --- a/llvmDebugInfoC/src/main/include/DebugInfoC.h +++ b/llvmDebugInfoC/src/main/include/DebugInfoC.h @@ -59,6 +59,7 @@ DICompositeTypeRef DICreateArrayType(DIBuilderRef refBuilder, uint64_t elementsCount); DIDerivedTypeRef DICreateReferenceType(DIBuilderRef refBuilder, DITypeOpaqueRef refType); +DIDerivedTypeRef DICreatePointerType(DIBuilderRef refBuilder, DITypeOpaqueRef refType); DICompositeTypeRef DICreateReplaceableCompositeType(DIBuilderRef refBuilder, int tag, const char *name, @@ -92,7 +93,7 @@ DISubroutineTypeRef DICreateSubroutineType(DIBuilderRef builder, unsigned typesCount); DILocalVariableRef DICreateAutoVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, DIFileRef file, unsigned line, DITypeOpaqueRef type); -void DIInsertDeclarationWithEmptyExpression(DIBuilderRef builder, LLVMValueRef value, DILocalVariableRef localVariable, DILocationRef location, LLVMBasicBlockRef bb); +void DIInsertDeclaration(DIBuilderRef builder, LLVMValueRef value, DILocalVariableRef localVariable, DILocationRef location, LLVMBasicBlockRef bb, int64_t *expr, uint64_t exprCount); DIExpressionRef DICreateEmptyExpression(DIBuilderRef builder); void DIFunctionAddSubprogram(LLVMValueRef fn, DISubprogramRef sp); DILocationRef LLVMBuilderSetDebugLocation(LLVMBuilderRef builder, unsigned line, unsigned col, DIScopeOpaqueRef scope); diff --git a/llvmDebugInfoC/src/scripts/konan_lldb.py b/llvmDebugInfoC/src/scripts/konan_lldb.py new file mode 100644 index 00000000000..0d2c8c1a4fd --- /dev/null +++ b/llvmDebugInfoC/src/scripts/konan_lldb.py @@ -0,0 +1,35 @@ +#!/usr/bin/python + +## +# Copyright 2010-2017 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# (lldb) command script import llvmDebugInfoC/src/scripts/konan_lldb.py +# (lldb) show_variable +# + +import lldb +import commands +import optparse +import shlex + +def show_variable(debugger, command, result, internal_dict): + debugger.GetCommandInterpreter().HandleCommand('expr -- Konan_DebugPrint(%s)' % command, result) + return result + +def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand('command script add -f konan_lldb.show_variable show_variable') +