Refactor klib serializer/deserializer
This commit is contained in:
+182
@@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.common.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||||
|
import org.jetbrains.kotlin.library.IrLibrary
|
||||||
|
import org.jetbrains.kotlin.protobuf.CodedInputStream
|
||||||
|
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile
|
||||||
|
|
||||||
|
abstract class BasicIrModuleDeserializer(
|
||||||
|
val linker: KotlinIrLinker,
|
||||||
|
moduleDescriptor: ModuleDescriptor,
|
||||||
|
override val klib: IrLibrary,
|
||||||
|
override val strategy: DeserializationStrategy,
|
||||||
|
private val containsErrorCode: Boolean = false
|
||||||
|
) :
|
||||||
|
IrModuleDeserializer(moduleDescriptor) {
|
||||||
|
|
||||||
|
private val fileToDeserializerMap = mutableMapOf<IrFile, IrFileDeserializer>()
|
||||||
|
|
||||||
|
private val moduleDeserializationState = ModuleDeserializationState(linker, this)
|
||||||
|
|
||||||
|
internal val moduleReversedFileIndex = mutableMapOf<IdSignature, FileDeserializationState>()
|
||||||
|
|
||||||
|
override val moduleDependencies by lazy {
|
||||||
|
moduleDescriptor.allDependencyModules.filter { it != moduleDescriptor }.map { linker.resolveModuleDeserializer(it, null) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun init(delegate: IrModuleDeserializer) {
|
||||||
|
val fileCount = klib.fileCount()
|
||||||
|
|
||||||
|
val files = ArrayList<IrFile>(fileCount)
|
||||||
|
|
||||||
|
for (i in 0 until fileCount) {
|
||||||
|
val fileStream = klib.file(i).codedInputStream
|
||||||
|
val fileProto = ProtoFile.parseFrom(fileStream, ExtensionRegistryLite.newInstance())
|
||||||
|
files.add(deserializeIrFile(fileProto, i, delegate, containsErrorCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
moduleFragment.files.addAll(files)
|
||||||
|
|
||||||
|
fileToDeserializerMap.values.forEach { it.symbolDeserializer.deserializeExpectActualMapping() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrSymbolDeserializer.deserializeExpectActualMapping() {
|
||||||
|
actuals.forEach {
|
||||||
|
val expectSymbol = parseSymbolData(it.expectSymbol)
|
||||||
|
val actualSymbol = parseSymbolData(it.actualSymbol)
|
||||||
|
|
||||||
|
val expect = deserializeIdSignature(expectSymbol.signatureId)
|
||||||
|
val actual = deserializeIdSignature(actualSymbol.signatureId)
|
||||||
|
|
||||||
|
assert(linker.expectUniqIdToActualUniqId[expect] == null) {
|
||||||
|
"Expect signature $expect is already actualized by ${linker.expectUniqIdToActualUniqId[expect]}, while we try to record $actual"
|
||||||
|
}
|
||||||
|
linker.expectUniqIdToActualUniqId[expect] = actual
|
||||||
|
// Non-null only for topLevel declarations.
|
||||||
|
findModuleDeserializerForTopLevelId(actual)?.let { md -> linker.topLevelActualUniqItToDeserializer[actual] = md }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun referenceSimpleFunctionByLocalSignature(file: IrFile, idSignature: IdSignature) : IrSimpleFunctionSymbol =
|
||||||
|
fileToDeserializerMap[file]?.symbolDeserializer?.referenceSimpleFunctionByLocalSignature(idSignature)
|
||||||
|
?: error("No deserializer for file $file in module ${moduleDescriptor.name}")
|
||||||
|
|
||||||
|
override fun referencePropertyByLocalSignature(file: IrFile, idSignature: IdSignature): IrPropertySymbol =
|
||||||
|
fileToDeserializerMap[file]?.symbolDeserializer?.referencePropertyByLocalSignature(idSignature)
|
||||||
|
?: error("No deserializer for file $file in module ${moduleDescriptor.name}")
|
||||||
|
|
||||||
|
// TODO: fix to topLevel checker
|
||||||
|
override fun contains(idSig: IdSignature): Boolean = idSig in moduleReversedFileIndex
|
||||||
|
|
||||||
|
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||||
|
assert(idSig.isPublic)
|
||||||
|
|
||||||
|
val topLevelSignature = idSig.topLevelSignature()
|
||||||
|
val fileLocalDeserializationState = moduleReversedFileIndex[topLevelSignature]
|
||||||
|
?: error("No file for $topLevelSignature (@ $idSig) in module $moduleDescriptor")
|
||||||
|
|
||||||
|
fileLocalDeserializationState.addIdSignature(topLevelSignature)
|
||||||
|
moduleDeserializationState.enqueueFile(fileLocalDeserializationState)
|
||||||
|
|
||||||
|
return fileLocalDeserializationState.fileDeserializer.symbolDeserializer.deserializeIrSymbol(idSig, symbolKind).also {
|
||||||
|
linker.deserializedSymbols.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, linker.builtIns, emptyList())
|
||||||
|
|
||||||
|
private fun deserializeIrFile(fileProto: ProtoFile, fileIndex: Int, moduleDeserializer: IrModuleDeserializer, allowErrorNodes: Boolean): IrFile {
|
||||||
|
|
||||||
|
val fileReader = IrLibraryFileFromKlib(moduleDeserializer.klib, fileIndex)
|
||||||
|
val file = fileReader.createFile(moduleDescriptor, fileProto)
|
||||||
|
|
||||||
|
val fileDeserializationState = FileDeserializationState(
|
||||||
|
linker,
|
||||||
|
file,
|
||||||
|
fileReader,
|
||||||
|
fileProto,
|
||||||
|
strategy.needBodies,
|
||||||
|
allowErrorNodes,
|
||||||
|
strategy.inlineBodies,
|
||||||
|
moduleDeserializer,
|
||||||
|
linker::handleNoModuleDeserializerFound,
|
||||||
|
)
|
||||||
|
|
||||||
|
fileToDeserializerMap[file] = fileDeserializationState.fileDeserializer
|
||||||
|
|
||||||
|
val topLevelDeclarations = fileDeserializationState.fileDeserializer.reversedSignatureIndex.keys
|
||||||
|
topLevelDeclarations.forEach {
|
||||||
|
moduleReversedFileIndex.putIfAbsent(it, fileDeserializationState) // TODO Why not simple put?
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strategy.theWholeWorld) {
|
||||||
|
fileDeserializationState.enqueueAllDeclarations()
|
||||||
|
}
|
||||||
|
if (strategy.theWholeWorld || strategy.explicitlyExported) {
|
||||||
|
moduleDeserializationState.enqueueFile(fileDeserializationState)
|
||||||
|
}
|
||||||
|
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO useless
|
||||||
|
override fun addModuleReachableTopLevel(idSig: IdSignature) {
|
||||||
|
moduleDeserializationState.addIdSignature(idSig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ModuleDeserializationState(val linker: KotlinIrLinker, val moduleDeserializer: BasicIrModuleDeserializer) {
|
||||||
|
private val filesWithPendingTopLevels = mutableSetOf<FileDeserializationState>()
|
||||||
|
|
||||||
|
fun enqueueFile(fileDeserializationState: FileDeserializationState) {
|
||||||
|
filesWithPendingTopLevels.add(fileDeserializationState)
|
||||||
|
linker.modulesWithReachableTopLevels.add(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addIdSignature(key: IdSignature) {
|
||||||
|
val fileLocalDeserializationState = moduleDeserializer.moduleReversedFileIndex[key] ?: error("No file found for key $key")
|
||||||
|
fileLocalDeserializationState.addIdSignature(key)
|
||||||
|
|
||||||
|
enqueueFile(fileLocalDeserializationState)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserializeReachableDeclarations() {
|
||||||
|
while (filesWithPendingTopLevels.isNotEmpty()) {
|
||||||
|
val pendingFileDeserializationState = filesWithPendingTopLevels.first()
|
||||||
|
|
||||||
|
pendingFileDeserializationState.fileDeserializer.deserializeFileImplicitDataIfFirstUse()
|
||||||
|
pendingFileDeserializationState.deserializeAllFileReachableTopLevel()
|
||||||
|
|
||||||
|
filesWithPendingTopLevels.remove(pendingFileDeserializationState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = moduleDeserializer.klib.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrModuleDeserializer.findModuleDeserializerForTopLevelId(idSignature: IdSignature): IrModuleDeserializer? {
|
||||||
|
if (idSignature in this) return this
|
||||||
|
return moduleDependencies.firstOrNull { idSignature in it }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val ByteArray.codedInputStream: CodedInputStream
|
||||||
|
get() {
|
||||||
|
val codedInputStream = CodedInputStream.newInstance(this)
|
||||||
|
codedInputStream.setRecursionLimit(65535) // The default 64 is blatantly not enough for IR.
|
||||||
|
return codedInputStream
|
||||||
|
}
|
||||||
-4
@@ -100,10 +100,6 @@ class CurrentModuleWithICDeserializer(
|
|||||||
icDeserializer.addModuleReachableTopLevel(idSig)
|
icDeserializer.addModuleReachableTopLevel(idSig)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun deserializeReachableDeclarations() {
|
|
||||||
icDeserializer.deserializeReachableDeclarations()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DeclarationDescriptor.isDirtyDescriptor(): Boolean {
|
private fun DeclarationDescriptor.isDirtyDescriptor(): Boolean {
|
||||||
if (this is PropertyAccessorDescriptor) return correspondingProperty.isDirtyDescriptor()
|
if (this is PropertyAccessorDescriptor) return correspondingProperty.isDirtyDescriptor()
|
||||||
// Since descriptors for FO methods of `kotlin.Any` (toString, equals, hashCode) are Deserialized even in
|
// Since descriptors for FO methods of `kotlin.Any` (toString, equals, hashCode) are Deserialized even in
|
||||||
|
|||||||
+787
@@ -0,0 +1,787 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.common.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.encodings.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConst.ValueCase.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrOperation.OperationCase.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement.StatementCase
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrVarargElement.VarargElementCase
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlock as ProtoBlock
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlockBody as ProtoBlockBody
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBranch as ProtoBranch
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBreak as ProtoBreak
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrCall as ProtoCall
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrCatch as ProtoCatch
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrClassReference as ProtoClassReference
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrComposite as ProtoComposite
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConst as ProtoConst
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConstructorCall as ProtoConstructorCall
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrContinue as ProtoContinue
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDelegatingConstructorCall as ProtoDelegatingConstructorCall
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDoWhile as ProtoDoWhile
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicMemberExpression as ProtoDynamicMemberExpression
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicOperatorExpression as ProtoDynamicOperatorExpression
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrEnumConstructorCall as ProtoEnumConstructorCall
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunctionExpression as ProtoFunctionExpression
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorExpression as ProtoErrorExpression
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorCallExpression as ProtoErrorCallExpression
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunctionReference as ProtoFunctionReference
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetClass as ProtoGetClass
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetEnumValue as ProtoGetEnumValue
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetField as ProtoGetField
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetObject as ProtoGetObject
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetValue as ProtoGetValue
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrInstanceInitializerCall as ProtoInstanceInitializerCall
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrLocalDelegatedPropertyReference as ProtoLocalDelegatedPropertyReference
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrOperation as ProtoOperation
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrPropertyReference as ProtoPropertyReference
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrReturn as ProtoReturn
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSetField as ProtoSetField
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSetValue as ProtoSetValue
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSpreadElement as ProtoSpreadElement
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement as ProtoStatement
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrStringConcat as ProtoStringConcat
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSyntheticBody as ProtoSyntheticBody
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSyntheticBodyKind as ProtoSyntheticBodyKind
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrThrow as ProtoThrow
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTry as ProtoTry
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeOp as ProtoTypeOp
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeOperator as ProtoTypeOperator
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrVararg as ProtoVararg
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrVarargElement as ProtoVarargElement
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrWhen as ProtoWhen
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrWhile as ProtoWhile
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.Loop as ProtoLoop
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.MemberAccessCommon as ProtoMemberAccessCommon
|
||||||
|
|
||||||
|
class IrBodyDeserializer(
|
||||||
|
private val builtIns: IrBuiltIns,
|
||||||
|
private val allowErrorNodes: Boolean,
|
||||||
|
private val irFactory: IrFactory,
|
||||||
|
private val fileReader: IrLibraryFile,
|
||||||
|
private val declarationDeserializer: IrDeclarationDeserializer,
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val fileLoops = mutableMapOf<Int, IrLoop>()
|
||||||
|
|
||||||
|
private fun deserializeLoopHeader(loopIndex: Int, loopBuilder: () -> IrLoop): IrLoop =
|
||||||
|
fileLoops.getOrPut(loopIndex, loopBuilder)
|
||||||
|
|
||||||
|
private fun deserializeBlockBody(
|
||||||
|
proto: ProtoBlockBody,
|
||||||
|
start: Int, end: Int
|
||||||
|
): IrBlockBody {
|
||||||
|
|
||||||
|
val statements = mutableListOf<IrStatement>()
|
||||||
|
|
||||||
|
val statementProtos = proto.statementList
|
||||||
|
statementProtos.forEach {
|
||||||
|
statements.add(deserializeStatement(it) as IrStatement)
|
||||||
|
}
|
||||||
|
|
||||||
|
return irFactory.createBlockBody(start, end, statements)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeBranch(proto: ProtoBranch, start: Int, end: Int): IrBranch {
|
||||||
|
|
||||||
|
val condition = deserializeExpression(proto.condition)
|
||||||
|
val result = deserializeExpression(proto.result)
|
||||||
|
|
||||||
|
return IrBranchImpl(start, end, condition, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeCatch(proto: ProtoCatch, start: Int, end: Int): IrCatch {
|
||||||
|
val catchParameter = declarationDeserializer.deserializeIrVariable(proto.catchParameter)
|
||||||
|
val result = deserializeExpression(proto.result)
|
||||||
|
|
||||||
|
return IrCatchImpl(start, end, catchParameter, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeSyntheticBody(proto: ProtoSyntheticBody, start: Int, end: Int): IrSyntheticBody {
|
||||||
|
val kind = when (proto.kind!!) {
|
||||||
|
ProtoSyntheticBodyKind.ENUM_VALUES -> IrSyntheticBodyKind.ENUM_VALUES
|
||||||
|
ProtoSyntheticBodyKind.ENUM_VALUEOF -> IrSyntheticBodyKind.ENUM_VALUEOF
|
||||||
|
}
|
||||||
|
return IrSyntheticBodyImpl(start, end, kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun deserializeStatement(proto: ProtoStatement): IrElement {
|
||||||
|
val coordinates = BinaryCoordinates.decode(proto.coordinates)
|
||||||
|
val start = coordinates.startOffset
|
||||||
|
val end = coordinates.endOffset
|
||||||
|
val element = when (proto.statementCase) {
|
||||||
|
StatementCase.BLOCK_BODY //proto.hasBlockBody()
|
||||||
|
-> deserializeBlockBody(proto.blockBody, start, end)
|
||||||
|
StatementCase.BRANCH //proto.hasBranch()
|
||||||
|
-> deserializeBranch(proto.branch, start, end)
|
||||||
|
StatementCase.CATCH //proto.hasCatch()
|
||||||
|
-> deserializeCatch(proto.catch, start, end)
|
||||||
|
StatementCase.DECLARATION // proto.hasDeclaration()
|
||||||
|
-> declarationDeserializer.deserializeDeclaration(proto.declaration)
|
||||||
|
StatementCase.EXPRESSION // proto.hasExpression()
|
||||||
|
-> deserializeExpression(proto.expression)
|
||||||
|
StatementCase.SYNTHETIC_BODY // proto.hasSyntheticBody()
|
||||||
|
-> deserializeSyntheticBody(proto.syntheticBody, start, end)
|
||||||
|
else
|
||||||
|
-> TODO("Statement deserialization not implemented: ${proto.statementCase}")
|
||||||
|
}
|
||||||
|
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeBlock(proto: ProtoBlock, start: Int, end: Int, type: IrType): IrBlock {
|
||||||
|
val statements = mutableListOf<IrStatement>()
|
||||||
|
val statementProtos = proto.statementList
|
||||||
|
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
|
||||||
|
|
||||||
|
statementProtos.forEach {
|
||||||
|
statements.add(deserializeStatement(it) as IrStatement)
|
||||||
|
}
|
||||||
|
|
||||||
|
return IrBlockImpl(start, end, type, origin, statements)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeMemberAccessCommon(access: IrMemberAccessExpression<*>, proto: ProtoMemberAccessCommon) {
|
||||||
|
|
||||||
|
proto.valueArgumentList.mapIndexed { i, arg ->
|
||||||
|
if (arg.hasExpression()) {
|
||||||
|
val expr = deserializeExpression(arg.expression)
|
||||||
|
access.putValueArgument(i, expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proto.typeArgumentList.mapIndexed { i, arg ->
|
||||||
|
access.putTypeArgument(i, declarationDeserializer.deserializeIrType(arg))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proto.hasDispatchReceiver()) {
|
||||||
|
access.dispatchReceiver = deserializeExpression(proto.dispatchReceiver)
|
||||||
|
}
|
||||||
|
if (proto.hasExtensionReceiver()) {
|
||||||
|
access.extensionReceiver = deserializeExpression(proto.extensionReceiver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeClassReference(
|
||||||
|
proto: ProtoClassReference,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
type: IrType
|
||||||
|
): IrClassReference {
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.classSymbol) as IrClassifierSymbol
|
||||||
|
val classType = declarationDeserializer.deserializeIrType(proto.classType)
|
||||||
|
/** TODO: [createClassifierSymbolForClassReference] is internal function */
|
||||||
|
return IrClassReferenceImpl(start, end, type, symbol, classType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserializeAnnotation(proto: ProtoConstructorCall): IrConstructorCall {
|
||||||
|
return deserializeConstructorCall(proto, 0, 0, builtIns.unitType) // TODO: need a proper deserialization here
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserializeConstructorCall(proto: ProtoConstructorCall, start: Int, end: Int, type: IrType): IrConstructorCall {
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrConstructorSymbol
|
||||||
|
return IrConstructorCallImpl(
|
||||||
|
start, end, type,
|
||||||
|
symbol, typeArgumentsCount = proto.memberAccess.typeArgumentCount,
|
||||||
|
constructorTypeArgumentsCount = proto.constructorTypeArgumentsCount,
|
||||||
|
valueArgumentsCount = proto.memberAccess.valueArgumentCount
|
||||||
|
).also {
|
||||||
|
deserializeMemberAccessCommon(it, proto.memberAccess)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeCall(proto: ProtoCall, start: Int, end: Int, type: IrType): IrCall {
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrSimpleFunctionSymbol
|
||||||
|
|
||||||
|
val superSymbol = if (proto.hasSuper()) {
|
||||||
|
declarationDeserializer.deserializeIrSymbolAndRemap(proto.`super`) as IrClassSymbol
|
||||||
|
} else null
|
||||||
|
|
||||||
|
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
|
||||||
|
|
||||||
|
val call: IrCall =
|
||||||
|
// TODO: implement the last three args here.
|
||||||
|
IrCallImpl(
|
||||||
|
start, end, type,
|
||||||
|
symbol, proto.memberAccess.typeArgumentCount,
|
||||||
|
proto.memberAccess.valueArgumentList.size,
|
||||||
|
origin,
|
||||||
|
superSymbol
|
||||||
|
)
|
||||||
|
deserializeMemberAccessCommon(call, proto.memberAccess)
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeComposite(proto: ProtoComposite, start: Int, end: Int, type: IrType): IrComposite {
|
||||||
|
val statements = mutableListOf<IrStatement>()
|
||||||
|
val statementProtos = proto.statementList
|
||||||
|
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
|
||||||
|
|
||||||
|
statementProtos.forEach {
|
||||||
|
statements.add(deserializeStatement(it) as IrStatement)
|
||||||
|
}
|
||||||
|
return IrCompositeImpl(start, end, type, origin, statements)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeDelegatingConstructorCall(
|
||||||
|
proto: ProtoDelegatingConstructorCall,
|
||||||
|
start: Int,
|
||||||
|
end: Int
|
||||||
|
): IrDelegatingConstructorCall {
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrConstructorSymbol
|
||||||
|
val call = IrDelegatingConstructorCallImpl(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
builtIns.unitType,
|
||||||
|
symbol,
|
||||||
|
proto.memberAccess.typeArgumentCount,
|
||||||
|
proto.memberAccess.valueArgumentCount
|
||||||
|
)
|
||||||
|
|
||||||
|
deserializeMemberAccessCommon(call, proto.memberAccess)
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun deserializeEnumConstructorCall(
|
||||||
|
proto: ProtoEnumConstructorCall,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
): IrEnumConstructorCall {
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrConstructorSymbol
|
||||||
|
val call = IrEnumConstructorCallImpl(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
builtIns.unitType,
|
||||||
|
symbol,
|
||||||
|
proto.memberAccess.typeArgumentCount,
|
||||||
|
proto.memberAccess.valueArgumentCount
|
||||||
|
)
|
||||||
|
deserializeMemberAccessCommon(call, proto.memberAccess)
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeFunctionExpression(
|
||||||
|
functionExpression: ProtoFunctionExpression,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
type: IrType
|
||||||
|
) =
|
||||||
|
IrFunctionExpressionImpl(
|
||||||
|
start, end, type,
|
||||||
|
declarationDeserializer.deserializeIrFunction(functionExpression.function),
|
||||||
|
deserializeIrStatementOrigin(functionExpression.originName)
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun deserializeErrorExpression(
|
||||||
|
proto: ProtoErrorExpression,
|
||||||
|
start: Int, end: Int, type: IrType
|
||||||
|
): IrErrorExpression {
|
||||||
|
require(allowErrorNodes) {
|
||||||
|
"IrErrorExpression($start, $end, \"${fileReader.deserializeString(proto.description)}\") found but error code is not allowed"
|
||||||
|
}
|
||||||
|
return IrErrorExpressionImpl(start, end, type, fileReader.deserializeString(proto.description))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeErrorCallExpression(
|
||||||
|
proto: ProtoErrorCallExpression,
|
||||||
|
start: Int, end: Int, type: IrType
|
||||||
|
): IrErrorCallExpression {
|
||||||
|
require(allowErrorNodes) {
|
||||||
|
"IrErrorCallExpressionImpl($start, $end, \"${fileReader.deserializeString(proto.description)}\") found but error code is not allowed"
|
||||||
|
}
|
||||||
|
return IrErrorCallExpressionImpl(start, end, type, fileReader.deserializeString(proto.description)).apply {
|
||||||
|
if (proto.hasReceiver()) {
|
||||||
|
explicitReceiver = deserializeExpression(proto.receiver)
|
||||||
|
}
|
||||||
|
proto.valueArgumentList.forEach {
|
||||||
|
addArgument(deserializeExpression(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeFunctionReference(
|
||||||
|
proto: ProtoFunctionReference,
|
||||||
|
start: Int, end: Int, type: IrType
|
||||||
|
): IrFunctionReference {
|
||||||
|
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrFunctionSymbol
|
||||||
|
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
|
||||||
|
val reflectionTarget =
|
||||||
|
if (proto.hasReflectionTargetSymbol()) declarationDeserializer.deserializeIrSymbolAndRemap(proto.reflectionTargetSymbol) as IrFunctionSymbol else null
|
||||||
|
val callable = IrFunctionReferenceImpl(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
type,
|
||||||
|
symbol,
|
||||||
|
proto.memberAccess.typeArgumentCount,
|
||||||
|
proto.memberAccess.valueArgumentCount,
|
||||||
|
reflectionTarget,
|
||||||
|
origin
|
||||||
|
)
|
||||||
|
deserializeMemberAccessCommon(callable, proto.memberAccess)
|
||||||
|
|
||||||
|
return callable
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeGetClass(proto: ProtoGetClass, start: Int, end: Int, type: IrType): IrGetClass {
|
||||||
|
val argument = deserializeExpression(proto.argument)
|
||||||
|
return IrGetClassImpl(start, end, type, argument)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeGetField(proto: ProtoGetField, start: Int, end: Int, type: IrType): IrGetField {
|
||||||
|
val access = proto.fieldAccess
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(access.symbol) as IrFieldSymbol
|
||||||
|
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
|
||||||
|
|
||||||
|
val superQualifier = if (access.hasSuper()) {
|
||||||
|
declarationDeserializer.deserializeIrSymbolAndRemap(access.symbol) as IrClassSymbol
|
||||||
|
} else null
|
||||||
|
val receiver = if (access.hasReceiver()) {
|
||||||
|
deserializeExpression(access.receiver)
|
||||||
|
} else null
|
||||||
|
|
||||||
|
return IrGetFieldImpl(start, end, symbol, type, receiver, origin, superQualifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeGetValue(proto: ProtoGetValue, start: Int, end: Int, type: IrType): IrGetValue {
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrValueSymbol
|
||||||
|
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
|
||||||
|
// TODO: origin!
|
||||||
|
return IrGetValueImpl(start, end, type, symbol, origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeGetEnumValue(
|
||||||
|
proto: ProtoGetEnumValue,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
type: IrType
|
||||||
|
): IrGetEnumValue {
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrEnumEntrySymbol
|
||||||
|
return IrGetEnumValueImpl(start, end, type, symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeGetObject(
|
||||||
|
proto: ProtoGetObject,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
type: IrType
|
||||||
|
): IrGetObjectValue {
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrClassSymbol
|
||||||
|
return IrGetObjectValueImpl(start, end, type, symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeInstanceInitializerCall(
|
||||||
|
proto: ProtoInstanceInitializerCall,
|
||||||
|
start: Int,
|
||||||
|
end: Int
|
||||||
|
): IrInstanceInitializerCall {
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrClassSymbol
|
||||||
|
return IrInstanceInitializerCallImpl(start, end, symbol, builtIns.unitType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrLocalDelegatedPropertyReference(
|
||||||
|
proto: ProtoLocalDelegatedPropertyReference,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
type: IrType
|
||||||
|
): IrLocalDelegatedPropertyReference {
|
||||||
|
|
||||||
|
val delegate = declarationDeserializer.deserializeIrSymbolAndRemap(proto.delegate) as IrVariableSymbol
|
||||||
|
val getter = declarationDeserializer.deserializeIrSymbolAndRemap(proto.getter) as IrSimpleFunctionSymbol
|
||||||
|
val setter = if (proto.hasSetter()) declarationDeserializer.deserializeIrSymbolAndRemap(proto.setter) as IrSimpleFunctionSymbol else null
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrLocalDelegatedPropertySymbol
|
||||||
|
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
|
||||||
|
|
||||||
|
return IrLocalDelegatedPropertyReferenceImpl(
|
||||||
|
start, end, type,
|
||||||
|
symbol,
|
||||||
|
delegate,
|
||||||
|
getter,
|
||||||
|
setter,
|
||||||
|
origin
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializePropertyReference(proto: ProtoPropertyReference, start: Int, end: Int, type: IrType): IrPropertyReference {
|
||||||
|
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrPropertySymbol
|
||||||
|
|
||||||
|
val field = if (proto.hasField()) declarationDeserializer.deserializeIrSymbolAndRemap(proto.field) as IrFieldSymbol else null
|
||||||
|
val getter = if (proto.hasGetter()) declarationDeserializer.deserializeIrSymbolAndRemap(proto.getter) as IrSimpleFunctionSymbol else null
|
||||||
|
val setter = if (proto.hasSetter()) declarationDeserializer.deserializeIrSymbolAndRemap(proto.setter) as IrSimpleFunctionSymbol else null
|
||||||
|
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
|
||||||
|
|
||||||
|
val callable = IrPropertyReferenceImpl(
|
||||||
|
start, end, type,
|
||||||
|
symbol,
|
||||||
|
proto.memberAccess.typeArgumentCount,
|
||||||
|
field,
|
||||||
|
getter,
|
||||||
|
setter,
|
||||||
|
origin
|
||||||
|
)
|
||||||
|
deserializeMemberAccessCommon(callable, proto.memberAccess)
|
||||||
|
return callable
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeReturn(proto: ProtoReturn, start: Int, end: Int): IrReturn {
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.returnTarget) as IrReturnTargetSymbol
|
||||||
|
val value = deserializeExpression(proto.value)
|
||||||
|
return IrReturnImpl(start, end, builtIns.nothingType, symbol, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeSetField(proto: ProtoSetField, start: Int, end: Int): IrSetField {
|
||||||
|
val access = proto.fieldAccess
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(access.symbol) as IrFieldSymbol
|
||||||
|
val superQualifier = if (access.hasSuper()) {
|
||||||
|
declarationDeserializer.deserializeIrSymbolAndRemap(access.symbol) as IrClassSymbol
|
||||||
|
} else null
|
||||||
|
val receiver = if (access.hasReceiver()) {
|
||||||
|
deserializeExpression(access.receiver)
|
||||||
|
} else null
|
||||||
|
val value = deserializeExpression(proto.value)
|
||||||
|
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
|
||||||
|
|
||||||
|
return IrSetFieldImpl(start, end, symbol, receiver, value, builtIns.unitType, origin, superQualifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeSetValue(proto: ProtoSetValue, start: Int, end: Int): IrSetValue {
|
||||||
|
val symbol = declarationDeserializer.deserializeIrSymbolAndRemap(proto.symbol) as IrVariableSymbol
|
||||||
|
val value = deserializeExpression(proto.value)
|
||||||
|
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
|
||||||
|
return IrSetValueImpl(start, end, builtIns.unitType, symbol, value, origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeSpreadElement(proto: ProtoSpreadElement): IrSpreadElement {
|
||||||
|
val expression = deserializeExpression(proto.expression)
|
||||||
|
val coordinates = BinaryCoordinates.decode(proto.coordinates)
|
||||||
|
return IrSpreadElementImpl(coordinates.startOffset, coordinates.endOffset, expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeStringConcat(proto: ProtoStringConcat, start: Int, end: Int, type: IrType): IrStringConcatenation {
|
||||||
|
val argumentProtos = proto.argumentList
|
||||||
|
val arguments = mutableListOf<IrExpression>()
|
||||||
|
|
||||||
|
argumentProtos.forEach {
|
||||||
|
arguments.add(deserializeExpression(it))
|
||||||
|
}
|
||||||
|
return IrStringConcatenationImpl(start, end, type, arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeThrow(proto: ProtoThrow, start: Int, end: Int): IrThrowImpl {
|
||||||
|
return IrThrowImpl(start, end, builtIns.nothingType, deserializeExpression(proto.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeTry(proto: ProtoTry, start: Int, end: Int, type: IrType): IrTryImpl {
|
||||||
|
val result = deserializeExpression(proto.result)
|
||||||
|
val catches = mutableListOf<IrCatch>()
|
||||||
|
proto.catchList.forEach {
|
||||||
|
catches.add(deserializeStatement(it) as IrCatch)
|
||||||
|
}
|
||||||
|
val finallyExpression =
|
||||||
|
if (proto.hasFinally()) deserializeExpression(proto.getFinally()) else null
|
||||||
|
return IrTryImpl(start, end, type, result, catches, finallyExpression)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeTypeOperator(operator: ProtoTypeOperator) = when (operator) {
|
||||||
|
ProtoTypeOperator.CAST ->
|
||||||
|
IrTypeOperator.CAST
|
||||||
|
ProtoTypeOperator.IMPLICIT_CAST ->
|
||||||
|
IrTypeOperator.IMPLICIT_CAST
|
||||||
|
ProtoTypeOperator.IMPLICIT_NOTNULL ->
|
||||||
|
IrTypeOperator.IMPLICIT_NOTNULL
|
||||||
|
ProtoTypeOperator.IMPLICIT_COERCION_TO_UNIT ->
|
||||||
|
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT
|
||||||
|
ProtoTypeOperator.IMPLICIT_INTEGER_COERCION ->
|
||||||
|
IrTypeOperator.IMPLICIT_INTEGER_COERCION
|
||||||
|
ProtoTypeOperator.SAFE_CAST ->
|
||||||
|
IrTypeOperator.SAFE_CAST
|
||||||
|
ProtoTypeOperator.INSTANCEOF ->
|
||||||
|
IrTypeOperator.INSTANCEOF
|
||||||
|
ProtoTypeOperator.NOT_INSTANCEOF ->
|
||||||
|
IrTypeOperator.NOT_INSTANCEOF
|
||||||
|
ProtoTypeOperator.SAM_CONVERSION ->
|
||||||
|
IrTypeOperator.SAM_CONVERSION
|
||||||
|
ProtoTypeOperator.IMPLICIT_DYNAMIC_CAST ->
|
||||||
|
IrTypeOperator.IMPLICIT_DYNAMIC_CAST
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeTypeOp(proto: ProtoTypeOp, start: Int, end: Int, type: IrType): IrTypeOperatorCall {
|
||||||
|
val operator = deserializeTypeOperator(proto.operator)
|
||||||
|
val operand = declarationDeserializer.deserializeIrType(proto.operand)//.brokenIr
|
||||||
|
val argument = deserializeExpression(proto.argument)
|
||||||
|
return IrTypeOperatorCallImpl(start, end, type, operator, operand, argument)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeVararg(proto: ProtoVararg, start: Int, end: Int, type: IrType): IrVararg {
|
||||||
|
val elementType = declarationDeserializer.deserializeIrType(proto.elementType)
|
||||||
|
|
||||||
|
val elements = mutableListOf<IrVarargElement>()
|
||||||
|
proto.elementList.forEach {
|
||||||
|
elements.add(deserializeVarargElement(it))
|
||||||
|
}
|
||||||
|
return IrVarargImpl(start, end, type, elementType, elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeVarargElement(element: ProtoVarargElement): IrVarargElement {
|
||||||
|
return when (element.varargElementCase) {
|
||||||
|
VarargElementCase.EXPRESSION
|
||||||
|
-> deserializeExpression(element.expression)
|
||||||
|
VarargElementCase.SPREAD_ELEMENT
|
||||||
|
-> deserializeSpreadElement(element.spreadElement)
|
||||||
|
else
|
||||||
|
-> TODO("Unexpected vararg element")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeWhen(proto: ProtoWhen, start: Int, end: Int, type: IrType): IrWhen {
|
||||||
|
val branches = mutableListOf<IrBranch>()
|
||||||
|
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
|
||||||
|
|
||||||
|
proto.branchList.forEach {
|
||||||
|
branches.add(deserializeStatement(it) as IrBranch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: provide some origin!
|
||||||
|
return IrWhenImpl(start, end, type, origin, branches)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeLoop(proto: ProtoLoop, loop: IrLoop): IrLoop {
|
||||||
|
val label = if (proto.hasLabel()) fileReader.deserializeString(proto.label) else null
|
||||||
|
val body = if (proto.hasBody()) deserializeExpression(proto.body) else null
|
||||||
|
val condition = deserializeExpression(proto.condition)
|
||||||
|
|
||||||
|
loop.label = label
|
||||||
|
loop.condition = condition
|
||||||
|
loop.body = body
|
||||||
|
|
||||||
|
return loop
|
||||||
|
}
|
||||||
|
|
||||||
|
// we create the loop before deserializing the body, so that
|
||||||
|
// IrBreak statements have something to put into 'loop' field.
|
||||||
|
private fun deserializeDoWhile(proto: ProtoDoWhile, start: Int, end: Int, type: IrType) =
|
||||||
|
deserializeLoop(
|
||||||
|
proto.loop,
|
||||||
|
deserializeLoopHeader(proto.loop.loopId) {
|
||||||
|
val origin = if (proto.loop.hasOriginName()) deserializeIrStatementOrigin(proto.loop.originName) else null
|
||||||
|
IrDoWhileLoopImpl(start, end, type, origin)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun deserializeWhile(proto: ProtoWhile, start: Int, end: Int, type: IrType) =
|
||||||
|
deserializeLoop(
|
||||||
|
proto.loop,
|
||||||
|
deserializeLoopHeader(proto.loop.loopId) {
|
||||||
|
val origin = if (proto.loop.hasOriginName()) deserializeIrStatementOrigin(proto.loop.originName) else null
|
||||||
|
IrWhileLoopImpl(start, end, type, origin)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun deserializeDynamicMemberExpression(
|
||||||
|
proto: ProtoDynamicMemberExpression,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
type: IrType
|
||||||
|
) =
|
||||||
|
IrDynamicMemberExpressionImpl(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
type,
|
||||||
|
fileReader.deserializeString(proto.memberName),
|
||||||
|
deserializeExpression(proto.receiver)
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun deserializeDynamicOperatorExpression(
|
||||||
|
proto: ProtoDynamicOperatorExpression,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
type: IrType
|
||||||
|
) =
|
||||||
|
IrDynamicOperatorExpressionImpl(start, end, type, deserializeDynamicOperator(proto.operator)).apply {
|
||||||
|
receiver = deserializeExpression(proto.receiver)
|
||||||
|
proto.argumentList.mapTo(arguments) { deserializeExpression(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeDynamicOperator(operator: ProtoDynamicOperatorExpression.IrDynamicOperator) =
|
||||||
|
when (operator) {
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.UNARY_PLUS -> IrDynamicOperator.UNARY_PLUS
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.UNARY_MINUS -> IrDynamicOperator.UNARY_MINUS
|
||||||
|
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.EXCL -> IrDynamicOperator.EXCL
|
||||||
|
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.PREFIX_INCREMENT -> IrDynamicOperator.PREFIX_INCREMENT
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.PREFIX_DECREMENT -> IrDynamicOperator.PREFIX_DECREMENT
|
||||||
|
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.POSTFIX_INCREMENT -> IrDynamicOperator.POSTFIX_INCREMENT
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.POSTFIX_DECREMENT -> IrDynamicOperator.POSTFIX_DECREMENT
|
||||||
|
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.BINARY_PLUS -> IrDynamicOperator.BINARY_PLUS
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.BINARY_MINUS -> IrDynamicOperator.BINARY_MINUS
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.MUL -> IrDynamicOperator.MUL
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.DIV -> IrDynamicOperator.DIV
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.MOD -> IrDynamicOperator.MOD
|
||||||
|
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.GT -> IrDynamicOperator.GT
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.LT -> IrDynamicOperator.LT
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.GE -> IrDynamicOperator.GE
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.LE -> IrDynamicOperator.LE
|
||||||
|
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.EQEQ -> IrDynamicOperator.EQEQ
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.EXCLEQ -> IrDynamicOperator.EXCLEQ
|
||||||
|
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.EQEQEQ -> IrDynamicOperator.EQEQEQ
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.EXCLEQEQ -> IrDynamicOperator.EXCLEQEQ
|
||||||
|
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.ANDAND -> IrDynamicOperator.ANDAND
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.OROR -> IrDynamicOperator.OROR
|
||||||
|
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.EQ -> IrDynamicOperator.EQ
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.PLUSEQ -> IrDynamicOperator.PLUSEQ
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.MINUSEQ -> IrDynamicOperator.MINUSEQ
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.MULEQ -> IrDynamicOperator.MULEQ
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.DIVEQ -> IrDynamicOperator.DIVEQ
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.MODEQ -> IrDynamicOperator.MODEQ
|
||||||
|
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.ARRAY_ACCESS -> IrDynamicOperator.ARRAY_ACCESS
|
||||||
|
|
||||||
|
ProtoDynamicOperatorExpression.IrDynamicOperator.INVOKE -> IrDynamicOperator.INVOKE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeBreak(proto: ProtoBreak, start: Int, end: Int, type: IrType): IrBreak {
|
||||||
|
val label = if (proto.hasLabel()) fileReader.deserializeString(proto.label) else null
|
||||||
|
val loopId = proto.loopId
|
||||||
|
val loop = deserializeLoopHeader(loopId) { error("break clause before loop header") }
|
||||||
|
val irBreak = IrBreakImpl(start, end, type, loop)
|
||||||
|
irBreak.label = label
|
||||||
|
|
||||||
|
return irBreak
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeContinue(proto: ProtoContinue, start: Int, end: Int, type: IrType): IrContinue {
|
||||||
|
val label = if (proto.hasLabel()) fileReader.deserializeString(proto.label) else null
|
||||||
|
val loopId = proto.loopId
|
||||||
|
val loop = deserializeLoopHeader(loopId) { error("continue clause before loop header") }
|
||||||
|
val irContinue = IrContinueImpl(start, end, type, loop)
|
||||||
|
irContinue.label = label
|
||||||
|
|
||||||
|
return irContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeConst(proto: ProtoConst, start: Int, end: Int, type: IrType): IrExpression =
|
||||||
|
when (proto.valueCase!!) {
|
||||||
|
NULL
|
||||||
|
-> IrConstImpl.constNull(start, end, type)
|
||||||
|
BOOLEAN
|
||||||
|
-> IrConstImpl.boolean(start, end, type, proto.boolean)
|
||||||
|
BYTE
|
||||||
|
-> IrConstImpl.byte(start, end, type, proto.byte.toByte())
|
||||||
|
CHAR
|
||||||
|
-> IrConstImpl.char(start, end, type, proto.char.toChar())
|
||||||
|
SHORT
|
||||||
|
-> IrConstImpl.short(start, end, type, proto.short.toShort())
|
||||||
|
INT
|
||||||
|
-> IrConstImpl.int(start, end, type, proto.int)
|
||||||
|
LONG
|
||||||
|
-> IrConstImpl.long(start, end, type, proto.long)
|
||||||
|
STRING
|
||||||
|
-> IrConstImpl.string(start, end, type, fileReader.deserializeString(proto.string))
|
||||||
|
FLOAT_BITS
|
||||||
|
-> IrConstImpl.float(start, end, type, Float.fromBits(proto.floatBits))
|
||||||
|
DOUBLE_BITS
|
||||||
|
-> IrConstImpl.double(start, end, type, Double.fromBits(proto.doubleBits))
|
||||||
|
VALUE_NOT_SET
|
||||||
|
-> error("Const deserialization error: ${proto.valueCase} ")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeOperation(proto: ProtoOperation, start: Int, end: Int, type: IrType): IrExpression =
|
||||||
|
when (proto.operationCase!!) {
|
||||||
|
BLOCK -> deserializeBlock(proto.block, start, end, type)
|
||||||
|
BREAK -> deserializeBreak(proto.`break`, start, end, type)
|
||||||
|
CLASS_REFERENCE -> deserializeClassReference(proto.classReference, start, end, type)
|
||||||
|
CALL -> deserializeCall(proto.call, start, end, type)
|
||||||
|
COMPOSITE -> deserializeComposite(proto.composite, start, end, type)
|
||||||
|
CONST -> deserializeConst(proto.const, start, end, type)
|
||||||
|
CONTINUE -> deserializeContinue(proto.`continue`, start, end, type)
|
||||||
|
DELEGATING_CONSTRUCTOR_CALL -> deserializeDelegatingConstructorCall(proto.delegatingConstructorCall, start, end)
|
||||||
|
DO_WHILE -> deserializeDoWhile(proto.doWhile, start, end, type)
|
||||||
|
ENUM_CONSTRUCTOR_CALL -> deserializeEnumConstructorCall(proto.enumConstructorCall, start, end)
|
||||||
|
FUNCTION_REFERENCE -> deserializeFunctionReference(proto.functionReference, start, end, type)
|
||||||
|
GET_ENUM_VALUE -> deserializeGetEnumValue(proto.getEnumValue, start, end, type)
|
||||||
|
GET_CLASS -> deserializeGetClass(proto.getClass, start, end, type)
|
||||||
|
GET_FIELD -> deserializeGetField(proto.getField, start, end, type)
|
||||||
|
GET_OBJECT -> deserializeGetObject(proto.getObject, start, end, type)
|
||||||
|
GET_VALUE -> deserializeGetValue(proto.getValue, start, end, type)
|
||||||
|
LOCAL_DELEGATED_PROPERTY_REFERENCE -> deserializeIrLocalDelegatedPropertyReference(
|
||||||
|
proto.localDelegatedPropertyReference,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
type
|
||||||
|
)
|
||||||
|
INSTANCE_INITIALIZER_CALL -> deserializeInstanceInitializerCall(proto.instanceInitializerCall, start, end)
|
||||||
|
PROPERTY_REFERENCE -> deserializePropertyReference(proto.propertyReference, start, end, type)
|
||||||
|
RETURN -> deserializeReturn(proto.`return`, start, end)
|
||||||
|
SET_FIELD -> deserializeSetField(proto.setField, start, end)
|
||||||
|
SET_VALUE -> deserializeSetValue(proto.setValue, start, end)
|
||||||
|
STRING_CONCAT -> deserializeStringConcat(proto.stringConcat, start, end, type)
|
||||||
|
THROW -> deserializeThrow(proto.`throw`, start, end)
|
||||||
|
TRY -> deserializeTry(proto.`try`, start, end, type)
|
||||||
|
TYPE_OP -> deserializeTypeOp(proto.typeOp, start, end, type)
|
||||||
|
VARARG -> deserializeVararg(proto.vararg, start, end, type)
|
||||||
|
WHEN -> deserializeWhen(proto.`when`, start, end, type)
|
||||||
|
WHILE -> deserializeWhile(proto.`while`, start, end, type)
|
||||||
|
DYNAMIC_MEMBER -> deserializeDynamicMemberExpression(proto.dynamicMember, start, end, type)
|
||||||
|
DYNAMIC_OPERATOR -> deserializeDynamicOperatorExpression(proto.dynamicOperator, start, end, type)
|
||||||
|
CONSTRUCTOR_CALL -> deserializeConstructorCall(proto.constructorCall, start, end, type)
|
||||||
|
FUNCTION_EXPRESSION -> deserializeFunctionExpression(proto.functionExpression, start, end, type)
|
||||||
|
ERROR_EXPRESSION -> deserializeErrorExpression(proto.errorExpression, start, end, type)
|
||||||
|
ERROR_CALL_EXPRESSION -> deserializeErrorCallExpression(proto.errorCallExpression, start, end, type)
|
||||||
|
OPERATION_NOT_SET -> error("Expression deserialization not implemented: ${proto.operationCase}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserializeExpression(proto: ProtoExpression): IrExpression {
|
||||||
|
val coordinates = BinaryCoordinates.decode(proto.coordinates)
|
||||||
|
val start = coordinates.startOffset
|
||||||
|
val end = coordinates.endOffset
|
||||||
|
val type = declarationDeserializer.deserializeIrType(proto.type)
|
||||||
|
val operation = proto.operation
|
||||||
|
val expression = deserializeOperation(operation, start, end, type)
|
||||||
|
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserializeIrStatementOrigin(protoName: Int): IrStatementOrigin {
|
||||||
|
return fileReader.deserializeString(protoName).let {
|
||||||
|
val componentPrefix = "COMPONENT_"
|
||||||
|
when {
|
||||||
|
it.startsWith(componentPrefix) -> {
|
||||||
|
IrStatementOrigin.COMPONENT_N.withIndex(it.removePrefix(componentPrefix).toInt())
|
||||||
|
}
|
||||||
|
else -> statementOriginIndex[it] ?: error("Unexpected statement origin: $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val allKnownStatementOrigins = IrStatementOrigin::class.nestedClasses.toList()
|
||||||
|
|
||||||
|
private val statementOriginIndex =
|
||||||
|
allKnownStatementOrigins.mapNotNull { it.objectInstance as? IrStatementOriginImpl }.associateBy { it.debugName }
|
||||||
|
}
|
||||||
|
}
|
||||||
+695
@@ -0,0 +1,695 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.common.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport
|
||||||
|
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
|
||||||
|
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideClassFilter
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.encodings.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration.DeclaratorCase.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrType.KindCase.*
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrPublicSymbolBase
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.protobuf.CodedInputStream
|
||||||
|
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrAnonymousInit as ProtoAnonymousInit
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrClass as ProtoClass
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConstructor as ProtoConstructor
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConstructorCall as ProtoConstructorCall
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclarationBase as ProtoDeclarationBase
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicType as ProtoDynamicType
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrEnumEntry as ProtoEnumEntry
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorType as ProtoErrorType
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrField as ProtoField
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunction as ProtoFunction
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunctionBase as ProtoFunctionBase
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorDeclaration as ProtoErrorDeclaration
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement as ProtoStatement
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrLocalDelegatedProperty as ProtoLocalDelegatedProperty
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrProperty as ProtoProperty
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSimpleType as ProtoSimpleType
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrType as ProtoType
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeAbbreviation as ProtoTypeAbbreviation
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeAlias as ProtoTypeAlias
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeParameter as ProtoTypeParameter
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrValueParameter as ProtoValueParameter
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrVariable as ProtoVariable
|
||||||
|
|
||||||
|
|
||||||
|
class IrDeclarationDeserializer(
|
||||||
|
builtIns: IrBuiltIns,
|
||||||
|
private val symbolTable: SymbolTable,
|
||||||
|
private val irFactory: IrFactory,
|
||||||
|
private val fileReader: IrLibraryFile,
|
||||||
|
file: IrFile,
|
||||||
|
private val allowErrorNodes: Boolean,
|
||||||
|
private val deserializeInlineFunctions: Boolean,
|
||||||
|
private var deserializeBodies: Boolean,
|
||||||
|
private val symbolDeserializer: IrSymbolDeserializer,
|
||||||
|
private val platformFakeOverrideClassFilter: FakeOverrideClassFilter,
|
||||||
|
private val fakeOverrideBuilder: FakeOverrideBuilder,
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val bodyDeserializer = IrBodyDeserializer(builtIns, allowErrorNodes, irFactory, fileReader, this)
|
||||||
|
|
||||||
|
private fun deserializeName(index: Int): Name {
|
||||||
|
val name = fileReader.deserializeString(index)
|
||||||
|
return Name.guessByFirstCharacter(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val irTypeCache = mutableMapOf<Int, IrType>()
|
||||||
|
|
||||||
|
private fun readType(index: Int): CodedInputStream =
|
||||||
|
fileReader.type(index).codedInputStream
|
||||||
|
|
||||||
|
private fun loadTypeProto(index: Int): ProtoType {
|
||||||
|
return ProtoType.parseFrom(readType(index), ExtensionRegistryLite.newInstance())
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun deserializeIrType(index: Int): IrType {
|
||||||
|
return irTypeCache.getOrPut(index) {
|
||||||
|
val typeData = loadTypeProto(index)
|
||||||
|
deserializeIrTypeData(typeData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrTypeArgument(proto: Long): IrTypeArgument {
|
||||||
|
val encoding = BinaryTypeProjection.decode(proto)
|
||||||
|
|
||||||
|
if (encoding.isStarProjection) return IrStarProjectionImpl
|
||||||
|
|
||||||
|
return makeTypeProjection(deserializeIrType(encoding.typeIndex), encoding.variance)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun deserializeAnnotations(annotations: List<ProtoConstructorCall>): List<IrConstructorCall> {
|
||||||
|
return annotations.map {
|
||||||
|
bodyDeserializer.deserializeAnnotation(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeSimpleType(proto: ProtoSimpleType): IrSimpleType {
|
||||||
|
val symbol = deserializeIrSymbolAndRemap(proto.classifier) as? IrClassifierSymbol
|
||||||
|
?: error("could not convert sym to ClassifierSymbol")
|
||||||
|
|
||||||
|
val arguments = proto.argumentList.map { deserializeIrTypeArgument(it) }
|
||||||
|
val annotations = deserializeAnnotations(proto.annotationList)
|
||||||
|
|
||||||
|
val result: IrSimpleType = IrSimpleTypeImpl(
|
||||||
|
null,
|
||||||
|
symbol,
|
||||||
|
proto.hasQuestionMark,
|
||||||
|
arguments,
|
||||||
|
annotations,
|
||||||
|
if (proto.hasAbbreviation()) deserializeTypeAbbreviation(proto.abbreviation) else null
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeTypeAbbreviation(proto: ProtoTypeAbbreviation): IrTypeAbbreviation =
|
||||||
|
IrTypeAbbreviationImpl(
|
||||||
|
deserializeIrSymbolAndRemap(proto.typeAlias).let {
|
||||||
|
it as? IrTypeAliasSymbol
|
||||||
|
?: error("IrTypeAliasSymbol expected: $it")
|
||||||
|
},
|
||||||
|
proto.hasQuestionMark,
|
||||||
|
proto.argumentList.map { deserializeIrTypeArgument(it) },
|
||||||
|
deserializeAnnotations(proto.annotationList)
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun deserializeDynamicType(proto: ProtoDynamicType): IrDynamicType {
|
||||||
|
val annotations = deserializeAnnotations(proto.annotationList)
|
||||||
|
return IrDynamicTypeImpl(null, annotations, Variance.INVARIANT)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeErrorType(proto: ProtoErrorType): IrErrorType {
|
||||||
|
require(allowErrorNodes) { "IrErrorType found but error code is not allowed" }
|
||||||
|
val annotations = deserializeAnnotations(proto.annotationList)
|
||||||
|
return IrErrorTypeImpl(null, annotations, Variance.INVARIANT)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrTypeData(proto: ProtoType): IrType {
|
||||||
|
return when (proto.kindCase) {
|
||||||
|
SIMPLE -> deserializeSimpleType(proto.simple)
|
||||||
|
DYNAMIC -> deserializeDynamicType(proto.dynamic)
|
||||||
|
ERROR -> deserializeErrorType(proto.error)
|
||||||
|
else -> error("Unexpected IrType kind: ${proto.kindCase}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var currentParent: IrDeclarationParent = file
|
||||||
|
|
||||||
|
private inline fun <T : IrDeclarationParent> T.usingParent(block: T.() -> Unit): T =
|
||||||
|
this.apply {
|
||||||
|
val oldParent = currentParent
|
||||||
|
currentParent = this
|
||||||
|
try {
|
||||||
|
block(this)
|
||||||
|
} finally {
|
||||||
|
currentParent = oldParent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delegating symbol maps to it's delegate only inside the declaration the symbol belongs to.
|
||||||
|
private val delegatedSymbolMap = mutableMapOf<IrSymbol, IrSymbol>()
|
||||||
|
|
||||||
|
internal fun deserializeIrSymbolAndRemap(code: Long): IrSymbol {
|
||||||
|
// TODO: could be simplified
|
||||||
|
return symbolDeserializer.deserializeIrSymbol(code).let {
|
||||||
|
delegatedSymbolMap[it] ?: it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun recordDelegatedSymbol(symbol: IrSymbol) {
|
||||||
|
if (symbol is IrDelegatingSymbol<*, *, *>) {
|
||||||
|
delegatedSymbolMap[symbol] = symbol.delegate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun eraseDelegatedSymbol(symbol: IrSymbol) {
|
||||||
|
if (symbol is IrDelegatingSymbol<*, *, *>) {
|
||||||
|
delegatedSymbolMap.remove(symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <T> withDeserializedIrDeclarationBase(
|
||||||
|
proto: ProtoDeclarationBase,
|
||||||
|
block: (IrSymbol, IdSignature, Int, Int, IrDeclarationOrigin, Long) -> T
|
||||||
|
): T where T : IrDeclaration, T : IrSymbolOwner {
|
||||||
|
val (s, uid) = symbolDeserializer.deserializeIrSymbolToDeclare(proto.symbol)
|
||||||
|
val coordinates = BinaryCoordinates.decode(proto.coordinates)
|
||||||
|
try {
|
||||||
|
recordDelegatedSymbol(s)
|
||||||
|
val result = block(
|
||||||
|
s,
|
||||||
|
uid,
|
||||||
|
coordinates.startOffset, coordinates.endOffset,
|
||||||
|
deserializeIrDeclarationOrigin(proto.originName), proto.flags
|
||||||
|
)
|
||||||
|
result.annotations += deserializeAnnotations(proto.annotationList)
|
||||||
|
result.parent = currentParent
|
||||||
|
return result
|
||||||
|
} finally {
|
||||||
|
eraseDelegatedSymbol(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrTypeParameter(proto: ProtoTypeParameter, index: Int, isGlobal: Boolean): IrTypeParameter {
|
||||||
|
val name = deserializeName(proto.name)
|
||||||
|
val coordinates = BinaryCoordinates.decode(proto.base.coordinates)
|
||||||
|
val flags = TypeParameterFlags.decode(proto.base.flags)
|
||||||
|
|
||||||
|
val factory = { symbol: IrTypeParameterSymbol ->
|
||||||
|
irFactory.createTypeParameter(
|
||||||
|
coordinates.startOffset,
|
||||||
|
coordinates.endOffset,
|
||||||
|
deserializeIrDeclarationOrigin(proto.base.originName),
|
||||||
|
symbol,
|
||||||
|
name,
|
||||||
|
index,
|
||||||
|
flags.isReified,
|
||||||
|
flags.variance
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val sig: IdSignature
|
||||||
|
val result = symbolTable.run {
|
||||||
|
if (isGlobal) {
|
||||||
|
val p = symbolDeserializer.deserializeIrSymbolToDeclare(proto.base.symbol)
|
||||||
|
val symbol = p.first as IrTypeParameterSymbol
|
||||||
|
sig = p.second
|
||||||
|
declareGlobalTypeParameter(sig, { symbol }, factory)
|
||||||
|
} else {
|
||||||
|
val symbolData = BinarySymbolData
|
||||||
|
.decode(proto.base.symbol)
|
||||||
|
sig = symbolDeserializer.deserializeIdSignature(symbolData.signatureId)
|
||||||
|
declareScopedTypeParameter(sig, { IrTypeParameterSymbolImpl() }, factory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure this symbol is known to linker
|
||||||
|
symbolDeserializer.referenceLocalIrSymbol(result.symbol, sig)
|
||||||
|
result.annotations += deserializeAnnotations(proto.base.annotationList)
|
||||||
|
result.parent = currentParent
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrValueParameter(proto: ProtoValueParameter, index: Int): IrValueParameter =
|
||||||
|
withDeserializedIrDeclarationBase(proto.base) { symbol, _, startOffset, endOffset, origin, fcode ->
|
||||||
|
val flags = ValueParameterFlags.decode(fcode)
|
||||||
|
val nameAndType = BinaryNameAndType.decode(proto.nameType)
|
||||||
|
irFactory.createValueParameter(
|
||||||
|
startOffset, endOffset, origin,
|
||||||
|
symbol as IrValueParameterSymbol,
|
||||||
|
deserializeName(nameAndType.nameIndex),
|
||||||
|
index,
|
||||||
|
deserializeIrType(nameAndType.typeIndex),
|
||||||
|
if (proto.hasVarargElementType()) deserializeIrType(proto.varargElementType) else null,
|
||||||
|
flags.isCrossInline,
|
||||||
|
flags.isNoInline,
|
||||||
|
flags.isHidden,
|
||||||
|
flags.isAssignable
|
||||||
|
).apply {
|
||||||
|
if (proto.hasDefaultValue())
|
||||||
|
defaultValue = deserializeExpressionBody(proto.defaultValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrClass(proto: ProtoClass): IrClass =
|
||||||
|
withDeserializedIrDeclarationBase(proto.base) { symbol, signature, startOffset, endOffset, origin, fcode ->
|
||||||
|
val flags = ClassFlags.decode(fcode)
|
||||||
|
|
||||||
|
symbolTable.declareClass(signature, { symbol as IrClassSymbol }) {
|
||||||
|
irFactory.createClass(
|
||||||
|
startOffset, endOffset, origin,
|
||||||
|
it,
|
||||||
|
deserializeName(proto.name),
|
||||||
|
flags.kind,
|
||||||
|
flags.visibility,
|
||||||
|
flags.modality,
|
||||||
|
flags.isCompanion,
|
||||||
|
flags.isInner,
|
||||||
|
flags.isData,
|
||||||
|
flags.isExternal,
|
||||||
|
flags.isInline,
|
||||||
|
flags.isExpect,
|
||||||
|
flags.isFun,
|
||||||
|
)
|
||||||
|
}.usingParent {
|
||||||
|
typeParameters = deserializeTypeParameters(proto.typeParameterList, true)
|
||||||
|
|
||||||
|
superTypes = proto.superTypeList.map { deserializeIrType(it) }
|
||||||
|
|
||||||
|
proto.declarationList
|
||||||
|
.filterNot { isSkippableFakeOverride(it, this) }
|
||||||
|
.mapTo(declarations) { deserializeDeclaration(it) }
|
||||||
|
|
||||||
|
thisReceiver = deserializeIrValueParameter(proto.thisReceiver, -1)
|
||||||
|
|
||||||
|
fakeOverrideBuilder.enqueueClass(this, signature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrTypeAlias(proto: ProtoTypeAlias): IrTypeAlias =
|
||||||
|
withDeserializedIrDeclarationBase(proto.base) { symbol, uniqId, startOffset, endOffset, origin, fcode ->
|
||||||
|
require(symbol is IrTypeAliasSymbol)
|
||||||
|
symbolTable.declareTypeAlias(uniqId, { symbol }) {
|
||||||
|
val flags = TypeAliasFlags.decode(fcode)
|
||||||
|
val nameType = BinaryNameAndType.decode(proto.nameType)
|
||||||
|
irFactory.createTypeAlias(
|
||||||
|
startOffset, endOffset,
|
||||||
|
it,
|
||||||
|
deserializeName(nameType.nameIndex),
|
||||||
|
flags.visibility,
|
||||||
|
deserializeIrType(nameType.typeIndex),
|
||||||
|
flags.isActual,
|
||||||
|
origin
|
||||||
|
)
|
||||||
|
}.usingParent {
|
||||||
|
typeParameters = deserializeTypeParameters(proto.typeParameterList, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeErrorDeclaration(proto: ProtoErrorDeclaration): IrErrorDeclaration {
|
||||||
|
require(allowErrorNodes) { "IrErrorDeclaration found but error code is not allowed" }
|
||||||
|
val coordinates = BinaryCoordinates.decode(proto.coordinates)
|
||||||
|
return irFactory.createErrorDeclaration(coordinates.startOffset, coordinates.endOffset).also {
|
||||||
|
it.parent = currentParent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeTypeParameters(protos: List<ProtoTypeParameter>, isGlobal: Boolean): List<IrTypeParameter> {
|
||||||
|
// NOTE: fun <C : MutableCollection<in T>, T : Any> Array<out T?>.filterNotNullTo(destination: C): C
|
||||||
|
val result = ArrayList<IrTypeParameter>(protos.size)
|
||||||
|
for (index in protos.indices) {
|
||||||
|
val proto = protos[index]
|
||||||
|
result.add(deserializeIrTypeParameter(proto, index, isGlobal))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i in protos.indices) {
|
||||||
|
result[i].superTypes = protos[i].superTypeList.map { deserializeIrType(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeValueParameters(protos: List<ProtoValueParameter>): List<IrValueParameter> {
|
||||||
|
val result = ArrayList<IrValueParameter>(protos.size)
|
||||||
|
|
||||||
|
for (i in protos.indices) {
|
||||||
|
result.add(deserializeIrValueParameter(protos[i], i))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In `declarations-only` mode in case of private property/function with inferred anonymous private type like this
|
||||||
|
* class C {
|
||||||
|
* private val p = object {
|
||||||
|
* fun foo() = 42
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* private fun f() = object {
|
||||||
|
* fun bar() = "42"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* private val pp = p.foo()
|
||||||
|
* private fun ff() = f().bar()
|
||||||
|
* }
|
||||||
|
* object's classifier is leaked outside p/f scopes and accessible on C's level so
|
||||||
|
* if their initializer/body weren't read we have unbound `foo/bar` symbol and unbound `object` symbols.
|
||||||
|
* To fix this make sure that such declaration forced to be deserialized completely.
|
||||||
|
*
|
||||||
|
* For more information see `anonymousClassLeak.kt` test and issue KT-40216
|
||||||
|
*/
|
||||||
|
private fun IrType.checkObjectLeak(): Boolean {
|
||||||
|
return if (this is IrSimpleType) {
|
||||||
|
classifier.let { !it.isPublicApi && it !is IrTypeParameterSymbol } || arguments.any { it.typeOrNull?.checkObjectLeak() == true }
|
||||||
|
} else false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T : IrFunction> T.withBodyGuard(block: T.() -> Unit) {
|
||||||
|
val oldBodiesPolicy = deserializeBodies
|
||||||
|
|
||||||
|
fun checkInlineBody(): Boolean = deserializeInlineFunctions && this is IrSimpleFunction && isInline
|
||||||
|
|
||||||
|
try {
|
||||||
|
deserializeBodies = oldBodiesPolicy || checkInlineBody() || returnType.checkObjectLeak()
|
||||||
|
block()
|
||||||
|
} finally {
|
||||||
|
deserializeBodies = oldBodiesPolicy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun IrField.withInitializerGuard(f: IrField.() -> Unit) {
|
||||||
|
val oldBodiesPolicy = deserializeBodies
|
||||||
|
|
||||||
|
try {
|
||||||
|
deserializeBodies = oldBodiesPolicy || type.checkObjectLeak()
|
||||||
|
f()
|
||||||
|
} finally {
|
||||||
|
deserializeBodies = oldBodiesPolicy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun readBody(index: Int): CodedInputStream =
|
||||||
|
fileReader.body(index).codedInputStream
|
||||||
|
|
||||||
|
private fun loadStatementBodyProto(index: Int): ProtoStatement {
|
||||||
|
return ProtoStatement.parseFrom(readBody(index), ExtensionRegistryLite.newInstance())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadExpressionBodyProto(index: Int): ProtoExpression {
|
||||||
|
return ProtoExpression.parseFrom(readBody(index), ExtensionRegistryLite.newInstance())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeExpressionBody(index: Int): IrExpressionBody {
|
||||||
|
return irFactory.createExpressionBody(
|
||||||
|
if (deserializeBodies) {
|
||||||
|
val bodyData = loadExpressionBodyProto(index)
|
||||||
|
bodyDeserializer.deserializeExpression(bodyData)
|
||||||
|
} else {
|
||||||
|
val errorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT)
|
||||||
|
IrErrorExpressionImpl(-1, -1, errorType, "Expression body is not deserialized yet")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeStatementBody(index: Int): IrElement {
|
||||||
|
return if (deserializeBodies) {
|
||||||
|
val bodyData = loadStatementBodyProto(index)
|
||||||
|
bodyDeserializer.deserializeStatement(bodyData)
|
||||||
|
} else {
|
||||||
|
val errorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT)
|
||||||
|
irFactory.createBlockBody(
|
||||||
|
-1, -1, listOf(IrErrorExpressionImpl(-1, -1, errorType, "Statement body is not deserialized yet"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <T : IrFunction> withDeserializedIrFunctionBase(
|
||||||
|
proto: ProtoFunctionBase,
|
||||||
|
block: (IrFunctionSymbol, IdSignature, Int, Int, IrDeclarationOrigin, Long) -> T
|
||||||
|
): T = withDeserializedIrDeclarationBase(proto.base) { symbol, idSig, startOffset, endOffset, origin, fcode ->
|
||||||
|
symbolTable.withScope(symbol) {
|
||||||
|
block(symbol as IrFunctionSymbol, idSig, startOffset, endOffset, origin, fcode).usingParent {
|
||||||
|
typeParameters = deserializeTypeParameters(proto.typeParameterList, false)
|
||||||
|
val nameType = BinaryNameAndType.decode(proto.nameType)
|
||||||
|
returnType = deserializeIrType(nameType.typeIndex)
|
||||||
|
|
||||||
|
withBodyGuard {
|
||||||
|
valueParameters = deserializeValueParameters(proto.valueParameterList)
|
||||||
|
if (proto.hasDispatchReceiver())
|
||||||
|
dispatchReceiverParameter = deserializeIrValueParameter(proto.dispatchReceiver, -1)
|
||||||
|
if (proto.hasExtensionReceiver())
|
||||||
|
extensionReceiverParameter = deserializeIrValueParameter(proto.extensionReceiver, -1)
|
||||||
|
if (proto.hasBody()) {
|
||||||
|
body = deserializeStatementBody(proto.body) as IrBody
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun deserializeIrFunction(proto: ProtoFunction): IrSimpleFunction {
|
||||||
|
return withDeserializedIrFunctionBase(proto.base) { symbol, idSig, startOffset, endOffset, origin, fcode ->
|
||||||
|
val flags = FunctionFlags.decode(fcode)
|
||||||
|
symbolTable.declareSimpleFunction(idSig, { symbol as IrSimpleFunctionSymbol }) {
|
||||||
|
val nameType = BinaryNameAndType.decode(proto.base.nameType)
|
||||||
|
irFactory.createFunction(
|
||||||
|
startOffset, endOffset, origin,
|
||||||
|
it,
|
||||||
|
deserializeName(nameType.nameIndex),
|
||||||
|
flags.visibility,
|
||||||
|
flags.modality,
|
||||||
|
IrUninitializedType,
|
||||||
|
flags.isInline,
|
||||||
|
flags.isExternal,
|
||||||
|
flags.isTailrec,
|
||||||
|
flags.isSuspend,
|
||||||
|
flags.isOperator,
|
||||||
|
flags.isInfix,
|
||||||
|
flags.isExpect,
|
||||||
|
flags.isFakeOverride
|
||||||
|
)
|
||||||
|
}.apply {
|
||||||
|
overriddenSymbols = proto.overriddenList.map { deserializeIrSymbolAndRemap(it) as IrSimpleFunctionSymbol }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun deserializeIrVariable(proto: ProtoVariable): IrVariable =
|
||||||
|
withDeserializedIrDeclarationBase(proto.base) { symbol, _, startOffset, endOffset, origin, fcode ->
|
||||||
|
val flags = LocalVariableFlags.decode(fcode)
|
||||||
|
val nameType = BinaryNameAndType.decode(proto.nameType)
|
||||||
|
IrVariableImpl(
|
||||||
|
startOffset, endOffset, origin,
|
||||||
|
symbol as IrVariableSymbol,
|
||||||
|
deserializeName(nameType.nameIndex),
|
||||||
|
deserializeIrType(nameType.typeIndex),
|
||||||
|
flags.isVar,
|
||||||
|
flags.isConst,
|
||||||
|
flags.isLateinit
|
||||||
|
).apply {
|
||||||
|
if (proto.hasInitializer())
|
||||||
|
initializer = bodyDeserializer.deserializeExpression(proto.initializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrEnumEntry(proto: ProtoEnumEntry): IrEnumEntry =
|
||||||
|
withDeserializedIrDeclarationBase(proto.base) { symbol, uniqId, startOffset, endOffset, origin, _ ->
|
||||||
|
symbolTable.declareEnumEntry(uniqId, { symbol as IrEnumEntrySymbol }) {
|
||||||
|
irFactory.createEnumEntry(startOffset, endOffset, origin, it, deserializeName(proto.name))
|
||||||
|
}.apply {
|
||||||
|
if (proto.hasCorrespondingClass())
|
||||||
|
correspondingClass = deserializeIrClass(proto.correspondingClass)
|
||||||
|
if (proto.hasInitializer())
|
||||||
|
initializerExpression = deserializeExpressionBody(proto.initializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrAnonymousInit(proto: ProtoAnonymousInit): IrAnonymousInitializer =
|
||||||
|
withDeserializedIrDeclarationBase(proto.base) { symbol, _, startOffset, endOffset, origin, _ ->
|
||||||
|
irFactory.createAnonymousInitializer(startOffset, endOffset, origin, symbol as IrAnonymousInitializerSymbol).apply {
|
||||||
|
body = deserializeStatementBody(proto.body) as IrBlockBody
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrConstructor(proto: ProtoConstructor): IrConstructor =
|
||||||
|
withDeserializedIrFunctionBase(proto.base) { symbol, idSig, startOffset, endOffset, origin, fcode ->
|
||||||
|
require(symbol is IrConstructorSymbol)
|
||||||
|
val flags = FunctionFlags.decode(fcode)
|
||||||
|
val nameType = BinaryNameAndType.decode(proto.base.nameType)
|
||||||
|
symbolTable.declareConstructor(idSig, { symbol }) {
|
||||||
|
irFactory.createConstructor(
|
||||||
|
startOffset, endOffset, origin,
|
||||||
|
it,
|
||||||
|
deserializeName(nameType.nameIndex),
|
||||||
|
flags.visibility,
|
||||||
|
IrUninitializedType,
|
||||||
|
flags.isInline,
|
||||||
|
flags.isExternal,
|
||||||
|
flags.isPrimary,
|
||||||
|
flags.isExpect
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun deserializeIrField(proto: ProtoField): IrField =
|
||||||
|
withDeserializedIrDeclarationBase(proto.base) { symbol, uniqId, startOffset, endOffset, origin, fcode ->
|
||||||
|
require(symbol is IrFieldSymbol)
|
||||||
|
val nameType = BinaryNameAndType.decode(proto.nameType)
|
||||||
|
val type = deserializeIrType(nameType.typeIndex)
|
||||||
|
val flags = FieldFlags.decode(fcode)
|
||||||
|
symbolTable.declareField(uniqId, { symbol }) {
|
||||||
|
irFactory.createField(
|
||||||
|
startOffset, endOffset, origin,
|
||||||
|
it,
|
||||||
|
deserializeName(nameType.nameIndex),
|
||||||
|
type,
|
||||||
|
flags.visibility,
|
||||||
|
flags.isFinal,
|
||||||
|
flags.isExternal,
|
||||||
|
flags.isStatic,
|
||||||
|
)
|
||||||
|
}.usingParent {
|
||||||
|
if (proto.hasInitializer()) {
|
||||||
|
withInitializerGuard {
|
||||||
|
initializer = deserializeExpressionBody(proto.initializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrLocalDelegatedProperty(proto: ProtoLocalDelegatedProperty): IrLocalDelegatedProperty =
|
||||||
|
withDeserializedIrDeclarationBase(proto.base) { symbol, _, startOffset, endOffset, origin, fcode ->
|
||||||
|
val flags = LocalVariableFlags.decode(fcode)
|
||||||
|
val nameAndType = BinaryNameAndType.decode(proto.nameType)
|
||||||
|
irFactory.createLocalDelegatedProperty(
|
||||||
|
startOffset, endOffset, origin,
|
||||||
|
symbol as IrLocalDelegatedPropertySymbol,
|
||||||
|
deserializeName(nameAndType.nameIndex),
|
||||||
|
deserializeIrType(nameAndType.typeIndex),
|
||||||
|
flags.isVar
|
||||||
|
).apply {
|
||||||
|
delegate = deserializeIrVariable(proto.delegate)
|
||||||
|
getter = deserializeIrFunction(proto.getter)
|
||||||
|
if (proto.hasSetter())
|
||||||
|
setter = deserializeIrFunction(proto.setter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrProperty(proto: ProtoProperty): IrProperty =
|
||||||
|
withDeserializedIrDeclarationBase(proto.base) { symbol, uniqId, startOffset, endOffset, origin, fcode ->
|
||||||
|
require(symbol is IrPropertySymbol)
|
||||||
|
val flags = PropertyFlags.decode(fcode)
|
||||||
|
symbolTable.declareProperty(uniqId, { symbol }) {
|
||||||
|
irFactory.createProperty(
|
||||||
|
startOffset, endOffset, origin,
|
||||||
|
it,
|
||||||
|
deserializeName(proto.name),
|
||||||
|
flags.visibility,
|
||||||
|
flags.modality,
|
||||||
|
flags.isVar,
|
||||||
|
flags.isConst,
|
||||||
|
flags.isLateinit,
|
||||||
|
flags.isDelegated,
|
||||||
|
flags.isExternal,
|
||||||
|
flags.isExpect,
|
||||||
|
flags.isFakeOverride
|
||||||
|
)
|
||||||
|
}.apply {
|
||||||
|
if (proto.hasGetter()) {
|
||||||
|
getter = deserializeIrFunction(proto.getter).also {
|
||||||
|
it.correspondingPropertySymbol = symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (proto.hasSetter()) {
|
||||||
|
setter = deserializeIrFunction(proto.setter).also {
|
||||||
|
it.correspondingPropertySymbol = symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (proto.hasBackingField()) {
|
||||||
|
backingField = deserializeIrField(proto.backingField).also {
|
||||||
|
it.correspondingPropertySymbol = symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val allKnownDeclarationOrigins =
|
||||||
|
IrDeclarationOrigin::class.nestedClasses.toList() + InnerClassesSupport.FIELD_FOR_OUTER_THIS::class
|
||||||
|
private val declarationOriginIndex =
|
||||||
|
allKnownDeclarationOrigins.map { it.objectInstance as IrDeclarationOriginImpl }.associateBy { it.name }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeIrDeclarationOrigin(protoName: Int): IrDeclarationOriginImpl {
|
||||||
|
val originName = fileReader.deserializeString(protoName)
|
||||||
|
return declarationOriginIndex[originName] ?: object : IrDeclarationOriginImpl(originName) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserializeDeclaration(proto: ProtoDeclaration): IrDeclaration {
|
||||||
|
val declaration: IrDeclaration = when (proto.declaratorCase!!) {
|
||||||
|
IR_ANONYMOUS_INIT -> deserializeIrAnonymousInit(proto.irAnonymousInit)
|
||||||
|
IR_CONSTRUCTOR -> deserializeIrConstructor(proto.irConstructor)
|
||||||
|
IR_FIELD -> deserializeIrField(proto.irField)
|
||||||
|
IR_CLASS -> deserializeIrClass(proto.irClass)
|
||||||
|
IR_FUNCTION -> deserializeIrFunction(proto.irFunction)
|
||||||
|
IR_PROPERTY -> deserializeIrProperty(proto.irProperty)
|
||||||
|
IR_TYPE_PARAMETER -> error("Unreachable execution Type Parameter") // deserializeIrTypeParameter(proto.irTypeParameter)
|
||||||
|
IR_VARIABLE -> deserializeIrVariable(proto.irVariable)
|
||||||
|
IR_VALUE_PARAMETER -> error("Unreachable execution Value Parameter") // deserializeIrValueParameter(proto.irValueParameter)
|
||||||
|
IR_ENUM_ENTRY -> deserializeIrEnumEntry(proto.irEnumEntry)
|
||||||
|
IR_LOCAL_DELEGATED_PROPERTY -> deserializeIrLocalDelegatedProperty(proto.irLocalDelegatedProperty)
|
||||||
|
IR_TYPE_ALIAS -> deserializeIrTypeAlias(proto.irTypeAlias)
|
||||||
|
IR_ERROR_DECLARATION -> deserializeErrorDeclaration(proto.irErrorDeclaration)
|
||||||
|
DECLARATOR_NOT_SET -> error("Declaration deserialization not implemented: ${proto.declaratorCase}")
|
||||||
|
}
|
||||||
|
|
||||||
|
return declaration
|
||||||
|
}
|
||||||
|
|
||||||
|
// Depending on deserialization strategy we either deserialize public api fake overrides
|
||||||
|
// or reconstruct them after IR linker completes.
|
||||||
|
private fun isSkippableFakeOverride(proto: ProtoDeclaration, parent: IrClass): Boolean {
|
||||||
|
if (!platformFakeOverrideClassFilter.needToConstructFakeOverrides(parent)) return false
|
||||||
|
|
||||||
|
val symbol = when (proto.declaratorCase!!) {
|
||||||
|
IR_FUNCTION -> symbolDeserializer.deserializeIrSymbol(proto.irFunction.base.base.symbol)
|
||||||
|
IR_PROPERTY -> symbolDeserializer.deserializeIrSymbol(proto.irProperty.base.symbol)
|
||||||
|
// Don't consider IR_FIELDS here.
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
if (symbol !is IrPublicSymbolBase<*>) return false
|
||||||
|
if (!symbol.signature.isPublic) return false
|
||||||
|
|
||||||
|
return when (proto.declaratorCase!!) {
|
||||||
|
IR_FUNCTION -> FunctionFlags.decode(proto.irFunction.base.base.flags).isFakeOverride
|
||||||
|
IR_PROPERTY -> PropertyFlags.decode(proto.irProperty.base.flags).isFakeOverride
|
||||||
|
// Don't consider IR_FIELDS here.
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+138
-1431
File diff suppressed because it is too large
Load Diff
-6
@@ -55,8 +55,6 @@ abstract class IrModuleDeserializer(val moduleDescriptor: ModuleDescriptor) {
|
|||||||
|
|
||||||
open fun addModuleReachableTopLevel(idSig: IdSignature) { error("Unsupported Operation (sig: $idSig") }
|
open fun addModuleReachableTopLevel(idSig: IdSignature) { error("Unsupported Operation (sig: $idSig") }
|
||||||
|
|
||||||
open fun deserializeReachableDeclarations() { error("Unsupported Operation") }
|
|
||||||
|
|
||||||
abstract val moduleFragment: IrModuleFragment
|
abstract val moduleFragment: IrModuleFragment
|
||||||
|
|
||||||
abstract val moduleDependencies: Collection<IrModuleDeserializer>
|
abstract val moduleDependencies: Collection<IrModuleDeserializer>
|
||||||
@@ -103,10 +101,6 @@ class IrModuleDeserializerWithBuiltIns(
|
|||||||
override fun referencePropertyByLocalSignature(file: IrFile, idSignature: IdSignature): IrPropertySymbol =
|
override fun referencePropertyByLocalSignature(file: IrFile, idSignature: IdSignature): IrPropertySymbol =
|
||||||
delegate.referencePropertyByLocalSignature(file, idSignature)
|
delegate.referencePropertyByLocalSignature(file, idSignature)
|
||||||
|
|
||||||
override fun deserializeReachableDeclarations() {
|
|
||||||
delegate.deserializeReachableDeclarations()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun computeFunctionDescriptor(className: String): FunctionClassDescriptor {
|
private fun computeFunctionDescriptor(className: String): FunctionClassDescriptor {
|
||||||
val isK = className[0] == 'K'
|
val isK = className[0] == 'K'
|
||||||
val isSuspend = (if (isK) className[1] else className[0]) == 'S'
|
val isSuspend = (if (isK) className[1] else className[0]) == 'S'
|
||||||
|
|||||||
+156
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.common.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.encodings.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.Actual
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IdSignature.IdsigCase.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrLocalDelegatedPropertySymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.protobuf.CodedInputStream
|
||||||
|
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.AccessorIdSignature as ProtoAccessorIdSignature
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.FileLocalIdSignature as ProtoFileLocalIdSignature
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IdSignature as ProtoIdSignature
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.proto.PublicIdSignature as ProtoPublicIdSignature
|
||||||
|
|
||||||
|
class IrSymbolDeserializer(
|
||||||
|
val symbolTable: ReferenceSymbolTable,
|
||||||
|
val fileReader: IrLibraryFile,
|
||||||
|
val actuals: List<Actual>,
|
||||||
|
val enqueueLocalTopLevelDeclaration: (IdSignature) -> Unit,
|
||||||
|
val handleExpectActualMapping: (IdSignature, IrSymbol) -> IrSymbol,
|
||||||
|
val deserializePublicSymbol: (IdSignature, BinarySymbolData.SymbolKind) -> IrSymbol,
|
||||||
|
) {
|
||||||
|
|
||||||
|
val deserializedSymbols = mutableMapOf<IdSignature, IrSymbol>()
|
||||||
|
|
||||||
|
fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||||
|
return deserializedSymbols.getOrPut(idSig) {
|
||||||
|
val symbol = referenceDeserializedSymbol(symbolKind, idSig)
|
||||||
|
|
||||||
|
handleExpectActualMapping(idSig, symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun referenceDeserializedSymbol(symbolKind: BinarySymbolData.SymbolKind, idSig: IdSignature): IrSymbol = symbolTable.run {
|
||||||
|
when (symbolKind) {
|
||||||
|
BinarySymbolData.SymbolKind.ANONYMOUS_INIT_SYMBOL -> IrAnonymousInitializerSymbolImpl()
|
||||||
|
BinarySymbolData.SymbolKind.CLASS_SYMBOL -> referenceClassFromLinker(idSig)
|
||||||
|
BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL -> referenceConstructorFromLinker(idSig)
|
||||||
|
BinarySymbolData.SymbolKind.TYPE_PARAMETER_SYMBOL -> referenceTypeParameterFromLinker(idSig)
|
||||||
|
BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL -> referenceEnumEntryFromLinker(idSig)
|
||||||
|
BinarySymbolData.SymbolKind.STANDALONE_FIELD_SYMBOL -> referenceFieldFromLinker(idSig)
|
||||||
|
BinarySymbolData.SymbolKind.FIELD_SYMBOL -> referenceFieldFromLinker(idSig)
|
||||||
|
BinarySymbolData.SymbolKind.FUNCTION_SYMBOL -> referenceSimpleFunctionFromLinker(idSig)
|
||||||
|
BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL -> referenceTypeAliasFromLinker(idSig)
|
||||||
|
BinarySymbolData.SymbolKind.PROPERTY_SYMBOL -> referencePropertyFromLinker(idSig)
|
||||||
|
BinarySymbolData.SymbolKind.VARIABLE_SYMBOL -> IrVariableSymbolImpl()
|
||||||
|
BinarySymbolData.SymbolKind.VALUE_PARAMETER_SYMBOL -> IrValueParameterSymbolImpl()
|
||||||
|
BinarySymbolData.SymbolKind.RECEIVER_PARAMETER_SYMBOL -> IrValueParameterSymbolImpl()
|
||||||
|
BinarySymbolData.SymbolKind.LOCAL_DELEGATED_PROPERTY_SYMBOL ->
|
||||||
|
IrLocalDelegatedPropertySymbolImpl()
|
||||||
|
else -> error("Unexpected classifier symbol kind: $symbolKind for signature $idSig")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun referenceLocalIrSymbol(symbol: IrSymbol, signature: IdSignature) {
|
||||||
|
assert(signature.isLocal)
|
||||||
|
deserializedSymbols.putIfAbsent(signature, symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun referenceSimpleFunctionByLocalSignature(idSignature: IdSignature) : IrSimpleFunctionSymbol =
|
||||||
|
deserializeIrSymbolData(idSignature, BinarySymbolData.SymbolKind.FUNCTION_SYMBOL) as IrSimpleFunctionSymbol
|
||||||
|
|
||||||
|
fun referencePropertyByLocalSignature(idSignature: IdSignature): IrPropertySymbol =
|
||||||
|
deserializeIrSymbolData(idSignature, BinarySymbolData.SymbolKind.PROPERTY_SYMBOL) as IrPropertySymbol
|
||||||
|
|
||||||
|
private fun deserializeIrSymbolData(idSignature: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||||
|
if (idSignature.isLocal) {
|
||||||
|
if (idSignature.hasTopLevel) {
|
||||||
|
enqueueLocalTopLevelDeclaration(idSignature.topLevelSignature())
|
||||||
|
}
|
||||||
|
return deserializedSymbols.getOrPut(idSignature) {
|
||||||
|
referenceDeserializedSymbol(symbolKind, idSignature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deserializePublicSymbol(idSignature, symbolKind)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserializeIrSymbolToDeclare(code: Long): Pair<IrSymbol, IdSignature> {
|
||||||
|
val symbolData = parseSymbolData(code)
|
||||||
|
val signature = deserializeIdSignature(symbolData.signatureId)
|
||||||
|
return Pair(deserializeIrSymbolData(signature, symbolData.kind), signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseSymbolData(code: Long): BinarySymbolData = BinarySymbolData.decode(code)
|
||||||
|
|
||||||
|
fun deserializeIrSymbol(code: Long): IrSymbol {
|
||||||
|
val symbolData = parseSymbolData(code)
|
||||||
|
val signature = deserializeIdSignature(symbolData.signatureId)
|
||||||
|
return deserializeIrSymbolData(signature, symbolData.kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun readSignature(index: Int): CodedInputStream =
|
||||||
|
fileReader.signature(index).codedInputStream
|
||||||
|
|
||||||
|
private fun loadSignatureProto(index: Int): ProtoIdSignature {
|
||||||
|
return ProtoIdSignature.parseFrom(readSignature(index), ExtensionRegistryLite.newInstance())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserializeIdSignature(index: Int): IdSignature {
|
||||||
|
val sigData = loadSignatureProto(index)
|
||||||
|
return deserializeSignatureData(sigData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// TODO: Think about isolating id signature related logic behind corresponding interface
|
||||||
|
|
||||||
|
private fun deserializePublicIdSignature(proto: ProtoPublicIdSignature): IdSignature.PublicSignature {
|
||||||
|
val pkg = fileReader.deserializeFqName(proto.packageFqNameList)
|
||||||
|
val cls = fileReader.deserializeFqName(proto.declarationFqNameList)
|
||||||
|
val memberId = if (proto.hasMemberUniqId()) proto.memberUniqId else null
|
||||||
|
|
||||||
|
return IdSignature.PublicSignature(pkg, cls, memberId, proto.flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeAccessorIdSignature(proto: ProtoAccessorIdSignature): IdSignature.AccessorSignature {
|
||||||
|
val propertySignature = deserializeIdSignature(proto.propertySignature)
|
||||||
|
require(propertySignature is IdSignature.PublicSignature) { "For public accessor corresponding property supposed to be public as well" }
|
||||||
|
val name = fileReader.deserializeString(proto.name)
|
||||||
|
val hash = proto.accessorHashId
|
||||||
|
val mask = proto.flags
|
||||||
|
|
||||||
|
val accessorSignature =
|
||||||
|
IdSignature.PublicSignature(propertySignature.packageFqName, "${propertySignature.declarationFqName}.$name", hash, mask)
|
||||||
|
|
||||||
|
return IdSignature.AccessorSignature(propertySignature, accessorSignature)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeFileLocalIdSignature(proto: ProtoFileLocalIdSignature): IdSignature.FileLocalSignature {
|
||||||
|
return IdSignature.FileLocalSignature(deserializeIdSignature(proto.container), proto.localId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeScopeLocalIdSignature(proto: Int): IdSignature.ScopeLocalDeclaration {
|
||||||
|
return IdSignature.ScopeLocalDeclaration(proto)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserializeSignatureData(proto: ProtoIdSignature): IdSignature {
|
||||||
|
return when (proto.idsigCase) {
|
||||||
|
PUBLIC_SIG -> deserializePublicIdSignature(proto.publicSig)
|
||||||
|
ACCESSOR_SIG -> deserializeAccessorIdSignature(proto.accessorSig)
|
||||||
|
PRIVATE_SIG -> deserializeFileLocalIdSignature(proto.privateSig)
|
||||||
|
SCOPED_LOCAL_SIG -> deserializeScopeLocalIdSignature(proto.scopedLocalSig)
|
||||||
|
else -> error("Unexpected IdSignature kind: ${proto.idsigCase}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+51
-482
@@ -11,25 +11,15 @@ import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolD
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
|
import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
|
||||||
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.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
import org.jetbrains.kotlin.ir.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
|
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory
|
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
|
||||||
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
|
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
|
||||||
import org.jetbrains.kotlin.ir.linkage.KotlinIrLinkerInternalException
|
import org.jetbrains.kotlin.ir.linkage.KotlinIrLinkerInternalException
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
|
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.library.IrLibrary
|
import org.jetbrains.kotlin.library.IrLibrary
|
||||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||||
@@ -38,32 +28,23 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.protobuf.CodedInputStream
|
import org.jetbrains.kotlin.protobuf.CodedInputStream
|
||||||
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite.newInstance
|
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite.newInstance
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.types.Variance
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.proto.Actual as ProtoActual
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IdSignature as ProtoIdSignature
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConstructorCall as ProtoConstructorCall
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement as ProtoStatement
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrType as ProtoType
|
|
||||||
|
|
||||||
abstract class KotlinIrLinker(
|
abstract class KotlinIrLinker(
|
||||||
private val currentModule: ModuleDescriptor?,
|
private val currentModule: ModuleDescriptor?,
|
||||||
val messageLogger: IrMessageLogger,
|
val messageLogger: IrMessageLogger,
|
||||||
val builtIns: IrBuiltIns,
|
val builtIns: IrBuiltIns,
|
||||||
val symbolTable: SymbolTable,
|
val symbolTable: SymbolTable,
|
||||||
private val exportedDependencies: List<ModuleDescriptor>
|
private val exportedDependencies: List<ModuleDescriptor>,
|
||||||
) : IrDeserializer, FileLocalAwareLinker {
|
) : IrDeserializer, FileLocalAwareLinker {
|
||||||
|
|
||||||
// Kotlin-MPP related data. Consider some refactoring
|
// Kotlin-MPP related data. Consider some refactoring
|
||||||
private val expectUniqIdToActualUniqId = mutableMapOf<IdSignature, IdSignature>()
|
internal val expectUniqIdToActualUniqId = mutableMapOf<IdSignature, IdSignature>()
|
||||||
private val topLevelActualUniqItToDeserializer = mutableMapOf<IdSignature, IrModuleDeserializer>()
|
internal val topLevelActualUniqItToDeserializer = mutableMapOf<IdSignature, IrModuleDeserializer>()
|
||||||
private val expectSymbols = mutableMapOf<IdSignature, IrSymbol>()
|
internal val expectSymbols = mutableMapOf<IdSignature, IrSymbol>()
|
||||||
private val actualSymbols = mutableMapOf<IdSignature, IrSymbol>()
|
internal val actualSymbols = mutableMapOf<IdSignature, IrSymbol>()
|
||||||
|
|
||||||
private val modulesWithReachableTopLevels = mutableSetOf<IrModuleDeserializer>()
|
internal val modulesWithReachableTopLevels = mutableSetOf<ModuleDeserializationState>()
|
||||||
|
|
||||||
// TODO: replace with Map<Name, IrModuleDeserializer>
|
// TODO: replace with Map<Name, IrModuleDeserializer>
|
||||||
protected val deserializersForModules = mutableMapOf<ModuleDescriptor, IrModuleDeserializer>()
|
protected val deserializersForModules = mutableMapOf<ModuleDescriptor, IrModuleDeserializer>()
|
||||||
@@ -72,411 +53,12 @@ abstract class KotlinIrLinker(
|
|||||||
|
|
||||||
abstract val translationPluginContext: TranslationPluginContext?
|
abstract val translationPluginContext: TranslationPluginContext?
|
||||||
|
|
||||||
private val haveSeen = mutableSetOf<IrSymbol>()
|
internal val triedToDeserializeDeclarationForSymbol = mutableSetOf<IrSymbol>()
|
||||||
|
internal val deserializedSymbols = mutableSetOf<IrSymbol>()
|
||||||
|
|
||||||
private lateinit var linkerExtensions: Collection<IrDeserializer.IrLinkerExtension>
|
private lateinit var linkerExtensions: Collection<IrDeserializer.IrLinkerExtension>
|
||||||
|
|
||||||
abstract inner class BasicIrModuleDeserializer(moduleDescriptor: ModuleDescriptor, override val klib: IrLibrary, override val strategy: DeserializationStrategy, private val containsErrorCode: Boolean = false) :
|
public open fun handleNoModuleDeserializerFound(idSignature: IdSignature, currentModule: ModuleDescriptor, dependencies: Collection<IrModuleDeserializer>): IrModuleDeserializer {
|
||||||
IrModuleDeserializer(moduleDescriptor) {
|
|
||||||
|
|
||||||
private val fileToDeserializerMap = mutableMapOf<IrFile, IrDeserializerForFile>()
|
|
||||||
|
|
||||||
private inner class ModuleDeserializationState {
|
|
||||||
private val filesWithPendingTopLevels = mutableSetOf<IrDeserializerForFile>()
|
|
||||||
|
|
||||||
fun enqueueFile(fileDeserializer: IrDeserializerForFile) {
|
|
||||||
filesWithPendingTopLevels.add(fileDeserializer)
|
|
||||||
enqueueModule()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addIdSignature(key: IdSignature) {
|
|
||||||
val fileDeserializer = moduleReversedFileIndex[key] ?: error("No file found for key $key")
|
|
||||||
fileDeserializer.fileLocalDeserializationState.addIdSignature(key)
|
|
||||||
|
|
||||||
enqueueFile(fileDeserializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun processPendingDeclarations() {
|
|
||||||
while (filesWithPendingTopLevels.isNotEmpty()) {
|
|
||||||
val pendingDeserializer = filesWithPendingTopLevels.first()
|
|
||||||
|
|
||||||
pendingDeserializer.deserializeFileImplicitDataIfFirstUse()
|
|
||||||
pendingDeserializer.deserializeAllFileReachableTopLevel()
|
|
||||||
|
|
||||||
filesWithPendingTopLevels.remove(pendingDeserializer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = klib.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val moduleDeserializationState = ModuleDeserializationState()
|
|
||||||
private val moduleReversedFileIndex = mutableMapOf<IdSignature, IrDeserializerForFile>()
|
|
||||||
override val moduleDependencies by lazy {
|
|
||||||
moduleDescriptor.allDependencyModules.filter { it != moduleDescriptor }.map { resolveModuleDeserializer(it, null) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun init(delegate: IrModuleDeserializer) {
|
|
||||||
val fileCount = klib.fileCount()
|
|
||||||
|
|
||||||
val files = ArrayList<IrFile>(fileCount)
|
|
||||||
|
|
||||||
for (i in 0 until fileCount) {
|
|
||||||
val fileStream = klib.file(i).codedInputStream
|
|
||||||
files.add(deserializeIrFile(ProtoFile.parseFrom(fileStream, newInstance()), i, delegate, containsErrorCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
moduleFragment.files.addAll(files)
|
|
||||||
|
|
||||||
fileToDeserializerMap.values.forEach { it.deserializeExpectActualMapping() }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun referenceSimpleFunctionByLocalSignature(file: IrFile, idSignature: IdSignature): IrSimpleFunctionSymbol =
|
|
||||||
fileToDeserializerMap[file]?.referenceSimpleFunctionByLocalSignature(idSignature)
|
|
||||||
?: error("No deserializer for file $file in module ${moduleDescriptor.name}")
|
|
||||||
|
|
||||||
override fun referencePropertyByLocalSignature(file: IrFile, idSignature: IdSignature): IrPropertySymbol =
|
|
||||||
fileToDeserializerMap[file]?.referencePropertyByLocalSignature(idSignature)
|
|
||||||
?: error("No deserializer for file $file in module ${moduleDescriptor.name}")
|
|
||||||
|
|
||||||
// TODO: fix to topLevel checker
|
|
||||||
override fun contains(idSig: IdSignature): Boolean = idSig in moduleReversedFileIndex
|
|
||||||
|
|
||||||
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
|
||||||
assert(idSig.isPublic)
|
|
||||||
|
|
||||||
val topLevelSignature = idSig.topLevelSignature()
|
|
||||||
val fileDeserializer = moduleReversedFileIndex[topLevelSignature]
|
|
||||||
?: error("No file for $topLevelSignature (@ $idSig) in module $moduleDescriptor")
|
|
||||||
|
|
||||||
val fileDeserializationState = fileDeserializer.fileLocalDeserializationState
|
|
||||||
|
|
||||||
fileDeserializationState.addIdSignature(topLevelSignature)
|
|
||||||
moduleDeserializationState.enqueueFile(fileDeserializer)
|
|
||||||
|
|
||||||
return fileDeserializationState.deserializedSymbols.getOrPut(idSig) {
|
|
||||||
// val descriptor = resolveSpecialSignature(idSig)
|
|
||||||
val symbol = referenceDeserializedSymbol(symbolKind, idSig)
|
|
||||||
|
|
||||||
handleExpectActualMapping(idSig, symbol)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns, emptyList())
|
|
||||||
|
|
||||||
private fun deserializeIrFile(fileProto: ProtoFile, fileIndex: Int, moduleDeserializer: IrModuleDeserializer, allowErrorNodes: Boolean): IrFile {
|
|
||||||
|
|
||||||
val fileName = fileProto.fileEntry.name
|
|
||||||
|
|
||||||
val fileEntry = NaiveSourceBasedFileEntryImpl(fileName, fileProto.fileEntry.lineStartOffsetsList.toIntArray())
|
|
||||||
|
|
||||||
val fileDeserializer =
|
|
||||||
IrDeserializerForFile(
|
|
||||||
fileProto.annotationList,
|
|
||||||
fileProto.actualsList,
|
|
||||||
fileIndex,
|
|
||||||
!strategy.needBodies,
|
|
||||||
strategy.inlineBodies,
|
|
||||||
moduleDeserializer, allowErrorNodes
|
|
||||||
).apply {
|
|
||||||
|
|
||||||
// Explicitly exported declarations (e.g. top-level initializers) must be deserialized before all other declarations.
|
|
||||||
// Thus we schedule their deserialization in deserializer's constructor.
|
|
||||||
fileProto.explicitlyExportedToCompilerList.forEach {
|
|
||||||
val symbolData = parseSymbolData(it)
|
|
||||||
val sig = deserializeIdSignature(symbolData.signatureId)
|
|
||||||
assert(!sig.isPackageSignature())
|
|
||||||
fileLocalDeserializationState.addIdSignature(sig.topLevelSignature())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val fqName = FqName(fileDeserializer.deserializeFqName(fileProto.fqNameList))
|
|
||||||
|
|
||||||
val packageFragmentDescriptor = EmptyPackageFragmentDescriptor(moduleDescriptor, fqName)
|
|
||||||
|
|
||||||
val symbol = IrFileSymbolImpl(packageFragmentDescriptor)
|
|
||||||
val file = IrFileImpl(fileEntry, symbol, fqName)
|
|
||||||
|
|
||||||
fileDeserializer.file = file
|
|
||||||
fileToDeserializerMap[file] = fileDeserializer
|
|
||||||
|
|
||||||
val fileSignatureIndex = fileProto.declarationIdList.map { fileDeserializer.deserializeIdSignature(it) to it }
|
|
||||||
|
|
||||||
fileSignatureIndex.forEach {
|
|
||||||
moduleReversedFileIndex.getOrPut(it.first) { fileDeserializer }
|
|
||||||
}
|
|
||||||
|
|
||||||
fileDeserializer.reversedSignatureIndex = fileSignatureIndex.toMap()
|
|
||||||
|
|
||||||
if (strategy.theWholeWorld) {
|
|
||||||
for (id in fileSignatureIndex) {
|
|
||||||
moduleDeserializationState.addIdSignature(id.first)
|
|
||||||
}
|
|
||||||
moduleDeserializationState.enqueueFile(fileDeserializer)
|
|
||||||
} else if (strategy.explicitlyExported) {
|
|
||||||
moduleDeserializationState.enqueueFile(fileDeserializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserializeReachableDeclarations() {
|
|
||||||
moduleDeserializationState.processPendingDeclarations()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun enqueueModule() {
|
|
||||||
modulesWithReachableTopLevels.add(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun addModuleReachableTopLevel(idSig: IdSignature) {
|
|
||||||
moduleDeserializationState.addIdSignature(idSig)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class IrDeserializerForFile(
|
|
||||||
private var annotations: List<ProtoConstructorCall>?,
|
|
||||||
private val actuals: List<ProtoActual>,
|
|
||||||
private val fileIndex: Int,
|
|
||||||
onlyHeaders: Boolean,
|
|
||||||
inlineBodies: Boolean,
|
|
||||||
private val moduleDeserializer: IrModuleDeserializer,
|
|
||||||
allowErrorNodes: Boolean
|
|
||||||
) :
|
|
||||||
IrFileDeserializer(
|
|
||||||
messageLogger,
|
|
||||||
builtIns,
|
|
||||||
symbolTable,
|
|
||||||
!onlyHeaders,
|
|
||||||
fakeOverrideBuilder,
|
|
||||||
allowErrorNodes
|
|
||||||
)
|
|
||||||
{
|
|
||||||
|
|
||||||
private var fileLoops = mutableMapOf<Int, IrLoop>()
|
|
||||||
|
|
||||||
lateinit var file: IrFile
|
|
||||||
|
|
||||||
private val irTypeCache = mutableMapOf<Int, IrType>()
|
|
||||||
|
|
||||||
override val deserializeInlineFunctions: Boolean = inlineBodies
|
|
||||||
|
|
||||||
override val platformFakeOverrideClassFilter = fakeOverrideBuilder.platformSpecificClassFilter
|
|
||||||
|
|
||||||
var reversedSignatureIndex = emptyMap<IdSignature, Int>()
|
|
||||||
|
|
||||||
inner class FileDeserializationState {
|
|
||||||
private val reachableTopLevels = LinkedHashSet<IdSignature>()
|
|
||||||
val deserializedSymbols = mutableMapOf<IdSignature, IrSymbol>()
|
|
||||||
|
|
||||||
fun addIdSignature(key: IdSignature) {
|
|
||||||
reachableTopLevels.add(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun processPendingDeclarations() {
|
|
||||||
while (reachableTopLevels.isNotEmpty()) {
|
|
||||||
val reachableKey = reachableTopLevels.first()
|
|
||||||
|
|
||||||
val existedSymbol = deserializedSymbols[reachableKey]
|
|
||||||
if (existedSymbol == null || !existedSymbol.isBound) {
|
|
||||||
val declaration = deserializeDeclaration(reachableKey)
|
|
||||||
file.declarations.add(declaration)
|
|
||||||
}
|
|
||||||
|
|
||||||
reachableTopLevels.remove(reachableKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val fileLocalDeserializationState = FileDeserializationState()
|
|
||||||
|
|
||||||
fun deserializeDeclaration(idSig: IdSignature): IrDeclaration {
|
|
||||||
return deserializeDeclaration(loadTopLevelDeclarationProto(idSig), file)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deserializeExpectActualMapping() {
|
|
||||||
actuals.forEach {
|
|
||||||
val expectSymbol = parseSymbolData(it.expectSymbol)
|
|
||||||
val actualSymbol = parseSymbolData(it.actualSymbol)
|
|
||||||
|
|
||||||
val expect = deserializeIdSignature(expectSymbol.signatureId)
|
|
||||||
val actual = deserializeIdSignature(actualSymbol.signatureId)
|
|
||||||
|
|
||||||
assert(expectUniqIdToActualUniqId[expect] == null) {
|
|
||||||
"Expect signature $expect is already actualized by ${expectUniqIdToActualUniqId[expect]}, while we try to record $actual"
|
|
||||||
}
|
|
||||||
expectUniqIdToActualUniqId[expect] = actual
|
|
||||||
// Non-null only for topLevel declarations.
|
|
||||||
getModuleForTopLevelId(actual)?.let { md -> topLevelActualUniqItToDeserializer[actual] = md }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resolveSignatureIndex(idSig: IdSignature): Int {
|
|
||||||
return reversedSignatureIndex[idSig] ?: error("Not found Idx for $idSig")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun readDeclaration(index: Int): CodedInputStream =
|
|
||||||
moduleDeserializer.klib.irDeclaration(index, fileIndex).codedInputStream
|
|
||||||
|
|
||||||
private fun loadTopLevelDeclarationProto(idSig: IdSignature): ProtoDeclaration {
|
|
||||||
val idSigIndex = resolveSignatureIndex(idSig)
|
|
||||||
return ProtoDeclaration.parseFrom(readDeclaration(idSigIndex), newInstance())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun readType(index: Int): CodedInputStream =
|
|
||||||
moduleDeserializer.klib.type(index, fileIndex).codedInputStream
|
|
||||||
|
|
||||||
private fun loadTypeProto(index: Int): ProtoType {
|
|
||||||
return ProtoType.parseFrom(readType(index), newInstance())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun readSignature(index: Int): CodedInputStream =
|
|
||||||
moduleDeserializer.klib.signature(index, fileIndex).codedInputStream
|
|
||||||
|
|
||||||
private fun loadSignatureProto(index: Int): ProtoIdSignature {
|
|
||||||
return ProtoIdSignature.parseFrom(readSignature(index), newInstance())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun readBody(index: Int): CodedInputStream =
|
|
||||||
moduleDeserializer.klib.body(index, fileIndex).codedInputStream
|
|
||||||
|
|
||||||
private fun loadStatementBodyProto(index: Int): ProtoStatement {
|
|
||||||
return ProtoStatement.parseFrom(readBody(index), newInstance())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadExpressionBodyProto(index: Int): ProtoExpression {
|
|
||||||
return ProtoExpression.parseFrom(readBody(index), newInstance())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadStringProto(index: Int): String {
|
|
||||||
return String(moduleDeserializer.klib.string(index, fileIndex))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getModuleForTopLevelId(idSignature: IdSignature): IrModuleDeserializer? {
|
|
||||||
if (idSignature in moduleDeserializer) return moduleDeserializer
|
|
||||||
return moduleDeserializer.moduleDependencies.firstOrNull { idSignature in it }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findModuleDeserializer(idSig: IdSignature): IrModuleDeserializer {
|
|
||||||
assert(idSig.isPublic)
|
|
||||||
|
|
||||||
val topLevelSig = idSig.topLevelSignature()
|
|
||||||
if (topLevelSig in moduleDeserializer) return moduleDeserializer
|
|
||||||
return moduleDeserializer.moduleDependencies.firstOrNull { topLevelSig in it } ?: handleNoModuleDeserializerFound(
|
|
||||||
idSig,
|
|
||||||
moduleDeserializer.moduleDescriptor,
|
|
||||||
moduleDeserializer.moduleDependencies
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun referenceIrSymbolData(symbol: IrSymbol, signature: IdSignature) {
|
|
||||||
assert(signature.isLocal)
|
|
||||||
fileLocalDeserializationState.deserializedSymbols.putIfAbsent(signature, symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deserializeIrLocalSymbolData(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
|
||||||
assert(idSig.isLocal)
|
|
||||||
|
|
||||||
if (idSig.hasTopLevel) {
|
|
||||||
fileLocalDeserializationState.addIdSignature(idSig.topLevelSignature())
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileLocalDeserializationState.deserializedSymbols.getOrPut(idSig) {
|
|
||||||
referenceDeserializedSymbol(symbolKind, idSig)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun referenceSimpleFunctionByLocalSignature(idSignature: IdSignature) : IrSimpleFunctionSymbol =
|
|
||||||
deserializeIrSymbolData(idSignature, BinarySymbolData.SymbolKind.FUNCTION_SYMBOL) as IrSimpleFunctionSymbol
|
|
||||||
|
|
||||||
fun referencePropertyByLocalSignature(idSignature: IdSignature): IrPropertySymbol =
|
|
||||||
deserializeIrSymbolData(idSignature, BinarySymbolData.SymbolKind.PROPERTY_SYMBOL) as IrPropertySymbol
|
|
||||||
|
|
||||||
private fun deserializeIrSymbolData(idSignature: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
|
||||||
if (idSignature.isLocal) return deserializeIrLocalSymbolData(idSignature, symbolKind)
|
|
||||||
|
|
||||||
return findModuleDeserializer(idSignature).deserializeIrSymbol(idSignature, symbolKind).also {
|
|
||||||
haveSeen.add(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserializeIrSymbolToDeclare(code: Long): Pair<IrSymbol, IdSignature> {
|
|
||||||
val symbolData = parseSymbolData(code)
|
|
||||||
val signature = deserializeIdSignature(symbolData.signatureId)
|
|
||||||
return Pair(deserializeIrSymbolData(signature, symbolData.kind), signature)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parseSymbolData(code: Long): BinarySymbolData = BinarySymbolData.decode(code)
|
|
||||||
|
|
||||||
override fun deserializeIrSymbol(code: Long): IrSymbol {
|
|
||||||
val symbolData = parseSymbolData(code)
|
|
||||||
val signature = deserializeIdSignature(symbolData.signatureId)
|
|
||||||
return deserializeIrSymbolData(signature, symbolData.kind)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserializeIrType(index: Int): IrType {
|
|
||||||
return irTypeCache.getOrPut(index) {
|
|
||||||
val typeData = loadTypeProto(index)
|
|
||||||
deserializeIrTypeData(typeData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserializeIdSignature(index: Int): IdSignature {
|
|
||||||
val sigData = loadSignatureProto(index)
|
|
||||||
return deserializeSignatureData(sigData)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserializeString(index: Int): String =
|
|
||||||
loadStringProto(index)
|
|
||||||
|
|
||||||
override fun deserializeLoopHeader(loopIndex: Int, loopBuilder: () -> IrLoop) =
|
|
||||||
fileLoops.getOrPut(loopIndex, loopBuilder)
|
|
||||||
|
|
||||||
override fun deserializeExpressionBody(index: Int): IrExpression {
|
|
||||||
return if (deserializeBodies) {
|
|
||||||
val bodyData = loadExpressionBodyProto(index)
|
|
||||||
deserializeExpression(bodyData)
|
|
||||||
} else {
|
|
||||||
val errorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT)
|
|
||||||
IrErrorExpressionImpl(-1, -1, errorType, "Expression body is not deserialized yet")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserializeStatementBody(index: Int): IrElement {
|
|
||||||
return if (deserializeBodies) {
|
|
||||||
val bodyData = loadStatementBodyProto(index)
|
|
||||||
deserializeStatement(bodyData)
|
|
||||||
} else {
|
|
||||||
val errorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT)
|
|
||||||
irFactory.createBlockBody(
|
|
||||||
-1, -1, listOf(IrErrorExpressionImpl(-1, -1, errorType, "Statement body is not deserialized yet"))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun referenceIrSymbol(symbol: IrSymbol, signature: IdSignature) {
|
|
||||||
referenceIrSymbolData(symbol, signature)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deserializeFileImplicitDataIfFirstUse() {
|
|
||||||
annotations?.let {
|
|
||||||
file.annotations += deserializeAnnotations(it)
|
|
||||||
annotations = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deserializeAllFileReachableTopLevel() {
|
|
||||||
fileLocalDeserializationState.processPendingDeclarations()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val ByteArray.codedInputStream: CodedInputStream
|
|
||||||
get() {
|
|
||||||
val codedInputStream = CodedInputStream.newInstance(this)
|
|
||||||
codedInputStream.setRecursionLimit(65535) // The default 64 is blatantly not enough for IR.
|
|
||||||
return codedInputStream
|
|
||||||
}
|
|
||||||
|
|
||||||
protected open fun handleNoModuleDeserializerFound(idSignature: IdSignature, currentModule: ModuleDescriptor, dependencies: Collection<IrModuleDeserializer>): IrModuleDeserializer {
|
|
||||||
val message = buildString {
|
val message = buildString {
|
||||||
append("Module $currentModule has reference $idSignature, unfortunately neither itself nor its dependencies ")
|
append("Module $currentModule has reference $idSignature, unfortunately neither itself nor its dependencies ")
|
||||||
dependencies.joinTo(this, "\n\t", "[\n\t", "\n]")
|
dependencies.joinTo(this, "\n\t", "[\n\t", "\n]")
|
||||||
@@ -489,7 +71,7 @@ abstract class KotlinIrLinker(
|
|||||||
throw KotlinIrLinkerInternalException
|
throw KotlinIrLinkerInternalException
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun resolveModuleDeserializer(module: ModuleDescriptor, signature: IdSignature?): IrModuleDeserializer {
|
public open fun resolveModuleDeserializer(module: ModuleDescriptor, signature: IdSignature?): IrModuleDeserializer {
|
||||||
return deserializersForModules[module] ?: run {
|
return deserializersForModules[module] ?: run {
|
||||||
val message = buildString {
|
val message = buildString {
|
||||||
append("Could not load module ")
|
append("Could not load module ")
|
||||||
@@ -515,58 +97,22 @@ abstract class KotlinIrLinker(
|
|||||||
|
|
||||||
protected abstract fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean
|
protected abstract fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean
|
||||||
|
|
||||||
// TODO: the following code worth some refactoring in the nearest future
|
|
||||||
|
|
||||||
private fun handleExpectActualMapping(idSig: IdSignature, rawSymbol: IrSymbol): IrSymbol {
|
|
||||||
val referencingSymbol = if (idSig in expectUniqIdToActualUniqId.keys) {
|
|
||||||
assert(idSig.run { IdSignature.Flags.IS_EXPECT.test() })
|
|
||||||
wrapInDelegatedSymbol(rawSymbol).also { expectSymbols[idSig] = it }
|
|
||||||
} else rawSymbol
|
|
||||||
|
|
||||||
if (idSig in expectUniqIdToActualUniqId.values) {
|
|
||||||
actualSymbols[idSig] = rawSymbol
|
|
||||||
}
|
|
||||||
|
|
||||||
return referencingSymbol
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun referenceDeserializedSymbol(symbolKind: BinarySymbolData.SymbolKind, idSig: IdSignature): IrSymbol = symbolTable.run {
|
|
||||||
when (symbolKind) {
|
|
||||||
BinarySymbolData.SymbolKind.ANONYMOUS_INIT_SYMBOL -> IrAnonymousInitializerSymbolImpl()
|
|
||||||
BinarySymbolData.SymbolKind.CLASS_SYMBOL -> referenceClassFromLinker(idSig)
|
|
||||||
BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL -> referenceConstructorFromLinker(idSig)
|
|
||||||
BinarySymbolData.SymbolKind.TYPE_PARAMETER_SYMBOL -> referenceTypeParameterFromLinker(idSig)
|
|
||||||
BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL -> referenceEnumEntryFromLinker(idSig)
|
|
||||||
BinarySymbolData.SymbolKind.STANDALONE_FIELD_SYMBOL -> referenceFieldFromLinker(idSig)
|
|
||||||
BinarySymbolData.SymbolKind.FIELD_SYMBOL -> referenceFieldFromLinker(idSig)
|
|
||||||
BinarySymbolData.SymbolKind.FUNCTION_SYMBOL -> referenceSimpleFunctionFromLinker(idSig)
|
|
||||||
BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL -> referenceTypeAliasFromLinker(idSig)
|
|
||||||
BinarySymbolData.SymbolKind.PROPERTY_SYMBOL -> referencePropertyFromLinker(idSig)
|
|
||||||
BinarySymbolData.SymbolKind.VARIABLE_SYMBOL -> IrVariableSymbolImpl()
|
|
||||||
BinarySymbolData.SymbolKind.VALUE_PARAMETER_SYMBOL -> IrValueParameterSymbolImpl()
|
|
||||||
BinarySymbolData.SymbolKind.RECEIVER_PARAMETER_SYMBOL -> IrValueParameterSymbolImpl()
|
|
||||||
BinarySymbolData.SymbolKind.LOCAL_DELEGATED_PROPERTY_SYMBOL ->
|
|
||||||
IrLocalDelegatedPropertySymbolImpl()
|
|
||||||
else -> error("Unexpected classifier symbol kind: $symbolKind for signature $idSig")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deserializeAllReachableTopLevels() {
|
private fun deserializeAllReachableTopLevels() {
|
||||||
while (modulesWithReachableTopLevels.isNotEmpty()) {
|
while (modulesWithReachableTopLevels.isNotEmpty()) {
|
||||||
val moduleDeserializer = modulesWithReachableTopLevels.first()
|
val moduleDeserializationState = modulesWithReachableTopLevels.first()
|
||||||
modulesWithReachableTopLevels.remove(moduleDeserializer)
|
modulesWithReachableTopLevels.remove(moduleDeserializationState)
|
||||||
|
|
||||||
moduleDeserializer.deserializeReachableDeclarations()
|
moduleDeserializationState.deserializeReachableDeclarations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findDeserializedDeclarationForSymbol(symbol: IrSymbol): DeclarationDescriptor? {
|
private fun findDeserializedDeclarationForSymbol(symbol: IrSymbol): DeclarationDescriptor? {
|
||||||
assert(symbol.isPublicApi || symbol.descriptor.module === currentModule || platformSpecificSymbol(symbol))
|
assert(symbol.isPublicApi || symbol.descriptor.module === currentModule || platformSpecificSymbol(symbol))
|
||||||
|
|
||||||
if (haveSeen.contains(symbol)) {
|
if (symbol in triedToDeserializeDeclarationForSymbol || symbol in deserializedSymbols) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
haveSeen.add(symbol)
|
triedToDeserializeDeclarationForSymbol.add(symbol)
|
||||||
|
|
||||||
val descriptor = symbol.descriptor
|
val descriptor = symbol.descriptor
|
||||||
|
|
||||||
@@ -586,6 +132,7 @@ abstract class KotlinIrLinker(
|
|||||||
if (!symbol.hasDescriptor) return null
|
if (!symbol.hasDescriptor) return null
|
||||||
|
|
||||||
val descriptor = symbol.descriptor
|
val descriptor = symbol.descriptor
|
||||||
|
|
||||||
if (descriptor is CallableMemberDescriptor) {
|
if (descriptor is CallableMemberDescriptor) {
|
||||||
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||||
// skip fake overrides
|
// skip fake overrides
|
||||||
@@ -661,12 +208,43 @@ abstract class KotlinIrLinker(
|
|||||||
override fun postProcess() {
|
override fun postProcess() {
|
||||||
finalizeExpectActualLinker()
|
finalizeExpectActualLinker()
|
||||||
fakeOverrideBuilder.provideFakeOverrides()
|
fakeOverrideBuilder.provideFakeOverrides()
|
||||||
haveSeen.clear()
|
triedToDeserializeDeclarationForSymbol.clear()
|
||||||
|
deserializedSymbols.clear()
|
||||||
|
|
||||||
// TODO: fix IrPluginContext to make it not produce additional external reference
|
// TODO: fix IrPluginContext to make it not produce additional external reference
|
||||||
// symbolTable.noUnboundLeft("unbound after fake overrides:")
|
// symbolTable.noUnboundLeft("unbound after fake overrides:")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun handleExpectActualMapping(idSig: IdSignature, rawSymbol: IrSymbol): IrSymbol {
|
||||||
|
|
||||||
|
// Actual signature
|
||||||
|
if (idSig in expectUniqIdToActualUniqId.values) {
|
||||||
|
actualSymbols[idSig] = rawSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expect signature
|
||||||
|
expectUniqIdToActualUniqId[idSig]?.let { actualSig ->
|
||||||
|
assert(idSig.run { IdSignature.Flags.IS_EXPECT.test() })
|
||||||
|
|
||||||
|
val referencingSymbol = wrapInDelegatedSymbol(rawSymbol)
|
||||||
|
|
||||||
|
expectSymbols[idSig] = referencingSymbol
|
||||||
|
|
||||||
|
// Trigger actual symbol deserialization
|
||||||
|
topLevelActualUniqItToDeserializer[actualSig]?.let { moduleDeserializer -> // Not null if top-level
|
||||||
|
val actualSymbol = actualSymbols[actualSig]
|
||||||
|
// Check if
|
||||||
|
if (actualSymbol == null || !actualSymbol.isBound) {
|
||||||
|
moduleDeserializer.addModuleReachableTopLevel(actualSig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return referencingSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
return rawSymbol
|
||||||
|
}
|
||||||
|
|
||||||
private fun topLevelKindToSymbolKind(kind: IrDeserializer.TopLevelSymbolKind): BinarySymbolData.SymbolKind {
|
private fun topLevelKindToSymbolKind(kind: IrDeserializer.TopLevelSymbolKind): BinarySymbolData.SymbolKind {
|
||||||
return when (kind) {
|
return when (kind) {
|
||||||
IrDeserializer.TopLevelSymbolKind.CLASS_SYMBOL -> BinarySymbolData.SymbolKind.CLASS_SYMBOL
|
IrDeserializer.TopLevelSymbolKind.CLASS_SYMBOL -> BinarySymbolData.SymbolKind.CLASS_SYMBOL
|
||||||
@@ -690,16 +268,7 @@ abstract class KotlinIrLinker(
|
|||||||
// because the expect can not see the actual higher in the module dependency dag.
|
// because the expect can not see the actual higher in the module dependency dag.
|
||||||
// So we force deserialization of actuals for all deserialized expect symbols here.
|
// So we force deserialization of actuals for all deserialized expect symbols here.
|
||||||
private fun finalizeExpectActualLinker() {
|
private fun finalizeExpectActualLinker() {
|
||||||
expectUniqIdToActualUniqId.filter { topLevelActualUniqItToDeserializer[it.value] != null }.forEach {
|
// All actuals have been deserialized, retarget delegating symbols from expects to actuals.
|
||||||
val expectSymbol = expectSymbols[it.key]
|
|
||||||
val actualSymbol = actualSymbols[it.value]
|
|
||||||
if (expectSymbol != null && (actualSymbol == null || !actualSymbol.isBound)) {
|
|
||||||
topLevelActualUniqItToDeserializer[it.value]!!.addModuleReachableTopLevel(it.value)
|
|
||||||
deserializeAllReachableTopLevels()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now after all actuals have been deserialized, retarget delegating symbols from expects to actuals.
|
|
||||||
expectUniqIdToActualUniqId.forEach {
|
expectUniqIdToActualUniqId.forEach {
|
||||||
val expectSymbol = expectSymbols[it.key]
|
val expectSymbol = expectSymbols[it.key]
|
||||||
val actualSymbol = actualSymbols[it.value]
|
val actualSymbol = actualSymbols[it.value]
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ class JsIrLinker(
|
|||||||
JsModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy, klib.libContainsErrorCode)
|
JsModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy, klib.libContainsErrorCode)
|
||||||
|
|
||||||
private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy, allowErrorCode: Boolean) :
|
private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy, allowErrorCode: Boolean) :
|
||||||
KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy, allowErrorCode)
|
BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategy, allowErrorCode)
|
||||||
|
|
||||||
override fun createCurrentModuleDeserializer(moduleFragment: IrModuleFragment, dependencies: Collection<IrModuleDeserializer>): IrModuleDeserializer {
|
override fun createCurrentModuleDeserializer(moduleFragment: IrModuleFragment, dependencies: Collection<IrModuleDeserializer>): IrModuleDeserializer {
|
||||||
val currentModuleDeserializer = super.createCurrentModuleDeserializer(moduleFragment, dependencies)
|
val currentModuleDeserializer = super.createCurrentModuleDeserializer(moduleFragment, dependencies)
|
||||||
|
|||||||
+1
-1
@@ -61,7 +61,7 @@ class JvmIrLinker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private inner class JvmModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy) :
|
private inner class JvmModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy) :
|
||||||
KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy)
|
BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategy)
|
||||||
|
|
||||||
private fun DeclarationDescriptor.isJavaDescriptor(): Boolean {
|
private fun DeclarationDescriptor.isJavaDescriptor(): Boolean {
|
||||||
if (this is PackageFragmentDescriptor) {
|
if (this is PackageFragmentDescriptor) {
|
||||||
|
|||||||
Reference in New Issue
Block a user