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.LazyThreadSafetyMode.PUBLICATION
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
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.objcexport.ObjCExport
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
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 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 enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) }
|
||||||
private val outerThisFields = mutableMapOf<ClassDescriptor, IrField>()
|
private val outerThisFields = mutableMapOf<ClassDescriptor, IrField>()
|
||||||
private val bridgesDescriptors = mutableMapOf<Pair<IrSimpleFunction, BridgeDirections>, IrSimpleFunction>()
|
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.LoggingContext
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
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.isForwardDeclarationModule
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
|
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
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.cli.common.messages.AnalyzerWithCompilerReport
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
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.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||||
@@ -67,7 +69,7 @@ internal val psiToIrPhase = konanUnitPhase(
|
|||||||
|
|
||||||
val forwardDeclarationsModuleDescriptor = moduleDescriptor.allDependencyModules.firstOrNull { it.isForwardDeclarationModule }
|
val forwardDeclarationsModuleDescriptor = moduleDescriptor.allDependencyModules.firstOrNull { it.isForwardDeclarationModule }
|
||||||
|
|
||||||
val deserializer = KonanIrModuleDeserializer(
|
val deserializer = KonanIrLinker(
|
||||||
moduleDescriptor,
|
moduleDescriptor,
|
||||||
this as LoggingContext,
|
this as LoggingContext,
|
||||||
generatorContext.irBuiltIns,
|
generatorContext.irBuiltIns,
|
||||||
@@ -144,8 +146,8 @@ internal val patchDeclarationParents0Phase = konanUnitPhase(
|
|||||||
|
|
||||||
internal val serializerPhase = konanUnitPhase(
|
internal val serializerPhase = konanUnitPhase(
|
||||||
op = {
|
op = {
|
||||||
val declarationTable = DeclarationTable(irModule!!.irBuiltins, DescriptorTable())
|
val declarationTable = KonanDeclarationTable(irModule!!.irBuiltins, DescriptorTable()).apply { loadKnownBuiltins() }
|
||||||
val serializedIr = IrModuleSerializer(this, declarationTable).serializedIrModule(irModule!!)
|
val serializedIr = KonanIrModuleSerializer(this, declarationTable).serializedIrModule(irModule!!)
|
||||||
val serializer = KonanSerializationUtil(this, config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!, declarationTable)
|
val serializer = KonanSerializationUtil(this, config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!, declarationTable)
|
||||||
serializedLinkData =
|
serializedLinkData =
|
||||||
serializer.serializeModule(moduleDescriptor, /*if (!config.isInteropStubs) serializedIr else null*/ serializedIr)
|
serializer.serializeModule(moduleDescriptor, /*if (!config.isInteropStubs) serializedIr else null*/ serializedIr)
|
||||||
|
|||||||
+1
-7
@@ -6,7 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.library
|
package org.jetbrains.kotlin.backend.konan.library
|
||||||
|
|
||||||
import llvm.LLVMModuleRef
|
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.KonanLibrary
|
||||||
import org.jetbrains.kotlin.konan.library.KonanLibraryVersioning
|
import org.jetbrains.kotlin.konan.library.KonanLibraryVersioning
|
||||||
import org.jetbrains.kotlin.konan.properties.Properties
|
import org.jetbrains.kotlin.konan.properties.Properties
|
||||||
@@ -31,12 +31,6 @@ class LinkData(
|
|||||||
val ir: SerializedIr? = null
|
val ir: SerializedIr? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
class SerializedIr (
|
|
||||||
val module: ByteArray,
|
|
||||||
val combinedDeclarationFilePath: String,
|
|
||||||
val debugIndex: Map<UniqId, String>
|
|
||||||
)
|
|
||||||
|
|
||||||
interface MetadataWriter {
|
interface MetadataWriter {
|
||||||
fun addLinkData(linkData: LinkData)
|
fun addLinkData(linkData: LinkData)
|
||||||
}
|
}
|
||||||
|
|||||||
-2
@@ -30,7 +30,5 @@ internal class MetadataWriterImpl(libraryLayout: KonanLibraryLayout): KonanLibra
|
|||||||
// TODO: use Files.move.
|
// TODO: use Files.move.
|
||||||
File(it).copyTo(irFile)
|
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
|
package org.jetbrains.kotlin.backend.konan.llvm
|
||||||
|
|
||||||
import llvm.LLVMTypeRef
|
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.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.externalSymbolOrThrow
|
import org.jetbrains.kotlin.backend.konan.descriptors.externalSymbolOrThrow
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationValue
|
import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationValue
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
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.konan.library.KonanLibrary
|
||||||
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
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: revise the naming scheme to ensure it produces unique names.
|
||||||
// TODO: do not serialize descriptors of non-exported declarations.
|
// TODO: do not serialize descriptors of non-exported declarations.
|
||||||
|
|
||||||
/**
|
object KonanMangler : KotlinManglerImpl() {
|
||||||
* 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
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isAnonymousObject)
|
override val String.hashMangle get() = this.localHash.value
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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) {
|
override fun IrDeclaration.isPlatformSpecificExported(): Boolean {
|
||||||
// If the declaration is explicitly marked as non-public,
|
// TODO: revise
|
||||||
// then it must not be accessible from other modules.
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val parent = this.parent
|
private val symbolNameAnnotation = RuntimeNames.symbolName
|
||||||
if (parent is IrDeclaration) {
|
|
||||||
return parent.isExported()
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
override val IrFunction.argsPart get() = this.valueParameters.map {
|
||||||
|
|
||||||
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 {
|
|
||||||
|
|
||||||
// TODO: there are clashes originating from ObjectiveC interop.
|
// 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
|
// kotlinx.cinterop.ObjCClassOf<T>.create(format: kotlin.String): T defined in platform.Foundation in file Foundation.kt
|
||||||
// and
|
// and
|
||||||
// kotlinx.cinterop.ObjCClassOf<T>.create(string: kotlin.String): T defined in platform.Foundation in file Foundation.kt
|
// 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 ""
|
val argName =
|
||||||
"$argName${typeToHashString(it.type)}${if (it.isVararg) "_VarArg" else ""}"
|
if (this.hasObjCMethodAnnotation || this.hasObjCFactoryAnnotation || this.isObjCClassMethod()) "${it.name}:" else ""
|
||||||
}.joinToString(";")
|
"$argName${typeToHashString(it.type)}${if (it.isVararg) "_VarArg" else ""}"
|
||||||
// Distinguish value types and references - it's needed for calling virtual methods through bridges.
|
}.joinToString(";")
|
||||||
// Also is function has type arguments - frontend allows exactly matching overrides.
|
|
||||||
val signatureSuffix =
|
|
||||||
when {
|
override val IrFunction.platformSpecificFunctionName: String?
|
||||||
this.typeParameters.isNotEmpty() -> "Generic"
|
get() {
|
||||||
returnType.isInlined() -> "ValueType"
|
(if (this is IrConstructor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo()
|
||||||
!returnType.isUnitOrNullableUnit() -> typeToHashString(returnType)
|
?.let {
|
||||||
else -> ""
|
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.symbolName: String
|
||||||
internal val IrFunction.functionName: String
|
get() {
|
||||||
get() {
|
if (!this.isExported()) {
|
||||||
(if (this is IrConstructor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo()?.let {
|
throw AssertionError(this.descriptor.toString())
|
||||||
return buildString {
|
}
|
||||||
if (extensionReceiverParameter != null) {
|
|
||||||
append(extensionReceiverParameter!!.type.getClass()!!.name)
|
|
||||||
append(".")
|
|
||||||
}
|
|
||||||
|
|
||||||
append("objc:")
|
if (isExternal) {
|
||||||
append(it.selector)
|
this.descriptor.externalSymbolOrThrow()?.let {
|
||||||
if (this@functionName is IrConstructor && this@functionName.isObjCConstructor) append("#Constructor")
|
return it
|
||||||
|
|
||||||
// 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") }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val name = this.name.mangleIfInternal(this.module, this.visibility)
|
this.descriptor.annotations.findAnnotation(exportForCppRuntimeAnnotation)?.let {
|
||||||
|
val name = getAnnotationValue(it) ?: this.name.asString()
|
||||||
return "$name$signature"
|
return name // no wrapping currently required
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
internal val IrClass.writableTypeInfoSymbolName: String
|
||||||
get() {
|
get() {
|
||||||
assert (this.isExported())
|
assert (this.isExported())
|
||||||
@@ -311,6 +172,39 @@ internal val IrClass.objectInstanceShadowFieldSymbolName: String
|
|||||||
return "kshadowobjref:$fqNameSafe"
|
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
|
internal val IrClass.typeInfoHasVtableAttached: Boolean
|
||||||
get() = !this.isAbstract() && !this.isExternalObjCClass()
|
get() = !this.isAbstract() && !this.isExternalObjCClass()
|
||||||
|
|
||||||
|
|||||||
+1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.KotlinMangler
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.objc.*
|
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
|
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.descriptors.*
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
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.
|
// tree of deserialized descriptors. Think of it as base + offset.
|
||||||
// packageFqName + classFqName + index allow to localize some deserialized descriptor.
|
// 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.
|
// 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> {
|
// TODO: these are dummies. Eliminate them.
|
||||||
val packageFqName = packageFqNameString.let {
|
override fun resolveSpecialDescriptor(fqn: FqName): DeclarationDescriptor = currentModule
|
||||||
if (it == "<root>") FqName.ROOT else FqName(it)
|
override fun checkIfSpecialDescriptorId(id: Long): Boolean = false
|
||||||
}// TODO: whould we store an empty string in the protobuf?
|
override fun getDescriptorIdOrNull(descriptor: DeclarationDescriptor): Long? = null
|
||||||
|
|
||||||
val memberScope = currentModule.getPackage(packageFqName).memberScope
|
// Most of this function duplicates the parent, but it deals with forward declarations.
|
||||||
return getContributedDescriptors(memberScope, name)
|
// TODO: Refactor me.
|
||||||
}
|
override fun deserializeDescriptorReference(
|
||||||
|
|
||||||
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(
|
|
||||||
packageFqNameString: String,
|
packageFqNameString: String,
|
||||||
classFqNameString: String,
|
classFqNameString: String,
|
||||||
name: String,
|
name: String,
|
||||||
index: Long?,
|
index: Long?,
|
||||||
isEnumEntry: Boolean = false,
|
isEnumEntry: Boolean,
|
||||||
isEnumSpecial: Boolean = false,
|
isEnumSpecial: Boolean,
|
||||||
isDefaultConstructor: Boolean = false,
|
isDefaultConstructor: Boolean,
|
||||||
isFakeOverride: Boolean = false,
|
isFakeOverride: Boolean,
|
||||||
isGetter: Boolean = false,
|
isGetter: Boolean,
|
||||||
isSetter: Boolean = false
|
isSetter: Boolean
|
||||||
): DeclarationDescriptor {
|
): DeclarationDescriptor {
|
||||||
val packageFqName = packageFqNameString.let {
|
val packageFqName = packageFqNameString.let {
|
||||||
if (it == "<root>") FqName.ROOT else FqName(it)
|
if (it == "<root>") FqName.ROOT else FqName(it)
|
||||||
@@ -93,7 +64,7 @@ class DescriptorReferenceDeserializer(val currentModule: ModuleDescriptor, val r
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (descriptor is DeserializedClassDescriptor) {
|
if (descriptor is DeserializedClassDescriptor) {
|
||||||
val uniqId = UniqId(descriptor.getUniqId()!!.index, false)
|
val uniqId = UniqId(descriptor.getUniqId()!!, false)
|
||||||
val newKey = UniqIdKey(null, uniqId)
|
val newKey = UniqIdKey(null, uniqId)
|
||||||
val oldKey = UniqIdKey(null, UniqId(protoIndex!!, false))
|
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}")
|
} ?: 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
|
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.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember
|
import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isSerializableExpectClass
|
import org.jetbrains.kotlin.backend.konan.descriptors.isSerializableExpectClass
|
||||||
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||||
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
|
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.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
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.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
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.deserialization.BinaryVersion
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
|
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
|
||||||
@@ -20,7 +21,8 @@ import org.jetbrains.kotlin.serialization.konan.SourceFileMap
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
internal class KonanSerializerExtension(val context: Context, override val metadataVersion: BinaryVersion,
|
internal class KonanSerializerExtension(val context: Context, override val metadataVersion: BinaryVersion,
|
||||||
val sourceFileMap: SourceFileMap, val declarationTable: DeclarationTable) :
|
val sourceFileMap: SourceFileMap, val declarationTable: DeclarationTable
|
||||||
|
) :
|
||||||
KotlinSerializerExtensionBase(KonanSerializerProtocol) {
|
KotlinSerializerExtensionBase(KonanSerializerProtocol) {
|
||||||
|
|
||||||
override val stringTable = KonanStringTable()
|
override val stringTable = KonanStringTable()
|
||||||
@@ -28,7 +30,7 @@ internal class KonanSerializerExtension(val context: Context, override val metad
|
|||||||
|
|
||||||
fun uniqId(descriptor: DeclarationDescriptor): KonanProtoBuf.DescriptorUniqId? {
|
fun uniqId(descriptor: DeclarationDescriptor): KonanProtoBuf.DescriptorUniqId? {
|
||||||
val index = declarationTable.descriptorTable.get(descriptor)
|
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) {
|
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
|
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.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
|
||||||
import org.jetbrains.kotlin.metadata.KonanIr
|
|
||||||
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
|
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
|
||||||
import org.jetbrains.kotlin.protobuf.GeneratedMessageLite
|
import org.jetbrains.kotlin.protobuf.GeneratedMessageLite
|
||||||
|
|
||||||
// This is an abstract uniqIdIndex any serialized IR declarations gets.
|
object KonanDescriptorUniqIdAware: DescriptorUniqIdAware {
|
||||||
// It is either isLocal and then just gets and ordinary number within its module.
|
override fun DeclarationDescriptor.getUniqId(): Long? = when (this) {
|
||||||
// Or is visible across modules and then gets a hash of mangled name as its index.
|
is DeserializedClassDescriptor -> this.classProto.tryGetExtension(KonanProtoBuf.classUniqId)
|
||||||
data class UniqId (
|
is DeserializedSimpleFunctionDescriptor -> this.proto.tryGetExtension(KonanProtoBuf.functionUniqId)
|
||||||
val index: Long,
|
is DeserializedPropertyDescriptor -> this.proto.tryGetExtension(KonanProtoBuf.propertyUniqId)
|
||||||
val isLocal: Boolean
|
is DeserializedClassConstructorDescriptor -> this.proto.tryGetExtension(KonanProtoBuf.constructorUniqId)
|
||||||
)
|
else -> null
|
||||||
|
}?.index
|
||||||
// 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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val IrDeclaration.uniqIdIndex: Long
|
fun newKonanDescriptorUniqId(index: Long): KonanProtoBuf.DescriptorUniqId =
|
||||||
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 =
|
|
||||||
KonanProtoBuf.DescriptorUniqId.newBuilder().setIndex(index).build()
|
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