[codegen][debug info][dwarf] (var) variable inspection in debugger support

- debug location metainformation attached to stack allcated slots.
- python bindings to work such variables.
This commit is contained in:
Vasily Levchenko
2017-08-03 13:19:31 +03:00
committed by Vasily Levchenko
parent 4931b2f05b
commit db1a1b029a
9 changed files with 324 additions and 90 deletions
@@ -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<Int,VariableDebugLocation>()
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)
}
@@ -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<T> 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
@@ -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),
@@ -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: Map<IrE
override fun genThrow(exception: LLVMValueRef) = unsupported()
override fun genDeclareVariable(descriptor: VariableDescriptor, value: LLVMValueRef?) = unsupported(descriptor)
override fun genDeclareVariable(descriptor: VariableDescriptor, value: LLVMValueRef?, variableLocation: VariableDebugLocation?) = unsupported(descriptor)
override fun getDeclaredVariable(descriptor: VariableDescriptor) = -1
@@ -492,8 +492,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
*/
private inner class VariableScope : InnerScopeImpl() {
override fun genDeclareVariable(descriptor: VariableDescriptor, value: LLVMValueRef?): Int {
return functionGenerationContext.vars.createVariable(descriptor, value)
override fun genDeclareVariable(descriptor: VariableDescriptor, value: LLVMValueRef?, variableLocation: VariableDebugLocation?): Int {
return functionGenerationContext.vars.createVariable(descriptor, value, variableLocation)
}
override fun getDeclaredVariable(descriptor: VariableDescriptor): Int {
@@ -964,7 +964,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
for (catch in catches) {
fun genCatchBlock() {
using(VariableScope()) {
currentCodeContext.genDeclareVariable(catch.parameter, exception)
currentCodeContext.genDeclareVariable(catch.parameter, exception, null)
evaluateExpressionAndJump(catch.result, success)
}
}
@@ -1128,22 +1128,20 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
context.log{"generateVariable : ${ir2string(value)}"}
val result = value.initializer?.let { evaluateExpression(it) }
val variableDescriptor = value.descriptor
val index = currentCodeContext.genDeclareVariable(variableDescriptor, result)
if (context.shouldContainDebugInfo()) {
val functionScope = (currentCodeContext.functionScope() as FunctionScope).declaration?.scope()
val variableLocation = if (context.shouldContainDebugInfo() && functionScope != null && variableDescriptor.isVar) {
val location = debugLocation(value)
val functionScope = (currentCodeContext.functionScope() as FunctionScope).declaration?.scope() ?: return
val file = (currentCodeContext.fileScope() as FileScope).file.file()
val variable = functionGenerationContext.vars.load(index)
val line = value.startLine()
functionGenerationContext.vars.debugInfoLocalVariableLocation(
functionScope = functionScope,
diType = variableDescriptor.type.diType(context, functionGenerationContext.llvmTargetData),
name = variableDescriptor.name,
variable = variable,
file = file,
line = line,
location = location)
}
} else null
currentCodeContext.genDeclareVariable(variableDescriptor, result, variableLocation)
}
//-------------------------------------------------------------------------//
@@ -51,7 +51,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
contextVariablesToIndex.clear()
}
fun createVariable(descriptor: VariableDescriptor, value: LLVMValueRef? = null) : Int {
fun createVariable(descriptor: VariableDescriptor, value: LLVMValueRef? = null, variableLocation: VariableDebugLocation?) : Int {
// Note that we always create slot for object references for memory management.
if (!descriptor.isVar && value != null)
return createImmutable(descriptor, value)
@@ -60,15 +60,15 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
// as even vals can be assigned on multiple paths. However, we use varness
// knowledge, as anonymous slots are created only for true vars (for vals
// their single assigner already have slot).
return createMutable(descriptor, descriptor.isVar, value)
return createMutable(descriptor, descriptor.isVar, value, variableLocation)
}
fun createMutable(descriptor: VariableDescriptor,
isVar: Boolean, value: LLVMValueRef? = null) : Int {
isVar: Boolean, value: LLVMValueRef? = null, variableLocation: VariableDebugLocation?) : Int {
assert(!contextVariablesToIndex.contains(descriptor))
val index = variables.size
val type = functionGenerationContext.getLLVMType(descriptor.type)
val slot = functionGenerationContext.alloca(type, descriptor.name.asString())
val slot = functionGenerationContext.alloca(type, descriptor.name.asString(), variableLocation)
if (value != null)
functionGenerationContext.storeAnyLocal(value, slot)
variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), isVar))
@@ -85,7 +85,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
private fun createAnonymousMutable(type: LLVMTypeRef, value: LLVMValueRef? = null) : Int {
val index = variables.size
val slot = functionGenerationContext.alloca(type)
val slot = functionGenerationContext.alloca(type, variableLocation = null)
if (value != null)
functionGenerationContext.storeAnyLocal(value, slot)
variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), true))
@@ -117,7 +117,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
variables[index].store(value)
}
fun debugInfoLocalVariableLocation(functionScope: DIScopeOpaqueRef, diType: DITypeOpaqueRef, name:Name, variable: LLVMValueRef, file: DIFileRef, line: Int, location: DILocationRef?) {
fun debugInfoLocalVariableLocation(functionScope: DIScopeOpaqueRef, diType: DITypeOpaqueRef, name:Name, file: DIFileRef, line: Int, location: DILocationRef?):VariableDebugLocation {
val variableDeclaration = DICreateAutoVariable(
builder = functionGenerationContext.context.debugInfo.builder,
scope = functionScope,
@@ -125,11 +125,9 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
file = file,
line = line,
type = diType)
DIInsertDeclarationWithEmptyExpression(
builder = functionGenerationContext.context.debugInfo.builder,
value = variable,
localVariable = variableDeclaration,
location = location,
bb = LLVMGetInsertBlock(functionGenerationContext.builder))
return VariableDebugLocation(localVariable = variableDeclaration!!, location = location, file = file, line = line)
}
}
internal data class VariableDebugLocation(val localVariable: DILocalVariableRef, val location:DILocationRef?, val file:DIFileRef, val line:Int)
@@ -33,6 +33,12 @@ internal enum class DwarfTypeKind(val value:Byte) {
#undef HANDLE_DW_ATE
}
internal enum class DwarfOp(val value:Long) {
#define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME(ID),
#include "llvm/Support/Dwarf.def"
#undef HANDLE_DW_OP
}
internal enum class DwarfLanguage(val value:Int) {
#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME(ID),
#include "llvm/Support/Dwarf.def"
+11 -2
View File
@@ -178,6 +178,12 @@ DIDerivedTypeRef DICreateReferenceType(DIBuilderRef refBuilder, DITypeOpaqueRef
llvm::unwrap(refType)));
}
DIDerivedTypeRef DICreatePointerType(DIBuilderRef refBuilder, DITypeOpaqueRef refType) {
return llvm::wrap(llvm::unwrap(refBuilder)->createReferenceType(
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<int64_t> 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));
}
+2 -1
View File
@@ -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);
+35
View File
@@ -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')