[KLIB] Make K/N work with new linker
(cherry picked from commit 19a301ee517ad89e82e4b65347a6ff112042e781)
This commit is contained in:
committed by
Vasily Levchenko
parent
9021273001
commit
98ad71fc11
+170
-55
@@ -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) }
|
||||
}
|
||||
}
|
||||
+30
-32
@@ -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",
|
||||
|
||||
+4
-4
@@ -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)
|
||||
|
||||
+8
-6
@@ -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) }
|
||||
+37
-63
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-66
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
+155
-89
@@ -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) }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user