IR: Add UniqId to IrSymbol

This commit is contained in:
Georgy Bronnikov
2019-11-11 14:51:20 +03:00
parent 1647279a8c
commit c5159d9cbe
5 changed files with 216 additions and 42 deletions
@@ -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
}
@@ -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) {
@@ -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 <D, R> accept(visitor: IrSymbolVisitor<R, D>, data: D): R
}
@@ -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<out D : DeclarationDescriptor>(override val descriptor: D) : IrSymbol
abstract class IrSymbolBase<out D : DeclarationDescriptor>(override val descriptor: D, override var uniqId: UniqId = UniqId.NONE) : IrSymbol
abstract class IrBindableSymbolBase<out D : DeclarationDescriptor, B : IrSymbolOwner>(descriptor: D) :
IrBindableSymbol<D, B>, IrSymbolBase<D>(descriptor) {
abstract class IrBindableSymbolBase<out D : DeclarationDescriptor, B : IrSymbolOwner>(descriptor: D, uniqId: UniqId = UniqId.NONE) :
IrBindableSymbol<D, B>, IrSymbolBase<D>(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<ClassDescriptor, IrClass>(descriptor),
IrClassSymbol
class IrClassSymbolImpl(descriptor: ClassDescriptor, uniqId: UniqId = UniqId.NONE) :
IrBindableSymbolBase<ClassDescriptor, IrClass>(descriptor, uniqId),
IrClassSymbol {
constructor(uniqId: UniqId) : this(WrappedClassDescriptor(), uniqId)
}
class IrEnumEntrySymbolImpl(descriptor: ClassDescriptor) :
IrBindableSymbolBase<ClassDescriptor, IrEnumEntry>(descriptor),
IrEnumEntrySymbol
class IrEnumEntrySymbolImpl(descriptor: ClassDescriptor, uniqId: UniqId = UniqId.NONE) :
IrBindableSymbolBase<ClassDescriptor, IrEnumEntry>(descriptor, uniqId),
IrEnumEntrySymbol {
constructor(uniqId: UniqId) : this(WrappedEnumEntryDescriptor(), uniqId)
}
class IrFieldSymbolImpl(descriptor: PropertyDescriptor) :
IrBindableSymbolBase<PropertyDescriptor, IrField>(descriptor),
IrFieldSymbol
class IrFieldSymbolImpl(descriptor: PropertyDescriptor, uniqId: UniqId = UniqId.NONE) :
IrBindableSymbolBase<PropertyDescriptor, IrField>(descriptor, uniqId),
IrFieldSymbol {
constructor(uniqId: UniqId) : this(WrappedFieldDescriptor(), uniqId)
}
class IrTypeParameterSymbolImpl(descriptor: TypeParameterDescriptor) :
IrBindableSymbolBase<TypeParameterDescriptor, IrTypeParameter>(descriptor),
IrTypeParameterSymbol
class IrTypeParameterSymbolImpl(descriptor: TypeParameterDescriptor, uniqId: UniqId = UniqId.NONE) :
IrBindableSymbolBase<TypeParameterDescriptor, IrTypeParameter>(descriptor, uniqId),
IrTypeParameterSymbol {
constructor(uniqId: UniqId) : this(WrappedTypeParameterDescriptor(), uniqId)
}
class IrValueParameterSymbolImpl(descriptor: ParameterDescriptor) :
IrBindableSymbolBase<ParameterDescriptor, IrValueParameter>(descriptor),
IrValueParameterSymbol
class IrValueParameterSymbolImpl(descriptor: ParameterDescriptor, uniqId: UniqId = UniqId.NONE) :
IrBindableSymbolBase<ParameterDescriptor, IrValueParameter>(descriptor, uniqId),
IrValueParameterSymbol {
constructor(uniqId: UniqId) : this(WrappedValueParameterDescriptor(), uniqId)
}
class IrVariableSymbolImpl(descriptor: VariableDescriptor) :
IrBindableSymbolBase<VariableDescriptor, IrVariable>(descriptor),
IrVariableSymbol
class IrVariableSymbolImpl(descriptor: VariableDescriptor, uniqId: UniqId = UniqId.NONE) :
IrBindableSymbolBase<VariableDescriptor, IrVariable>(descriptor, uniqId),
IrVariableSymbol {
constructor(uniqId: UniqId) : this(WrappedVariableDescriptor(), uniqId)
}
class IrSimpleFunctionSymbolImpl(descriptor: FunctionDescriptor) :
IrBindableSymbolBase<FunctionDescriptor, IrSimpleFunction>(descriptor),
IrSimpleFunctionSymbol
class IrSimpleFunctionSymbolImpl(descriptor: FunctionDescriptor, uniqId: UniqId = UniqId.NONE) :
IrBindableSymbolBase<FunctionDescriptor, IrSimpleFunction>(descriptor, uniqId),
IrSimpleFunctionSymbol {
constructor(uniqId: UniqId) : this(WrappedSimpleFunctionDescriptor(), uniqId)
}
class IrConstructorSymbolImpl(descriptor: ClassConstructorDescriptor) :
IrBindableSymbolBase<ClassConstructorDescriptor, IrConstructor>(descriptor),
IrConstructorSymbol
class IrConstructorSymbolImpl(descriptor: ClassConstructorDescriptor, uniqId: UniqId = UniqId.NONE) :
IrBindableSymbolBase<ClassConstructorDescriptor, IrConstructor>(descriptor, uniqId),
IrConstructorSymbol {
constructor(uniqId: UniqId) : this(WrappedClassConstructorDescriptor(), uniqId)
}
class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor) :
IrBindableSymbolBase<FunctionDescriptor, IrReturnableBlock>(descriptor),
IrReturnableBlockSymbol
class IrPropertySymbolImpl(descriptor: PropertyDescriptor) :
IrBindableSymbolBase<PropertyDescriptor, IrProperty>(descriptor),
IrPropertySymbol
class IrPropertySymbolImpl(descriptor: PropertyDescriptor, uniqId: UniqId = UniqId.NONE) :
IrBindableSymbolBase<PropertyDescriptor, IrProperty>(descriptor, uniqId),
IrPropertySymbol {
constructor(uniqId: UniqId) : this(WrappedPropertyDescriptor(), uniqId)
}
class IrLocalDelegatedPropertySymbolImpl(descriptor: VariableDescriptorWithAccessors) :
IrBindableSymbolBase<VariableDescriptorWithAccessors, IrLocalDelegatedProperty>(descriptor),
IrLocalDelegatedPropertySymbol
class IrTypeAliasSymbolImpl(descriptor: TypeAliasDescriptor) :
IrBindableSymbolBase<TypeAliasDescriptor, IrTypeAlias>(descriptor),
IrTypeAliasSymbol
class IrTypeAliasSymbolImpl(descriptor: TypeAliasDescriptor, uniqId: UniqId = UniqId.NONE) :
IrBindableSymbolBase<TypeAliasDescriptor, IrTypeAlias>(descriptor, uniqId),
IrTypeAliasSymbol {
constructor(uniqId: UniqId) : this(WrappedTypeAliasDescriptor(), uniqId)
}
@@ -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<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> {
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<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> {
val unboundSymbols = linkedSetOf<S>()
val unboundUniqIds = linkedSetOf<UniqId>()
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<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>>
private inner class FlatSymbolTable<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>>
: SymbolTableBase<D, B, S>() {
val descriptorToSymbol = linkedMapOf<D, S>()
val uniqIdToSymbol = linkedMapOf<UniqId, S>()
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<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>>
private inner class ScopedSymbolTable<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>>
: SymbolTableBase<D, B, S>() {
inner class Scope(val owner: DeclarationDescriptor, val parent: Scope?) {
private val descriptorToSymbol = linkedMapOf<D, S>()
private val uniqIdToSymbol = linkedMapOf<UniqId, S>()
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<IrClassSymbol> 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<IrConstructorSymbol> 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<IrEnumEntrySymbol> 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<IrFieldSymbol> 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<IrPropertySymbol> 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<IrValueParameterSymbol> 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<IrVariableSymbol> 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 <T, D: DeclarationDescriptor> SymbolTable.withScope(owner: D, block: SymbolTable.(D) -> T): T {
@@ -554,3 +676,18 @@ inline fun <T, D: DeclarationDescriptor> 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)
}
}