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)
|
||||
}
|
||||
|
||||
override fun deserializeReachableDeclarations() {
|
||||
icDeserializer.deserializeReachableDeclarations()
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.isDirtyDescriptor(): Boolean {
|
||||
if (this is PropertyAccessorDescriptor) return correspondingProperty.isDirtyDescriptor()
|
||||
// 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 deserializeReachableDeclarations() { error("Unsupported Operation") }
|
||||
|
||||
abstract val moduleFragment: IrModuleFragment
|
||||
|
||||
abstract val moduleDependencies: Collection<IrModuleDeserializer>
|
||||
@@ -103,10 +101,6 @@ class IrModuleDeserializerWithBuiltIns(
|
||||
override fun referencePropertyByLocalSignature(file: IrFile, idSignature: IdSignature): IrPropertySymbol =
|
||||
delegate.referencePropertyByLocalSignature(file, idSignature)
|
||||
|
||||
override fun deserializeReachableDeclarations() {
|
||||
delegate.deserializeReachableDeclarations()
|
||||
}
|
||||
|
||||
private fun computeFunctionDescriptor(className: String): FunctionClassDescriptor {
|
||||
val isK = className[0] == 'K'
|
||||
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}")
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
-483
@@ -11,25 +11,15 @@ import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolD
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
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.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
|
||||
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.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
|
||||
import org.jetbrains.kotlin.ir.linkage.KotlinIrLinkerInternalException
|
||||
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.library.IrLibrary
|
||||
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.ExtensionRegistryLite.newInstance
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
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(
|
||||
private val currentModule: ModuleDescriptor?,
|
||||
val messageLogger: IrMessageLogger,
|
||||
val builtIns: IrBuiltIns,
|
||||
val symbolTable: SymbolTable,
|
||||
private val exportedDependencies: List<ModuleDescriptor>
|
||||
private val exportedDependencies: List<ModuleDescriptor>,
|
||||
) : IrDeserializer, FileLocalAwareLinker {
|
||||
|
||||
// Kotlin-MPP related data. Consider some refactoring
|
||||
private val expectUniqIdToActualUniqId = mutableMapOf<IdSignature, IdSignature>()
|
||||
private val topLevelActualUniqItToDeserializer = mutableMapOf<IdSignature, IrModuleDeserializer>()
|
||||
private val expectSymbols = mutableMapOf<IdSignature, IrSymbol>()
|
||||
private val actualSymbols = mutableMapOf<IdSignature, IrSymbol>()
|
||||
internal val expectUniqIdToActualUniqId = mutableMapOf<IdSignature, IdSignature>()
|
||||
internal val topLevelActualUniqItToDeserializer = mutableMapOf<IdSignature, IrModuleDeserializer>()
|
||||
internal val expectSymbols = 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>
|
||||
protected val deserializersForModules = mutableMapOf<ModuleDescriptor, IrModuleDeserializer>()
|
||||
@@ -72,411 +53,12 @@ abstract class KotlinIrLinker(
|
||||
|
||||
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>
|
||||
|
||||
abstract inner class BasicIrModuleDeserializer(moduleDescriptor: ModuleDescriptor, override val klib: IrLibrary, override val strategy: DeserializationStrategy, private val containsErrorCode: Boolean = false) :
|
||||
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 {
|
||||
public open fun handleNoModuleDeserializerFound(idSignature: IdSignature, currentModule: ModuleDescriptor, dependencies: Collection<IrModuleDeserializer>): IrModuleDeserializer {
|
||||
val message = buildString {
|
||||
append("Module $currentModule has reference $idSignature, unfortunately neither itself nor its dependencies ")
|
||||
dependencies.joinTo(this, "\n\t", "[\n\t", "\n]")
|
||||
@@ -489,7 +71,7 @@ abstract class KotlinIrLinker(
|
||||
throw KotlinIrLinkerInternalException
|
||||
}
|
||||
|
||||
protected open fun resolveModuleDeserializer(module: ModuleDescriptor, signature: IdSignature?): IrModuleDeserializer {
|
||||
public open fun resolveModuleDeserializer(module: ModuleDescriptor, signature: IdSignature?): IrModuleDeserializer {
|
||||
return deserializersForModules[module] ?: run {
|
||||
val message = buildString {
|
||||
append("Could not load module ")
|
||||
@@ -515,58 +97,22 @@ abstract class KotlinIrLinker(
|
||||
|
||||
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() {
|
||||
while (modulesWithReachableTopLevels.isNotEmpty()) {
|
||||
val moduleDeserializer = modulesWithReachableTopLevels.first()
|
||||
modulesWithReachableTopLevels.remove(moduleDeserializer)
|
||||
val moduleDeserializationState = modulesWithReachableTopLevels.first()
|
||||
modulesWithReachableTopLevels.remove(moduleDeserializationState)
|
||||
|
||||
moduleDeserializer.deserializeReachableDeclarations()
|
||||
moduleDeserializationState.deserializeReachableDeclarations()
|
||||
}
|
||||
}
|
||||
|
||||
private fun findDeserializedDeclarationForSymbol(symbol: IrSymbol): DeclarationDescriptor? {
|
||||
assert(symbol.isPublicApi || symbol.descriptor.module === currentModule || platformSpecificSymbol(symbol))
|
||||
|
||||
if (haveSeen.contains(symbol)) {
|
||||
if (symbol in triedToDeserializeDeclarationForSymbol || symbol in deserializedSymbols) {
|
||||
return null
|
||||
}
|
||||
haveSeen.add(symbol)
|
||||
triedToDeserializeDeclarationForSymbol.add(symbol)
|
||||
|
||||
val descriptor = symbol.descriptor
|
||||
|
||||
@@ -586,6 +132,7 @@ abstract class KotlinIrLinker(
|
||||
if (!symbol.hasDescriptor) return null
|
||||
|
||||
val descriptor = symbol.descriptor
|
||||
|
||||
if (descriptor is CallableMemberDescriptor) {
|
||||
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||
// skip fake overrides
|
||||
@@ -661,12 +208,43 @@ abstract class KotlinIrLinker(
|
||||
override fun postProcess() {
|
||||
finalizeExpectActualLinker()
|
||||
fakeOverrideBuilder.provideFakeOverrides()
|
||||
haveSeen.clear()
|
||||
triedToDeserializeDeclarationForSymbol.clear()
|
||||
deserializedSymbols.clear()
|
||||
|
||||
// TODO: fix IrPluginContext to make it not produce additional external reference
|
||||
// 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 {
|
||||
return when (kind) {
|
||||
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.
|
||||
// So we force deserialization of actuals for all deserialized expect symbols here.
|
||||
private fun finalizeExpectActualLinker() {
|
||||
expectUniqIdToActualUniqId.filter { topLevelActualUniqItToDeserializer[it.value] != null }.forEach {
|
||||
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.
|
||||
// All actuals have been deserialized, retarget delegating symbols from expects to actuals.
|
||||
expectUniqIdToActualUniqId.forEach {
|
||||
val expectSymbol = expectSymbols[it.key]
|
||||
val actualSymbol = actualSymbols[it.value]
|
||||
@@ -773,4 +342,4 @@ enum class DeserializationStrategy(
|
||||
EXPLICITLY_EXPORTED(true, true, false, true),
|
||||
ONLY_DECLARATION_HEADERS(false, false, false, false),
|
||||
WITH_INLINE_BODIES(false, false, false, true)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -41,7 +41,7 @@ class JsIrLinker(
|
||||
JsModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy, klib.libContainsErrorCode)
|
||||
|
||||
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 {
|
||||
val currentModuleDeserializer = super.createCurrentModuleDeserializer(moduleFragment, dependencies)
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ class JvmIrLinker(
|
||||
}
|
||||
|
||||
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 {
|
||||
if (this is PackageFragmentDescriptor) {
|
||||
|
||||
Reference in New Issue
Block a user