Better debug locations logic. (#2496)

This commit is contained in:
Nikolay Igotti
2018-12-25 18:31:04 +03:00
committed by GitHub
parent 104cbb199b
commit 28ab39f593
11 changed files with 103 additions and 82 deletions
@@ -52,6 +52,11 @@ import java.lang.System.out
import kotlin.LazyThreadSafetyMode.PUBLICATION import kotlin.LazyThreadSafetyMode.PUBLICATION
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
/**
* Offset for synthetic elements created by lowerings and not attributable to other places in the source code.
*/
internal const val SYNTHETIC_OFFSET = -2
internal class SpecialDeclarationsFactory(val context: Context) { internal class SpecialDeclarationsFactory(val context: Context) {
private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) } private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) }
private val outerThisFields = mutableMapOf<ClassDescriptor, IrField>() private val outerThisFields = mutableMapOf<ClassDescriptor, IrField>()
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.konan.util.visibleName
/** /**
* Creates and stores terminal compiler outputs * Creates and stores terminal compiler outputs.
*/ */
class OutputFiles(outputPath: String?, target: KonanTarget, produce: CompilerOutputKind) { class OutputFiles(outputPath: String?, target: KonanTarget, produce: CompilerOutputKind) {
@@ -24,13 +24,13 @@ class OutputFiles(outputPath: String?, target: KonanTarget, produce: CompilerOut
val outputName = outputPath?.removeSuffixIfPresent(suffix) ?: produce.visibleName val outputName = outputPath?.removeSuffixIfPresent(suffix) ?: produce.visibleName
/** /**
* Header file for dynamic library * Header file for dynamic library.
*/ */
val cAdapterHeader by lazy { File("${outputName}_api.h") } val cAdapterHeader by lazy { File("${outputName}_api.h") }
val cAdapterDef by lazy { File("${outputName}_symbols.def") } val cAdapterDef by lazy { File("${outputName}_symbols.def") }
/** /**
* Main compiler's output file * Main compiler's output file.
*/ */
val mainFile = outputName val mainFile = outputName
.prefixBaseNameIfNot(prefix) .prefixBaseNameIfNot(prefix)
@@ -5,30 +5,27 @@
package org.jetbrains.kotlin.backend.konan.ir package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.backend.konan.SYNTHETIC_OFFSET
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.ir.SourceManager import org.jetbrains.kotlin.ir.SourceManager
import org.jetbrains.kotlin.ir.SourceRangeInfo import org.jetbrains.kotlin.ir.SourceRangeInfo
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrClassReference import org.jetbrains.kotlin.ir.expressions.IrClassReference
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallWithIndexedArgumentsBase
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase
import org.jetbrains.kotlin.ir.expressions.impl.IrTerminalDeclarationReferenceBase import org.jetbrains.kotlin.ir.expressions.impl.IrTerminalDeclarationReferenceBase
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.types.KotlinType
//-----------------------------------------------------------------------------// //-----------------------------------------------------------------------------//
/** /**
@@ -49,12 +46,19 @@ class NaiveSourceBasedFileEntryImpl(override val name: String) : SourceManager.F
init { init {
val file = File(name) val file = File(name)
if (file.isFile) { if (file.isFile) {
// TODO: could be incorrect, if file is not in system's line terminator format.
// Maybe use (0..document.lineCount - 1)
// .map { document.getLineStartOffset(it) }
// .toIntArray()
// as in PSI.
val separatorLength = System.lineSeparator().length
val buffer = mutableListOf<Int>() val buffer = mutableListOf<Int>()
var currentOffset = 0 var currentOffset = 0
file.forEachLine { line -> file.forEachLine { line ->
buffer.add(currentOffset) buffer.add(currentOffset)
currentOffset += line.length currentOffset += line.length + separatorLength
} }
buffer.add(currentOffset)
lineStartOffsets = buffer.toIntArray() lineStartOffsets = buffer.toIntArray()
} else { } else {
lineStartOffsets = IntArray(0) lineStartOffsets = IntArray(0)
@@ -64,19 +68,18 @@ class NaiveSourceBasedFileEntryImpl(override val name: String) : SourceManager.F
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
override fun getLineNumber(offset: Int): Int { override fun getLineNumber(offset: Int): Int {
assert(offset != UNDEFINED_OFFSET)
if (offset == SYNTHETIC_OFFSET) return 0
val index = lineStartOffsets.binarySearch(offset) val index = lineStartOffsets.binarySearch(offset)
return if (index >= 0) index else -index - 1 return if (index >= 0) index else -index - 2
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
override fun getColumnNumber(offset: Int): Int { override fun getColumnNumber(offset: Int): Int {
assert(offset != UNDEFINED_OFFSET)
if (offset == SYNTHETIC_OFFSET) return 0
var lineNumber = getLineNumber(offset) var lineNumber = getLineNumber(offset)
if (lineNumber >= lineStartOffsets.size) {
lineNumber = lineStartOffsets.size - 1
}
if (lineNumber < 0) lineNumber = 0
if (lineStartOffsets.size == 0) return offset
return offset - lineStartOffsets[lineNumber] return offset - lineStartOffsets[lineNumber]
} }
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.* import kotlinx.cinterop.*
import llvm.* import llvm.*
import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
@@ -130,8 +131,9 @@ internal inline fun<R> generateFunction(codegen: CodeGenerator,
} }
internal inline fun<R> generateFunction(codegen: CodeGenerator, function: LLVMValueRef, code:FunctionGenerationContext.(FunctionGenerationContext) -> R) { internal inline fun<R> generateFunction(codegen: CodeGenerator, function: LLVMValueRef,
generateFunctionBody(FunctionGenerationContext(function, codegen), code) code:FunctionGenerationContext.(FunctionGenerationContext) -> R) {
generateFunctionBody(FunctionGenerationContext(function, codegen, null, null), code)
} }
internal inline fun generateFunction( internal inline fun generateFunction(
@@ -145,7 +147,9 @@ internal inline fun generateFunction(
return function return function
} }
inline private fun <R> generateFunctionBody(functionGenerationContext: FunctionGenerationContext, code: FunctionGenerationContext.(FunctionGenerationContext) -> R) { inline private fun <R> generateFunctionBody(
functionGenerationContext: FunctionGenerationContext,
code: FunctionGenerationContext.(FunctionGenerationContext) -> R) {
functionGenerationContext.prologue() functionGenerationContext.prologue()
functionGenerationContext.code(functionGenerationContext) functionGenerationContext.code(functionGenerationContext)
if (!functionGenerationContext.isAfterTerminator()) if (!functionGenerationContext.isAfterTerminator())
@@ -155,10 +159,11 @@ inline private fun <R> generateFunctionBody(functionGenerationContext: FunctionG
} }
internal class FunctionGenerationContext(val function: LLVMValueRef, internal class FunctionGenerationContext(val function: LLVMValueRef,
val codegen:CodeGenerator, val codegen: CodeGenerator,
startLocation:LocationInfo? = null, startLocation: LocationInfo?,
endLocation:LocationInfo? = null, endLocation: LocationInfo?,
internal val functionDescriptor: FunctionDescriptor? = null):ContextUtils { internal val functionDescriptor: FunctionDescriptor? = null): ContextUtils {
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, LocationInfo>()
@@ -208,7 +213,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
return bb return bb
} }
fun basicBlock(name:String = "label_" , locationInfo:LocationInfo?):LLVMBasicBlockRef { fun basicBlock(name:String = "label_" , locationInfo:LocationInfo?): LLVMBasicBlockRef {
val result = LLVMInsertBasicBlock(this.currentBlock, name)!! val result = LLVMInsertBasicBlock(this.currentBlock, name)!!
update(result, locationInfo) update(result, locationInfo)
LLVMMoveBasicBlockAfter(result, this.currentBlock) LLVMMoveBasicBlockAfter(result, this.currentBlock)
@@ -359,7 +364,6 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
val rargs = args.toCValues() val rargs = args.toCValues()
if (LLVMIsAFunction(llvmFunction) != null /* the function declaration */ && if (LLVMIsAFunction(llvmFunction) != null /* the function declaration */ &&
isFunctionNoUnwind(llvmFunction)) { isFunctionNoUnwind(llvmFunction)) {
return LLVMBuildCall(builder, llvmFunction, rargs, args.size, "")!! return LLVMBuildCall(builder, llvmFunction, rargs, args.size, "")!!
} else { } else {
val unwind = when (exceptionHandler) { val unwind = when (exceptionHandler) {
@@ -8,12 +8,14 @@ package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.allocArrayOf import kotlinx.cinterop.allocArrayOf
import kotlinx.cinterop.memScoped import kotlinx.cinterop.memScoped
import llvm.* import llvm.*
import org.jetbrains.kotlin.backend.konan.SYNTHETIC_OFFSET
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.KonanConfig import org.jetbrains.kotlin.backend.konan.KonanConfig
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.backend.konan.irasdescriptors.FunctionDescriptor import org.jetbrains.kotlin.backend.konan.irasdescriptors.FunctionDescriptor
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.ir.SourceManager.FileEntry import org.jetbrains.kotlin.ir.SourceManager.FileEntry
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
import org.jetbrains.kotlin.konan.KonanVersion import org.jetbrains.kotlin.konan.KonanVersion
import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.file.File
@@ -81,19 +83,26 @@ internal class DebugInfo internal constructor(override val context: Context):Con
val otherTypeSize = LLVMSizeOfTypeInBits(llvmTargetData, otherLlvmType) val otherTypeSize = LLVMSizeOfTypeInBits(llvmTargetData, otherLlvmType)
val otherTypeAlignment = LLVMPreferredAlignmentOfType(llvmTargetData, otherLlvmType) val otherTypeAlignment = LLVMPreferredAlignmentOfType(llvmTargetData, otherLlvmType)
} }
/** /**
* File entry starts offsets from zero while dwarf number lines/column starting from 1. * File entry starts offsets from zero while dwarf number lines/column starting from 1.
*/ */
private fun FileEntry.location(offset:Int, offsetToNumber:(Int) -> Int):Int { private val NO_SOURCE_FILE = "no source file"
return if (offset < 0) 0 // lldb uses 1-based unsigned integers, so 0 is "no-info" private fun FileEntry.location(offset: Int, offsetToNumber: (Int) -> Int): Int {
else offsetToNumber(offset) + 1 assert(offset != UNDEFINED_OFFSET)
// Part "name.isEmpty() || name == NO_SOURCE_FILE" is an awful hack, @minamoto, please fix properly.
if (offset == SYNTHETIC_OFFSET || name.isEmpty() || name == NO_SOURCE_FILE) return 1
// lldb uses 1-based unsigned integers, so 0 is "no-info".
val result = offsetToNumber(offset) + 1
assert(result != 0)
return result
} }
internal fun FileEntry.line(offset: Int) = location(offset, this::getLineNumber) internal fun FileEntry.line(offset: Int) = location(offset, this::getLineNumber)
internal fun FileEntry.column(offset: Int) = location(offset, this::getColumnNumber) internal fun FileEntry.column(offset: Int) = location(offset, this::getColumnNumber)
internal data class FileAndFolder(val file:String, val folder:String) { internal data class FileAndFolder(val file: String, val folder: String) {
companion object { companion object {
val NOFILE = FileAndFolder("-", "") val NOFILE = FileAndFolder("-", "")
} }
@@ -109,7 +118,6 @@ internal fun String?.toFileAndFolder():FileAndFolder {
internal fun generateDebugInfoHeader(context: Context) { internal fun generateDebugInfoHeader(context: Context) {
if (context.shouldContainDebugInfo()) { if (context.shouldContainDebugInfo()) {
val path = context.config.outputFile val path = context.config.outputFile
.toFileAndFolder() .toFileAndFolder()
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -150,7 +158,7 @@ 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 {
when { when {
KotlinBuiltIns.isPrimitiveType(this) -> return 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())
else -> { else -> {
@@ -186,7 +194,6 @@ internal fun KotlinType.diType(context: Context, llvmTargetData: LLVMTargetDataR
dwarfType(context, llvmTargetData) dwarfType(context, llvmTargetData)
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private fun debugInfoBaseType(context:Context, targetData:LLVMTargetDataRef, typeName:String, type:LLVMTypeRef, encoding:Int) = DICreateBasicType( private fun debugInfoBaseType(context:Context, targetData:LLVMTargetDataRef, typeName:String, type:LLVMTypeRef, encoding:Int) = DICreateBasicType(
context.debugInfo.builder, typeName, context.debugInfo.builder, typeName,
@@ -205,14 +212,12 @@ 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)} internal fun KotlinType.encoding(context: Context): DwarfTypeKind = when {
internal fun KotlinType.encoding(context:Context):DwarfTypeKind = when {
this in context.debugInfo.intTypes -> DwarfTypeKind.DW_ATE_signed this in context.debugInfo.intTypes -> DwarfTypeKind.DW_ATE_signed
this in context.debugInfo.realTypes -> DwarfTypeKind.DW_ATE_float this in context.debugInfo.realTypes -> DwarfTypeKind.DW_ATE_float
KotlinBuiltIns.isBoolean(this) -> DwarfTypeKind.DW_ATE_boolean KotlinBuiltIns.isBoolean(this) -> DwarfTypeKind.DW_ATE_boolean
KotlinBuiltIns.isChar(this) -> DwarfTypeKind.DW_ATE_unsigned KotlinBuiltIns.isChar(this) -> DwarfTypeKind.DW_ATE_unsigned
(!KotlinBuiltIns.isPrimitiveType(this)) -> DwarfTypeKind.DW_ATE_address (!KotlinBuiltIns.isPrimitiveType(this)) -> DwarfTypeKind.DW_ATE_address
else -> TODO(toString()) else -> TODO(toString())
} }
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SourceFile
import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
@@ -32,6 +33,7 @@ import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.getArguments import org.jetbrains.kotlin.ir.util.getArguments
import org.jetbrains.kotlin.ir.util.getContainingFile
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
@@ -655,12 +657,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
private inner class FunctionScope (val declaration: IrFunction?, val functionGenerationContext: FunctionGenerationContext) : InnerScopeImpl() { private inner class FunctionScope (val declaration: IrFunction?, val functionGenerationContext: FunctionGenerationContext) : InnerScopeImpl() {
constructor(llvmFunction:LLVMValueRef, name:String, functionGenerationContext: FunctionGenerationContext):this(null, functionGenerationContext) { constructor(llvmFunction:LLVMValueRef, name:String, functionGenerationContext: FunctionGenerationContext):
this(null, functionGenerationContext) {
this.llvmFunction = llvmFunction this.llvmFunction = llvmFunction
this.name = name this.name = name
} }
var llvmFunction:LLVMValueRef? = declaration?.let{ var llvmFunction: LLVMValueRef? = declaration?.let{
codegen.llvmFunction(it) codegen.llvmFunction(it)
} }
@@ -1641,8 +1644,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
fun getFileEntry(sourceFileName: String): SourceManager.FileEntry = fun getFileEntry(sourceFileName: String): SourceManager.FileEntry =
// We must cache file entries, otherwise we reparse same file many times. // We must cache file entries, otherwise we reparse same file many times.
context.fileEntryCache.getOrPut(sourceFileName) { context.fileEntryCache.getOrPut(sourceFileName) {
NaiveSourceBasedFileEntryImpl(sourceFileName) NaiveSourceBasedFileEntryImpl(sourceFileName)
} }
@@ -1687,7 +1690,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
* 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.
*/ */
private val scope by lazy { private val scope by lazy {
if (!context.shouldContainDebugInfo()) if (!context.shouldContainDebugInfo() || returnableBlock.startOffset == UNDEFINED_OFFSET)
return@lazy null return@lazy null
val lexicalBlockFile = DICreateLexicalBlockFile(context.debugInfo.builder, functionScope()!!.scope(), super.file.file()) val lexicalBlockFile = DICreateLexicalBlockFile(context.debugInfo.builder, functionScope()!!.scope(), super.file.file())
DICreateLexicalBlock(context.debugInfo.builder, lexicalBlockFile, super.file.file(), returnableBlock.startLine(), returnableBlock.startColumn())!! DICreateLexicalBlock(context.debugInfo.builder, lexicalBlockFile, super.file.file(), returnableBlock.startLine(), returnableBlock.startColumn())!!
@@ -1702,7 +1705,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
private open inner class FileScope(val file: IrFile) : InnerScopeImpl() { private open inner class FileScope(val file: IrFile) : InnerScopeImpl() {
override fun fileScope(): CodeContext? = this override fun fileScope(): CodeContext? = this
override fun location(line: Int, column: Int) = scope()?.let {LocationInfo(it, line, column) } override fun location(line: Int, column: Int) = scope()?.let { LocationInfo(it, line, column) }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private val scope by lazy { private val scope by lazy {
@@ -1861,11 +1864,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
private fun updateBuilderDebugLocation(element: IrElement): DILocationRef? { private fun updateBuilderDebugLocation(element: IrElement): DILocationRef? {
if (!context.shouldContainDebugInfo() || currentCodeContext.functionScope() == null) return null if (!context.shouldContainDebugInfo() || currentCodeContext.functionScope() == null) return null
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return element.startLocation?.let{ functionGenerationContext.debugLocation(it) } return element.startLocation?.let { functionGenerationContext.debugLocation(it) }
} }
private val IrElement.startLocation: LocationInfo? private val IrElement.startLocation: LocationInfo?
get() = if (startOffset == UNDEFINED_OFFSET) null get() = if (startOffset == UNDEFINED_OFFSET) null
else currentCodeContext.location(startLine(), startColumn()) else currentCodeContext.location(startLine(), startColumn())
private val IrElement.endLocation: LocationInfo? private val IrElement.endLocation: LocationInfo?
@@ -1928,7 +1931,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
private fun IrFunction.scope():DIScopeOpaqueRef? = this.scope(startLine()) private fun IrFunction.scope(): DIScopeOpaqueRef? = if (startOffset != UNDEFINED_OFFSET)
this.scope(startLine()) else null
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private fun FunctionDescriptor.scope(startLine:Int): DIScopeOpaqueRef? { private fun FunctionDescriptor.scope(startLine:Int): DIScopeOpaqueRef? {
@@ -15,12 +15,12 @@ import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.KonanBackendContext import org.jetbrains.kotlin.backend.konan.KonanBackendContext
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections
import org.jetbrains.kotlin.backend.konan.isObjCClass import org.jetbrains.kotlin.backend.konan.isObjCClass
import org.jetbrains.kotlin.backend.konan.SYNTHETIC_OFFSET
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
@@ -103,7 +103,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
val kPropertiesFieldType: IrType = context.ir.symbols.array.typeWith(kPropertyImplType) val kPropertiesFieldType: IrType = context.ir.symbols.array.typeWith(kPropertyImplType)
val kPropertiesField = IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, val kPropertiesField = IrFieldImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION, DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION,
createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor, createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor,
kPropertiesFieldType.toKotlinType() kPropertiesFieldType.toKotlinType()
@@ -187,8 +187,9 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
val initializers = kProperties.values.sortedBy { it.second }.map { it.first } val initializers = kProperties.values.sortedBy { it.second }.map { it.first }
// TODO: move to object for lazy initialization. // TODO: move to object for lazy initialization.
irFile.declarations.add(0, kPropertiesField.apply { irFile.declarations.add(0, kPropertiesField.apply {
initializer = IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, initializer = IrExpressionBodyImpl(startOffset, endOffset,
context.createArrayOfExpression(kPropertyImplType, initializers, UNDEFINED_OFFSET, UNDEFINED_OFFSET)) context.createArrayOfExpression(kPropertyImplType, initializers,
startOffset, endOffset))
}) })
kPropertiesField.parent = irFile kPropertiesField.parent = irFile
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.declarations.impl.*
@@ -938,7 +937,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
} }
// These are marker descriptors to split up the lowering on two parts. // These are marker descriptors to split up the lowering on two parts.
private val saveState = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, private val saveState = IrFunctionImpl(irFunction.startOffset, irFunction.startOffset, IrDeclarationOrigin.DEFINED,
SimpleFunctionDescriptorImpl.create( SimpleFunctionDescriptorImpl.create(
irFunction.descriptor, irFunction.descriptor,
Annotations.EMPTY, Annotations.EMPTY,
@@ -948,7 +947,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
initialize(null, null, emptyList(), emptyList(), context.builtIns.unitType, Modality.ABSTRACT, Visibilities.PRIVATE) initialize(null, null, emptyList(), emptyList(), context.builtIns.unitType, Modality.ABSTRACT, Visibilities.PRIVATE)
}, context.irBuiltIns.unitType) }, context.irBuiltIns.unitType)
private val restoreState = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, private val restoreState = IrFunctionImpl(irFunction.startOffset, irFunction.startOffset, IrDeclarationOrigin.DEFINED,
SimpleFunctionDescriptorImpl.create( SimpleFunctionDescriptorImpl.create(
irFunction.descriptor, irFunction.descriptor,
Annotations.EMPTY, Annotations.EMPTY,
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithoutArguments import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithoutArguments
import org.jetbrains.kotlin.backend.konan.SYNTHETIC_OFFSET
import org.jetbrains.kotlin.backend.konan.reportCompilationError import org.jetbrains.kotlin.backend.konan.reportCompilationError
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.builtins.isFunctionType
@@ -26,7 +27,6 @@ import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
@@ -105,20 +105,20 @@ internal class TestProcessor (val context: KonanBackendContext) {
+irCall(registerTestCase, registerTestCase.descriptor.returnType!!.toErasedIrType()).apply { +irCall(registerTestCase, registerTestCase.descriptor.returnType!!.toErasedIrType()).apply {
dispatchReceiver = irGet(receiver) dispatchReceiver = irGet(receiver)
putValueArgument(0, IrConstImpl.string( putValueArgument(0, IrConstImpl.string(
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
context.irBuiltIns.stringType, context.irBuiltIns.stringType,
it.function.descriptor.name.identifier) it.function.descriptor.name.identifier)
) )
putValueArgument(1, IrFunctionReferenceImpl( putValueArgument(1, IrFunctionReferenceImpl(
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
descriptor.valueParameters[1].type.toErasedIrType(), descriptor.valueParameters[1].type.toErasedIrType(),
it.function, it.function,
it.function.descriptor, 0)) it.function.descriptor, 0))
putValueArgument(2, IrConstImpl.boolean( putValueArgument(2, IrConstImpl.boolean(
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
context.irBuiltIns.booleanType, context.irBuiltIns.booleanType,
it.ignored it.ignored
)) ))
@@ -129,13 +129,14 @@ internal class TestProcessor (val context: KonanBackendContext) {
dispatchReceiver = irGet(receiver) dispatchReceiver = irGet(receiver)
val testKindEntry = it.kind.runtimeKind val testKindEntry = it.kind.runtimeKind
putValueArgument(0, IrGetEnumValueImpl( putValueArgument(0, IrGetEnumValueImpl(
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
symbols.testFunctionKind.typeWithoutArguments, symbols.testFunctionKind.typeWithoutArguments,
testKindEntry) testKindEntry)
) )
putValueArgument(1, IrFunctionReferenceImpl(UNDEFINED_OFFSET, putValueArgument(1, IrFunctionReferenceImpl(
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
SYNTHETIC_OFFSET,
descriptor.valueParameters[1].type.toErasedIrType(), descriptor.valueParameters[1].type.toErasedIrType(),
it.function, it.function,
it.function.descriptor, 0)) it.function.descriptor, 0))
@@ -385,7 +386,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
: GetterBuilder(objectSymbol.typeWithoutArguments, testSuite, getterName) { : GetterBuilder(objectSymbol.typeWithoutArguments, testSuite, getterName) {
override fun buildIr(): IrFunction = IrFunctionImpl( override fun buildIr(): IrFunction = IrFunctionImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
TEST_SUITE_GENERATED_MEMBER, TEST_SUITE_GENERATED_MEMBER,
symbol, symbol,
this@ObjectGetterBuilder.returnType this@ObjectGetterBuilder.returnType
@@ -393,7 +394,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
val builder = context.createIrBuilder(symbol) val builder = context.createIrBuilder(symbol)
createParameterDeclarations(context.ir.symbols.symbolTable) createParameterDeclarations(context.ir.symbols.symbolTable)
body = builder.irBlockBody { body = builder.irBlockBody {
+irReturn(IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, +irReturn(IrGetObjectValueImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
objectSymbol.typeWithoutArguments, objectSymbol) objectSymbol.typeWithoutArguments, objectSymbol)
) )
} }
@@ -408,7 +409,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
: GetterBuilder(classSymbol.typeWithStarProjections, testSuite, getterName) { : GetterBuilder(classSymbol.typeWithStarProjections, testSuite, getterName) {
override fun buildIr() = IrFunctionImpl( override fun buildIr() = IrFunctionImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
TEST_SUITE_GENERATED_MEMBER, TEST_SUITE_GENERATED_MEMBER,
symbol, symbol,
this@InstanceGetterBuilder.returnType this@InstanceGetterBuilder.returnType
@@ -441,7 +442,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
.single(predicate)) .single(predicate))
override fun buildIr() = IrConstructorImpl( override fun buildIr() = IrConstructorImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
TEST_SUITE_GENERATED_MEMBER, TEST_SUITE_GENERATED_MEMBER,
symbol, symbol,
testSuite.typeWithStarProjections testSuite.typeWithStarProjections
@@ -464,8 +465,8 @@ internal class TestProcessor (val context: KonanBackendContext) {
body = context.createIrBuilder(symbol).irBlockBody { body = context.createIrBuilder(symbol).irBlockBody {
val superConstructor = symbols.baseClassSuiteConstructor val superConstructor = symbols.baseClassSuiteConstructor
+IrDelegatingConstructorCallImpl( +IrDelegatingConstructorCallImpl(
startOffset = UNDEFINED_OFFSET, startOffset = SYNTHETIC_OFFSET,
endOffset = UNDEFINED_OFFSET, endOffset = SYNTHETIC_OFFSET,
type = context.irBuiltIns.unitType, type = context.irBuiltIns.unitType,
symbol = symbols.symbolTable.referenceConstructor(superConstructor), symbol = symbols.symbolTable.referenceConstructor(superConstructor),
descriptor = superConstructor, descriptor = superConstructor,
@@ -475,14 +476,14 @@ internal class TestProcessor (val context: KonanBackendContext) {
putTypeArgument(1, testCompanionType.toErasedIrType()) putTypeArgument(1, testCompanionType.toErasedIrType())
putValueArgument(0, IrConstImpl.string( putValueArgument(0, IrConstImpl.string(
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
context.irBuiltIns.stringType, context.irBuiltIns.stringType,
suiteName) suiteName)
) )
putValueArgument(1, IrConstImpl.boolean( putValueArgument(1, IrConstImpl.boolean(
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
context.irBuiltIns.booleanType, context.irBuiltIns.booleanType,
ignored ignored
)) ))
@@ -556,8 +557,8 @@ internal class TestProcessor (val context: KonanBackendContext) {
} }
override fun buildIr() = symbols.symbolTable.declareClass( override fun buildIr() = symbols.symbolTable.declareClass(
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
UNDEFINED_OFFSET, SYNTHETIC_OFFSET,
TEST_SUITE_CLASS, TEST_SUITE_CLASS,
symbol.descriptor).apply { symbol.descriptor).apply {
createParameterDeclarations() createParameterDeclarations()
@@ -617,7 +618,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
irFile.addChild(ir) irFile.addChild(ir)
val irConstructor = ir.constructors.single() val irConstructor = ir.constructors.single()
irFile.addTopLevelInitializer( irFile.addTopLevelInitializer(
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irConstructor.returnType, irConstructor.symbol), IrCallImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, irConstructor.returnType, irConstructor.symbol),
context, threadLocal = true) context, threadLocal = true)
} }
@@ -643,7 +644,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
// and later on we could modify some suite's properties. This shall be redesigned. // and later on we could modify some suite's properties. This shall be redesigned.
irFile.addTopLevelInitializer(builder.irBlock { irFile.addTopLevelInitializer(builder.irBlock {
val constructorCall = irCall(symbols.topLevelSuiteConstructor).apply { val constructorCall = irCall(symbols.topLevelSuiteConstructor).apply {
putValueArgument(0, IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, putValueArgument(0, IrConstImpl.string(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
context.irBuiltIns.stringType, suiteName)) context.irBuiltIns.stringType, suiteName))
} }
val testSuiteVal = irTemporary(constructorCall, "topLevelTestSuite") val testSuiteVal = irTemporary(constructorCall, "topLevelTestSuite")
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.functionName
import org.jetbrains.kotlin.backend.konan.llvm.localHash import org.jetbrains.kotlin.backend.konan.llvm.localHash
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
@@ -636,7 +635,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
is IrDelegatingConstructorCall -> { is IrDelegatingConstructorCall -> {
val thisReceiver = (descriptor as ConstructorDescriptor).constructedClass.thisReceiver!! val thisReceiver = (descriptor as ConstructorDescriptor).constructedClass.thisReceiver!!
val thiz = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, thisReceiver.type, val thiz = IrGetValueImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, thisReceiver.type,
thisReceiver.symbol) thisReceiver.symbol)
val arguments = listOf(thiz) + value.getArguments().map { it.second } val arguments = listOf(thiz) + value.getArguments().map { it.second }
DataFlowIR.Node.StaticCall( DataFlowIR.Node.StaticCall(
@@ -575,8 +575,8 @@ class RunInteropKonanTest extends KonanTest {
List<String> linkerArguments = interopConf.linkerOpts // TODO: add arguments from .def file List<String> linkerArguments = interopConf.linkerOpts // TODO: add arguments from .def file
List<String> compilerArguments = ["-library", interopBc, "-nativelibrary", interopStubsBc] + List<String> compilerArguments = ["-library", interopBc, "-native-library", interopStubsBc] +
linkerArguments.collectMany { ["-linkerOpts", it] } linkerArguments.collectMany { ["-linker-options", it] }
runCompiler(filesToCompile, exe, compilerArguments) runCompiler(filesToCompile, exe, compilerArguments)
} }