Lines Matching full:symbol

1 //===- SymbolTable.cpp - MLIR Symbol Table Class --------------------------===//
21 /// symbol table.
26 /// Returns the string name of the given symbol, or null if this is not a
27 /// symbol.
35 /// Computes the nested symbol reference attribute for the symbol 'symbolName'
36 /// that are usable within the symbol table operations from 'symbol' as far up
37 /// to the given operation 'within', where 'within' is an ancestor of 'symbol'.
40 collectValidReferencesFor(Operation *symbol, StringAttr symbolName,
43 assert(within->isAncestor(symbol) && "expected 'within' to be an ancestor");
44 MLIRContext *ctx = symbol->getContext();
49 // Early exit for when 'within' is the parent of 'symbol'.
50 Operation *symbolTableOp = symbol->getParentOp();
59 // Each parent of 'symbol' should define a symbol table.
62 // Each parent of 'symbol' should also be a symbol.
78 /// traversing into any nested symbol tables. Stops walking if the result of the
90 // If this op defines a new symbol table scope, we can't traverse. Any
91 // symbol references nested within 'op' are different semantically.
102 /// without traversing into any nested symbol tables. Stops walking if the
117 /// Build a symbol table with the symbols within the given operation.
137 "expected region to contain uniquely named symbol operations");
141 /// Look up a symbol with the specified name, returning null if no such name
162 void SymbolTable::erase(Operation *symbol) {
163 remove(symbol);
164 symbol->erase();
168 /// Insert a new symbol into the table and associated operation if not already
170 /// the symbol after insertion as attribute.
171 StringAttr SymbolTable::insert(Operation *symbol, Block::iterator insertPt) {
172 // The symbol cannot be the child of another op and must be the child of the
176 if (!symbol->getParentOp()) {
190 body.getOperations().insert(insertPt, symbol);
192 assert(symbol->getParentOp() == symbolTableOp &&
193 "symbol is already inserted in another op");
195 // Add this symbol to the symbol table, uniquing the name if a conflict is
197 StringAttr name = getSymbolName(symbol);
198 if (symbolTable.insert({name, symbol}).second)
200 // If the symbol was already in the table, also return.
201 if (symbolTable.lookup(name) == symbol)
204 MLIRContext *context = symbol->getContext();
209 .insert({StringAttr::get(context, candidate), symbol})
213 setSymbolName(symbol, nameBuffer);
214 return getSymbolName(symbol);
262 // Determine new name that is unique in all symbol tables.
291 /// Returns the name of the given symbol operation.
292 StringAttr SymbolTable::getSymbolName(Operation *symbol) {
293 StringAttr name = getNameIfSymbol(symbol);
294 assert(name && "expected valid symbol name");
298 /// Sets the name of the given symbol operation.
299 void SymbolTable::setSymbolName(Operation *symbol, StringAttr name) {
300 symbol->setAttr(getSymbolAttrName(), name);
303 /// Returns the visibility of the given symbol operation.
304 SymbolTable::Visibility SymbolTable::getSymbolVisibility(Operation *symbol) {
306 StringAttr vis = symbol->getAttrOfType<StringAttr>(getVisibilityAttrName());
316 /// Sets the visibility of the given symbol operation.
317 void SymbolTable::setSymbolVisibility(Operation *symbol, Visibility vis) {
318 MLIRContext *ctx = symbol->getContext();
323 symbol->removeAttr(StringAttr::get(ctx, getVisibilityAttrName()));
329 "unknown symbol visibility kind");
332 symbol->setAttr(getVisibilityAttrName(), StringAttr::get(ctx, visName));
335 /// Returns the nearest symbol table from a given operation `from`. Returns
336 /// nullptr if no valid parent symbol table could be found.
345 // Check that this is a valid op and isn't an unknown symbol table.
352 /// Walks all symbol table operations nested within, and including, `op`. For
353 /// each symbol table operation, the provided callback is invoked with the op
354 /// and a boolean signifying if the symbols within that symbol table can be
356 /// all of the symbol uses of symbols within `op` are visible.
362 SymbolOpInterface symbol = dyn_cast<SymbolOpInterface>(op);
363 allSymUsesVisible |= !symbol || symbol.isPrivate();
365 // Otherwise if 'op' is not a symbol table, any nested symbols are
375 // If 'op' had the symbol table trait, visit it after any nested symbol
381 /// Returns the operation registered with the given symbol name with the
383 /// with the 'OpTrait::SymbolTable' trait. Returns nullptr if no valid symbol
386 StringAttr symbol) {
392 // Look for a symbol with the given name.
396 if (getNameIfSymbol(&op, symbolNameId) == symbol)
401 SymbolRefAttr symbol) {
403 if (failed(lookupSymbolIn(symbolTableOp, symbol, resolvedSymbols)))
411 Operation *symbolTableOp, SymbolRefAttr symbol,
416 // Lookup the root reference for this symbol.
417 symbolTableOp = lookupSymbolFn(symbolTableOp, symbol.getRootReference());
422 // If there are no nested references, just return the root symbol directly.
423 ArrayRef<FlatSymbolRefAttr> nestedRefs = symbol.getNestedReferences();
427 // Verify that the root is also a symbol table.
432 // each corresponds to a valid symbol table.
439 symbols.push_back(lookupSymbolFn(symbolTableOp, symbol.getLeafReference()));
444 SymbolTable::lookupSymbolIn(Operation *symbolTableOp, SymbolRefAttr symbol,
446 auto lookupFn = [](Operation *symbolTableOp, StringAttr symbol) {
447 return lookupSymbolIn(symbolTableOp, symbol);
449 return lookupSymbolInImpl(symbolTableOp, symbol, symbols, lookupFn);
452 /// Returns the operation registered with the given symbol name within the
454 /// nullptr if no valid symbol was found.
456 StringAttr symbol) {
458 return symbolTableOp ? lookupSymbolIn(symbolTableOp, symbol) : nullptr;
461 SymbolRefAttr symbol) {
463 return symbolTableOp ? lookupSymbolIn(symbolTableOp, symbol) : nullptr;
495 // Check for a symbol name attribute.
501 // Try to insert this symbol into the table.
505 .append("redefinition of symbol named '", nameAttr.getValue(), "'")
507 .append("see existing symbol definition here");
511 // Verify any nested symbol user operations.
549 // Symbol Use Lists
552 /// Walk all of the symbol references within the given operation, invoking the
554 /// symbol.
568 /// Walk all of the uses, for any symbol, that are nested within the given
570 /// into any nested symbol tables.
576 // Check that this isn't a potentially unknown symbol
584 /// Walk all of the uses, for any symbol, that are nested within the given
586 /// traverse into any nested symbol tables.
592 // symbol table, so we can't opaquely know if we should traverse to find
601 // Only recurse if this operation is not a symbol table. A symbol table
602 // defines a new scope, so we can't walk the attributes from within the symbol
610 /// This class represents a single symbol scope. A symbol scope represents the
611 /// set of operations nested within a symbol table that may reference symbols
612 /// within that table. A symbol scope does not contain the symbol table
614 /// operations or another symbol table operation.
616 /// Walk the symbol uses within this scope, invoking the given callback.
641 /// traversing into any nested symbol tables.
649 /// The representation of the symbol within this scope.
650 SymbolRefAttr symbol;
657 /// Collect all of the symbol scopes from 'symbol' to (inclusive) 'limit'.
658 static SmallVector<SymbolScope, 2> collectSymbolScopes(Operation *symbol,
660 StringAttr symName = SymbolTable::getSymbolName(symbol);
661 assert(!symbol->hasTrait<OpTrait::SymbolTable>() || symbol != limit);
669 // Check to see if 'symbol' is an ancestor of 'limit'.
670 if (limitAncestor == symbol) {
671 // Check that the nearest symbol table is 'symbol's parent. SymbolRefAttr
674 symbol->getParentOp())
682 // Try to find the first ancestor of 'symbol' that is an ancestor of 'limit'.
683 Operation *commonAncestor = symbol->getParentOp();
688 assert(commonAncestor && "'limit' and 'symbol' have no common ancestor");
690 // Compute the set of valid nested references for 'symbol' as far up to the
694 collectValidReferencesFor(symbol, symName, commonAncestor, references));
700 // Walk each of the ancestors of 'symbol', calling the compute function for
702 Operation *limitIt = symbol->getParentOp();
711 // Otherwise, we just need the symbol reference for 'symbol' that will be
718 static SmallVector<SymbolScope, 2> collectSymbolScopes(Operation *symbol,
720 auto scopes = collectSymbolScopes(symbol, limit->getParentOp());
728 static SmallVector<SymbolScope, 1> collectSymbolScopes(StringAttr symbol,
730 return {{SymbolRefAttr::get(symbol), limit}};
733 static SmallVector<SymbolScope, 1> collectSymbolScopes(StringAttr symbol,
736 auto symbolRef = SymbolRefAttr::get(symbol);
776 /// Get an iterator range for all of the uses, for any symbol, that are nested
778 /// symbol tables, and will also only return uses on 'from' if it does not
779 /// also define a symbol table. This is because we treat the region as the
780 /// boundary of the symbol table, and not the op itself. This function returns
782 /// symbol tables.
795 static std::optional<SymbolTable::UseRange> getSymbolUsesImpl(SymbolT symbol,
798 for (SymbolScope &scope : collectSymbolScopes(symbol, limit)) {
800 if (isReferencePrefixOf(scope.symbol, symbolUse.getSymbolRef()))
808 /// Get all of the uses of the given symbol that are nested within the given
810 /// traverse into any nested symbol tables. This function returns std::nullopt
811 /// if there are any unknown operations that may potentially be symbol tables.
812 auto SymbolTable::getSymbolUses(StringAttr symbol, Operation *from)
814 return getSymbolUsesImpl(symbol, from);
816 auto SymbolTable::getSymbolUses(Operation *symbol, Operation *from)
818 return getSymbolUsesImpl(symbol, from);
820 auto SymbolTable::getSymbolUses(StringAttr symbol, Region *from)
822 return getSymbolUsesImpl(symbol, from);
824 auto SymbolTable::getSymbolUses(Operation *symbol, Region *from)
826 return getSymbolUsesImpl(symbol, from);
834 static bool symbolKnownUseEmptyImpl(SymbolT symbol, IRUnitT *limit) {
835 for (SymbolScope &scope : collectSymbolScopes(symbol, limit)) {
836 // Walk all of the symbol uses looking for a reference to 'symbol'.
838 return isReferencePrefixOf(scope.symbol, symbolUse.getSymbolRef())
847 /// Return if the given symbol is known to have no uses that are nested within
848 /// the given operation 'from'. This does not traverse into any nested symbol
850 /// operations that may potentially be symbol tables.
851 bool SymbolTable::symbolKnownUseEmpty(StringAttr symbol, Operation *from) {
852 return symbolKnownUseEmptyImpl(symbol, from);
854 bool SymbolTable::symbolKnownUseEmpty(Operation *symbol, Operation *from) {
855 return symbolKnownUseEmptyImpl(symbol, from);
857 bool SymbolTable::symbolKnownUseEmpty(StringAttr symbol, Region *from) {
858 return symbolKnownUseEmptyImpl(symbol, from);
860 bool SymbolTable::symbolKnownUseEmpty(Operation *symbol, Region *from) {
861 return symbolKnownUseEmptyImpl(symbol, from);
867 /// Generates a new symbol reference attribute with a new leaf reference.
880 replaceAllSymbolUsesImpl(SymbolT symbol, StringAttr newSymbol, IRUnitT *limit) {
883 for (SymbolScope &scope : collectSymbolScopes(symbol, limit)) {
884 SymbolRefAttr oldAttr = scope.symbol;
885 SymbolRefAttr newAttr = generateNewRefAttr(scope.symbol, newLeafAttr);
919 /// Attempt to replace all uses of the given symbol 'oldSymbol' with the
920 /// provided symbol 'newSymbol' that are nested within the given operation
921 /// 'from'. This does not traverse into any nested symbol tables. If there are
922 /// any unknown operations that may potentially be symbol tables, no uses are
950 StringAttr symbol) {
951 return getSymbolTable(symbolTableOp).lookup(symbol);
967 auto lookupFn = [this](Operation *symbolTableOp, StringAttr symbol) {
968 return lookupSymbolIn(symbolTableOp, symbol);
973 /// Returns the operation registered with the given symbol name within the
975 /// 'OpTrait::SymbolTable' trait. Returns nullptr if no valid symbol was
978 StringAttr symbol) {
980 return symbolTableOp ? lookupSymbolIn(symbolTableOp, symbol) : nullptr;
984 SymbolRefAttr symbol) {
986 return symbolTableOp ? lookupSymbolIn(symbolTableOp, symbol) : nullptr;
989 /// Lookup, or create, a symbol table for an operation.
1002 StringAttr symbol) {
1003 return getSymbolTable(symbolTableOp).lookup(symbol);
1008 FlatSymbolRefAttr symbol) {
1009 return lookupSymbolIn(symbolTableOp, symbol.getAttr());
1023 auto lookupFn = [this](Operation *symbolTableOp, StringAttr symbol) {
1024 return lookupSymbolIn(symbolTableOp, symbol);
1032 // Try to find an existing symbol table.
1039 // Create a symbol table for the operation. Perform construction outside of
1042 // Insert the constructed symbol table.
1056 // Walk each of the symbol tables looking for discardable callgraph nodes.
1078 void SymbolUserMap::replaceAllUsesWith(Operation *symbol,
1080 auto it = symbolToUsers.find(symbol);
1084 // Replace the uses within the users of `symbol`.
1086 (void)SymbolTable::replaceAllSymbolUses(symbol, newSymbolName, user);
1088 // Move the current users of `symbol` to the new symbol if it is in the
1089 // symbol table.
1091 symbolTable.lookupSymbolIn(symbol->getParentOp(), newSymbolName);
1092 if (newSymbol != symbol) {
1093 // Transfer over the users to the new symbol. The reference to the old one
1096 auto oldIt = symbolToUsers.find(symbol);
1123 // Symbol Interfaces
1126 /// Include the generated symbol interfaces.