[codegen][debug] generation debug info for vals.
This commit is contained in:
committed by
Vasily Levchenko
parent
b6713df52a
commit
fea734ec83
+1
-1
@@ -365,6 +365,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var debugInfo:DebugInfo
|
lateinit var debugInfo: DebugInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-2
@@ -24,6 +24,7 @@ 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.ir.declarations.IrValueParameter
|
||||||
|
|
||||||
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||||
|
|
||||||
@@ -478,6 +479,12 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
private fun position() = basicBlockToLastLocation[currentBlock]
|
private fun position() = basicBlockToLastLocation[currentBlock]
|
||||||
|
|
||||||
|
|
||||||
|
internal fun mapParameterForDebug(index: Int, value: LLVMValueRef) {
|
||||||
|
appendingTo(localsInitBb) {
|
||||||
|
LLVMBuildStore(builder, value, vars.addressOf(index))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal fun prologue() {
|
internal fun prologue() {
|
||||||
assert(returns.isEmpty())
|
assert(returns.isEmpty())
|
||||||
if (isObjectType(returnType!!)) {
|
if (isObjectType(returnType!!)) {
|
||||||
@@ -505,7 +512,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
Int32(slotCount * codegen.runtime.pointerSize).llvm,
|
Int32(slotCount * codegen.runtime.pointerSize).llvm,
|
||||||
Int32(codegen.runtime.pointerAlignment).llvm,
|
Int32(codegen.runtime.pointerAlignment).llvm,
|
||||||
Int1(0).llvm))
|
Int1(0).llvm))
|
||||||
call(context.llvm.enterFrameFunction, listOf(slots, Int32(slotCount).llvm))
|
call(context.llvm.enterFrameFunction, listOf(slots, Int32(vars.skip).llvm, Int32(slotCount).llvm))
|
||||||
}
|
}
|
||||||
addPhiIncoming(slotsPhi!!, prologueBb to slots)
|
addPhiIncoming(slotsPhi!!, prologueBb to slots)
|
||||||
memScoped {
|
memScoped {
|
||||||
@@ -669,7 +676,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
private fun releaseVars() {
|
private fun releaseVars() {
|
||||||
if (needSlots) {
|
if (needSlots) {
|
||||||
call(context.llvm.leaveFrameFunction,
|
call(context.llvm.leaveFrameFunction,
|
||||||
listOf(slotsPhi!!, Int32(slotCount).llvm))
|
listOf(slotsPhi!!, Int32(vars.skip).llvm, Int32(slotCount).llvm))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+73
-34
@@ -31,8 +31,10 @@ import org.jetbrains.kotlin.ir.IrElement
|
|||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.SourceManager
|
import org.jetbrains.kotlin.ir.SourceManager
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptorBase
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptorBase
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
import org.jetbrains.kotlin.ir.util.getArguments
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
@@ -463,17 +465,30 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
/**
|
/**
|
||||||
* The scope of parameter visibility.
|
* The scope of parameter visibility.
|
||||||
*/
|
*/
|
||||||
private open inner class ParameterScope(private val functionGenerationContext: FunctionGenerationContext,
|
private open inner class ParameterScope(
|
||||||
parameters: Map<ParameterDescriptor, LLVMValueRef>): InnerScopeImpl() {
|
function: IrFunction?,
|
||||||
|
private val functionGenerationContext: FunctionGenerationContext): InnerScopeImpl() {
|
||||||
|
|
||||||
// Note: it is possible to generate access to a parameter without any variables,
|
val parameters = bindParameters(function?.descriptor)
|
||||||
// however variables are named and thus the resulting bitcode can be more readable.
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
parameters.map { (descriptor, value) ->
|
if (function != null) {
|
||||||
functionGenerationContext.vars.createImmutable(descriptor, value)
|
parameters.forEach{
|
||||||
}
|
val descriptor = it.key
|
||||||
|
val ir = when {
|
||||||
|
descriptor is ValueParameterDescriptor -> function.getIrValueParameter(descriptor)
|
||||||
|
descriptor is ReceiverParameterDescriptor && function.extensionReceiverParameter?.descriptor == descriptor -> function.extensionReceiverParameter!!
|
||||||
|
descriptor is ReceiverParameterDescriptor && function.dispatchReceiverParameter?.descriptor == descriptor-> function.dispatchReceiverParameter!!
|
||||||
|
function.descriptor is ClassConstructorDescriptor && (function.descriptor as ClassConstructorDescriptor).constructedClass.thisAsReceiverParameter == descriptor-> IrValueParameterImpl(function.startOffset, function.startOffset, object: IrDeclarationOriginImpl("THIS"){}, descriptor)
|
||||||
|
else -> TODO()
|
||||||
|
}
|
||||||
|
|
||||||
|
val local = functionGenerationContext.vars.createParameter(descriptor,
|
||||||
|
it.value, debugInfoIfNeeded(function, ir))
|
||||||
|
functionGenerationContext.mapParameterForDebug(local, it.value)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun genGetValue(descriptor: ValueDescriptor): LLVMValueRef {
|
override fun genGetValue(descriptor: ValueDescriptor): LLVMValueRef {
|
||||||
@@ -489,10 +504,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
/**
|
/**
|
||||||
* The [CodeContext] enclosing the entire function body.
|
* The [CodeContext] enclosing the entire function body.
|
||||||
*/
|
*/
|
||||||
private inner class FunctionScope (val declaration: IrFunction?, val functionGenerationContext: FunctionGenerationContext) :
|
private inner class FunctionScope (val declaration: IrFunction?, val functionGenerationContext: FunctionGenerationContext) : InnerScopeImpl() {
|
||||||
ParameterScope(functionGenerationContext, bindParameters(declaration?.descriptor)) {
|
|
||||||
|
|
||||||
constructor(llvmFunction:LLVMValueRef, functionGenerationContext: FunctionGenerationContext):this(null, functionGenerationContext) {
|
constructor(llvmFunction:LLVMValueRef, functionGenerationContext: FunctionGenerationContext):this(null, functionGenerationContext) {
|
||||||
this.llvmFunction = llvmFunction
|
this.llvmFunction = llvmFunction
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var llvmFunction:LLVMValueRef? = declaration?.let{
|
var llvmFunction:LLVMValueRef? = declaration?.let{
|
||||||
@@ -531,7 +548,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
/**
|
/**
|
||||||
* Binds LLVM function parameters to IR parameter descriptors.
|
* Binds LLVM function parameters to IR parameter descriptors.
|
||||||
*/
|
*/
|
||||||
private fun bindParameters(descriptor: FunctionDescriptor?): Map<ParameterDescriptor, LLVMValueRef> {
|
private fun bindParameters(descriptor: FunctionDescriptor?): Map<ParameterDescriptor, LLVMValueRef> {
|
||||||
if (descriptor == null) return emptyMap()
|
if (descriptor == null) return emptyMap()
|
||||||
val parameterDescriptors = descriptor.allParameters
|
val parameterDescriptors = descriptor.allParameters
|
||||||
return parameterDescriptors.mapIndexed { i, parameterDescriptor ->
|
return parameterDescriptors.mapIndexed { i, parameterDescriptor ->
|
||||||
@@ -549,22 +566,27 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
if (declaration.descriptor.isExternal) return
|
if (declaration.descriptor.isExternal) return
|
||||||
if (body == null) return
|
if (body == null) return
|
||||||
|
|
||||||
|
val scope = declaration.scope()
|
||||||
|
val startLine = declaration.startLine()
|
||||||
val startLocationInfo = LocationInfo(
|
val startLocationInfo = LocationInfo(
|
||||||
scope = declaration.scope(),
|
scope = scope,
|
||||||
line = declaration.startLine(),
|
line = startLine,
|
||||||
column = declaration.startColumn())
|
column = declaration.startColumn())
|
||||||
val endLocationInfo = LocationInfo(
|
val endLocationInfo = LocationInfo(
|
||||||
scope = declaration.scope(),
|
scope = scope,
|
||||||
line = declaration.endLine(),
|
line = declaration.endLine(),
|
||||||
column = declaration.endColumn())
|
column = declaration.endColumn())
|
||||||
generateFunction(codegen, declaration.descriptor, startLocationInfo, endLocationInfo) {
|
generateFunction(codegen, declaration.descriptor, startLocationInfo, endLocationInfo) {
|
||||||
using(FunctionScope(declaration, it)) {
|
using(FunctionScope(declaration, it)) {
|
||||||
using(VariableScope()) {
|
val parameterScope = ParameterScope(declaration, functionGenerationContext)
|
||||||
when (body) {
|
using(parameterScope) {
|
||||||
is IrBlockBody -> body.statements.forEach { generateStatement(it) }
|
using(VariableScope()) {
|
||||||
is IrExpressionBody -> generateStatement(body.expression)
|
when (body) {
|
||||||
is IrSyntheticBody -> throw AssertionError("Synthetic body ${body.kind} has not been lowered")
|
is IrBlockBody -> body.statements.forEach { generateStatement(it) }
|
||||||
else -> TODO(ir2string(body))
|
is IrExpressionBody -> generateStatement(body.expression)
|
||||||
|
is IrSyntheticBody -> throw AssertionError("Synthetic body ${body.kind} has not been lowered")
|
||||||
|
else -> TODO(ir2string(body))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1070,25 +1092,41 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
private fun debugInfoIfNeeded(function: IrFunction?, element: IrElement): VariableDebugLocation? {
|
||||||
private fun generateVariable(value: IrVariable) {
|
if (function == null || !context.shouldContainDebugInfo()) return null
|
||||||
context.log{"generateVariable : ${ir2string(value)}"}
|
val functionScope = function?.scope()
|
||||||
val result = value.initializer?.let { evaluateExpression(it) }
|
if (functionScope == null || !element.needDebugInfo(context)) return null
|
||||||
val variableDescriptor = value.descriptor
|
val location = debugLocation(element)
|
||||||
val functionScope = (currentCodeContext.functionScope() as FunctionScope).declaration?.scope()
|
val file = (currentCodeContext.fileScope() as FileScope).file.file()
|
||||||
val variableLocation = if (context.shouldContainDebugInfo() && functionScope != null && variableDescriptor.isVar) {
|
val line = element.startLine()
|
||||||
val location = debugLocation(value)
|
return when (element) {
|
||||||
val file = (currentCodeContext.fileScope() as FileScope).file.file()
|
is IrVariable -> debugInfoLocalVariableLocation(
|
||||||
val line = value.startLine()
|
builder = context.debugInfo.builder,
|
||||||
functionGenerationContext.vars.debugInfoLocalVariableLocation(
|
|
||||||
functionScope = functionScope,
|
functionScope = functionScope,
|
||||||
diType = variableDescriptor.type.diType(context, functionGenerationContext.llvmTargetData),
|
diType = element.descriptor.type.diType(context, codegen.llvmTargetData),
|
||||||
name = variableDescriptor.name,
|
name = element.descriptor.name,
|
||||||
file = file,
|
file = file,
|
||||||
line = line,
|
line = line,
|
||||||
location = location)
|
location = location)
|
||||||
} else null
|
is IrValueParameter -> debugInfoParameterLocation(
|
||||||
currentCodeContext.genDeclareVariable(variableDescriptor, result, variableLocation)
|
builder = context.debugInfo.builder,
|
||||||
|
functionScope = functionScope,
|
||||||
|
diType = element.descriptor.type.diType(context, codegen.llvmTargetData),
|
||||||
|
name = element.descriptor.name,
|
||||||
|
argNo = (element.descriptor as? ValueParameterDescriptor)?.index ?: 0,
|
||||||
|
file = file,
|
||||||
|
line = line,
|
||||||
|
location = location)
|
||||||
|
else -> throw Error("Unsupported element type: ${ir2string(element)}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateVariable(variable: IrVariable) {
|
||||||
|
context.log{"generateVariable : ${ir2string(variable)}"}
|
||||||
|
val value = variable.initializer?.let { evaluateExpression(it) }
|
||||||
|
currentCodeContext.genDeclareVariable(
|
||||||
|
variable.descriptor, value, debugInfoIfNeeded(
|
||||||
|
(currentCodeContext.functionScope() as FunctionScope)?.declaration, variable))
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -2414,3 +2452,4 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
internal data class LocationInfo(val scope:DIScopeOpaqueRef?, val line:Int, val column:Int)
|
internal data class LocationInfo(val scope:DIScopeOpaqueRef?, val line:Int, val column:Int)
|
||||||
|
|
||||||
|
private fun IrFunction.hasNotReceiver() = this.extensionReceiverParameter == null && this.dispatchReceiverParameter == null
|
||||||
+62
-18
@@ -17,9 +17,13 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.llvm
|
package org.jetbrains.kotlin.backend.konan.llvm
|
||||||
|
|
||||||
import llvm.*
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
internal fun IrElement.needDebugInfo(context: Context) = context.shouldContainDebugInfo() || (this is IrVariable && this.descriptor.isVar)
|
||||||
|
|
||||||
internal class VariableManager(val functionGenerationContext: FunctionGenerationContext) {
|
internal class VariableManager(val functionGenerationContext: FunctionGenerationContext) {
|
||||||
internal interface Record {
|
internal interface Record {
|
||||||
@@ -35,6 +39,13 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
override fun toString() = (if (refSlot) "refslot" else "slot") + " for ${address}"
|
override fun toString() = (if (refSlot) "refslot" else "slot") + " for ${address}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inner class ParameterRecord(val address: LLVMValueRef, val refSlot: Boolean) : Record {
|
||||||
|
override fun load() : LLVMValueRef = functionGenerationContext.loadSlot(address, false)
|
||||||
|
override fun store(value: LLVMValueRef) = throw Error("writing to parameter")
|
||||||
|
override fun address() : LLVMValueRef = this.address
|
||||||
|
override fun toString() = (if (refSlot) "refslot" else "slot") + " for ${address}"
|
||||||
|
}
|
||||||
|
|
||||||
class ValueRecord(val value: LLVMValueRef, val name: Name) : Record {
|
class ValueRecord(val value: LLVMValueRef, val name: Name) : Record {
|
||||||
override fun load() : LLVMValueRef = value
|
override fun load() : LLVMValueRef = value
|
||||||
override fun store(value: LLVMValueRef) = throw Error("writing to immutable: ${name}")
|
override fun store(value: LLVMValueRef) = throw Error("writing to immutable: ${name}")
|
||||||
@@ -51,19 +62,20 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
contextVariablesToIndex.clear()
|
contextVariablesToIndex.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createVariable(descriptor: VariableDescriptor, value: LLVMValueRef? = null, variableLocation: VariableDebugLocation?) : Int {
|
fun createVariable(descriptor: ValueDescriptor, value: LLVMValueRef? = null, variableLocation: VariableDebugLocation?) : Int {
|
||||||
|
val isVar = descriptor is VariableDescriptor && descriptor.isVar
|
||||||
// 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 (!functionGenerationContext.context.shouldContainDebugInfo() && !isVar && value != null)
|
||||||
return createImmutable(descriptor, value)
|
return createImmutable(descriptor, value)
|
||||||
else
|
else
|
||||||
// Unfortunately, we have to create mutable slots here,
|
// Unfortunately, we have to create mutable slots here,
|
||||||
// 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, variableLocation)
|
return createMutable(descriptor, isVar, value, variableLocation)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createMutable(descriptor: VariableDescriptor,
|
internal fun createMutable(descriptor: ValueDescriptor,
|
||||||
isVar: Boolean, value: LLVMValueRef? = null, variableLocation: VariableDebugLocation?) : 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
|
||||||
@@ -76,6 +88,20 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal var skip = 0
|
||||||
|
internal fun createParameter(descriptor: ValueDescriptor, 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, "p-${descriptor.name.asString()}", variableLocation)
|
||||||
|
val isObject = functionGenerationContext.isObjectType(type)
|
||||||
|
variables.add(ParameterRecord(slot, isObject))
|
||||||
|
contextVariablesToIndex[descriptor] = index
|
||||||
|
if (isObject)
|
||||||
|
skip++
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
// Creates anonymous mutable variable.
|
// Creates anonymous mutable variable.
|
||||||
// Think of slot reuse.
|
// Think of slot reuse.
|
||||||
fun createAnonymousSlot(value: LLVMValueRef? = null) : LLVMValueRef {
|
fun createAnonymousSlot(value: LLVMValueRef? = null) : LLVMValueRef {
|
||||||
@@ -92,7 +118,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createImmutable(descriptor: ValueDescriptor, value: LLVMValueRef) : Int {
|
internal fun createImmutable(descriptor: ValueDescriptor, value: LLVMValueRef) : Int {
|
||||||
if (contextVariablesToIndex.containsKey(descriptor))
|
if (contextVariablesToIndex.containsKey(descriptor))
|
||||||
throw Error("$descriptor is already defined")
|
throw Error("$descriptor is already defined")
|
||||||
val index = variables.size
|
val index = variables.size
|
||||||
@@ -116,18 +142,36 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
fun store(value: LLVMValueRef, index: Int) {
|
fun store(value: LLVMValueRef, index: Int) {
|
||||||
variables[index].store(value)
|
variables[index].store(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|
||||||
name = name.asString(),
|
|
||||||
file = file,
|
|
||||||
line = line,
|
|
||||||
type = diType)
|
|
||||||
|
|
||||||
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)
|
internal data class VariableDebugLocation(val localVariable: DILocalVariableRef, val location:DILocationRef?, val file:DIFileRef, val line:Int)
|
||||||
|
|
||||||
|
internal fun debugInfoLocalVariableLocation(builder: DIBuilderRef?,
|
||||||
|
functionScope: DIScopeOpaqueRef, diType: DITypeOpaqueRef, name:Name, file: DIFileRef, line: Int,
|
||||||
|
location: DILocationRef?): VariableDebugLocation {
|
||||||
|
val variableDeclaration = DICreateAutoVariable(
|
||||||
|
builder = builder,
|
||||||
|
scope = functionScope,
|
||||||
|
name = name.asString(),
|
||||||
|
file = file,
|
||||||
|
line = line,
|
||||||
|
type = diType)
|
||||||
|
|
||||||
|
return VariableDebugLocation(localVariable = variableDeclaration!!, location = location, file = file, line = line)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun debugInfoParameterLocation(builder: DIBuilderRef?,
|
||||||
|
functionScope: DIScopeOpaqueRef, diType: DITypeOpaqueRef,
|
||||||
|
name:Name, argNo: Int, file: DIFileRef, line: Int,
|
||||||
|
location: DILocationRef?): VariableDebugLocation {
|
||||||
|
val variableDeclaration = DICreateParameterVariable(
|
||||||
|
builder = builder,
|
||||||
|
scope = functionScope,
|
||||||
|
name = name.asString(),
|
||||||
|
argNo = argNo,
|
||||||
|
file = file,
|
||||||
|
line = line,
|
||||||
|
type = diType)
|
||||||
|
|
||||||
|
return VariableDebugLocation(localVariable = variableDeclaration!!, location = location, file = file, line = line)
|
||||||
|
}
|
||||||
@@ -214,6 +214,16 @@ DILocalVariableRef DICreateAutoVariable(DIBuilderRef builder, DIScopeOpaqueRef s
|
|||||||
llvm::unwrap(type)));
|
llvm::unwrap(type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DILocalVariableRef DICreateParameterVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, unsigned argNo, DIFileRef file, unsigned line, DITypeOpaqueRef type) {
|
||||||
|
return llvm::wrap(llvm::unwrap(builder)->createParameterVariable(
|
||||||
|
llvm::unwrap(scope),
|
||||||
|
name,
|
||||||
|
argNo,
|
||||||
|
llvm::unwrap(file),
|
||||||
|
line,
|
||||||
|
llvm::unwrap(type)));
|
||||||
|
}
|
||||||
|
|
||||||
DIExpressionRef DICreateEmptyExpression(DIBuilderRef builder) {
|
DIExpressionRef DICreateEmptyExpression(DIBuilderRef builder) {
|
||||||
return llvm::wrap(llvm::unwrap(builder)->createExpression());
|
return llvm::wrap(llvm::unwrap(builder)->createExpression());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,6 +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);
|
||||||
|
DILocalVariableRef DICreateParameterVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, unsigned argNo, DIFileRef file, unsigned line, DITypeOpaqueRef type);
|
||||||
void DIInsertDeclaration(DIBuilderRef builder, LLVMValueRef value, DILocalVariableRef localVariable, DILocationRef location, LLVMBasicBlockRef bb, int64_t *expr, uint64_t exprCount);
|
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);
|
||||||
|
|||||||
@@ -1080,13 +1080,13 @@ void UpdateRef(ObjHeader** location, const ObjHeader* object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnterFrame(ObjHeader** start, int count) {
|
void EnterFrame(ObjHeader** start, int parameters, int count) {
|
||||||
MEMORY_LOG("EnterFrame %p .. %p\n", start, start + count)
|
MEMORY_LOG("EnterFrame %p .. %p\n", start, start + count + parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeaveFrame(ObjHeader** start, int count) {
|
void LeaveFrame(ObjHeader** start, int parameters, int count) {
|
||||||
MEMORY_LOG("LeaveFrame %p .. %p\n", start, start + count)
|
MEMORY_LOG("LeaveFrame %p .. %p\n", start, start + count + parameters)
|
||||||
ReleaseRefs(start + kFrameOverlaySlots, count - kFrameOverlaySlots);
|
ReleaseRefs(start + parameters + kFrameOverlaySlots, count - kFrameOverlaySlots - parameters);
|
||||||
if (*start != nullptr) {
|
if (*start != nullptr) {
|
||||||
auto arena = initedArena(start);
|
auto arena = initedArena(start);
|
||||||
MEMORY_LOG("LeaveFrame: free arena %p\n", arena)
|
MEMORY_LOG("LeaveFrame: free arena %p\n", arena)
|
||||||
|
|||||||
@@ -362,9 +362,9 @@ void UpdateReturnRef(ObjHeader** returnSlot, const ObjHeader* object) RUNTIME_NO
|
|||||||
// Optimization: release all references in range.
|
// Optimization: release all references in range.
|
||||||
void ReleaseRefs(ObjHeader** start, int count) RUNTIME_NOTHROW;
|
void ReleaseRefs(ObjHeader** start, int count) RUNTIME_NOTHROW;
|
||||||
// Called on frame enter, if it has object slots.
|
// Called on frame enter, if it has object slots.
|
||||||
void EnterFrame(ObjHeader** start, int count) RUNTIME_NOTHROW;
|
void EnterFrame(ObjHeader** start, int parameters, int count) RUNTIME_NOTHROW;
|
||||||
// Called on frame leave, if it has object slots.
|
// Called on frame leave, if it has object slots.
|
||||||
void LeaveFrame(ObjHeader** start, int count) RUNTIME_NOTHROW;
|
void LeaveFrame(ObjHeader** start, int parameters, int count) RUNTIME_NOTHROW;
|
||||||
// Tries to use returnSlot's arena for allocation.
|
// Tries to use returnSlot's arena for allocation.
|
||||||
ObjHeader** GetReturnSlotIfArena(ObjHeader** returnSlot, ObjHeader** localSlot) RUNTIME_NOTHROW;
|
ObjHeader** GetReturnSlotIfArena(ObjHeader** returnSlot, ObjHeader** localSlot) RUNTIME_NOTHROW;
|
||||||
// Tries to use param's arena for allocation.
|
// Tries to use param's arena for allocation.
|
||||||
|
|||||||
Reference in New Issue
Block a user