From c5159d9cbe62b06c67368733eff357035b8f9e3a Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Mon, 11 Nov 2019 14:51:20 +0300 Subject: [PATCH] IR: Add UniqId to IrSymbol --- ...MoveBodilessDeclarationsToSeparatePlace.kt | 10 +- .../kotlin/backend/wasm/WasmBackendContext.kt | 5 + .../jetbrains/kotlin/ir/symbols/IrSymbol.kt | 3 + .../kotlin/ir/symbols/impl/IrSymbolBase.kt | 89 +++++++---- .../jetbrains/kotlin/ir/util/SymbolTable.kt | 151 +++++++++++++++++- 5 files changed, 216 insertions(+), 42 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt index 3fc93c9bb79..fb6df3de1aa 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol import org.jetbrains.kotlin.ir.symbols.IrFileSymbol +import org.jetbrains.kotlin.ir.util.UniqId import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.ir.util.transformFlat @@ -49,6 +50,10 @@ private class DescriptorlessExternalPackageFragmentSymbol : IrExternalPackageFra private var _owner: IrExternalPackageFragment? = null override val owner get() = _owner!! + override var uniqId: UniqId + get() = error("Operation is unsupported") + set(value) { error("Operation is unsupported") } + override val isBound get() = _owner != null override fun bind(owner: IrExternalPackageFragment) { @@ -67,8 +72,11 @@ private class DescriptorlessIrFileSymbol : IrFileSymbol { private var _owner: IrFile? = null override val owner get() = _owner!! - override val isBound get() = _owner != null + override var uniqId: UniqId + get() = error("Operation is unsupported") + set(value) { error("Operation is unsupported") } + override val isBound get() = _owner != null } diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt index f04b7688485..8853a495d2e 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.ir.util.UniqId import org.jetbrains.kotlin.name.FqName class WasmBackendContext( @@ -85,6 +86,10 @@ class DescriptorlessExternalPackageFragmentSymbol : IrExternalPackageFragmentSym private var _owner: IrExternalPackageFragment? = null override val owner get() = _owner!! + override var uniqId: UniqId + get() = error("Operation is unsupported") + set(value) { error("Operation is unsupported") } + override val isBound get() = _owner != null override fun bind(owner: IrExternalPackageFragment) { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt index c802e5e6283..51aae4d9771 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.IrScript import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock import org.jetbrains.kotlin.ir.util.IrSymbolVisitor +import org.jetbrains.kotlin.ir.util.UniqId import org.jetbrains.kotlin.types.model.TypeConstructorMarker import org.jetbrains.kotlin.types.model.TypeParameterMarker @@ -29,6 +30,8 @@ interface IrSymbol { val descriptor: DeclarationDescriptor val isBound: Boolean + var uniqId: UniqId + fun accept(visitor: IrSymbolVisitor, data: D): R } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt index 49e0a07a1f9..cfa1132602e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt @@ -18,14 +18,15 @@ package org.jetbrains.kotlin.ir.symbols.impl import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.descriptors.IrBasedDeclarationDescriptor +import org.jetbrains.kotlin.ir.descriptors.* import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.util.UniqId -abstract class IrSymbolBase(override val descriptor: D) : IrSymbol +abstract class IrSymbolBase(override val descriptor: D, override var uniqId: UniqId = UniqId.NONE) : IrSymbol -abstract class IrBindableSymbolBase(descriptor: D) : - IrBindableSymbol, IrSymbolBase(descriptor) { +abstract class IrBindableSymbolBase(descriptor: D, uniqId: UniqId = UniqId.NONE) : + IrBindableSymbol, IrSymbolBase(descriptor, uniqId) { init { assert(isOriginalDescriptor(descriptor)) { @@ -68,50 +69,70 @@ class IrAnonymousInitializerSymbolImpl(descriptor: ClassDescriptor) : constructor(irClassSymbol: IrClassSymbol) : this(irClassSymbol.descriptor) {} } -class IrClassSymbolImpl(descriptor: ClassDescriptor) : - IrBindableSymbolBase(descriptor), - IrClassSymbol +class IrClassSymbolImpl(descriptor: ClassDescriptor, uniqId: UniqId = UniqId.NONE) : + IrBindableSymbolBase(descriptor, uniqId), + IrClassSymbol { + constructor(uniqId: UniqId) : this(WrappedClassDescriptor(), uniqId) +} -class IrEnumEntrySymbolImpl(descriptor: ClassDescriptor) : - IrBindableSymbolBase(descriptor), - IrEnumEntrySymbol +class IrEnumEntrySymbolImpl(descriptor: ClassDescriptor, uniqId: UniqId = UniqId.NONE) : + IrBindableSymbolBase(descriptor, uniqId), + IrEnumEntrySymbol { + constructor(uniqId: UniqId) : this(WrappedEnumEntryDescriptor(), uniqId) +} -class IrFieldSymbolImpl(descriptor: PropertyDescriptor) : - IrBindableSymbolBase(descriptor), - IrFieldSymbol +class IrFieldSymbolImpl(descriptor: PropertyDescriptor, uniqId: UniqId = UniqId.NONE) : + IrBindableSymbolBase(descriptor, uniqId), + IrFieldSymbol { + constructor(uniqId: UniqId) : this(WrappedFieldDescriptor(), uniqId) +} -class IrTypeParameterSymbolImpl(descriptor: TypeParameterDescriptor) : - IrBindableSymbolBase(descriptor), - IrTypeParameterSymbol +class IrTypeParameterSymbolImpl(descriptor: TypeParameterDescriptor, uniqId: UniqId = UniqId.NONE) : + IrBindableSymbolBase(descriptor, uniqId), + IrTypeParameterSymbol { + constructor(uniqId: UniqId) : this(WrappedTypeParameterDescriptor(), uniqId) +} -class IrValueParameterSymbolImpl(descriptor: ParameterDescriptor) : - IrBindableSymbolBase(descriptor), - IrValueParameterSymbol +class IrValueParameterSymbolImpl(descriptor: ParameterDescriptor, uniqId: UniqId = UniqId.NONE) : + IrBindableSymbolBase(descriptor, uniqId), + IrValueParameterSymbol { + constructor(uniqId: UniqId) : this(WrappedValueParameterDescriptor(), uniqId) +} -class IrVariableSymbolImpl(descriptor: VariableDescriptor) : - IrBindableSymbolBase(descriptor), - IrVariableSymbol +class IrVariableSymbolImpl(descriptor: VariableDescriptor, uniqId: UniqId = UniqId.NONE) : + IrBindableSymbolBase(descriptor, uniqId), + IrVariableSymbol { + constructor(uniqId: UniqId) : this(WrappedVariableDescriptor(), uniqId) +} -class IrSimpleFunctionSymbolImpl(descriptor: FunctionDescriptor) : - IrBindableSymbolBase(descriptor), - IrSimpleFunctionSymbol +class IrSimpleFunctionSymbolImpl(descriptor: FunctionDescriptor, uniqId: UniqId = UniqId.NONE) : + IrBindableSymbolBase(descriptor, uniqId), + IrSimpleFunctionSymbol { + constructor(uniqId: UniqId) : this(WrappedSimpleFunctionDescriptor(), uniqId) +} -class IrConstructorSymbolImpl(descriptor: ClassConstructorDescriptor) : - IrBindableSymbolBase(descriptor), - IrConstructorSymbol +class IrConstructorSymbolImpl(descriptor: ClassConstructorDescriptor, uniqId: UniqId = UniqId.NONE) : + IrBindableSymbolBase(descriptor, uniqId), + IrConstructorSymbol { + constructor(uniqId: UniqId) : this(WrappedClassConstructorDescriptor(), uniqId) +} class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor) : IrBindableSymbolBase(descriptor), IrReturnableBlockSymbol -class IrPropertySymbolImpl(descriptor: PropertyDescriptor) : - IrBindableSymbolBase(descriptor), - IrPropertySymbol +class IrPropertySymbolImpl(descriptor: PropertyDescriptor, uniqId: UniqId = UniqId.NONE) : + IrBindableSymbolBase(descriptor, uniqId), + IrPropertySymbol { + constructor(uniqId: UniqId) : this(WrappedPropertyDescriptor(), uniqId) +} class IrLocalDelegatedPropertySymbolImpl(descriptor: VariableDescriptorWithAccessors) : IrBindableSymbolBase(descriptor), IrLocalDelegatedPropertySymbol -class IrTypeAliasSymbolImpl(descriptor: TypeAliasDescriptor) : - IrBindableSymbolBase(descriptor), - IrTypeAliasSymbol \ No newline at end of file +class IrTypeAliasSymbolImpl(descriptor: TypeAliasDescriptor, uniqId: UniqId = UniqId.NONE) : + IrBindableSymbolBase(descriptor, uniqId), + IrTypeAliasSymbol { + constructor(uniqId: UniqId) : this(WrappedTypeAliasDescriptor(), uniqId) +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt index 808f1b66042..addc403ffe2 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyDeclarationBase @@ -29,6 +30,9 @@ import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.* import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid interface IrProvider { fun getDeclaration(symbol: IrSymbol): IrDeclaration? @@ -69,18 +73,48 @@ interface ReferenceSymbolTable { fun enterScope(owner: DeclarationDescriptor) fun leaveScope(owner: DeclarationDescriptor) + + // Referencing by UniqId produces symbols with WrappedDescriptor + fun referenceClass(uniqId: UniqId): IrClassSymbol + fun referenceConstructor(uniqId: UniqId): IrConstructorSymbol + fun referenceEnumEntry(uniqId: UniqId): IrEnumEntrySymbol + fun referenceField(uniqId: UniqId): IrFieldSymbol + fun referenceProperty(uniqId: UniqId): IrPropertySymbol + fun referenceSimpleFunction(uniqId: UniqId): IrSimpleFunctionSymbol + fun referenceTypeParameter(uniqId: UniqId): IrTypeParameterSymbol + fun referenceTypeAlias(uniqId: UniqId): IrTypeAliasSymbol + + // Should only be called when the declaration is in a `ready` state -- with a full chain of parents, + // type and value parameters etc. + fun computeUniqId(declaration: IrDeclaration) } -open class SymbolTable : ReferenceSymbolTable { +open class SymbolTable(val mangler: KotlinMangler? = null) : ReferenceSymbolTable { @Suppress("LeakingThis") val lazyWrapper = IrLazySymbolTable(this) - private abstract class SymbolTableBase> { + private fun IrSymbolOwner.getUniqId() = mangler?.run { + (this@getUniqId as? IrDeclaration)?.hashedMangle?.let { UniqId(it) } ?: UniqId.NONE + } ?: UniqId.NONE + + fun IrSymbol.setUniqId() { + if (isBound) { + val oldUid = uniqId + val newUid = owner.getUniqId() + assert(oldUid == UniqId.NONE || oldUid == newUid) + uniqId = newUid + } + } + + private abstract inner class SymbolTableBase> { val unboundSymbols = linkedSetOf() + val unboundUniqIds = linkedSetOf() abstract fun get(d: D): S? abstract fun set(d: D, s: S) + abstract fun get(uid: UniqId): S? + abstract fun set(uid: UniqId, s: S) inline fun declare(d: D, createSymbol: () -> S, createOwner: (S) -> B): B { @Suppress("UNCHECKED_CAST") @@ -100,6 +134,14 @@ open class SymbolTable : ReferenceSymbolTable { return createOwner(symbol) } + fun computeUniqId(b: B) { + if (b !is IrDeclaration) return + val symbol = b.symbol as S + symbol.setUniqId() + set(symbol.uniqId, symbol) + unboundSymbols.remove(symbol) + } + inline fun referenced(d: D, orElse: () -> S): S { @Suppress("UNCHECKED_CAST") val d0 = d.original as D @@ -117,23 +159,44 @@ open class SymbolTable : ReferenceSymbolTable { } return s } + + inline fun referenced(uid: UniqId, orElse: () -> S): S { + return get(uid) ?: run { + val new = orElse() + assert(unboundSymbols.add(new)) { + "Symbol for ${new.uniqId} was already referenced" + } + set(uid, new) + set(new.descriptor, new) + new + } + } } - private class FlatSymbolTable> + private inner class FlatSymbolTable> : SymbolTableBase() { val descriptorToSymbol = linkedMapOf() + val uniqIdToSymbol = linkedMapOf() override fun get(d: D): S? = descriptorToSymbol[d] override fun set(d: D, s: S) { descriptorToSymbol[d] = s } + + override fun get(uid: UniqId): S? = uniqIdToSymbol[uid] + override fun set(uid: UniqId, s: S) { + if (uid != UniqId.NONE) { + uniqIdToSymbol[uid] = s + } + } } - private class ScopedSymbolTable> + private inner class ScopedSymbolTable> : SymbolTableBase() { inner class Scope(val owner: DeclarationDescriptor, val parent: Scope?) { private val descriptorToSymbol = linkedMapOf() + private val uniqIdToSymbol = linkedMapOf() operator fun get(d: D): S? = descriptorToSymbol[d] ?: parent?.get(d) @@ -144,6 +207,15 @@ open class SymbolTable : ReferenceSymbolTable { descriptorToSymbol[d] = s } + operator fun get(uid: UniqId): S? = + uniqIdToSymbol[uid] ?: parent?.get(uid) + + operator fun set(uid: UniqId, s: S) { + if (uid != UniqId.NONE) { + uniqIdToSymbol[uid] = s + } + } + fun dumpTo(stringBuilder: StringBuilder): StringBuilder = stringBuilder.also { it.append("owner=") @@ -169,6 +241,16 @@ open class SymbolTable : ReferenceSymbolTable { scope[d] = s } + override fun get(uid: UniqId): S? { + val scope = currentScope ?: return null + return scope[uid] + } + + override fun set(uid: UniqId, s: S) { + val scope = currentScope ?: throw AssertionError("No active scope") + scope[uid] = s + } + inline fun declareLocal(d: D, createSymbol: () -> S, createOwner: (S) -> B): B { val scope = currentScope ?: throw AssertionError("No active scope") val symbol = scope.getLocal(d) ?: createSymbol().also { scope[d] = it } @@ -277,6 +359,9 @@ open class SymbolTable : ReferenceSymbolTable { override fun referenceClass(descriptor: ClassDescriptor) = classSymbolTable.referenced(descriptor) { IrClassSymbolImpl(descriptor) } + override fun referenceClass(uniqId: UniqId): IrClassSymbol = + classSymbolTable.referenced(uniqId) { IrClassSymbolImpl(uniqId) } + val unboundClasses: Set get() = classSymbolTable.unboundSymbols fun declareConstructor( @@ -299,6 +384,9 @@ open class SymbolTable : ReferenceSymbolTable { override fun referenceConstructor(descriptor: ClassConstructorDescriptor) = constructorSymbolTable.referenced(descriptor) { IrConstructorSymbolImpl(descriptor) } + override fun referenceConstructor(uniqId: UniqId): IrConstructorSymbol = + constructorSymbolTable.referenced(uniqId) { IrConstructorSymbolImpl(uniqId) } + val unboundConstructors: Set get() = constructorSymbolTable.unboundSymbols fun declareEnumEntry( @@ -314,6 +402,9 @@ open class SymbolTable : ReferenceSymbolTable { override fun referenceEnumEntry(descriptor: ClassDescriptor) = enumEntrySymbolTable.referenced(descriptor) { IrEnumEntrySymbolImpl(descriptor) } + override fun referenceEnumEntry(uniqId: UniqId): IrEnumEntrySymbol = + enumEntrySymbolTable.referenced(uniqId) { IrEnumEntrySymbolImpl(uniqId) } + val unboundEnumEntries: Set get() = enumEntrySymbolTable.unboundSymbols fun declareField( @@ -350,6 +441,9 @@ open class SymbolTable : ReferenceSymbolTable { override fun referenceField(descriptor: PropertyDescriptor) = fieldSymbolTable.referenced(descriptor) { IrFieldSymbolImpl(descriptor) } + override fun referenceField(uniqId: UniqId) = + fieldSymbolTable.referenced(uniqId) { IrFieldSymbolImpl(uniqId) } + val unboundFields: Set get() = fieldSymbolTable.unboundSymbols @Deprecated(message = "Use declareProperty/referenceProperty", level = DeprecationLevel.WARNING) @@ -379,11 +473,17 @@ open class SymbolTable : ReferenceSymbolTable { fun referenceProperty(descriptor: PropertyDescriptor): IrPropertySymbol = propertySymbolTable.referenced(descriptor) { IrPropertySymbolImpl(descriptor) } + override fun referenceProperty(uniqId: UniqId): IrPropertySymbol = + propertySymbolTable.referenced(uniqId) { IrPropertySymbolImpl(uniqId) } + val unboundProperties: Set get() = propertySymbolTable.unboundSymbols override fun referenceTypeAlias(descriptor: TypeAliasDescriptor): IrTypeAliasSymbol = typeAliasSymbolTable.referenced(descriptor) { IrTypeAliasSymbolImpl(descriptor) } + override fun referenceTypeAlias(uniqId: UniqId): IrTypeAliasSymbol = + typeAliasSymbolTable.referenced(uniqId) { IrTypeAliasSymbolImpl(uniqId) } + fun declareTypeAlias(descriptor: TypeAliasDescriptor, factory: (IrTypeAliasSymbol) -> IrTypeAlias): IrTypeAlias = typeAliasSymbolTable.declare(descriptor, { IrTypeAliasSymbolImpl(descriptor) }, factory) @@ -410,6 +510,9 @@ open class SymbolTable : ReferenceSymbolTable { override fun referenceSimpleFunction(descriptor: FunctionDescriptor) = simpleFunctionSymbolTable.referenced(descriptor) { IrSimpleFunctionSymbolImpl(descriptor) } + override fun referenceSimpleFunction(uniqId: UniqId): IrSimpleFunctionSymbol = + simpleFunctionSymbolTable.referenced(uniqId) { IrSimpleFunctionSymbolImpl(uniqId) } + override fun referenceDeclaredFunction(descriptor: FunctionDescriptor) = simpleFunctionSymbolTable.referenced(descriptor) { throw AssertionError("Function is not declared: $descriptor") } @@ -475,7 +578,10 @@ open class SymbolTable : ReferenceSymbolTable { IrTypeParameterSymbolImpl(classifier) } - val unboundValueParameters: Set get() = valueParameterSymbolTable.unboundSymbols + override fun referenceTypeParameter(uniqId: UniqId): IrTypeParameterSymbol = + scopedTypeParameterSymbolTable.get(uniqId) ?: globalTypeParameterSymbolTable.referenced(uniqId) { + IrTypeParameterSymbolImpl(uniqId) + } fun declareVariable( startOffset: Int, @@ -509,8 +615,6 @@ open class SymbolTable : ReferenceSymbolTable { override fun referenceVariable(descriptor: VariableDescriptor) = variableSymbolTable.referenced(descriptor) { throw AssertionError("Undefined variable referenced: $descriptor") } - val unboundVariables: Set get() = variableSymbolTable.unboundSymbols - fun declareLocalDelegatedProperty( startOffset: Int, endOffset: Int, @@ -546,6 +650,24 @@ open class SymbolTable : ReferenceSymbolTable { else -> throw IllegalArgumentException("Unexpected value descriptor: $value") } + + override fun computeUniqId(declaration: IrDeclaration) { + if (mangler == null) return + with(mangler) { + if (!declaration.isExported()) return + } + when(declaration) { + is IrConstructor -> constructorSymbolTable.computeUniqId(declaration) + is IrClass -> classSymbolTable.computeUniqId(declaration) + is IrEnumEntry -> enumEntrySymbolTable.computeUniqId(declaration) + is IrField -> fieldSymbolTable.computeUniqId(declaration) + is IrProperty -> propertySymbolTable.computeUniqId(declaration) + is IrSimpleFunction -> simpleFunctionSymbolTable.computeUniqId(declaration) + is IrTypeAlias -> typeAliasSymbolTable.computeUniqId(declaration) + is IrTypeParameter -> globalTypeParameterSymbolTable.computeUniqId(declaration) + else -> { /* do nothing */ } + } + } } inline fun SymbolTable.withScope(owner: D, block: SymbolTable.(D) -> T): T { @@ -554,3 +676,18 @@ inline fun SymbolTable.withScope(owner: D, block: leaveScope(owner) return result } + +fun IrElement.computeUniqIdForDeclarations(symbolTable: SymbolTable) { + acceptVoid(ComputeUniqIdVisitor(symbolTable)) +} + +private class ComputeUniqIdVisitor(val symbolTable: SymbolTable) : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitDeclaration(declaration: IrDeclaration) { + symbolTable.computeUniqId(declaration) + super.visitDeclaration(declaration) + } +}