From 67d6d47e5f1e3ec4657252545db310a8921be699 Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Fri, 1 Feb 2019 17:12:59 +0300 Subject: [PATCH] Moved to IrReturnableBlock version with proper IrFile instead of String file name. --- .../kotlin/backend/konan/ir/KonanIr.kt | 104 +++++++++++++----- .../konan/irasdescriptors/NewIrUtils.kt | 6 +- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 11 +- .../konan/lower/FinallyBlocksLowering.kt | 6 +- .../backend/konan/lower/FunctionInlining.kt | 12 +- .../konan/optimizations/Devirtualization.kt | 6 +- .../konan/serialization/IrModuleSerializer.kt | 4 +- .../backend/konan/serialization/KonanIr.proto | 6 +- .../KonanIrModuleDeserializer.kt | 7 +- 9 files changed, 105 insertions(+), 57 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt index e1fed413754..b336a22db83 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt @@ -9,24 +9,49 @@ import org.jetbrains.kotlin.backend.konan.SYNTHETIC_OFFSET import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.SourceManager +import org.jetbrains.kotlin.ir.SourceManager.FileEntry 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.IrFile -import org.jetbrains.kotlin.ir.expressions.IrCall -import org.jetbrains.kotlin.ir.expressions.IrClassReference -import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrContainerExpressionBase import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase import org.jetbrains.kotlin.ir.expressions.impl.IrTerminalDeclarationReferenceBase import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrFileSymbol +import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.name.FqName +val File.lineStartOffsets: IntArray get() { + // 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() + var currentOffset = 0 + this.forEachLine { line -> + buffer.add(currentOffset) + currentOffset += line.length + separatorLength + } + buffer.add(currentOffset) + return buffer.toIntArray() +} + +val FileEntry.lineStartOffsets get() = File(name).let { + if (it.exists && it.isFile) it.lineStartOffsets else IntArray(0) +} + + //-----------------------------------------------------------------------------// /** * TODO @@ -37,33 +62,7 @@ import org.jetbrains.kotlin.name.FqName * compilation stage (perhaps in or before inline face) */ -class NaiveSourceBasedFileEntryImpl(override val name: String) : SourceManager.FileEntry { - - private val lineStartOffsets: IntArray - - //-------------------------------------------------------------------------// - - init { - val file = File(name) - 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() - var currentOffset = 0 - file.forEachLine { line -> - buffer.add(currentOffset) - currentOffset += line.length + separatorLength - } - buffer.add(currentOffset) - lineStartOffsets = buffer.toIntArray() - } else { - lineStartOffsets = IntArray(0) - } - } +class NaiveSourceBasedFileEntryImpl(override val name: String, val lineStartOffsets: IntArray = IntArray(0)) : SourceManager.FileEntry { //-------------------------------------------------------------------------// @@ -216,4 +215,49 @@ internal class IrPrivateClassReferenceImpl(startOffset: Int, { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitClassReference(this, data) +} + +class KonanIrReturnableBlockImpl( + startOffset: Int, + endOffset: Int, + type: IrType, + override val symbol: IrReturnableBlockSymbol, + origin: IrStatementOrigin? = null, + val sourceFile: IrFile? = null +) : + IrContainerExpressionBase(startOffset, endOffset, type, origin), + IrReturnableBlock { + + override val descriptor = symbol.descriptor + + constructor( + startOffset: Int, + endOffset: Int, + type: IrType, + symbol: IrReturnableBlockSymbol, + origin: IrStatementOrigin?, + statements: List, + sourceFile: IrFile? = null + ) : this(startOffset, endOffset, type, symbol, origin, sourceFile) { + this.statements.addAll(statements) + } + + override val sourceFileName: String = sourceFile?.fileEntry?.name ?: "no source file" + + init { + symbol.bind(this) + } + + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitBlock(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + statements.forEach { it.accept(visitor, data) } + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + statements.forEachIndexed { i, irStatement -> + statements[i] = irStatement.transform(transformer, data) + } + } } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt index c330a32f224..0e47316e315 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt @@ -193,11 +193,11 @@ val IrDeclaration.isSetter get() = this is IrSimpleFunction && this == this.corr val IrDeclaration.isAccessor get() = this.isGetter || this.isSetter -val IrDeclaration.fileEntry: SourceManager.FileEntry get() = parent.let { +val IrDeclaration.file: IrFile get() = parent.let { when (it) { - is IrFile -> it.fileEntry + is IrFile -> it is IrPackageFragment -> TODO("Unknown file") - is IrDeclaration -> it.fileEntry + is IrDeclaration -> it.file else -> TODO("Unexpected declaration parent") } } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 0c75312e9dd..149d44165f9 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptor import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.defaultType @@ -857,7 +856,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map return evaluateWhen (value) is IrThrow -> return evaluateThrow (value) is IrTry -> return evaluateTry (value) - is IrReturnableBlockImpl -> return evaluateReturnableBlock (value) + is IrReturnableBlock -> return evaluateReturnableBlock (value) is IrContainerExpression -> return evaluateContainerExpression (value) is IrWhileLoop -> return evaluateWhileLoop (value) is IrDoWhileLoop -> return evaluateDoWhileLoop (value) @@ -1661,14 +1660,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map Unit) = - IrReturnableBlockImpl(startOffset, endOffset, type, symbol, null, + KonanIrReturnableBlockImpl(startOffset, endOffset, type, symbol, null, IrBlockBuilder(context, scope, startOffset, endOffset, null, type) .block(body).statements) } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt index 85a4fa7ddb2..8331d29282f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt @@ -17,8 +17,9 @@ import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride +import org.jetbrains.kotlin.backend.konan.ir.KonanIrReturnableBlockImpl import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass -import org.jetbrains.kotlin.backend.konan.irasdescriptors.fileEntry +import org.jetbrains.kotlin.backend.konan.irasdescriptors.file import org.jetbrains.kotlin.backend.konan.irasdescriptors.isInlineParameter import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -33,7 +34,6 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl @@ -118,7 +118,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid } } - private fun inlineFunction(callSite: IrCall, callee: IrFunction): IrReturnableBlockImpl { + private fun inlineFunction(callSite: IrCall, callee: IrFunction): KonanIrReturnableBlockImpl { val copiedCallee = copyIrElement.copy(callee) as IrFunction val evaluationStatements = evaluateArguments(callSite, copiedCallee) @@ -149,7 +149,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid } } - val sourceFileName = callee.fileEntry.name + val sourceFile = callee.file val transformer = ParameterSubstitutor() statements.transform { it.transform(transformer, data = null) } @@ -158,14 +158,14 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid val isCoroutineIntrinsicCall = callSite.descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn( context.config.configuration.languageVersionSettings) - return IrReturnableBlockImpl( + return KonanIrReturnableBlockImpl( startOffset = startOffset, endOffset = endOffset, type = callSite.type, symbol = irReturnableBlockSymbol, origin = if (isCoroutineIntrinsicCall) CoroutineIntrinsicLambdaOrigin else null, statements = statements, - sourceFileName = sourceFileName + sourceFile = sourceFile ).apply { transformChildrenVoid(object : IrElementTransformerVoid() { override fun visitReturn(expression: IrReturn): IrExpression { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt index 2156c122ddb..7d4ee1ef507 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.isInterface import org.jetbrains.kotlin.backend.konan.ir.IrPrivateClassReferenceImpl import org.jetbrains.kotlin.backend.konan.ir.IrPrivateFunctionCall import org.jetbrains.kotlin.backend.konan.ir.IrPrivateFunctionCallImpl +import org.jetbrains.kotlin.backend.konan.ir.KonanIrReturnableBlockImpl import org.jetbrains.kotlin.backend.konan.irasdescriptors.getErasedTypeClass import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.IrElement @@ -1374,6 +1375,7 @@ internal object Devirtualization { } return when (expression) { is IrReturnableBlock -> { + check(expression is KonanIrReturnableBlockImpl) // TODO: need to obtain IrFile rather than just sourceFileName val foldedReturnableBlockValues = returnableBlockValues[expression]!!.associate { it to fold(it, coercion, cast, false) } @@ -1385,14 +1387,14 @@ internal object Devirtualization { val oldSymbol = expression.symbol val newSymbol = IrReturnableBlockSymbolImpl(expression.descriptor) val transformedReturnableBlock = with(expression) { - IrReturnableBlockImpl( + KonanIrReturnableBlockImpl( startOffset = startOffset, endOffset = endOffset, type = coercion.type, symbol = newSymbol, origin = origin, statements = statements, - sourceFileName = sourceFileName) + sourceFile = sourceFile) } transformedReturnableBlock.transformChildrenVoid(object: IrElementTransformerVoid() { override fun visitExpression(expression: IrExpression): IrExpression { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleSerializer.kt index 65e44cf5cc2..b276d446ed6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleSerializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleSerializer.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.konan.descriptors.findTopLevelDeclaration import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember import org.jetbrains.kotlin.backend.konan.descriptors.isSerializableExpectClass +import org.jetbrains.kotlin.backend.konan.ir.lineStartOffsets import org.jetbrains.kotlin.backend.konan.library.SerializedIr import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind.* @@ -1046,6 +1047,7 @@ internal class IrModuleSerializer( fun serializeFileEntry(entry: SourceManager.FileEntry) = KonanIr.FileEntry.newBuilder() .setName(serializeString(entry.name)) + .addAllLineStartOffsets(entry.lineStartOffsets.asIterable()) .build() val topLevelDeclarations = mutableMapOf() @@ -1053,7 +1055,7 @@ internal class IrModuleSerializer( fun serializeIrFile(file: IrFile): KonanIr.IrFile { val proto = KonanIr.IrFile.newBuilder() .setFileEntry(serializeFileEntry(file.fileEntry)) - .setFqName(file.fqName.toString()) + .setFqName(serializeString(file.fqName.toString())) file.declarations.forEach { if (it is IrTypeAlias) return@forEach diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto index 29efff9f644..7539b3037a2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto @@ -80,15 +80,15 @@ message IrDeclarationContainer { repeated IrDeclaration declaration = 1; } -message FileEntry { // TODO: extend me. +message FileEntry { required String name = 1; + repeated int32 line_start_offsets = 2; } message IrFile { repeated UniqId declaration_id = 1; required FileEntry file_entry = 2; - // TODO: we need a better string management. See metadata serialization as an example. - required string fq_name = 3; + required String fq_name = 3; } message IrModule { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleDeserializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleDeserializer.kt index d7dde8a6da7..2b7db51ac75 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleDeserializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleDeserializer.kt @@ -310,10 +310,13 @@ class KonanIrModuleDeserializer( } fun deserializeIrFile(fileProto: KonanIr.IrFile, moduleDescriptor: ModuleDescriptor, deserializeAllDeclarations: Boolean): IrFile { - val fileEntry = NaiveSourceBasedFileEntryImpl(deserializeString(fileProto.fileEntry.name)) + val fileEntry = NaiveSourceBasedFileEntryImpl( + deserializeString(fileProto.fileEntry.name), + fileProto.fileEntry.lineStartOffsetsList.toIntArray() + ) // TODO: we need to store "" in protobuf, I suppose. Or better yet, reuse fqname storage from metadata. - val fqName = if (fileProto.fqName == "") FqName.ROOT else FqName(fileProto.fqName) + val fqName = deserializeString(fileProto.fqName).let { if (it == "") FqName.ROOT else FqName(it) } val packageFragmentDescriptor = EmptyPackageFragmentDescriptor(moduleDescriptor, fqName)