[codegen][debug info] codegerator uses start/end location encapsulated in IrElement

This commit is contained in:
Vasily Levchenko
2019-06-28 16:28:34 +03:00
parent 360dc2c9b4
commit c8af53e58b
4 changed files with 61 additions and 35 deletions
@@ -155,6 +155,11 @@ private inline fun <R> generateFunctionBody(
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,
val codegen: CodeGenerator,
startLocation: LocationInfo?,
@@ -163,11 +168,11 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
override val context = codegen.context
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
basicBlockToLastLocation.put(block, locationInfo)
basicBlockToLastLocation.put(block, LocationInfoRange(locationInfo, endLocation))
}
var returnType: LLVMTypeRef? = LLVMGetReturnType(getFunctionType(function))
@@ -209,9 +214,9 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
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)!!
update(result, locationInfo)
update(result, startLocationInfo, endLocationInfo)
LLVMMoveBasicBlockAfter(result, this.currentBlock)
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, "")!!
update(success, endLocation, endLocation)
positionAtEnd(success)
return result
}
@@ -526,15 +534,15 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
}
fun filteringExceptionHandler(codeContext: CodeContext): ExceptionHandler {
val lpBlock = basicBlockInFunction("filteringExceptionHandler", position())
val lpBlock = basicBlockInFunction("filteringExceptionHandler", position()?.start)
appendingTo(lpBlock) {
val landingpad = gxxLandingpad(2)
LLVMAddClause(landingpad, kotlinExceptionRtti.llvm)
LLVMAddClause(landingpad, LLVMConstNull(kInt8Ptr))
val fatalForeignExceptionBlock = basicBlock("fatalForeignException", position())
val forwardKotlinExceptionBlock = basicBlock("forwardKotlinException", position())
val fatalForeignExceptionBlock = basicBlock("fatalForeignException", position()?.start)
val forwardKotlinExceptionBlock = basicBlock("forwardKotlinException", position()?.start)
val isKotlinException = icmpEq(
extractValue(landingpad, 1),
@@ -565,7 +573,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
call(context.llvm.cxxStdTerminate, emptyList())
// 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)
appendingTo(loopBlock) {
br(loopBlock)
@@ -626,12 +634,14 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
): LLVMValueRef {
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) {
phi(resultType)
}
val bbElse = basicBlock(locationInfo = position())
val bbElse = basicBlock(startLocationInfo = position?.start, endLocationInfo = endPosition)
condBr(condition, bbExit, bbElse)
assignPhis(resultPhi to thenValue)
@@ -647,8 +657,9 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
}
inline fun ifThen(condition: LLVMValueRef, thenBlock: () -> Unit) {
val bbExit = basicBlock(locationInfo = position())
val bbThen = basicBlock(locationInfo = position())
val endPosition = position()?.end
val bbExit = basicBlock(startLocationInfo = endPosition, endLocationInfo = endPosition)
val bbThen = basicBlock(startLocationInfo = endPosition, endLocationInfo = endPosition)
condBr(condition, bbThen, bbExit)
@@ -660,10 +671,10 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
positionAtEnd(bbExit)
}
internal fun debugLocation(locationInfo: LocationInfo): DILocationRef? {
internal fun debugLocation(startLocationInfo: LocationInfo, endLocation: LocationInfo?): DILocationRef? {
if (!context.shouldContainDebugInfo()) return null
update(currentBlock, locationInfo)
val debugLocation = codegen.generateLocationInfo(locationInfo)
update(currentBlock, startLocationInfo, endLocation)
val debugLocation = codegen.generateLocationInfo(startLocationInfo)
currentPositionHolder.setBuilderDebugLocation(debugLocation)
return debugLocation
}
@@ -741,7 +752,8 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
fun getObjectValue(
irClass: IrClass,
exceptionHandler: ExceptionHandler,
locationInfo: LocationInfo?
startLocationInfo: LocationInfo?,
endLocationInfo: LocationInfo? = null
): LLVMValueRef {
if (irClass.isUnit()) {
return codegen.theUnitInstanceRef.llvm
@@ -763,8 +775,8 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
val shared = irClass.objectIsShared && context.config.threadsAreAllowed
val objectPtr = codegen.getObjectInstanceStorage(irClass, shared)
val bbInit = basicBlock("label_init", locationInfo)
val bbExit = basicBlock("label_continue", locationInfo)
val bbInit = basicBlock("label_init", startLocationInfo, endLocationInfo)
val bbExit = basicBlock("label_continue", startLocationInfo, endLocationInfo)
val objectVal = loadSlot(objectPtr, false)
val objectInitialized = icmpUGt(ptrToInt(objectVal, codegen.intPtrType), codegen.immOneIntPtrType)
val bbCurrent = currentBlock
@@ -1034,7 +1046,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
fun positionAtEnd(block: LLVMBasicBlockRef) {
LLVMPositionBuilderAtEnd(builder, block)
basicBlockToLastLocation[block]?.let{ debugLocation(it) }
basicBlockToLastLocation[block]?.let{ debugLocation(it.start, it.end) }
val lastInstr = LLVMGetLastInstruction(block)
isAfterTerminator = lastInstr != null && (LLVMIsATerminatorInst(lastInstr) != null)
}
@@ -467,7 +467,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
//-------------------------------------------------------------------------//
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)
override fun genBreak(destination: IrBreak) {
@@ -806,7 +806,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
functionGenerationContext.getObjectValue(
value.symbol.owner,
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 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 {
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())
null
else
functionGenerationContext.basicBlock("when_next", it.startLocation)
functionGenerationContext.basicBlock("when_next", it.startLocation, it.endLocation)
generateWhenCase(whenEmittingContext, it, bbNext)
}
@@ -1089,7 +1090,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
val brResult = if (isUnconditional(branch))
evaluateExpression(branch.result)
else {
val bbCase = functionGenerationContext.basicBlock("when_case", branch.startLocation)
val bbCase = functionGenerationContext.basicBlock("when_case", branch.startLocation, branch.endLocation)
val condition = evaluateExpression(branch.condition)
functionGenerationContext.condBr(condition, bbCase, bbNext ?: whenEmittingContext.bbExit.value)
functionGenerationContext.positionAtEnd(bbCase)
@@ -1558,9 +1559,17 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
var bbExit : LLVMBasicBlockRef? = null
var resultPhi : LLVMValueRef? = null
private val functionScope: DIScopeOpaqueRef?
get() = returnableBlock.inlineFunctionSymbol?.owner?.scope()
private val outerScope = currentCodeContext.scope()
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!!
}
@@ -1591,13 +1600,19 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
override fun location(line: Int, column: Int): LocationInfo? {
return if (returnableBlock.inlineFunctionSymbol != null) {
val diScope = returnableBlock.inlineFunctionSymbol?.owner?.scope() ?: return null
LocationInfo(diScope, line, column, outerContext.location(returnableBlock.startLine(), returnableBlock.endLine()))
val diScope = functionScope ?: return null
val outerFileEntry = outerFileEntry()
val inlinedAt = outerContext.location(outerFileEntry.line(returnableBlock.startOffset), outerFileEntry.column(returnableBlock.startOffset))
LocationInfo(diScope, line, column, inlinedAt)
} else {
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.
@@ -1736,10 +1751,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
private fun file() = (currentCodeContext.fileScope() as FileScope).file
//-------------------------------------------------------------------------//
private fun updateBuilderDebugLocation(element: IrElement): DILocationRef? {
if (!context.shouldContainDebugInfo() || currentCodeContext.functionScope() == null) return null
@Suppress("UNCHECKED_CAST")
return element.startLocation?.let { functionGenerationContext.debugLocation(it) }
private fun updateBuilderDebugLocation(element: IrElement) {
if (!context.shouldContainDebugInfo() || currentCodeContext.functionScope() == null || element.startLocation == null) return
functionGenerationContext.debugLocation(element.startLocation!!, element.endLocation!!)
}
private val IrElement.startLocation: LocationInfo?
@@ -330,7 +330,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
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))
@@ -1148,7 +1148,7 @@ private fun ObjCExportCodeGenerator.createObjectInstanceAdapter(
return generateObjCToKotlinSyntheticGetter(selector) {
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))
}
}