[codegen][debug info] codegerator uses start/end location encapsulated in IrElement
This commit is contained in:
+33
-21
@@ -155,6 +155,11 @@ private inline fun <R> generateFunctionBody(
|
|||||||
functionGenerationContext.resetDebugLocation()
|
functionGenerationContext.resetDebugLocation()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There're cases when we don't need end position or it is meaningless.
|
||||||
|
*/
|
||||||
|
internal data class LocationInfoRange(var start: LocationInfo, var end: LocationInfo?)
|
||||||
|
|
||||||
internal class FunctionGenerationContext(val function: LLVMValueRef,
|
internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||||
val codegen: CodeGenerator,
|
val codegen: CodeGenerator,
|
||||||
startLocation: LocationInfo?,
|
startLocation: LocationInfo?,
|
||||||
@@ -163,11 +168,11 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
|
|
||||||
override val context = codegen.context
|
override val context = codegen.context
|
||||||
val vars = VariableManager(this)
|
val vars = VariableManager(this)
|
||||||
private val basicBlockToLastLocation = mutableMapOf<LLVMBasicBlockRef, LocationInfo>()
|
private val basicBlockToLastLocation = mutableMapOf<LLVMBasicBlockRef, LocationInfoRange>()
|
||||||
|
|
||||||
private fun update(block:LLVMBasicBlockRef, locationInfo: LocationInfo?) {
|
private fun update(block:LLVMBasicBlockRef, locationInfo: LocationInfo?, endLocation: LocationInfo? = null) {
|
||||||
locationInfo ?: return
|
locationInfo ?: return
|
||||||
basicBlockToLastLocation.put(block, locationInfo)
|
basicBlockToLastLocation.put(block, LocationInfoRange(locationInfo, endLocation))
|
||||||
}
|
}
|
||||||
|
|
||||||
var returnType: LLVMTypeRef? = LLVMGetReturnType(getFunctionType(function))
|
var returnType: LLVMTypeRef? = LLVMGetReturnType(getFunctionType(function))
|
||||||
@@ -209,9 +214,9 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
return bb
|
return bb
|
||||||
}
|
}
|
||||||
|
|
||||||
fun basicBlock(name:String = "label_" , locationInfo:LocationInfo?): LLVMBasicBlockRef {
|
fun basicBlock(name:String = "label_", startLocationInfo:LocationInfo?, endLocationInfo: LocationInfo? = null): LLVMBasicBlockRef {
|
||||||
val result = LLVMInsertBasicBlock(this.currentBlock, name)!!
|
val result = LLVMInsertBasicBlock(this.currentBlock, name)!!
|
||||||
update(result, locationInfo)
|
update(result, startLocationInfo, endLocationInfo)
|
||||||
LLVMMoveBasicBlockAfter(result, this.currentBlock)
|
LLVMMoveBasicBlockAfter(result, this.currentBlock)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -375,8 +380,11 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val success = basicBlock("call_success", position())
|
val position = position()
|
||||||
|
val endLocation = position?.start.let { position?.end }
|
||||||
|
val success = basicBlock("call_success", endLocation)
|
||||||
val result = LLVMBuildInvoke(builder, llvmFunction, rargs, args.size, success, unwind, "")!!
|
val result = LLVMBuildInvoke(builder, llvmFunction, rargs, args.size, success, unwind, "")!!
|
||||||
|
update(success, endLocation, endLocation)
|
||||||
positionAtEnd(success)
|
positionAtEnd(success)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -526,15 +534,15 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun filteringExceptionHandler(codeContext: CodeContext): ExceptionHandler {
|
fun filteringExceptionHandler(codeContext: CodeContext): ExceptionHandler {
|
||||||
val lpBlock = basicBlockInFunction("filteringExceptionHandler", position())
|
val lpBlock = basicBlockInFunction("filteringExceptionHandler", position()?.start)
|
||||||
|
|
||||||
appendingTo(lpBlock) {
|
appendingTo(lpBlock) {
|
||||||
val landingpad = gxxLandingpad(2)
|
val landingpad = gxxLandingpad(2)
|
||||||
LLVMAddClause(landingpad, kotlinExceptionRtti.llvm)
|
LLVMAddClause(landingpad, kotlinExceptionRtti.llvm)
|
||||||
LLVMAddClause(landingpad, LLVMConstNull(kInt8Ptr))
|
LLVMAddClause(landingpad, LLVMConstNull(kInt8Ptr))
|
||||||
|
|
||||||
val fatalForeignExceptionBlock = basicBlock("fatalForeignException", position())
|
val fatalForeignExceptionBlock = basicBlock("fatalForeignException", position()?.start)
|
||||||
val forwardKotlinExceptionBlock = basicBlock("forwardKotlinException", position())
|
val forwardKotlinExceptionBlock = basicBlock("forwardKotlinException", position()?.start)
|
||||||
|
|
||||||
val isKotlinException = icmpEq(
|
val isKotlinException = icmpEq(
|
||||||
extractValue(landingpad, 1),
|
extractValue(landingpad, 1),
|
||||||
@@ -565,7 +573,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
call(context.llvm.cxxStdTerminate, emptyList())
|
call(context.llvm.cxxStdTerminate, emptyList())
|
||||||
|
|
||||||
// Note: unreachable instruction to be generated here, but debug information is improper in this case.
|
// Note: unreachable instruction to be generated here, but debug information is improper in this case.
|
||||||
val loopBlock = basicBlock("loop", position())
|
val loopBlock = basicBlock("loop", position()?.start)
|
||||||
br(loopBlock)
|
br(loopBlock)
|
||||||
appendingTo(loopBlock) {
|
appendingTo(loopBlock) {
|
||||||
br(loopBlock)
|
br(loopBlock)
|
||||||
@@ -626,12 +634,14 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
): LLVMValueRef {
|
): LLVMValueRef {
|
||||||
val resultType = thenValue.type
|
val resultType = thenValue.type
|
||||||
|
|
||||||
val bbExit = basicBlock(locationInfo = position())
|
val position = position()
|
||||||
|
val endPosition = position()?.end
|
||||||
|
val bbExit = basicBlock(startLocationInfo = endPosition, endLocationInfo = endPosition)
|
||||||
val resultPhi = appendingTo(bbExit) {
|
val resultPhi = appendingTo(bbExit) {
|
||||||
phi(resultType)
|
phi(resultType)
|
||||||
}
|
}
|
||||||
|
|
||||||
val bbElse = basicBlock(locationInfo = position())
|
val bbElse = basicBlock(startLocationInfo = position?.start, endLocationInfo = endPosition)
|
||||||
|
|
||||||
condBr(condition, bbExit, bbElse)
|
condBr(condition, bbExit, bbElse)
|
||||||
assignPhis(resultPhi to thenValue)
|
assignPhis(resultPhi to thenValue)
|
||||||
@@ -647,8 +657,9 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun ifThen(condition: LLVMValueRef, thenBlock: () -> Unit) {
|
inline fun ifThen(condition: LLVMValueRef, thenBlock: () -> Unit) {
|
||||||
val bbExit = basicBlock(locationInfo = position())
|
val endPosition = position()?.end
|
||||||
val bbThen = basicBlock(locationInfo = position())
|
val bbExit = basicBlock(startLocationInfo = endPosition, endLocationInfo = endPosition)
|
||||||
|
val bbThen = basicBlock(startLocationInfo = endPosition, endLocationInfo = endPosition)
|
||||||
|
|
||||||
condBr(condition, bbThen, bbExit)
|
condBr(condition, bbThen, bbExit)
|
||||||
|
|
||||||
@@ -660,10 +671,10 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
positionAtEnd(bbExit)
|
positionAtEnd(bbExit)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun debugLocation(locationInfo: LocationInfo): DILocationRef? {
|
internal fun debugLocation(startLocationInfo: LocationInfo, endLocation: LocationInfo?): DILocationRef? {
|
||||||
if (!context.shouldContainDebugInfo()) return null
|
if (!context.shouldContainDebugInfo()) return null
|
||||||
update(currentBlock, locationInfo)
|
update(currentBlock, startLocationInfo, endLocation)
|
||||||
val debugLocation = codegen.generateLocationInfo(locationInfo)
|
val debugLocation = codegen.generateLocationInfo(startLocationInfo)
|
||||||
currentPositionHolder.setBuilderDebugLocation(debugLocation)
|
currentPositionHolder.setBuilderDebugLocation(debugLocation)
|
||||||
return debugLocation
|
return debugLocation
|
||||||
}
|
}
|
||||||
@@ -741,7 +752,8 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
fun getObjectValue(
|
fun getObjectValue(
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
exceptionHandler: ExceptionHandler,
|
exceptionHandler: ExceptionHandler,
|
||||||
locationInfo: LocationInfo?
|
startLocationInfo: LocationInfo?,
|
||||||
|
endLocationInfo: LocationInfo? = null
|
||||||
): LLVMValueRef {
|
): LLVMValueRef {
|
||||||
if (irClass.isUnit()) {
|
if (irClass.isUnit()) {
|
||||||
return codegen.theUnitInstanceRef.llvm
|
return codegen.theUnitInstanceRef.llvm
|
||||||
@@ -763,8 +775,8 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
|
|
||||||
val shared = irClass.objectIsShared && context.config.threadsAreAllowed
|
val shared = irClass.objectIsShared && context.config.threadsAreAllowed
|
||||||
val objectPtr = codegen.getObjectInstanceStorage(irClass, shared)
|
val objectPtr = codegen.getObjectInstanceStorage(irClass, shared)
|
||||||
val bbInit = basicBlock("label_init", locationInfo)
|
val bbInit = basicBlock("label_init", startLocationInfo, endLocationInfo)
|
||||||
val bbExit = basicBlock("label_continue", locationInfo)
|
val bbExit = basicBlock("label_continue", startLocationInfo, endLocationInfo)
|
||||||
val objectVal = loadSlot(objectPtr, false)
|
val objectVal = loadSlot(objectPtr, false)
|
||||||
val objectInitialized = icmpUGt(ptrToInt(objectVal, codegen.intPtrType), codegen.immOneIntPtrType)
|
val objectInitialized = icmpUGt(ptrToInt(objectVal, codegen.intPtrType), codegen.immOneIntPtrType)
|
||||||
val bbCurrent = currentBlock
|
val bbCurrent = currentBlock
|
||||||
@@ -1034,7 +1046,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
|
|
||||||
fun positionAtEnd(block: LLVMBasicBlockRef) {
|
fun positionAtEnd(block: LLVMBasicBlockRef) {
|
||||||
LLVMPositionBuilderAtEnd(builder, block)
|
LLVMPositionBuilderAtEnd(builder, block)
|
||||||
basicBlockToLastLocation[block]?.let{ debugLocation(it) }
|
basicBlockToLastLocation[block]?.let{ debugLocation(it.start, it.end) }
|
||||||
val lastInstr = LLVMGetLastInstruction(block)
|
val lastInstr = LLVMGetLastInstruction(block)
|
||||||
isAfterTerminator = lastInstr != null && (LLVMIsATerminatorInst(lastInstr) != null)
|
isAfterTerminator = lastInstr != null && (LLVMIsATerminatorInst(lastInstr) != null)
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-12
@@ -467,7 +467,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private inner class LoopScope(val loop: IrLoop) : InnerScopeImpl() {
|
private inner class LoopScope(val loop: IrLoop) : InnerScopeImpl() {
|
||||||
val loopExit = functionGenerationContext.basicBlock("loop_exit", loop.condition.startLocation)
|
val loopExit = functionGenerationContext.basicBlock("loop_exit", loop.endLocation)
|
||||||
val loopCheck = functionGenerationContext.basicBlock("loop_check", loop.condition.startLocation)
|
val loopCheck = functionGenerationContext.basicBlock("loop_check", loop.condition.startLocation)
|
||||||
|
|
||||||
override fun genBreak(destination: IrBreak) {
|
override fun genBreak(destination: IrBreak) {
|
||||||
@@ -806,7 +806,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
functionGenerationContext.getObjectValue(
|
functionGenerationContext.getObjectValue(
|
||||||
value.symbol.owner,
|
value.symbol.owner,
|
||||||
currentCodeContext.exceptionHandler,
|
currentCodeContext.exceptionHandler,
|
||||||
value.startLocation
|
value.startLocation,
|
||||||
|
value.endLocation
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -1052,7 +1053,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
val needsPhi = isUnconditional(expression.branches.last()) && !expression.type.isUnit()
|
val needsPhi = isUnconditional(expression.branches.last()) && !expression.type.isUnit()
|
||||||
val llvmType = codegen.getLLVMType(expression.type)
|
val llvmType = codegen.getLLVMType(expression.type)
|
||||||
|
|
||||||
val bbExit = lazy { functionGenerationContext.basicBlock("when_exit", expression.startLocation) }
|
val bbExit = lazy { functionGenerationContext.basicBlock("when_exit", expression.endLocation) }
|
||||||
|
|
||||||
val resultPhi = lazy {
|
val resultPhi = lazy {
|
||||||
functionGenerationContext.appendingTo(bbExit.value) {
|
functionGenerationContext.appendingTo(bbExit.value) {
|
||||||
@@ -1070,7 +1071,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
val bbNext = if (it == expression.branches.last())
|
val bbNext = if (it == expression.branches.last())
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
functionGenerationContext.basicBlock("when_next", it.startLocation)
|
functionGenerationContext.basicBlock("when_next", it.startLocation, it.endLocation)
|
||||||
generateWhenCase(whenEmittingContext, it, bbNext)
|
generateWhenCase(whenEmittingContext, it, bbNext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1089,7 +1090,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
val brResult = if (isUnconditional(branch))
|
val brResult = if (isUnconditional(branch))
|
||||||
evaluateExpression(branch.result)
|
evaluateExpression(branch.result)
|
||||||
else {
|
else {
|
||||||
val bbCase = functionGenerationContext.basicBlock("when_case", branch.startLocation)
|
val bbCase = functionGenerationContext.basicBlock("when_case", branch.startLocation, branch.endLocation)
|
||||||
val condition = evaluateExpression(branch.condition)
|
val condition = evaluateExpression(branch.condition)
|
||||||
functionGenerationContext.condBr(condition, bbCase, bbNext ?: whenEmittingContext.bbExit.value)
|
functionGenerationContext.condBr(condition, bbCase, bbNext ?: whenEmittingContext.bbExit.value)
|
||||||
functionGenerationContext.positionAtEnd(bbCase)
|
functionGenerationContext.positionAtEnd(bbCase)
|
||||||
@@ -1558,9 +1559,17 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
var bbExit : LLVMBasicBlockRef? = null
|
var bbExit : LLVMBasicBlockRef? = null
|
||||||
var resultPhi : LLVMValueRef? = null
|
var resultPhi : LLVMValueRef? = null
|
||||||
|
private val functionScope: DIScopeOpaqueRef?
|
||||||
|
get() = returnableBlock.inlineFunctionSymbol?.owner?.scope()
|
||||||
|
private val outerScope = currentCodeContext.scope()
|
||||||
|
|
||||||
private fun getExit(): LLVMBasicBlockRef {
|
private fun getExit(): LLVMBasicBlockRef {
|
||||||
if (bbExit == null) bbExit = functionGenerationContext.basicBlock("returnable_block_exit", returnableBlock.startLocation)
|
val location = returnableBlock.inlineFunctionSymbol?.let {
|
||||||
|
location(it.owner.endLine(), it.owner.endColumn())
|
||||||
|
} ?: returnableBlock.statements.lastOrNull()?.let {
|
||||||
|
location(it.endLine(), it.endColumn())
|
||||||
|
}
|
||||||
|
if (bbExit == null) bbExit = functionGenerationContext.basicBlock("returnable_block_exit", location)
|
||||||
return bbExit!!
|
return bbExit!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1591,13 +1600,19 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
override fun location(line: Int, column: Int): LocationInfo? {
|
override fun location(line: Int, column: Int): LocationInfo? {
|
||||||
return if (returnableBlock.inlineFunctionSymbol != null) {
|
return if (returnableBlock.inlineFunctionSymbol != null) {
|
||||||
val diScope = returnableBlock.inlineFunctionSymbol?.owner?.scope() ?: return null
|
val diScope = functionScope ?: return null
|
||||||
LocationInfo(diScope, line, column, outerContext.location(returnableBlock.startLine(), returnableBlock.endLine()))
|
val outerFileEntry = outerFileEntry()
|
||||||
|
val inlinedAt = outerContext.location(outerFileEntry.line(returnableBlock.startOffset), outerFileEntry.column(returnableBlock.startOffset))
|
||||||
|
LocationInfo(diScope, line, column, inlinedAt)
|
||||||
} else {
|
} else {
|
||||||
outerContext.location(line, column)
|
outerContext.location(line, column)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun outerFileEntry() =
|
||||||
|
(outerContext.fileScope() as? FileScope)?.file?.fileEntry
|
||||||
|
?: error("returnable block should be inlined at some file")
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: DILexicalBlocks aren't nested, they should be scoped with the parent function.
|
* Note: DILexicalBlocks aren't nested, they should be scoped with the parent function.
|
||||||
@@ -1736,10 +1751,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
private fun file() = (currentCodeContext.fileScope() as FileScope).file
|
private fun file() = (currentCodeContext.fileScope() as FileScope).file
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
private fun updateBuilderDebugLocation(element: IrElement): DILocationRef? {
|
private fun updateBuilderDebugLocation(element: IrElement) {
|
||||||
if (!context.shouldContainDebugInfo() || currentCodeContext.functionScope() == null) return null
|
if (!context.shouldContainDebugInfo() || currentCodeContext.functionScope() == null || element.startLocation == null) return
|
||||||
@Suppress("UNCHECKED_CAST")
|
functionGenerationContext.debugLocation(element.startLocation!!, element.endLocation!!)
|
||||||
return element.startLocation?.let { functionGenerationContext.debugLocation(it) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val IrElement.startLocation: LocationInfo?
|
private val IrElement.startLocation: LocationInfo?
|
||||||
|
|||||||
+1
-1
@@ -330,7 +330,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
functionType(kObjHeaderPtr, false, kObjHeaderPtrPtr),
|
functionType(kObjHeaderPtr, false, kObjHeaderPtrPtr),
|
||||||
""
|
""
|
||||||
) {
|
) {
|
||||||
ret(getObjectValue(value, ExceptionHandler.Caller, locationInfo = null))
|
ret(getObjectValue(value, ExceptionHandler.Caller, startLocationInfo = null))
|
||||||
}
|
}
|
||||||
|
|
||||||
Struct(runtime.associatedObjectTableRecordType, key.typeInfoPtr, constPointer(associatedObjectGetter))
|
Struct(runtime.associatedObjectTableRecordType, key.typeInfoPtr, constPointer(associatedObjectGetter))
|
||||||
|
|||||||
+1
-1
@@ -1148,7 +1148,7 @@ private fun ObjCExportCodeGenerator.createObjectInstanceAdapter(
|
|||||||
|
|
||||||
return generateObjCToKotlinSyntheticGetter(selector) {
|
return generateObjCToKotlinSyntheticGetter(selector) {
|
||||||
initRuntimeIfNeeded() // For instance methods it gets called when allocating.
|
initRuntimeIfNeeded() // For instance methods it gets called when allocating.
|
||||||
val value = getObjectValue(irClass, locationInfo = null, exceptionHandler = ExceptionHandler.Caller)
|
val value = getObjectValue(irClass, startLocationInfo = null, exceptionHandler = ExceptionHandler.Caller)
|
||||||
ret(kotlinToObjC(value, ReferenceBridge))
|
ret(kotlinToObjC(value, ReferenceBridge))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user