[FIR2IR] Introduce staged transformation (first step)

Now FE IR -> BE IR transformation is performed in multiple stages
controller by Fir2IrConverter. Stages are
 * files & classes registration
 * supertypes & type parameters handling
 * functions & properties signature generation
 * body generation

After each step we have guarantee (with exception of local classes &
type inference combination, and external symbols) that required symbols
(class/function/property/variable/type parameter)
are already bound to real declarations and have correct parents.

This commit also fixes incorrect parents for local classes
This commit is contained in:
Mikhail Glukhikh
2020-03-11 15:35:14 +03:00
parent a9f7ff254b
commit 20c4a7b244
95 changed files with 436 additions and 394 deletions
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiCompiledElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
@@ -216,3 +217,6 @@ internal fun FirReference.statementOrigin(): IrStatementOrigin? {
else -> null
}
}
fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
@@ -17,8 +17,6 @@ class Fir2IrCallableCache {
private val variableCache = mutableMapOf<FirVariable<*>, IrVariable>()
private val localClassCache = mutableMapOf<FirClass<*>, IrClass>()
private val localFunctionCache = mutableMapOf<FirFunction<*>, IrSimpleFunction>()
fun getParameter(parameter: FirValueParameter): IrValueParameter? = parameterCache[parameter]
@@ -33,13 +31,6 @@ class Fir2IrCallableCache {
variableCache[firVariable] = irVariable
}
fun getLocalClass(localClass: FirClass<*>): IrClass? = localClassCache[localClass]
fun putLocalClass(localClass: FirClass<*>, irClass: IrClass) {
require(localClass !is FirRegularClass || localClass.visibility == Visibilities.LOCAL)
localClassCache[localClass] = irClass
}
fun getLocalFunction(localFunction: FirFunction<*>): IrSimpleFunction? = localFunctionCache[localFunction]
fun putLocalFunction(localFunction: FirFunction<*>, irFunction: IrSimpleFunction) {
@@ -50,7 +41,6 @@ class Fir2IrCallableCache {
fun clear() {
parameterCache.clear()
variableCache.clear()
localClassCache.clear()
localFunctionCache.clear()
}
}
@@ -20,6 +20,8 @@ class Fir2IrConversionScope {
return parent
}
fun parentFromStack(): IrDeclarationParent = parentStack.last()
fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T {
declaration.parent = parentStack.last()
return declaration
@@ -7,58 +7,207 @@ package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
object Fir2IrConverter {
class Fir2IrConverter(
private val moduleDescriptor: FirModuleDescriptor,
private val sourceManager: PsiSourceManager,
private val declarationStorage: Fir2IrDeclarationStorage
) {
fun createModuleFragment(
session: FirSession,
firFiles: List<FirFile>,
languageVersionSettings: LanguageVersionSettings,
fakeOverrideMode: FakeOverrideMode = FakeOverrideMode.NORMAL,
signaturer: IdSignatureComposer
): Fir2IrResult {
val moduleDescriptor = FirModuleDescriptor(session)
val symbolTable = SymbolTable(signaturer)
val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable)
val typeTranslator = TypeTranslator(symbolTable, languageVersionSettings, moduleDescriptor.builtIns)
constantValueGenerator.typeTranslator = typeTranslator
typeTranslator.constantValueGenerator = constantValueGenerator
val builtIns = IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, signaturer, symbolTable)
val sourceManager = PsiSourceManager()
val fir2irVisitor = Fir2IrVisitor(session, moduleDescriptor, symbolTable, sourceManager, builtIns, fakeOverrideMode)
val irFiles = mutableListOf<IrFile>()
for (firFile in firFiles) {
fir2irVisitor.registerFile(firFile)
}
for (firFile in firFiles) {
val irFile = firFile.accept(fir2irVisitor, null) as IrFile
val fileEntry = sourceManager.getOrCreateFileEntry(firFile.psi as KtFile)
sourceManager.putFileEntry(irFile, fileEntry)
irFiles += irFile
}
val irModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns, irFiles)
generateUnboundSymbolsAsDependencies(irModuleFragment, symbolTable, builtIns)
return Fir2IrResult(irModuleFragment, symbolTable, sourceManager)
fun processLocalClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent) {
val irClass = registerClassAndNestedClasses(regularClass, parent)
processClassAndNestedClassHeaders(regularClass)
processClassMembers(regularClass, irClass)
}
private fun generateUnboundSymbolsAsDependencies(
irModule: IrModuleFragment,
symbolTable: SymbolTable,
builtIns: IrBuiltIns
) {
// TODO: provide StubGeneratorExtensions for correct lazy stub IR generation on JVM
ExternalDependenciesGenerator(symbolTable, generateTypicalIrProviderList(irModule.descriptor, builtIns, symbolTable))
.generateUnboundSymbolsAsDependencies()
fun processRegisteredLocalClassAndNestedClasses(regularClass: FirRegularClass, irClass: IrClass) {
regularClass.declarations.forEach {
if (it is FirRegularClass) {
registerClassAndNestedClasses(it, irClass)
}
}
processClassAndNestedClassHeaders(regularClass)
processClassMembers(regularClass, irClass)
}
fun registerFileAndClasses(file: FirFile) {
val irFile = IrFileImpl(
sourceManager.getOrCreateFileEntry(file.psi as KtFile),
moduleDescriptor.getPackage(file.packageFqName).fragments.first()
)
declarationStorage.registerFile(file, irFile)
file.declarations.forEach {
if (it is FirRegularClass) {
registerClassAndNestedClasses(it, irFile)
}
}
}
fun processClassHeaders(file: FirFile) {
file.declarations.forEach {
if (it is FirRegularClass) {
processClassAndNestedClassHeaders(it)
}
}
}
fun processFileAndClassMembers(file: FirFile) {
val irFile = declarationStorage.getIrFile(file)
for (declaration in file.declarations) {
val irDeclaration = processMemberDeclaration(declaration, irFile) ?: continue
irFile.declarations += irDeclaration
}
}
fun processAnonymousObjectMembers(
anonymousObject: FirAnonymousObject,
irClass: IrClass = declarationStorage.getCachedIrClass(anonymousObject)!!
): IrClass {
anonymousObject.getPrimaryConstructorIfAny()?.let {
irClass.declarations += declarationStorage.createIrConstructor(it, irClass)
}
for (declaration in anonymousObject.declarations) {
if (declaration is FirRegularClass) {
registerClassAndNestedClasses(declaration, irClass)
processClassAndNestedClassHeaders(declaration)
}
val irDeclaration = processMemberDeclaration(declaration, irClass) ?: continue
irClass.declarations += irDeclaration
}
return irClass
}
private fun processClassMembers(
regularClass: FirRegularClass,
irClass: IrClass = declarationStorage.getCachedIrClass(regularClass)!!
): IrClass {
regularClass.getPrimaryConstructorIfAny()?.let {
irClass.declarations += declarationStorage.createIrConstructor(it, irClass)
}
for (declaration in regularClass.declarations) {
val irDeclaration = processMemberDeclaration(declaration, irClass) ?: continue
irClass.declarations += irDeclaration
}
return irClass
}
private fun registerClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
val irClass = declarationStorage.registerIrClass(regularClass, parent)
regularClass.declarations.forEach {
if (it is FirRegularClass) {
registerClassAndNestedClasses(it, irClass)
}
}
return irClass
}
private fun processClassAndNestedClassHeaders(regularClass: FirRegularClass) {
declarationStorage.processClassHeader(regularClass)
regularClass.declarations.forEach {
if (it is FirRegularClass) {
processClassAndNestedClassHeaders(it)
}
}
}
private fun processMemberDeclaration(declaration: FirDeclaration, parent: IrDeclarationParent): IrDeclaration? {
return when (declaration) {
is FirRegularClass -> {
processClassMembers(declaration)
}
is FirSimpleFunction -> {
declarationStorage.createIrFunction(declaration, parent)
}
is FirProperty -> {
declarationStorage.createIrProperty(declaration, parent)
}
is FirConstructor -> if (!declaration.isPrimary) {
declarationStorage.createIrConstructor(declaration, parent as IrClass)
} else {
null
}
is FirEnumEntry -> {
declarationStorage.createIrEnumEntry(declaration, parent as IrClass)
}
is FirAnonymousInitializer -> {
declarationStorage.createIrAnonymousInitializer(declaration, parent as IrClass)
}
is FirTypeAlias -> {
// DO NOTHING
null
}
else -> {
throw AssertionError("Unexpected member: ${declaration::class}")
}
}
}
companion object {
fun createModuleFragment(
session: FirSession,
firFiles: List<FirFile>,
languageVersionSettings: LanguageVersionSettings,
fakeOverrideMode: FakeOverrideMode = FakeOverrideMode.NORMAL,
signaturer: IdSignatureComposer
): Fir2IrResult {
val moduleDescriptor = FirModuleDescriptor(session)
val symbolTable = SymbolTable(signaturer)
val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable)
val typeTranslator = TypeTranslator(symbolTable, languageVersionSettings, moduleDescriptor.builtIns)
constantValueGenerator.typeTranslator = typeTranslator
typeTranslator.constantValueGenerator = constantValueGenerator
val builtIns = IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, signaturer, symbolTable)
val sourceManager = PsiSourceManager()
val declarationStorage = Fir2IrDeclarationStorage(session, symbolTable, moduleDescriptor)
val typeConverter = Fir2IrTypeConverter(session, declarationStorage, builtIns)
declarationStorage.typeConverter = typeConverter
typeConverter.initBuiltinTypes()
val irFiles = mutableListOf<IrFile>()
val converter = Fir2IrConverter(moduleDescriptor, sourceManager, declarationStorage)
for (firFile in firFiles) {
converter.registerFileAndClasses(firFile)
}
for (firFile in firFiles) {
converter.processClassHeaders(firFile)
}
for (firFile in firFiles) {
converter.processFileAndClassMembers(firFile)
}
val fir2irVisitor = Fir2IrVisitor(
session, symbolTable, declarationStorage, converter, typeConverter, builtIns, fakeOverrideMode
)
for (firFile in firFiles) {
val irFile = firFile.accept(fir2irVisitor, null) as IrFile
val fileEntry = sourceManager.getOrCreateFileEntry(firFile.psi as KtFile)
sourceManager.putFileEntry(irFile, fileEntry)
irFiles += irFile
}
val irModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns, irFiles)
generateUnboundSymbolsAsDependencies(irModuleFragment, symbolTable, builtIns)
return Fir2IrResult(irModuleFragment, symbolTable, sourceManager)
}
private fun generateUnboundSymbolsAsDependencies(
irModule: IrModuleFragment,
symbolTable: SymbolTable,
builtIns: IrBuiltIns
) {
// TODO: provide StubGeneratorExtensions for correct lazy stub IR generation on JVM
ExternalDependenciesGenerator(symbolTable, generateTypicalIrProviderList(irModule.descriptor, builtIns, symbolTable))
.generateUnboundSymbolsAsDependencies()
}
}
}
@@ -66,6 +66,8 @@ class Fir2IrDeclarationStorage(
private val constructorCache = mutableMapOf<FirConstructor, IrConstructor>()
private val initializerCache = mutableMapOf<FirAnonymousInitializer, IrAnonymousInitializer>()
private val propertyCache = mutableMapOf<FirProperty, IrProperty>()
private val fieldCache = mutableMapOf<FirField, IrField>()
@@ -98,7 +100,8 @@ class Fir2IrDeclarationStorage(
fun leaveScope(descriptor: DeclarationDescriptor) {
if (descriptor is WrappedSimpleFunctionDescriptor ||
descriptor is WrappedClassConstructorDescriptor ||
descriptor is WrappedPropertyDescriptor
descriptor is WrappedPropertyDescriptor ||
descriptor is WrappedEnumEntryDescriptor
) {
localStorage.leaveCallable()
}
@@ -189,14 +192,18 @@ class Fir2IrDeclarationStorage(
irClass.declarations += when (declaration) {
is FirSimpleFunction -> {
processedNames += declaration.name
getIrFunction(declaration, irClass)
createIrFunction(declaration, irClass)
}
is FirProperty -> {
processedNames += declaration.name
getIrProperty(declaration, irClass)
createIrProperty(declaration, irClass)
}
is FirConstructor -> {
createIrConstructor(declaration, irClass)
}
is FirRegularClass -> {
createIrClass(declaration, irClass)
}
is FirConstructor -> getIrConstructor(declaration, irClass)
is FirRegularClass -> getIrClass(declaration, exactlySourceClass = false)
else -> continue
}
}
@@ -210,14 +217,14 @@ class Fir2IrDeclarationStorage(
if (functionSymbol is FirNamedFunctionSymbol) {
val fakeOverrideSymbol =
FirClassSubstitutionScope.createFakeOverrideFunction(session, functionSymbol.fir, functionSymbol)
irClass.declarations += getIrFunction(fakeOverrideSymbol.fir, irClass)
irClass.declarations += createIrFunction(fakeOverrideSymbol.fir, irClass)
}
}
scope.processPropertiesByName(name) { propertySymbol ->
if (propertySymbol is FirPropertySymbol) {
val fakeOverrideSymbol =
FirClassSubstitutionScope.createFakeOverrideProperty(session, propertySymbol.fir, propertySymbol)
irClass.declarations += getIrProperty(fakeOverrideSymbol.fir, irClass)
irClass.declarations += createIrProperty(fakeOverrideSymbol.fir, irClass)
}
}
}
@@ -228,7 +235,7 @@ class Fir2IrDeclarationStorage(
}
}
private fun getCachedIrClass(klass: FirClass<*>): IrClass? {
fun getCachedIrClass(klass: FirClass<*>): IrClass? {
return if (klass is FirAnonymousObject || klass is FirRegularClass && klass.visibility == Visibilities.LOCAL) {
localStorage.getLocalClass(klass)
} else {
@@ -250,24 +257,39 @@ class Fir2IrDeclarationStorage(
}
}
private fun createIrClass(klass: FirClass<*>, exactlySourceClass: Boolean = false): IrClass {
private fun createIrClass(klass: FirClass<*>, parent: IrDeclarationParent? = null): IrClass {
// NB: klass can be either FirRegularClass or FirAnonymousObject
if (klass is FirAnonymousObject) {
return createIrAnonymousObject(klass)
return createIrAnonymousObject(klass, irParent = parent)
}
val regularClass = klass as FirRegularClass
val descriptor = WrappedClassDescriptor()
val origin =
if (exactlySourceClass || firProvider.getFirClassifierContainerFileIfAny(klass.symbol) != null) IrDeclarationOrigin.DEFINED
if (firProvider.getFirClassifierContainerFileIfAny(klass.symbol) != null) IrDeclarationOrigin.DEFINED
else IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
val irClass = registerIrClass(regularClass, parent, origin)
processClassHeader(regularClass, irClass)
return irClass
}
fun processClassHeader(regularClass: FirRegularClass, irClass: IrClass = getCachedIrClass(regularClass)!!): IrClass {
irClass.declareSupertypesAndTypeParameters(regularClass)
irClass.setThisReceiver()
return irClass
}
fun registerIrClass(
regularClass: FirRegularClass,
parent: IrDeclarationParent? = null,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
): IrClass {
val descriptor = WrappedClassDescriptor()
val visibility = regularClass.visibility
val modality = if (regularClass.classKind == ClassKind.ENUM_CLASS) {
regularClass.enumClassModality()
} else {
regularClass.modality ?: Modality.FINAL
}
val irClass = klass.convertWithOffsets { startOffset, endOffset ->
val irClass = regularClass.convertWithOffsets { startOffset, endOffset ->
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality, visibility) { symbol ->
IrClassImpl(
startOffset,
@@ -275,7 +297,7 @@ class Fir2IrDeclarationStorage(
origin,
symbol,
regularClass.name,
klass.classKind,
regularClass.classKind,
visibility,
modality,
isCompanion = regularClass.isCompanion,
@@ -290,25 +312,22 @@ class Fir2IrDeclarationStorage(
}
}
}
if (regularClass.visibility == Visibilities.LOCAL) {
localStorage.putLocalClass(klass, irClass)
} else {
classCache[klass] = irClass
if (parent != null) {
irClass.parent = parent
}
if (regularClass.visibility == Visibilities.LOCAL) {
localStorage.putLocalClass(regularClass, irClass)
} else {
classCache[regularClass] = irClass
}
irClass.declareSupertypesAndTypeParameters(klass)
irClass.setThisReceiver()
return irClass
}
fun getIrClass(klass: FirClass<*>, exactlySourceClass: Boolean = true): IrClass {
return getCachedIrClass(klass) ?: createIrClass(klass, exactlySourceClass)
}
private fun createIrAnonymousObject(
fun createIrAnonymousObject(
anonymousObject: FirAnonymousObject,
visibility: Visibility = Visibilities.LOCAL,
name: Name = Name.special("<no name provided>"),
irParent: IrClass? = null
irParent: IrDeclarationParent? = null
): IrClass {
val descriptor = WrappedClassDescriptor()
val origin = IrDeclarationOrigin.DEFINED
@@ -335,18 +354,9 @@ class Fir2IrDeclarationStorage(
return result
}
fun getIrAnonymousObject(
anonymousObject: FirAnonymousObject,
visibility: Visibility = Visibilities.LOCAL,
name: Name = Name.special("<no name provided>"),
irParent: IrClass? = null
): IrClass {
private fun getIrAnonymousObjectForEnumEntry(anonymousObject: FirAnonymousObject, name: Name, irParent: IrClass?): IrClass {
localStorage.getLocalClass(anonymousObject)?.let { return it }
return createIrAnonymousObject(anonymousObject, visibility, name, irParent)
}
private fun getIrEnumEntryClass(enumEntry: FirEnumEntry, anonymousObject: FirAnonymousObject, irParent: IrClass?): IrClass {
return getIrAnonymousObject(anonymousObject, Visibilities.PRIVATE, enumEntry.name, irParent)
return createIrAnonymousObject(anonymousObject, Visibilities.PRIVATE, name, irParent)
}
private fun getIrTypeParameter(
@@ -487,7 +497,7 @@ class Fir2IrDeclarationStorage(
declareDefaultSetterParameter(type)
} else if (function != null) {
valueParameters = function.valueParameters.mapIndexed { index, valueParameter ->
createAndSaveIrParameter(
createIrParameter(
valueParameter, index,
useStubForDefaultValueStub = function !is FirConstructor || containingClass?.name != Name.identifier("Enum"),
typeContext
@@ -535,16 +545,18 @@ class Fir2IrDeclarationStorage(
return this
}
fun <T : IrFunction> T.enterLocalScope(function: FirFunction<*>): T {
enterScope(descriptor)
fun <T : IrFunction> T.putParametersInScope(function: FirFunction<*>): T {
for ((firParameter, irParameter) in function.valueParameters.zip(valueParameters)) {
irSymbolTable.introduceValueParameter(irParameter)
localStorage.putParameter(firParameter, irParameter)
}
return this
}
private fun getCachedIrFunction(function: FirFunction<*>): IrSimpleFunction? {
fun putEnumEntryClassInScope(enumEntry: FirEnumEntry, correspondingClass: IrClass) {
localStorage.putLocalClass(enumEntry.initializer as FirAnonymousObject, correspondingClass)
}
fun getCachedIrFunction(function: FirFunction<*>): IrSimpleFunction? {
return if (function !is FirSimpleFunction || function.visibility == Visibilities.LOCAL) {
localStorage.getLocalFunction(function)
} else {
@@ -552,10 +564,9 @@ class Fir2IrDeclarationStorage(
}
}
private fun createIrFunction(
fun createIrFunction(
function: FirFunction<*>,
irParent: IrDeclarationParent?,
shouldLeaveScope: Boolean = true,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
): IrSimpleFunction {
val simpleFunction = function as? FirSimpleFunction
@@ -591,9 +602,7 @@ class Fir2IrDeclarationStorage(
result
}.bindAndDeclareParameters(function, descriptor, irParent, isStatic = simpleFunction?.isStatic == true)
if (shouldLeaveScope) {
leaveScope(created.descriptor)
}
leaveScope(created.descriptor)
if (visibility == Visibilities.LOCAL) {
localStorage.putLocalFunction(function, created)
return created
@@ -607,33 +616,32 @@ class Fir2IrDeclarationStorage(
return created
}
fun getIrFunction(
function: FirFunction<*>,
irParent: IrDeclarationParent?,
shouldLeaveScope: Boolean = true,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
): IrSimpleFunction {
return getCachedIrFunction(function)?.apply {
if (!shouldLeaveScope) enterLocalScope(function)
} ?: createIrFunction(function, irParent, shouldLeaveScope, origin)
fun getCachedIrAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer): IrAnonymousInitializer? =
initializerCache[anonymousInitializer]
fun createIrAnonymousInitializer(
anonymousInitializer: FirAnonymousInitializer,
irParent: IrClass
): IrAnonymousInitializer {
return anonymousInitializer.convertWithOffsets { startOffset, endOffset ->
irSymbolTable.declareAnonymousInitializer(startOffset, endOffset, IrDeclarationOrigin.DEFINED, irParent.descriptor).apply {
this.parent = irParent
initializerCache[anonymousInitializer] = this
}
}
}
private fun getCachedIrConstructor(
constructor: FirConstructor
): IrConstructor? {
return constructorCache[constructor]
}
fun getCachedIrConstructor(constructor: FirConstructor): IrConstructor? = constructorCache[constructor]
private fun createIrConstructor(
fun createIrConstructor(
constructor: FirConstructor,
irParent: IrDeclarationParent,
shouldLeaveScope: Boolean = true,
irParent: IrClass,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
): IrConstructor {
val descriptor = WrappedClassConstructorDescriptor()
val isPrimary = constructor.isPrimary
val visibility = when {
irParent is IrClass && irParent.modality == Modality.SEALED -> Visibilities.PRIVATE
val visibility = when (irParent.modality) {
Modality.SEALED -> Visibilities.PRIVATE
else -> constructor.visibility
}
val created = constructor.convertWithOffsets { startOffset, endOffset ->
@@ -646,9 +654,7 @@ class Fir2IrDeclarationStorage(
).apply {
enterScope(descriptor)
}.bindAndDeclareParameters(constructor, descriptor, irParent, isStatic = true).apply {
if (shouldLeaveScope) {
leaveScope(descriptor)
}
leaveScope(descriptor)
}
}
}
@@ -656,18 +662,6 @@ class Fir2IrDeclarationStorage(
return created
}
fun getIrConstructor(
constructor: FirConstructor,
irParent: IrDeclarationParent,
shouldLeaveScope: Boolean = true
): IrConstructor {
val cached = getCachedIrConstructor(constructor)
if (cached != null) {
return if (shouldLeaveScope) cached else cached.enterLocalScope(constructor)
}
return createIrConstructor(constructor, irParent, shouldLeaveScope)
}
private fun createIrPropertyAccessor(
propertyAccessor: FirPropertyAccessor?,
property: FirProperty,
@@ -725,49 +719,48 @@ class Fir2IrDeclarationStorage(
}
}
fun getCachedIrEnumEntry(enumEntry: FirEnumEntry): IrEnumEntry? = enumEntryCache[enumEntry]
fun getIrEnumEntry(
fun createIrEnumEntry(
enumEntry: FirEnumEntry,
irParent: IrClass? = null,
irParent: IrClass?,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
): IrEnumEntry {
return enumEntryCache.getOrPut(enumEntry) {
enumEntry.convertWithOffsets { startOffset, endOffset ->
val desc = WrappedEnumEntryDescriptor()
enterScope(desc)
val result = irSymbolTable.declareEnumEntry(startOffset, endOffset, origin, desc) { symbol ->
IrEnumEntryImpl(
startOffset, endOffset, origin, symbol, enumEntry.name
).apply {
desc.bind(this)
val irType = enumEntry.returnTypeRef.toIrType()
if (irParent != null) {
this.parent = irParent
}
val initializer = enumEntry.initializer
if (initializer != null) {
initializer as FirAnonymousObject
val klass = getIrEnumEntryClass(enumEntry, initializer, irParent)
return enumEntry.convertWithOffsets { startOffset, endOffset ->
val desc = WrappedEnumEntryDescriptor()
enterScope(desc)
val result = irSymbolTable.declareEnumEntry(startOffset, endOffset, origin, desc) { symbol ->
IrEnumEntryImpl(
startOffset, endOffset, origin, symbol, enumEntry.name
).apply {
desc.bind(this)
val irType = enumEntry.returnTypeRef.toIrType()
if (irParent != null) {
this.parent = irParent
}
val initializer = enumEntry.initializer
if (initializer != null) {
initializer as FirAnonymousObject
val klass = getIrAnonymousObjectForEnumEntry(initializer, enumEntry.name, irParent)
this.correspondingClass = klass
} else if (irParent != null) {
this.initializerExpression = IrExpressionBodyImpl(
IrEnumConstructorCallImpl(startOffset, endOffset, irType, irParent.constructors.first().symbol)
)
}
this.correspondingClass = klass
} else if (irParent != null) {
this.initializerExpression = IrExpressionBodyImpl(
IrEnumConstructorCallImpl(startOffset, endOffset, irType, irParent.constructors.first().symbol)
)
}
}
leaveScope(desc)
result
}
leaveScope(desc)
enumEntryCache[enumEntry] = result
result
}
}
private fun createIrProperty(
fun createIrProperty(
property: FirProperty,
irParent: IrDeclarationParent?,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED,
shouldLeaveScope: Boolean = true
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
): IrProperty {
val containerSource = property.containerSource
val descriptor = containerSource?.let { WrappedPropertyDescriptorWithContainerSource(it) } ?: WrappedPropertyDescriptor()
@@ -818,29 +811,13 @@ class Fir2IrDeclarationStorage(
}
}
}
if (shouldLeaveScope) {
leaveScope(descriptor)
}
leaveScope(descriptor)
propertyCache[property] = result
result
}
}
fun getIrProperty(
property: FirProperty,
irParent: IrDeclarationParent?,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED,
shouldLeaveScope: Boolean = true
): IrProperty {
val cached = propertyCache[property]
if (cached != null) {
if (!shouldLeaveScope) {
enterScope(cached.descriptor)
}
return cached
}
return createIrProperty(property, irParent, origin, shouldLeaveScope)
}
fun getCachedIrProperty(property: FirProperty): IrProperty? = propertyCache[property]
private fun createIrField(field: FirField): IrField {
val descriptor = WrappedFieldDescriptor()
@@ -866,7 +843,7 @@ class Fir2IrDeclarationStorage(
}
}
private fun createAndSaveIrParameter(
private fun createIrParameter(
valueParameter: FirValueParameter,
index: Int = -1,
useStubForDefaultValueStub: Boolean = true,
@@ -929,7 +906,7 @@ class Fir2IrDeclarationStorage(
}
}
fun createAndSaveIrVariable(variable: FirVariable<*>, givenOrigin: IrDeclarationOrigin? = null): IrVariable {
fun createIrVariable(variable: FirVariable<*>, irParent: IrDeclarationParent, givenOrigin: IrDeclarationOrigin? = null): IrVariable {
val type = variable.returnTypeRef.toIrType()
// Some temporary variables are produced in RawFirBuilder, but we consistently use special names for them.
val origin = when {
@@ -944,6 +921,7 @@ class Fir2IrDeclarationStorage(
variable.name, type, variable.isVar, isConst = false, isLateinit = false
)
}
irVariable.parent = irParent
localStorage.putVariable(variable, irVariable)
return irVariable
}
@@ -961,6 +939,7 @@ class Fir2IrDeclarationStorage(
fun getIrClassSymbol(firClassSymbol: FirClassSymbol<*>): IrClassSymbol {
val firClass = firClassSymbol.fir
getCachedIrClass(firClass)?.let { return irSymbolTable.referenceClass(it.descriptor) }
// TODO: remove all this code and change to unbound symbol creation
val irClass = createIrClass(firClass)
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.visibility == Visibilities.LOCAL) {
return irSymbolTable.referenceClass(irClass.descriptor)
@@ -982,10 +961,22 @@ class Fir2IrDeclarationStorage(
firTypeParameterSymbol: FirTypeParameterSymbol,
typeContext: ConversionTypeContext
): IrTypeParameterSymbol {
// TODO: use cached type parameter here
val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, typeContext = typeContext)
return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor)
}
fun getIrConstructorSymbol(firConstructorSymbol: FirConstructorSymbol): IrConstructorSymbol {
val firConstructor = firConstructorSymbol.fir
getCachedIrConstructor(firConstructor)?.let { return irSymbolTable.referenceConstructor(it.descriptor) }
val irParent = findIrParent(firConstructor) as IrClass
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
val irDeclaration = createIrConstructor(firConstructor, irParent, origin = parentOrigin).apply {
setAndModifyParent(irParent)
}
return irSymbolTable.referenceConstructor(irDeclaration.descriptor)
}
fun getIrFunctionSymbol(firFunctionSymbol: FirFunctionSymbol<*>): IrFunctionSymbol {
return when (val firDeclaration = firFunctionSymbol.fir) {
is FirSimpleFunction, is FirAnonymousFunction -> {
@@ -998,13 +989,7 @@ class Fir2IrDeclarationStorage(
irSymbolTable.referenceSimpleFunction(irDeclaration.descriptor)
}
is FirConstructor -> {
getCachedIrConstructor(firDeclaration)?.let { return irSymbolTable.referenceConstructor(it.descriptor) }
val irParent = findIrParent(firDeclaration)!!
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
val irDeclaration = createIrConstructor(firDeclaration, irParent, origin = parentOrigin).apply {
setAndModifyParent(irParent)
}
irSymbolTable.referenceConstructor(irDeclaration.descriptor)
getIrConstructorSymbol(firDeclaration.symbol)
}
else -> throw AssertionError("Should not be here: ${firDeclaration::class.java}: ${firDeclaration.render()}")
}
@@ -1058,10 +1043,11 @@ class Fir2IrDeclarationStorage(
fun getIrValueSymbol(firVariableSymbol: FirVariableSymbol<*>): IrSymbol {
return when (val firDeclaration = firVariableSymbol.fir) {
is FirEnumEntry -> {
getCachedIrEnumEntry(firDeclaration)?.let { return irSymbolTable.referenceEnumEntry(it.descriptor) }
val containingFile = firProvider.getFirCallableContainerFile(firVariableSymbol)
val parentClassSymbol = firVariableSymbol.callableId.classId?.let { firSymbolProvider.getClassLikeSymbolByFqName(it) }
val irParentClass = (parentClassSymbol?.fir as? FirClass<*>)?.let { getIrClass(it) }
val irEnumEntry = getIrEnumEntry(
val irParentClass = (parentClassSymbol?.fir as? FirClass<*>)?.let { getCachedIrClass(it) }
val irEnumEntry = createIrEnumEntry(
firDeclaration,
irParent = irParentClass,
origin = if (containingFile == null) IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB else IrDeclarationOrigin.DEFINED
@@ -43,9 +43,7 @@ class Fir2IrFakeOverrideGenerator(
firOverriddenSymbol: FirPropertySymbol
): IrProperty {
val firOverriddenProperty = firOverriddenSymbol.fir
val overriddenProperty = declarationStorage.getIrProperty(
firOverriddenProperty, declarationStorage.findIrParent(firOverriddenProperty)
)
val overriddenProperty = declarationStorage.getCachedIrProperty(firOverriddenProperty)!!
getter?.apply {
overriddenProperty.getter?.symbol?.let { overriddenSymbols = listOf(it) }
}
@@ -71,7 +69,7 @@ class Fir2IrFakeOverrideGenerator(
if (functionSymbol.isFakeOverride) {
// Substitution case
val baseSymbol = functionSymbol.deepestOverriddenSymbol() as FirNamedFunctionSymbol
val irFunction = declarationStorage.getIrFunction(
val irFunction = declarationStorage.createIrFunction(
// TODO: parents for functions and properties should be consistent
originalFunction, declarationStorage.findIrParent(baseSymbol.fir), origin = origin
)
@@ -89,7 +87,7 @@ class Fir2IrFakeOverrideGenerator(
)
val fakeOverrideFunction = fakeOverrideSymbol.fir
val irFunction = declarationStorage.getIrFunction(
val irFunction = declarationStorage.createIrFunction(
fakeOverrideFunction, declarationStorage.findIrParent(originalFunction), origin = origin
)
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(functionSymbol) as IrSimpleFunctionSymbol
@@ -106,7 +104,7 @@ class Fir2IrFakeOverrideGenerator(
if (propertySymbol.isFakeOverride) {
// Substitution case
val baseSymbol = propertySymbol.deepestOverriddenSymbol() as FirPropertySymbol
val irProperty = declarationStorage.getIrProperty(
val irProperty = declarationStorage.createIrProperty(
originalProperty, irParent = this, origin = origin
)
declarations += irProperty.withProperty {
@@ -119,7 +117,7 @@ class Fir2IrFakeOverrideGenerator(
)
val fakeOverrideProperty = fakeOverrideSymbol.fir
val irProperty = declarationStorage.getIrProperty(
val irProperty = declarationStorage.createIrProperty(
fakeOverrideProperty, irParent = this, origin = origin
)
declarations += irProperty.withProperty {
@@ -18,6 +18,8 @@ class Fir2IrLocalStorage {
private val cacheStack = mutableListOf<Fir2IrCallableCache>()
private val localClassCache = mutableMapOf<FirClass<*>, IrClass>()
fun enterCallable() {
cacheStack += Fir2IrCallableCache()
}
@@ -44,11 +46,7 @@ class Fir2IrLocalStorage {
}
fun getLocalClass(localClass: FirClass<*>): IrClass? {
for (cache in cacheStack.asReversed()) {
val local = cache.getLocalClass(localClass)
if (local != null) return local
}
return null
return localClassCache[localClass]
}
fun getLocalFunction(localFunction: FirFunction<*>): IrSimpleFunction? {
@@ -68,7 +66,7 @@ class Fir2IrLocalStorage {
}
fun putLocalClass(firClass: FirClass<*>, irClass: IrClass) {
cacheStack.last().putLocalClass(firClass, irClass)
localClassCache[firClass] = irClass
}
fun putLocalFunction(firFunction: FirFunction<*>, irFunction: IrSimpleFunction) {
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.*
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.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
@@ -34,7 +33,6 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
@@ -44,14 +42,14 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
import java.util.*
class Fir2IrVisitor(
private val session: FirSession,
private val moduleDescriptor: FirModuleDescriptor,
private val symbolTable: SymbolTable,
private val sourceManager: PsiSourceManager,
private val declarationStorage: Fir2IrDeclarationStorage,
private val converter: Fir2IrConverter,
private val typeConverter: Fir2IrTypeConverter,
override val irBuiltIns: IrBuiltIns,
fakeOverrideMode: FakeOverrideMode
) : FirDefaultVisitor<IrElement, Any?>(), IrGeneratorContextInterface {
@@ -63,40 +61,24 @@ class Fir2IrVisitor(
private val integerApproximator = IntegerLiteralTypeApproximationTransformer(session.firSymbolProvider, session.inferenceContext)
private val declarationStorage = Fir2IrDeclarationStorage(session, symbolTable, moduleDescriptor)
private val conversionScope = Fir2IrConversionScope()
private val typeConverter = Fir2IrTypeConverter(session, declarationStorage, irBuiltIns).also {
declarationStorage.typeConverter = it
it.initBuiltinTypes()
}
private val fakeOverrideGenerator = Fir2IrFakeOverrideGenerator(session, declarationStorage, conversionScope, fakeOverrideMode)
private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() }
private fun ConeKotlinType.toIrType(): IrType = with(typeConverter) { toIrType() }
private val conversionScope = Fir2IrConversionScope()
private fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T = conversionScope.applyParentFromStackTo(declaration)
private val fakeOverrideGenerator = Fir2IrFakeOverrideGenerator(session, declarationStorage, conversionScope, fakeOverrideMode)
override fun visitElement(element: FirElement, data: Any?): IrElement {
TODO("Should not be here: ${element.render()}")
}
fun registerFile(file: FirFile) {
val irFile = IrFileImpl(
sourceManager.getOrCreateFileEntry(file.psi as KtFile),
moduleDescriptor.getPackage(file.packageFqName).fragments.first()
)
declarationStorage.registerFile(file, irFile)
}
override fun visitFile(file: FirFile, data: Any?): IrFile {
return conversionScope.withParent(declarationStorage.getIrFile(file)) {
file.declarations.forEach {
val irDeclaration = it.toIrDeclaration() ?: return@forEach
declarations += irDeclaration
it.toIrDeclaration()
}
annotations = file.annotations.mapNotNull {
@@ -110,9 +92,14 @@ class Fir2IrVisitor(
return accept(this@Fir2IrVisitor, null) as IrDeclaration
}
// ==================================================================================
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: Any?): IrElement {
val irEnumEntry = declarationStorage.getIrEnumEntry(enumEntry, irParent = conversionScope.lastClass())
val irEnumEntry = declarationStorage.getCachedIrEnumEntry(enumEntry)!!
val correspondingClass = irEnumEntry.correspondingClass ?: return irEnumEntry
declarationStorage.enterScope(irEnumEntry.descriptor)
declarationStorage.putEnumEntryClassInScope(enumEntry, correspondingClass)
converter.processAnonymousObjectMembers(enumEntry.initializer as FirAnonymousObject, correspondingClass)
conversionScope.withParent(correspondingClass) {
setClassContent(enumEntry.initializer as FirAnonymousObject)
irEnumEntry.initializerExpression = IrExpressionBodyImpl(
@@ -122,25 +109,27 @@ class Fir2IrVisitor(
)
)
}
declarationStorage.leaveScope(irEnumEntry.descriptor)
return irEnumEntry
}
private fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
private fun IrClass.setClassContent(klass: FirClass<*>) {
declarationStorage.enterScope(descriptor)
conversionScope.withClass(this) {
val primaryConstructor = klass.getPrimaryConstructorIfAny()
val irPrimaryConstructor = primaryConstructor?.accept(this@Fir2IrVisitor, null) as IrConstructor?
val irPrimaryConstructor = primaryConstructor?.let { declarationStorage.getCachedIrConstructor(it)!! }
if (irPrimaryConstructor != null) {
declarations += irPrimaryConstructor
with(declarationStorage) {
enterScope(irPrimaryConstructor.descriptor)
irPrimaryConstructor.valueParameters.forEach { symbolTable.introduceValueParameter(it) }
irPrimaryConstructor.putParametersInScope(primaryConstructor)
irPrimaryConstructor.setFunctionContent(irPrimaryConstructor.descriptor, primaryConstructor)
}
}
val processedCallableNames = mutableListOf<Name>()
klass.declarations.forEach {
if (it !is FirConstructor || !it.isPrimary) {
val irDeclaration = it.toIrDeclaration() ?: return@forEach
declarations += irDeclaration
it.toIrDeclaration() ?: return@forEach
when (it) {
is FirSimpleFunction -> processedCallableNames += it.name
is FirProperty -> processedCallableNames += it.name
@@ -159,16 +148,64 @@ class Fir2IrVisitor(
}
override fun visitRegularClass(regularClass: FirRegularClass, data: Any?): IrElement {
return conversionScope.withParent(
applyParentFromStackTo(declarationStorage.getIrClass(regularClass))
) {
if (regularClass.visibility == Visibilities.LOCAL) {
val irParent = conversionScope.parentFromStack()
val irClass = declarationStorage.getCachedIrClass(regularClass)?.apply { this.parent = irParent }
if (irClass != null) {
converter.processRegisteredLocalClassAndNestedClasses(regularClass, irClass)
return conversionScope.withParent(irClass) {
setClassContent(regularClass)
}
}
converter.processLocalClassAndNestedClasses(regularClass, irParent)
}
val irClass = declarationStorage.getCachedIrClass(regularClass)!!
return conversionScope.withParent(irClass) {
setClassContent(regularClass)
}
}
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): IrElement {
val irParent = conversionScope.parentFromStack()
// NB: for implicit types it is possible that anonymous object is already cached
val irAnonymousObject = declarationStorage.getCachedIrClass(anonymousObject)?.apply { this.parent = irParent }
?: declarationStorage.createIrAnonymousObject(anonymousObject, irParent = irParent)
converter.processAnonymousObjectMembers(anonymousObject, irAnonymousObject)
conversionScope.withParent(irAnonymousObject) {
setClassContent(anonymousObject)
}
val anonymousClassType = irAnonymousObject.thisReceiver!!.type
return anonymousObject.convertWithOffsets { startOffset, endOffset ->
IrBlockImpl(
startOffset, endOffset, anonymousClassType, IrStatementOrigin.OBJECT_LITERAL,
listOf(
irAnonymousObject,
IrConstructorCallImpl.fromSymbolOwner(
startOffset,
endOffset,
anonymousClassType,
irAnonymousObject.constructors.first().symbol,
irAnonymousObject.typeParameters.size,
origin = IrStatementOrigin.OBJECT_LITERAL
)
)
)
}
}
// ==================================================================================
private fun <T : IrFunction> T.setFunctionContent(descriptor: FunctionDescriptor, firFunction: FirFunction<*>?): T {
conversionScope.withParent(this) {
if (firFunction != null) {
if (this !is IrConstructor || !this.isPrimary) {
// Scope for primary constructor should be entered before class declaration processing
with(declarationStorage) {
enterScope(descriptor)
valueParameters.forEach { symbolTable.introduceValueParameter(it) }
putParametersInScope(firFunction)
}
}
for ((valueParameter, firValueParameter) in valueParameters.zip(firFunction.valueParameters)) {
valueParameter.setDefaultValue(firValueParameter)
}
@@ -208,27 +245,18 @@ class Fir2IrVisitor(
}
override fun visitConstructor(constructor: FirConstructor, data: Any?): IrElement {
val irConstructor = declarationStorage.getIrConstructor(
constructor, irParent = conversionScope.lastClass()!!, shouldLeaveScope = false
)
val irConstructor = declarationStorage.getCachedIrConstructor(constructor)!!
return conversionScope.withFunction(irConstructor) {
setFunctionContent(irConstructor.descriptor, constructor)
}
}
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: Any?): IrElement {
val origin = IrDeclarationOrigin.DEFINED
val parent = conversionScope.lastClass()!!
return anonymousInitializer.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareAnonymousInitializer(
startOffset, endOffset, origin, parent.descriptor
).apply {
this.parent = parent
declarationStorage.enterScope(descriptor)
body = anonymousInitializer.body!!.convertToIrBlockBody()
declarationStorage.leaveScope(descriptor)
}
}
val irAnonymousInitializer = declarationStorage.getCachedIrAnonymousInitializer(anonymousInitializer)!!
declarationStorage.enterScope(irAnonymousInitializer.descriptor)
irAnonymousInitializer.body = anonymousInitializer.body!!.convertToIrBlockBody()
declarationStorage.leaveScope(irAnonymousInitializer.descriptor)
return irAnonymousInitializer
}
private fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrCallWithIndexedArgumentsBase? {
@@ -265,9 +293,12 @@ class Fir2IrVisitor(
}
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): IrElement {
val irFunction = declarationStorage.getIrFunction(
simpleFunction, irParent = conversionScope.parent(), shouldLeaveScope = false
)
val irFunction = if (simpleFunction.visibility == Visibilities.LOCAL) {
val irParent = conversionScope.parent()
declarationStorage.createIrFunction(simpleFunction, irParent)
} else {
declarationStorage.getCachedIrFunction(simpleFunction)!!
}
return conversionScope.withFunction(irFunction) {
setFunctionContent(irFunction.descriptor, simpleFunction)
}
@@ -275,7 +306,7 @@ class Fir2IrVisitor(
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: Any?): IrElement {
return anonymousFunction.convertWithOffsets { startOffset, endOffset ->
val irFunction = declarationStorage.getIrFunction(anonymousFunction, conversionScope.parent(), shouldLeaveScope = false)
val irFunction = declarationStorage.createIrFunction(anonymousFunction, conversionScope.parent())
conversionScope.withFunction(irFunction) {
setFunctionContent(irFunction.descriptor, anonymousFunction)
}
@@ -299,14 +330,13 @@ class Fir2IrVisitor(
val isNextVariable = initializer is FirFunctionCall &&
initializer.resolvedNamedFunctionSymbol()?.callableId?.isIteratorNext() == true &&
variable.source.psi?.parent is KtForExpression
val irVariable = declarationStorage.createAndSaveIrVariable(
variable, if (isNextVariable) IrDeclarationOrigin.FOR_LOOP_VARIABLE else null
val irVariable = declarationStorage.createIrVariable(
variable, conversionScope.parentFromStack(), if (isNextVariable) IrDeclarationOrigin.FOR_LOOP_VARIABLE else null
)
return applyParentFromStackTo(irVariable).apply {
if (initializer != null) {
this.initializer = initializer.toIrExpression()
}
if (initializer != null) {
irVariable.initializer = initializer.toIrExpression()
}
return irVariable
}
private fun IrProperty.createBackingField(
@@ -373,14 +403,15 @@ class Fir2IrVisitor(
annotations = property.annotations.mapNotNull {
it.accept(this@Fir2IrVisitor, null) as? IrConstructorCall
}
declarationStorage.leaveScope(descriptor)
return this
}
override fun visitProperty(property: FirProperty, data: Any?): IrElement {
if (property.isLocal) return visitLocalVariable(property)
val irProperty = declarationStorage.getIrProperty(property, irParent = conversionScope.parent(), shouldLeaveScope = false)
return conversionScope.withProperty(irProperty) { setPropertyContent(irProperty.descriptor, property) }
val irProperty = declarationStorage.getCachedIrProperty(property)!!
return conversionScope.withProperty(irProperty) {
setPropertyContent(irProperty.descriptor, property)
}
}
private fun IrFieldAccessExpression.setReceiver(declaration: IrDeclaration): IrFieldAccessExpression {
@@ -400,11 +431,6 @@ class Fir2IrVisitor(
isDefault: Boolean
) {
conversionScope.withFunction(this) {
if (propertyAccessor != null) {
with(declarationStorage) { this@setPropertyAccessorContent.enterLocalScope(propertyAccessor) }
} else {
declarationStorage.enterScope(descriptor)
}
applyParentFromStackTo(this)
setFunctionContent(descriptor, propertyAccessor)
if (isDefault) {
@@ -518,14 +544,12 @@ class Fir2IrVisitor(
val irClass = symbol.owner
val fir = firSymbol?.fir as? FirClass<*>
val irConstructor = fir?.getPrimaryConstructorIfAny()?.let { firConstructor ->
declarationStorage.getIrConstructor(firConstructor, irParent = irClass)
}?.apply {
this.parent = irClass
declarationStorage.getIrConstructorSymbol(firConstructor.symbol)
}
if (irConstructor == null) {
IrErrorCallExpressionImpl(startOffset, endOffset, type, "No annotation constructor found: ${irClass.name}")
} else {
IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, type, irConstructor.symbol)
IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, type, irConstructor)
}
}
@@ -623,7 +647,7 @@ class Fir2IrVisitor(
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
}
firClass?.convertWithOffsets { startOffset, endOffset ->
val irClass = declarationStorage.getIrClass(firClass)
val irClass = declarationStorage.getCachedIrClass(firClass)!!
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
}
}
@@ -691,7 +715,7 @@ class Fir2IrVisitor(
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
}
if (firObject != null) {
val irObject = declarationStorage.getIrClass(firObject)
val irObject = declarationStorage.getCachedIrClass(firObject)!!
if (irObject != conversionScope.lastClass()) {
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
IrGetObjectValueImpl(startOffset, endOffset, irObject.defaultType, irObject.symbol)
@@ -827,30 +851,6 @@ class Fir2IrVisitor(
}
}
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): IrElement {
val anonymousClass = declarationStorage.getIrAnonymousObject(anonymousObject)
conversionScope.withParent(applyParentFromStackTo(anonymousClass)) {
setClassContent(anonymousObject)
}
val anonymousClassType = anonymousClass.thisReceiver!!.type
return anonymousObject.convertWithOffsets { startOffset, endOffset ->
IrBlockImpl(
startOffset, endOffset, anonymousClassType, IrStatementOrigin.OBJECT_LITERAL,
listOf(
anonymousClass,
IrConstructorCallImpl.fromSymbolOwner(
startOffset,
endOffset,
anonymousClassType,
anonymousClass.constructors.first().symbol,
anonymousClass.typeParameters.size,
origin = IrStatementOrigin.OBJECT_LITERAL
)
)
)
}
}
// ==================================================================================
private fun FirStatement.toIrStatement(): IrStatement? {
@@ -1082,8 +1082,8 @@ class Fir2IrVisitor(
override fun visitCatch(catch: FirCatch, data: Any?): IrElement {
return catch.convertWithOffsets { startOffset, endOffset ->
val catchParameter = declarationStorage.createAndSaveIrVariable(catch.parameter)
IrCatchImpl(startOffset, endOffset, applyParentFromStackTo(catchParameter)).apply {
val catchParameter = declarationStorage.createIrVariable(catch.parameter, conversionScope.parentFromStack())
IrCatchImpl(startOffset, endOffset, catchParameter).apply {
result = catch.block.convertToIrExpressionOrBlock()
}
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
var result = "Fail"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS, JS_IR
fun box(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A
fun box(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
class A
fun A.foo() = "OK"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun Int.is42With(that: Int) = this + 2 * that == 42
return if ((Int::is42With)(16, 13)) "OK" else "Fail"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A
fun box(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun foo(): String {
fun bar() = "OK"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(until: Int): String {
fun bar(x: Int): String =
if (x == until) "OK" else bar(x + 1)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun foo() = "OK"
return (::foo)()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
val result = "OK"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun foo(s: String) = s
return (::foo)("OK")
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
var state = 23
fun box(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
package example2
fun box() = Context.OsType.OK.toString()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun String.f(x: String): String {
fun String.g() = { this@f + this@g }()
return x.g()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Base(val fn: () -> String)
fun box(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Z(val s: Int) {
open fun a() {}
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box() : String {
fun <T> local(s : T) : T {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun rec(n : Int) {
fun x(m : Int) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun rec(n : Int) {
fun x(m : Int, k : Int) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun foo(x: Int) {
fun bar(y: Int) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun foo(x: Int, s: String): String {
fun bar(y: Int) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
//KT-3276
fun box(): String {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box() : String {
fun <T> foo(t:() -> T) : T = t()
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
val x = "OK"
fun bar(y: String = x): String = y
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
val o = "O"
fun ok() = o + "K"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun local():Int {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun local():Int {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box() : String {
fun <T> local(s : T) : T {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(s: String): String {
fun bar(count: Int): String =
if (count == 0) s else bar(count - 1)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS, JS_IR
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// DONT_RUN_GENERATED_CODE: JS
fun test() {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
package test
fun box() = MyEnum.E1.f() + MyEnum.E2.f()
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box() = if(Context.operatingSystemType == Context.Companion.OsType.OTHER) "OK" else "fail"
public class Context
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
enum class X {
B {
val value2 = "K"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
fun box(): String {
val sb = StringBuilder()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun String.foo() : String {
fun Int.bar() : String {
fun Long.baz() : String {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun rmrf(i: Int) {
if (i > 0) rmrf(i - 1)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
import kotlin.test.assertEquals
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun <T, V : T> f(x: V): V {
fun g(y: V) = y
return g(x)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
import kotlin.test.assertEquals
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
import kotlin.test.assertEquals
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
import kotlin.test.assertEquals
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun outer() {
fun inner(i: Int) {
if (i > 0){
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun <T> foo(t: T) = t
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box() : String {
fun local(i: Int = 1) : Int {
return i
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class C() {
fun box(): Int {
fun local(i: Int = 1): Int {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(f: (Int?) -> Int): Int {
return f(0)
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
infix fun Int.foo(a: Int): Int = a + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun String.f() = this
val vf: String.() -> String = { this }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class T(val value: Int) {
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class It(val id: String)
fun box(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
var s = ""
var foo = "O"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun test(b: Boolean): String {
if (b) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
fun foo(x: String) = x
fun foo() = foo("K")
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
var s = ""
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
var s = ""
var foo = "K"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
var s = ""
var foo = "K"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
var s = ""
var foo = "O"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(): String {
fun bar(x: String, y: String = x): String {
return y
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Holder<T: Any>(val v: T)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(x: String): String {
fun bar(y: String) = x + y
return bar("K")
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun <X : Any> foo(x: X): String {
fun <Y : Any> bar(y: Y) =
x.toString() + y.toString()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(x: String): String {
fun bar(y: String): String {
fun qux(z: String): String =
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun String.foo(): String {
fun bar(y: String) = this + y
return bar("K")
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
var result = ""
fun add(s: String) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
data class A(val a: Int, val b: Int)
fun box() : String
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class C(val s: String) {
fun test(): String {
return s
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
var x = ""
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
var x = ""
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A {
operator fun component1() = 1
operator fun component2() = 2
@@ -1,5 +1,4 @@
// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: fromAnonymousObjectInNestedClass.kt
import outer.*
@@ -1,5 +1,4 @@
// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField
// IGNORE_BACKEND_FIR: JVM_IR
class Outer {
private companion object {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
var boo = "OK"
var foo = object {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
package p
private class C(val y: Int) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class A(open val v: String)
fun A.a(newv: String) = object: A("fail") {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
operator fun Int?.inc() = (this ?: 0) + 1
var counter: Int? = null
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// SKIP_JDK6
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
private class One {
val a1 = arrayOf(
object { val fy = "text"}
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Foo {
fun bar(): String {
fun <T> foo(t:() -> T) : T = t()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@@ -108,7 +108,7 @@ FILE fqName:<root> fileName:/partialSam.kt
BLOCK_BODY
CALL 'public final fun runConversion (f1: <root>.Fn<kotlin.String, kotlin.Int>, f2: <root>.Fn<kotlin.Int, kotlin.String>): kotlin.Int declared in <root>.J' type=kotlin.Int origin=null
$this: GET_VAR 'j: <root>.J declared in <root>.test' type=<root>.J origin=null
f1: CALL 'public final fun <get-fsi> (): <root>.fsi.<no name provided> declared in <root>' type=<uninitialized parent>.<no name provided> origin=GET_PROPERTY
f1: CALL 'public final fun <get-fsi> (): <root>.fsi.<no name provided> declared in <root>' type=<root>.fsi.<no name provided> origin=GET_PROPERTY
f2: FUN_EXPR type=kotlin.Function3<kotlin.String, kotlin.Int, kotlin.Int, kotlin.String> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (s:kotlin.String, i:kotlin.Int, ti:kotlin.Int) returnType:kotlin.String
VALUE_PARAMETER name:s index:0 type:kotlin.String
@@ -127,4 +127,4 @@ FILE fqName:<root> fileName:/partialSam.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <anonymous> (s: kotlin.String, i: kotlin.Int, ts: kotlin.String): kotlin.Int declared in <root>.test'
CONST Int type=kotlin.Int value=1
f2: CALL 'public final fun <get-fis> (): <root>.fis.<no name provided> declared in <root>' type=<uninitialized parent>.<no name provided> origin=GET_PROPERTY
f2: CALL 'public final fun <get-fis> (): <root>.fis.<no name provided> declared in <root>' type=<root>.fis.<no name provided> origin=GET_PROPERTY
+1 -1
View File
@@ -11,4 +11,4 @@ FILE fqName:<root> fileName:/localFunction.kt
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.outer.local' type=kotlin.Int origin=null
GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.outer.local' type=kotlin.Int origin=null
CALL 'local final fun local (): kotlin.Unit declared in <local>' type=kotlin.Unit origin=null
CALL 'local final fun local (): kotlin.Unit declared in <root>.outer' type=kotlin.Unit origin=null