[KLIB] Create an abstract class for module deserializer

- Introduce Ir-based Functional interface factory
 - Switch from LazyIr to pure
 - Use kotlin library to access raw bytes
 - Link dirty files against IC cache and dependencies instead of LazyIr
 - Move `DescriptorByIdSignatureFinder` from K/N to common
 - Support inline-bodies only MODE
This commit is contained in:
Roman Artemev
2020-03-16 17:19:51 +03:00
committed by romanart
parent 74132fbc03
commit a9788f9506
19 changed files with 1647 additions and 801 deletions
@@ -10,8 +10,11 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.IrExtensionGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.resolve.BindingContext
@@ -26,7 +29,7 @@ class IrPluginContext(
val symbols: BuiltinSymbolsBase = BuiltinSymbolsBase(irBuiltIns.builtIns, symbolTable)
) : IrGeneratorContext()
interface IrGenerationExtension {
interface IrGenerationExtension : IrExtensionGenerator {
companion object :
ProjectExtensionDescriptor<IrGenerationExtension>("org.jetbrains.kotlin.irGenerationExtension", IrGenerationExtension::class.java)
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.StageController
import org.jetbrains.kotlin.ir.declarations.stageController
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.generateTypicalIrProviderList
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
@@ -58,11 +59,8 @@ fun compile(
val context = JsIrBackendContext(moduleDescriptor, irBuiltIns, symbolTable, moduleFragment, exportedDeclarations, configuration)
// Load declarations referenced during `context` initialization
dependencyModules.forEach {
val irProviders = generateTypicalIrProviderList(it.descriptor, irBuiltIns, symbolTable, deserializer)
ExternalDependenciesGenerator(symbolTable, irProviders, configuration.languageVersionSettings)
.generateUnboundSymbolsAsDependencies()
}
val irProviders = listOf(deserializer)
ExternalDependenciesGenerator(symbolTable, irProviders, configuration.languageVersionSettings).generateUnboundSymbolsAsDependencies()
val allModules = when (mainModule) {
is MainModule.SourceFiles -> dependencyModules + listOf(moduleFragment)
@@ -71,16 +69,12 @@ fun compile(
val irFiles = allModules.flatMap { it.files }
deserializer.postProcess()
moduleFragment.files.clear()
moduleFragment.files += irFiles
val irProvidersWithoutDeserializer = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable)
// Create stubs
ExternalDependenciesGenerator(symbolTable, irProvidersWithoutDeserializer, configuration.languageVersionSettings)
.generateUnboundSymbolsAsDependencies()
moduleFragment.patchDeclarationParents()
deserializer.finalizeExpectActualLinker()
symbolTable.lazyWrapper.stubGenerator = DeclarationStubGenerator(moduleDescriptor, symbolTable, irBuiltIns.languageVersionSettings)
moveBodilessDeclarationsToSeparatePlace(context, moduleFragment)
@@ -13,8 +13,11 @@ import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.ir.backend.jvm.serialization.EmptyLoggingContext
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrLinker
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmManglerDesc
@@ -33,8 +36,9 @@ object JvmBackendFacade {
val signaturer = JvmIdSignatureDescriptor(mangler)
val psi2ir = Psi2IrTranslator(state.languageVersionSettings, signaturer = signaturer)
val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext, extensions = extensions)
val pluginExtensions = IrGenerationExtension.getInstances(state.project)
for (extension in IrGenerationExtension.getInstances(state.project)) {
for (extension in pluginExtensions) {
psi2ir.addPostprocessingStep { module ->
extension.generate(
module,
@@ -53,22 +57,22 @@ object JvmBackendFacade {
val stubGenerator = DeclarationStubGenerator(
psi2irContext.moduleDescriptor, psi2irContext.symbolTable, psi2irContext.irBuiltIns.languageVersionSettings, extensions
)
val deserializer = JvmIrLinker(
EmptyLoggingContext, psi2irContext.irBuiltIns, psi2irContext.symbolTable
)
psi2irContext.moduleDescriptor.allDependencyModules.filter { it.getCapability(KlibModuleOrigin.CAPABILITY) != null }.forEach {
deserializer.deserializeIrModuleHeader(it)
val irLinker = JvmIrLinker(psi2irContext.moduleDescriptor, EmptyLoggingContext, psi2irContext.irBuiltIns, psi2irContext.symbolTable, stubGenerator, mangler)
val dependencies = psi2irContext.moduleDescriptor.allDependencyModules.map {
val kotlinLibrary = (it.getCapability(KlibModuleOrigin.CAPABILITY) as? DeserializedKlibModuleOrigin)?.library
irLinker.deserializeIrModuleHeader(it, kotlinLibrary)
}
val irProviders = listOf(deserializer, stubGenerator)
val irProviders = listOf(irLinker)
stubGenerator.setIrProviders(irProviders)
val irModuleFragment = psi2ir.generateModuleFragment(
psi2irContext, files,
irProviders = irProviders,
expectDescriptorToSymbol = null
)
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files, irProviders, expectDescriptorToSymbol = null, pluginExtensions)
irLinker.postProcess()
stubGenerator.unboundSymbolGeneration = true
// We need to compile all files we reference in Klibs
irModuleFragment.files.addAll(deserializer.getAllIrFiles())
irModuleFragment.files.addAll(dependencies.flatMap { it.files })
doGenerateFilesInternal(
state, irModuleFragment, psi2irContext.symbolTable, psi2irContext.sourceManager, phaseConfig, irProviders, extensions
@@ -56,7 +56,7 @@ fun compileWasm(
val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer)
ExternalDependenciesGenerator(symbolTable, irProviders, configuration.languageVersionSettings).generateUnboundSymbolsAsDependencies()
moduleFragment.patchDeclarationParents()
deserializer.finalizeExpectActualLinker()
deserializer.postProcess()
wasmPhases.invokeToplevel(phaseConfig, context, moduleFragment)
@@ -43,6 +43,7 @@ class Psi2IrTranslator(
postprocessingSteps.add(step)
}
// NOTE: used only for test purpose
fun generateModule(
moduleDescriptor: ModuleDescriptor,
ktFiles: Collection<KtFile>,
@@ -68,7 +69,8 @@ class Psi2IrTranslator(
context: GeneratorContext,
ktFiles: Collection<KtFile>,
irProviders: List<IrProvider>,
expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>? = null
expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>? = null,
pluginExtensions: Collection<IrExtensionGenerator> = emptyList()
): IrModuleFragment {
val moduleGenerator = ModuleGenerator(context)
val irModule = moduleGenerator.generateModuleFragmentWithoutDependencies(ktFiles)
@@ -76,8 +78,14 @@ class Psi2IrTranslator(
irModule.patchDeclarationParents()
expectDescriptorToSymbol?.let { referenceExpectsForUsedActuals(it, context.symbolTable, irModule) }
postprocess(context, irModule)
// do not generate unbound symbols before postprocessing,
// since plugins must work with non-lazy IR
irProviders.filterIsInstance<IrDeserializer>().forEach { it.init(irModule, pluginExtensions) }
moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders)
postprocessingSteps.forEach { it.invoke(irModule) }
// TODO: remove it once plugin API improved
moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders)
return irModule
@@ -87,8 +95,6 @@ class Psi2IrTranslator(
insertImplicitCasts(irElement, context)
generateAnnotationsForDeclarations(context, irElement)
postprocessingSteps.forEach { it(irElement) }
irElement.patchDeclarationParents()
}
@@ -0,0 +1,457 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.descriptors
import org.jetbrains.kotlin.builtins.KOTLIN_REFLECT_FQ_NAME
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
abstract class IrAbstractFunctionFactory {
abstract fun functionClassDescriptor(arity: Int): FunctionClassDescriptor
abstract fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor
abstract fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor
abstract fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor
abstract fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
abstract fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
abstract fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
abstract fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
fun functionN(n: Int) = functionN(n) { callback ->
val descriptor = functionClassDescriptor(n)
declareClass(offset, offset, classOrigin, descriptor) { symbol ->
callback(symbol)
}
}
fun kFunctionN(n: Int): IrClass {
return kFunctionN(n) { callback ->
val descriptor = kFunctionClassDescriptor(n)
declareClass(offset, offset, classOrigin, descriptor) { symbol ->
callback(symbol)
}
}
}
fun suspendFunctionN(n: Int): IrClass = suspendFunctionN(n) { callback ->
val descriptor = suspendFunctionClassDescriptor(n)
declareClass(offset, offset, classOrigin, descriptor) { symbol ->
callback(symbol)
}
}
fun kSuspendFunctionN(n: Int): IrClass = kSuspendFunctionN(n) { callback ->
val descriptor = kSuspendFunctionClassDescriptor(n)
declareClass(offset, offset, classOrigin, descriptor) { symbol ->
callback(symbol)
}
}
companion object {
val classOrigin = object : IrDeclarationOriginImpl("FUNCTION_INTERFACE_CLASS") {}
val memberOrigin = object : IrDeclarationOriginImpl("FUNCTION_INTERFACE_MEMBER") {}
const val offset = SYNTHETIC_OFFSET
}
}
class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTable: SymbolTable) : IrAbstractFunctionFactory() {
// TODO: Lazieness
private val functionNMap = mutableMapOf<Int, IrClass>()
private val kFunctionNMap = mutableMapOf<Int, IrClass>()
private val suspendFunctionNMap = mutableMapOf<Int, IrClass>()
private val kSuspendFunctionNMap = mutableMapOf<Int, IrClass>()
override fun functionClassDescriptor(arity: Int): FunctionClassDescriptor =
irBuiltIns.builtIns.getFunction(arity) as FunctionClassDescriptor
override fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
return functionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
val descriptor = symbol.descriptor as FunctionClassDescriptor
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
createFunctionClass(symbol, false, false, arity, irBuiltIns.functionClass, kotlinPackageFragment, descriptorFactory)
}
}
}
override fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor =
irBuiltIns.builtIns.getSuspendFunction(arity) as FunctionClassDescriptor
override fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
return suspendFunctionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
val descriptor = symbol.descriptor as FunctionClassDescriptor
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
createFunctionClass(symbol, false, true, arity, irBuiltIns.functionClass, kotlinCoroutinesPackageFragment, descriptorFactory)
}
}
}
override fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(false, arity))
return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
override fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
return kFunctionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
val descriptor = symbol.descriptor as FunctionClassDescriptor
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
createFunctionClass(symbol, true, false, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, descriptorFactory)
}
}
}
override fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(true, arity))
return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
override fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
return kSuspendFunctionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
val descriptor = symbol.descriptor as FunctionClassDescriptor
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
createFunctionClass(symbol, true, true, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, descriptorFactory)
}
}
}
companion object {
private fun reflectFunctionClassFqn(shortName: Name): FqName = KOTLIN_REFLECT_FQ_NAME.child(shortName)
private fun reflectionFunctionClassName(isSuspend: Boolean, arity: Int): Name =
Name.identifier("K${if (isSuspend) "Suspend" else ""}Function$arity")
private fun functionClassName(isK: Boolean, isSuspend: Boolean, arity: Int): String =
"${if (isK) "K" else ""}${if (isSuspend) "Suspend" else ""}Function$arity"
}
private sealed class FunctionDescriptorFactory(protected val symbolTable: SymbolTable) {
abstract fun memberDescriptor(name: String, factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction): IrSimpleFunctionSymbol
abstract fun FunctionDescriptor.valueParameterDescriptor(index: Int): ValueParameterDescriptor
abstract fun typeParameterDescriptor(index: Int, factory: (IrTypeParameterSymbol) -> IrTypeParameter): IrTypeParameterSymbol
abstract fun classReceiverParameterDescriptor(): ReceiverParameterDescriptor
abstract fun FunctionDescriptor.memberReceiverParameterDescriptor(): ReceiverParameterDescriptor
class RealDescriptorFactory(private val classDescriptor: FunctionClassDescriptor, symbolTable: SymbolTable) :
FunctionDescriptorFactory(symbolTable) {
override fun memberDescriptor(name: String, factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction): IrSimpleFunctionSymbol {
val descriptor = classDescriptor.unsubstitutedMemberScope.run {
if (name[0] == '<') {
val propertyName = name.drop(5).dropLast(1)
val property = getContributedVariables(Name.identifier(propertyName), NoLookupLocation.FROM_BACKEND).single()
property.accessors.first { it.name.asString() == name }
} else {
getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first()
}
}
return symbolTable.declareSimpleFunction(offset, offset, memberOrigin, descriptor, factory).symbol
}
override fun FunctionDescriptor.valueParameterDescriptor(index: Int): ValueParameterDescriptor {
assert(containingDeclaration === classDescriptor)
return valueParameters[index]
}
override fun typeParameterDescriptor(index: Int, factory: (IrTypeParameterSymbol) -> IrTypeParameter): IrTypeParameterSymbol {
val descriptor = classDescriptor.declaredTypeParameters[index]
return symbolTable.declareGlobalTypeParameter(offset, offset, classOrigin, descriptor, factory).symbol
}
override fun classReceiverParameterDescriptor(): ReceiverParameterDescriptor {
return classDescriptor.thisAsReceiverParameter
}
override fun FunctionDescriptor.memberReceiverParameterDescriptor(): ReceiverParameterDescriptor {
assert(containingDeclaration === classDescriptor)
return dispatchReceiverParameter ?: error("Expected dispatch receiver at $this")
}
}
}
private fun IrTypeParametersContainer.createTypeParameters(n: Int, descriptorFactory: FunctionDescriptorFactory): IrTypeParameter {
var index = 0
val typeParametersArray = ArrayList<IrTypeParameter>(n + 1)
for (i in 1 until (n + 1)) {
val pName = Name.identifier("P$i")
val pSymbol = descriptorFactory.typeParameterDescriptor(index) {
IrTypeParameterImpl(offset, offset, classOrigin, it, pName, index++, false, Variance.IN_VARIANCE)
}
val pDeclaration = pSymbol.owner
pDeclaration.superTypes += irBuiltIns.anyNType
pDeclaration.parent = this
typeParametersArray.add(pDeclaration)
}
val rSymbol = descriptorFactory.typeParameterDescriptor(index) {
IrTypeParameterImpl(offset, offset, classOrigin, it, Name.identifier("R"), index, false, Variance.OUT_VARIANCE)
}
val rDeclaration = rSymbol.owner
rDeclaration.superTypes += irBuiltIns.anyNType
rDeclaration.parent = this
typeParametersArray.add(rDeclaration)
typeParameters = typeParametersArray
return rDeclaration
}
private val kotlinPackageFragment: IrPackageFragment by lazy {
irBuiltIns.builtIns.getFunction(0).let {
symbolTable.declareExternalPackageFragment(it.containingDeclaration as PackageFragmentDescriptor)
}
}
private val kotlinCoroutinesPackageFragment: IrPackageFragment by lazy {
irBuiltIns.builtIns.getSuspendFunction(0).let {
symbolTable.declareExternalPackageFragment(it.containingDeclaration as PackageFragmentDescriptor)
}
}
private val kotlinReflectPackageFragment: IrPackageFragment by lazy {
irBuiltIns.kPropertyClass.descriptor.let {
symbolTable.declareExternalPackageFragment(it.containingDeclaration as PackageFragmentDescriptor)
}
}
private fun IrClass.createThisReceiver(descriptorFactory: FunctionDescriptorFactory): IrValueParameter {
val vDescriptor = descriptorFactory.classReceiverParameterDescriptor()
val vSymbol = IrValueParameterSymbolImpl(vDescriptor)
val type = with(IrSimpleTypeBuilder()) {
classifier = symbol
arguments = typeParameters.run {
val builder = IrSimpleTypeBuilder()
mapTo(ArrayList(size)) {
builder.classifier = it.symbol
buildTypeProjection()
}
}
buildSimpleType()
}
val vDeclaration = IrValueParameterImpl(
offset, offset, classOrigin, vSymbol, Name.special("<this>"), -1, type, null,
isCrossinline = false,
isNoinline = false
)
if (vDescriptor is WrappedReceiverParameterDescriptor) vDescriptor.bind(vDeclaration)
return vDeclaration
}
private fun FunctionClassDescriptor.createFunctionClass(): IrClass {
val s = symbolTable.referenceClass(this)
if (s.isBound) return s.owner
return symbolTable.declareClass(offset, offset, classOrigin, this, modality) {
val factory = FunctionDescriptorFactory.RealDescriptorFactory(this, symbolTable)
when (functionKind) {
FunctionClassDescriptor.Kind.Function ->
createFunctionClass(it, false, false, arity, irBuiltIns.functionClass, kotlinPackageFragment, factory)
FunctionClassDescriptor.Kind.SuspendFunction ->
createFunctionClass(it, false, true, arity, irBuiltIns.functionClass, kotlinCoroutinesPackageFragment, factory)
FunctionClassDescriptor.Kind.KFunction ->
createFunctionClass(it, true, false, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, factory)
FunctionClassDescriptor.Kind.KSuspendFunction ->
createFunctionClass(it, true, true, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, factory)
}
}
}
private fun IrClass.createMembers(isK: Boolean, isSuspend: Boolean, arity: Int, name: String, descriptorFactory: FunctionDescriptorFactory) {
if (!isK) {
val invokeSymbol = descriptorFactory.memberDescriptor("invoke") {
val returnType = with(IrSimpleTypeBuilder()) {
classifier = typeParameters.last().symbol
buildSimpleType()
}
IrFunctionImpl(offset, offset, memberOrigin, it, Name.identifier("invoke"), Visibilities.PUBLIC, Modality.ABSTRACT,
returnType,
isInline = false,
isExternal = false,
isTailrec = false,
isSuspend = isSuspend,
isOperator = true,
isExpect = false,
isFakeOverride = false
)
}
val fDeclaration = invokeSymbol.owner
fDeclaration.dispatchReceiverParameter = createThisReceiver(descriptorFactory).also { it.parent = fDeclaration }
val typeBuilder = IrSimpleTypeBuilder()
for (i in 1 until typeParameters.size) {
val vTypeParam = typeParameters[i - 1]
val vDescriptor = with(descriptorFactory) { invokeSymbol.descriptor.valueParameterDescriptor(i - 1) }
val vSymbol = IrValueParameterSymbolImpl(vDescriptor)
val vType = with(typeBuilder) {
classifier = vTypeParam.symbol
buildSimpleType()
}
val vDeclaration = IrValueParameterImpl(
offset, offset, memberOrigin, vSymbol, Name.identifier("p$i"), i - 1, vType, null,
isCrossinline = false,
isNoinline = false
)
vDeclaration.parent = fDeclaration
if (vDescriptor is WrappedValueParameterDescriptor) vDescriptor.bind(vDeclaration)
fDeclaration.valueParameters += vDeclaration
}
fDeclaration.parent = this
declarations += fDeclaration
}
addFakeOverrides()
}
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 newFunction = symbolTable.declareSimpleFunction(offset, offset, memberOrigin, descriptor) {
descriptor.run {
IrFunctionImpl(
offset, offset, memberOrigin, it, name, visibility, modality, returnType,
isInline, isExternal, isTailrec, isSuspend, isOperator, isExpect, true
)
}
}
newFunction.parent = this
newFunction.overriddenSymbols = descriptor.overriddenDescriptors.map { 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 {
return symbolTable.declareProperty(offset, offset, memberOrigin, descriptor) {
IrPropertyImpl(offset, offset, memberOrigin, it, descriptor.name).apply {
parent = this@addFakeOverrides
getter = descriptor.getter?.let { g -> createFakeOverrideFunction(g, symbol) }
setter = descriptor.setter?.let { s -> createFakeOverrideFunction(s, symbol) }
}
}
}
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) }
}
private fun createFunctionClass(
symbol: IrClassSymbol,
isK: Boolean,
isSuspend: Boolean,
n: Int,
baseClass: IrClassSymbol,
packageFragment: IrPackageFragment,
descriptorFactory: FunctionDescriptorFactory
): IrClass {
val name = functionClassName(isK, isSuspend, n)
val klass = IrClassImpl(
offset, offset, classOrigin, symbol, Name.identifier(name), ClassKind.INTERFACE, Visibilities.PUBLIC, Modality.ABSTRACT,
isCompanion = false,
isInner = false,
isData = false,
isExternal = false,
isInline = false,
isExpect = false,
isFun = false
)
val r = klass.createTypeParameters(n, descriptorFactory)
klass.thisReceiver = klass.createThisReceiver(descriptorFactory).also { it.parent = klass }
klass.superTypes = listOf(with(IrSimpleTypeBuilder()) {
classifier = baseClass
arguments = listOf(
with(IrSimpleTypeBuilder()) {
classifier = r.symbol
buildTypeProjection()
},
)
buildSimpleType()
})
klass.createMembers(isK, isSuspend, n, klass.name.identifier, descriptorFactory)
klass.parent = packageFragment
packageFragment.declarations += klass
return klass
}
}
@@ -52,8 +52,6 @@ class ExternalDependenciesGenerator(
assert(symbol.isBound) { "$symbol unbound even after deserialization attempt" }
}
} while (unbound.isNotEmpty())
irProviders.forEach { (it as? IrDeserializer)?.declareForwardDeclarations() }
}
}
@@ -46,8 +46,12 @@ interface LazyIrProvider : IrProvider {
override fun getDeclaration(symbol: IrSymbol): IrLazyDeclarationBase?
}
interface IrExtensionGenerator {
fun declare(symbol: IrSymbol): IrDeclaration? = null
}
interface IrDeserializer : IrProvider {
fun declareForwardDeclarations()
fun init(moduleFragment: IrModuleFragment?, extensions: Collection<IrExtensionGenerator>) {}
}
interface ReferenceSymbolTable {
@@ -846,6 +850,25 @@ open class SymbolTable(val signaturer: IdSignatureComposer) : ReferenceSymbolTab
}
return result
}
private inline fun <D : DeclarationDescriptor, IR : IrSymbolOwner, S : IrBindableSymbol<D, IR>> FlatSymbolTable<D, IR, S>.forEachPublicSymbolImpl(
block: (IrSymbol) -> Unit
) {
idSigToSymbol.forEach { (_, sym) ->
assert(sym.isPublicApi)
block(sym)
}
}
fun forEachPublicSymbol(block: (IrSymbol) -> Unit) {
classSymbolTable.forEachPublicSymbolImpl { block(it) }
constructorSymbolTable.forEachPublicSymbolImpl { block(it) }
simpleFunctionSymbolTable.forEachPublicSymbolImpl { block(it) }
propertySymbolTable.forEachPublicSymbolImpl { block(it) }
enumEntrySymbolTable.forEachPublicSymbolImpl { block(it) }
typeAliasSymbolTable.forEachPublicSymbolImpl { block(it) }
fieldSymbolTable.forEachPublicSymbolImpl { block(it) }
}
}
inline fun <T, D : DeclarationDescriptor> SymbolTable.withScope(owner: D, block: SymbolTable.(D) -> T): T {
@@ -0,0 +1,63 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.KotlinMangler
class DescriptorByIdSignatureFinder(private val moduleDescriptor: ModuleDescriptor, private val mangler: KotlinMangler.DescriptorMangler) {
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(mangler) { candidate.signatureMangle }
candidateHash == id
}
}
}
@@ -0,0 +1,137 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.DeserializedDescriptor
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.SerializedIrFile
import org.jetbrains.kotlin.library.impl.*
class ICKotlinLibrary(private val icData: List<SerializedIrFile>) : IrLibrary {
override val dataFlowGraph: ByteArray? = null
private inline fun <K, R : IrTableReader<K>> Array<R?>.itemBytes(fileIndex: Int, key: K, factory: () -> R): ByteArray {
val reader = this[fileIndex] ?: factory().also { this[fileIndex] = it }
return reader.tableItemBytes(key)
}
private inline fun <R : IrArrayReader> Array<R?>.itemBytes(fileIndex: Int, index: Int, factory: () -> R): ByteArray {
val reader = this[fileIndex] ?: factory().also { this[fileIndex] = it }
return reader.tableItemBytes(index)
}
private val indexedDeclarations = arrayOfNulls<DeclarationIrTableMemoryReader>(icData.size)
private val indexedTypes = arrayOfNulls<IrArrayMemoryReader>(icData.size)
private val indexedSignatures = arrayOfNulls<IrArrayMemoryReader>(icData.size)
private val indexedStrings = arrayOfNulls<IrArrayMemoryReader>(icData.size)
private val indexedBodies = arrayOfNulls<IrArrayMemoryReader>(icData.size)
override fun irDeclaration(index: Int, fileIndex: Int): ByteArray =
indexedDeclarations.itemBytes(fileIndex, DeclarationId(index)) {
DeclarationIrTableMemoryReader(icData[fileIndex].declarations)
}
override fun type(index: Int, fileIndex: Int): ByteArray =
indexedTypes.itemBytes(fileIndex, index) {
IrArrayMemoryReader(icData[fileIndex].types)
}
override fun signature(index: Int, fileIndex: Int): ByteArray =
indexedSignatures.itemBytes(fileIndex, index) {
IrArrayMemoryReader(icData[fileIndex].signatures)
}
override fun string(index: Int, fileIndex: Int): ByteArray =
indexedStrings.itemBytes(fileIndex, index) {
IrArrayMemoryReader(icData[fileIndex].strings)
}
override fun body(index: Int, fileIndex: Int): ByteArray =
indexedBodies.itemBytes(fileIndex, index) {
IrArrayMemoryReader(icData[fileIndex].bodies)
}
override fun file(index: Int): ByteArray = icData[index].fileData
override fun fileCount(): Int = icData.size
}
class CurrentModuleWithICDeserializer(
private val delegate: IrModuleDeserializer,
private val symbolTable: SymbolTable,
private val irBuiltIns: IrBuiltIns,
icData: List<SerializedIrFile>,
icReaderFactory: (IrLibrary) -> IrModuleDeserializer) :
IrModuleDeserializer(delegate.moduleDescriptor) {
private val dirtyDeclarations = mutableMapOf<IdSignature, IrSymbol>()
private val icKlib = ICKotlinLibrary(icData)
private val icDeserializer: IrModuleDeserializer = icReaderFactory(icKlib)
override fun contains(idSig: IdSignature): Boolean {
return idSig in dirtyDeclarations || idSig.topLevelSignature() in icDeserializer || idSig in delegate
}
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
dirtyDeclarations[idSig]?.let { return it }
if (idSig.topLevelSignature() in icDeserializer) return icDeserializer.deserializeIrSymbol(idSig, symbolKind)
return delegate.deserializeIrSymbol(idSig, symbolKind)
}
override fun addModuleReachableTopLevel(idSig: IdSignature) {
assert(idSig in icDeserializer)
icDeserializer.addModuleReachableTopLevel(idSig)
}
override fun deserializeReachableDeclarations() {
icDeserializer.deserializeReachableDeclarations()
}
override fun postProcess() {
icDeserializer.postProcess()
}
private fun DeclarationDescriptor.isDirtyDescriptor(): Boolean {
if (this is PropertyAccessorDescriptor) return correspondingProperty.isDirtyDescriptor()
return this !is DeserializedDescriptor
}
override fun init() {
val knownBuiltIns = irBuiltIns.knownBuiltins.map { (it as IrSymbolOwner).symbol }.toSet()
symbolTable.forEachPublicSymbol {
if (it.descriptor.isDirtyDescriptor()) { // public && non-deserialized should be dirty symbol
if (it !in knownBuiltIns) {
dirtyDeclarations[it.signature] = it
}
}
}
icDeserializer.init(this)
}
override val klib: IrLibrary
get() = icDeserializer.klib
override val moduleFragment: IrModuleFragment
get() = delegate.moduleFragment
override val moduleDependencies: Collection<IrModuleDeserializer>
get() = delegate.moduleDependencies
}
@@ -1,76 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol
import org.jetbrains.kotlin.ir.util.isReal
import org.jetbrains.kotlin.ir.util.original
// We may get several real supers here (e.g. see the code snippet from KT-33034).
// TODO: Consider reworking the resolution algorithm to get a determined super declaration.
private fun <S: IrBindableSymbol<*, D>, D: IrOverridableDeclaration<S>> D.getRealSupers(): Set<D> {
if (this.isReal) {
return setOf(this)
}
val visited = mutableSetOf<D>()
val realSupers = mutableSetOf<D>()
fun findRealSupers(declaration: D) {
if (declaration in visited) return
visited += declaration
if (declaration.isReal) {
realSupers += declaration
} else {
declaration.overriddenSymbols.forEach { findRealSupers(it.owner) }
}
}
findRealSupers(this)
if (realSupers.size > 1) {
visited.clear()
fun excludeOverridden(declaration: D) {
if (declaration in visited) return
visited += declaration
declaration.overriddenSymbols.forEach {
realSupers.remove(it.owner)
excludeOverridden(it.owner)
}
}
realSupers.toList().forEach { excludeOverridden(it) }
}
return realSupers
}
/**
* Implementation of given method.
*
* TODO: this method is actually a part of resolve and probably duplicates another one
*/
fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false): IrSimpleFunction {
val realSupers = getRealSupers()
return if (allowAbstract) {
realSupers.first()
} else {
realSupers.single { it.modality != Modality.ABSTRACT }
}
}
val IrSimpleFunction.target: IrSimpleFunction
get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride()).original
val IrFunction.target: IrFunction get() = when (this) {
is IrSimpleFunction -> this.target
is IrConstructor -> this
else -> error(this)
}
@@ -104,7 +104,7 @@ import org.jetbrains.kotlin.backend.common.serialization.proto.PublicIdSignature
import org.jetbrains.kotlin.backend.common.serialization.proto.AccessorIdSignature as ProtoAccessorIdSignature
import org.jetbrains.kotlin.backend.common.serialization.proto.FileLocalIdSignature as ProtoFileLocalIdSignature
abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBuiltIns, val symbolTable: SymbolTable) {
abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBuiltIns, val symbolTable: SymbolTable, protected var deserializeBodies: Boolean) {
abstract fun deserializeIrSymbolToDeclare(code: Long): Pair<IrSymbol, IdSignature>
abstract fun deserializeIrSymbol(code: Long): IrSymbol
@@ -118,6 +118,9 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
abstract fun referenceIrSymbol(symbol: IrSymbol, signature: IdSignature)
private val parentsStack = mutableListOf<IrDeclarationParent>()
private val delegatedSymbolMap = mutableMapOf<IrSymbol, IrSymbol>()
abstract val deserializeInlineFunctions: Boolean
fun deserializeFqName(fqn: List<Int>): FqName {
return fqn.run {
@@ -125,6 +128,13 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
}
}
private fun deserializeIrSymbolAndRemap(code: Long): IrSymbol {
// TODO: could be simplified
return deserializeIrSymbol(code).let {
delegatedSymbolMap[it] ?: it
}
}
private fun deserializeName(index: Int): Name {
val name = deserializeString(index)
return Name.guessByFirstCharacter(name)
@@ -145,7 +155,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
}
private fun deserializeSimpleType(proto: ProtoSimpleType): IrSimpleType {
val symbol = deserializeIrSymbol(proto.classifier) as? IrClassifierSymbol
val symbol = deserializeIrSymbolAndRemap(proto.classifier) as? IrClassifierSymbol
?: error("could not convert sym to ClassifierSymbol")
logger.log { "deserializeSimpleType: symbol=$symbol" }
@@ -167,7 +177,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
private fun deserializeTypeAbbreviation(proto: ProtoTypeAbbreviation): IrTypeAbbreviation =
IrTypeAbbreviationImpl(
deserializeIrSymbol(proto.typeAlias).let {
deserializeIrSymbolAndRemap(proto.typeAlias).let {
it as? IrTypeAliasSymbol
?: error("IrTypeAliasSymbol expected: $it")
},
@@ -344,14 +354,14 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
end: Int,
type: IrType
): IrClassReference {
val symbol = deserializeIrSymbol(proto.classSymbol) as IrClassifierSymbol
val symbol = deserializeIrSymbolAndRemap(proto.classSymbol) as IrClassifierSymbol
val classType = deserializeIrType(proto.classType)
/** TODO: [createClassifierSymbolForClassReference] is internal function */
return IrClassReferenceImpl(start, end, type, symbol, classType)
}
private fun deserializeConstructorCall(proto: ProtoConstructorCall, start: Int, end: Int, type: IrType): IrConstructorCall {
val symbol = deserializeIrSymbol(proto.symbol) as IrConstructorSymbol
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrConstructorSymbol
return IrConstructorCallImpl(
start, end, type,
symbol, typeArgumentsCount = proto.memberAccess.typeArgumentCount,
@@ -363,10 +373,10 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
}
private fun deserializeCall(proto: ProtoCall, start: Int, end: Int, type: IrType): IrCall {
val symbol = deserializeIrSymbol(proto.symbol) as IrFunctionSymbol
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrFunctionSymbol
val superSymbol = if (proto.hasSuper()) {
deserializeIrSymbol(proto.`super`) as IrClassSymbol
deserializeIrSymbolAndRemap(proto.`super`) as IrClassSymbol
} else null
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
@@ -400,7 +410,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
start: Int,
end: Int
): IrDelegatingConstructorCall {
val symbol = deserializeIrSymbol(proto.symbol) as IrConstructorSymbol
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrConstructorSymbol
val call = IrDelegatingConstructorCallImpl(
start,
end,
@@ -421,7 +431,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
end: Int,
type: IrType
): IrEnumConstructorCall {
val symbol = deserializeIrSymbol(proto.symbol) as IrConstructorSymbol
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrConstructorSymbol
val call = IrEnumConstructorCallImpl(
start,
end,
@@ -451,10 +461,10 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
start: Int, end: Int, type: IrType
): IrFunctionReference {
val symbol = deserializeIrSymbol(proto.symbol) as IrFunctionSymbol
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrFunctionSymbol
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
val reflectionTarget =
if (proto.hasReflectionTargetSymbol()) deserializeIrSymbol(proto.reflectionTargetSymbol) as IrFunctionSymbol else null
if (proto.hasReflectionTargetSymbol()) deserializeIrSymbolAndRemap(proto.reflectionTargetSymbol) as IrFunctionSymbol else null
val callable = IrFunctionReferenceImpl(
start,
end,
@@ -477,11 +487,11 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
private fun deserializeGetField(proto: ProtoGetField, start: Int, end: Int, type: IrType): IrGetField {
val access = proto.fieldAccess
val symbol = deserializeIrSymbol(access.symbol) as IrFieldSymbol
val symbol = deserializeIrSymbolAndRemap(access.symbol) as IrFieldSymbol
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
val superQualifier = if (access.hasSuper()) {
deserializeIrSymbol(access.symbol) as IrClassSymbol
deserializeIrSymbolAndRemap(access.symbol) as IrClassSymbol
} else null
val receiver = if (access.hasReceiver()) {
deserializeExpression(access.receiver)
@@ -491,7 +501,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
}
private fun deserializeGetValue(proto: ProtoGetValue, start: Int, end: Int, type: IrType): IrGetValue {
val symbol = deserializeIrSymbol(proto.symbol) as IrValueSymbol
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrValueSymbol
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
// TODO: origin!
return IrGetValueImpl(start, end, type, symbol, origin)
@@ -503,7 +513,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
end: Int,
type: IrType
): IrGetEnumValue {
val symbol = deserializeIrSymbol(proto.symbol) as IrEnumEntrySymbol
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrEnumEntrySymbol
return IrGetEnumValueImpl(start, end, type, symbol)
}
@@ -513,7 +523,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
end: Int,
type: IrType
): IrGetObjectValue {
val symbol = deserializeIrSymbol(proto.symbol) as IrClassSymbol
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrClassSymbol
return IrGetObjectValueImpl(start, end, type, symbol)
}
@@ -522,7 +532,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
start: Int,
end: Int
): IrInstanceInitializerCall {
val symbol = deserializeIrSymbol(proto.symbol) as IrClassSymbol
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrClassSymbol
return IrInstanceInitializerCallImpl(start, end, symbol, builtIns.unitType)
}
@@ -533,10 +543,10 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
type: IrType
): IrLocalDelegatedPropertyReference {
val delegate = deserializeIrSymbol(proto.delegate) as IrVariableSymbol
val getter = deserializeIrSymbol(proto.getter) as IrSimpleFunctionSymbol
val setter = if (proto.hasSetter()) deserializeIrSymbol(proto.setter) as IrSimpleFunctionSymbol else null
val symbol = deserializeIrSymbol(proto.symbol) as IrLocalDelegatedPropertySymbol
val delegate = deserializeIrSymbolAndRemap(proto.delegate) as IrVariableSymbol
val getter = deserializeIrSymbolAndRemap(proto.getter) as IrSimpleFunctionSymbol
val setter = if (proto.hasSetter()) deserializeIrSymbolAndRemap(proto.setter) as IrSimpleFunctionSymbol else null
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrLocalDelegatedPropertySymbol
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
return IrLocalDelegatedPropertyReferenceImpl(
@@ -551,11 +561,11 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
private fun deserializePropertyReference(proto: ProtoPropertyReference, start: Int, end: Int, type: IrType): IrPropertyReference {
val symbol = deserializeIrSymbol(proto.symbol) as IrPropertySymbol
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrPropertySymbol
val field = if (proto.hasField()) deserializeIrSymbol(proto.field) as IrFieldSymbol else null
val getter = if (proto.hasGetter()) deserializeIrSymbol(proto.getter) as IrSimpleFunctionSymbol else null
val setter = if (proto.hasSetter()) deserializeIrSymbol(proto.setter) as IrSimpleFunctionSymbol else null
val field = if (proto.hasField()) deserializeIrSymbolAndRemap(proto.field) as IrFieldSymbol else null
val getter = if (proto.hasGetter()) deserializeIrSymbolAndRemap(proto.getter) as IrSimpleFunctionSymbol else null
val setter = if (proto.hasSetter()) deserializeIrSymbolAndRemap(proto.setter) as IrSimpleFunctionSymbol else null
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
val callable = IrPropertyReferenceImpl(
@@ -572,16 +582,16 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
}
private fun deserializeReturn(proto: ProtoReturn, start: Int, end: Int, type: IrType): IrReturn {
val symbol = deserializeIrSymbol(proto.returnTarget) as IrReturnTargetSymbol
val symbol = deserializeIrSymbolAndRemap(proto.returnTarget) as IrReturnTargetSymbol
val value = deserializeExpression(proto.value)
return IrReturnImpl(start, end, builtIns.nothingType, symbol, value)
}
private fun deserializeSetField(proto: ProtoSetField, start: Int, end: Int): IrSetField {
val access = proto.fieldAccess
val symbol = deserializeIrSymbol(access.symbol) as IrFieldSymbol
val symbol = deserializeIrSymbolAndRemap(access.symbol) as IrFieldSymbol
val superQualifier = if (access.hasSuper()) {
deserializeIrSymbol(access.symbol) as IrClassSymbol
deserializeIrSymbolAndRemap(access.symbol) as IrClassSymbol
} else null
val receiver = if (access.hasReceiver()) {
deserializeExpression(access.receiver)
@@ -593,7 +603,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
}
private fun deserializeSetVariable(proto: ProtoSetVariable, start: Int, end: Int): IrSetVariable {
val symbol = deserializeIrSymbol(proto.symbol) as IrVariableSymbol
val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrVariableSymbol
val value = deserializeExpression(proto.value)
val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null
return IrSetVariableImpl(start, end, builtIns.unitType, symbol, value, origin)
@@ -902,6 +912,16 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
}
}
private fun recordDelegatedSymbol(symbol: IrSymbol) {
if (symbol is IrDelegatingSymbol<*, *, *>) {
delegatedSymbolMap[symbol] = symbol.delegate
}
}
private fun eraseDelegatedSymbol(symbol: IrSymbol) {
delegatedSymbolMap.remove(symbol)
}
private inline fun <T : IrDeclarationParent> T.usingParent(block: T.() -> Unit): T =
this.apply { usingParent(this) { block(it) } }
@@ -911,15 +931,20 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
): T where T : IrDeclaration, T : IrSymbolOwner {
val (s, uid) = deserializeIrSymbolToDeclare(proto.symbol)
val coordinates = BinaryCoordinates.decode(proto.coordinates)
val result = block(
s,
uid,
coordinates.startOffset, coordinates.endOffset,
deserializeIrDeclarationOrigin(proto.originName), proto.flags
)
result.annotations += deserializeAnnotations(proto.annotationList)
result.parent = parentsStack.peek()!!
return result
try {
recordDelegatedSymbol(s)
val result = block(
s,
uid,
coordinates.startOffset, coordinates.endOffset,
deserializeIrDeclarationOrigin(proto.originName), proto.flags
)
result.annotations += deserializeAnnotations(proto.annotationList)
result.parent = parentsStack.peek()!!
return result
} finally {
eraseDelegatedSymbol(s)
}
}
private fun deserializeIrTypeParameter(proto: ProtoTypeParameter, index: Int, isGlobal: Boolean): IrTypeParameter {
@@ -1067,24 +1092,36 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
return result
}
private inline fun <T : IrFunction> T.withInlineGuard(block: T.() -> Unit) {
val oldInline = deserializeBodies
try {
deserializeBodies = oldInline || (deserializeInlineFunctions && this is IrSimpleFunction && isInline)
block()
} finally {
deserializeBodies = oldInline
}
}
private inline fun <T : IrFunction> withDeserializedIrFunctionBase(
proto: ProtoFunctionBase,
block: (IrFunctionSymbol, IdSignature, Int, Int, IrDeclarationOrigin, Long) -> T
) = withDeserializedIrDeclarationBase(proto.base) { symbol, idSig, startOffset, endOffset, origin, fcode ->
symbolTable.withScope(symbol.descriptor) {
block(symbol as IrFunctionSymbol, idSig, startOffset, endOffset, origin, fcode).usingParent {
typeParameters = deserializeTypeParameters(proto.typeParameterList, false)
valueParameters = deserializeValueParameters(proto.valueParameterList)
withInlineGuard {
typeParameters = deserializeTypeParameters(proto.typeParameterList, false)
valueParameters = deserializeValueParameters(proto.valueParameterList)
val nameType = BinaryNameAndType.decode(proto.nameType)
returnType = deserializeIrType(nameType.typeIndex)
val nameType = BinaryNameAndType.decode(proto.nameType)
returnType = deserializeIrType(nameType.typeIndex)
if (proto.hasDispatchReceiver())
dispatchReceiverParameter = deserializeIrValueParameter(proto.dispatchReceiver, -1)
if (proto.hasExtensionReceiver())
extensionReceiverParameter = deserializeIrValueParameter(proto.extensionReceiver, -1)
if (proto.hasBody()) {
body = deserializeStatementBody(proto.body) as IrBody
if (proto.hasDispatchReceiver())
dispatchReceiverParameter = deserializeIrValueParameter(proto.dispatchReceiver, -1)
if (proto.hasExtensionReceiver())
extensionReceiverParameter = deserializeIrValueParameter(proto.extensionReceiver, -1)
if (proto.hasBody()) {
body = deserializeStatementBody(proto.body) as IrBody
}
}
}
}
@@ -1111,7 +1148,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
flags.isFakeOverride
)
}.apply {
overriddenSymbols = proto.overriddenList.map { deserializeIrSymbol(it) as IrSimpleFunctionSymbol }
overriddenSymbols = proto.overriddenList.map { deserializeIrSymbolAndRemap(it) as IrSimpleFunctionSymbol }
(descriptor as? WrappedSimpleFunctionDescriptor)?.bind(this)
}
@@ -1328,6 +1365,4 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
usingParent(parent) {
deserializeDeclaration(proto)
}
}
val irrelevantOrigin = object : IrDeclarationOriginImpl("irrelevant") {}
}
@@ -0,0 +1,276 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.IrExtensionGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
internal fun IrSymbol.kind(): BinarySymbolData.SymbolKind {
return when (this) {
is IrClassSymbol -> BinarySymbolData.SymbolKind.CLASS_SYMBOL
is IrConstructorSymbol -> BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL
is IrSimpleFunctionSymbol -> BinarySymbolData.SymbolKind.FUNCTION_SYMBOL
is IrPropertySymbol -> BinarySymbolData.SymbolKind.PROPERTY_SYMBOL
is IrEnumEntrySymbol -> BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL
is IrTypeAliasSymbol -> BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL
else -> error("Unexpected symbol kind $this")
}
}
abstract class IrModuleDeserializer(val moduleDescriptor: ModuleDescriptor) {
abstract operator fun contains(idSig: IdSignature): Boolean
abstract fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol
open fun declareIrSymbol(symbol: IrSymbol) {
assert(symbol.isPublicApi)
assert(symbol.descriptor !is WrappedDeclarationDescriptor<*>)
deserializeIrSymbol(symbol.signature, symbol.kind())
}
open val klib: IrLibrary get() = error("Unsupported operation")
open fun init() = init(this)
open fun init(delegate: IrModuleDeserializer) {}
open fun addModuleReachableTopLevel(idSig: IdSignature) { error("Unsupported Operation (sig: $idSig") }
open fun deserializeReachableDeclarations() { error("Unsupported Operation") }
open fun postProcess() {}
abstract val moduleFragment: IrModuleFragment
abstract val moduleDependencies: Collection<IrModuleDeserializer>
open val strategy: DeserializationStrategy = DeserializationStrategy.ONLY_DECLARATION_HEADERS
}
// Used to resolve built in symbols like `kotlin.ir.internal.*` or `kotlin.FunctionN`
class IrModuleDeserializerWithBuiltIns(
private val builtIns: IrBuiltIns,
private val functionFactory: IrAbstractFunctionFactory,
private val delegate: IrModuleDeserializer
) : IrModuleDeserializer(delegate.moduleDescriptor) {
init {
// TODO: figure out how it should work for K/N
// assert(builtIns.builtIns.builtInsModule === delegate.moduleDescriptor)
}
private val irBuiltInsMap = builtIns.knownBuiltins.map {
val symbol = (it as IrSymbolOwner).symbol
symbol.signature to symbol
}.toMap()
private fun checkIsFunctionInterface(idSig: IdSignature): Boolean {
val publicSig = idSig.asPublic() ?: return false
if (publicSig.packageFqn !in functionalPackages) return false
val declarationFqn = publicSig.declarationFqn
if (declarationFqn.isRoot) return false
val fqnParts = declarationFqn.pathSegments()
val className = fqnParts.first()
return functionPattern.matcher(className.asString()).find()
}
override operator fun contains(idSig: IdSignature): Boolean {
if (idSig in irBuiltInsMap) return true
return checkIsFunctionInterface(idSig) || idSig in delegate
}
override fun deserializeReachableDeclarations() {
delegate.deserializeReachableDeclarations()
}
private fun computeFunctionDescriptor(className: Name): FunctionClassDescriptor {
val nameString = className.asString()
val isK = nameString[0] == 'K'
val isSuspend = (if (isK) nameString[1] else nameString[0]) == 'S'
val arity = nameString.run { substring(indexOfFirst { it.isDigit() }).toInt(10) }
return functionFactory.run {
when {
isK && isSuspend -> kSuspendFunctionClassDescriptor(arity)
isK -> kFunctionClassDescriptor(arity)
isSuspend -> suspendFunctionClassDescriptor(arity)
else -> functionClassDescriptor(arity)
}
}
}
private fun resolveFunctionalInterface(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
val publicSig = idSig.asPublic() ?: error("$idSig has to be public")
val fqnParts = publicSig.declarationFqn.pathSegments()
val className = fqnParts.firstOrNull() ?: error("Expected class name for $idSig")
val functionDescriptor = computeFunctionDescriptor(className)
val topLevelSignature = IdSignature.PublicSignature(publicSig.packageFqn, FqName(className.asString()), null, publicSig.mask)
val functionClass = when (functionDescriptor.functionKind) {
FunctionClassDescriptor.Kind.KSuspendFunction -> functionFactory.kSuspendFunctionN(functionDescriptor.arity) { callback ->
declareClassFromLinker(functionDescriptor, topLevelSignature) { callback(it) }
}
FunctionClassDescriptor.Kind.KFunction -> functionFactory.kFunctionN(functionDescriptor.arity) { callback ->
declareClassFromLinker(functionDescriptor, topLevelSignature) { callback(it) }
}
FunctionClassDescriptor.Kind.SuspendFunction -> functionFactory.suspendFunctionN(functionDescriptor.arity) { callback ->
declareClassFromLinker(functionDescriptor, topLevelSignature) { callback(it) }
}
FunctionClassDescriptor.Kind.Function -> functionFactory.functionN(functionDescriptor.arity) { callback ->
declareClassFromLinker(functionDescriptor, topLevelSignature) { callback(it) }
}
}
return when (fqnParts.size) {
1 -> functionClass.symbol.also { assert(symbolKind == BinarySymbolData.SymbolKind.CLASS_SYMBOL) }
2 -> {
val memberName = fqnParts[1]!!
functionClass.declarations.single { it is IrDeclarationWithName && it.name == memberName }.let {
(it as IrSymbolOwner).symbol
}
}
3 -> {
assert(idSig is IdSignature.AccessorSignature)
assert(symbolKind == BinarySymbolData.SymbolKind.FUNCTION_SYMBOL)
val propertyName = fqnParts[1]!!
val accessorName = fqnParts[2]!!
functionClass.declarations.filterIsInstance<IrProperty>().single { it.name == propertyName }.let { p ->
p.getter?.let { g -> if (g.name == accessorName) return g.symbol }
p.setter?.let { s -> if (s.name == accessorName) return s.symbol }
error("No accessor found for signature $idSig")
}
}
else -> error("No member found for signature $idSig")
}
}
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
irBuiltInsMap[idSig]?.let { return it }
if (checkIsFunctionInterface(idSig)) return resolveFunctionalInterface(idSig, symbolKind)
return delegate.deserializeIrSymbol(idSig, symbolKind)
}
override fun postProcess() {
delegate.postProcess()
}
override fun init() {
delegate.init(this)
}
override val klib: IrLibrary
get() = delegate.klib
override val strategy: DeserializationStrategy
get() = delegate.strategy
override fun addModuleReachableTopLevel(idSig: IdSignature) {
delegate.addModuleReachableTopLevel(idSig)
}
override val moduleFragment: IrModuleFragment get() = delegate.moduleFragment
override val moduleDependencies: Collection<IrModuleDeserializer> get() = delegate.moduleDependencies
}
open class CurrentModuleDeserializer(
override val moduleFragment: IrModuleFragment,
override val moduleDependencies: Collection<IrModuleDeserializer>,
private val symbolTable: SymbolTable,
private val extensions: Collection<IrExtensionGenerator>
) : IrModuleDeserializer(moduleFragment.descriptor) {
override fun contains(idSig: IdSignature): Boolean = false // TODO:
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
error("Unreachable execution: there could not be back-links")
}
override fun declareIrSymbol(symbol: IrSymbol) {
declareIrSymbolImpl(symbol)
}
private fun referenceParentDescriptor(descriptor: DeclarationDescriptor): IrSymbol {
return when (descriptor) {
is ClassDescriptor -> symbolTable.referenceClass(descriptor)
is PropertyDescriptor -> symbolTable.referenceProperty(descriptor)
is PackageFragmentDescriptor -> moduleFragment.files.single { it.symbol.descriptor === descriptor }.symbol
else -> error("Unexpected declaration parent $descriptor")
}
}
private fun declareIrDeclaration(symbol: IrSymbol): IrDeclaration {
for (extension in extensions) {
extension.declare(symbol)?.let { return it }
}
return declareIrDeclarationDefault(symbol)
}
private fun declareIrDeclarationDefault(symbol: IrSymbol): IrDeclaration {
return when (symbol) {
is IrClassSymbol -> symbolTable.declareClass(offset, offset, IrDeclarationOrigin.DEFINED, symbol.descriptor)
is IrConstructorSymbol -> symbolTable.declareConstructor(offset, offset, IrDeclarationOrigin.DEFINED, symbol.descriptor)
is IrSimpleFunctionSymbol -> symbolTable.declareSimpleFunction(offset, offset, IrDeclarationOrigin.DEFINED, symbol.descriptor)
is IrPropertySymbol -> symbolTable.declareProperty(offset, offset, IrDeclarationOrigin.DEFINED, symbol.descriptor)
is IrTypeAliasSymbol -> TODO("Implement type alias $symbol")
is IrEnumEntrySymbol -> symbolTable.declareEnumEntry(offset, offset, IrDeclarationOrigin.DEFINED, symbol.descriptor)
else -> error("Unexpected symbol $symbol")
}
}
private fun declareIrSymbolImpl(symbol: IrSymbol): IrSymbolOwner {
if (symbol.isBound) return symbol.owner
val descriptor = symbol.descriptor
assert(descriptor !is WrappedDeclarationDescriptor<*>)
val accessor = descriptor as? PropertyAccessorDescriptor
val parent = descriptor.containingDeclaration ?: error("Expect non-root declaration $descriptor")
val parentDeclaration = declareIrSymbolImpl(referenceParentDescriptor(parent)) as IrDeclarationContainer
val declaredDeclaration = declareIrDeclaration(symbol).also {
it.parent = parentDeclaration
if (accessor != null) {
val property = accessor.correspondingProperty
val irProperty = declareIrSymbolImpl(referenceParentDescriptor(property)) as IrProperty
val irAccessor = it as IrSimpleFunction
irAccessor.correspondingPropertySymbol = irProperty.symbol
if (accessor === property.getter) irProperty.getter = irAccessor
if (accessor === property.setter) irProperty.setter = irAccessor
} else {
parentDeclaration.declarations.add(it)
}
}
return declaredDeclaration as IrSymbolOwner
}
companion object {
private const val offset = UNDEFINED_OFFSET
}
}
@@ -102,6 +102,7 @@ fun generateKLib(
val incrementalDataProvider = configuration.get(JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER)
val icData: List<KotlinFileSerializedData>
val serializedIrFiles: List<SerializedIrFile>?
if (incrementalDataProvider != null) {
val nonCompiledSources = files.map { VfsUtilCore.virtualToIoFile(it.virtualFile) to it }.toMap()
@@ -124,8 +125,10 @@ fun generateKLib(
}
icData = storage
serializedIrFiles = storage.map { it.irData }
} else {
icData = emptyList()
serializedIrFiles = null
}
val depsDescriptors =
@@ -135,8 +138,13 @@ fun generateKLib(
val expectDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>()
val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, files,
deserializer = null, expectDescriptorToSymbol = expectDescriptorToSymbol)
val irLinker = JsIrLinker(psi2IrContext.moduleDescriptor, emptyLoggingContext, psi2IrContext.irBuiltIns, psi2IrContext.symbolTable, serializedIrFiles)
val deserializedModuleFragments = sortDependencies(allDependencies.getFullList(), depsDescriptors.descriptors).map {
irLinker.deserializeOnlyHeaderModule(depsDescriptors.getModuleDescriptor(it), it)
}
val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, files, irLinker, expectDescriptorToSymbol)
moduleFragment.acceptVoid(ManglerChecker(JsManglerIr, Ir2DescriptorManglerAdapter(JsManglerDesc)))
@@ -193,22 +201,20 @@ fun loadIr(
val irBuiltIns = psi2IrContext.irBuiltIns
val symbolTable = psi2IrContext.symbolTable
val deserializer = JsIrLinker(emptyLoggingContext, irBuiltIns, symbolTable)
val irLinker = JsIrLinker(psi2IrContext.moduleDescriptor, emptyLoggingContext, irBuiltIns, symbolTable, null)
val deserializedModuleFragments = sortDependencies(allDependencies.getFullList(), depsDescriptors.descriptors).map {
deserializer.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it))!!
irLinker.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it), it)
}
deserializer.initializeExpectActualLinker()
val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, mainModule.files, deserializer)
val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, mainModule.files, irLinker)
// TODO: not sure whether this check should be enabled by default. Add configuration key for it.
val mangleChecker = ManglerChecker(JsManglerIr, Ir2DescriptorManglerAdapter(JsManglerDesc))
moduleFragment.acceptVoid(mangleChecker)
irBuiltIns.knownBuiltins.forEach { it.acceptVoid(mangleChecker) }
return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, deserializer)
return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker)
}
is MainModule.Klib -> {
val moduleDescriptor = depsDescriptors.getModuleDescriptor(mainModule.lib)
@@ -224,7 +230,7 @@ fun loadIr(
typeTranslator.constantValueGenerator = constantValueGenerator
constantValueGenerator.typeTranslator = typeTranslator
val irBuiltIns = IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, signaturer, symbolTable)
val deserializer = JsIrLinker(emptyLoggingContext, irBuiltIns, symbolTable)
val irLinker = JsIrLinker(null, emptyLoggingContext, irBuiltIns, symbolTable, null)
val deserializedModuleFragments = sortDependencies(allDependencies.getFullList(), depsDescriptors.descriptors).map {
val strategy =
@@ -233,16 +239,16 @@ fun loadIr(
else
DeserializationStrategy.EXPLICITLY_EXPORTED
deserializer.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it), strategy)
irLinker.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it), it, strategy)
}
deserializer.initializeExpectActualLinker()
val moduleFragment = deserializedModuleFragments.last()
val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer)
ExternalDependenciesGenerator(symbolTable, irProviders, configuration.languageVersionSettings)
.generateUnboundSymbolsAsDependencies()
irLinker.init(null, emptyList())
ExternalDependenciesGenerator(symbolTable, listOf(irLinker), configuration.languageVersionSettings).generateUnboundSymbolsAsDependencies()
irLinker.postProcess()
return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, deserializer)
return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker)
}
}
}
@@ -266,14 +272,15 @@ private fun runAnalysisAndPreparePsi2Ir(depsDescriptors: ModulesStructure): Gene
fun GeneratorContext.generateModuleFragmentWithPlugins(
project: Project,
files: List<KtFile>,
deserializer: IrDeserializer? = null,
irLinker: IrDeserializer,
expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>? = null
): IrModuleFragment {
val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer)
val signaturer = IdSignatureDescriptor(JsManglerDesc)
val psi2Ir = Psi2IrTranslator(languageVersionSettings, configuration, signaturer)
for (extension in IrGenerationExtension.getInstances(project)) {
val extensions = IrGenerationExtension.getInstances(project)
for (extension in extensions) {
psi2Ir.addPostprocessingStep { module ->
extension.generate(
module,
@@ -289,26 +296,9 @@ fun GeneratorContext.generateModuleFragmentWithPlugins(
}
}
val moduleFragment =
psi2Ir.generateModuleFragment(
this,
files,
irProviders,
expectDescriptorToSymbol
)
return moduleFragment
return psi2Ir.generateModuleFragment(this, files, listOf(irLinker), expectDescriptorToSymbol, extensions)
}
fun GeneratorContext.generateModuleFragment(files: List<KtFile>, deserializer: IrDeserializer? = null, expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>? = null): IrModuleFragment {
val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer)
val mangler = JsManglerDesc
val signaturer = IdSignatureDescriptor(mangler)
return Psi2IrTranslator(
languageVersionSettings, configuration, signaturer
).generateModuleFragment(this, files, irProviders, expectDescriptorToSymbol)
}
private fun createBuiltIns(storageManager: StorageManager) = object : KotlinBuiltIns(storageManager) {}
internal val JsFactories = KlibMetadataFactories(::createBuiltIns, DynamicTypeDeserializer)
@@ -6,40 +6,45 @@
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.serialization.CurrentModuleWithICDeserializer
import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy
import org.jetbrains.kotlin.backend.common.serialization.IrModuleDeserializer
import org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.descriptors.IrFunctionFactory
import org.jetbrains.kotlin.ir.util.IrExtensionGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.SerializedIrFile
class JsIrLinker(logger: LoggingContext, builtIns: IrBuiltIns, symbolTable: SymbolTable) :
KotlinIrLinker(logger, builtIns, symbolTable, emptyList(), null) {
class JsIrLinker(currentModule: ModuleDescriptor?, logger: LoggingContext, builtIns: IrBuiltIns, symbolTable: SymbolTable, private val icData: List<SerializedIrFile>? = null) :
KotlinIrLinker(currentModule, logger, builtIns, symbolTable, emptyList()) {
override fun reader(moduleDescriptor: ModuleDescriptor, fileIndex: Int, idSigIndex: Int) =
moduleDescriptor.kotlinLibrary.irDeclaration(idSigIndex, fileIndex)
override val functionalInteraceFactory: IrAbstractFunctionFactory = IrFunctionFactory(builtIns, symbolTable)
override fun readType(moduleDescriptor: ModuleDescriptor, fileIndex: Int, typeIndex: Int) =
moduleDescriptor.kotlinLibrary.type(typeIndex, fileIndex)
override fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean =
moduleDescriptor === moduleDescriptor.builtIns.builtInsModule
override fun readSignature(moduleDescriptor: ModuleDescriptor, fileIndex: Int, signatureIndex: Int) =
moduleDescriptor.kotlinLibrary.signature(signatureIndex, fileIndex)
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer =
JsModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy)
override fun readString(moduleDescriptor: ModuleDescriptor, fileIndex: Int, stringIndex: Int) =
moduleDescriptor.kotlinLibrary.string(stringIndex, fileIndex)
private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy) :
KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy)
override fun readBody(moduleDescriptor: ModuleDescriptor, fileIndex: Int, bodyIndex: Int) =
moduleDescriptor.kotlinLibrary.body(bodyIndex, fileIndex)
override fun readFile(moduleDescriptor: ModuleDescriptor, fileIndex: Int) =
moduleDescriptor.kotlinLibrary.file(fileIndex)
override fun readFileCount(moduleDescriptor: ModuleDescriptor) =
moduleDescriptor.kotlinLibrary.fileCount()
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy): IrModuleDeserializer =
JsModuleDeserializer(moduleDescriptor, strategy)
private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy) :
KotlinIrLinker.IrModuleDeserializer(moduleDescriptor, strategy)
}
override fun createCurrentModuleDeserializer(
moduleFragment: IrModuleFragment,
dependencies: Collection<IrModuleDeserializer>,
extensions: Collection<IrExtensionGenerator>
): IrModuleDeserializer {
val currentModuleDeserializer = super.createCurrentModuleDeserializer(moduleFragment, dependencies, extensions)
icData?.let {
return CurrentModuleWithICDeserializer(currentModuleDeserializer, symbolTable, builtIns, it) { lib ->
JsModuleDeserializer(currentModuleDeserializer.moduleDescriptor, lib, currentModuleDeserializer.strategy)
}
}
return currentModuleDeserializer
}
}
@@ -6,51 +6,146 @@
package org.jetbrains.kotlin.ir.backend.jvm.serialization
import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy
import org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.descriptors.*
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.IrExtensionGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.load.java.descriptors.*
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment
import org.jetbrains.kotlin.name.Name
class JvmIrLinker(logger: LoggingContext, builtIns: IrBuiltIns, symbolTable: SymbolTable) :
KotlinIrLinker(logger, builtIns, symbolTable, emptyList(), null) {
class JvmIrLinker(currentModule: ModuleDescriptor?, logger: LoggingContext, builtIns: IrBuiltIns, symbolTable: SymbolTable, private val stubGenerator: DeclarationStubGenerator, private val manglerDesc: JvmManglerDesc) :
KotlinIrLinker(currentModule, logger, builtIns, symbolTable, emptyList()) {
override fun handleNoModuleDeserializerFound(idSignature: IdSignature): DeserializationState<*> {
// TODO: Implement special java-module deserializer instead of this hack
return globalDeserializationState // !!!!!! Wrong, as external references will all have UniqId.NONE
}
override val functionalInteraceFactory: IrAbstractFunctionFactory = IrFunctionFactory(builtIns, symbolTable)
override fun reader(moduleDescriptor: ModuleDescriptor, fileIndex: Int, idSigIndex: Int) =
moduleDescriptor.kotlinLibrary.irDeclaration(idSigIndex, fileIndex)
private val javaName = Name.identifier("java")
override fun readType(moduleDescriptor: ModuleDescriptor, fileIndex: Int, typeIndex: Int) =
moduleDescriptor.kotlinLibrary.type(typeIndex, fileIndex)
override fun readSignature(moduleDescriptor: ModuleDescriptor, fileIndex: Int, signatureIndex: Int) =
moduleDescriptor.kotlinLibrary.signature(signatureIndex, fileIndex)
override fun readString(moduleDescriptor: ModuleDescriptor, fileIndex: Int, stringIndex: Int) =
moduleDescriptor.kotlinLibrary.string(stringIndex, fileIndex)
override fun readBody(moduleDescriptor: ModuleDescriptor, fileIndex: Int, bodyIndex: Int) =
moduleDescriptor.kotlinLibrary.body(bodyIndex, fileIndex)
override fun readFile(moduleDescriptor: ModuleDescriptor, fileIndex: Int) =
moduleDescriptor.kotlinLibrary.file(fileIndex)
override fun readFileCount(moduleDescriptor: ModuleDescriptor) =
moduleDescriptor.kotlinLibrary.fileCount()
override fun resolveModuleDeserializer(moduleDescriptor: ModuleDescriptor): IrModuleDeserializer? {
return deserializersForModules[moduleDescriptor]
}
override fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean =
moduleDescriptor.name.asString() == "<built-ins module>"
// TODO: implement special Java deserializer
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy): IrModuleDeserializer =
JvmModuleDeserializer(moduleDescriptor, strategy)
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer {
if (klib != null) {
assert(moduleDescriptor.getCapability(KlibModuleOrigin.CAPABILITY) != null)
return JvmModuleDeserializer(moduleDescriptor, klib, strategy)
}
private inner class JvmModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy) :
KotlinIrLinker.IrModuleDeserializer(moduleDescriptor, strategy)
return MetadataJVMModuleDeserializer(moduleDescriptor, emptyList())
}
private inner class JvmModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy) :
KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy)
private fun DeclarationDescriptor.isJavaDescriptor(): Boolean {
if (this is PackageFragmentDescriptor) {
return this is LazyJavaPackageFragment || fqName.startsWith(javaName)
}
return this is JavaClassDescriptor || this is JavaCallableMemberDescriptor || (containingDeclaration?.isJavaDescriptor() == true)
}
private fun DeclarationDescriptor.isCleanDescriptor(): Boolean {
if (this is PropertyAccessorDescriptor) return correspondingProperty.isCleanDescriptor()
return this is DeserializedDescriptor
}
override fun platformSpecificSymbol(symbol: IrSymbol): Boolean {
return symbol.descriptor.isJavaDescriptor()
}
private fun declareJavaFieldStub(symbol: IrFieldSymbol): IrField {
return with(stubGenerator) {
val old = stubGenerator.unboundSymbolGeneration
try {
stubGenerator.unboundSymbolGeneration = true
generateFieldStub(symbol.descriptor)
} finally {
stubGenerator.unboundSymbolGeneration = old
}
}
}
override fun createCurrentModuleDeserializer(moduleFragment: IrModuleFragment, dependencies: Collection<IrModuleDeserializer>, extensions: Collection<IrExtensionGenerator>): IrModuleDeserializer =
JvmCurrentModuleDeserializer(moduleFragment, dependencies, extensions)
private inner class JvmCurrentModuleDeserializer(moduleFragment: IrModuleFragment, dependencies: Collection<IrModuleDeserializer>, extensions: Collection<IrExtensionGenerator>) :
CurrentModuleDeserializer(moduleFragment, dependencies, symbolTable, extensions) {
override fun declareIrSymbol(symbol: IrSymbol) {
val descriptor = symbol.descriptor
if (descriptor.isJavaDescriptor()) {
// Wrap java declaration with lazy ir
if (symbol is IrFieldSymbol) {
declareJavaFieldStub(symbol)
} else {
stubGenerator.generateMemberStub(descriptor)
}
return
}
if (descriptor.isCleanDescriptor()) {
stubGenerator.generateMemberStub(descriptor)
return
}
super.declareIrSymbol(symbol)
}
}
private inner class MetadataJVMModuleDeserializer(moduleDescriptor: ModuleDescriptor, dependencies: List<IrModuleDeserializer>) :
IrModuleDeserializer(moduleDescriptor) {
// TODO: implement proper check whether `idSig` belongs to this module
override fun contains(idSig: IdSignature): Boolean = true
private val descriptorFinder = DescriptorByIdSignatureFinder(moduleDescriptor, manglerDesc)
private fun resolveDescriptor(idSig: IdSignature): DeclarationDescriptor {
return descriptorFinder.findDescriptorBySignature(idSig) ?: error("No descriptor found for $idSig")
}
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
val descriptor = resolveDescriptor(idSig)
val declaration = stubGenerator.run {
when (symbolKind) {
BinarySymbolData.SymbolKind.CLASS_SYMBOL -> generateClassStub(descriptor as ClassDescriptor)
BinarySymbolData.SymbolKind.PROPERTY_SYMBOL -> generatePropertyStub(descriptor as PropertyDescriptor)
BinarySymbolData.SymbolKind.FUNCTION_SYMBOL -> generateFunctionStub(descriptor as FunctionDescriptor)
BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL -> generateConstructorStub(descriptor as ClassConstructorDescriptor)
BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL -> generateEnumEntryStub(descriptor as ClassDescriptor)
BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL -> generateTypeAliasStub(descriptor as TypeAliasDescriptor)
else -> error("Unexpected type $symbolKind for sig $idSig")
}
}
return declaration.symbol
}
override fun declareIrSymbol(symbol: IrSymbol) {
assert(symbol.isPublicApi || symbol.descriptor.isJavaDescriptor())
if (symbol is IrFieldSymbol) {
declareJavaFieldStub(symbol)
} else {
stubGenerator.generateMemberStub(symbol.descriptor)
}
}
override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns, emptyList())
override val moduleDependencies: Collection<IrModuleDeserializer> = dependencies
}
}
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.generateJsCode
import org.jetbrains.kotlin.ir.backend.js.generateModuleFragment
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
@@ -58,14 +57,15 @@ class JsCoreScriptingCompiler(
if (messageCollector.hasErrors()) return ReplCompileResult.Error("Error while analysis")
}
val files = listOf(snippetKtFile)
val module = analysisResult.moduleDescriptor
val bindingContext = analysisResult.bindingContext
val mangler = JsManglerDesc
val signaturer = IdSignatureDescriptor(mangler)
val psi2ir = Psi2IrTranslator(environment.configuration.languageVersionSettings, signaturer = signaturer)
val psi2irContext = psi2ir.createGeneratorContext(module, bindingContext, symbolTable)
val irModuleFragment = psi2irContext.generateModuleFragment(listOf(snippetKtFile))
val providers = generateTypicalIrProviderList(module, psi2irContext.irBuiltIns, psi2irContext.symbolTable)
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files, providers, null) // TODO: deserializer
val context = JsIrBackendContext(
irModuleFragment.descriptor,
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.emptyLoggingContext
import org.jetbrains.kotlin.ir.backend.js.generateJsCode
@@ -49,10 +50,10 @@ class JsScriptDependencyCompiler(
val signaturer = IdSignatureDescriptor(JsManglerDesc)
val irBuiltIns = IrBuiltIns(builtIns, typeTranslator, signaturer, symbolTable)
val jsLinker = JsIrLinker(emptyLoggingContext, irBuiltIns, symbolTable)
val jsLinker = JsIrLinker(null, emptyLoggingContext, irBuiltIns, symbolTable, null)
val moduleFragment = IrModuleFragmentImpl(moduleDescriptor, irBuiltIns)
val irDependencies = dependencies.map { jsLinker.deserializeFullModule(it) }
val irDependencies = dependencies.map { jsLinker.deserializeFullModule(it, it.kotlinLibrary) }
val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer = jsLinker)
ExternalDependenciesGenerator(symbolTable, irProviders, configuration.languageVersionSettings)