[KLIB] Make K/N work with new linker

(cherry picked from commit 19a301ee517ad89e82e4b65347a6ff112042e781)
This commit is contained in:
Roman Artemev
2020-03-20 18:13:21 +03:00
committed by Vasily Levchenko
parent 9021273001
commit 98ad71fc11
7 changed files with 404 additions and 315 deletions
@@ -12,16 +12,24 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions
internal object DECLARATION_ORIGIN_FUNCTION_CLASS : IrDeclarationOriginImpl("DECLARATION_ORIGIN_FUNCTION_CLASS")
@@ -30,10 +38,12 @@ internal class BuiltInFictitiousFunctionIrClassFactory(
var symbolTable: SymbolTable?,
private val irBuiltIns: IrBuiltIns,
private val reflectionTypes: KonanReflectionTypes
) : IrProvider {
) : IrAbstractFunctionFactory(), IrProvider {
override fun getDeclaration(symbol: IrSymbol) =
(symbol.descriptor as? FunctionClassDescriptor)?.let { buildClass(it) }
(symbol.descriptor as? FunctionClassDescriptor)?.let { descriptor ->
buildClass(descriptor) { declareClass(offset, offset, DECLARATION_ORIGIN_FUNCTION_CLASS, descriptor) }
}
var module: IrModuleFragment? = null
set(value) {
@@ -43,7 +53,7 @@ internal class BuiltInFictitiousFunctionIrClassFactory(
error("Module has already been set")
field = value
value.files += filesMap.values
builtClasses.forEach { it.addFakeOverrides() }
// builtClasses.forEach { it.addFakeOverrides() }
}
class FunctionalInterface(val irClass: IrClass, val arity: Int)
@@ -51,17 +61,36 @@ internal class BuiltInFictitiousFunctionIrClassFactory(
fun buildAllClasses() {
val maxArity = 255 // See [BuiltInFictitiousFunctionClassFactory].
(0 .. maxArity).forEach { arity ->
function(arity)
kFunction(arity)
suspendFunction(arity)
kSuspendFunction(arity)
functionN(arity)
kFunctionN(arity)
suspendFunctionN(arity)
kSuspendFunctionN(arity)
}
}
fun function(n: Int) = buildClass(irBuiltIns.builtIns.getFunction(n) as FunctionClassDescriptor)
fun kFunction(n: Int) = buildClass(reflectionTypes.getKFunction(n) as FunctionClassDescriptor)
fun suspendFunction(n: Int) = buildClass(irBuiltIns.builtIns.getSuspendFunction(n) as FunctionClassDescriptor)
fun kSuspendFunction(n: Int) = buildClass(reflectionTypes.getKSuspendFunction(n) as FunctionClassDescriptor)
override fun functionClassDescriptor(arity: Int): FunctionClassDescriptor =
irBuiltIns.builtIns.getFunction(arity) as FunctionClassDescriptor
override fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor =
reflectionTypes.getKFunction(arity) as FunctionClassDescriptor
override fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor =
irBuiltIns.builtIns.getSuspendFunction(arity) as FunctionClassDescriptor
override fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor =
reflectionTypes.getKSuspendFunction(arity) as FunctionClassDescriptor
override fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass =
buildClass(irBuiltIns.builtIns.getFunction(arity) as FunctionClassDescriptor, declarator)
override fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass =
buildClass(reflectionTypes.getKFunction(arity) as FunctionClassDescriptor, declarator)
override fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass =
buildClass(irBuiltIns.builtIns.getSuspendFunction(arity) as FunctionClassDescriptor, declarator)
override fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass =
buildClass(reflectionTypes.getKSuspendFunction(arity) as FunctionClassDescriptor, declarator)
private val functionSymbol = symbolTable!!.referenceClass(
irBuiltIns.builtIns.builtInsModule.findClassAcrossModuleDependencies(
@@ -112,19 +141,16 @@ internal class BuiltInFictitiousFunctionIrClassFactory(
returnType
)
private fun createClass(descriptor: FunctionClassDescriptor) =
symbolTable?.declareClass(
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, DECLARATION_ORIGIN_FUNCTION_CLASS,
descriptor
)
?: IrClassImpl(
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, DECLARATION_ORIGIN_FUNCTION_CLASS,
IrClassSymbolImpl(descriptor)
)
private val createClassLambda =
{ s: IrClassSymbol -> IrClassImpl(offset, offset, DECLARATION_ORIGIN_FUNCTION_CLASS, s) }
private fun buildClass(descriptor: FunctionClassDescriptor): IrClass =
private fun createClass(descriptor: FunctionClassDescriptor, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
return symbolTable?.declarator(createClassLambda) ?: createClassLambda(IrClassSymbolImpl(descriptor))
}
private fun buildClass(descriptor: FunctionClassDescriptor, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass =
builtClassesMap.getOrPut(descriptor) {
createClass(descriptor).apply {
createClass(descriptor, declarator).apply {
val functionClass = this
typeParameters += descriptor.declaredTypeParameters.map { typeParameterDescriptor ->
createTypeParameter(typeParameterDescriptor).also {
@@ -142,7 +168,9 @@ internal class BuiltInFictitiousFunctionIrClassFactory(
makeTypeProjection(argumentClassifierSymbol.defaultType, argument.projectionKind)
}
val superTypeSymbol = when (val superTypeDescriptor = superType.constructor.declarationDescriptor) {
is FunctionClassDescriptor -> buildClass(superTypeDescriptor).symbol
is FunctionClassDescriptor -> buildClass(superTypeDescriptor) {
declareClass(offset, offset, DECLARATION_ORIGIN_FUNCTION_CLASS, superTypeDescriptor)
}.symbol
functionSymbol.descriptor -> functionSymbol
kFunctionSymbol.descriptor -> kFunctionSymbol
else -> error("Unexpected super type: $superTypeDescriptor")
@@ -155,40 +183,42 @@ internal class BuiltInFictitiousFunctionIrClassFactory(
val invokeFunctionDescriptor = descriptor.unsubstitutedMemberScope.getContributedFunctions(
OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).single()
val isFakeOverride = invokeFunctionDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE
val invokeFunctionOrigin =
if (isFakeOverride)
IrDeclarationOrigin.FAKE_OVERRIDE
else
DECLARATION_ORIGIN_FUNCTION_CLASS
declarations += createSimpleFunction(
invokeFunctionDescriptor, invokeFunctionOrigin,
typeParameters.last().defaultType
).apply {
parent = functionClass
valueParameters += invokeFunctionDescriptor.valueParameters.map {
IrValueParameterImpl(
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
invokeFunctionOrigin,
it,
functionClass.typeParameters[it.index].defaultType,
null
).also { it.parent = this }
}
if (!isFakeOverride)
createDispatchReceiverParameter(invokeFunctionOrigin)
else {
val overriddenFunction = superTypes
.mapNotNull { it.classOrNull?.owner }
.single { it.descriptor is FunctionClassDescriptor }
.simpleFunctions()
.single { it.name == OperatorNameConventions.INVOKE }
overriddenSymbols += overriddenFunction.symbol
dispatchReceiverParameter = overriddenFunction.dispatchReceiverParameter?.copyTo(this)
if (!isFakeOverride) {
val invokeFunctionOrigin =
if (isFakeOverride)
IrDeclarationOrigin.FAKE_OVERRIDE
else
DECLARATION_ORIGIN_FUNCTION_CLASS
declarations += createSimpleFunction(
invokeFunctionDescriptor, invokeFunctionOrigin,
typeParameters.last().defaultType
).apply {
parent = functionClass
valueParameters += invokeFunctionDescriptor.valueParameters.map {
IrValueParameterImpl(
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
invokeFunctionOrigin,
it,
functionClass.typeParameters[it.index].defaultType,
null
).also { it.parent = this }
}
if (!isFakeOverride)
createDispatchReceiverParameter(invokeFunctionOrigin)
else {
val overriddenFunction = superTypes
.mapNotNull { it.classOrNull?.owner }
.single { it.descriptor is FunctionClassDescriptor }
.simpleFunctions()
.single { it.name == OperatorNameConventions.INVOKE }
overriddenSymbols += overriddenFunction.symbol
dispatchReceiverParameter = overriddenFunction.dispatchReceiverParameter?.copyTo(this)
}
}
}
// Unfortunately, addFakeOverrides() uses some parents but they are only set after PsiToIr phase.
// So we add all the fake overrides only when we're supplied with the module (this is done after PsiToIr).
if (this@BuiltInFictitiousFunctionIrClassFactory.module != null)
// if (this@BuiltInFictitiousFunctionIrClassFactory.module != null)
addFakeOverrides()
val packageFragmentDescriptor = descriptor.findPackage()
@@ -201,4 +231,89 @@ internal class BuiltInFictitiousFunctionIrClassFactory(
file.declarations += this
}
}
private fun toIrType(wrapped: KotlinType): IrType {
val kotlinType = wrapped.unwrap()
return with(IrSimpleTypeBuilder()) {
classifier =
symbolTable?.referenceClassifier(kotlinType.constructor.declarationDescriptor ?: error("No classifier for type $kotlinType"))
hasQuestionMark = kotlinType.isMarkedNullable
arguments = kotlinType.arguments.map {
if (it.isStarProjection) IrStarProjectionImpl
else makeTypeProjection(toIrType(it.type), it.projectionKind)
}
buildSimpleType()
}
}
private fun IrFunction.createValueParameter(descriptor: ParameterDescriptor): IrValueParameter {
val symbol = IrValueParameterSymbolImpl(descriptor)
val varargType = if (descriptor is ValueParameterDescriptor) descriptor.varargElementType else null
return IrValueParameterImpl(
offset,
offset,
memberOrigin,
symbol,
toIrType(descriptor.type),
varargType?.let { toIrType(it) }).also {
it.parent = this
}
}
private fun IrClass.addFakeOverrides() {
val fakeOverrideDescriptors = descriptor.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.CALLABLES)
.filterIsInstance<CallableMemberDescriptor>().filter { it.kind === CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
fun createFakeOverrideFunction(descriptor: FunctionDescriptor, property: IrPropertySymbol?): IrSimpleFunction {
val returnType = descriptor.returnType?.let { toIrType(it) } ?: error("No return type for $descriptor")
val functionDeclare = { s: IrSimpleFunctionSymbol ->
descriptor.run {
IrFunctionImpl(
offset, offset, memberOrigin, s, name, visibility, modality, returnType,
isInline, isExternal, isTailrec, isSuspend, isOperator, isExpect, true
)
}
}
val newFunction = symbolTable?.declareSimpleFunction(offset, offset, memberOrigin, descriptor, functionDeclare)
?: functionDeclare(IrSimpleFunctionSymbolImpl(descriptor))
newFunction.parent = this
newFunction.overriddenSymbols = descriptor.overriddenDescriptors.mapNotNull { symbolTable?.referenceSimpleFunction(it.original) }
newFunction.dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.let { newFunction.createValueParameter(it) }
newFunction.extensionReceiverParameter = descriptor.extensionReceiverParameter?.let { newFunction.createValueParameter(it) }
newFunction.valueParameters = descriptor.valueParameters.map { newFunction.createValueParameter(it) }
newFunction.correspondingPropertySymbol = property
return newFunction
}
fun createFakeOverrideProperty(descriptor: PropertyDescriptor): IrProperty {
val propertyDeclare = { s: IrPropertySymbol ->
IrPropertyImpl(offset, offset, memberOrigin, s, descriptor.name)
}
val property = symbolTable?.declareProperty(offset, offset, memberOrigin, descriptor, propertyFactory = propertyDeclare)
?: propertyDeclare(IrPropertySymbolImpl(descriptor))
property.parent = this
property.getter = descriptor.getter?.let { g -> createFakeOverrideFunction(g, property.symbol) }
property.setter = descriptor.setter?.let { s -> createFakeOverrideFunction(s, property.symbol) }
return property
}
fun createFakeOverride(descriptor: CallableMemberDescriptor): IrDeclaration {
return when (descriptor) {
is FunctionDescriptor -> createFakeOverrideFunction(descriptor, null)
is PropertyDescriptor -> createFakeOverrideProperty(descriptor)
else -> error("Unexpected member $descriptor")
}
}
declarations += fakeOverrideDescriptors.map { createFakeOverride(it) }
}
}
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMo
import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule
import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForInteropStubs
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs
import org.jetbrains.kotlin.backend.konan.llvm.*
@@ -21,6 +20,8 @@ import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -144,8 +145,9 @@ internal val psiToIrPhase = konanUnitPhase(
Psi2IrConfiguration(false), KonanIdSignaturer(KonanManglerDesc))
val generatorContext = translator.createGeneratorContext(moduleDescriptor, bindingContext, symbolTable)
val pluginExtensions = IrGenerationExtension.getInstances(config.project)
translator.addPostprocessingStep { module ->
val extensions = IrGenerationExtension.getInstances(config.project)
val pluginContext = IrPluginContext(
generatorContext.moduleDescriptor,
generatorContext.bindingContext,
@@ -154,7 +156,7 @@ internal val psiToIrPhase = konanUnitPhase(
generatorContext.typeTranslator,
generatorContext.irBuiltIns
)
extensions.forEach { extension ->
pluginExtensions.forEach { extension ->
extension.generate(module, pluginContext)
}
}
@@ -167,12 +169,25 @@ internal val psiToIrPhase = konanUnitPhase(
// Note: using [llvmModuleSpecification] since this phase produces IR for generating single LLVM module.
val exportedDependencies = (getExportedDependencies() + modulesWithoutDCE).distinct()
val functionIrClassFactory = BuiltInFictitiousFunctionIrClassFactory(
symbolTable, generatorContext.irBuiltIns, reflectionTypes)
val stubGenerator = DeclarationStubGenerator(
moduleDescriptor, symbolTable,
config.configuration.languageVersionSettings
)
val symbols = KonanSymbols(this, symbolTable, symbolTable.lazyWrapper, functionIrClassFactory)
val irProviderForCEnumsAndCStructs =
IrProviderForCEnumAndCStructStubs(generatorContext, interopBuiltIns, symbols)
val deserializer = KonanIrLinker(
moduleDescriptor,
functionIrClassFactory,
this as LoggingContext,
generatorContext.irBuiltIns,
symbolTable,
forwardDeclarationsModuleDescriptor,
stubGenerator,
irProviderForCEnumsAndCStructs,
exportedDependencies
)
@@ -190,40 +205,22 @@ internal val psiToIrPhase = konanUnitPhase(
}
for (dependency in sortDependencies(dependencies)) {
deserializer.deserializeIrModuleHeader(dependency)
val kotlinLibrary = dependency.getCapability(KlibModuleOrigin.CAPABILITY)?.let {
(it as? DeserializedKlibModuleOrigin)?.library
}
deserializer.deserializeIrModuleHeader(dependency, kotlinLibrary)
}
if (dependencies.size == dependenciesCount) break
dependenciesCount = dependencies.size
}
deserializer.initializeExpectActualLinker()
val functionIrClassFactory = BuiltInFictitiousFunctionIrClassFactory(
symbolTable, generatorContext.irBuiltIns, reflectionTypes)
val symbols = KonanSymbols(this, symbolTable, symbolTable.lazyWrapper, functionIrClassFactory)
val stubGenerator = DeclarationStubGenerator(
moduleDescriptor, symbolTable,
config.configuration.languageVersionSettings
)
val irProviderForCEnumsAndCStructs = IrProviderForCEnumAndCStructStubs(
generatorContext, interopBuiltIns, symbols, llvmModuleSpecification::containsModule
)
// We need to run `buildAllEnumsAndStructsFrom` before `generateModuleFragment` because it adds references to symbolTable
// that should be bound.
modulesWithoutDCE
.filter(ModuleDescriptor::isFromInteropLibrary)
.forEach(irProviderForCEnumsAndCStructs::buildAllEnumsAndStructsFrom)
val irProviderForInteropStubs = IrProviderForInteropStubs(
stubGenerator,
irProviderForCEnumsAndCStructs::canHandleSymbol
)
val irProviders = listOf(
irProviderForCEnumsAndCStructs,
irProviderForInteropStubs,
functionIrClassFactory,
deserializer,
stubGenerator
)
.forEach(irProviderForCEnumsAndCStructs::referenceAllEnumsAndStructsFrom)
val irProviders = listOf(deserializer)
stubGenerator.setIrProviders(irProviders)
expectDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>()
@@ -238,14 +235,16 @@ internal val psiToIrPhase = konanUnitPhase(
if (expectActualLinker) expectDescriptorToSymbol else null
)
deserializer.finalizeExpectActualLinker()
deserializer.postProcess()
if (this.stdlibModule in modulesWithoutDCE) {
functionIrClassFactory.buildAllClasses()
}
module.acceptVoid(ManglerChecker(KonanManglerIr, Ir2DescriptorManglerAdapter(KonanManglerDesc)))
module.files += irProviderForCEnumsAndCStructs.outputFiles
// Enable lazy IR genration for newly-created symbols inside BE
stubGenerator.unboundSymbolGeneration = true
module.acceptVoid(ManglerChecker(KonanManglerIr, Ir2DescriptorManglerAdapter(KonanManglerDesc)))
irModule = module
irModules = deserializer.modules.filterValues { llvmModuleSpecification.containsModule(it) }
@@ -263,7 +262,6 @@ internal val psiToIrPhase = konanUnitPhase(
internal val destroySymbolTablePhase = konanUnitPhase(
op = {
this.symbolTable = null // TODO: invalidate symbolTable itself.
ir.symbols.functionIrClassFactory.symbolTable = null
},
name = "DestroySymbolTable",
description = "Destroy SymbolTable",
@@ -514,13 +514,13 @@ internal class KonanSymbols(
.getContributedClassifier(Name.identifier(name), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
)
override fun functionN(n: Int) = functionIrClassFactory.function(n).symbol
override fun functionN(n: Int) = functionIrClassFactory.functionN(n).symbol
override fun suspendFunctionN(n: Int) = functionIrClassFactory.suspendFunction(n).symbol
override fun suspendFunctionN(n: Int) = functionIrClassFactory.suspendFunctionN(n).symbol
fun kFunctionN(n: Int) = functionIrClassFactory.kFunction(n).symbol
fun kFunctionN(n: Int) = functionIrClassFactory.kFunctionN(n).symbol
fun kSuspendFunctionN(n: Int) = functionIrClassFactory.kSuspendFunction(n).symbol
fun kSuspendFunctionN(n: Int) = functionIrClassFactory.kSuspendFunctionN(n).symbol
fun getKFunctionType(returnType: IrType, parameterTypes: List<IrType>) =
kFunctionN(parameterTypes.size).typeWith(parameterTypes + returnType)
@@ -160,9 +160,10 @@ internal fun ClassDescriptor.inheritsFromCStructVar(interopBuiltIns: InteropBuil
* CEnum inheritor.
*/
internal fun IrSymbol.findCEnumDescriptor(interopBuiltIns: InteropBuiltIns): ClassDescriptor? =
descriptor.parentsWithSelf
.filterIsInstance<ClassDescriptor>()
.firstOrNull { it.implementsCEnum(interopBuiltIns) }
descriptor.findCEnumDescriptor(interopBuiltIns)
internal fun DeclarationDescriptor.findCEnumDescriptor(interopBuiltIns: InteropBuiltIns): ClassDescriptor? =
parentsWithSelf.filterIsInstance<ClassDescriptor>().firstOrNull { it.implementsCEnum(interopBuiltIns) }
/**
* All structs that come from interop library inherit from CStructVar class.
@@ -170,6 +171,7 @@ internal fun IrSymbol.findCEnumDescriptor(interopBuiltIns: InteropBuiltIns): Cla
* CStructVar inheritor.
*/
internal fun IrSymbol.findCStructDescriptor(interopBuiltIns: InteropBuiltIns): ClassDescriptor? =
descriptor.parentsWithSelf
.filterIsInstance<ClassDescriptor>()
.firstOrNull { it.inheritsFromCStructVar(interopBuiltIns) }
descriptor.findCStructDescriptor(interopBuiltIns)
internal fun DeclarationDescriptor.findCStructDescriptor(interopBuiltIns: InteropBuiltIns): ClassDescriptor? =
parentsWithSelf.filterIsInstance<ClassDescriptor>().firstOrNull { it.inheritsFromCStructVar(interopBuiltIns) }
@@ -4,28 +4,20 @@
*/
package org.jetbrains.kotlin.backend.konan.ir.interop
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.backend.konan.InteropBuiltIns
import org.jetbrains.kotlin.backend.konan.descriptors.findPackage
import org.jetbrains.kotlin.backend.konan.descriptors.getPackageFragments
import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumByValueFunctionGenerator
import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumClassGenerator
import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumCompanionGenerator
import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumVarClassGenerator
import org.jetbrains.kotlin.backend.konan.ir.interop.cstruct.CStructVarClassGenerator
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
/**
@@ -38,23 +30,18 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
* compiler phases.
* 2. It is an easier and more obvious approach. Since implementation of metadata-based
* libraries generation already took too much time we take an easier approach here.
*
* [moduleFilter] -- We want to select modules that should be part of compiler's output.
*
* For example, when we generate compiler cache,
* declarations from dependencies should not be added to the current module.
*/
internal class IrProviderForCEnumAndCStructStubs(
context: GeneratorContext,
private val interopBuiltIns: InteropBuiltIns,
symbols: KonanSymbols,
private val moduleFilter: (ModuleDescriptor) -> Boolean
) : IrProvider {
symbols: KonanSymbols
) {
/**
* TODO: integrate this provider into [KonanIrLinker.KonanInteropModuleDeserializer]
*/
private val symbolTable: SymbolTable = context.symbolTable
private val filesMap = mutableMapOf<PackageFragmentDescriptor, IrFile>()
private val cEnumByValueFunctionGenerator =
CEnumByValueFunctionGenerator(context, symbols)
private val cEnumCompanionGenerator =
@@ -66,60 +53,47 @@ internal class IrProviderForCEnumAndCStructStubs(
private val cStructClassGenerator =
CStructVarClassGenerator(context, interopBuiltIns)
/**
* The final output of this provider is a list of files which contain IR declarations
* of enums and structs that should be generated.
*/
val outputFiles: List<IrFile>
get() = filesMap.filterKeys { moduleFilter(it.module) }.values.toList()
fun isCEnumOrCStruct(declarationDescriptor: DeclarationDescriptor): Boolean =
declarationDescriptor.run { findCEnumDescriptor(interopBuiltIns) ?: findCStructDescriptor(interopBuiltIns) } != null
fun canHandleSymbol(symbol: IrSymbol): Boolean {
if (!symbol.isPublicApi) return false
if (symbol.signature.run { !IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.test() }) return false
return symbol.findCEnumDescriptor(interopBuiltIns) != null
|| symbol.findCStructDescriptor(interopBuiltIns) != null
}
fun buildAllEnumsAndStructsFrom(interopModule: ModuleDescriptor) = interopModule.getPackageFragments()
fun referenceAllEnumsAndStructsFrom(interopModule: ModuleDescriptor) = interopModule.getPackageFragments()
.flatMap { it.getMemberScope().getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) }
.filterIsInstance<ClassDescriptor>()
.forEach {
when {
it.implementsCEnum(interopBuiltIns) ->
cEnumClassGenerator.findOrGenerateCEnum(it, irParentFor(it))
it.inheritsFromCStructVar(interopBuiltIns) ->
cStructClassGenerator.findOrGenerateCStruct(it, irParentFor(it))
}
}
.filter { it.implementsCEnum(interopBuiltIns) || it.inheritsFromCStructVar(interopBuiltIns) }
.forEach { symbolTable.referenceClass(it) }
private fun generateIrIfNeeded(symbol: IrSymbol) {
private fun generateIrIfNeeded(symbol: IrSymbol, file: IrFile) {
// TODO: These `findOrGenerate` calls generate a whole subtree.
// This a simple but clearly suboptimal solution.
symbol.findCEnumDescriptor(interopBuiltIns)?.let { enumDescriptor ->
cEnumClassGenerator.findOrGenerateCEnum(enumDescriptor, irParentFor(enumDescriptor))
cEnumClassGenerator.findOrGenerateCEnum(enumDescriptor, file)
}
symbol.findCStructDescriptor(interopBuiltIns)?.let { structDescriptor ->
cStructClassGenerator.findOrGenerateCStruct(structDescriptor, irParentFor(structDescriptor))
cStructClassGenerator.findOrGenerateCStruct(structDescriptor, file)
}
}
override fun getDeclaration(symbol: IrSymbol): IrDeclaration? {
if (symbol.isBound) return symbol.owner as IrDeclaration
if (!canHandleSymbol(symbol)) return null
generateIrIfNeeded(symbol)
return when (symbol) {
is IrClassSymbol -> symbolTable.referenceClass(symbol.descriptor).owner
is IrEnumEntrySymbol -> symbolTable.referenceEnumEntry(symbol.descriptor).owner
is IrFunctionSymbol -> symbolTable.referenceFunction(symbol.descriptor).owner
is IrPropertySymbol -> symbolTable.referenceProperty(symbol.descriptor).owner
else -> error(symbol)
}
}
private fun irParentFor(descriptor: ClassDescriptor): IrDeclarationContainer {
val packageFragmentDescriptor = descriptor.findPackage()
return filesMap.getOrPut(packageFragmentDescriptor) {
IrFileImpl(NaiveSourceBasedFileEntryImpl(cTypeDefinitionsFileName), packageFragmentDescriptor)
fun getDeclaration(descriptor: DeclarationDescriptor, idSignature: IdSignature, file: IrFile, symbolKind: BinarySymbolData.SymbolKind): IrSymbolOwner {
return symbolTable.run {
when (symbolKind) {
BinarySymbolData.SymbolKind.CLASS_SYMBOL -> declareClassFromLinker(descriptor as ClassDescriptor, idSignature) { s ->
generateIrIfNeeded(s, file)
s.owner
}
BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL -> declareEnumEntryFromLinker(descriptor as ClassDescriptor, idSignature) { s ->
generateIrIfNeeded(s, file)
s.owner
}
BinarySymbolData.SymbolKind.FUNCTION_SYMBOL -> declareSimpleFunctionFromLinker(descriptor as FunctionDescriptor, idSignature) { s ->
generateIrIfNeeded(s, file)
s.owner
}
BinarySymbolData.SymbolKind.PROPERTY_SYMBOL -> declarePropertyFromLinker(descriptor as PropertyDescriptor, idSignature) { s ->
generateIrIfNeeded(s, file)
s.owner
}
else -> error("Unexpected symbol kind $symbolKind for sig $idSignature")
}
}
}
@@ -1,66 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan.serialization
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.util.IdSignature
// The code here is intentionally copy-pasted from DeclarationStubGenerator with
// minor changes.
// "Find descriptor by IdSignature" task appears to be common and should be unified later.
class DescriptorByIdSignatureFinder(
private val moduleDescriptor: ModuleDescriptor
) {
fun findDescriptorBySignature(signature: IdSignature): DeclarationDescriptor? = when (signature) {
is IdSignature.AccessorSignature -> findDescriptorForAccessorSignature(signature)
is IdSignature.PublicSignature -> findDescriptorForPublicSignature(signature)
else -> error("only PublicSignature or AccessorSignature should reach this point, got $signature")
}
private fun findDescriptorForAccessorSignature(signature: IdSignature.AccessorSignature): DeclarationDescriptor? {
val propertyDescriptor = findDescriptorBySignature(signature.propertySignature) as? PropertyDescriptor
?: return null
return propertyDescriptor.accessors.singleOrNull {
it.name == signature.accessorSignature.declarationFqn.shortName()
}
}
private fun findDescriptorForPublicSignature(signature: IdSignature.PublicSignature): DeclarationDescriptor? {
val packageDescriptor = moduleDescriptor.getPackage(signature.packageFqName())
val pathSegments = signature.declarationFqn.pathSegments()
val toplevelDescriptors = packageDescriptor.memberScope.getContributedDescriptors { name -> name == pathSegments.first() }
.filter { it.name == pathSegments.first() }
val candidates = pathSegments.drop(1).fold(toplevelDescriptors) { acc, current ->
acc.flatMap { container ->
val classDescriptor = container as? ClassDescriptor
?: return@flatMap emptyList<DeclarationDescriptor>()
val nextStepCandidates = classDescriptor.constructors +
classDescriptor.unsubstitutedMemberScope.getContributedDescriptors { name -> name == current } +
// Static scope is required only for Enum.values() and Enum.valueOf().
classDescriptor.staticScope.getContributedDescriptors { name -> name == current }
nextStepCandidates.filter { it.name == current }
}
}
return when (candidates.size) {
1 -> candidates.first()
else -> {
findDescriptorByHash(candidates, signature.id)
?: error("No descriptor found for $signature")
}
}
}
private fun findDescriptorByHash(candidates: List<DeclarationDescriptor>, id: Long?): DeclarationDescriptor? =
candidates.firstOrNull { candidate ->
if (id == null) {
// We don't compute id for typealiases and classes.
candidate is ClassDescriptor || candidate is TypeAliasDescriptor
} else {
val candidateHash = with(KonanManglerDesc) { candidate.signatureMangle }
candidateHash == id
}
}
}
@@ -18,123 +18,189 @@ package org.jetbrains.kotlin.backend.konan.serialization
import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.backend.konan.descriptors.isInteropLibrary
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
class KonanIrLinker(
private val currentModule: ModuleDescriptor,
logger: LoggingContext,
builtIns: IrBuiltIns,
symbolTable: SymbolTable,
private val forwardModuleDescriptor: ModuleDescriptor?,
exportedDependencies: List<ModuleDescriptor>
) : KotlinIrLinker(logger, builtIns, symbolTable, exportedDependencies, forwardModuleDescriptor) {
private val descriptorByIdSignatureFinder = DescriptorByIdSignatureFinder(currentModule)
override fun reader(moduleDescriptor: ModuleDescriptor, fileIndex: Int, idSigIndex: Int) =
moduleDescriptor.konanLibrary!!.irDeclaration(idSigIndex, fileIndex)
override fun readType(moduleDescriptor: ModuleDescriptor, fileIndex: Int, typeIndex: Int) =
moduleDescriptor.konanLibrary!!.type(typeIndex, fileIndex)
override fun readSignature(moduleDescriptor: ModuleDescriptor, fileIndex: Int, signatureIndex: Int) =
moduleDescriptor.konanLibrary!!.signature(signatureIndex, fileIndex)
override fun readString(moduleDescriptor: ModuleDescriptor, fileIndex: Int, stringIndex: Int) =
moduleDescriptor.konanLibrary!!.string(stringIndex, fileIndex)
override fun readBody(moduleDescriptor: ModuleDescriptor, fileIndex: Int, bodyIndex: Int) =
moduleDescriptor.konanLibrary!!.body(bodyIndex, fileIndex)
override fun readFile(moduleDescriptor: ModuleDescriptor, fileIndex: Int) =
moduleDescriptor.konanLibrary!!.file(fileIndex)
override fun readFileCount(moduleDescriptor: ModuleDescriptor) =
moduleDescriptor.run { if (this === forwardModuleDescriptor || moduleDescriptor.isFromInteropLibrary()) 0 else konanLibrary!!.fileCount() }
override fun handleNoModuleDeserializerFound(idSignature: IdSignature): DeserializationState<*> {
return globalDeserializationState
}
internal class KonanIrLinker(
private val currentModule: ModuleDescriptor,
override val functionalInteraceFactory: IrAbstractFunctionFactory,
logger: LoggingContext,
builtIns: IrBuiltIns,
symbolTable: SymbolTable,
private val forwardModuleDescriptor: ModuleDescriptor?,
private val stubGenerator: DeclarationStubGenerator,
private val cenumsProvider: IrProviderForCEnumAndCStructStubs,
exportedDependencies: List<ModuleDescriptor>
) : KotlinIrLinker(currentModule, logger, builtIns, symbolTable, exportedDependencies) {
companion object {
private val C_NAMES_NAME = Name.identifier("cnames")
private val OBJC_NAMES_NAME = Name.identifier("objcnames")
val FORWARD_DECLARATION_ORIGIN = object : IrDeclarationOriginImpl("FORWARD_DECLARATION_ORIGIN") {}
const val offset = SYNTHETIC_OFFSET
}
override fun isSpecialPlatformSignature(idSig: IdSignature): Boolean = idSig.isForwardDeclarationSignature()
override fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean = moduleDescriptor.isNativeStdlib()
override fun postProcessPlatformSpecificDeclaration(idSig: IdSignature, descriptor: DeclarationDescriptor?, block: (IdSignature) -> Unit) {
if (descriptor == null) return
private val forwardDeclarationDeserializer = forwardModuleDescriptor?.let { KonanForwardDeclarationModuleDeserialier(it) }
if (!idSig.isForwardDeclarationSignature()) return
val fqn = descriptor.fqNameSafe
if (!fqn.startsWith(C_NAMES_NAME) && !fqn.startsWith(OBJC_NAMES_NAME)) {
val signature = IdSignature.PublicSignature(fqn.parent(), FqName(fqn.shortName().asString()), null, 0)
block(signature)
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer {
if (moduleDescriptor === forwardModuleDescriptor) {
return forwardDeclarationDeserializer ?: error("forward declaration deserializer expected")
}
if (klib is KotlinLibrary && klib.isInteropLibrary()) {
return KonanInteropModuleDeserializer(moduleDescriptor)
}
return KonanModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy)
}
override fun resolvePlatformDescriptor(idSig: IdSignature): DeclarationDescriptor? {
if (idSig.isInteropSignature()) {
return descriptorByIdSignatureFinder.findDescriptorBySignature(idSig)
private inner class KonanModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy):
KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy)
private inner class KonanInteropModuleDeserializer(moduleDescriptor: ModuleDescriptor) : IrModuleDeserializer(moduleDescriptor) {
init {
assert(moduleDescriptor.kotlinLibrary.isInteropLibrary())
}
if (!idSig.isForwardDeclarationSignature()) return null
val fwdModule = forwardModuleDescriptor ?: error("Forward declaration module should not be null")
private val descriptorByIdSignatureFinder = DescriptorByIdSignatureFinder(moduleDescriptor, KonanManglerDesc)
private fun IdSignature.isInteropSignature(): Boolean = IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.test()
return with(idSig as IdSignature.PublicSignature) {
val classId = ClassId(packageFqn, declarationFqn, false)
fwdModule.findClassAcrossModuleDependencies(classId)
override fun contains(idSig: IdSignature): Boolean {
if (idSig.isPublic) {
if (idSig.isInteropSignature()) {
// TODO: add descriptor cache??
return descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) != null
}
}
return false
}
}
private fun IdSignature.isInteropSignature(): Boolean = IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.test()
private fun DeclarationDescriptor.isCEnumsOrCStruct(): Boolean = cenumsProvider.isCEnumOrCStruct(this)
private fun IdSignature.isForwardDeclarationSignature(): Boolean {
if (isPublic) {
return packageFqName().run {
startsWith(C_NAMES_NAME) || startsWith(OBJC_NAMES_NAME)
private val fileMap = mutableMapOf<PackageFragmentDescriptor, IrFile>()
private fun getIrFile(packageFragment: PackageFragmentDescriptor): IrFile = fileMap.getOrPut(packageFragment) {
IrFileImpl(NaiveSourceBasedFileEntryImpl(IrProviderForCEnumAndCStructStubs.cTypeDefinitionsFileName), packageFragment).also {
moduleFragment.files.add(it)
}
}
return false
}
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy): IrModuleDeserializer {
return KonanModuleDeserializer(moduleDescriptor, strategy)
}
private inner class KonanModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy):
IrModuleDeserializer(moduleDescriptor, strategy)
/**
* If declaration is from interop library then IR for it is generated by IrProviderForInteropStubs.
*/
override fun IdSignature.shouldBeDeserialized(): Boolean = !isInteropSignature() && !isForwardDeclarationSignature()
val modules: Map<String, IrModuleFragment> get() = mutableMapOf<String, IrModuleFragment>().apply {
deserializersForModules.filter { !it.key.isForwardDeclarationModule }.forEach {
this.put(it.key.konanLibrary!!.libraryName, it.value.module)
private fun resolveCEnumsOrStruct(descriptor: DeclarationDescriptor, idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
val file = getIrFile(descriptor.findPackage())
return cenumsProvider.getDeclaration(descriptor, idSig, file, symbolKind).symbol
}
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
val descriptor = descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) ?: error("Expecting descriptor for $idSig")
if (descriptor.isCEnumsOrCStruct()) return resolveCEnumsOrStruct(descriptor, idSig, symbolKind)
val symbolOwner = stubGenerator.generateMemberStub(descriptor) as IrSymbolOwner
return symbolOwner.symbol
}
override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns)
override val moduleDependencies: Collection<IrModuleDeserializer> = listOfNotNull(forwardDeclarationDeserializer)
}
}
private inner class KonanForwardDeclarationModuleDeserialier(moduleDescriptor: ModuleDescriptor) : IrModuleDeserializer(moduleDescriptor) {
init {
assert(moduleDescriptor.isForwardDeclarationModule)
}
private val declaredDeclaration = mutableMapOf<IdSignature, IrClass>()
private val packageToFileMap = mutableMapOf<FqName, IrFile>()
private fun IdSignature.isForwardDeclarationSignature(): Boolean {
if (isPublic) {
return packageFqName().run {
startsWith(C_NAMES_NAME) || startsWith(OBJC_NAMES_NAME)
}
}
return false
}
override fun contains(idSig: IdSignature): Boolean = idSig.isForwardDeclarationSignature()
private fun resolveDescriptor(idSig: IdSignature): ClassDescriptor =
with(idSig as IdSignature.PublicSignature) {
val classId = ClassId(packageFqn, declarationFqn, false)
moduleDescriptor.findClassAcrossModuleDependencies(classId) ?: error("No declaration found with $idSig")
}
private fun getIrFile(packageFragment: PackageFragmentDescriptor): IrFile {
val fqn = packageFragment.fqName
return packageToFileMap.getOrPut(packageFragment.fqName) {
val fileSymbol = IrFileSymbolImpl(packageFragment)
IrFileImpl(NaiveSourceBasedFileEntryImpl("forward declarations for $fqn"), fileSymbol).also {
moduleFragment.files.add(it)
}
}
}
private fun buildForwardDeclarationStub(idSig: IdSignature, descriptor: ClassDescriptor): IrClass {
val packageDescriptor = descriptor.containingDeclaration as PackageFragmentDescriptor
val irFile = getIrFile(packageDescriptor)
val klass = symbolTable.declareClassFromLinker(descriptor, idSig) { s ->
IrClassImpl(offset, offset, FORWARD_DECLARATION_ORIGIN, s)
}
klass.parent = irFile
irFile.declarations.add(klass)
return klass
}
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
assert(symbolKind == BinarySymbolData.SymbolKind.CLASS_SYMBOL) { "Only class could be a Forward declaration $idSig (kind $symbolKind)" }
val descriptor = resolveDescriptor(idSig)
val actualModule = descriptor.module
if (actualModule !== moduleDescriptor) {
val moduleDeserializer = deserializersForModules[actualModule] ?: error("No module deserializer for $actualModule")
moduleDeserializer.addModuleReachableTopLevel(idSig)
return symbolTable.referenceClassFromLinker(descriptor, idSig)
}
return declaredDeclaration.getOrPut(idSig) { buildForwardDeclarationStub(idSig, descriptor) }.symbol
}
override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns)
override val moduleDependencies: Collection<IrModuleDeserializer> = emptyList()
}
val modules: Map<String, IrModuleFragment>
get() = mutableMapOf<String, IrModuleFragment>().apply {
deserializersForModules
.filter { !it.key.isForwardDeclarationModule && it.value.moduleDescriptor !== currentModule }
.forEach { this.put(it.key.konanLibrary!!.libraryName, it.value.moduleFragment) }
}
}