Commonized native and js IR serialization infrastructure.
This commit is contained in:
committed by
alexander-gorshenev
parent
46879b94cc
commit
d9ff5a9778
+2
-1
@@ -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<ClassDescriptor, IrField>()
|
||||
private val bridgesDescriptors = mutableMapOf<Pair<IrSimpleFunction, BridgeDirections>, IrSimpleFunction>()
|
||||
|
||||
+5
-3
@@ -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)
|
||||
|
||||
+1
-7
@@ -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<UniqId, String>
|
||||
)
|
||||
|
||||
interface MetadataWriter {
|
||||
fun addLinkData(linkData: LinkData)
|
||||
}
|
||||
|
||||
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+121
-227
@@ -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<IrTypeParameter>, 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<IrTypeParameter>(), 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<T>.create(format: kotlin.String): T defined in platform.Foundation in file Foundation.kt
|
||||
// and
|
||||
// kotlinx.cinterop.ObjCClassOf<T>.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()
|
||||
|
||||
|
||||
+1
@@ -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.*
|
||||
|
||||
-56
@@ -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<DeclarationDescriptor, Long>()
|
||||
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<IrDeclaration, UniqId>()
|
||||
val debugIndex = mutableMapOf<UniqId, String>()
|
||||
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
|
||||
-1113
File diff suppressed because it is too large
Load Diff
-1141
File diff suppressed because it is too large
Load Diff
+18
@@ -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
|
||||
+24
-53
@@ -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<UniqIdKey, UniqIdKey>) {
|
||||
class KonanDescriptorReferenceDeserializer(
|
||||
currentModule: ModuleDescriptor,
|
||||
resolvedForwardDeclarations: MutableMap<UniqIdKey, UniqIdKey>)
|
||||
: DescriptorReferenceDeserializer(currentModule, resolvedForwardDeclarations),
|
||||
DescriptorUniqIdAware by KonanDescriptorUniqIdAware{
|
||||
|
||||
private fun getContributedDescriptors(packageFqNameString: String, name: String): Collection<DeclarationDescriptor> {
|
||||
val packageFqName = packageFqNameString.let {
|
||||
if (it == "<root>") 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<DeclarationDescriptor> {
|
||||
val contributedNameString = if (name.startsWith("<get-") || name.startsWith("<set-")) {
|
||||
name.substring(5, name.length - 1) // FIXME: rework serialization format.
|
||||
} else {
|
||||
name
|
||||
}
|
||||
val contributedName = Name.identifier(contributedNameString)
|
||||
return memberScope.getContributedFunctions(contributedName, NoLookupLocation.FROM_BACKEND) +
|
||||
memberScope.getContributedVariables(contributedName, NoLookupLocation.FROM_BACKEND) +
|
||||
listOfNotNull(memberScope.getContributedClassifier(contributedName, NoLookupLocation.FROM_BACKEND))
|
||||
}
|
||||
|
||||
private class ClassMembers(val defaultConstructor: ClassConstructorDescriptor?,
|
||||
val members: Map<Long, DeclarationDescriptor>,
|
||||
val realMembers: Map<Long, DeclarationDescriptor>)
|
||||
|
||||
private fun getMembers(members: Collection<DeclarationDescriptor>): ClassMembers {
|
||||
val allMembersMap = mutableMapOf<Long, DeclarationDescriptor>()
|
||||
val realMembersMap = mutableMapOf<Long, DeclarationDescriptor>()
|
||||
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 == "<root>") 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}")
|
||||
}
|
||||
}
|
||||
}
|
||||
-660
@@ -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;
|
||||
}
|
||||
}
|
||||
-378
@@ -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<UniqIdKey, IrSymbol>()
|
||||
val reachableTopLevels = mutableSetOf<UniqIdKey>()
|
||||
val deserializedTopLevels = mutableSetOf<UniqIdKey>()
|
||||
val forwardDeclarations = mutableSetOf<IrSymbol>()
|
||||
|
||||
var deserializedModuleDescriptor: ModuleDescriptor? = null
|
||||
var deserializedModuleProtoSymbolTables = mutableMapOf<ModuleDescriptor, KonanIr.IrSymbolTable>()
|
||||
var deserializedModuleProtoStringTables = mutableMapOf<ModuleDescriptor, KonanIr.StringTable>()
|
||||
var deserializedModuleProtoTypeTables = mutableMapOf<ModuleDescriptor, KonanIr.IrTypeTable>()
|
||||
var deserializedModuleLoops = mutableMapOf<Pair<ModuleDescriptor, Int>, IrLoopBase>()
|
||||
|
||||
val resolvedForwardDeclarations = mutableMapOf<UniqIdKey, UniqIdKey>()
|
||||
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<UniqIdKey, IrFile>()
|
||||
|
||||
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 == "<root>") 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
|
||||
}
|
||||
+24
@@ -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)
|
||||
|
||||
}
|
||||
+55
@@ -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<IrSymbol>()
|
||||
|
||||
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++
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -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
|
||||
|
||||
+4
-2
@@ -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) {
|
||||
|
||||
-108
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-42
@@ -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 <T, M:GeneratedMessageLite.ExtendableMessage<M>> M.tryGetExtension(extension: GeneratedMessageLite.GeneratedExtension<M, T>)
|
||||
= if (this.hasExtension(extension)) this.getExtension<T>(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()
|
||||
|
||||
-72
@@ -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 <full signature>.
|
||||
private val IrFunction.uniqFunctionName: String
|
||||
get() {
|
||||
val parent = this.parent
|
||||
|
||||
val containingDeclarationPart = parent.fqNameUnique.let {
|
||||
if (it.isRoot) "" else "$it."
|
||||
}
|
||||
|
||||
return "kfun:$containingDeclarationPart#$functionName"
|
||||
}
|
||||
Reference in New Issue
Block a user