All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.backend.common.serialization.DeclarationTable.kt Maven / Gradle / Ivy

/*
 * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.backend.common.serialization

import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyDeclarationBase
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns

class DescriptorTable {
    private val descriptors = mutableMapOf()
    fun put(descriptor: DeclarationDescriptor, uniqId: UniqId) {
        descriptors.getOrPut(descriptor) { uniqId.index }
    }

    fun get(descriptor: DeclarationDescriptor) = descriptors[descriptor]
}

interface UniqIdClashTracker {
    fun commit(declaration: IrDeclaration, uniqId: UniqId)

    companion object {
        val DEFAULT_TRACKER = object : UniqIdClashTracker {
            override fun commit(declaration: IrDeclaration, uniqId: UniqId) {}
        }
    }
}

abstract class GlobalDeclarationTable(private val mangler: KotlinMangler, private val clashTracker: UniqIdClashTracker) {
    private val table = mutableMapOf()

    constructor(mangler: KotlinMangler) : this(mangler, UniqIdClashTracker.DEFAULT_TRACKER)

    protected open fun loadKnownBuiltins(builtIns: IrBuiltIns, startIndex: Long): Long {
        var index = startIndex
        builtIns.knownBuiltins.forEach {
            table[it.owner] = UniqId(index++, false).also { id -> clashTracker.commit(it.owner, id) }
        }
        return index
    }

    open fun computeUniqIdByDeclaration(declaration: IrDeclaration): UniqId {
        return table.getOrPut(declaration) {
            with(mangler) {
                UniqId(declaration.hashedMangle, false).also { clashTracker.commit(declaration, it) }
            }
        }
    }

    fun isExportedDeclaration(declaration: IrDeclaration): Boolean = with(mangler) { declaration.isExported() }
}

class DeclarationTable(
    private val descriptorTable: DescriptorTable,
    private val globalDeclarationTable: GlobalDeclarationTable,
    startIndex: Long
) {
    private val table = mutableMapOf()

    private fun IrDeclaration.isLocalDeclaration(): Boolean {
        return origin == IrDeclarationOrigin.FAKE_OVERRIDE || !isExportedDeclaration(this) || this is IrValueDeclaration || this is IrAnonymousInitializer || this is IrLocalDelegatedProperty
    }

    private var localIndex = startIndex

    fun isExportedDeclaration(declaration: IrDeclaration) = globalDeclarationTable.isExportedDeclaration(declaration)

    private fun computeUniqIdByDeclaration(declaration: IrDeclaration): UniqId {
        return if (declaration.isLocalDeclaration()) {
            table.getOrPut(declaration) { UniqId(localIndex++, true) }
        } else globalDeclarationTable.computeUniqIdByDeclaration(declaration)
    }

    fun uniqIdByDeclaration(declaration: IrDeclaration): UniqId {
        val uniqId = computeUniqIdByDeclaration(declaration)
        if (declaration.isMetadataDeclaration(false)) {
            descriptorTable.put(declaration.descriptor, uniqId)
        }
        return uniqId
    }

    private tailrec fun IrDeclaration.isMetadataDeclaration(isTypeParameter: Boolean): Boolean {
        if (this is IrValueDeclaration || this is IrField) {
            return false
        }

        if (origin == IrDeclarationOrigin.FAKE_OVERRIDE || origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER) {
            return false
        }

        if (!isTypeParameter) {
            if (this is IrSimpleFunction) {
                if (correspondingPropertySymbol != null)
                    return false
            }
        }

        if (this is IrDeclarationWithVisibility) {
            if (visibility == Visibilities.LOCAL) {
                return false
            }
        }

        // Currently this check is skipped because LazyIr
        // can be generated by kotlinx-serialization compiler plugin

        // if (this is IrLazyDeclarationBase) return false

        if (parent is IrPackageFragment) return true

        return (parent as IrDeclaration).isMetadataDeclaration(this is IrTypeParameter || isTypeParameter)
    }
}

// This is what we pre-populate tables with
val IrBuiltIns.knownBuiltins
    get() = irBuiltInsSymbols




© 2015 - 2025 Weber Informatics LLC | Privacy Policy