diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index 5428271c765..57590c162e0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -53,6 +53,7 @@ import java.lang.System.out import kotlin.LazyThreadSafetyMode.PUBLICATION import kotlin.reflect.KProperty import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.serialization.KotlinMangler import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl @@ -62,7 +63,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl */ internal const val SYNTHETIC_OFFSET = -2 -internal class SpecialDeclarationsFactory(val context: Context) { +internal class SpecialDeclarationsFactory(val context: Context) : KotlinMangler by KonanMangler { private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) } private val outerThisFields = mutableMapOf() private val bridgesDescriptors = mutableMapOf, IrSimpleFunction>() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index 1912b2efc2e..1b2c437d1d3 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.backend.common.LoggingContext import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.phaser.* +import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols @@ -13,6 +14,7 @@ import org.jetbrains.kotlin.backend.konan.serialization.* import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.util.patchDeclarationParents @@ -67,7 +69,7 @@ internal val psiToIrPhase = konanUnitPhase( val forwardDeclarationsModuleDescriptor = moduleDescriptor.allDependencyModules.firstOrNull { it.isForwardDeclarationModule } - val deserializer = KonanIrModuleDeserializer( + val deserializer = KonanIrLinker( moduleDescriptor, this as LoggingContext, generatorContext.irBuiltIns, @@ -144,8 +146,8 @@ internal val patchDeclarationParents0Phase = konanUnitPhase( internal val serializerPhase = konanUnitPhase( op = { - val declarationTable = DeclarationTable(irModule!!.irBuiltins, DescriptorTable()) - val serializedIr = IrModuleSerializer(this, declarationTable).serializedIrModule(irModule!!) + val declarationTable = KonanDeclarationTable(irModule!!.irBuiltins, DescriptorTable()).apply { loadKnownBuiltins() } + val serializedIr = KonanIrModuleSerializer(this, declarationTable).serializedIrModule(irModule!!) val serializer = KonanSerializationUtil(this, config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!, declarationTable) serializedLinkData = serializer.serializeModule(moduleDescriptor, /*if (!config.isInteropStubs) serializedIr else null*/ serializedIr) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt index 28fbfd1eb30..780ba9928f6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.backend.konan.library import llvm.LLVMModuleRef -import org.jetbrains.kotlin.backend.konan.serialization.UniqId +import org.jetbrains.kotlin.backend.common.serialization.SerializedIr import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.konan.library.KonanLibraryVersioning import org.jetbrains.kotlin.konan.properties.Properties @@ -31,12 +31,6 @@ class LinkData( val ir: SerializedIr? = null ) -class SerializedIr ( - val module: ByteArray, - val combinedDeclarationFilePath: String, - val debugIndex: Map -) - interface MetadataWriter { fun addLinkData(linkData: LinkData) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataWriterImpl.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataWriterImpl.kt index 1d224ce2457..b766a456f19 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataWriterImpl.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataWriterImpl.kt @@ -30,7 +30,5 @@ internal class MetadataWriterImpl(libraryLayout: KonanLibraryLayout): KonanLibra // TODO: use Files.move. File(it).copyTo(irFile) } - val lines = linkData.ir?.debugIndex?.map { entry -> "${entry.key}: ${entry.value}" } - if (lines != null) irIndex.writeLines(lines) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt index d3aec1cf73b..2d69c32bdfa 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt @@ -6,11 +6,15 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.LLVMTypeRef +import org.jetbrains.kotlin.backend.common.serialization.KotlinMangler +import org.jetbrains.kotlin.backend.common.serialization.KotlinManglerImpl +import org.jetbrains.kotlin.backend.common.serialization.isVararg import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.descriptors.externalSymbolOrThrow import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationValue import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.llvm.KonanMangler.isExported import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -29,261 +33,118 @@ import org.jetbrains.kotlin.name.Name // TODO: revise the naming scheme to ensure it produces unique names. // TODO: do not serialize descriptors of non-exported declarations. -/** - * Defines whether the declaration is exported, i.e. visible from other modules. - * - * Exported declarations must have predictable and stable ABI - * that doesn't depend on any internal transformations (e.g. IR lowering), - * and so should be computable from the descriptor itself without checking a backend state. - */ -internal tailrec fun IrDeclaration.isExported(): Boolean { - // TODO: revise - val descriptorAnnotations = this.descriptor.annotations - if (descriptorAnnotations.hasAnnotation(symbolNameAnnotation)) { - // Treat any `@SymbolName` declaration as exported. - return true - } - if (descriptorAnnotations.hasAnnotation(exportForCppRuntimeAnnotation)) { - // Treat any `@ExportForCppRuntime` declaration as exported. - return true - } - if (descriptorAnnotations.hasAnnotation(cnameAnnotation)) { - // Treat `@CName` declaration as exported. - return true - } - if (descriptorAnnotations.hasAnnotation(exportForCompilerAnnotation)) { - return true - } - if (descriptorAnnotations.hasAnnotation(publishedApiAnnotation)){ - return true - } +object KonanMangler : KotlinManglerImpl() { - if (this.isAnonymousObject) - return false - - if (this is IrConstructor && constructedClass.kind.isSingleton) { - // Currently code generator can access the constructor of the singleton, - // so ignore visibility of the constructor itself. - return constructedClass.isExported() - } - - if (this is IrFunction) { - val descriptor = this.descriptor - // TODO: this code is required because accessor doesn't have a reference to property. - if (descriptor is PropertyAccessorDescriptor) { - val property = descriptor.correspondingProperty - if (property.annotations.hasAnnotation(publishedApiAnnotation)) return true - } - } - - val visibility = when (this) { - is IrClass -> this.visibility - is IrFunction -> this.visibility - is IrProperty -> this.visibility - is IrField -> this.visibility - else -> null - } + override val String.hashMangle get() = this.localHash.value /** - * note: about INTERNAL - with support of friend modules we let frontend to deal with internal declarations. + * Defines whether the declaration is exported, i.e. visible from other modules. + * + * Exported declarations must have predictable and stable ABI + * that doesn't depend on any internal transformations (e.g. IR lowering), + * and so should be computable from the descriptor itself without checking a backend state. */ - if (visibility != null && !visibility.isPublicAPI && visibility != Visibilities.INTERNAL) { - // If the declaration is explicitly marked as non-public, - // then it must not be accessible from other modules. + override fun IrDeclaration.isPlatformSpecificExported(): Boolean { + // TODO: revise + val descriptorAnnotations = this.descriptor.annotations + if (descriptorAnnotations.hasAnnotation(symbolNameAnnotation)) { + // Treat any `@SymbolName` declaration as exported. + return true + } + if (descriptorAnnotations.hasAnnotation(exportForCppRuntimeAnnotation)) { + // Treat any `@ExportForCppRuntime` declaration as exported. + return true + } + if (descriptorAnnotations.hasAnnotation(cnameAnnotation)) { + // Treat `@CName` declaration as exported. + return true + } + if (descriptorAnnotations.hasAnnotation(exportForCompilerAnnotation)) { + return true + } + return false } - val parent = this.parent - if (parent is IrDeclaration) { - return parent.isExported() - } + private val symbolNameAnnotation = RuntimeNames.symbolName - return true -} + private val cnameAnnotation = FqName("kotlin.native.CName") -private val symbolNameAnnotation = RuntimeNames.symbolName + private val exportForCppRuntimeAnnotation = RuntimeNames.exportForCppRuntime -private val cnameAnnotation = FqName("kotlin.native.CName") + private val exportForCompilerAnnotation = RuntimeNames.exportForCompilerAnnotation -private val exportForCppRuntimeAnnotation = RuntimeNames.exportForCppRuntime -private val exportForCompilerAnnotation = RuntimeNames.exportForCompilerAnnotation - -private val publishedApiAnnotation = FqName("kotlin.PublishedApi") - -private fun acyclicTypeMangler(visited: MutableSet, type: IrType): String { - val descriptor = (type.classifierOrNull as? IrTypeParameterSymbol)?.owner - if (descriptor != null) { - val upperBounds = if (visited.contains(descriptor)) "" else { - - visited.add(descriptor) - - descriptor.superTypes.map { - val bound = acyclicTypeMangler(visited, it) - if (bound == "kotlin.Any?") "" else "_$bound" - }.joinToString("") - } - return "#GENERIC${if (type.isMarkedNullable()) "?" else ""}$upperBounds" - } - - var hashString = type.getClass()!!.fqNameSafe.asString() - if (type !is IrSimpleType) error(type) - if (!type.arguments.isEmpty()) { - hashString += "<${type.arguments.map { - when (it) { - is IrStarProjection -> "#STAR" - is IrTypeProjection -> { - val variance = it.variance.label - val projection = if (variance == "") "" else "${variance}_" - projection + acyclicTypeMangler(visited, it.type) - } - else -> error(it) - } - }.joinToString(",")}>" - } - - if (type.hasQuestionMark) hashString += "?" - return hashString -} - -private fun typeToHashString(type: IrType) - = acyclicTypeMangler(mutableSetOf(), type) - -internal val IrValueParameter.extensionReceiverNamePart: String - get() = "@${typeToHashString(this.type)}." - -private val IrFunction.signature: String - get() { - val extensionReceiverPart = this.extensionReceiverParameter?.extensionReceiverNamePart ?: "" - val argsPart = this.valueParameters.map { + override val IrFunction.argsPart get() = this.valueParameters.map { // TODO: there are clashes originating from ObjectiveC interop. // kotlinx.cinterop.ObjCClassOf.create(format: kotlin.String): T defined in platform.Foundation in file Foundation.kt // and // kotlinx.cinterop.ObjCClassOf.create(string: kotlin.String): T defined in platform.Foundation in file Foundation.kt - val argName = if (this.hasObjCMethodAnnotation || this.hasObjCFactoryAnnotation || this.isObjCClassMethod()) "${it.name}:" else "" - "$argName${typeToHashString(it.type)}${if (it.isVararg) "_VarArg" else ""}" - }.joinToString(";") - // Distinguish value types and references - it's needed for calling virtual methods through bridges. - // Also is function has type arguments - frontend allows exactly matching overrides. - val signatureSuffix = - when { - this.typeParameters.isNotEmpty() -> "Generic" - returnType.isInlined() -> "ValueType" - !returnType.isUnitOrNullableUnit() -> typeToHashString(returnType) - else -> "" + val argName = + if (this.hasObjCMethodAnnotation || this.hasObjCFactoryAnnotation || this.isObjCClassMethod()) "${it.name}:" else "" + "$argName${typeToHashString(it.type)}${if (it.isVararg) "_VarArg" else ""}" + }.joinToString(";") + + + override val IrFunction.platformSpecificFunctionName: String? + get() { + (if (this is IrConstructor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo() + ?.let { + return buildString { + if (extensionReceiverParameter != null) { + append(extensionReceiverParameter!!.type.getClass()!!.name) + append(".") + } + + append("objc:") + append(it.selector) + if (this@platformSpecificFunctionName is IrConstructor && this@platformSpecificFunctionName.isObjCConstructor) append("#Constructor") + + // We happen to have the clashing combinations such as + //@ObjCMethod("issueChallengeToPlayers:message:", "objcKniBridge1165") + //external fun GKScore.issueChallengeToPlayers(playerIDs: List<*>?, message: String?): Unit + //@ObjCMethod("issueChallengeToPlayers:message:", "objcKniBridge1172") + //external fun GKScore.issueChallengeToPlayers(playerIDs: List<*>?, message: String?): Unit + // So disambiguate by the name of the bridge for now. + // TODO: idealy we'd never generate such identical declarations. + + if (this@platformSpecificFunctionName is IrSimpleFunction && this@platformSpecificFunctionName.hasObjCMethodAnnotation()) { + this@platformSpecificFunctionName.objCMethodArgValue("selector")?.let { append("#$it") } + this@platformSpecificFunctionName.objCMethodArgValue("bridge")?.let { append("#$it") } + } + } } - return "$extensionReceiverPart($argsPart)$signatureSuffix" - } + return null + } -// TODO: rename to indicate that it has signature included -internal val IrFunction.functionName: String - get() { - (if (this is IrConstructor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo()?.let { - return buildString { - if (extensionReceiverParameter != null) { - append(extensionReceiverParameter!!.type.getClass()!!.name) - append(".") - } + internal val IrFunction.symbolName: String + get() { + if (!this.isExported()) { + throw AssertionError(this.descriptor.toString()) + } - append("objc:") - append(it.selector) - if (this@functionName is IrConstructor && this@functionName.isObjCConstructor) append("#Constructor") - - // We happen to have the clashing combinations such as - //@ObjCMethod("issueChallengeToPlayers:message:", "objcKniBridge1165") - //external fun GKScore.issueChallengeToPlayers(playerIDs: List<*>?, message: String?): Unit - //@ObjCMethod("issueChallengeToPlayers:message:", "objcKniBridge1172") - //external fun GKScore.issueChallengeToPlayers(playerIDs: List<*>?, message: String?): Unit - // So disambiguate by the name of the bridge for now. - // TODO: idealy we'd never generate such identical declarations. - - if (this@functionName is IrSimpleFunction && this@functionName.hasObjCMethodAnnotation()) { - this@functionName.objCMethodArgValue("selector") ?.let { append("#$it") } - this@functionName.objCMethodArgValue("bridge") ?.let { append("#$it") } + if (isExternal) { + this.descriptor.externalSymbolOrThrow()?.let { + return it } } - } - val name = this.name.mangleIfInternal(this.module, this.visibility) - - return "$name$signature" - } - -private fun Name.mangleIfInternal(moduleDescriptor: ModuleDescriptor, visibility: Visibility): String = - if (visibility != Visibilities.INTERNAL) { - this.asString() - } else { - val moduleName = moduleDescriptor.name.asString() - .let { it.substring(1, it.lastIndex) } // Remove < and >. - - "$this\$$moduleName" - } - -internal val IrFunction.symbolName: String - get() { - if (!this.isExported()) { - throw AssertionError(this.descriptor.toString()) - } - - if (isExternal) { - this.descriptor.externalSymbolOrThrow()?.let { - return it + this.descriptor.annotations.findAnnotation(exportForCppRuntimeAnnotation)?.let { + val name = getAnnotationValue(it) ?: this.name.asString() + return name // no wrapping currently required } + + val parent = this.parent + + val containingDeclarationPart = parent.fqNameSafe.let { + if (it.isRoot) "" else "$it." + } + return "kfun:$containingDeclarationPart$functionName" } - - this.descriptor.annotations.findAnnotation(exportForCppRuntimeAnnotation)?.let { - val name = getAnnotationValue(it) ?: this.name.asString() - return name // no wrapping currently required - } - - val parent = this.parent - - val containingDeclarationPart = parent.fqNameSafe.let { - if (it.isRoot) "" else "$it." - } - return "kfun:$containingDeclarationPart$functionName" - } - -internal val IrField.symbolName: String - get() { - val containingDeclarationPart = parent.fqNameSafe.let { - if (it.isRoot) "" else "$it." - } - return "kfield:$containingDeclarationPart$name" - - } - -// TODO: bring here dependencies of this method? -internal fun RuntimeAware.getLlvmFunctionType(function: IrFunction): LLVMTypeRef { - val returnType = when { - function is IrConstructor -> voidType - function.isSuspend -> kObjHeaderPtr // Suspend functions return Any?. - else -> getLLVMReturnType(function.returnType) - } - val paramTypes = ArrayList(function.allParameters.map { getLLVMType(it.type) }) - if (function.isSuspend) - paramTypes.add(kObjHeaderPtr) // Suspend functions have implicit parameter of type Continuation<>. - if (isObjectType(returnType)) paramTypes.add(kObjHeaderPtrPtr) - - return functionType(returnType, isVarArg = false, paramTypes = *paramTypes.toTypedArray()) } -internal fun RuntimeAware.getLlvmFunctionType(symbol: DataFlowIR.FunctionSymbol): LLVMTypeRef { - val returnType = if (symbol.returnsUnit) voidType else getLLVMType(symbol.returnParameter.type) - val paramTypes = ArrayList(symbol.parameters.map { getLLVMType(it.type) }) - if (isObjectType(returnType)) paramTypes.add(kObjHeaderPtrPtr) - - return functionType(returnType, isVarArg = false, paramTypes = *paramTypes.toTypedArray()) -} - -internal val IrClass.typeInfoSymbolName: String - get() { - assert (this.isExported()) - return "ktype:" + this.fqNameSafe.toString() - } - internal val IrClass.writableTypeInfoSymbolName: String get() { assert (this.isExported()) @@ -311,6 +172,39 @@ internal val IrClass.objectInstanceShadowFieldSymbolName: String return "kshadowobjref:$fqNameSafe" } +val IrFunction.functionName get() = with(KonanMangler) { functionName } + +val IrFunction.symbolName get() = with(KonanMangler) { symbolName } + +val IrField.symbolName get() = with(KonanMangler) { symbolName } + +val IrClass.typeInfoSymbolName get() = with(KonanMangler) { typeInfoSymbolName } + +fun IrDeclaration.isExported() = with(KonanMangler) { isExported() } + +// TODO: bring here dependencies of this method? +internal fun RuntimeAware.getLlvmFunctionType(function: IrFunction): LLVMTypeRef { + val returnType = when { + function is IrConstructor -> voidType + function.isSuspend -> kObjHeaderPtr // Suspend functions return Any?. + else -> getLLVMReturnType(function.returnType) + } + val paramTypes = ArrayList(function.allParameters.map { getLLVMType(it.type) }) + if (function.isSuspend) + paramTypes.add(kObjHeaderPtr) // Suspend functions have implicit parameter of type Continuation<>. + if (isObjectType(returnType)) paramTypes.add(kObjHeaderPtrPtr) + + return functionType(returnType, isVarArg = false, paramTypes = *paramTypes.toTypedArray()) +} + +internal fun RuntimeAware.getLlvmFunctionType(symbol: DataFlowIR.FunctionSymbol): LLVMTypeRef { + val returnType = if (symbol.returnsUnit) voidType else getLLVMType(symbol.returnParameter.type) + val paramTypes = ArrayList(symbol.parameters.map { getLLVMType(it.type) }) + if (isObjectType(returnType)) paramTypes.add(kObjHeaderPtrPtr) + + return functionType(returnType, isVarArg = false, paramTypes = *paramTypes.toTypedArray()) +} + internal val IrClass.typeInfoHasVtableAttached: Boolean get() = !this.isAbstract() && !this.isExternalObjCClass() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index 74346216e98..3447e2a9080 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.konan.llvm import kotlinx.cinterop.* import llvm.* +import org.jetbrains.kotlin.backend.common.serialization.KotlinMangler import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.descriptors.isInterface import org.jetbrains.kotlin.backend.konan.llvm.objc.* diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DeclarationTable.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DeclarationTable.kt deleted file mode 100644 index 38f79e2b5c8..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DeclarationTable.kt +++ /dev/null @@ -1,56 +0,0 @@ -package org.jetbrains.kotlin.backend.konan.serialization - -import org.jetbrains.kotlin.backend.konan.llvm.* -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrAnonymousInitializerImpl -import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns - -class DescriptorTable { - private val descriptors = mutableMapOf() - fun put(descriptor: DeclarationDescriptor, uniqId: UniqId) { - descriptors.getOrPut(descriptor) { uniqId.index } - } - fun get(descriptor: DeclarationDescriptor) = descriptors[descriptor] -} - -// TODO: We don't manage id clashes anyhow now. -class DeclarationTable(val builtIns: IrBuiltIns, val descriptorTable: DescriptorTable) { - - private val table = mutableMapOf() - val debugIndex = mutableMapOf() - val descriptors = descriptorTable - private var currentIndex = 0L - - init { - builtIns.knownBuiltins.forEach { - table.put(it, UniqId(currentIndex ++, false)) - } - } - - fun uniqIdByDeclaration(value: IrDeclaration): UniqId = table.getOrPut(value) { - val index = if (value.origin == IrDeclarationOrigin.FAKE_OVERRIDE || - !value.isExported() - || value is IrVariable - || value is IrTypeParameter - || value is IrValueParameter - || value is IrAnonymousInitializerImpl - ) { - - UniqId(currentIndex++, true) - } else { - UniqId(value.uniqIdIndex, false) - } - - // It can grow as large as 1/3 of ir/* size. - // debugIndex.put(index) { - // "${if (index.isLocal) "" else value.uniqSymbolName()} descriptor = ${value.descriptor}" - //}.also {it == null} - - index - } -} - -// This is what we pre-populate tables with -val IrBuiltIns.knownBuiltins - get() = irBuiltInsExternalPackageFragment.declarations diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleDeserializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleDeserializer.kt deleted file mode 100644 index 3cc32dde6dd..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleDeserializer.kt +++ /dev/null @@ -1,1113 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.konan.serialization - -import org.jetbrains.kotlin.backend.common.LoggingContext -import org.jetbrains.kotlin.backend.common.descriptors.* -import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory -import org.jetbrains.kotlin.backend.common.ir.ir2string -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.* -import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns -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.ir.types.impl.* -import org.jetbrains.kotlin.ir.util.IrDeserializer -import org.jetbrains.kotlin.ir.util.SymbolTable -import org.jetbrains.kotlin.ir.util.render -import org.jetbrains.kotlin.metadata.KonanIr -import org.jetbrains.kotlin.metadata.KonanIr.IrConst.ValueCase.* -import org.jetbrains.kotlin.metadata.KonanIr.IrDeclarator.DeclaratorCase.* -import org.jetbrains.kotlin.metadata.KonanIr.IrOperation.OperationCase.* -import org.jetbrains.kotlin.metadata.KonanIr.IrStatement.StatementCase -import org.jetbrains.kotlin.metadata.KonanIr.IrType.KindCase.* -import org.jetbrains.kotlin.metadata.KonanIr.IrTypeArgument.KindCase.STAR -import org.jetbrains.kotlin.metadata.KonanIr.IrTypeArgument.KindCase.TYPE -import org.jetbrains.kotlin.metadata.KonanIr.IrVarargElement.VarargElementCase -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.Variance - -// TODO: This code still has some uses of descriptors: -// 1. We use descriptors as keys for symbolTable -- probably symbol table related code should be refactored out from -// the deserializer. -// 2. Properties use descriptors but not symbols -- that causes lots of assymmetry all around. -// 3. Declarations are provided with wrapped descriptors. That is probably a legitimate descriptor use. - -abstract class IrModuleDeserializer( - val logger: LoggingContext, - val builtIns: IrBuiltIns, - val symbolTable: SymbolTable -) : IrDeserializer { - - abstract fun deserializeIrSymbol(proto: KonanIr.IrSymbol): IrSymbol - abstract fun deserializeIrType(proto: KonanIr.IrTypeIndex): IrType - abstract fun deserializeDescriptorReference(proto: KonanIr.DescriptorReference): DeclarationDescriptor - abstract fun deserializeString(proto: KonanIr.String): String - abstract fun deserializeLoopHeader(loopIndex: Int, loopBuilder: () -> IrLoopBase): IrLoopBase - - private fun deserializeTypeArguments(proto: KonanIr.TypeArguments): List { - logger.log { "### deserializeTypeArguments" } - val result = mutableListOf() - proto.typeArgumentList.forEach { typeProto -> - val type = deserializeIrType(typeProto) - result.add(type) - logger.log { "$type" } - } - return result - } - - fun deserializeIrTypeVariance(variance: KonanIr.IrTypeVariance) = when (variance) { - KonanIr.IrTypeVariance.IN -> Variance.IN_VARIANCE - KonanIr.IrTypeVariance.OUT -> Variance.OUT_VARIANCE - KonanIr.IrTypeVariance.INV -> Variance.INVARIANT - } - - fun deserializeIrTypeArgument(proto: KonanIr.IrTypeArgument) = when (proto.kindCase) { - STAR -> IrStarProjectionImpl - TYPE -> makeTypeProjection( - deserializeIrType(proto.type.type), deserializeIrTypeVariance(proto.type.variance) - ) - else -> TODO("Unexpected projection kind") - - } - - fun deserializeAnnotations(annotations: KonanIr.Annotations): List { - return annotations.annotationList.map { - deserializeCall(it, 0, 0, builtIns.unitType) // TODO: need a proper deserialization here - } - } - - fun deserializeSimpleType(proto: KonanIr.IrSimpleType): IrSimpleType { - val arguments = proto.argumentList.map { deserializeIrTypeArgument(it) } - val annotations = deserializeAnnotations(proto.annotations) - val symbol = deserializeIrSymbol(proto.classifier) as? IrClassifierSymbol - //?: error("could not convert sym to ClassifierSym ${proto.classifier.kind} ${proto.classifier.uniqId.index} ${proto.classifier.uniqId.isLocal}") - ?: error("could not convert sym to ClassifierSymbol") - logger.log { "deserializeSimpleType: symbol=$symbol" } - val result = IrSimpleTypeImpl( - null, - symbol, - proto.hasQuestionMark, - arguments, - annotations - ) - logger.log { "ir_type = $result; render = ${result.render()}" } - return result - } - - fun deserializeDynamicType(proto: KonanIr.IrDynamicType): IrDynamicType { - val annotations = deserializeAnnotations(proto.annotations) - return IrDynamicTypeImpl(null, annotations, Variance.INVARIANT) - } - - fun deserializeErrorType(proto: KonanIr.IrErrorType): IrErrorType { - val annotations = deserializeAnnotations(proto.annotations) - return IrErrorTypeImpl(null, annotations, Variance.INVARIANT) - } - - fun deserializeIrTypeData(proto: KonanIr.IrType): IrType { - return when (proto.kindCase) { - SIMPLE -> deserializeSimpleType(proto.simple) - DYNAMIC -> deserializeDynamicType(proto.dynamic) - ERROR -> deserializeErrorType(proto.error) - else -> TODO("Unexpected IrType kind: ${proto.kindCase}") - } - } - - /* -------------------------------------------------------------- */ - - private fun deserializeBlockBody( - proto: KonanIr.IrBlockBody, - start: Int, end: Int - ): IrBlockBody { - - val statements = mutableListOf() - - val statementProtos = proto.statementList - statementProtos.forEach { - statements.add(deserializeStatement(it) as IrStatement) - } - - return IrBlockBodyImpl(start, end, statements) - } - - private fun deserializeBranch(proto: KonanIr.IrBranch, 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: KonanIr.IrCatch, start: Int, end: Int): IrCatch { - val catchParameter = - deserializeDeclaration(proto.catchParameter, null) as IrVariable // TODO: we need a proper parent here - val result = deserializeExpression(proto.result) - - val catch = IrCatchImpl(start, end, catchParameter, result) - return catch - } - - private fun deserializeSyntheticBody(proto: KonanIr.IrSyntheticBody, start: Int, end: Int): IrSyntheticBody { - val kind = when (proto.kind) { - KonanIr.IrSyntheticBodyKind.ENUM_VALUES -> IrSyntheticBodyKind.ENUM_VALUES - KonanIr.IrSyntheticBodyKind.ENUM_VALUEOF -> IrSyntheticBodyKind.ENUM_VALUEOF - } - return IrSyntheticBodyImpl(start, end, kind) - } - - private fun deserializeStatement(proto: KonanIr.IrStatement): IrElement { - val start = proto.coordinates.startOffset - val end = proto.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() - -> deserializeDeclaration(proto.declaration, null) // TODO: we need a proper parent here. - 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}") - } - - logger.log { "### Deserialized statement: ${ir2string(element)}" } - - return element - } - - private fun deserializeBlock(proto: KonanIr.IrBlock, start: Int, end: Int, type: IrType): IrBlock { - val statements = mutableListOf() - val statementProtos = proto.statementList - statementProtos.forEach { - statements.add(deserializeStatement(it) as IrStatement) - } - - val isLambdaOrigin = if (proto.isLambdaOrigin) IrStatementOrigin.LAMBDA else null - - return IrBlockImpl(start, end, type, isLambdaOrigin, statements) - } - - private fun deserializeMemberAccessCommon(access: IrMemberAccessExpression, proto: KonanIr.MemberAccessCommon) { - - proto.valueArgumentList.mapIndexed { i, arg -> - if (arg.hasExpression()) { - val expr = deserializeExpression(arg.expression) - access.putValueArgument(i, expr) - } - } - - deserializeTypeArguments(proto.typeArguments).forEachIndexed { index, type -> - access.putTypeArgument(index, type) - } - - if (proto.hasDispatchReceiver()) { - access.dispatchReceiver = deserializeExpression(proto.dispatchReceiver) - } - if (proto.hasExtensionReceiver()) { - access.extensionReceiver = deserializeExpression(proto.extensionReceiver) - } - } - - private fun deserializeClassReference( - proto: KonanIr.IrClassReference, - start: Int, - end: Int, - type: IrType - ): IrClassReference { - val symbol = deserializeIrSymbol(proto.classSymbol) as IrClassifierSymbol - val classType = deserializeIrType(proto.classType) - /** TODO: [createClassifierSymbolForClassReference] is internal function */ - return IrClassReferenceImpl(start, end, type, symbol, classType) - } - - private fun deserializeCall(proto: KonanIr.IrCall, start: Int, end: Int, type: IrType): IrCall { - val symbol = deserializeIrSymbol(proto.symbol) as IrFunctionSymbol - - val superSymbol = if (proto.hasSuper()) { - deserializeIrSymbol(proto.`super`) as IrClassSymbol - } else null - - val call: IrCall = when (proto.kind) { - KonanIr.IrCall.Primitive.NOT_PRIMITIVE -> - // TODO: implement the last three args here. - IrCallImpl( - start, end, type, - symbol, symbol.descriptor, - proto.memberAccess.typeArguments.typeArgumentCount, - proto.memberAccess.valueArgumentList.size, - null, superSymbol - ) - KonanIr.IrCall.Primitive.NULLARY -> - IrNullaryPrimitiveImpl(start, end, type, null, symbol) - KonanIr.IrCall.Primitive.UNARY -> - IrUnaryPrimitiveImpl(start, end, type, null, symbol) - KonanIr.IrCall.Primitive.BINARY -> - IrBinaryPrimitiveImpl(start, end, type, null, symbol) - else -> TODO("Unexpected primitive IrCall.") - } - deserializeMemberAccessCommon(call, proto.memberAccess) - return call - } - - private fun deserializeComposite(proto: KonanIr.IrComposite, start: Int, end: Int, type: IrType): IrComposite { - val statements = mutableListOf() - val statementProtos = proto.statementList - statementProtos.forEach { - statements.add(deserializeStatement(it) as IrStatement) - } - return IrCompositeImpl(start, end, type, null, statements) - } - - private fun deserializeDelegatingConstructorCall( - proto: KonanIr.IrDelegatingConstructorCall, - start: Int, - end: Int - ): IrDelegatingConstructorCall { - val symbol = deserializeIrSymbol(proto.symbol) as IrConstructorSymbol - val call = IrDelegatingConstructorCallImpl( - start, - end, - builtIns.unitType, - symbol, - symbol.descriptor, - proto.memberAccess.typeArguments.typeArgumentCount, - proto.memberAccess.valueArgumentList.size - ) - - deserializeMemberAccessCommon(call, proto.memberAccess) - return call - } - - - fun deserializeEnumConstructorCall( - proto: KonanIr.IrEnumConstructorCall, - start: Int, - end: Int, - type: IrType - ): IrEnumConstructorCall { - val symbol = deserializeIrSymbol(proto.symbol) as IrConstructorSymbol - val call = IrEnumConstructorCallImpl( - start, - end, - type, - symbol, - proto.memberAccess.typeArguments.typeArgumentList.size, - proto.memberAccess.valueArgumentList.size - ) - deserializeMemberAccessCommon(call, proto.memberAccess) - return call - } - - - private fun deserializeFunctionReference( - proto: KonanIr.IrFunctionReference, - start: Int, end: Int, type: IrType - ): IrFunctionReference { - - val symbol = deserializeIrSymbol(proto.symbol) as IrFunctionSymbol - val callable = IrFunctionReferenceImpl( - start, - end, - type, - symbol, - symbol.descriptor, - proto.memberAccess.typeArguments.typeArgumentCount, - proto.memberAccess.valueArgumentCount, - null - ) - deserializeMemberAccessCommon(callable, proto.memberAccess) - - return callable - } - - private fun deserializeGetClass(proto: KonanIr.IrGetClass, start: Int, end: Int, type: IrType): IrGetClass { - val argument = deserializeExpression(proto.argument) - return IrGetClassImpl(start, end, type, argument) - } - - private fun deserializeGetField(proto: KonanIr.IrGetField, start: Int, end: Int, type: IrType): IrGetField { - val access = proto.fieldAccess - val symbol = deserializeIrSymbol(access.symbol) as IrFieldSymbol - val superQualifier = if (access.hasSuper()) { - deserializeIrSymbol(access.symbol) as IrClassSymbol - } else null - val receiver = if (access.hasReceiver()) { - deserializeExpression(access.receiver) - } else null - - return IrGetFieldImpl(start, end, symbol, type, receiver, null, superQualifier) - } - - private fun deserializeGetValue(proto: KonanIr.IrGetValue, start: Int, end: Int, type: IrType): IrGetValue { - val symbol = deserializeIrSymbol(proto.symbol) as IrValueSymbol - // TODO: origin! - return IrGetValueImpl(start, end, type, symbol, null) - } - - private fun deserializeGetEnumValue(proto: KonanIr.IrGetEnumValue, start: Int, end: Int, type: IrType): IrGetEnumValue { - val symbol = deserializeIrSymbol(proto.symbol) as IrEnumEntrySymbol - return IrGetEnumValueImpl(start, end, type, symbol) - } - - private fun deserializeGetObject(proto: KonanIr.IrGetObject, start: Int, end: Int, type: IrType): IrGetObjectValue { - val symbol = deserializeIrSymbol(proto.symbol) as IrClassSymbol - return IrGetObjectValueImpl(start, end, type, symbol) - } - - private fun deserializeInstanceInitializerCall( - proto: KonanIr.IrInstanceInitializerCall, - start: Int, - end: Int - ): IrInstanceInitializerCall { - val symbol = deserializeIrSymbol(proto.symbol) as IrClassSymbol - return IrInstanceInitializerCallImpl(start, end, symbol, builtIns.unitType) - } - - private val getterToPropertyDescriptorMap = mutableMapOf() - - private fun deserializePropertyReference( - proto: KonanIr.IrPropertyReference, - start: Int, end: Int, type: IrType - ): IrPropertyReference { - - val field = if (proto.hasField()) deserializeIrSymbol(proto.field) as IrFieldSymbol else null - val getter = if (proto.hasGetter()) deserializeIrSymbol(proto.getter) as IrSimpleFunctionSymbol else null - val setter = if (proto.hasSetter()) deserializeIrSymbol(proto.setter) as IrSimpleFunctionSymbol else null - val descriptor = - if (proto.hasDescriptor()) - deserializeDescriptorReference(proto.descriptor) as PropertyDescriptor - else - field?.descriptor as? WrappedPropertyDescriptor // If field's descriptor coincides with property's. - ?: getterToPropertyDescriptorMap.getOrPut(getter!!) { WrappedPropertyDescriptor() } - - val callable = IrPropertyReferenceImpl( - start, end, type, - descriptor, - proto.memberAccess.typeArguments.typeArgumentCount, - field, - getter, - setter, - null - ) - deserializeMemberAccessCommon(callable, proto.memberAccess) - return callable - } - - private fun deserializeReturn(proto: KonanIr.IrReturn, start: Int, end: Int, type: IrType): IrReturn { - val symbol = deserializeIrSymbol(proto.returnTarget) as IrReturnTargetSymbol - val value = deserializeExpression(proto.value) - return IrReturnImpl(start, end, builtIns.nothingType, symbol, value) - } - - private fun deserializeSetField(proto: KonanIr.IrSetField, start: Int, end: Int): IrSetField { - val access = proto.fieldAccess - val symbol = deserializeIrSymbol(access.symbol) as IrFieldSymbol - val superQualifier = if (access.hasSuper()) { - deserializeIrSymbol(access.symbol) as IrClassSymbol - } else null - val receiver = if (access.hasReceiver()) { - deserializeExpression(access.receiver) - } else null - val value = deserializeExpression(proto.value) - - return IrSetFieldImpl(start, end, symbol, receiver, value, builtIns.unitType, null, superQualifier) - } - - private fun deserializeSetVariable(proto: KonanIr.IrSetVariable, start: Int, end: Int): IrSetVariable { - val symbol = deserializeIrSymbol(proto.symbol) as IrVariableSymbol - val value = deserializeExpression(proto.value) - return IrSetVariableImpl(start, end, builtIns.unitType, symbol, value, null) - } - - private fun deserializeSpreadElement(proto: KonanIr.IrSpreadElement): IrSpreadElement { - val expression = deserializeExpression(proto.expression) - return IrSpreadElementImpl(proto.coordinates.startOffset, proto.coordinates.endOffset, expression) - } - - private fun deserializeStringConcat( - proto: KonanIr.IrStringConcat, - start: Int, - end: Int, - type: IrType - ): IrStringConcatenation { - val argumentProtos = proto.argumentList - val arguments = mutableListOf() - - argumentProtos.forEach { - arguments.add(deserializeExpression(it)) - } - return IrStringConcatenationImpl(start, end, type, arguments) - } - - private fun deserializeThrow(proto: KonanIr.IrThrow, start: Int, end: Int, type: IrType): IrThrowImpl { - return IrThrowImpl(start, end, builtIns.nothingType, deserializeExpression(proto.value)) - } - - private fun deserializeTry(proto: KonanIr.IrTry, start: Int, end: Int, type: IrType): IrTryImpl { - val result = deserializeExpression(proto.result) - val catches = mutableListOf() - 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: KonanIr.IrTypeOperator) = when (operator) { - KonanIr.IrTypeOperator.CAST - -> IrTypeOperator.CAST - KonanIr.IrTypeOperator.IMPLICIT_CAST - -> IrTypeOperator.IMPLICIT_CAST - KonanIr.IrTypeOperator.IMPLICIT_NOTNULL - -> IrTypeOperator.IMPLICIT_NOTNULL - KonanIr.IrTypeOperator.IMPLICIT_COERCION_TO_UNIT - -> IrTypeOperator.IMPLICIT_COERCION_TO_UNIT - KonanIr.IrTypeOperator.IMPLICIT_INTEGER_COERCION - -> IrTypeOperator.IMPLICIT_INTEGER_COERCION - KonanIr.IrTypeOperator.SAFE_CAST - -> IrTypeOperator.SAFE_CAST - KonanIr.IrTypeOperator.INSTANCEOF - -> IrTypeOperator.INSTANCEOF - KonanIr.IrTypeOperator.NOT_INSTANCEOF - -> IrTypeOperator.NOT_INSTANCEOF - KonanIr.IrTypeOperator.SAM_CONVERSION - -> IrTypeOperator.SAM_CONVERSION - } - - private fun deserializeTypeOp(proto: KonanIr.IrTypeOp, start: Int, end: Int, type: IrType): IrTypeOperatorCall { - val operator = deserializeTypeOperator(proto.operator) - val operand = deserializeIrType(proto.operand)//.brokenIr - val argument = deserializeExpression(proto.argument) - return IrTypeOperatorCallImpl(start, end, type, operator, operand).apply { - this.argument = argument - this.typeOperandClassifier = operand.classifierOrFail - } - } - - private fun deserializeVararg(proto: KonanIr.IrVararg, start: Int, end: Int, type: IrType): IrVararg { - val elementType = deserializeIrType(proto.elementType) - - val elements = mutableListOf() - proto.elementList.forEach { - elements.add(deserializeVarargElement(it)) - } - return IrVarargImpl(start, end, type, elementType, elements) - } - - private fun deserializeVarargElement(element: KonanIr.IrVarargElement): 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: KonanIr.IrWhen, start: Int, end: Int, type: IrType): IrWhen { - val branches = mutableListOf() - - proto.branchList.forEach { - branches.add(deserializeStatement(it) as IrBranch) - } - - // TODO: provide some origin! - return IrWhenImpl(start, end, type, null, branches) - } - - private fun deserializeLoop(proto: KonanIr.Loop, loop: IrLoopBase): IrLoopBase { - val label = if (proto.hasLabel()) 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: KonanIr.IrDoWhile, start: Int, end: Int, type: IrType) = - deserializeLoop(proto.loop, deserializeLoopHeader(proto.loop.loopId) { IrDoWhileLoopImpl(start, end, type, null) }) - - private fun deserializeWhile(proto: KonanIr.IrWhile, start: Int, end: Int, type: IrType) = - deserializeLoop(proto.loop, deserializeLoopHeader(proto.loop.loopId) { IrWhileLoopImpl(start, end, type, null) }) - - private fun deserializeBreak(proto: KonanIr.IrBreak, start: Int, end: Int, type: IrType): IrBreak { - val label = if (proto.hasLabel()) 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: KonanIr.IrContinue, start: Int, end: Int, type: IrType): IrContinue { - val label = if (proto.hasLabel()) 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: KonanIr.IrConst, 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, deserializeString(proto.string)) - FLOAT - -> IrConstImpl.float(start, end, type, proto.float) - DOUBLE - -> IrConstImpl.double(start, end, type, proto.double) - VALUE_NOT_SET - -> error("Const deserialization error: ${proto.valueCase} ") - } - - private fun deserializeOperation(proto: KonanIr.IrOperation, 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, type) - 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) - INSTANCE_INITIALIZER_CALL - -> deserializeInstanceInitializerCall(proto.instanceInitializerCall, start, end) - PROPERTY_REFERENCE - -> deserializePropertyReference(proto.propertyReference, start, end, type) - RETURN - -> deserializeReturn(proto.`return`, start, end, type) - SET_FIELD - -> deserializeSetField(proto.setField, start, end) - SET_VARIABLE - -> deserializeSetVariable(proto.setVariable, start, end) - STRING_CONCAT - -> deserializeStringConcat(proto.stringConcat, start, end, type) - THROW - -> deserializeThrow(proto.`throw`, start, end, type) - 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) - OPERATION_NOT_SET - -> error("Expression deserialization not implemented: ${proto.operationCase}") - } - - private fun deserializeExpression(proto: KonanIr.IrExpression): IrExpression { - val start = proto.coordinates.startOffset - val end = proto.coordinates.endOffset - val type = deserializeIrType(proto.type) - val operation = proto.operation - val expression = deserializeOperation(operation, start, end, type) - - logger.log { "### Deserialized expression: ${ir2string(expression)} ir_type=$type" } - return expression - } - - private fun deserializeIrTypeParameter( - proto: KonanIr.IrTypeParameter, - start: Int, - end: Int, - origin: IrDeclarationOrigin - ): IrTypeParameter { - val symbol = deserializeIrSymbol(proto.symbol) as IrTypeParameterSymbol - val name = Name.identifier(deserializeString(proto.name)) - val variance = deserializeIrTypeVariance(proto.variance) - - val parameter = symbolTable.declareGlobalTypeParameter(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irrelevantOrigin, - symbol.descriptor, { symbol -> - IrTypeParameterImpl(start, end, origin, symbol, name, proto.index, proto.isReified, variance) - } - ) - - val superTypes = proto.superTypeList.map { deserializeIrType(it) } - parameter.superTypes.addAll(superTypes) - - return parameter - } - - private fun deserializeIrTypeParameterContainer( - proto: KonanIr.IrTypeParameterContainer, - parent: IrDeclarationParent - ): List { - return proto.typeParameterList.map { - deserializeDeclaration( - it, - parent - ) as IrTypeParameter - } // TODO: we need proper start, end and origin here? - } - - private fun deserializeClassKind(kind: KonanIr.ClassKind) = when (kind) { - KonanIr.ClassKind.CLASS -> ClassKind.CLASS - KonanIr.ClassKind.INTERFACE -> ClassKind.INTERFACE - KonanIr.ClassKind.ENUM_CLASS -> ClassKind.ENUM_CLASS - KonanIr.ClassKind.ENUM_ENTRY -> ClassKind.ENUM_ENTRY - KonanIr.ClassKind.ANNOTATION_CLASS -> ClassKind.ANNOTATION_CLASS - KonanIr.ClassKind.OBJECT -> ClassKind.OBJECT - } - - private fun deserializeIrValueParameter( - proto: KonanIr.IrValueParameter, - start: Int, - end: Int, - origin: IrDeclarationOrigin - ): IrValueParameter { - - val varargElementType = if (proto.hasVarargElementType()) deserializeIrType(proto.varargElementType) else null - val parameter = - IrValueParameterImpl( - start, end, origin, - deserializeIrSymbol(proto.symbol) as IrValueParameterSymbol, - Name.identifier(deserializeString(proto.name)), - proto.index, - deserializeIrType(proto.type), - varargElementType, - proto.isCrossinline, - proto.isNoinline - ).apply { - defaultValue = if (proto.hasDefaultValue()) { - val expression = deserializeExpression(proto.defaultValue) - IrExpressionBodyImpl(expression) - } else null - } - - return parameter - } - - private fun deserializeIrClass(proto: KonanIr.IrClass, start: Int, end: Int, origin: IrDeclarationOrigin): IrClass { - - val symbol = deserializeIrSymbol(proto.symbol) as IrClassSymbol - - val modality = deserializeModality(proto.modality) - val clazz = symbolTable.declareClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irrelevantOrigin, - symbol.descriptor, modality) { - IrClassImpl( - start, end, origin, - it, - Name.identifier(deserializeString(proto.name)), - deserializeClassKind(proto.kind), - deserializeVisibility(proto.visibility), - modality, - proto.isCompanion, - proto.isInner, - proto.isData, - proto.isExternal, - proto.isInline - ) - } - - proto.declarationContainer.declarationList.forEach { - val member = deserializeDeclaration(it, clazz) - clazz.addMember(member) - member.parent = clazz - } - - clazz.thisReceiver = deserializeDeclaration(proto.thisReceiver, clazz) as IrValueParameter - - val typeParameters = deserializeIrTypeParameterContainer(proto.typeParameters, clazz) - clazz.typeParameters.addAll(typeParameters) - - val superTypes = proto.superTypeList.map { deserializeIrType(it) } - clazz.superTypes.addAll(superTypes) - - return clazz - } - - private fun deserializeIrFunctionBase( - base: KonanIr.IrFunctionBase, - function: IrFunctionBase, - start: Int, - end: Int, - origin: IrDeclarationOrigin - ) { - - function.body = if (base.hasBody()) deserializeStatement(base.body) as IrBody else null - - val valueParameters = base.valueParameterList.map { deserializeDeclaration(it, function) as IrValueParameter } - function.valueParameters.addAll(valueParameters) - function.dispatchReceiverParameter = if (base.hasDispatchReceiver()) deserializeDeclaration( - base.dispatchReceiver, - function - ) as IrValueParameter else null - function.extensionReceiverParameter = if (base.hasExtensionReceiver()) deserializeDeclaration( - base.extensionReceiver, - function - ) as IrValueParameter else null - val typeParameters = deserializeIrTypeParameterContainer(base.typeParameters, function) // TODO - function.typeParameters.addAll(typeParameters) - } - - private fun deserializeIrFunction( - proto: KonanIr.IrFunction, - start: Int, end: Int, origin: IrDeclarationOrigin - ): IrSimpleFunction { - - logger.log { "### deserializing IrFunction ${deserializeString(proto.base.name)}" } - val symbol = deserializeIrSymbol(proto.symbol) as IrSimpleFunctionSymbol - - val function = symbolTable.declareSimpleFunction(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irrelevantOrigin, - symbol.descriptor, { - IrFunctionImpl( - start, end, origin, it, - Name.identifier(deserializeString(proto.base.name)), - deserializeVisibility(proto.base.visibility), - deserializeModality(proto.modality), - deserializeIrType(proto.base.returnType), - proto.base.isInline, - proto.base.isExternal, - proto.isTailrec, - proto.isSuspend - ) - }) - - deserializeIrFunctionBase(proto.base, function as IrFunctionBase, start, end, origin) - val overridden = proto.overriddenList.map { deserializeIrSymbol(it) as IrSimpleFunctionSymbol } - function.overriddenSymbols.addAll(overridden) - - return function - } - - private fun deserializeIrVariable( - proto: KonanIr.IrVariable, - start: Int, end: Int, origin: IrDeclarationOrigin - ): IrVariable { - - val initializer = if (proto.hasInitializer()) { - deserializeExpression(proto.initializer) - } else null - - val symbol = deserializeIrSymbol(proto.symbol) as IrVariableSymbol - val type = deserializeIrType(proto.type) - - val variable = IrVariableImpl( - start, - end, - origin, - symbol, - Name.identifier(deserializeString(proto.name)), - type, - proto.isVar, - proto.isConst, - proto.isLateinit - ) - variable.initializer = initializer - return variable - } - - private fun deserializeIrEnumEntry( - proto: KonanIr.IrEnumEntry, - start: Int, end: Int, origin: IrDeclarationOrigin - ): IrEnumEntry { - val symbol = deserializeIrSymbol(proto.symbol) as IrEnumEntrySymbol - - val enumEntry = symbolTable.declareEnumEntry( - UNDEFINED_OFFSET, - UNDEFINED_OFFSET, - irrelevantOrigin, - symbol.descriptor - ) { - IrEnumEntryImpl(start, end, origin, it, Name.identifier(deserializeString(proto.name))) - } - - if (proto.hasCorrespondingClass()) { - enumEntry.correspondingClass = deserializeDeclaration(proto.correspondingClass, null) as IrClass - } - if (proto.hasInitializer()) { - enumEntry.initializerExpression = deserializeExpression(proto.initializer) - } - - return enumEntry - } - - private fun deserializeIrAnonymousInit( - proto: KonanIr.IrAnonymousInit, - start: Int, - end: Int, - origin: IrDeclarationOrigin - ): IrAnonymousInitializer { - val symbol = deserializeIrSymbol(proto.symbol) as IrAnonymousInitializerSymbol - val initializer = IrAnonymousInitializerImpl(start, end, origin, symbol) - initializer.body = deserializeBlockBody(proto.body.blockBody, start, end) - return initializer - } - - private fun deserializeVisibility(value: KonanIr.Visibility): Visibility { // TODO: switch to enum - return when (deserializeString(value.name)) { - "public" -> Visibilities.PUBLIC - "private" -> Visibilities.PRIVATE - "private_to_this" -> Visibilities.PRIVATE_TO_THIS - "protected" -> Visibilities.PROTECTED - "internal" -> Visibilities.INTERNAL - "invisible_fake" -> Visibilities.INVISIBLE_FAKE // TODO: eventually we should not serialize fake overrides, so this will be gone. - "local" -> Visibilities.LOCAL - else -> error("Unexpected visibility value: $value") - } - } - - private fun deserializeIrConstructor( - proto: KonanIr.IrConstructor, - start: Int, - end: Int, - origin: IrDeclarationOrigin - ): IrConstructor { - val symbol = deserializeIrSymbol(proto.symbol) as IrConstructorSymbol - - val constructor = symbolTable.declareConstructor(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irrelevantOrigin, - symbol.descriptor, { - IrConstructorImpl( - start, end, origin, - it, - Name.identifier(deserializeString(proto.base.name)), - deserializeVisibility(proto.base.visibility), - deserializeIrType(proto.base.returnType), - proto.base.isInline, - proto.base.isExternal, - proto.isPrimary - ) - - }) - - deserializeIrFunctionBase(proto.base, constructor as IrFunctionBase, start, end, origin) - return constructor - } - - private fun deserializeIrField(proto: KonanIr.IrField, start: Int, end: Int, origin: IrDeclarationOrigin): IrField { - - val symbol = deserializeIrSymbol(proto.symbol) as IrFieldSymbol - val type = deserializeIrType(proto.type) - val field = symbolTable.declareField(UNDEFINED_OFFSET, - UNDEFINED_OFFSET, - irrelevantOrigin, - symbol.descriptor, - type, - { IrFieldImpl( - start, end, origin, - it, - Name.identifier(deserializeString(proto.name)), - type, - deserializeVisibility(proto.visibility), - proto.isFinal, - proto.isExternal, - proto.isStatic - ) - } - ) - - val initializer = if (proto.hasInitializer()) deserializeExpression(proto.initializer) else null - field.initializer = initializer?.let { IrExpressionBodyImpl(it) } - - return field - } - - private fun deserializeModality(modality: KonanIr.ModalityKind) = when (modality) { - KonanIr.ModalityKind.OPEN_MODALITY -> Modality.OPEN - KonanIr.ModalityKind.SEALED_MODALITY -> Modality.SEALED - KonanIr.ModalityKind.FINAL_MODALITY -> Modality.FINAL - KonanIr.ModalityKind.ABSTRACT_MODALITY -> Modality.ABSTRACT - } - - private fun deserializeIrProperty( - proto: KonanIr.IrProperty, - start: Int, - end: Int, - origin: IrDeclarationOrigin - ): IrProperty { - - val backingField = if (proto.hasBackingField()) deserializeIrField(proto.backingField, start, end, origin) else null - val getter = if (proto.hasGetter()) deserializeIrFunction(proto.getter, start, end, origin) else null - val setter = if (proto.hasSetter()) deserializeIrFunction(proto.setter, start, end, origin) else null - - backingField?.let { (it.descriptor as? WrappedFieldDescriptor)?.bind(it) } - getter?.let { (it.descriptor as? WrappedSimpleFunctionDescriptor)?.bind(it) } - setter?.let { (it.descriptor as? WrappedSimpleFunctionDescriptor)?.bind(it) } - - val descriptor = - if (proto.hasDescriptor()) - deserializeDescriptorReference(proto.descriptor) as PropertyDescriptor - else - backingField?.descriptor as? WrappedPropertyDescriptor // If field's descriptor coincides with property's. - ?: getterToPropertyDescriptorMap.getOrPut(getter!!.symbol) { WrappedPropertyDescriptor() } - - val property = IrPropertyImpl( - start, end, origin, - descriptor, - Name.identifier(deserializeString(proto.name)), - deserializeVisibility(proto.visibility), - deserializeModality(proto.modality), - proto.isVar, - proto.isConst, - proto.isLateinit, - proto.isDelegated, - proto.isExternal - ) - - symbolTable.referenceProperty(descriptor, { property }) - - property.backingField = backingField - property.getter = getter - property.setter = setter - - backingField?.let { it.correspondingProperty = property } - getter?.let { it.correspondingProperty = property } - setter?.let { it.correspondingProperty = property } - - return property - } - - private fun deserializeIrTypeAlias( - proto: KonanIr.IrTypeAlias, - start: Int, - end: Int, - origin: IrDeclarationOrigin - ): IrDeclaration { - return IrErrorDeclarationImpl(start, end, WrappedClassDescriptor()) - } - - private val allKnownOrigins = - IrDeclarationOrigin::class.nestedClasses.toList() + DeclarationFactory.FIELD_FOR_OUTER_THIS::class - val originIndex = allKnownOrigins.map { it.objectInstance as IrDeclarationOriginImpl }.associateBy { it.name } - val irrelevantOrigin = object : IrDeclarationOriginImpl("irrelevant") {} - fun deserializeIrDeclarationOrigin(proto: KonanIr.IrDeclarationOrigin) = originIndex[deserializeString(proto.custom)]!! - - protected fun deserializeDeclaration(proto: KonanIr.IrDeclaration, parent: IrDeclarationParent?): IrDeclaration { - - val start = proto.coordinates.startOffset - val end = proto.coordinates.endOffset - val origin = deserializeIrDeclarationOrigin(proto.origin) - - val declarator = proto.declarator - - val declaration: IrDeclaration = when (declarator.declaratorCase) { - IR_ANONYMOUS_INIT - -> deserializeIrAnonymousInit(declarator.irAnonymousInit, start, end, origin) - IR_CONSTRUCTOR - -> deserializeIrConstructor(declarator.irConstructor, start, end, origin) - IR_FIELD - -> deserializeIrField(declarator.irField, start, end, origin) - IR_CLASS - -> deserializeIrClass(declarator.irClass, start, end, origin) - IR_FUNCTION - -> deserializeIrFunction(declarator.irFunction, start, end, origin) - IR_PROPERTY - -> deserializeIrProperty(declarator.irProperty, start, end, origin) - IR_TYPE_ALIAS - -> deserializeIrTypeAlias(declarator.irTypeAlias, start, end, origin) - IR_TYPE_PARAMETER - -> deserializeIrTypeParameter(declarator.irTypeParameter, start, end, origin) - IR_VARIABLE - -> deserializeIrVariable(declarator.irVariable, start, end, origin) - IR_VALUE_PARAMETER - -> deserializeIrValueParameter(declarator.irValueParameter, start, end, origin) - IR_ENUM_ENTRY - -> deserializeIrEnumEntry(declarator.irEnumEntry, start, end, origin) - DECLARATOR_NOT_SET - -> error("Declaration deserialization not implemented: ${declarator.declaratorCase}") - } - - val annotations = deserializeAnnotations(proto.annotations) - declaration.annotations.addAll(annotations) - - parent?.let { declaration.parent = it } - - val descriptor = declaration.descriptor - - if (descriptor is WrappedDeclarationDescriptor<*>) { - when (declaration) { - is IrValueParameter -> - if (descriptor is WrappedValueParameterDescriptor) descriptor.bind(declaration) - else (descriptor as WrappedReceiverParameterDescriptor).bind(declaration) - is IrVariable -> (descriptor as WrappedVariableDescriptor).bind(declaration) - is IrTypeParameter -> (descriptor as WrappedTypeParameterDescriptor).bind(declaration) - is IrAnonymousInitializer -> (descriptor as WrappedClassDescriptor).bind(parent!! as IrClass) - is IrClass -> (descriptor as WrappedClassDescriptor).bind(declaration) - is IrConstructor -> (descriptor as WrappedClassConstructorDescriptor).bind(declaration) - is IrField -> (descriptor as WrappedFieldDescriptor).bind(declaration) - is IrProperty -> (descriptor as WrappedPropertyDescriptor).bind(declaration) - is IrEnumEntry -> (descriptor as WrappedEnumEntryDescriptor).bind(declaration) - is IrSimpleFunction -> (descriptor as WrappedSimpleFunctionDescriptor).bind(declaration) - } - } - logger.log { "### Deserialized declaration: ${descriptor} -> ${ir2string(declaration)}" } - - return declaration - } -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleSerializer.kt deleted file mode 100644 index 805e30c7f61..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleSerializer.kt +++ /dev/null @@ -1,1141 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.konan.serialization - -import org.jetbrains.kotlin.backend.common.LoggingContext -import org.jetbrains.kotlin.backend.common.ir.ir2string -import org.jetbrains.kotlin.backend.konan.RuntimeNames -import org.jetbrains.kotlin.backend.konan.descriptors.findTopLevelDeclaration -import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember -import org.jetbrains.kotlin.backend.konan.descriptors.isSerializableExpectClass -import org.jetbrains.kotlin.backend.konan.ir.lineStartOffsets -import org.jetbrains.kotlin.backend.konan.library.SerializedIr -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.ClassKind.* -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor -import org.jetbrains.kotlin.descriptors.Visibility -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.SourceManager -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionBase -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrBinaryPrimitiveImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrNullaryPrimitiveImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrUnaryPrimitiveImpl -import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl -import org.jetbrains.kotlin.ir.util.dump -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid -import org.jetbrains.kotlin.ir.visitors.acceptVoid -import org.jetbrains.kotlin.konan.library.impl.CombinedIrFileWriter -import org.jetbrains.kotlin.konan.library.impl.DeclarationId -import org.jetbrains.kotlin.metadata.KonanIr -import org.jetbrains.kotlin.types.SimpleType -import org.jetbrains.kotlin.types.StarProjectionImpl -import org.jetbrains.kotlin.types.Variance - -internal class IrModuleSerializer( - val logger: LoggingContext, - val declarationTable: DeclarationTable, - val bodiesOnlyForInlines: Boolean = false -) { - - private val loopIndex = mutableMapOf() - private var currentLoopIndex = 0 - val descriptorReferenceSerializer = DescriptorReferenceSerializer(declarationTable, { string -> serializeString(string) }) - - // The same symbol can be used multiple times in a module - // so use this index to store symbol data only once. - val protoSymbolMap = mutableMapOf() - val protoSymbolArray = arrayListOf() - - // The same type can be used multiple times in a module - // so use this index to store type data only once. - val protoTypeMap = mutableMapOf() - val protoTypeArray = arrayListOf() - - val protoStringMap = mutableMapOf() - val protoStringArray = arrayListOf() - - /* ------- Common fields ---------------------------------------------------- */ - - private fun serializeIrDeclarationOrigin(origin: IrDeclarationOrigin) = - KonanIr.IrDeclarationOrigin.newBuilder() - .setCustom(serializeString((origin as IrDeclarationOriginImpl).name)) - .build() - - private fun serializeIrStatementOrigin(origin: IrStatementOrigin) = - KonanIr.IrStatementOrigin.newBuilder() - .setName(serializeString((origin as IrStatementOriginImpl).debugName)) - .build() - - private fun serializeVisibility(visibility: Visibility) = - KonanIr.Visibility.newBuilder() - .setName(serializeString(visibility.name)) - .build() - - private fun serializeCoordinates(start: Int, end: Int): KonanIr.Coordinates { - return KonanIr.Coordinates.newBuilder() - .setStartOffset(start) - .setEndOffset(end) - .build() - } - - /* ------- Strings ---------------------------------------------------------- */ - - fun serializeString(value: String): KonanIr.String { - val proto = KonanIr.String.newBuilder() - proto.index = protoStringMap.getOrPut(value) { - protoStringArray.add(value) - protoStringArray.size - 1 - } - return proto.build() - } - - /* ------- IrSymbols -------------------------------------------------------- */ - - fun protoSymbolKind(symbol: IrSymbol): KonanIr.IrSymbolKind = when (symbol) { - is IrAnonymousInitializerSymbol -> - KonanIr.IrSymbolKind.ANONYMOUS_INIT_SYMBOL - is IrClassSymbol -> - KonanIr.IrSymbolKind.CLASS_SYMBOL - is IrConstructorSymbol -> - KonanIr.IrSymbolKind.CONSTRUCTOR_SYMBOL - is IrTypeParameterSymbol -> - KonanIr.IrSymbolKind.TYPE_PARAMETER_SYMBOL - is IrEnumEntrySymbol -> - KonanIr.IrSymbolKind.ENUM_ENTRY_SYMBOL - is IrVariableSymbol -> - KonanIr.IrSymbolKind.VARIABLE_SYMBOL - is IrValueParameterSymbol -> - if (symbol.descriptor is ReceiverParameterDescriptor) // TODO: we use descriptor here. - KonanIr.IrSymbolKind.RECEIVER_PARAMETER_SYMBOL - else - KonanIr.IrSymbolKind.VALUE_PARAMETER_SYMBOL - is IrSimpleFunctionSymbol -> - KonanIr.IrSymbolKind.FUNCTION_SYMBOL - is IrReturnableBlockSymbol -> - KonanIr.IrSymbolKind.RETURNABLE_BLOCK_SYMBOL - is IrFieldSymbol -> - if (symbol.owner.correspondingProperty.let { it == null || it.isDelegated }) - KonanIr.IrSymbolKind.STANDALONE_FIELD_SYMBOL - else - KonanIr.IrSymbolKind.FIELD_SYMBOL - else -> - TODO("Unexpected symbol kind: $symbol") - } - - fun serializeIrSymbolData(symbol: IrSymbol): KonanIr.IrSymbolData { - - val declaration = symbol.owner as? IrDeclaration ?: error("Expected IrDeclaration: ${symbol.owner}") - - val proto = KonanIr.IrSymbolData.newBuilder() - proto.kind = protoSymbolKind(symbol) - - val uniqId = - declarationTable.uniqIdByDeclaration(declaration) - proto.setUniqId(protoUniqId(uniqId)) - - val topLevelUniqId = - declarationTable.uniqIdByDeclaration((declaration).findTopLevelDeclaration()) - proto.setTopLevelUniqId(protoUniqId(topLevelUniqId)) - - descriptorReferenceSerializer.serializeDescriptorReference(declaration) ?. let { - proto.setDescriptorReference(it) - } - - return proto.build() - } - - fun serializeIrSymbol(symbol: IrSymbol): KonanIr.IrSymbol { - val proto = KonanIr.IrSymbol.newBuilder() - proto.index = protoSymbolMap.getOrPut(symbol) { - protoSymbolArray.add(serializeIrSymbolData(symbol)) - protoSymbolArray.size - 1 - } - return proto.build() - } - - /* ------- IrTypes ---------------------------------------------------------- */ - - // TODO: we, probably, need a type table. - - private fun serializeTypeArguments(call: IrMemberAccessExpression): KonanIr.TypeArguments { - val proto = KonanIr.TypeArguments.newBuilder() - for (i in 0 until call.typeArgumentsCount) { - proto.addTypeArgument(serializeIrType(call.getTypeArgument(i)!!)) - } - return proto.build() - } - - fun serializeIrTypeVariance(variance: Variance) = when (variance) { - Variance.IN_VARIANCE -> KonanIr.IrTypeVariance.IN - Variance.OUT_VARIANCE -> KonanIr.IrTypeVariance.OUT - Variance.INVARIANT -> KonanIr.IrTypeVariance.INV - } - - fun serializeAnnotations(annotations: List): KonanIr.Annotations { - val proto = KonanIr.Annotations.newBuilder() - annotations.forEach { - proto.addAnnotation(serializeCall(it)) - } - return proto.build() - } - - fun serializeIrTypeProjection(argument: IrTypeProjection) = KonanIr.IrTypeProjection.newBuilder() - .setVariance(serializeIrTypeVariance(argument.variance)) - .setType(serializeIrType(argument.type)) - .build() - - fun serializeTypeArgument(argument: IrTypeArgument): KonanIr.IrTypeArgument { - val proto = KonanIr.IrTypeArgument.newBuilder() - when (argument) { - is IrStarProjection -> - proto.star = KonanIr.IrStarProjection.newBuilder() - .build() // TODO: Do we need a singletone here? Or just an enum? - is IrTypeProjection -> - proto.type = serializeIrTypeProjection(argument) - else -> TODO("Unexpected type argument kind: $argument") - } - return proto.build() - } - - fun serializeSimpleType(type: IrSimpleType): KonanIr.IrSimpleType { - val proto = KonanIr.IrSimpleType.newBuilder() - .setAnnotations(serializeAnnotations(type.annotations)) - .setClassifier(serializeIrSymbol(type.classifier)) - .setHasQuestionMark(type.hasQuestionMark) - type.arguments.forEach { - proto.addArgument(serializeTypeArgument(it)) - } - return proto.build() - } - - fun serializeDynamicType(type: IrDynamicType) = KonanIr.IrDynamicType.newBuilder() - .setAnnotations(serializeAnnotations(type.annotations)) - .build() - - fun serializeErrorType(type: IrErrorType) = KonanIr.IrErrorType.newBuilder() - .setAnnotations(serializeAnnotations(type.annotations)) - .build() - - private fun serializeIrTypeData(type: IrType): KonanIr.IrType { - logger.log { "### serializing IrType: " + type } - val proto = KonanIr.IrType.newBuilder() - when (type) { - is IrSimpleType -> - proto.simple = serializeSimpleType(type) - is IrDynamicType -> - proto.dynamic = serializeDynamicType(type) - is IrErrorType -> - proto.error = serializeErrorType(type) - else -> TODO("IrType serialization not implemented yet: $type.") - } - return proto.build() - } - - enum class IrTypeKind { - SIMPLE, - DYNAMIC, - ERROR - } - - enum class IrTypeArgumentKind { - STAR, - PROJECTION - } - - // This is just IrType repacked as a data class, good to address a hash map. - data class IrTypeKey ( - val kind: IrTypeKind, - val classifier: IrClassifierSymbol?, - val hasQuestionMark: Boolean?, - val arguments: List?, - val annotations: List - ) - - data class IrTypeArgumentKey ( - val kind: IrTypeArgumentKind, - val variance: Variance?, - val type: IrTypeKey? - ) - - val IrType.toIrTypeKey: IrTypeKey get() = IrTypeKey( - kind = when (this) { - is IrSimpleType -> IrTypeKind.SIMPLE - is IrDynamicType -> IrTypeKind.DYNAMIC - is IrErrorType -> IrTypeKind.ERROR - else -> error("Unexpected IrType kind: $this") - }, - classifier = this.classifierOrNull, - hasQuestionMark = (this as? IrSimpleType)?.hasQuestionMark, - arguments = (this as? IrSimpleType)?.arguments?.map { it.toIrTypeArgumentKey }, - annotations = this.annotations - ) - - val IrTypeArgument.toIrTypeArgumentKey: IrTypeArgumentKey get() = IrTypeArgumentKey( - kind = when (this) { - is IrStarProjection -> IrTypeArgumentKind.STAR - is IrTypeProjection -> IrTypeArgumentKind.PROJECTION - else -> error("Unexpected type argument kind: $this") - }, - variance = (this as? IrTypeProjection)?.variance, - type = (this as? IrTypeProjection)?.type?.toIrTypeKey - ) - - fun serializeIrType(type: IrType): KonanIr.IrTypeIndex { - val proto = KonanIr.IrTypeIndex.newBuilder() - val key = type.toIrTypeKey - proto.index = protoTypeMap.getOrPut(key) { - // println("new type: $type ${(type as? IrSimpleType)?.classifier?.descriptor}${if((type as? IrSimpleType)?.hasQuestionMark ?: false) "?" else ""}") - // println("new key = $key") - protoTypeArray.add(serializeIrTypeData(type)) - protoTypeArray.size - 1 - } - return proto.build() - } - - /* -------------------------------------------------------------------------- */ - - private fun serializeBlockBody(expression: IrBlockBody): KonanIr.IrBlockBody { - val proto = KonanIr.IrBlockBody.newBuilder() - expression.statements.forEach { - proto.addStatement(serializeStatement(it)) - } - return proto.build() - } - - private fun serializeBranch(branch: IrBranch): KonanIr.IrBranch { - val proto = KonanIr.IrBranch.newBuilder() - - proto.condition = serializeExpression(branch.condition) - proto.result = serializeExpression(branch.result) - - return proto.build() - } - - private fun serializeBlock(block: IrBlock): KonanIr.IrBlock { - val isLambdaOrigin = - block.origin == IrStatementOrigin.LAMBDA || - block.origin == IrStatementOrigin.ANONYMOUS_FUNCTION - val proto = KonanIr.IrBlock.newBuilder() - .setIsLambdaOrigin(isLambdaOrigin) - block.statements.forEach { - proto.addStatement(serializeStatement(it)) - } - return proto.build() - } - - private fun serializeComposite(composite: IrComposite): KonanIr.IrComposite { - val proto = KonanIr.IrComposite.newBuilder() - composite.statements.forEach { - proto.addStatement(serializeStatement(it)) - } - return proto.build() - } - - private fun serializeCatch(catch: IrCatch): KonanIr.IrCatch { - val proto = KonanIr.IrCatch.newBuilder() - .setCatchParameter(serializeDeclaration(catch.catchParameter)) - .setResult(serializeExpression(catch.result)) - return proto.build() - } - - private fun serializeStringConcat(expression: IrStringConcatenation): KonanIr.IrStringConcat { - val proto = KonanIr.IrStringConcat.newBuilder() - expression.arguments.forEach { - proto.addArgument(serializeExpression(it)) - } - return proto.build() - } - - private fun irCallToPrimitiveKind(call: IrCall): KonanIr.IrCall.Primitive = when (call) { - is IrNullaryPrimitiveImpl - -> KonanIr.IrCall.Primitive.NULLARY - is IrUnaryPrimitiveImpl - -> KonanIr.IrCall.Primitive.UNARY - is IrBinaryPrimitiveImpl - -> KonanIr.IrCall.Primitive.BINARY - else - -> KonanIr.IrCall.Primitive.NOT_PRIMITIVE - } - - private fun serializeMemberAccessCommon(call: IrMemberAccessExpression): KonanIr.MemberAccessCommon { - val proto = KonanIr.MemberAccessCommon.newBuilder() - if (call.extensionReceiver != null) { - proto.extensionReceiver = serializeExpression(call.extensionReceiver!!) - } - - if (call.dispatchReceiver != null) { - proto.dispatchReceiver = serializeExpression(call.dispatchReceiver!!) - } - proto.typeArguments = serializeTypeArguments(call) - - for (index in 0..call.valueArgumentsCount - 1) { - val actual = call.getValueArgument(index) - val argOrNull = KonanIr.NullableIrExpression.newBuilder() - if (actual == null) { - // Am I observing an IR generation regression? - // I see a lack of arg for an empty vararg, - // rather than an empty vararg node. - - // TODO: how do we assert that without descriptora? - //assert(it.varargElementType != null || it.hasDefaultValue()) - } else { - argOrNull.expression = serializeExpression(actual) - } - proto.addValueArgument(argOrNull) - } - return proto.build() - } - - private fun serializeCall(call: IrCall): KonanIr.IrCall { - val proto = KonanIr.IrCall.newBuilder() - - proto.kind = irCallToPrimitiveKind(call) - proto.symbol = serializeIrSymbol(call.symbol) - - call.superQualifierSymbol?.let { - proto.`super` = serializeIrSymbol(it) - } - proto.memberAccess = serializeMemberAccessCommon(call) - return proto.build() - } - - private fun serializeFunctionReference(callable: IrFunctionReference): KonanIr.IrFunctionReference { - val proto = KonanIr.IrFunctionReference.newBuilder() - .setSymbol(serializeIrSymbol(callable.symbol)) - .setMemberAccess(serializeMemberAccessCommon(callable)) - callable.origin?.let { proto.origin = serializeIrStatementOrigin(it) } - return proto.build() - } - - - private fun serializePropertyReference(callable: IrPropertyReference): KonanIr.IrPropertyReference { - val proto = KonanIr.IrPropertyReference.newBuilder() - .setMemberAccess(serializeMemberAccessCommon(callable)) - callable.field?.let { proto.field = serializeIrSymbol(it) } - callable.getter?.let { proto.getter = serializeIrSymbol(it) } - callable.setter?.let { proto.setter = serializeIrSymbol(it) } - callable.origin?.let { proto.origin = serializeIrStatementOrigin(it) } - val property = callable.getter!!.owner.correspondingProperty!! - descriptorReferenceSerializer.serializeDescriptorReference(property)?.let { proto.setDescriptor(it) } - return proto.build() - } - - private fun serializeClassReference(expression: IrClassReference): KonanIr.IrClassReference { - val proto = KonanIr.IrClassReference.newBuilder() - .setClassSymbol(serializeIrSymbol(expression.symbol)) - .setClassType(serializeIrType(expression.classType)) - return proto.build() - } - - private fun serializeConst(value: IrConst<*>): KonanIr.IrConst { - val proto = KonanIr.IrConst.newBuilder() - when (value.kind) { - IrConstKind.Null -> proto.`null` = true - IrConstKind.Boolean -> proto.boolean = value.value as Boolean - IrConstKind.Byte -> proto.byte = (value.value as Byte).toInt() - IrConstKind.Char -> proto.char = (value.value as Char).toInt() - IrConstKind.Short -> proto.short = (value.value as Short).toInt() - IrConstKind.Int -> proto.int = value.value as Int - IrConstKind.Long -> proto.long = value.value as Long - IrConstKind.String -> proto.string = serializeString(value.value as String) - IrConstKind.Float -> proto.float = value.value as Float - IrConstKind.Double -> proto.double = value.value as Double - } - return proto.build() - } - - private fun serializeDelegatingConstructorCall(call: IrDelegatingConstructorCall): KonanIr.IrDelegatingConstructorCall { - val proto = KonanIr.IrDelegatingConstructorCall.newBuilder() - .setSymbol(serializeIrSymbol(call.symbol)) - .setMemberAccess(serializeMemberAccessCommon(call)) - return proto.build() - } - - private fun serializeDoWhile(expression: IrDoWhileLoop): KonanIr.IrDoWhile { - val proto = KonanIr.IrDoWhile.newBuilder() - .setLoop(serializeLoop(expression)) - - return proto.build() - } - - fun serializeEnumConstructorCall(call: IrEnumConstructorCall): KonanIr.IrEnumConstructorCall { - val proto = KonanIr.IrEnumConstructorCall.newBuilder() - .setSymbol(serializeIrSymbol(call.symbol)) - .setMemberAccess(serializeMemberAccessCommon(call)) - return proto.build() - } - - private fun serializeGetClass(expression: IrGetClass): KonanIr.IrGetClass { - val proto = KonanIr.IrGetClass.newBuilder() - .setArgument(serializeExpression(expression.argument)) - return proto.build() - } - - private fun serializeGetEnumValue(expression: IrGetEnumValue): KonanIr.IrGetEnumValue { - val proto = KonanIr.IrGetEnumValue.newBuilder() - .setSymbol(serializeIrSymbol(expression.symbol)) - return proto.build() - } - - private fun serializeFieldAccessCommon(expression: IrFieldAccessExpression): KonanIr.FieldAccessCommon { - val proto = KonanIr.FieldAccessCommon.newBuilder() - .setSymbol(serializeIrSymbol(expression.symbol)) - expression.superQualifierSymbol?.let { proto.`super` = serializeIrSymbol(it) } - expression.receiver?.let { proto.receiver = serializeExpression(it) } - return proto.build() - } - - private fun serializeGetField(expression: IrGetField): KonanIr.IrGetField { - val proto = KonanIr.IrGetField.newBuilder() - .setFieldAccess(serializeFieldAccessCommon(expression)) - return proto.build() - } - - private fun serializeGetValue(expression: IrGetValue): KonanIr.IrGetValue { - val proto = KonanIr.IrGetValue.newBuilder() - .setSymbol(serializeIrSymbol(expression.symbol)) - return proto.build() - } - - private fun serializeGetObject(expression: IrGetObjectValue): KonanIr.IrGetObject { - val proto = KonanIr.IrGetObject.newBuilder() - .setSymbol(serializeIrSymbol(expression.symbol)) - return proto.build() - } - - private fun serializeInstanceInitializerCall(call: IrInstanceInitializerCall): KonanIr.IrInstanceInitializerCall { - val proto = KonanIr.IrInstanceInitializerCall.newBuilder() - - proto.symbol = serializeIrSymbol(call.classSymbol) - - return proto.build() - } - - private fun serializeReturn(expression: IrReturn): KonanIr.IrReturn { - val proto = KonanIr.IrReturn.newBuilder() - .setReturnTarget(serializeIrSymbol(expression.returnTargetSymbol)) - .setValue(serializeExpression(expression.value)) - return proto.build() - } - - private fun serializeSetField(expression: IrSetField): KonanIr.IrSetField { - val proto = KonanIr.IrSetField.newBuilder() - .setFieldAccess(serializeFieldAccessCommon(expression)) - .setValue(serializeExpression(expression.value)) - return proto.build() - } - - private fun serializeSetVariable(expression: IrSetVariable): KonanIr.IrSetVariable { - val proto = KonanIr.IrSetVariable.newBuilder() - .setSymbol(serializeIrSymbol(expression.symbol)) - .setValue(serializeExpression(expression.value)) - return proto.build() - } - - private fun serializeSpreadElement(element: IrSpreadElement): KonanIr.IrSpreadElement { - val coordinates = serializeCoordinates(element.startOffset, element.endOffset) - return KonanIr.IrSpreadElement.newBuilder() - .setExpression(serializeExpression(element.expression)) - .setCoordinates(coordinates) - .build() - } - - private fun serializeSyntheticBody(expression: IrSyntheticBody) = KonanIr.IrSyntheticBody.newBuilder() - .setKind( - when (expression.kind) { - IrSyntheticBodyKind.ENUM_VALUES -> KonanIr.IrSyntheticBodyKind.ENUM_VALUES - IrSyntheticBodyKind.ENUM_VALUEOF -> KonanIr.IrSyntheticBodyKind.ENUM_VALUEOF - } - ) - .build() - - private fun serializeThrow(expression: IrThrow): KonanIr.IrThrow { - val proto = KonanIr.IrThrow.newBuilder() - .setValue(serializeExpression(expression.value)) - return proto.build() - } - - private fun serializeTry(expression: IrTry): KonanIr.IrTry { - val proto = KonanIr.IrTry.newBuilder() - .setResult(serializeExpression(expression.tryResult)) - val catchList = expression.catches - catchList.forEach { - proto.addCatch(serializeStatement(it)) - } - val finallyExpression = expression.finallyExpression - if (finallyExpression != null) { - proto.finally = serializeExpression(finallyExpression) - } - return proto.build() - } - - private fun serializeTypeOperator(operator: IrTypeOperator): KonanIr.IrTypeOperator = when (operator) { - IrTypeOperator.CAST - -> KonanIr.IrTypeOperator.CAST - IrTypeOperator.IMPLICIT_CAST - -> KonanIr.IrTypeOperator.IMPLICIT_CAST - IrTypeOperator.IMPLICIT_NOTNULL - -> KonanIr.IrTypeOperator.IMPLICIT_NOTNULL - IrTypeOperator.IMPLICIT_COERCION_TO_UNIT - -> KonanIr.IrTypeOperator.IMPLICIT_COERCION_TO_UNIT - IrTypeOperator.IMPLICIT_INTEGER_COERCION - -> KonanIr.IrTypeOperator.IMPLICIT_INTEGER_COERCION - IrTypeOperator.SAFE_CAST - -> KonanIr.IrTypeOperator.SAFE_CAST - IrTypeOperator.INSTANCEOF - -> KonanIr.IrTypeOperator.INSTANCEOF - IrTypeOperator.NOT_INSTANCEOF - -> KonanIr.IrTypeOperator.NOT_INSTANCEOF - IrTypeOperator.SAM_CONVERSION - -> KonanIr.IrTypeOperator.SAM_CONVERSION - } - - private fun serializeTypeOp(expression: IrTypeOperatorCall): KonanIr.IrTypeOp { - val proto = KonanIr.IrTypeOp.newBuilder() - .setOperator(serializeTypeOperator(expression.operator)) - .setOperand(serializeIrType(expression.typeOperand)) - .setArgument(serializeExpression(expression.argument)) - return proto.build() - - } - - private fun serializeVararg(expression: IrVararg): KonanIr.IrVararg { - val proto = KonanIr.IrVararg.newBuilder() - .setElementType(serializeIrType(expression.varargElementType)) - expression.elements.forEach { - proto.addElement(serializeVarargElement(it)) - } - return proto.build() - } - - private fun serializeVarargElement(element: IrVarargElement): KonanIr.IrVarargElement { - val proto = KonanIr.IrVarargElement.newBuilder() - when (element) { - is IrExpression - -> proto.expression = serializeExpression(element) - is IrSpreadElement - -> proto.spreadElement = serializeSpreadElement(element) - else -> error("Unknown vararg element kind") - } - return proto.build() - } - - private fun serializeWhen(expression: IrWhen): KonanIr.IrWhen { - val proto = KonanIr.IrWhen.newBuilder() - - val branches = expression.branches - branches.forEach { - proto.addBranch(serializeStatement(it)) - } - - return proto.build() - } - - private fun serializeLoop(expression: IrLoop): KonanIr.Loop { - val proto = KonanIr.Loop.newBuilder() - .setCondition(serializeExpression(expression.condition)) - val label = expression.label?.let { serializeString(it) } - if (label != null) { - proto.label = label - } - - proto.loopId = currentLoopIndex - loopIndex[expression] = currentLoopIndex++ - - val body = expression.body - if (body != null) { - proto.body = serializeExpression(body) - } - - return proto.build() - } - - private fun serializeWhile(expression: IrWhileLoop): KonanIr.IrWhile { - val proto = KonanIr.IrWhile.newBuilder() - .setLoop(serializeLoop(expression)) - - return proto.build() - } - - private fun serializeBreak(expression: IrBreak): KonanIr.IrBreak { - val proto = KonanIr.IrBreak.newBuilder() - val label = expression.label?.let { serializeString(it) } - if (label != null) { - proto.label = label - } - val loopId = loopIndex[expression.loop]!! - proto.loopId = loopId - - return proto.build() - } - - private fun serializeContinue(expression: IrContinue): KonanIr.IrContinue { - val proto = KonanIr.IrContinue.newBuilder() - val label = expression.label?.let { serializeString(it) } - if (label != null) { - proto.label = label - } - val loopId = loopIndex[expression.loop]!! - proto.loopId = loopId - - return proto.build() - } - - private fun serializeExpression(expression: IrExpression): KonanIr.IrExpression { - logger.log { "### serializing Expression: ${ir2string(expression)}" } - - val coordinates = serializeCoordinates(expression.startOffset, expression.endOffset) - val proto = KonanIr.IrExpression.newBuilder() - .setType(serializeIrType(expression.type)) - .setCoordinates(coordinates) - - val operationProto = KonanIr.IrOperation.newBuilder() - - // TODO: make me a visitor. - when (expression) { - is IrBlock -> operationProto.block = serializeBlock(expression) - is IrBreak -> operationProto.`break` = serializeBreak(expression) - is IrClassReference - -> operationProto.classReference = serializeClassReference(expression) - is IrCall -> operationProto.call = serializeCall(expression) - - is IrComposite -> operationProto.composite = serializeComposite(expression) - is IrConst<*> -> operationProto.const = serializeConst(expression) - is IrContinue -> operationProto.`continue` = serializeContinue(expression) - is IrDelegatingConstructorCall - -> operationProto.delegatingConstructorCall = serializeDelegatingConstructorCall(expression) - is IrDoWhileLoop -> operationProto.doWhile = serializeDoWhile(expression) - is IrEnumConstructorCall - -> operationProto.enumConstructorCall = serializeEnumConstructorCall(expression) - is IrFunctionReference - -> operationProto.functionReference = serializeFunctionReference(expression) - is IrGetClass -> operationProto.getClass = serializeGetClass(expression) - is IrGetField -> operationProto.getField = serializeGetField(expression) - is IrGetValue -> operationProto.getValue = serializeGetValue(expression) - is IrGetEnumValue - -> operationProto.getEnumValue = serializeGetEnumValue(expression) - is IrGetObjectValue - -> operationProto.getObject = serializeGetObject(expression) - is IrInstanceInitializerCall - -> operationProto.instanceInitializerCall = serializeInstanceInitializerCall(expression) - is IrPropertyReference - -> operationProto.propertyReference = serializePropertyReference(expression) - is IrReturn -> operationProto.`return` = serializeReturn(expression) - is IrSetField -> operationProto.setField = serializeSetField(expression) - is IrSetVariable -> operationProto.setVariable = serializeSetVariable(expression) - is IrStringConcatenation - -> operationProto.stringConcat = serializeStringConcat(expression) - is IrThrow -> operationProto.`throw` = serializeThrow(expression) - is IrTry -> operationProto.`try` = serializeTry(expression) - is IrTypeOperatorCall - -> operationProto.typeOp = serializeTypeOp(expression) - is IrVararg -> operationProto.vararg = serializeVararg(expression) - is IrWhen -> operationProto.`when` = serializeWhen(expression) - is IrWhileLoop -> operationProto.`while` = serializeWhile(expression) - else -> { - TODO("Expression serialization not implemented yet: ${ir2string(expression)}.") - } - } - proto.setOperation(operationProto) - - return proto.build() - } - - private fun serializeStatement(statement: IrElement): KonanIr.IrStatement { - logger.log { "### serializing Statement: ${ir2string(statement)}" } - - val coordinates = serializeCoordinates(statement.startOffset, statement.endOffset) - val proto = KonanIr.IrStatement.newBuilder() - .setCoordinates(coordinates) - - when (statement) { - is IrDeclaration -> { - logger.log { " ###Declaration " }; proto.declaration = serializeDeclaration(statement) - } - is IrExpression -> { - logger.log { " ###Expression " }; proto.expression = serializeExpression(statement) - } - is IrBlockBody -> { - logger.log { " ###BlockBody " }; proto.blockBody = serializeBlockBody(statement) - } - is IrBranch -> { - logger.log { " ###Branch " }; proto.branch = serializeBranch(statement) - } - is IrCatch -> { - logger.log { " ###Catch " }; proto.catch = serializeCatch(statement) - } - is IrSyntheticBody -> { - logger.log { " ###SyntheticBody " }; proto.syntheticBody = serializeSyntheticBody(statement) - } - else -> { - TODO("Statement not implemented yet: ${ir2string(statement)}") - } - } - return proto.build() - } - - private fun serializeIrTypeAlias(typeAlias: IrTypeAlias) = KonanIr.IrTypeAlias.newBuilder().build() - - private fun serializeIrValueParameter(parameter: IrValueParameter): KonanIr.IrValueParameter { - val proto = KonanIr.IrValueParameter.newBuilder() - .setSymbol(serializeIrSymbol(parameter.symbol)) - .setName(serializeString(parameter.name.toString())) - .setIndex(parameter.index) - .setType(serializeIrType(parameter.type)) - .setIsCrossinline(parameter.isCrossinline) - .setIsNoinline(parameter.isNoinline) - - parameter.varargElementType?.let { proto.setVarargElementType(serializeIrType(it)) } - parameter.defaultValue?.let { proto.setDefaultValue(serializeExpression(it.expression)) } - - return proto.build() - } - - private fun serializeIrTypeParameter(parameter: IrTypeParameter): KonanIr.IrTypeParameter { - val proto = KonanIr.IrTypeParameter.newBuilder() - .setSymbol(serializeIrSymbol(parameter.symbol)) - .setName(serializeString(parameter.name.toString())) - .setIndex(parameter.index) - .setVariance(serializeIrTypeVariance(parameter.variance)) - .setIsReified(parameter.isReified) - parameter.superTypes.forEach { - proto.addSuperType(serializeIrType(it)) - } - return proto.build() - } - - private fun serializeIrTypeParameterContainer(typeParameters: List): KonanIr.IrTypeParameterContainer { - val proto = KonanIr.IrTypeParameterContainer.newBuilder() - typeParameters.forEach { - proto.addTypeParameter(serializeDeclaration(it)) - } - return proto.build() - } - - private fun serializeIrFunctionBase(function: IrFunction): KonanIr.IrFunctionBase { - val proto = KonanIr.IrFunctionBase.newBuilder() - .setName(serializeString(function.name.toString())) - .setVisibility(serializeVisibility(function.visibility)) - .setIsInline(function.isInline) - .setIsExternal(function.isExternal) - .setReturnType(serializeIrType(function.returnType)) - .setTypeParameters(serializeIrTypeParameterContainer(function.typeParameters)) - - function.dispatchReceiverParameter?.let { proto.setDispatchReceiver(serializeDeclaration(it)) } - function.extensionReceiverParameter?.let { proto.setExtensionReceiver(serializeDeclaration(it)) } - function.valueParameters.forEach { - //proto.addValueParameter(serializeIrValueParameter(it)) - proto.addValueParameter(serializeDeclaration(it)) - } - if (!bodiesOnlyForInlines || function.isInline) { - function.body?.let { proto.body = serializeStatement(it) } - } - return proto.build() - } - - private fun serializeModality(modality: Modality) = when (modality) { - Modality.FINAL -> KonanIr.ModalityKind.FINAL_MODALITY - Modality.SEALED -> KonanIr.ModalityKind.SEALED_MODALITY - Modality.OPEN -> KonanIr.ModalityKind.OPEN_MODALITY - Modality.ABSTRACT -> KonanIr.ModalityKind.ABSTRACT_MODALITY - } - - private fun serializeIrConstructor(declaration: IrConstructor): KonanIr.IrConstructor = - KonanIr.IrConstructor.newBuilder() - .setSymbol(serializeIrSymbol(declaration.symbol)) - .setBase(serializeIrFunctionBase(declaration)) - .setIsPrimary(declaration.isPrimary) - .build() - - private fun serializeIrFunction(declaration: IrSimpleFunction): KonanIr.IrFunction { - val function = declaration// as IrFunctionImpl - val proto = KonanIr.IrFunction.newBuilder() - .setSymbol(serializeIrSymbol(function.symbol)) - .setModality(serializeModality(function.modality)) - .setIsTailrec(function.isTailrec) - .setIsSuspend(function.isSuspend) - - function.overriddenSymbols.forEach { - proto.addOverridden(serializeIrSymbol(it)) - } - - //function.correspondingProperty?.let { - // val uniqId = declarationTable.uniqIdByDeclaration(it) - // proto.setCorrespondingProperty(protoUniqId(uniqId)) - //} - - val base = serializeIrFunctionBase(function) - proto.setBase(base) - - return proto.build() - } - - private fun serializeIrAnonymousInit(declaration: IrAnonymousInitializer) = KonanIr.IrAnonymousInit.newBuilder() - .setSymbol(serializeIrSymbol(declaration.symbol)) - .setBody(serializeStatement(declaration.body)) - .build() - - private fun serializeIrProperty(property: IrProperty): KonanIr.IrProperty { - val index = declarationTable.uniqIdByDeclaration(property) - - val proto = KonanIr.IrProperty.newBuilder() - .setIsDelegated(property.isDelegated) - .setName(serializeString(property.name.toString())) - .setVisibility(serializeVisibility(property.visibility)) - .setModality(serializeModality(property.modality)) - .setIsVar(property.isVar) - .setIsConst(property.isConst) - .setIsLateinit(property.isLateinit) - .setIsDelegated(property.isDelegated) - .setIsExternal(property.isExternal) - - descriptorReferenceSerializer.serializeDescriptorReference(property)?.let { proto.setDescriptor(it) } - - val backingField = property.backingField - val getter = property.getter - val setter = property.setter - if (backingField != null) - proto.backingField = serializeIrField(backingField) - if (getter != null) - proto.getter = serializeIrFunction(getter) - if (setter != null) - proto.setter = serializeIrFunction(setter) - - return proto.build() - } - - private fun serializeIrField(field: IrField): KonanIr.IrField { - val proto = KonanIr.IrField.newBuilder() - .setSymbol(serializeIrSymbol(field.symbol)) - .setName(serializeString(field.name.toString())) - .setVisibility(serializeVisibility(field.visibility)) - .setIsFinal(field.isFinal) - .setIsExternal(field.isExternal) - .setIsStatic(field.isStatic) - .setType(serializeIrType(field.type)) - val initializer = field.initializer?.expression - if (initializer != null) { - proto.initializer = serializeExpression(initializer) - } - return proto.build() - } - - private fun serializeIrVariable(variable: IrVariable): KonanIr.IrVariable { - val proto = KonanIr.IrVariable.newBuilder() - .setSymbol(serializeIrSymbol(variable.symbol)) - .setName(serializeString(variable.name.toString())) - .setType(serializeIrType(variable.type)) - .setIsConst(variable.isConst) - .setIsVar(variable.isVar) - .setIsLateinit(variable.isLateinit) - variable.initializer?.let { proto.initializer = serializeExpression(it) } - return proto.build() - } - - private fun serializeIrDeclarationContainer(declarations: List): KonanIr.IrDeclarationContainer { - val proto = KonanIr.IrDeclarationContainer.newBuilder() - declarations.forEach { - //if (it is IrDeclarationWithVisibility && it.visibility == Visibilities.INVISIBLE_FAKE) return@forEach - proto.addDeclaration(serializeDeclaration(it)) - } - return proto.build() - } - - private fun serializeClassKind(kind: ClassKind) = when (kind) { - CLASS -> KonanIr.ClassKind.CLASS - INTERFACE -> KonanIr.ClassKind.INTERFACE - ENUM_CLASS -> KonanIr.ClassKind.ENUM_CLASS - ENUM_ENTRY -> KonanIr.ClassKind.ENUM_ENTRY - ANNOTATION_CLASS -> KonanIr.ClassKind.ANNOTATION_CLASS - OBJECT -> KonanIr.ClassKind.OBJECT - } - - private fun serializeIrClass(clazz: IrClass): KonanIr.IrClass { - val proto = KonanIr.IrClass.newBuilder() - .setName(serializeString(clazz.name.toString())) - .setSymbol(serializeIrSymbol(clazz.symbol)) - .setKind(serializeClassKind(clazz.kind)) - .setVisibility(serializeVisibility(clazz.visibility)) - .setModality(serializeModality(clazz.modality)) - .setIsCompanion(clazz.isCompanion) - .setIsInner(clazz.isInner) - .setIsData(clazz.isData) - .setIsExternal(clazz.isExternal) - .setIsInline(clazz.isInline) - .setTypeParameters(serializeIrTypeParameterContainer(clazz.typeParameters)) - .setDeclarationContainer(serializeIrDeclarationContainer(clazz.declarations)) - clazz.superTypes.forEach { - proto.addSuperType(serializeIrType(it)) - } - clazz.thisReceiver?.let { proto.thisReceiver = serializeDeclaration(it) } - - return proto.build() - } - - private fun serializeIrEnumEntry(enumEntry: IrEnumEntry): KonanIr.IrEnumEntry { - val proto = KonanIr.IrEnumEntry.newBuilder() - .setName(serializeString(enumEntry.name.toString())) - .setSymbol(serializeIrSymbol(enumEntry.symbol)) - - enumEntry.initializerExpression?.let { - proto.initializer = serializeExpression(it) - } - enumEntry.correspondingClass?.let { - proto.correspondingClass = serializeDeclaration(it) - } - return proto.build() - } - - private fun serializeDeclaration(declaration: IrDeclaration): KonanIr.IrDeclaration { - logger.log { "### serializing Declaration: ${ir2string(declaration)}" } - - val declarator = KonanIr.IrDeclarator.newBuilder() - - when (declaration) { - is IrTypeAlias - -> declarator.irTypeAlias = serializeIrTypeAlias(declaration) - is IrAnonymousInitializer - -> declarator.irAnonymousInit = serializeIrAnonymousInit(declaration) - is IrConstructor - -> declarator.irConstructor = serializeIrConstructor(declaration) - is IrField - -> declarator.irField = serializeIrField(declaration) - is IrSimpleFunction - -> declarator.irFunction = serializeIrFunction(declaration) - is IrTypeParameter - -> declarator.irTypeParameter = serializeIrTypeParameter(declaration) - is IrVariable - -> declarator.irVariable = serializeIrVariable(declaration) - is IrValueParameter - -> declarator.irValueParameter = serializeIrValueParameter(declaration) - is IrClass - -> declarator.irClass = serializeIrClass(declaration) - is IrEnumEntry - -> declarator.irEnumEntry = serializeIrEnumEntry(declaration) - is IrProperty - -> declarator.irProperty = serializeIrProperty(declaration) - else - -> TODO("Declaration serialization not supported yet: $declaration") - } - - val coordinates = serializeCoordinates(declaration.startOffset, declaration.endOffset) - val annotations = serializeAnnotations(declaration.annotations) - val origin = serializeIrDeclarationOrigin(declaration.origin) - val proto = KonanIr.IrDeclaration.newBuilder() - .setCoordinates(coordinates) - .setAnnotations(annotations) - .setOrigin(origin) - - - proto.setDeclarator(declarator) - - return proto.build() - } - -// ---------- Top level ------------------------------------------------------ - - fun serializeFileEntry(entry: SourceManager.FileEntry) = KonanIr.FileEntry.newBuilder() - .setName(serializeString(entry.name)) - .addAllLineStartOffsets(entry.lineStartOffsets.asIterable()) - .build() - - fun serializeIrFile(file: IrFile): KonanIr.IrFile { - val proto = KonanIr.IrFile.newBuilder() - .setFileEntry(serializeFileEntry(file.fileEntry)) - .setFqName(serializeString(file.fqName.toString())) - .setAnnotations(serializeAnnotations(file.annotations)) - - file.declarations.forEach { - if (it is IrTypeAlias || (it.descriptor.isExpectMember && !it.descriptor.isSerializableExpectClass)) { - writer.skipDeclaration() - return@forEach - } - - val byteArray = serializeDeclaration(it).toByteArray() - val uniqId = declarationTable.uniqIdByDeclaration(it) - writer.addDeclaration(DeclarationId(uniqId.index, uniqId.isLocal), byteArray) - proto.addDeclarationId(protoUniqId(uniqId)) - } - - // Make sure that all top level properties are initialized on library's load. - file.declarations - .filterIsInstance() - .filter { it.backingField?.initializer != null && !it.isConst } - .forEach { proto.addExplicitlyExportedToCompiler(serializeIrSymbol(it.backingField!!.symbol)) } - - file.acceptVoid(object: IrElementVisitorVoid { - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitFunction(declaration: IrFunction) { - if (declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportForCppRuntime) - || declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) - proto.addExplicitlyExportedToCompiler(serializeIrSymbol(declaration.symbol)) - super.visitDeclaration(declaration) - } - - override fun visitClass(declaration: IrClass) { - if (declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportTypeInfoAnnotation)) - proto.addExplicitlyExportedToCompiler(serializeIrSymbol(declaration.symbol)) - super.visitDeclaration(declaration) - } - }) - - return proto.build() - } - - lateinit var writer: CombinedIrFileWriter - - fun serializeModule(module: IrModuleFragment): KonanIr.IrModule { - val proto = KonanIr.IrModule.newBuilder() - .setName(serializeString(module.name.toString())) - - val topLevelDeclarationsCount = module.files.sumBy { it.declarations.size } - - writer = CombinedIrFileWriter(topLevelDeclarationsCount) - - module.files.forEach { - proto.addFile(serializeIrFile(it)) - } - proto.symbolTable = KonanIr.IrSymbolTable.newBuilder() - .addAllSymbols(protoSymbolArray) - .build() - - proto.typeTable = KonanIr.IrTypeTable.newBuilder() - .addAllTypes(protoTypeArray) - .build() - - proto.stringTable = KonanIr.StringTable.newBuilder() - .addAllStrings(protoStringArray) - .build() - - return proto.build() - } - - - fun serializedIrModule(module: IrModuleFragment): SerializedIr { - val moduleHeader = serializeModule(module).toByteArray() - return SerializedIr(moduleHeader, writer.finishWriting().absolutePath, declarationTable.debugIndex) - } -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeclarationTable.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeclarationTable.kt new file mode 100644 index 00000000000..b22e789116a --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeclarationTable.kt @@ -0,0 +1,18 @@ +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable +import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns + + +// TODO: We don't manage id clashes anyhow now. +class KonanDeclarationTable(builtIns: IrBuiltIns, descriptorTable: DescriptorTable): + DeclarationTable(builtIns, descriptorTable, KonanMangler) { + override var currentIndex = 0L + +} + +// This is what we pre-populate tables with +val IrBuiltIns.knownBuiltins + get() = irBuiltInsExternalPackageFragment.declarations diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DeserializeDescriptorReference.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeserializeDescriptorReference.kt similarity index 56% rename from backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DeserializeDescriptorReference.kt rename to backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeserializeDescriptorReference.kt index b517b04b6db..db56ecd8d5d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DeserializeDescriptorReference.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeserializeDescriptorReference.kt @@ -1,5 +1,9 @@ package org.jetbrains.kotlin.backend.konan.serialization +import org.jetbrains.kotlin.backend.common.serialization.DescriptorReferenceDeserializer +import org.jetbrains.kotlin.backend.common.serialization.DescriptorUniqIdAware +import org.jetbrains.kotlin.backend.common.serialization.UniqId +import org.jetbrains.kotlin.backend.common.serialization.UniqIdKey import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.ClassId @@ -13,63 +17,30 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ // tree of deserialized descriptors. Think of it as base + offset. // packageFqName + classFqName + index allow to localize some deserialized descriptor. // Then the rest of the fields allow to find the needed descriptor relative to the one with index. -class DescriptorReferenceDeserializer(val currentModule: ModuleDescriptor, val resolvedForwardDeclarations: MutableMap) { +class KonanDescriptorReferenceDeserializer( + currentModule: ModuleDescriptor, + resolvedForwardDeclarations: MutableMap) + : DescriptorReferenceDeserializer(currentModule, resolvedForwardDeclarations), + DescriptorUniqIdAware by KonanDescriptorUniqIdAware{ - private fun getContributedDescriptors(packageFqNameString: String, name: String): Collection { - val packageFqName = packageFqNameString.let { - if (it == "") FqName.ROOT else FqName(it) - }// TODO: whould we store an empty string in the protobuf? + // TODO: these are dummies. Eliminate them. + override fun resolveSpecialDescriptor(fqn: FqName): DeclarationDescriptor = currentModule + override fun checkIfSpecialDescriptorId(id: Long): Boolean = false + override fun getDescriptorIdOrNull(descriptor: DeclarationDescriptor): Long? = null - val memberScope = currentModule.getPackage(packageFqName).memberScope - return getContributedDescriptors(memberScope, name) - } - - private fun getContributedDescriptors(memberScope: MemberScope, name: String): Collection { - val contributedNameString = if (name.startsWith(", - val realMembers: Map) - - private fun getMembers(members: Collection): ClassMembers { - val allMembersMap = mutableMapOf() - val realMembersMap = mutableMapOf() - var classConstructorDescriptor: ClassConstructorDescriptor? = null - members.forEach { member -> - if (member is ClassConstructorDescriptor) - classConstructorDescriptor = member - val realMembers = - if (member is CallableMemberDescriptor && member.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) - member.resolveFakeOverrideMaybeAbstract() - else - setOf(member) - - member.getUniqId()?.index?.let { allMembersMap[it] = member } - realMembers.mapNotNull { it.getUniqId()?.index }.forEach { realMembersMap[it] = member } - } - return ClassMembers(classConstructorDescriptor, allMembersMap, realMembersMap) - } - - fun deserializeDescriptorReference( + // Most of this function duplicates the parent, but it deals with forward declarations. + // TODO: Refactor me. + override fun deserializeDescriptorReference( packageFqNameString: String, classFqNameString: String, name: String, index: Long?, - isEnumEntry: Boolean = false, - isEnumSpecial: Boolean = false, - isDefaultConstructor: Boolean = false, - isFakeOverride: Boolean = false, - isGetter: Boolean = false, - isSetter: Boolean = false + isEnumEntry: Boolean, + isEnumSpecial: Boolean, + isDefaultConstructor: Boolean, + isFakeOverride: Boolean, + isGetter: Boolean, + isSetter: Boolean ): DeclarationDescriptor { val packageFqName = packageFqNameString.let { if (it == "") FqName.ROOT else FqName(it) @@ -93,7 +64,7 @@ class DescriptorReferenceDeserializer(val currentModule: ModuleDescriptor, val r ) ) { if (descriptor is DeserializedClassDescriptor) { - val uniqId = UniqId(descriptor.getUniqId()!!.index, false) + val uniqId = UniqId(descriptor.getUniqId()!!, false) val newKey = UniqIdKey(null, uniqId) val oldKey = UniqIdKey(null, UniqId(protoIndex!!, false)) @@ -132,4 +103,4 @@ class DescriptorReferenceDeserializer(val currentModule: ModuleDescriptor, val r } } ?: error("Could not find serialized descriptor for index: ${index} ${packageFqName},${classFqName},${name}") } -} \ No newline at end of file +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto deleted file mode 100644 index ccdda541e40..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto +++ /dev/null @@ -1,660 +0,0 @@ -syntax = "proto2"; -package org.jetbrains.kotlin.metadata; - -option java_outer_classname = "KonanIr"; -option optimize_for = LITE_RUNTIME; - -message DescriptorReference { - required String package_fq_name = 1; - required String class_fq_name = 2; - required String name = 3; - optional UniqId uniq_id = 4; - optional bool is_getter = 5 [default = false]; - optional bool is_setter = 6 [default = false]; - optional bool is_backing_field = 7 [default = false]; - optional bool is_fake_override = 8 [default = false]; - optional bool is_default_constructor = 9 [default = false]; - optional bool is_enum_entry = 10 [default = false]; - optional bool is_enum_special = 11 [default = false]; -} - -message UniqId { - required uint64 index = 1; - required bool isLocal = 2; -} - -message Coordinates { - required int32 start_offset = 1; - required int32 end_offset = 2; -} - -message Visibility { - required String name = 1; -} - -message IrStatementOrigin { - required String name = 1; -} - -enum KnownOrigin { - CUSTOM = 1; - DEFINED = 2; - FAKE_OVERRIDE = 3; - FOR_LOOP_ITERATOR = 4; - FOR_LOOP_VARIABLE = 5; - FOR_LOOP_IMPLICIT_VARIABLE = 6; - PROPERTY_BACKING_FIELD = 7; - DEFAULT_PROPERTY_ACCESSOR = 8; - DELEGATE = 9; - DELEGATED_PROPERTY_ACCESSOR = 10; - DELEGATED_MEMBER = 11; - ENUM_CLASS_SPECIAL_MEMBER = 12; - FUNCTION_FOR_DEFAULT_PARAMETER = 13; - FILE_CLASS = 14; - GENERATED_DATA_CLASS_MEMBER = 15; - GENERATED_INLINE_CLASS_MEMBER = 16; - LOCAL_FUNCTION_FOR_LAMBDA = 17; - CATCH_PARAMETER = 19; - INSTANCE_RECEIVER = 20; - PRIMARY_CONSTRUCTOR_PARAMETER = 21; - IR_TEMPORARY_VARIABLE = 22; - IR_EXTERNAL_DECLARATION_STUB = 23; - IR_EXTERNAL_JAVA_DECLARATION_STUB = 24; - IR_BUILTINS_STUB = 25; - BRIDGE = 26; - FIELD_FOR_ENUM_ENTRY = 27; - FIELD_FOR_ENUM_VALUES = 28; - FIELD_FOR_OBJECT_INSTANCE = 29; -} - -message IrDeclarationOrigin { - oneof either { - KnownOrigin origin = 1; - String custom = 2; - } -} - -/* ------ Top Level---------------------------------------KonanIrModuleDeserializer.kt------- */ - -message IrDeclarationContainer { - repeated IrDeclaration declaration = 1; -} - -message FileEntry { - required String name = 1; - repeated int32 line_start_offsets = 2; -} - -message IrFile { - repeated UniqId declaration_id = 1; - required FileEntry file_entry = 2; - required String fq_name = 3; - required Annotations annotations = 4; - repeated IrSymbol explicitly_exported_to_compiler = 5; // Symbols referenced by C runtime. TODO: Make an extension? -} - -message IrModule { - required String name = 1; - repeated IrFile file = 2; - required IrSymbolTable symbol_table = 3; - required IrTypeTable type_table = 4; - required StringTable string_table = 5; -} - -/* ------ String Table ------------------------------------------ */ - -message String { - required int32 index = 1; -} - -message StringTable { - repeated string strings = 1; -} - -/* ------ IrSymbols --------------------------------------------- */ - -enum IrSymbolKind { - FUNCTION_SYMBOL = 1; - CONSTRUCTOR_SYMBOL = 2; - ENUM_ENTRY_SYMBOL = 3; - FIELD_SYMBOL = 4; - VALUE_PARAMETER_SYMBOL = 5; - RETURNABLE_BLOCK_SYMBOL = 6; - CLASS_SYMBOL = 7; - TYPE_PARAMETER_SYMBOL = 8; - VARIABLE_SYMBOL = 9; - ANONYMOUS_INIT_SYMBOL = 10; - - STANDALONE_FIELD_SYMBOL = 11; // For fields without properties. WrappedFieldDescriptor, rather than WrappedPropertyDescriptor. - RECEIVER_PARAMETER_SYMBOL = 12; // ReceiverParameterDescriptor rather than ValueParameterDescriptor. -} - -message IrSymbolData { - required IrSymbolKind kind = 1; - required UniqId uniq_id = 2; - required UniqId top_level_uniq_id = 3; - optional String fqname = 4; - optional DescriptorReference descriptor_reference = 5; -} - -message IrSymbol { - required int32 index = 1; -} - -message IrSymbolTable { - repeated IrSymbolData symbols = 1; -} - -/* ------ IrTypes --------------------------------------------- */ - -enum IrTypeVariance { // Should we import metadata variance, or better stay separate? - IN = 0; - OUT = 1; - INV = 2; -} - -message Annotations { - repeated IrCall annotation = 1; -} - -message TypeArguments { - repeated IrTypeIndex type_argument = 1; -} - -message IrStarProjection { - optional bool void = 1; -} - -message IrTypeProjection { - required IrTypeVariance variance = 1; - required IrTypeIndex type = 2; -} - -message IrTypeArgument { - oneof kind { - IrStarProjection star = 1; - IrTypeProjection type = 2; - } -} - -message IrSimpleType { - required Annotations annotations = 1; - required IrSymbol classifier = 2; - required bool has_question_mark = 3; - repeated IrTypeArgument argument = 4; -} - -message IrDynamicType { - required Annotations annotations = 1; -} - -message IrErrorType { - required Annotations annotations = 1; -} - -message IrType { - oneof kind { - IrSimpleType simple = 1; - IrDynamicType dynamic = 2; - IrErrorType error = 3; - } -} - -message IrTypeTable { - repeated IrType types = 1; -} - -message IrTypeIndex { - required int32 index = 1; -} - -/* ------ IrExpressions --------------------------------------------- */ - -message IrBreak { - required int32 loop_id = 1; - optional String label = 2; -} - -message IrBlock { - required bool is_lambda_origin = 1; - repeated IrStatement statement = 2; -} - -message MemberAccessCommon { - optional IrExpression dispatch_receiver = 1; - optional IrExpression extension_receiver = 2; - repeated NullableIrExpression value_argument = 3; - required TypeArguments type_arguments = 4; -} - -message IrCall { - enum Primitive { - NOT_PRIMITIVE = 1; - NULLARY = 2; - UNARY = 3; - BINARY = 4; - } - required Primitive kind = 1; - required IrSymbol symbol = 2; - required MemberAccessCommon member_access = 3; - optional IrSymbol super = 4; -} - -message IrFunctionReference { - required IrSymbol symbol = 1; - optional IrStatementOrigin origin = 2; - required MemberAccessCommon member_access = 3; -} - - -message IrPropertyReference { - optional IrSymbol field = 1; - optional IrSymbol getter = 2; - optional IrSymbol setter = 3; - optional IrStatementOrigin origin = 4; - required MemberAccessCommon member_access = 5; - optional DescriptorReference descriptor = 6; // IrProperty doesn't have a symbol at all. Preserve this rudiment for now. -} - -message IrComposite { - repeated IrStatement statement = 1; -} - -message IrClassReference { - required IrSymbol class_symbol = 1; - required IrTypeIndex class_type = 2; -} - -message IrConst { - oneof value { - bool null = 1; - bool boolean = 2; - int32 char = 3; - int32 byte = 4; - int32 short = 5; - int32 int = 6; - int64 long = 7; - float float = 8; - double double = 9; - String string = 10; - } -} - -message IrContinue { - required int32 loop_id = 1; - optional String label = 2; -} - -message IrDelegatingConstructorCall { - required IrSymbol symbol = 1; - required MemberAccessCommon member_access = 2; -} - -message IrDoWhile { - required Loop loop = 1; -} - -message IrEnumConstructorCall { - required IrSymbol symbol = 1; - required MemberAccessCommon member_access = 2; -} - -message IrGetClass { - required IrExpression argument = 1; -} - -message IrGetEnumValue { - required IrSymbol symbol = 2; -} - -message FieldAccessCommon { - required IrSymbol symbol = 1; - optional IrSymbol super = 2; - optional IrExpression receiver = 3; -} - -message IrGetField { - required FieldAccessCommon field_access = 1; -} - -message IrGetValue { - required IrSymbol symbol = 1; -} - -message IrGetObject { - required IrSymbol symbol = 1; -} - -message IrInstanceInitializerCall { - required IrSymbol symbol = 1; -} - -message Loop { - required int32 loop_id = 1; - required IrExpression condition = 2; - optional String label = 3; - optional IrExpression body = 4; -} - -message IrReturn { - required IrSymbol return_target = 1; - required IrExpression value = 2; -} - -message IrSetField { - required FieldAccessCommon field_access = 1; - required IrExpression value = 2; -} - -message IrSetVariable { - required IrSymbol symbol = 1; - required IrExpression value = 2; -} - -message IrSpreadElement { - required IrExpression expression = 1; - required Coordinates coordinates = 2; -} - -message IrStringConcat { - repeated IrExpression argument = 1; -} - -message IrThrow { - required IrExpression value = 1; -} - -message IrTry { - required IrExpression result = 1; - repeated IrStatement catch = 2; - optional IrExpression finally = 3; -} - -message IrTypeOp { - required IrTypeOperator operator = 1; - required IrTypeIndex operand = 2; - required IrExpression argument = 3; -} - -message IrVararg { - required IrTypeIndex element_type = 1; - repeated IrVarargElement element = 2; -} - -message IrVarargElement { - oneof vararg_element { - IrExpression expression = 1; - IrSpreadElement spread_element = 2; - } -} - -message IrWhen { - repeated IrStatement branch = 1; -} - -message IrWhile { - required Loop loop = 1; -} - -// TODO: we need an extension mechanism to accomodate new -// IR operators in upcoming releases. -message IrOperation { - oneof operation { - IrBlock block = 1; - IrBreak break = 2; - IrCall call = 3; - IrClassReference class_reference = 4; - IrComposite composite = 5; - IrConst const = 6; - IrContinue continue = 7; - IrDelegatingConstructorCall delegating_constructor_call = 8; - IrDoWhile do_while = 9; - IrEnumConstructorCall enum_constructor_call = 10; - IrFunctionReference function_reference = 11; - IrGetClass get_class = 12; - IrGetEnumValue get_enum_value = 13; - IrGetField get_field = 14; - IrGetObject get_object = 15; - IrGetValue get_value = 16; - IrInstanceInitializerCall instance_initializer_call = 17; - IrPropertyReference property_reference = 18; - IrReturn return = 19; - IrSetField set_field = 20; - IrSetVariable set_variable = 21; - IrStringConcat string_concat = 22; - IrThrow throw = 23; - IrTry try = 24; - IrTypeOp type_op = 25; - IrVararg vararg = 26; - IrWhen when = 27; - IrWhile while = 28; - } -} - -enum IrTypeOperator { - CAST = 1; - IMPLICIT_CAST = 2; - IMPLICIT_NOTNULL = 3; - IMPLICIT_COERCION_TO_UNIT = 4; - IMPLICIT_INTEGER_COERCION = 5; - SAFE_CAST = 6; - INSTANCEOF = 7; - NOT_INSTANCEOF = 8; - SAM_CONVERSION = 9; -} - - -message IrExpression { - required IrOperation operation = 1; - required IrTypeIndex type = 2; - required Coordinates coordinates = 3; -} - -message NullableIrExpression { - optional IrExpression expression = 1; -} - -/* ------ Declarations --------------------------------------------- */ - -message IrTypeAlias { - // Nothing for now. -} - -message IrFunction { - required IrSymbol symbol = 1; - required IrFunctionBase base = 2; - required ModalityKind modality = 3; - required bool is_tailrec = 4; - required bool is_suspend = 5; - repeated IrSymbol overridden = 6; - //optional UniqId corresponding_property = 7; -} - -message IrFunctionBase { - required String name = 1; - required Visibility visibility = 2; - required bool is_inline = 3; - required bool is_external = 4; - required IrTypeParameterContainer type_parameters = 5; - optional IrDeclaration dispatch_receiver = 6; - optional IrDeclaration extension_receiver = 7; - repeated IrDeclaration value_parameter = 8; - optional IrStatement body = 9; - required IrTypeIndex return_type = 10; -} - -message IrConstructor { - required IrSymbol symbol = 1; - required IrFunctionBase base = 2; - required bool is_primary = 3; - -} - -message IrField { - required IrSymbol symbol = 1; - optional IrExpression initializer = 2; - required String name = 3; - required Visibility visibility = 4; - required bool is_final = 5; - required bool is_external = 6; - required bool is_static = 7; - required IrTypeIndex type = 8; -} - -message IrProperty { - optional DescriptorReference descriptor = 1; // IrProperty doesn't have a symbol at all. Preserve this rudiment for now. - required String name = 2; - required Visibility visibility = 3; - required ModalityKind modality = 4; - required bool is_var = 5; - required bool is_const = 6; - required bool is_lateinit = 7; - required bool is_delegated = 8; - required bool is_external = 9; - optional IrField backing_field = 10; - optional IrFunction getter = 11; - optional IrFunction setter = 12; -} - -message IrVariable { - required String name = 1; - required IrSymbol symbol = 2; - required IrTypeIndex type = 3; - required bool is_var = 4; - required bool is_const = 5; - required bool is_lateinit = 6; - optional IrExpression initializer = 7; -} - -enum ClassKind { - CLASS = 1; - INTERFACE = 2; - ENUM_CLASS = 3; - ENUM_ENTRY = 4; - ANNOTATION_CLASS = 5; - OBJECT = 6; -} - -enum ModalityKind { // It is ModalityKind to not clash with Modality in descriptor metadata. - FINAL_MODALITY = 1; - SEALED_MODALITY = 2; - OPEN_MODALITY = 3; - ABSTRACT_MODALITY = 4; -} - -message IrValueParameter { - required IrSymbol symbol = 1; - required String name = 2; - required int32 index = 3; - required IrTypeIndex type = 4; - optional IrTypeIndex vararg_element_type = 5; - required bool is_crossinline = 6; - required bool is_noinline = 7; - optional IrExpression default_value = 8; -} - -message IrTypeParameter { - required IrSymbol symbol = 1; - required String name = 2; - required int32 index = 3; - required IrTypeVariance variance = 4; - repeated IrTypeIndex super_type = 5; - required bool is_reified = 6; -} - -message IrTypeParameterContainer { - repeated IrDeclaration type_parameter = 1; -} - -message IrClass { - required IrSymbol symbol = 1; - required String name = 2; - required ClassKind kind = 3; - required Visibility visibility = 4; - required ModalityKind modality = 5; - // TODO: consider using flags for the booleans. - required bool is_companion = 6; - required bool is_inner = 7; - required bool is_data = 8; - required bool is_external = 9; - required bool is_inline = 10; - optional IrDeclaration this_receiver = 11; - required IrTypeParameterContainer type_parameters = 12; - required IrDeclarationContainer declaration_container = 13; - repeated IrTypeIndex super_type = 14; -} - -message IrEnumEntry { - required IrSymbol symbol = 1; - optional IrExpression initializer = 2; - optional IrDeclaration corresponding_class = 3; - required String name = 4; -} - -message IrAnonymousInit { - required IrSymbol symbol = 1; - required IrStatement body = 2; -} - -// TODO: we need an extension mechanism to accomodate new -// IR operators in upcoming releases. -message IrDeclarator { - oneof declarator { - IrAnonymousInit ir_anonymous_init = 1; - IrClass ir_class = 2; - IrConstructor ir_constructor = 3; - IrEnumEntry ir_enum_entry = 4; - IrField ir_field = 5; - IrFunction ir_function = 6; - IrProperty ir_property = 7; - IrTypeAlias ir_type_alias = 8; - IrTypeParameter ir_type_parameter = 9; - IrVariable ir_variable = 10; - IrValueParameter ir_value_parameter = 11; - } -} - -message IrDeclaration { - required IrDeclarationOrigin origin = 1; - required Coordinates coordinates = 2; - required Annotations annotations = 3; - required IrDeclarator declarator = 4; -} - -/* ------- IrStatements --------------------------------------------- */ - -message IrBranch { - required IrExpression condition = 1; - required IrExpression result = 2; -} - -message IrBlockBody { - repeated IrStatement statement = 1; -} - -message IrCatch { - required IrDeclaration catch_parameter = 1; - required IrExpression result = 2; -} - -enum IrSyntheticBodyKind { - ENUM_VALUES = 1; - ENUM_VALUEOF = 2; -} - -message IrSyntheticBody { - required IrSyntheticBodyKind kind = 1; -} - -// Let's try to map IrElement as well as IrStatement to IrStatement. -message IrStatement { - required Coordinates coordinates = 1; - oneof statement { - IrDeclaration declaration = 2; - IrExpression expression = 3; - IrBlockBody block_body = 4; - IrBranch branch = 5; - IrCatch catch = 6; - IrSyntheticBody synthetic_body = 7; - } -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleDeserializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleDeserializer.kt deleted file mode 100644 index 23147f884d9..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleDeserializer.kt +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.konan.serialization - -import org.jetbrains.kotlin.backend.common.LoggingContext -import org.jetbrains.kotlin.backend.common.descriptors.* -import org.jetbrains.kotlin.backend.konan.descriptors.findPackage -import org.jetbrains.kotlin.backend.konan.descriptors.findTopLevelDescriptor -import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule -import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary -import org.jetbrains.kotlin.backend.konan.ir.NaiveSourceBasedFileEntryImpl -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.* -import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns -import org.jetbrains.kotlin.ir.expressions.impl.IrLoopBase -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.util.SymbolTable -import org.jetbrains.kotlin.ir.util.patchDeclarationParents -import org.jetbrains.kotlin.metadata.KonanIr -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.descriptorUtil.module -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor -import org.jetbrains.kotlin.serialization.konan.KonanSerializerProtocol - -class KonanIrModuleDeserializer( - currentModule: ModuleDescriptor, - logger: LoggingContext, - builtIns: IrBuiltIns, - symbolTable: SymbolTable, - val forwardModuleDescriptor: ModuleDescriptor?) - : IrModuleDeserializer(logger, builtIns, symbolTable) { - - val deserializedSymbols = mutableMapOf() - val reachableTopLevels = mutableSetOf() - val deserializedTopLevels = mutableSetOf() - val forwardDeclarations = mutableSetOf() - - var deserializedModuleDescriptor: ModuleDescriptor? = null - var deserializedModuleProtoSymbolTables = mutableMapOf() - var deserializedModuleProtoStringTables = mutableMapOf() - var deserializedModuleProtoTypeTables = mutableMapOf() - var deserializedModuleLoops = mutableMapOf, IrLoopBase>() - - val resolvedForwardDeclarations = mutableMapOf() - val descriptorReferenceDeserializer = DescriptorReferenceDeserializer(currentModule, resolvedForwardDeclarations) - - init { - var currentIndex = 0L - builtIns.knownBuiltins.forEach { - require(it is IrFunction) - deserializedSymbols.put(UniqIdKey(null, UniqId(currentIndex, isLocal = false)), it.symbol) - assert(symbolTable.referenceSimpleFunction(it.descriptor) == it.symbol) - currentIndex++ - } - } - - private fun referenceDeserializedSymbol(proto: KonanIr.IrSymbolData, descriptor: DeclarationDescriptor?): IrSymbol = when (proto.kind) { - KonanIr.IrSymbolKind.ANONYMOUS_INIT_SYMBOL -> - IrAnonymousInitializerSymbolImpl( - descriptor as ClassDescriptor? - ?: WrappedClassDescriptor() - ) - KonanIr.IrSymbolKind.CLASS_SYMBOL -> - symbolTable.referenceClass( - descriptor as ClassDescriptor? - ?: WrappedClassDescriptor() - ) - KonanIr.IrSymbolKind.CONSTRUCTOR_SYMBOL -> - symbolTable.referenceConstructor( - descriptor as ClassConstructorDescriptor? - ?: WrappedClassConstructorDescriptor() - ) - KonanIr.IrSymbolKind.TYPE_PARAMETER_SYMBOL -> - symbolTable.referenceTypeParameter( - descriptor as TypeParameterDescriptor? - ?: WrappedTypeParameterDescriptor() - ) - KonanIr.IrSymbolKind.ENUM_ENTRY_SYMBOL -> - symbolTable.referenceEnumEntry( - descriptor as ClassDescriptor? - ?: WrappedEnumEntryDescriptor() - ) - KonanIr.IrSymbolKind.STANDALONE_FIELD_SYMBOL -> - symbolTable.referenceField(WrappedFieldDescriptor()) - - KonanIr.IrSymbolKind.FIELD_SYMBOL -> - symbolTable.referenceField( - descriptor as PropertyDescriptor? - ?: WrappedPropertyDescriptor() - ) - KonanIr.IrSymbolKind.FUNCTION_SYMBOL -> - symbolTable.referenceSimpleFunction( - descriptor as FunctionDescriptor? - ?: WrappedSimpleFunctionDescriptor() - ) - KonanIr.IrSymbolKind.VARIABLE_SYMBOL -> - IrVariableSymbolImpl( - descriptor as VariableDescriptor? - ?: WrappedVariableDescriptor() - ) - KonanIr.IrSymbolKind.VALUE_PARAMETER_SYMBOL -> - IrValueParameterSymbolImpl( - descriptor as ParameterDescriptor? - ?: WrappedValueParameterDescriptor() - ) - KonanIr.IrSymbolKind.RECEIVER_PARAMETER_SYMBOL -> - IrValueParameterSymbolImpl( - descriptor as ParameterDescriptor? ?: WrappedReceiverParameterDescriptor() - ) - else -> TODO("Unexpected classifier symbol kind: ${proto.kind}") - } - - override fun deserializeIrSymbol(proto: KonanIr.IrSymbol): IrSymbol { - val symbolData = - deserializedModuleProtoSymbolTables[deserializedModuleDescriptor]!!.getSymbols(proto.index) - return deserializeIrSymbolData(symbolData) - } - - override fun deserializeIrType(proto: KonanIr.IrTypeIndex): IrType { - val typeData = - deserializedModuleProtoTypeTables[deserializedModuleDescriptor]!!.getTypes(proto.index) - return deserializeIrTypeData(typeData) - } - - override fun deserializeString(proto: KonanIr.String) = - deserializedModuleProtoStringTables[deserializedModuleDescriptor]!!.getStrings(proto.index) - - override fun deserializeLoopHeader(loopIndex: Int, loopBuilder: () -> IrLoopBase) = - deserializedModuleLoops.getOrPut(deserializedModuleDescriptor!! to loopIndex, loopBuilder) - - fun deserializeIrSymbolData(proto: KonanIr.IrSymbolData): IrSymbol { - val key = proto.uniqId.uniqIdKey(deserializedModuleDescriptor!!) - val topLevelKey = proto.topLevelUniqId.uniqIdKey(deserializedModuleDescriptor!!) - - if (!deserializedTopLevels.contains(topLevelKey)) reachableTopLevels.add(topLevelKey) - - val symbol = deserializedSymbols.getOrPut(key) { - val descriptor = if (proto.hasDescriptorReference()) { - deserializeDescriptorReference(proto.descriptorReference) - } else { - null - } - - resolvedForwardDeclarations[key]?.let { - if (!deserializedTopLevels.contains(it)) reachableTopLevels.add(it) // Assuming forward declarations are always top levels. - } - - referenceDeserializedSymbol(proto, descriptor) - } - - if (symbol.descriptor is ClassDescriptor && - symbol.descriptor !is WrappedDeclarationDescriptor<*> && - symbol.descriptor.module.isForwardDeclarationModule - ) { - forwardDeclarations.add(symbol) - } - - return symbol - } - - override fun deserializeDescriptorReference(proto: KonanIr.DescriptorReference): DeclarationDescriptor = - descriptorReferenceDeserializer.deserializeDescriptorReference( - deserializeString(proto.packageFqName), - deserializeString(proto.classFqName), - deserializeString(proto.name), - if (proto.hasUniqId()) proto.uniqId.index else null, - isEnumEntry = proto.isEnumEntry, - isEnumSpecial = proto.isEnumSpecial, - isDefaultConstructor = proto.isDefaultConstructor, - isFakeOverride = proto.isFakeOverride, - isGetter = proto.isGetter, - isSetter = proto.isSetter - ) - - private val ByteArray.codedInputStream: org.jetbrains.kotlin.protobuf.CodedInputStream - get() { - val codedInputStream = org.jetbrains.kotlin.protobuf.CodedInputStream.newInstance(this) - codedInputStream.setRecursionLimit(65535) // The default 64 is blatantly not enough for IR. - return codedInputStream - } - - private val reversedFileIndex = mutableMapOf() - - private val UniqIdKey.moduleOfOrigin get() = - this.moduleDescriptor ?: reversedFileIndex[this]?.packageFragmentDescriptor?.containingDeclaration - - private fun deserializeTopLevelDeclaration(uniqIdKey: UniqIdKey): IrDeclaration { - val proto = loadTopLevelDeclarationProto(uniqIdKey) - return deserializeDeclaration(proto, reversedFileIndex[uniqIdKey]!!) - } - - private fun reader(moduleDescriptor: ModuleDescriptor, uniqId: UniqId) = moduleDescriptor.konanLibrary!!.irDeclaration(uniqId.index, uniqId.isLocal) - - private fun loadTopLevelDeclarationProto(uniqIdKey: UniqIdKey): KonanIr.IrDeclaration { - val stream = reader(uniqIdKey.moduleOfOrigin!!, uniqIdKey.uniqId).codedInputStream - return KonanIr.IrDeclaration.parseFrom(stream, KonanSerializerProtocol.extensionRegistry) - } - - private fun findDeserializedDeclarationForDescriptor(descriptor: DeclarationDescriptor): DeclarationDescriptor? { - val topLevelDescriptor = descriptor.findTopLevelDescriptor() - - if (topLevelDescriptor.module.isForwardDeclarationModule) return null - - if (topLevelDescriptor !is DeserializedClassDescriptor && topLevelDescriptor !is DeserializedCallableMemberDescriptor) { - return null - } - - val descriptorUniqId = topLevelDescriptor.getUniqId() - ?: error("could not get descriptor uniq id for $topLevelDescriptor") - val uniqId = UniqId(descriptorUniqId.index, isLocal = false) - val topLevelKey = UniqIdKey(topLevelDescriptor.module, uniqId) - - // This top level descriptor doesn't have a serialized IR declaration. - if (topLevelKey.moduleOfOrigin == null) return null - - reachableTopLevels.add(topLevelKey) - - do { - val key = reachableTopLevels.first() - - if (deserializedSymbols[key]?.isBound == true || - // The key.moduleOrigin is null for uniqIds that we haven't seen in any of the library headers. - // Just skip it for now and handle it elsewhere. - key.moduleOfOrigin == null) { - - reachableTopLevels.remove(key) - deserializedTopLevels.add(key) - continue - } - - deserializedModuleDescriptor = key.moduleOfOrigin - val reachable = deserializeTopLevelDeclaration(key) - val file = reversedFileIndex[key]!! - file.declarations.add(reachable) - reachable.patchDeclarationParents(file) - - reachableTopLevels.remove(key) - deserializedTopLevels.add(key) - } while (reachableTopLevels.isNotEmpty()) - - return topLevelDescriptor - } - - override fun findDeserializedDeclaration(symbol: IrSymbol): IrDeclaration? { - - if (!symbol.isBound) { - val topLevelDesecriptor = findDeserializedDeclarationForDescriptor(symbol.descriptor) - if (topLevelDesecriptor == null) return null - } - - assert(symbol.isBound) { - "findDeserializedDeclaration: symbol ${symbol} is unbound, descriptor = ${symbol.descriptor}, hash = ${symbol.descriptor.hashCode()}" - } - - return symbol.owner as IrDeclaration - } - - override fun findDeserializedDeclaration(propertyDescriptor: PropertyDescriptor): IrProperty? { - val topLevelDesecriptor = findDeserializedDeclarationForDescriptor(propertyDescriptor) - if (topLevelDesecriptor == null) return null - - return symbolTable.propertyTable[propertyDescriptor] - ?: error("findDeserializedDeclaration: property descriptor $propertyDescriptor} is not present in propertyTable after deserialization}") - } - - override fun declareForwardDeclarations() { - if (forwardModuleDescriptor == null) return - - val packageFragments = forwardDeclarations.map { it.descriptor.findPackage() }.distinct() - - // We don't bother making a real IR module here, as we have no need in it any later. - // All we need is just to declare forward declarations in the symbol table - // In case you need a full fledged module, turn the forEach into a map and collect - // produced files into an IrModuleFragment. - - packageFragments.forEach { packageFragment -> - val symbol = IrFileSymbolImpl(packageFragment) - val file = IrFileImpl(NaiveSourceBasedFileEntryImpl("forward declarations pseudo-file"), symbol) - val symbols = forwardDeclarations - .filter { !it.isBound } - .filter { it.descriptor.findPackage() == packageFragment } - val declarations = symbols.map { - - val classDescriptor = it.descriptor as ClassDescriptor - val declaration = symbolTable.declareClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irrelevantOrigin, - classDescriptor, - classDescriptor.modality - ) { symbol: IrClassSymbol -> IrClassImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irrelevantOrigin, symbol) } - .also { - it.parent = file - } - declaration - - } - file.declarations.addAll(declarations) - } - } - - fun deserializeIrFile(fileProto: KonanIr.IrFile, moduleDescriptor: ModuleDescriptor, deseralizationStrategy: DeserializationStrategy): IrFile { - val fileEntry = NaiveSourceBasedFileEntryImpl( - deserializeString(fileProto.fileEntry.name), - fileProto.fileEntry.lineStartOffsetsList.toIntArray() - ) - - // TODO: we need to store "" in protobuf, I suppose. Or better yet, reuse fqname storage from metadata. - val fqName = deserializeString(fileProto.fqName).let { if (it == "") FqName.ROOT else FqName(it) } - - val packageFragmentDescriptor = EmptyPackageFragmentDescriptor(moduleDescriptor, fqName) - - val symbol = IrFileSymbolImpl(packageFragmentDescriptor) - val file = IrFileImpl(fileEntry, symbol, fqName) - - fileProto.declarationIdList.forEach { - val uniqIdKey = it.uniqIdKey(moduleDescriptor) - reversedFileIndex.put(uniqIdKey, file) - - if (deseralizationStrategy == DeserializationStrategy.ALL) { - file.declarations.add(deserializeTopLevelDeclaration(uniqIdKey)) - } - } - - val annotations = deserializeAnnotations(fileProto.annotations) - file.annotations.addAll(annotations) - - - if (deseralizationStrategy == DeserializationStrategy.EXPLICITLY_EXPORTED) - fileProto.explicitlyExportedToCompilerList.forEach { deserializeIrSymbol(it) } - - return file - } - - fun deserializeIrModuleHeader(proto: KonanIr.IrModule, moduleDescriptor: ModuleDescriptor, deserializationStrategy: DeserializationStrategy): IrModuleFragment { - - deserializedModuleDescriptor = moduleDescriptor - deserializedModuleProtoSymbolTables.put(moduleDescriptor, proto.symbolTable) - deserializedModuleProtoStringTables.put(moduleDescriptor, proto.stringTable) - deserializedModuleProtoTypeTables.put(moduleDescriptor, proto.typeTable) - - val files = proto.fileList.map { - deserializeIrFile(it, moduleDescriptor, deserializationStrategy) - - } - val module = IrModuleFragmentImpl(moduleDescriptor, builtIns, files) - module.patchDeclarationParents(null) - return module - } - - fun deserializeIrModuleHeader(moduleDescriptor: ModuleDescriptor, byteArray: ByteArray, deserializationStrategy: DeserializationStrategy = DeserializationStrategy.ONLY_REFERENCED): IrModuleFragment { - val proto = KonanIr.IrModule.parseFrom(byteArray.codedInputStream, KonanSerializerProtocol.extensionRegistry) - return deserializeIrModuleHeader(proto, moduleDescriptor, deserializationStrategy) - } -} - -enum class DeserializationStrategy { - ONLY_REFERENCED, - ALL, - EXPLICITLY_EXPORTED -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleSerializer.kt new file mode 100644 index 00000000000..c6a768fedaa --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleSerializer.kt @@ -0,0 +1,24 @@ +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.common.LoggingContext +import org.jetbrains.kotlin.backend.common.serialization.IrModuleSerializer +import org.jetbrains.kotlin.backend.konan.RuntimeNames +import org.jetbrains.kotlin.backend.konan.llvm.KonanMangler +import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrFunction + +class KonanIrModuleSerializer( + logger: LoggingContext, + declarationTable: DeclarationTable, + bodiesOnlyForInlines: Boolean = false +) : IrModuleSerializer(logger, declarationTable, KonanMangler, bodiesOnlyForInlines) { + + override fun backendSpecificExplicitRoot(declaration: IrFunction) = + declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportForCppRuntime) || + declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation) + + override fun backendSpecificExplicitRoot(declaration: IrClass) = + declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportTypeInfoAnnotation) + +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt new file mode 100644 index 00000000000..4954850d111 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.common.LoggingContext +import org.jetbrains.kotlin.backend.common.serialization.DescriptorUniqIdAware +import org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker +import org.jetbrains.kotlin.backend.common.serialization.UniqId +import org.jetbrains.kotlin.backend.common.serialization.UniqIdKey +import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.util.SymbolTable + +class KonanIrLinker( + currentModule: ModuleDescriptor, + logger: LoggingContext, + builtIns: IrBuiltIns, + symbolTable: SymbolTable, + val forwardModuleDescriptor: ModuleDescriptor?) + : KotlinIrLinker(currentModule, logger, builtIns, symbolTable, forwardModuleDescriptor), + DescriptorUniqIdAware by KonanDescriptorUniqIdAware { + + private val forwardDeclarations = mutableSetOf() + + override val descriptorReferenceDeserializer = KonanDescriptorReferenceDeserializer(currentModule, resolvedForwardDeclarations) + + override fun reader(moduleDescriptor: ModuleDescriptor, uniqId: UniqId) = moduleDescriptor.konanLibrary!!.irDeclaration(uniqId.index, uniqId.isLocal) + + init { + var currentIndex = 0L + builtIns.knownBuiltins.forEach { + require(it is IrFunction) + deserializedSymbols.put(UniqIdKey(null, UniqId(currentIndex, isLocal = false)), it.symbol) + assert(symbolTable.referenceSimpleFunction(it.descriptor) == it.symbol) + currentIndex++ + } + } +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt index 10c9512cc9d..f41fc6062fd 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt @@ -5,15 +5,16 @@ package org.jetbrains.kotlin.backend.konan.serialization +import org.jetbrains.kotlin.backend.common.serialization.SerializedIr import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember import org.jetbrains.kotlin.backend.konan.descriptors.isSerializableExpectClass import org.jetbrains.kotlin.backend.konan.library.LinkData import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf -import org.jetbrains.kotlin.backend.konan.library.SerializedIr import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt index 34ec0cb4491..94ea1e51f1b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf @@ -20,7 +21,8 @@ import org.jetbrains.kotlin.serialization.konan.SourceFileMap import org.jetbrains.kotlin.types.KotlinType internal class KonanSerializerExtension(val context: Context, override val metadataVersion: BinaryVersion, - val sourceFileMap: SourceFileMap, val declarationTable: DeclarationTable) : + val sourceFileMap: SourceFileMap, val declarationTable: DeclarationTable +) : KotlinSerializerExtensionBase(KonanSerializerProtocol) { override val stringTable = KonanStringTable() @@ -28,7 +30,7 @@ internal class KonanSerializerExtension(val context: Context, override val metad fun uniqId(descriptor: DeclarationDescriptor): KonanProtoBuf.DescriptorUniqId? { val index = declarationTable.descriptorTable.get(descriptor) - return index?.let { newDescriptorUniqId(it) } + return index?.let { newKonanDescriptorUniqId(it) } } override fun serializeType(type: KotlinType, proto: ProtoBuf.Type.Builder) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeDescriptorReference.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeDescriptorReference.kt deleted file mode 100644 index 3e8a0e1ac0a..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeDescriptorReference.kt +++ /dev/null @@ -1,108 +0,0 @@ -package org.jetbrains.kotlin.backend.konan.serialization - -import org.jetbrains.kotlin.backend.konan.ir.isAccessor -import org.jetbrains.kotlin.backend.konan.ir.isGetter -import org.jetbrains.kotlin.backend.konan.ir.isSetter -import org.jetbrains.kotlin.backend.konan.llvm.isExported -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.metadata.KonanIr -import org.jetbrains.kotlin.resolve.descriptorUtil.classId - - -class DescriptorReferenceSerializer(val declarationTable: DeclarationTable, val serializeString: (String) -> KonanIr.String) { - - // Not all exported descriptors are deserialized, some a synthesized anew during metadata deserialization. - // Those created descriptors can't carry the uniqIdIndex, since it is available only for deserialized descriptors. - // So we record the uniq id of some other "discoverable" descriptor for which we know for sure that it will be - // available as deserialized descriptor, plus the path to find the needed descriptor from that one. - fun serializeDescriptorReference(declaration: IrDeclaration): KonanIr.DescriptorReference? { - - val descriptor = declaration.descriptor - - if (!declaration.isExported() && !((declaration as? IrDeclarationWithVisibility)?.visibility == Visibilities.INVISIBLE_FAKE)) { - return null - } - if (declaration is IrAnonymousInitializer) return null - - if (descriptor is ParameterDescriptor || (descriptor is VariableDescriptor && descriptor !is PropertyDescriptor) || descriptor is TypeParameterDescriptor) return null - - val containingDeclaration = descriptor.containingDeclaration!! - - val (packageFqName, classFqName) = when (containingDeclaration) { - is ClassDescriptor -> { - val classId = containingDeclaration.classId ?: return null - Pair(classId.packageFqName.toString(), classId.relativeClassName.toString()) - } - is PackageFragmentDescriptor -> Pair(containingDeclaration.fqName.toString(), "") - else -> return null - } - - val isAccessor = declaration.isAccessor - val isBackingField = declaration is IrField && declaration.correspondingProperty != null - val isFakeOverride = declaration.origin == IrDeclarationOrigin.FAKE_OVERRIDE - val isDefaultConstructor = - descriptor is ClassConstructorDescriptor && containingDeclaration is ClassDescriptor && containingDeclaration.kind == ClassKind.OBJECT - val isEnumEntry = descriptor is ClassDescriptor && descriptor.kind == ClassKind.ENUM_ENTRY - val isEnumSpecial = declaration.origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER - - - val realDeclaration = if (isFakeOverride) { - when (declaration) { - is IrSimpleFunction -> declaration.resolveFakeOverrideMaybeAbstract() - is IrField -> declaration.resolveFakeOverrideMaybeAbstract() - is IrProperty -> declaration.resolveFakeOverrideMaybeAbstract() - else -> error("Unexpected fake override declaration") - } - } else { - declaration - } - - val discoverableDescriptorsDeclaration: IrDeclaration? = if (isAccessor) { - (realDeclaration as IrSimpleFunction).correspondingProperty!! - } else if (isBackingField) { - (realDeclaration as IrField).correspondingProperty!! - } else if (isDefaultConstructor || isEnumEntry) { - null - } else { - realDeclaration - } - - val uniqId = discoverableDescriptorsDeclaration?.let { declarationTable.uniqIdByDeclaration(it) } - uniqId?.let { declarationTable.descriptors.put(discoverableDescriptorsDeclaration.descriptor, it) } - - val proto = KonanIr.DescriptorReference.newBuilder() - .setPackageFqName(serializeString(packageFqName)) - .setClassFqName(serializeString(classFqName)) - .setName(serializeString(descriptor.name.toString())) - - if (uniqId != null) proto.setUniqId(protoUniqId(uniqId)) - - if (isFakeOverride) { - proto.setIsFakeOverride(true) - } - - if (isBackingField) { - proto.setIsBackingField(true) - } - - if (isAccessor) { - if (declaration.isGetter) - proto.setIsGetter(true) - else if (declaration.isSetter) - proto.setIsSetter(true) - else - error("A property accessor which is neither a getter, nor a setter: $descriptor") - } else if (isDefaultConstructor) { - proto.setIsDefaultConstructor(true) - } else if (isEnumEntry) { - proto.setIsEnumEntry(true) - } else if (isEnumSpecial) { - proto.setIsEnumSpecial(true) - } - - return proto.build() - } -} - - diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/UniqId.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/UniqId.kt index d40ebd6411a..a23c209400b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/UniqId.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/UniqId.kt @@ -5,53 +5,22 @@ package org.jetbrains.kotlin.backend.konan.serialization -import org.jetbrains.kotlin.backend.konan.llvm.localHash +import org.jetbrains.kotlin.backend.common.serialization.DescriptorUniqIdAware +import org.jetbrains.kotlin.backend.common.serialization.tryGetExtension import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.serialization.deserialization.descriptors.* -import org.jetbrains.kotlin.metadata.KonanIr import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.protobuf.GeneratedMessageLite -// This is an abstract uniqIdIndex any serialized IR declarations gets. -// It is either isLocal and then just gets and ordinary number within its module. -// Or is visible across modules and then gets a hash of mangled name as its index. -data class UniqId ( - val index: Long, - val isLocal: Boolean -) - -// isLocal=true in UniqId is good while we dealing with a single current module. -// To disambiguate module local declarations of different modules we use UniqIdKey. -// It has moduleDescriptor specified for isLocal=true uniqIds. -data class UniqIdKey private constructor(val uniqId: UniqId, val moduleDescriptor: ModuleDescriptor?) { - constructor(moduleDescriptor: ModuleDescriptor?, uniqId: UniqId) - : this(uniqId, if (uniqId.isLocal) moduleDescriptor!! else null) +object KonanDescriptorUniqIdAware: DescriptorUniqIdAware { + override fun DeclarationDescriptor.getUniqId(): Long? = when (this) { + is DeserializedClassDescriptor -> this.classProto.tryGetExtension(KonanProtoBuf.classUniqId) + is DeserializedSimpleFunctionDescriptor -> this.proto.tryGetExtension(KonanProtoBuf.functionUniqId) + is DeserializedPropertyDescriptor -> this.proto.tryGetExtension(KonanProtoBuf.propertyUniqId) + is DeserializedClassConstructorDescriptor -> this.proto.tryGetExtension(KonanProtoBuf.constructorUniqId) + else -> null + }?.index } -internal val IrDeclaration.uniqIdIndex: Long - get() = this.uniqSymbolName().localHash.value - -fun protoUniqId(uniqId: UniqId): KonanIr.UniqId = - KonanIr.UniqId.newBuilder() - .setIndex(uniqId.index) - .setIsLocal(uniqId.isLocal) - .build() - -fun KonanIr.UniqId.uniqId(): UniqId = UniqId(this.index, this.isLocal) -fun KonanIr.UniqId.uniqIdKey(moduleDescriptor: ModuleDescriptor) = - UniqIdKey(moduleDescriptor, this.uniqId()) - -fun > M.tryGetExtension(extension: GeneratedMessageLite.GeneratedExtension) - = if (this.hasExtension(extension)) this.getExtension(extension) else null - -fun DeclarationDescriptor.getUniqId(): KonanProtoBuf.DescriptorUniqId? = when (this) { - is DeserializedClassDescriptor -> this.classProto.tryGetExtension(KonanProtoBuf.classUniqId) - is DeserializedSimpleFunctionDescriptor -> this.proto.tryGetExtension(KonanProtoBuf.functionUniqId) - is DeserializedPropertyDescriptor -> this.proto.tryGetExtension(KonanProtoBuf.propertyUniqId) - is DeserializedClassConstructorDescriptor -> this.proto.tryGetExtension(KonanProtoBuf.constructorUniqId) - else -> null -} - -fun newDescriptorUniqId(index: Long): KonanProtoBuf.DescriptorUniqId = +fun newKonanDescriptorUniqId(index: Long): KonanProtoBuf.DescriptorUniqId = KonanProtoBuf.DescriptorUniqId.newBuilder().setIndex(index).build() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/UniqSymbolName.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/UniqSymbolName.kt deleted file mode 100644 index 934ab6333d2..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/UniqSymbolName.kt +++ /dev/null @@ -1,72 +0,0 @@ -package org.jetbrains.kotlin.backend.konan.serialization - -import org.jetbrains.kotlin.backend.konan.ir.fqNameSafe -import org.jetbrains.kotlin.backend.konan.ir.name -import org.jetbrains.kotlin.backend.konan.llvm.extensionReceiverNamePart -import org.jetbrains.kotlin.backend.konan.llvm.functionName -import org.jetbrains.kotlin.backend.konan.llvm.symbolName -import org.jetbrains.kotlin.backend.konan.llvm.typeInfoSymbolName -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name - -// This is a little extension over what's used in real mangling -// since some declarations never appear in the bitcode symbols. - -internal fun IrDeclaration.uniqSymbolName(): String = when (this) { - is IrFunction - -> this.uniqFunctionName - is IrProperty - -> this.symbolName - is IrClass - -> this.typeInfoSymbolName - is IrField - -> this.symbolName - is IrEnumEntry - -> this.symbolName - else -> error("Unexpected exported declaration: $this") -} - -private val IrDeclarationParent.fqNameUnique: FqName - get() = when(this) { - is IrPackageFragment -> this.fqName - is IrDeclaration -> this.parent.fqNameUnique.child(this.uniqName) - else -> error(this) - } - -private val IrDeclaration.uniqName: Name - get() = when (this) { - is IrSimpleFunction -> Name.special("<${this.uniqFunctionName}>") - else -> this.name - } - -private val IrProperty.symbolName: String - get() { - val extensionReceiver: String = getter!!.extensionReceiverParameter ?. extensionReceiverNamePart ?: "" - - val containingDeclarationPart = parent.fqNameSafe.let { - if (it.isRoot) "" else "$it." - } - return "kprop:$containingDeclarationPart$extensionReceiver$name" - } - -private val IrEnumEntry.symbolName: String - get() { - val containingDeclarationPart = parent.fqNameSafe.let { - if (it.isRoot) "" else "$it." - } - return "kenumentry:$containingDeclarationPart$name" - } - -// This is basicly the same as .symbolName, but disambiguates external functions with the same C name. -// In addition functions appearing in fq sequence appear as . -private val IrFunction.uniqFunctionName: String - get() { - val parent = this.parent - - val containingDeclarationPart = parent.fqNameUnique.let { - if (it.isRoot) "" else "$it." - } - - return "kfun:$containingDeclarationPart#$functionName" - }