//===- SymbolTable.cpp - MLIR Symbol Table Class --------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "mlir/IR/SymbolTable.h" #include "mlir/IR/Builders.h" #include "mlir/IR/OpImplementation.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include <optional> usingnamespacemlir; /// Return true if the given operation is unknown and may potentially define a /// symbol table. static bool isPotentiallyUnknownSymbolTable(Operation *op) { … } /// Returns the string name of the given symbol, or null if this is not a /// symbol. static StringAttr getNameIfSymbol(Operation *op) { … } static StringAttr getNameIfSymbol(Operation *op, StringAttr symbolAttrNameId) { … } /// Computes the nested symbol reference attribute for the symbol 'symbolName' /// that are usable within the symbol table operations from 'symbol' as far up /// to the given operation 'within', where 'within' is an ancestor of 'symbol'. /// Returns success if all references up to 'within' could be computed. static LogicalResult collectValidReferencesFor(Operation *symbol, StringAttr symbolName, Operation *within, SmallVectorImpl<SymbolRefAttr> &results) { … } /// Walk all of the operations within the given set of regions, without /// traversing into any nested symbol tables. Stops walking if the result of the /// callback is anything other than `WalkResult::advance`. static std::optional<WalkResult> walkSymbolTable(MutableArrayRef<Region> regions, function_ref<std::optional<WalkResult>(Operation *)> callback) { … } /// Walk all of the operations nested under, and including, the given operation, /// without traversing into any nested symbol tables. Stops walking if the /// result of the callback is anything other than `WalkResult::advance`. static std::optional<WalkResult> walkSymbolTable(Operation *op, function_ref<std::optional<WalkResult>(Operation *)> callback) { … } //===----------------------------------------------------------------------===// // SymbolTable //===----------------------------------------------------------------------===// /// Build a symbol table with the symbols within the given operation. SymbolTable::SymbolTable(Operation *symbolTableOp) : … { … } /// Look up a symbol with the specified name, returning null if no such name /// exists. Names never include the @ on them. Operation *SymbolTable::lookup(StringRef name) const { … } Operation *SymbolTable::lookup(StringAttr name) const { … } void SymbolTable::remove(Operation *op) { … } void SymbolTable::erase(Operation *symbol) { … } // TODO: Consider if this should be renamed to something like insertOrUpdate /// Insert a new symbol into the table and associated operation if not already /// there and rename it as necessary to avoid collisions. Return the name of /// the symbol after insertion as attribute. StringAttr SymbolTable::insert(Operation *symbol, Block::iterator insertPt) { … } LogicalResult SymbolTable::rename(StringAttr from, StringAttr to) { … } LogicalResult SymbolTable::rename(Operation *op, StringAttr to) { … } LogicalResult SymbolTable::rename(StringAttr from, StringRef to) { … } LogicalResult SymbolTable::rename(Operation *op, StringRef to) { … } FailureOr<StringAttr> SymbolTable::renameToUnique(StringAttr oldName, ArrayRef<SymbolTable *> others) { … } FailureOr<StringAttr> SymbolTable::renameToUnique(Operation *op, ArrayRef<SymbolTable *> others) { … } /// Returns the name of the given symbol operation. StringAttr SymbolTable::getSymbolName(Operation *symbol) { … } /// Sets the name of the given symbol operation. void SymbolTable::setSymbolName(Operation *symbol, StringAttr name) { … } /// Returns the visibility of the given symbol operation. SymbolTable::Visibility SymbolTable::getSymbolVisibility(Operation *symbol) { … } /// Sets the visibility of the given symbol operation. void SymbolTable::setSymbolVisibility(Operation *symbol, Visibility vis) { … } /// Returns the nearest symbol table from a given operation `from`. Returns /// nullptr if no valid parent symbol table could be found. Operation *SymbolTable::getNearestSymbolTable(Operation *from) { … } /// Walks all symbol table operations nested within, and including, `op`. For /// each symbol table operation, the provided callback is invoked with the op /// and a boolean signifying if the symbols within that symbol table can be /// treated as if all uses are visible. `allSymUsesVisible` identifies whether /// all of the symbol uses of symbols within `op` are visible. void SymbolTable::walkSymbolTables( Operation *op, bool allSymUsesVisible, function_ref<void(Operation *, bool)> callback) { … } /// Returns the operation registered with the given symbol name with the /// regions of 'symbolTableOp'. 'symbolTableOp' is required to be an operation /// with the 'OpTrait::SymbolTable' trait. Returns nullptr if no valid symbol /// was found. Operation *SymbolTable::lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol) { … } Operation *SymbolTable::lookupSymbolIn(Operation *symbolTableOp, SymbolRefAttr symbol) { … } /// Internal implementation of `lookupSymbolIn` that allows for specialized /// implementations of the lookup function. static LogicalResult lookupSymbolInImpl( Operation *symbolTableOp, SymbolRefAttr symbol, SmallVectorImpl<Operation *> &symbols, function_ref<Operation *(Operation *, StringAttr)> lookupSymbolFn) { … } LogicalResult SymbolTable::lookupSymbolIn(Operation *symbolTableOp, SymbolRefAttr symbol, SmallVectorImpl<Operation *> &symbols) { … } /// Returns the operation registered with the given symbol name within the /// closes parent operation with the 'OpTrait::SymbolTable' trait. Returns /// nullptr if no valid symbol was found. Operation *SymbolTable::lookupNearestSymbolFrom(Operation *from, StringAttr symbol) { … } Operation *SymbolTable::lookupNearestSymbolFrom(Operation *from, SymbolRefAttr symbol) { … } raw_ostream &mlir::operator<<(raw_ostream &os, SymbolTable::Visibility visibility) { … } //===----------------------------------------------------------------------===// // SymbolTable Trait Types //===----------------------------------------------------------------------===// LogicalResult detail::verifySymbolTable(Operation *op) { … } LogicalResult detail::verifySymbol(Operation *op) { … } //===----------------------------------------------------------------------===// // Symbol Use Lists //===----------------------------------------------------------------------===// /// Walk all of the symbol references within the given operation, invoking the /// provided callback for each found use. The callbacks takes the use of the /// symbol. static WalkResult walkSymbolRefs(Operation *op, function_ref<WalkResult(SymbolTable::SymbolUse)> callback) { … } /// Walk all of the uses, for any symbol, that are nested within the given /// regions, invoking the provided callback for each. This does not traverse /// into any nested symbol tables. static std::optional<WalkResult> walkSymbolUses(MutableArrayRef<Region> regions, function_ref<WalkResult(SymbolTable::SymbolUse)> callback) { … } /// Walk all of the uses, for any symbol, that are nested within the given /// operation 'from', invoking the provided callback for each. This does not /// traverse into any nested symbol tables. static std::optional<WalkResult> walkSymbolUses(Operation *from, function_ref<WalkResult(SymbolTable::SymbolUse)> callback) { … } namespace { /// This class represents a single symbol scope. A symbol scope represents the /// set of operations nested within a symbol table that may reference symbols /// within that table. A symbol scope does not contain the symbol table /// operation itself, just its contained operations. A scope ends at leaf /// operations or another symbol table operation. struct SymbolScope { … }; } // namespace /// Collect all of the symbol scopes from 'symbol' to (inclusive) 'limit'. static SmallVector<SymbolScope, 2> collectSymbolScopes(Operation *symbol, Operation *limit) { … } static SmallVector<SymbolScope, 2> collectSymbolScopes(Operation *symbol, Region *limit) { … } static SmallVector<SymbolScope, 1> collectSymbolScopes(StringAttr symbol, Region *limit) { … } static SmallVector<SymbolScope, 1> collectSymbolScopes(StringAttr symbol, Operation *limit) { … } /// Returns true if the given reference 'SubRef' is a sub reference of the /// reference 'ref', i.e. 'ref' is a further qualified reference. static bool isReferencePrefixOf(SymbolRefAttr subRef, SymbolRefAttr ref) { … } //===----------------------------------------------------------------------===// // SymbolTable::getSymbolUses /// The implementation of SymbolTable::getSymbolUses below. template <typename FromT> static std::optional<SymbolTable::UseRange> getSymbolUsesImpl(FromT from) { … } /// Get an iterator range for all of the uses, for any symbol, that are nested /// within the given operation 'from'. This does not traverse into any nested /// symbol tables, and will also only return uses on 'from' if it does not /// also define a symbol table. This is because we treat the region as the /// boundary of the symbol table, and not the op itself. This function returns /// std::nullopt if there are any unknown operations that may potentially be /// symbol tables. auto SymbolTable::getSymbolUses(Operation *from) -> std::optional<UseRange> { … } auto SymbolTable::getSymbolUses(Region *from) -> std::optional<UseRange> { … } //===----------------------------------------------------------------------===// // SymbolTable::getSymbolUses /// The implementation of SymbolTable::getSymbolUses below. template <typename SymbolT, typename IRUnitT> static std::optional<SymbolTable::UseRange> getSymbolUsesImpl(SymbolT symbol, IRUnitT *limit) { … } /// Get all of the uses of the given symbol that are nested within the given /// operation 'from', invoking the provided callback for each. This does not /// traverse into any nested symbol tables. This function returns std::nullopt /// if there are any unknown operations that may potentially be symbol tables. auto SymbolTable::getSymbolUses(StringAttr symbol, Operation *from) -> std::optional<UseRange> { … } auto SymbolTable::getSymbolUses(Operation *symbol, Operation *from) -> std::optional<UseRange> { … } auto SymbolTable::getSymbolUses(StringAttr symbol, Region *from) -> std::optional<UseRange> { … } auto SymbolTable::getSymbolUses(Operation *symbol, Region *from) -> std::optional<UseRange> { … } //===----------------------------------------------------------------------===// // SymbolTable::symbolKnownUseEmpty /// The implementation of SymbolTable::symbolKnownUseEmpty below. template <typename SymbolT, typename IRUnitT> static bool symbolKnownUseEmptyImpl(SymbolT symbol, IRUnitT *limit) { … } /// Return if the given symbol is known to have no uses that are nested within /// the given operation 'from'. This does not traverse into any nested symbol /// tables. This function will also return false if there are any unknown /// operations that may potentially be symbol tables. bool SymbolTable::symbolKnownUseEmpty(StringAttr symbol, Operation *from) { … } bool SymbolTable::symbolKnownUseEmpty(Operation *symbol, Operation *from) { … } bool SymbolTable::symbolKnownUseEmpty(StringAttr symbol, Region *from) { … } bool SymbolTable::symbolKnownUseEmpty(Operation *symbol, Region *from) { … } //===----------------------------------------------------------------------===// // SymbolTable::replaceAllSymbolUses /// Generates a new symbol reference attribute with a new leaf reference. static SymbolRefAttr generateNewRefAttr(SymbolRefAttr oldAttr, FlatSymbolRefAttr newLeafAttr) { … } /// The implementation of SymbolTable::replaceAllSymbolUses below. template <typename SymbolT, typename IRUnitT> static LogicalResult replaceAllSymbolUsesImpl(SymbolT symbol, StringAttr newSymbol, IRUnitT *limit) { … } /// Attempt to replace all uses of the given symbol 'oldSymbol' with the /// provided symbol 'newSymbol' that are nested within the given operation /// 'from'. This does not traverse into any nested symbol tables. If there are /// any unknown operations that may potentially be symbol tables, no uses are /// replaced and failure is returned. LogicalResult SymbolTable::replaceAllSymbolUses(StringAttr oldSymbol, StringAttr newSymbol, Operation *from) { … } LogicalResult SymbolTable::replaceAllSymbolUses(Operation *oldSymbol, StringAttr newSymbol, Operation *from) { … } LogicalResult SymbolTable::replaceAllSymbolUses(StringAttr oldSymbol, StringAttr newSymbol, Region *from) { … } LogicalResult SymbolTable::replaceAllSymbolUses(Operation *oldSymbol, StringAttr newSymbol, Region *from) { … } //===----------------------------------------------------------------------===// // SymbolTableCollection //===----------------------------------------------------------------------===// Operation *SymbolTableCollection::lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol) { … } Operation *SymbolTableCollection::lookupSymbolIn(Operation *symbolTableOp, SymbolRefAttr name) { … } /// A variant of 'lookupSymbolIn' that returns all of the symbols referenced by /// a given SymbolRefAttr. Returns failure if any of the nested references could /// not be resolved. LogicalResult SymbolTableCollection::lookupSymbolIn(Operation *symbolTableOp, SymbolRefAttr name, SmallVectorImpl<Operation *> &symbols) { … } /// Returns the operation registered with the given symbol name within the /// closest parent operation of, or including, 'from' with the /// 'OpTrait::SymbolTable' trait. Returns nullptr if no valid symbol was /// found. Operation *SymbolTableCollection::lookupNearestSymbolFrom(Operation *from, StringAttr symbol) { … } Operation * SymbolTableCollection::lookupNearestSymbolFrom(Operation *from, SymbolRefAttr symbol) { … } /// Lookup, or create, a symbol table for an operation. SymbolTable &SymbolTableCollection::getSymbolTable(Operation *op) { … } //===----------------------------------------------------------------------===// // LockedSymbolTableCollection //===----------------------------------------------------------------------===// Operation *LockedSymbolTableCollection::lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol) { … } Operation * LockedSymbolTableCollection::lookupSymbolIn(Operation *symbolTableOp, FlatSymbolRefAttr symbol) { … } Operation *LockedSymbolTableCollection::lookupSymbolIn(Operation *symbolTableOp, SymbolRefAttr name) { … } LogicalResult LockedSymbolTableCollection::lookupSymbolIn( Operation *symbolTableOp, SymbolRefAttr name, SmallVectorImpl<Operation *> &symbols) { … } SymbolTable & LockedSymbolTableCollection::getSymbolTable(Operation *symbolTableOp) { … } //===----------------------------------------------------------------------===// // SymbolUserMap //===----------------------------------------------------------------------===// SymbolUserMap::SymbolUserMap(SymbolTableCollection &symbolTable, Operation *symbolTableOp) : … { … } void SymbolUserMap::replaceAllUsesWith(Operation *symbol, StringAttr newSymbolName) { … } //===----------------------------------------------------------------------===// // Visibility parsing implementation. //===----------------------------------------------------------------------===// ParseResult impl::parseOptionalVisibilityKeyword(OpAsmParser &parser, NamedAttrList &attrs) { … } //===----------------------------------------------------------------------===// // Symbol Interfaces //===----------------------------------------------------------------------===// /// Include the generated symbol interfaces. #include "mlir/IR/SymbolInterfaces.cpp.inc"