[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:
committed by
Vasily Levchenko
parent
4931b2f05b
commit
db1a1b029a
+36
-9
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
|||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
|
|
||||||
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||||
|
|
||||||
@@ -110,9 +109,10 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
get() = (functionDescriptor as? ClassConstructorDescriptor)?.constructedClass
|
get() = (functionDescriptor as? ClassConstructorDescriptor)?.constructedClass
|
||||||
private var returnSlot: LLVMValueRef? = null
|
private var returnSlot: LLVMValueRef? = null
|
||||||
private var slotsPhi: LLVMValueRef? = null
|
private var slotsPhi: LLVMValueRef? = null
|
||||||
private var slotCount = 0
|
private var slotCount = 1
|
||||||
private var localAllocs = 0
|
private var localAllocs = 0
|
||||||
private var arenaSlot: LLVMValueRef? = null
|
private var arenaSlot: LLVMValueRef? = null
|
||||||
|
private val slotToVariableLocation = mutableMapOf<Int,VariableDebugLocation>()
|
||||||
|
|
||||||
private val prologueBb = basicBlockInFunction("prologue", startLocation)
|
private val prologueBb = basicBlockInFunction("prologue", startLocation)
|
||||||
private val localsInitBb = basicBlockInFunction("locals_init", startLocation)
|
private val localsInitBb = basicBlockInFunction("locals_init", startLocation)
|
||||||
@@ -142,15 +142,31 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun alloca(type: LLVMTypeRef?, name: String = ""): LLVMValueRef {
|
fun alloca(type: LLVMTypeRef?, name: String = "", variableLocation: VariableDebugLocation? = null): LLVMValueRef {
|
||||||
if (isObjectType(type!!)) {
|
if (isObjectType(type!!)) {
|
||||||
appendingTo(localsInitBb) {
|
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) {
|
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 {
|
fun loadSlot(address: LLVMValueRef, isVar: Boolean, name: String = ""): LLVMValueRef {
|
||||||
val value = LLVMBuildLoad(builder, address, name)!!
|
val value = LLVMBuildLoad(builder, address, name)!!
|
||||||
if (isObjectRef(value) && isVar) {
|
if (isObjectRef(value) && isVar) {
|
||||||
val slot = alloca(LLVMTypeOf(value))
|
val slot = alloca(LLVMTypeOf(value), variableLocation = null)
|
||||||
storeAnyLocal(value, slot)
|
storeAnyLocal(value, slot)
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
@@ -465,9 +481,6 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
}
|
}
|
||||||
positionAtEnd(localsInitBb)
|
positionAtEnd(localsInitBb)
|
||||||
slotsPhi = phi(kObjHeaderPtrPtr)
|
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.
|
// Is removed by DCE trivially, if not needed.
|
||||||
arenaSlot = intToPtr(
|
arenaSlot = intToPtr(
|
||||||
or(ptrToInt(slotsPhi, codegen.intPtrType), codegen.immOneIntPtrType), kObjHeaderPtrPtr)
|
or(ptrToInt(slotsPhi, codegen.intPtrType), codegen.immOneIntPtrType), kObjHeaderPtrPtr)
|
||||||
@@ -491,6 +504,20 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
Int1(0).llvm))
|
Int1(0).llvm))
|
||||||
}
|
}
|
||||||
addPhiIncoming(slotsPhi!!, prologueBb to slots)
|
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)
|
br(localsInitBb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+52
-54
@@ -20,15 +20,14 @@ import kotlinx.cinterop.allocArrayOf
|
|||||||
import kotlinx.cinterop.memScoped
|
import kotlinx.cinterop.memScoped
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
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.backend.konan.KonanVersion
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.ir.SourceManager.FileEntry
|
import org.jetbrains.kotlin.ir.SourceManager.FileEntry
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
|
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.konan.file.File
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
|
||||||
@@ -104,23 +103,23 @@ internal fun generateDebugInfoHeader(context: Context) {
|
|||||||
|
|
||||||
val path = context.config.outputFile
|
val path = context.config.outputFile
|
||||||
.toFileAndFolder()
|
.toFileAndFolder()
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
context.debugInfo.module = DICreateModule(
|
context.debugInfo.module = DICreateModule(
|
||||||
builder = context.debugInfo.builder,
|
builder = context.debugInfo.builder,
|
||||||
scope = context.llvmModule as DIScopeOpaqueRef,
|
scope = context.llvmModule as DIScopeOpaqueRef,
|
||||||
name = path.path(),
|
name = path.path(),
|
||||||
configurationMacro = "",
|
configurationMacro = "",
|
||||||
includePath = "",
|
includePath = "",
|
||||||
iSysRoot = "")
|
iSysRoot = "")
|
||||||
context.debugInfo.compilationModule = DICreateCompilationUnit(
|
context.debugInfo.compilationModule = DICreateCompilationUnit(
|
||||||
builder = context.debugInfo.builder,
|
builder = context.debugInfo.builder,
|
||||||
lang = DwarfLanguage.DW_LANG_Kotlin.value,
|
lang = DwarfLanguage.DW_LANG_Kotlin.value,
|
||||||
File = path.file,
|
File = path.file,
|
||||||
dir = path.folder,
|
dir = path.folder,
|
||||||
producer = DWARF.producer,
|
producer = DWARF.producer,
|
||||||
isOptimized = 0,
|
isOptimized = 0,
|
||||||
flags = "",
|
flags = "",
|
||||||
rv = DWARF.runtimeVersion)
|
rv = DWARF.runtimeVersion)
|
||||||
/* TODO: figure out what here 2 means:
|
/* 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 - -
|
* 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")
|
@Suppress("UNCHECKED_CAST")
|
||||||
internal fun KotlinType.dwarfType(context:Context, targetData:LLVMTargetDataRef): DITypeOpaqueRef {
|
internal fun KotlinType.dwarfType(context:Context, targetData:LLVMTargetDataRef): DITypeOpaqueRef {
|
||||||
return when {
|
when {
|
||||||
KotlinBuiltIns.isPrimitiveType(this) -> debugInfoBaseType(context, targetData, this.getJetTypeFqName(false), llvmType(context), encoding(context).value.toInt())
|
KotlinBuiltIns.isPrimitiveType(this) -> return debugInfoBaseType(context, targetData, this.getJetTypeFqName(false), llvmType(context), encoding(context).value.toInt())
|
||||||
KotlinBuiltIns.isArray(this) -> {
|
KotlinBuiltIns.isArray(this) -> {
|
||||||
val arrayElementType = context.builtIns.getArrayElementType(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
|
arrayElementType.diType(context, targetData), 1) as DITypeOpaqueRef
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val classDescriptor = TypeUtils.getClassDescriptor(this)
|
val classDescriptor = TypeUtils.getClassDescriptor(this)
|
||||||
if (classDescriptor != null) {
|
return when {
|
||||||
/**
|
classDescriptor != null -> {
|
||||||
* Ideally we'd use [KotlinType.typeInfoSymbolName] here , by type could be not
|
val type = DICreateStructType(
|
||||||
* exportable.
|
refBuilder = context.debugInfo.builder,
|
||||||
*/
|
scope = context.debugInfo.compilationModule as DIScopeOpaqueRef,
|
||||||
DICreateStructType(
|
name = "ObjHeader",
|
||||||
refBuilder = context.debugInfo.builder,
|
file = null,
|
||||||
scope = context.debugInfo.compilationModule as DIScopeOpaqueRef,
|
lineNumber = 0,
|
||||||
name = "ktype:${classDescriptor.fqNameSafe}",
|
sizeInBits = 0,
|
||||||
file = null,
|
alignInBits = 0,
|
||||||
lineNumber = 0,
|
flags = DWARF.flagsForwardDeclaration,
|
||||||
sizeInBits = 0,
|
derivedFrom = null,
|
||||||
alignInBits = 0,
|
elements = null,
|
||||||
flags = DWARF.flagsForwardDeclaration,
|
elementsCount = 0,
|
||||||
derivedFrom = null,
|
refPlace = null)!! as DITypeOpaqueRef
|
||||||
elements = null,
|
dwarfPointerType(context, type)
|
||||||
elementsCount = 0,
|
}
|
||||||
refPlace = null)!! as DITypeOpaqueRef
|
TypeUtils.isTypeParameter(this) -> //TODO: Type parameter, how to deal with if?
|
||||||
}
|
debugInfoBaseType(context, targetData, this.toString(), llvmType(context), encoding(context).value.toInt())
|
||||||
else if (TypeUtils.isTypeParameter(this)){
|
else -> TODO("$this: Does this case really exist?")
|
||||||
//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)
|
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)}
|
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 alignTo(value:Long, align:Long):Long = (value + align - 1) / align * align
|
||||||
|
|
||||||
internal fun FunctionDescriptor.subroutineType(context: Context, llvmTargetData: LLVMTargetDataRef): DISubroutineTypeRef {
|
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))
|
return if (KotlinBuiltIns.isPrimitiveType(this))
|
||||||
refType
|
refType
|
||||||
else
|
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
|
||||||
|
|||||||
+163
-1
@@ -97,7 +97,8 @@ internal enum class DwarfTag(val value:Int) {
|
|||||||
DW_TAG_BORLAND_Delphi_set(0xb003),
|
DW_TAG_BORLAND_Delphi_set(0xb003),
|
||||||
DW_TAG_BORLAND_Delphi_variant(0xb004),
|
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_address(0x01),
|
||||||
DW_ATE_boolean(0x02),
|
DW_ATE_boolean(0x02),
|
||||||
DW_ATE_complex_float(0x03),
|
DW_ATE_complex_float(0x03),
|
||||||
@@ -115,6 +116,167 @@ internal enum class DwarfTag(val value:Int) {
|
|||||||
DW_ATE_decimal_float(0x0f),
|
DW_ATE_decimal_float(0x0f),
|
||||||
DW_ATE_UTF(0x10),
|
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) {
|
internal enum class DwarfLanguage(val value:Int) {
|
||||||
DW_LANG_C89(0x0001),
|
DW_LANG_C89(0x0001),
|
||||||
DW_LANG_C(0x0002),
|
DW_LANG_C(0x0002),
|
||||||
|
|||||||
+9
-11
@@ -208,7 +208,7 @@ internal interface CodeContext {
|
|||||||
* Declares the variable.
|
* Declares the variable.
|
||||||
* @return index of declared 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.
|
* @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 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
|
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() {
|
private inner class VariableScope : InnerScopeImpl() {
|
||||||
|
|
||||||
override fun genDeclareVariable(descriptor: VariableDescriptor, value: LLVMValueRef?): Int {
|
override fun genDeclareVariable(descriptor: VariableDescriptor, value: LLVMValueRef?, variableLocation: VariableDebugLocation?): Int {
|
||||||
return functionGenerationContext.vars.createVariable(descriptor, value)
|
return functionGenerationContext.vars.createVariable(descriptor, value, variableLocation)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDeclaredVariable(descriptor: VariableDescriptor): Int {
|
override fun getDeclaredVariable(descriptor: VariableDescriptor): Int {
|
||||||
@@ -964,7 +964,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
for (catch in catches) {
|
for (catch in catches) {
|
||||||
fun genCatchBlock() {
|
fun genCatchBlock() {
|
||||||
using(VariableScope()) {
|
using(VariableScope()) {
|
||||||
currentCodeContext.genDeclareVariable(catch.parameter, exception)
|
currentCodeContext.genDeclareVariable(catch.parameter, exception, null)
|
||||||
evaluateExpressionAndJump(catch.result, success)
|
evaluateExpressionAndJump(catch.result, success)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1128,22 +1128,20 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
context.log{"generateVariable : ${ir2string(value)}"}
|
context.log{"generateVariable : ${ir2string(value)}"}
|
||||||
val result = value.initializer?.let { evaluateExpression(it) }
|
val result = value.initializer?.let { evaluateExpression(it) }
|
||||||
val variableDescriptor = value.descriptor
|
val variableDescriptor = value.descriptor
|
||||||
val index = currentCodeContext.genDeclareVariable(variableDescriptor, result)
|
val functionScope = (currentCodeContext.functionScope() as FunctionScope).declaration?.scope()
|
||||||
if (context.shouldContainDebugInfo()) {
|
val variableLocation = if (context.shouldContainDebugInfo() && functionScope != null && variableDescriptor.isVar) {
|
||||||
val location = debugLocation(value)
|
val location = debugLocation(value)
|
||||||
val functionScope = (currentCodeContext.functionScope() as FunctionScope).declaration?.scope() ?: return
|
|
||||||
val file = (currentCodeContext.fileScope() as FileScope).file.file()
|
val file = (currentCodeContext.fileScope() as FileScope).file.file()
|
||||||
val variable = functionGenerationContext.vars.load(index)
|
|
||||||
val line = value.startLine()
|
val line = value.startLine()
|
||||||
functionGenerationContext.vars.debugInfoLocalVariableLocation(
|
functionGenerationContext.vars.debugInfoLocalVariableLocation(
|
||||||
functionScope = functionScope,
|
functionScope = functionScope,
|
||||||
diType = variableDescriptor.type.diType(context, functionGenerationContext.llvmTargetData),
|
diType = variableDescriptor.type.diType(context, functionGenerationContext.llvmTargetData),
|
||||||
name = variableDescriptor.name,
|
name = variableDescriptor.name,
|
||||||
variable = variable,
|
|
||||||
file = file,
|
file = file,
|
||||||
line = line,
|
line = line,
|
||||||
location = location)
|
location = location)
|
||||||
}
|
} else null
|
||||||
|
currentCodeContext.genDeclareVariable(variableDescriptor, result, variableLocation)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|||||||
+10
-12
@@ -51,7 +51,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
contextVariablesToIndex.clear()
|
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.
|
// Note that we always create slot for object references for memory management.
|
||||||
if (!descriptor.isVar && value != null)
|
if (!descriptor.isVar && value != null)
|
||||||
return createImmutable(descriptor, value)
|
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
|
// 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
|
// knowledge, as anonymous slots are created only for true vars (for vals
|
||||||
// their single assigner already have slot).
|
// their single assigner already have slot).
|
||||||
return createMutable(descriptor, descriptor.isVar, value)
|
return createMutable(descriptor, descriptor.isVar, value, variableLocation)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createMutable(descriptor: VariableDescriptor,
|
fun createMutable(descriptor: VariableDescriptor,
|
||||||
isVar: Boolean, value: LLVMValueRef? = null) : Int {
|
isVar: Boolean, value: LLVMValueRef? = null, variableLocation: VariableDebugLocation?) : Int {
|
||||||
assert(!contextVariablesToIndex.contains(descriptor))
|
assert(!contextVariablesToIndex.contains(descriptor))
|
||||||
val index = variables.size
|
val index = variables.size
|
||||||
val type = functionGenerationContext.getLLVMType(descriptor.type)
|
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)
|
if (value != null)
|
||||||
functionGenerationContext.storeAnyLocal(value, slot)
|
functionGenerationContext.storeAnyLocal(value, slot)
|
||||||
variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), isVar))
|
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 {
|
private fun createAnonymousMutable(type: LLVMTypeRef, value: LLVMValueRef? = null) : Int {
|
||||||
val index = variables.size
|
val index = variables.size
|
||||||
val slot = functionGenerationContext.alloca(type)
|
val slot = functionGenerationContext.alloca(type, variableLocation = null)
|
||||||
if (value != null)
|
if (value != null)
|
||||||
functionGenerationContext.storeAnyLocal(value, slot)
|
functionGenerationContext.storeAnyLocal(value, slot)
|
||||||
variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), true))
|
variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), true))
|
||||||
@@ -117,7 +117,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
variables[index].store(value)
|
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(
|
val variableDeclaration = DICreateAutoVariable(
|
||||||
builder = functionGenerationContext.context.debugInfo.builder,
|
builder = functionGenerationContext.context.debugInfo.builder,
|
||||||
scope = functionScope,
|
scope = functionScope,
|
||||||
@@ -125,11 +125,9 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
file = file,
|
file = file,
|
||||||
line = line,
|
line = line,
|
||||||
type = diType)
|
type = diType)
|
||||||
DIInsertDeclarationWithEmptyExpression(
|
|
||||||
builder = functionGenerationContext.context.debugInfo.builder,
|
return VariableDebugLocation(localVariable = variableDeclaration!!, location = location, file = file, line = line)
|
||||||
value = variable,
|
|
||||||
localVariable = variableDeclaration,
|
|
||||||
location = location,
|
|
||||||
bb = LLVMGetInsertBlock(functionGenerationContext.builder))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
#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) {
|
internal enum class DwarfLanguage(val value:Int) {
|
||||||
#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME(ID),
|
#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME(ID),
|
||||||
#include "llvm/Support/Dwarf.def"
|
#include "llvm/Support/Dwarf.def"
|
||||||
|
|||||||
@@ -178,6 +178,12 @@ DIDerivedTypeRef DICreateReferenceType(DIBuilderRef refBuilder, DITypeOpaqueRef
|
|||||||
llvm::unwrap(refType)));
|
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,
|
DISubroutineTypeRef DICreateSubroutineType(DIBuilderRef builder,
|
||||||
DITypeOpaqueRef* types,
|
DITypeOpaqueRef* types,
|
||||||
unsigned typesCount) {
|
unsigned typesCount) {
|
||||||
@@ -212,11 +218,14 @@ DIExpressionRef DICreateEmptyExpression(DIBuilderRef builder) {
|
|||||||
return llvm::wrap(llvm::unwrap(builder)->createExpression());
|
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);
|
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),
|
di_builder->insertDeclare(llvm::unwrap(value),
|
||||||
llvm::unwrap(localVariable),
|
llvm::unwrap(localVariable),
|
||||||
di_builder->createExpression(),
|
di_builder->createExpression(expression),
|
||||||
llvm::unwrap(location),
|
llvm::unwrap(location),
|
||||||
llvm::unwrap(bb));
|
llvm::unwrap(bb));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ DICompositeTypeRef DICreateArrayType(DIBuilderRef refBuilder,
|
|||||||
uint64_t elementsCount);
|
uint64_t elementsCount);
|
||||||
|
|
||||||
DIDerivedTypeRef DICreateReferenceType(DIBuilderRef refBuilder, DITypeOpaqueRef refType);
|
DIDerivedTypeRef DICreateReferenceType(DIBuilderRef refBuilder, DITypeOpaqueRef refType);
|
||||||
|
DIDerivedTypeRef DICreatePointerType(DIBuilderRef refBuilder, DITypeOpaqueRef refType);
|
||||||
DICompositeTypeRef DICreateReplaceableCompositeType(DIBuilderRef refBuilder,
|
DICompositeTypeRef DICreateReplaceableCompositeType(DIBuilderRef refBuilder,
|
||||||
int tag,
|
int tag,
|
||||||
const char *name,
|
const char *name,
|
||||||
@@ -92,7 +93,7 @@ DISubroutineTypeRef DICreateSubroutineType(DIBuilderRef builder,
|
|||||||
unsigned typesCount);
|
unsigned typesCount);
|
||||||
|
|
||||||
DILocalVariableRef DICreateAutoVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, DIFileRef file, unsigned line, DITypeOpaqueRef type);
|
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);
|
DIExpressionRef DICreateEmptyExpression(DIBuilderRef builder);
|
||||||
void DIFunctionAddSubprogram(LLVMValueRef fn, DISubprogramRef sp);
|
void DIFunctionAddSubprogram(LLVMValueRef fn, DISubprogramRef sp);
|
||||||
DILocationRef LLVMBuilderSetDebugLocation(LLVMBuilderRef builder, unsigned line, unsigned col, DIScopeOpaqueRef scope);
|
DILocationRef LLVMBuilderSetDebugLocation(LLVMBuilderRef builder, unsigned line, unsigned col, DIScopeOpaqueRef scope);
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|
||||||
Reference in New Issue
Block a user