[FIR2IR] Implement tables merging in Fir2Ir classes and SymbolTable

- Pass dependent (usually common code) components to further FIR2IR converters
- Don't reinitialize builtin
This commit is contained in:
Ivan Kochurkin
2022-11-18 19:54:36 +01:00
committed by Space Team
parent 5d273ce839
commit f17e1314f6
20 changed files with 376 additions and 101 deletions
@@ -84,6 +84,7 @@ private fun ModuleCompilerAnalyzedOutput.convertToIr(
irGeneratorExtensions,
kotlinBuiltIns = DefaultBuiltIns.Instance, // TODO: consider passing externally
generateSignatures = true,
dependentComponents = dependentComponents
)
} else {
return Fir2IrConverter.createModuleFragmentWithoutSignatures(
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.containingClassForLocalAttr
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
@@ -39,32 +39,47 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.addToStdlib.runUnless
class Fir2IrClassifierStorage(
private val components: Fir2IrComponents
private val components: Fir2IrComponents,
private val dependentStorages: List<Fir2IrClassifierStorage>
) : Fir2IrComponents by components {
private val firProvider = session.firProvider
private val classCache = mutableMapOf<FirRegularClass, IrClass>()
private val classCache: MutableMap<FirRegularClass, IrClass> = merge { it.classCache }
private val localClassesCreatedOnTheFly = mutableMapOf<FirClass, IrClass>()
private val localClassesCreatedOnTheFly: MutableMap<FirClass, IrClass> = mutableMapOf()
private var processMembersOfClassesOnTheFlyImmediately = false
private val typeAliasCache = mutableMapOf<FirTypeAlias, IrTypeAlias>()
private val typeAliasCache: MutableMap<FirTypeAlias, IrTypeAlias> = mutableMapOf()
private val typeParameterCache = mutableMapOf<FirTypeParameter, IrTypeParameter>()
private val typeParameterCache: MutableMap<FirTypeParameter, IrTypeParameter> = merge { it.typeParameterCache }
private val typeParameterCacheForSetter = mutableMapOf<FirTypeParameter, IrTypeParameter>()
private val typeParameterCacheForSetter: MutableMap<FirTypeParameter, IrTypeParameter> = mutableMapOf()
private val enumEntryCache = mutableMapOf<FirEnumEntry, IrEnumEntry>()
private val enumEntryCache: MutableMap<FirEnumEntry, IrEnumEntry> = merge { it.enumEntryCache }
private val fieldsForContextReceivers = mutableMapOf<IrClass, List<IrField>>()
private val fieldsForContextReceivers: MutableMap<IrClass, List<IrField>> = mutableMapOf()
private val localStorage = Fir2IrLocalStorage()
private val localStorage: Fir2IrLocalStorage = Fir2IrLocalStorage(
dependentStorages.map { it.localStorage }.fold(mutableMapOf()) { result, storage ->
result.putAll(storage.getLocalClassCache())
result
})
private fun <K, V> merge(mapFunc: (Fir2IrClassifierStorage) -> MutableMap<K, V>): MutableMap<K, V> {
return dependentStorages.map { mapFunc(it) }.fold(mutableMapOf()) { result, map ->
result.putAll(map)
result
}
}
private fun FirTypeRef.toIrType(typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT): IrType =
with(typeConverter) { toIrType(typeContext) }
fun preCacheBuiltinClasses() {
// dependentStorages are only actual for MPP scenario
// There is no need to precache them twice since the same library session is used and FIR and IR elements are the same
if (dependentStorages.isNotEmpty()) return
for ((classId, irBuiltinSymbol) in typeConverter.classIdToSymbolMap) {
val firClass = ConeClassLikeLookupTagImpl(classId).toSymbol(session)!!.fir as FirRegularClass
val irClass = irBuiltinSymbol.owner
@@ -438,7 +438,8 @@ class Fir2IrConverter(
specialSymbolProvider: Fir2IrSpecialSymbolProvider,
irGenerationExtensions: Collection<IrGenerationExtension>,
generateSignatures: Boolean,
kotlinBuiltIns: KotlinBuiltIns
kotlinBuiltIns: KotlinBuiltIns,
dependentComponents: List<Fir2IrComponents>
): Fir2IrResult {
if (!generateSignatures) {
return createModuleFragmentWithoutSignatures(
@@ -448,14 +449,14 @@ class Fir2IrConverter(
kotlinBuiltIns
)
}
val signatureComposer = FirBasedSignatureComposer(mangler)
val signatureComposer = FirBasedSignatureComposer(mangler, dependentComposers = dependentComponents.map { it.signatureComposer as FirBasedSignatureComposer })
val wrappedSignaturer = WrappedDescriptorSignatureComposer(signaturer, signatureComposer)
val symbolTable = SymbolTable(wrappedSignaturer, irFactory)
val symbolTable = SymbolTable(wrappedSignaturer, irFactory, dependentTables = dependentComponents.map { it.symbolTable })
return createModuleFragmentWithSymbolTable(
session, scopeSession, firFiles, languageVersionSettings,
fir2IrExtensions, irMangler, irFactory, visibilityConverter,
specialSymbolProvider, irGenerationExtensions, signatureComposer,
symbolTable, generateSignatures = true, kotlinBuiltIns = kotlinBuiltIns
symbolTable, generateSignatures = true, kotlinBuiltIns = kotlinBuiltIns, dependentComponents = dependentComponents
)
}
@@ -473,14 +474,14 @@ class Fir2IrConverter(
irGenerationExtensions: Collection<IrGenerationExtension>,
kotlinBuiltIns: KotlinBuiltIns
): Fir2IrResult {
val signatureComposer = FirBasedSignatureComposer(mangler)
val signatureComposer = FirBasedSignatureComposer(mangler, dependentComposers = dependentComponents.map { it.signatureComposer as FirBasedSignatureComposer })
val signaturer = DescriptorSignatureComposerStub()
val symbolTable = SymbolTable(signaturer, irFactory)
val symbolTable = SymbolTable(signaturer, irFactory, dependentTables = dependentComponents.map { it.symbolTable })
return createModuleFragmentWithSymbolTable(
session, scopeSession, firFiles, languageVersionSettings,
fir2IrExtensions, irMangler, irFactory, visibilityConverter,
specialSymbolProvider, irGenerationExtensions, signatureComposer,
symbolTable, generateSignatures = false, kotlinBuiltIns = kotlinBuiltIns
symbolTable, generateSignatures = false, kotlinBuiltIns = kotlinBuiltIns, dependentComponents = emptyList()
)
}
@@ -498,7 +499,8 @@ class Fir2IrConverter(
signatureComposer: FirBasedSignatureComposer,
symbolTable: SymbolTable,
generateSignatures: Boolean,
kotlinBuiltIns: KotlinBuiltIns
kotlinBuiltIns: KotlinBuiltIns,
dependentComponents: List<Fir2IrComponents>
): Fir2IrResult {
val moduleDescriptor = FirModuleDescriptor(session, kotlinBuiltIns)
val components = Fir2IrComponentsStorage(
@@ -508,19 +510,18 @@ class Fir2IrConverter(
components.converter = converter
val classifierStorage = Fir2IrClassifierStorage(components)
val classifierStorage = Fir2IrClassifierStorage(components, dependentComponents.map { it.classifierStorage })
components.classifierStorage = classifierStorage
components.delegatedMemberGenerator = DelegatedMemberGenerator(components)
val declarationStorage = Fir2IrDeclarationStorage(components, moduleDescriptor)
val declarationStorage = Fir2IrDeclarationStorage(components, moduleDescriptor, dependentComponents.map { it.declarationStorage })
components.declarationStorage = declarationStorage
components.visibilityConverter = visibilityConverter
val typeConverter = Fir2IrTypeConverter(components)
components.typeConverter = typeConverter
val irBuiltIns =
IrBuiltInsOverFir(
components, languageVersionSettings, moduleDescriptor, irMangler,
languageVersionSettings.getFlag(AnalysisFlags.builtInsFromSources) || kotlinBuiltIns !== DefaultBuiltIns.Instance
)
val irBuiltIns = dependentComponents.lastOrNull()?.irBuiltIns ?: IrBuiltInsOverFir(
components, languageVersionSettings, moduleDescriptor, irMangler,
languageVersionSettings.getFlag(AnalysisFlags.builtInsFromSources) || kotlinBuiltIns !== DefaultBuiltIns.Instance
)
components.irBuiltIns = irBuiltIns
val conversionScope = Fir2IrConversionScope()
val fir2irVisitor = Fir2IrVisitor(components, conversionScope)
@@ -64,26 +64,27 @@ import java.util.concurrent.ConcurrentHashMap
@OptIn(ObsoleteDescriptorBasedAPI::class)
class Fir2IrDeclarationStorage(
private val components: Fir2IrComponents,
private val moduleDescriptor: FirModuleDescriptor
private val moduleDescriptor: FirModuleDescriptor,
dependentStorages: List<Fir2IrDeclarationStorage>
) : Fir2IrComponents by components {
private val firProvider = session.firProvider
private val fragmentCache = ConcurrentHashMap<FqName, IrExternalPackageFragment>()
private val fragmentCache: ConcurrentHashMap<FqName, IrExternalPackageFragment> = ConcurrentHashMap()
private val builtInsFragmentCache = ConcurrentHashMap<FqName, IrExternalPackageFragment>()
private val builtInsFragmentCache: ConcurrentHashMap<FqName, IrExternalPackageFragment> = ConcurrentHashMap()
private val fileCache = ConcurrentHashMap<FirFile, IrFile>()
private val fileCache: ConcurrentHashMap<FirFile, IrFile> = ConcurrentHashMap()
private val scriptCache = ConcurrentHashMap<FirScript, IrScript>()
private val scriptCache: ConcurrentHashMap<FirScript, IrScript> = ConcurrentHashMap()
private val functionCache = ConcurrentHashMap<FirFunction, IrSimpleFunction>()
private val functionCache: ConcurrentHashMap<FirFunction, IrSimpleFunction> = merge(dependentStorages) { it.functionCache }
private val constructorCache = ConcurrentHashMap<FirConstructor, IrConstructor>()
private val constructorCache: ConcurrentHashMap<FirConstructor, IrConstructor> = ConcurrentHashMap()
private val initializerCache = ConcurrentHashMap<FirAnonymousInitializer, IrAnonymousInitializer>()
private val initializerCache: ConcurrentHashMap<FirAnonymousInitializer, IrAnonymousInitializer> = ConcurrentHashMap()
private val propertyCache = ConcurrentHashMap<FirProperty, IrProperty>()
private val propertyCache: ConcurrentHashMap<FirProperty, IrProperty> = merge(dependentStorages) { it.propertyCache }
// interface A { /* $1 */ fun foo() }
// interface B : A {
@@ -96,24 +97,40 @@ class Fir2IrDeclarationStorage(
// We've got FIR declarations only for $1 and $3, but we've got a fake override for $2 in IR
// and just to simplify things we create a synthetic FIR for $2, while it can't be referenced from other FIR nodes.
//
// But when we binding overrides for $3, we want it had $2 ad it's overridden,
// But when we're binding overrides for $3, we want it had $2 ad it's overridden,
// so remember that in class B there's a fake override $2 for real $1.
//
// Thus we may obtain it by fakeOverridesInClass[ir(B)][fir(A::foo)] -> fir(B::foo)
private val fakeOverridesInClass = mutableMapOf<IrClass, MutableMap<FirCallableDeclaration, FirCallableDeclaration>>()
// Thus, we may obtain it by fakeOverridesInClass[ir(B)][fir(A::foo)] -> fir(B::foo)
private val fakeOverridesInClass: MutableMap<IrClass, MutableMap<FirCallableDeclaration, FirCallableDeclaration>> =
dependentStorages.map { it.fakeOverridesInClass }.fold(mutableMapOf()) { result, map ->
// Note: merge is necessary here, because sometimes (see testFakeOverridesInPlatformModule)
// we have to match fake override in platform class with overridden fake overrides in common class
result.putAll(map)
result
}
// For pure fields (from Java) only
private val fieldToPropertyCache = ConcurrentHashMap<Pair<FirField, IrDeclarationParent>, IrProperty>()
private val fieldToPropertyCache: ConcurrentHashMap<Pair<FirField, IrDeclarationParent>, IrProperty> = ConcurrentHashMap()
private val delegatedReverseCache = ConcurrentHashMap<IrDeclaration, FirDeclaration>()
private val delegatedReverseCache: ConcurrentHashMap<IrDeclaration, FirDeclaration> = ConcurrentHashMap()
private val fieldCache = ConcurrentHashMap<FirField, IrField>()
private val fieldCache: ConcurrentHashMap<FirField, IrField> = ConcurrentHashMap()
private data class FieldStaticOverrideKey(val lookupTag: ConeClassLikeLookupTag, val name: Name)
private val fieldStaticOverrideCache = ConcurrentHashMap<FieldStaticOverrideKey, IrField>()
private val fieldStaticOverrideCache: ConcurrentHashMap<FieldStaticOverrideKey, IrField> = ConcurrentHashMap()
private val localStorage by threadLocal { Fir2IrLocalStorage() }
private val localStorage: Fir2IrLocalStorage by threadLocal { Fir2IrLocalStorage() }
private fun <K, V> merge(
dependentStorages: List<Fir2IrDeclarationStorage>,
mapFunc: (Fir2IrDeclarationStorage) -> ConcurrentHashMap<K, V>
): ConcurrentHashMap<K, V> {
return dependentStorages.map { mapFunc(it) }.fold(ConcurrentHashMap()) { result, map ->
result.putAll(map)
result
}
}
private fun areCompatible(firFunction: FirFunction, irFunction: IrFunction): Boolean {
if (firFunction is FirSimpleFunction && irFunction is IrSimpleFunction) {
@@ -8,11 +8,13 @@ package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.ir.declarations.*
class Fir2IrLocalStorage {
class Fir2IrLocalStorage(existingClassCache: MutableMap<FirClass, IrClass>? = null) {
private val cacheStack = mutableListOf<Fir2IrScopeCache>()
private val localClassCache = mutableMapOf<FirClass, IrClass>()
private val localClassCache = existingClassCache ?: mutableMapOf()
fun getLocalClassCache() = localClassCache
fun enterCallable() {
cacheStack += Fir2IrScopeCache()
@@ -42,12 +42,9 @@ import org.jetbrains.kotlin.name.Name
* methods and properties in the super-interface, and creates corresponding members in the subclass.
* TODO: generic super interface types and generic delegated members.
*/
class DelegatedMemberGenerator(
private val components: Fir2IrComponents
) : Fir2IrComponents by components {
private val baseFunctionSymbols = mutableMapOf<IrFunction, List<FirNamedFunctionSymbol>>()
private val basePropertySymbols = mutableMapOf<IrProperty, List<FirPropertySymbol>>()
class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2IrComponents by components {
private val baseFunctionSymbols: MutableMap<IrFunction, List<FirNamedFunctionSymbol>> = mutableMapOf()
private val basePropertySymbols: MutableMap<IrProperty, List<FirPropertySymbol>> = mutableMapOf()
private data class DeclarationBodyInfo(
val declaration: IrDeclaration,
@@ -6,10 +6,7 @@
package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.Fir2IrConversionScope
import org.jetbrains.kotlin.fir.backend.Fir2IrDeclarationStorage
import org.jetbrains.kotlin.fir.backend.unwrapSubstitutionAndIntersectionOverrides
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.resolve.defaultType
@@ -18,10 +15,7 @@ import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.symbols.impl.isStatic
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.ir.declarations.*
@@ -38,10 +32,9 @@ class FakeOverrideGenerator(
private val components: Fir2IrComponents,
private val conversionScope: Fir2IrConversionScope
) : Fir2IrComponents by components {
private val baseFunctionSymbols = mutableMapOf<IrFunction, List<FirNamedFunctionSymbol>>()
private val basePropertySymbols = mutableMapOf<IrProperty, List<FirPropertySymbol>>()
private val baseStaticFieldSymbols = mutableMapOf<IrField, List<FirFieldSymbol>>()
private val baseFunctionSymbols: MutableMap<IrFunction, List<FirNamedFunctionSymbol>> = mutableMapOf()
private val basePropertySymbols: MutableMap<IrProperty, List<FirPropertySymbol>> = mutableMapOf()
private val baseStaticFieldSymbols: MutableMap<IrField, List<FirFieldSymbol>> = mutableMapOf()
private fun IrSimpleFunction.withFunction(f: IrSimpleFunction.() -> Unit): IrSimpleFunction {
return conversionScope.withFunction(this, f)
@@ -8,32 +8,28 @@ package org.jetbrains.kotlin.fir.lazy
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.fir.backend.ConversionTypeContext
import org.jetbrains.kotlin.fir.backend.ConversionTypeOrigin
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.toIrConst
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.Fir2IrPropertySymbol
import org.jetbrains.kotlin.fir.symbols.Fir2IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.types.IrErrorType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.types.IrErrorType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.isComposite
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.NameUtils
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
class Fir2IrLazyProperty(
components: Fir2IrComponents,
@@ -166,6 +162,7 @@ class Fir2IrLazyProperty(
containingClass?.symbol?.toLookupTag(),
forceTopLevelPrivate = symbol.signature.isComposite()
)!!
symbolTable.referenceSimpleFunctionIfAny(signature)?.let { if (it.isBound) return@lazyVar it.owner }
symbolTable.declareSimpleFunction(signature, symbolFactory = { Fir2IrSimpleFunctionSymbol(signature) }) { symbol ->
Fir2IrLazyPropertyAccessor(
components, startOffset, endOffset,
@@ -200,6 +197,7 @@ class Fir2IrLazyProperty(
containingClass?.symbol?.toLookupTag(),
forceTopLevelPrivate = symbol.signature.isComposite()
)!!
symbolTable.referenceSimpleFunctionIfAny(signature)?.let { if (it.isBound) return@lazyVar it.owner }
symbolTable.declareSimpleFunction(signature, symbolFactory = { Fir2IrSimpleFunctionSymbol(signature) }) { symbol ->
Fir2IrLazyPropertyAccessor(
components, startOffset, endOffset,
@@ -23,7 +23,10 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
// @NoMutableState -- we'll restore this annotation once we get rid of withFileSignature().
class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignatureComposer {
class FirBasedSignatureComposer(
override val mangler: FirMangler,
dependentComposers: List<FirBasedSignatureComposer> = emptyList()
) : Fir2IrSignatureComposer {
private var fileSignature: IdSignature.FileSignature? = null
override fun withFileSignature(sig: IdSignature.FileSignature, body: () -> Unit) {
@@ -34,7 +37,11 @@ class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignat
private data class FirDeclarationWithParentId(val declaration: FirDeclaration, val classId: ClassId?)
private val signatureCache = mutableMapOf<FirDeclarationWithParentId, IdSignature.CommonSignature>()
private val signatureCache: MutableMap<FirDeclarationWithParentId, IdSignature.CommonSignature> =
dependentComposers.map { it.signatureCache }.fold(mutableMapOf()) { result, map ->
result.putAll(map)
result
}
inner class SignatureBuilder : FirVisitor<Unit, Any?>() {
var hashId: Long? = null
@@ -32695,6 +32695,72 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
public void testAllFilesPresentInMultiModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/multiplatform/multiModule"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("correctParentForTypeParameter.kt")
public void testCorrectParentForTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/correctParentForTypeParameter.kt");
}
@Test
@TestMetadata("enumEntryNameCall.kt")
public void testEnumEntryNameCall() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/enumEntryNameCall.kt");
}
@Test
@TestMetadata("expectActualCallableReference.kt")
public void testExpectActualCallableReference() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualCallableReference.kt");
}
@Test
@TestMetadata("expectActualDifferentPackages.kt")
public void testExpectActualDifferentPackages() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualDifferentPackages.kt");
}
@Test
@TestMetadata("expectActualFakeOverrides.kt")
public void testExpectActualFakeOverrides() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualFakeOverrides.kt");
}
@Test
@TestMetadata("expectActualMultiCommon.kt")
public void testExpectActualMultiCommon() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualMultiCommon.kt");
}
@Test
@TestMetadata("expectActualOverloads.kt")
public void testExpectActualOverloads() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualOverloads.kt");
}
@Test
@TestMetadata("expectActualSimple.kt")
public void testExpectActualSimple() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualSimple.kt");
}
@Test
@TestMetadata("expectActualTypealias.kt")
public void testExpectActualTypealias() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualTypealias.kt");
}
@Test
@TestMetadata("kt-51753-1.kt")
public void testKt_51753_1() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/kt-51753-1.kt");
}
@Test
@TestMetadata("kt-51753-2.kt")
public void testKt_51753_2() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/kt-51753-2.kt");
}
}
}
@@ -84,7 +84,8 @@ interface ReferenceSymbolTable {
open class SymbolTable(
val signaturer: IdSignatureComposer,
val irFactory: IrFactory,
val nameProvider: NameProvider = NameProvider.DEFAULT
val nameProvider: NameProvider = NameProvider.DEFAULT,
val dependentTables: List<SymbolTable> = emptyList(),
) : ReferenceSymbolTable {
val lock = IrLock()
@@ -212,10 +213,10 @@ open class SymbolTable(
}
}
private open inner class FlatSymbolTable<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> :
SymbolTableBase<D, B, S>(lock) {
val descriptorToSymbol = hashMapOf<D, S>()
val idSigToSymbol = hashMapOf<IdSignature, S>()
private open inner class FlatSymbolTable<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>>(
val descriptorToSymbol: HashMap<D, S> = hashMapOf(),
val idSigToSymbol: HashMap<IdSignature, S> = hashMapOf()
) : SymbolTableBase<D, B, S>(lock) {
override fun signature(descriptor: D): IdSignature? =
signaturer.composeSignature(descriptor)
@@ -244,11 +245,17 @@ open class SymbolTable(
}
}
private inner class EnumEntrySymbolTable : FlatSymbolTable<ClassDescriptor, IrEnumEntry, IrEnumEntrySymbol>() {
private inner class EnumEntrySymbolTable(
descriptorToSymbol: HashMap<ClassDescriptor, IrEnumEntrySymbol> = hashMapOf(),
idSigToSymbol: HashMap<IdSignature, IrEnumEntrySymbol> = hashMapOf()
) : FlatSymbolTable<ClassDescriptor, IrEnumEntry, IrEnumEntrySymbol>(descriptorToSymbol, idSigToSymbol) {
override fun signature(descriptor: ClassDescriptor): IdSignature? = signaturer.composeEnumEntrySignature(descriptor)
}
private inner class FieldSymbolTable : FlatSymbolTable<PropertyDescriptor, IrField, IrFieldSymbol>() {
private inner class FieldSymbolTable(
descriptorToSymbol: HashMap<PropertyDescriptor, IrFieldSymbol> = hashMapOf(),
idSigToSymbol: HashMap<IdSignature, IrFieldSymbol> = hashMapOf()
) : FlatSymbolTable<PropertyDescriptor, IrField, IrFieldSymbol>(descriptorToSymbol, idSigToSymbol) {
override fun signature(descriptor: PropertyDescriptor): IdSignature? = signaturer.composeFieldSignature(descriptor)
}
@@ -365,18 +372,32 @@ open class SymbolTable(
currentScope?.dump() ?: "<none>"
}
private val externalPackageFragmentTable =
FlatSymbolTable<PackageFragmentDescriptor, IrExternalPackageFragment, IrExternalPackageFragmentSymbol>()
private val scriptSymbolTable = FlatSymbolTable<ScriptDescriptor, IrScript, IrScriptSymbol>()
private val classSymbolTable = FlatSymbolTable<ClassDescriptor, IrClass, IrClassSymbol>()
private val constructorSymbolTable = FlatSymbolTable<ClassConstructorDescriptor, IrConstructor, IrConstructorSymbol>()
private val enumEntrySymbolTable = EnumEntrySymbolTable()
private val fieldSymbolTable = FieldSymbolTable()
private val simpleFunctionSymbolTable = FlatSymbolTable<FunctionDescriptor, IrSimpleFunction, IrSimpleFunctionSymbol>()
private val propertySymbolTable = FlatSymbolTable<PropertyDescriptor, IrProperty, IrPropertySymbol>()
private val typeAliasSymbolTable = FlatSymbolTable<TypeAliasDescriptor, IrTypeAlias, IrTypeAliasSymbol>()
private val externalPackageFragmentTable: FlatSymbolTable<PackageFragmentDescriptor, IrExternalPackageFragment, IrExternalPackageFragmentSymbol> =
mergeFlatTables(dependentTables) { it.externalPackageFragmentTable }
private val scriptSymbolTable: FlatSymbolTable<ScriptDescriptor, IrScript, IrScriptSymbol> =
mergeFlatTables(dependentTables) { it.scriptSymbolTable }
private val classSymbolTable: FlatSymbolTable<ClassDescriptor, IrClass, IrClassSymbol> =
mergeFlatTables(dependentTables) { it.classSymbolTable }
private val constructorSymbolTable: FlatSymbolTable<ClassConstructorDescriptor, IrConstructor, IrConstructorSymbol> =
mergeFlatTables(dependentTables) { it.constructorSymbolTable }
private val enumEntrySymbolTable: EnumEntrySymbolTable = run {
val (descriptorToSymbol, idSigToSymbol) = mergeTables(dependentTables) { it.enumEntrySymbolTable }
EnumEntrySymbolTable(descriptorToSymbol, idSigToSymbol)
}
private val fieldSymbolTable: FieldSymbolTable = run {
val (descriptorToSymbol, idSigToSymbol) = mergeTables(dependentTables) { it.fieldSymbolTable }
FieldSymbolTable(descriptorToSymbol, idSigToSymbol)
}
private val simpleFunctionSymbolTable: FlatSymbolTable<FunctionDescriptor, IrSimpleFunction, IrSimpleFunctionSymbol> =
mergeFlatTables(dependentTables) { it.simpleFunctionSymbolTable }
private val propertySymbolTable: FlatSymbolTable<PropertyDescriptor, IrProperty, IrPropertySymbol> =
mergeFlatTables(dependentTables) { it.propertySymbolTable }
private val typeAliasSymbolTable: FlatSymbolTable<TypeAliasDescriptor, IrTypeAlias, IrTypeAliasSymbol> =
mergeFlatTables(dependentTables) { it.typeAliasSymbolTable }
private val globalTypeParameterSymbolTable: FlatSymbolTable<TypeParameterDescriptor, IrTypeParameter, IrTypeParameterSymbol> =
mergeFlatTables(dependentTables) { it.globalTypeParameterSymbolTable }
private val globalTypeParameterSymbolTable = FlatSymbolTable<TypeParameterDescriptor, IrTypeParameter, IrTypeParameterSymbol>()
private val scopedTypeParameterSymbolTable by threadLocal {
ScopedSymbolTable<TypeParameterDescriptor, IrTypeParameter, IrTypeParameterSymbol>()
}
@@ -393,6 +414,28 @@ open class SymbolTable(
listOf(valueParameterSymbolTable, variableSymbolTable, scopedTypeParameterSymbolTable, localDelegatedPropertySymbolTable)
}
private fun <D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> mergeFlatTables(
dependentTables: List<SymbolTable>,
mapFunc: (SymbolTable) -> FlatSymbolTable<D, B, S>
): FlatSymbolTable<D, B, S> {
val (descriptorToSymbol, idSigToSymbol) = mergeTables(dependentTables, mapFunc)
return FlatSymbolTable(descriptorToSymbol, idSigToSymbol)
}
private fun <D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> mergeTables(
dependentTables: List<SymbolTable>,
mapFunc: (SymbolTable) -> FlatSymbolTable<D, B, S>
): Pair<HashMap<D, S>, HashMap<IdSignature, S>> {
val descriptorToSymbol = hashMapOf<D, S>()
val idSigToSymbol = hashMapOf<IdSignature, S>()
for (dependentTable in dependentTables) {
val flatSymbolTable = mapFunc(dependentTable)
descriptorToSymbol.putAll(flatSymbolTable.descriptorToSymbol)
idSigToSymbol.putAll(flatSymbolTable.idSigToSymbol)
}
return Pair(descriptorToSymbol, idSigToSymbol)
}
@ObsoleteDescriptorBasedAPI
fun referenceExternalPackageFragment(descriptor: PackageFragmentDescriptor) =
externalPackageFragmentTable.referenced(descriptor) { IrExternalPackageFragmentSymbolImpl(descriptor) }
@@ -0,0 +1,14 @@
// TARGET_BACKEND: JVM
// !LANGUAGE: +MultiPlatformProjects
// MODULE: common
// TARGET_PLATFORM: Common
// FILE: common.kt
enum class Base { OK }
// MODULE: jvm()()(common)
// TARGET_PLATFORM: JVM
// FILE: main.kt
fun box() = Base.OK.name
@@ -31693,6 +31693,30 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInMultiModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/multiplatform/multiModule"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@Test
@TestMetadata("correctParentForTypeParameter.kt")
public void testCorrectParentForTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/correctParentForTypeParameter.kt");
}
@Test
@TestMetadata("enumEntryNameCall.kt")
public void testEnumEntryNameCall() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/enumEntryNameCall.kt");
}
@Test
@TestMetadata("expectActualMultiCommon.kt")
public void testExpectActualMultiCommon() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualMultiCommon.kt");
}
@Test
@TestMetadata("expectActualSimple.kt")
public void testExpectActualSimple() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualSimple.kt");
}
}
}
@@ -32695,6 +32695,72 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
public void testAllFilesPresentInMultiModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/multiplatform/multiModule"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("correctParentForTypeParameter.kt")
public void testCorrectParentForTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/correctParentForTypeParameter.kt");
}
@Test
@TestMetadata("enumEntryNameCall.kt")
public void testEnumEntryNameCall() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/enumEntryNameCall.kt");
}
@Test
@TestMetadata("expectActualCallableReference.kt")
public void testExpectActualCallableReference() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualCallableReference.kt");
}
@Test
@TestMetadata("expectActualDifferentPackages.kt")
public void testExpectActualDifferentPackages() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualDifferentPackages.kt");
}
@Test
@TestMetadata("expectActualFakeOverrides.kt")
public void testExpectActualFakeOverrides() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualFakeOverrides.kt");
}
@Test
@TestMetadata("expectActualMultiCommon.kt")
public void testExpectActualMultiCommon() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualMultiCommon.kt");
}
@Test
@TestMetadata("expectActualOverloads.kt")
public void testExpectActualOverloads() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualOverloads.kt");
}
@Test
@TestMetadata("expectActualSimple.kt")
public void testExpectActualSimple() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualSimple.kt");
}
@Test
@TestMetadata("expectActualTypealias.kt")
public void testExpectActualTypealias() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualTypealias.kt");
}
@Test
@TestMetadata("kt-51753-1.kt")
public void testKt_51753_1() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/kt-51753-1.kt");
}
@Test
@TestMetadata("kt-51753-2.kt")
public void testKt_51753_2() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/kt-51753-2.kt");
}
}
}
@@ -126,7 +126,8 @@ fun AbstractFirAnalyzerFacade.convertToJsIr(
Fir2IrJvmSpecialAnnotationSymbolProvider(), // TODO: replace with appropriate (probably empty) implementation
irGeneratorExtensions,
generateSignatures = false,
kotlinBuiltIns = builtIns ?: DefaultBuiltIns.Instance // TODO: consider passing externally
kotlinBuiltIns = builtIns ?: DefaultBuiltIns.Instance, // TODO: consider passing externally,
dependentComponents = emptyList()
).also {
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = dependencies }
}
@@ -68,7 +68,14 @@ class Fir2IrResultsConverter(
lateinit var mainIrPart: JvmIrCodegenFactory.JvmIrBackendInput
for ((index, firOutputPart) in inputArtifact.partsForDependsOnModules.withIndex()) {
val (irModuleFragment, components, pluginContext) = firOutputPart.firAnalyzerFacade.convertToIr(fir2IrExtensions)
val dependentComponents = mutableListOf<Fir2IrComponents>()
if (isMppSupported) {
for (dependency in firOutputPart.module.dependsOnDependencies) {
dependentComponents.add(componentsMap[dependency.moduleName]!!)
}
}
val (irModuleFragment, components, pluginContext) = firOutputPart.firAnalyzerFacade.convertToIr(fir2IrExtensions, dependentComponents)
componentsMap[firOutputPart.module.name] = components
val irPart = JvmIrCodegenFactory.JvmIrBackendInput(
@@ -123,7 +123,7 @@ object GenerationUtils {
generateSignatures = false
)
val fir2IrExtensions = JvmFir2IrExtensions(configuration, JvmIrDeserializerImpl(), JvmIrMangler)
val (moduleFragment, components, pluginContext) = firAnalyzerFacade.convertToIr(fir2IrExtensions)
val (moduleFragment, components, pluginContext) = firAnalyzerFacade.convertToIr(fir2IrExtensions, dependentComponents = emptyList())
val dummyBindingContext = NoScopeRecordCliBindingTrace().bindingContext
val codegenFactory = JvmIrCodegenFactory(
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.Fir2IrConverter
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
import org.jetbrains.kotlin.fir.backend.Fir2IrResult
@@ -37,7 +38,7 @@ abstract class AbstractFirAnalyzerFacade {
abstract fun runResolution(): List<FirFile>
abstract fun convertToIr(fir2IrExtensions: Fir2IrExtensions): Fir2IrResult
abstract fun convertToIr(fir2IrExtensions: Fir2IrExtensions, dependentComponents: List<Fir2IrComponents>): Fir2IrResult
}
class FirAnalyzerFacade(
@@ -103,7 +104,7 @@ class FirAnalyzerFacade(
return collectedDiagnostics!!
}
override fun convertToIr(fir2IrExtensions: Fir2IrExtensions): Fir2IrResult {
override fun convertToIr(fir2IrExtensions: Fir2IrExtensions, dependentComponents: List<Fir2IrComponents>): Fir2IrResult {
if (_scopeSession == null) runResolution()
val mangler = JvmDescriptorMangler(null)
val signaturer = JvmIdSignatureDescriptor(mangler)
@@ -117,7 +118,8 @@ class FirAnalyzerFacade(
Fir2IrJvmSpecialAnnotationSymbolProvider(),
irGeneratorExtensions,
generateSignatures,
kotlinBuiltIns = DefaultBuiltIns.Instance // TODO: consider passing externally
kotlinBuiltIns = DefaultBuiltIns.Instance, // TODO: consider passing externally,
dependentComponents = dependentComponents
)
}
}
@@ -26977,6 +26977,26 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
public void testAllFilesPresentInMultiModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/multiplatform/multiModule"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("correctParentForTypeParameter.kt")
public void testCorrectParentForTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/correctParentForTypeParameter.kt");
}
@TestMetadata("enumEntryNameCall.kt")
public void testEnumEntryNameCall() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/enumEntryNameCall.kt");
}
@TestMetadata("expectActualMultiCommon.kt")
public void testExpectActualMultiCommon() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualMultiCommon.kt");
}
@TestMetadata("expectActualSimple.kt")
public void testExpectActualSimple() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/multiModule/expectActualSimple.kt");
}
}
}
@@ -78,7 +78,8 @@ internal fun PhaseContext.fir2Ir(
Fir2IrJvmSpecialAnnotationSymbolProvider(), // TODO: replace with appropriate (probably empty) implementation
IrGenerationExtension.getInstances(config.project),
generateSignatures = false,
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance // TODO: consider passing externally
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance, // TODO: consider passing externally
dependentComponents = emptyList()
).also {
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = librariesDescriptors }
}