12#include "llvm/ADT/SetVector.h"
13#include "llvm/ADT/SmallString.h"
27 auto symbol = dyn_cast<SymbolOpInterface>(op);
30 return symbol.getNameAttr();
41 assert(within->
isAncestor(symbol) &&
"expected 'within' to be an ancestor");
44 results.push_back(leafRef);
48 if (within == symbolTableOp)
61 results.push_back(SymbolRefAttr::get(symbolTableName, nestedRefs));
64 if (symbolTableOp == within)
66 nestedRefs.insert(nestedRefs.begin(),
75static std::optional<WalkResult>
79 while (!worklist.empty()) {
80 for (
Operation &op : worklist.pop_back_val()->getOps()) {
81 std::optional<WalkResult>
result = callback(&op);
88 for (
Region ®ion : op.getRegions())
89 worklist.push_back(®ion);
99static std::optional<WalkResult>
102 std::optional<WalkResult>
result = callback(op);
114 : symbolTableOp(symbolTableOp) {
116 "expected operation to have SymbolTable trait");
117 assert(symbolTableOp->getNumRegions() == 1 &&
118 "expected operation to have a single region");
119 assert(symbolTableOp->getRegion(0).hasOneBlock() &&
120 "expected operation to have a single block");
133 symbolTable.try_emplace(name, &op);
140 return lookup(StringAttr::get(symbolTableOp->getContext(), name));
143 return symbolTable.lookup(name);
148 assert(name &&
"expected valid 'name' attribute");
150 "expected this operation to be inside of the operation with this "
153 auto it = symbolTable.find(name);
154 if (it != symbolTable.end() && it->second == op)
155 symbolTable.erase(it);
173 auto &body = symbolTableOp->getRegion(0).front();
177 assert((insertPt == body.end() ||
178 insertPt->getParentOp() == symbolTableOp) &&
179 "expected insertPt to be in the associated module operation");
184 insertPt = std::prev(body.end());
186 body.getOperations().insert(insertPt, symbol);
189 "symbol is already inserted in another op");
194 if (symbolTable.insert({name, symbol}).second)
197 if (symbolTable.lookup(name) == symbol)
203 [&](StringRef candidate) {
205 .insert({StringAttr::get(context, candidate), symbol})
209 setSymbolName(symbol, nameBuffer);
210 return getSymbolName(symbol);
222 assert(from &&
"expected valid 'name' attribute");
224 "expected this operation to be inside of the operation with this "
226 assert(
lookup(from) == op &&
"current name does not resolve to op");
227 assert(
lookup(to) ==
nullptr &&
"new name already exists");
238 assert(
lookup(to) == op &&
"new name does not resolve to renamed op");
239 assert(
lookup(from) ==
nullptr &&
"old name still exists");
246 return rename(from, toAttr);
251 return rename(op, toAttr);
264 prefix.push_back(
'_');
266 newName = StringAttr::get(context, prefix + Twine(uniqueId++));
267 auto lookupNewName = [&](
SymbolTable *st) {
return st->lookup(newName); };
268 if (!lookupNewName(
this) && llvm::none_of(others, lookupNewName)) {
275 if (failed(
rename(oldName, newName)))
283 assert(from &&
"expected valid 'name' attribute");
289 auto symbolOp = cast<SymbolOpInterface>(symbol);
290 StringAttr name = symbolOp.getNameAttr();
291 assert(name &&
"expected valid symbol name");
297 auto symbolOp = cast<SymbolOpInterface>(symbol);
298 symbolOp.setSymbolName(name);
303 auto symbolOp = dyn_cast<SymbolOpInterface>(symbol);
304 assert(symbolOp &&
"expected valid symbol operation");
305 return symbolOp.getVisibility();
309 auto symbolOp = dyn_cast<SymbolOpInterface>(symbol);
310 assert(symbolOp &&
"expected valid symbol operation");
311 symbolOp.setVisibility(vis);
317 assert(from &&
"expected valid operation");
341 SymbolOpInterface symbol = dyn_cast<SymbolOpInterface>(op);
342 allSymUsesVisible |= !symbol || symbol.isPrivate();
346 allSymUsesVisible =
true;
350 for (
Block &block : region)
357 callback(op, allSymUsesVisible);
367 Region ®ion = symbolTableOp->getRegion(0);
372 for (
auto &op : region.
front())
378 SymbolRefAttr symbol) {
380 if (failed(
lookupSymbolIn(symbolTableOp, symbol, resolvedSymbols)))
382 return resolvedSymbols.back();
388 Operation *symbolTableOp, SymbolRefAttr symbol,
394 auto *symbolOp = lookupSymbolFn(symbolTableOp, symbol.getRootReference());
397 symbols.push_back(symbolOp);
404 symbolOp = lookupSymbolFn(symbolOp, ref.getAttr());
408 auto nestedSymbol = dyn_cast<SymbolOpInterface>(symbolOp);
409 if (nestedSymbol && nestedSymbol.isPrivate())
411 symbols.push_back(symbolOp);
419 auto lookupFn = [](
Operation *symbolTableOp, StringAttr symbol) {
431 return symbolTableOp ?
lookupSymbolIn(symbolTableOp, symbol) :
nullptr;
434 SymbolRefAttr symbol) {
436 return symbolTableOp ?
lookupSymbolIn(symbolTableOp, symbol) :
nullptr;
441 switch (visibility) {
443 return os <<
"public";
445 return os <<
"private";
447 return os <<
"nested";
449 llvm_unreachable(
"Unexpected visibility");
459 <<
"Operations with a 'SymbolTable' must have exactly one region";
462 <<
"Operations with a 'SymbolTable' must have exactly one block";
467 for (
auto &op : block) {
474 auto it = nameToOrigLoc.try_emplace(nameAttr, op.
getLoc());
477 .
append(
"redefinition of symbol named '", nameAttr.getValue(),
"'")
479 .
append(
"see existing symbol definition here");
485 auto verifySymbolUserFn = [&](
Operation *op) -> std::optional<WalkResult> {
486 if (SymbolUserOpInterface user = dyn_cast<SymbolUserOpInterface>(op))
487 if (failed(user.verifySymbolUses(symbolTable)))
490 if (
auto user = dyn_cast<SymbolUserAttrInterface>(attr.getValue())) {
491 if (failed(user.verifySymbolUses(op, symbolTable)))
498 std::optional<WalkResult>
result =
505 if (!cast<SymbolOpInterface>(op).getNameAttr())
509 StringRef visAttrName =
510 mlir::SymbolOpInterface::getDefaultVisibilityAttrName();
512 StringAttr visStrAttr = llvm::dyn_cast<StringAttr>(vis);
515 <<
"requires visibility attribute '" << visAttrName
516 <<
"' to be a string attribute, but got " << vis;
519 visStrAttr.getValue()))
521 <<
"visibility expected to be one of [\"public\", \"private\", "
522 "\"nested\"], but got "
538 bool interrupted =
false;
543 if (callback({op, symbolRef}).wasInterrupted())
553 op, [&](StringRef,
Attribute &attr) { walk(attr); });
560static std::optional<WalkResult>
564 [&](
Operation *op) -> std::optional<WalkResult> {
576static std::optional<WalkResult>
608 template <
typename CallbackT,
609 std::enable_if_t<!std::is_same<
610 typename llvm::function_traits<CallbackT>::result_t,
611 void>::value> * =
nullptr>
612 std::optional<WalkResult>
walk(CallbackT cback) {
613 if (Region *region = llvm::dyn_cast_if_present<Region *>(limit))
619 template <
typename CallbackT,
620 std::enable_if_t<std::is_same<
621 typename llvm::function_traits<CallbackT>::result_t,
622 void>::value> * =
nullptr>
623 std::optional<WalkResult>
walk(CallbackT cback) {
624 return walk([=](SymbolTable::SymbolUse use) {
631 template <
typename CallbackT>
633 if (Region *region = llvm::dyn_cast_if_present<Region *>(limit))
634 return ::walkSymbolTable(*region, cback);
635 return ::walkSymbolTable(cast<Operation *>(limit), cback);
639 SymbolRefAttr symbol;
642 llvm::PointerUnion<Operation *, Region *> limit;
659 if (limitAncestor == symbol) {
664 return {{SymbolRefAttr::get(symName), limit}};
668 limitAncestors.insert(limitAncestor);
669 }
while ((limitAncestor = limitAncestor->
getParentOp()));
674 if (limitAncestors.count(commonAncestor))
676 }
while ((commonAncestor = commonAncestor->
getParentOp()));
677 assert(commonAncestor &&
"'limit' and 'symbol' have no common ancestor");
682 bool collectedAllReferences = succeeded(
686 if (commonAncestor == limit) {
692 for (
size_t i = 0, e = references.size(); i != e;
695 scopes.push_back({references[i], &limitIt->
getRegion(0)});
703 if (!collectedAllReferences)
705 return {{references.back(), limit}};
714 scopes.back().limit = limit;
719 return {{SymbolRefAttr::get(symbol), limit}};
725 auto symbolRef = SymbolRefAttr::get(symbol);
727 scopes.push_back({symbolRef, ®ion});
739 if (llvm::isa<FlatSymbolRefAttr>(ref) ||
740 ref.getRootReference() != subRef.getRootReference())
743 auto refLeafs = ref.getNestedReferences();
744 auto subRefLeafs = subRef.getNestedReferences();
745 return subRefLeafs.size() < refLeafs.size() &&
746 subRefLeafs == refLeafs.take_front(subRefLeafs.size());
754template <
typename FromT>
756 std::vector<SymbolTable::SymbolUse> uses;
758 uses.push_back(symbolUse);
762 return result ? std::optional<SymbolTable::UseRange>(std::move(uses))
785template <
typename SymbolT,
typename IRUnitT>
788 std::vector<SymbolTable::SymbolUse> uses;
791 if (isReferencePrefixOf(scope.symbol, symbolUse.getSymbolRef()))
792 uses.push_back(symbolUse);
804 -> std::optional<UseRange> {
808 -> std::optional<UseRange> {
812 -> std::optional<UseRange> {
816 -> std::optional<UseRange> {
825template <
typename SymbolT,
typename IRUnitT>
830 return isReferencePrefixOf(scope.symbol, symbolUse.getSymbolRef())
831 ? WalkResult::interrupt()
832 : WalkResult::advance();
863 if (llvm::isa<FlatSymbolRefAttr>(oldAttr))
865 auto nestedRefs = llvm::to_vector<2>(oldAttr.getNestedReferences());
866 nestedRefs.back() = newLeafAttr;
867 return SymbolRefAttr::get(oldAttr.getRootReference(), nestedRefs);
871template <
typename SymbolT,
typename IRUnitT>
877 SymbolRefAttr oldAttr = scope.symbol;
881 [&](SymbolRefAttr attr) -> std::pair<Attribute, WalkResult> {
888 auto oldNestedRefs = oldAttr.getNestedReferences();
889 auto nestedRefs = attr.getNestedReferences();
890 if (oldNestedRefs.empty())
891 return {SymbolRefAttr::get(newSymbol, nestedRefs),
894 auto newNestedRefs = llvm::to_vector<4>(nestedRefs);
895 newNestedRefs[oldNestedRefs.size() - 1] = newLeafAttr;
896 return {SymbolRefAttr::get(attr.getRootReference(), newNestedRefs),
902 auto walkFn = [&](
Operation *op) -> std::optional<WalkResult> {
906 if (!scope.walkSymbolTable(walkFn))
918 StringAttr newSymbol,
923 StringAttr newSymbol,
928 StringAttr newSymbol,
933 StringAttr newSymbol,
947 SymbolRefAttr name) {
951 return symbols.back();
960 auto lookupFn = [
this](
Operation *symbolTableOp, StringAttr symbol) {
973 return symbolTableOp ?
lookupSymbolIn(symbolTableOp, symbol) :
nullptr;
977 SymbolRefAttr symbol) {
979 return symbolTableOp ?
lookupSymbolIn(symbolTableOp, symbol) :
nullptr;
984 auto it = symbolTables.try_emplace(op,
nullptr);
986 it.first->second = std::make_unique<SymbolTable>(op);
987 return *it.first->second;
991 symbolTables.erase(op);
1000 return getSymbolTable(symbolTableOp).lookup(symbol);
1010 SymbolRefAttr name) {
1014 return symbols.back();
1018 Operation *symbolTableOp, SymbolRefAttr name,
1020 auto lookupFn = [
this](
Operation *symbolTableOp, StringAttr symbol) {
1027LockedSymbolTableCollection::getSymbolTable(
Operation *symbolTableOp) {
1031 llvm::sys::SmartScopedReader<true> lock(mutex);
1032 auto it = collection.symbolTables.find(symbolTableOp);
1033 if (it != collection.symbolTables.end())
1038 auto symbolTable = std::make_unique<SymbolTable>(symbolTableOp);
1040 llvm::sys::SmartScopedWriter<true> lock(mutex);
1041 return *collection.symbolTables
1042 .insert({symbolTableOp, std::move(symbolTable)})
1052 : symbolTable(symbolTable) {
1055 auto walkFn = [&](
Operation *symbolTableOp,
bool allUsesVisible) {
1058 assert(symbolUses &&
"expected uses to be valid");
1062 (
void)symbolTable.lookupSymbolIn(symbolTableOp, use.getSymbolRef(),
1065 symbolToUsers[symbolOp].insert(use.getUser());
1076 StringAttr newSymbolName) {
1077 auto it = symbolToUsers.find(symbol);
1078 if (it == symbolToUsers.end())
1088 symbolTable.lookupSymbolIn(symbol->
getParentOp(), newSymbolName);
1089 if (newSymbol != symbol) {
1092 auto newIt = symbolToUsers.try_emplace(newSymbol);
1093 auto oldIt = symbolToUsers.find(symbol);
1094 assert(oldIt != symbolToUsers.end() &&
"missing old users list");
1096 newIt.first->second = std::move(oldIt->second);
1098 newIt.first->second.set_union(oldIt->second);
1099 symbolToUsers.erase(oldIt);
1109 StringRef visibility;
1115 SymbolOpInterface::getDefaultVisibilityAttrName(), visibilityAttr));
1124#include "mlir/IR/SymbolInterfaces.cpp.inc"
1125#include "mlir/IR/SymbolInterfacesAttrInterface.cpp.inc"
static std::optional< WalkResult > walkSymbolTable(MutableArrayRef< Region > regions, function_ref< std::optional< WalkResult >(Operation *)> callback)
Walk all of the operations within the given set of regions, without traversing into any nested symbol...
static std::optional< SymbolTable::UseRange > getSymbolUsesImpl(FromT from)
The implementation of SymbolTable::getSymbolUses below.
static LogicalResult collectValidReferencesFor(Operation *symbol, StringAttr symbolName, Operation *within, SmallVectorImpl< SymbolRefAttr > &results)
Computes the nested symbol reference attribute for the symbol 'symbolName' that are usable within the...
static bool symbolKnownUseEmptyImpl(SymbolT symbol, IRUnitT *limit)
The implementation of SymbolTable::symbolKnownUseEmpty below.
static SmallVector< SymbolScope, 2 > collectSymbolScopes(Operation *symbol, Operation *limit)
Collect all of the symbol scopes from 'symbol' to (inclusive) 'limit'.
static WalkResult walkSymbolRefs(Operation *op, function_ref< WalkResult(SymbolTable::SymbolUse)> callback)
Walk all of the symbol references within the given operation, invoking the provided callback for each...
static StringAttr getNameIfSymbol(Operation *op)
Returns the string name of the given symbol, or null if this is not a symbol.
static bool isReferencePrefixOf(SymbolRefAttr subRef, SymbolRefAttr ref)
Returns true if the given reference 'SubRef' is a sub reference of the reference 'ref',...
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 regions, invoking the provided...
static SymbolRefAttr generateNewRefAttr(SymbolRefAttr oldAttr, FlatSymbolRefAttr newLeafAttr)
Generates a new symbol reference attribute with a new leaf reference.
static LogicalResult replaceAllSymbolUsesImpl(SymbolT symbol, StringAttr newSymbol, IRUnitT *limit)
The implementation of SymbolTable::replaceAllSymbolUses below.
static LogicalResult lookupSymbolInImpl(Operation *symbolTableOp, SymbolRefAttr symbol, SmallVectorImpl< Operation * > &symbols, function_ref< Operation *(Operation *, StringAttr)> lookupSymbolFn)
Internal implementation of lookupSymbolIn that allows for specialized implementations of the lookup f...
static bool isPotentiallyUnknownSymbolTable(Operation *op)
Return true if the given operation is unknown and may potentially define a symbol table.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
This is an attribute/type replacer that is naively cached.
Attributes are known-constant values of operations.
Block represents an ordered list of Operations.
OpListType::iterator iterator
StringAttr getStringAttr(const Twine &bytes)
NamedAttribute getNamedAttr(StringRef name, Attribute val)
Diagnostic & append(Arg1 &&arg1, Arg2 &&arg2, Args &&...args)
Append arguments to the diagnostic.
A symbol reference with a reference path containing a single element.
static FlatSymbolRefAttr get(StringAttr value)
Construct a symbol reference for the given value name.
StringAttr getAttr() const
Returns the name of the held symbol reference as a StringAttr.
InFlightDiagnostic & append(Args &&...args) &
Append arguments to the diagnostic.
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol) override
Look up a symbol with the specified name within the specified symbol table operation,...
MLIRContext is the top-level object for a collection of MLIR operations.
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
void push_back(NamedAttribute newAttribute)
Add an attribute with the specified name.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
This class provides the API for ops that are known to be terminators.
A trait used to provide symbol table functionalities to a region operation.
void walkInherentAttrs(Operation *op, InherentAttrVisitor visitor) const
Visit the inherent attributes stored in the properties of op.
Operation is the basic unit of execution within MLIR.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
std::optional< Attribute > getInherentAttr(StringRef name)
Access an inherent attribute by name: returns an empty optional if there is no inherent attribute wit...
unsigned getNumRegions()
Returns the number of regions held by this operation.
Location getLoc()
The source location the operation was defined or derived from.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
DictionaryAttr getRawDictionaryAttrs()
Return all attributes that are not stored as properties.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OperationName getName()
The name of an operation is the key identifier for it.
DictionaryAttr getDiscardableAttrDictionary()
Return all of the discardable attributes on this operation as a DictionaryAttr.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
bool isAncestor(Operation *other)
Return true if this operation is an ancestor of the other operation.
MLIRContext * getContext()
Return the context this operation is associated with.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
void erase()
Remove this operation from its parent block and delete it.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
iterator_range< OpIterator > getOps()
Operation * getParentOp()
Return the parent operation this region is attached to.
bool hasOneBlock()
Return true if this region has exactly one block.
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
virtual void invalidateSymbolTable(Operation *op)
Invalidate the cached symbol table for an operation.
virtual SymbolTable & getSymbolTable(Operation *op)
Lookup, or create, a symbol table for an operation.
This class represents a specific symbol use.
This class implements a range of SymbolRef uses.
This class allows for representing and managing the symbol table used by operations with the 'SymbolT...
static SmallString< N > generateSymbolName(StringRef name, UniqueChecker uniqueChecker, unsigned &uniquingCounter)
Generate a unique symbol name.
static Visibility getSymbolVisibility(Operation *symbol)
Returns the visibility of the given symbol operation, which is required to implement SymbolOpInterfac...
static void setSymbolVisibility(Operation *symbol, Visibility vis)
Sets the visibility of the given symbol operation, which is required to implement SymbolOpInterface.
static LogicalResult replaceAllSymbolUses(StringAttr oldSymbol, StringAttr newSymbol, Operation *from)
Attempt to replace all uses of the given symbol 'oldSymbol' with the provided symbol 'newSymbol' that...
Visibility
An enumeration detailing the different visibility types that a symbol may have.
@ Nested
The symbol is visible to the current IR, which may include operations in symbol tables above the one ...
@ Public
The symbol is public and may be referenced anywhere internal or external to the visible references in...
@ Private
The symbol is private and may only be referenced by SymbolRefAttrs local to the operations within the...
LogicalResult rename(StringAttr from, StringAttr to)
Renames the given op or the op refered to by the given name to the given new name and updates the sym...
void erase(Operation *symbol)
Erase the given symbol from the table and delete the operation.
Operation * getOp() const
Returns the associated operation.
static Operation * lookupSymbolIn(Operation *op, StringAttr symbol)
Returns the operation registered with the given symbol name with the regions of 'symbolTableOp'.
Operation * lookup(StringRef name) const
Look up a symbol with the specified name, returning null if no such name exists.
SymbolTable(Operation *symbolTableOp)
Build a symbol table with the symbols within the given operation.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
static void setSymbolName(Operation *symbol, StringAttr name)
Sets the name of the given symbol operation.
static bool symbolKnownUseEmpty(StringAttr symbol, Operation *from)
Return if the given symbol is known to have no uses that are nested within the given operation 'from'...
FailureOr< StringAttr > renameToUnique(StringAttr from, ArrayRef< SymbolTable * > others)
Renames the given op or the op refered to by the given name to the a name that is unique within this ...
static void walkSymbolTables(Operation *op, bool allSymUsesVisible, function_ref< void(Operation *, bool)> callback)
Walks all symbol table operations nested within, and including, op.
static StringAttr getSymbolName(Operation *symbol)
Returns the name of the given symbol operation, aborting if no symbol is present.
static std::optional< UseRange > getSymbolUses(Operation *from)
Get an iterator range for all of the uses, for any symbol, that are nested within the given operation...
StringAttr insert(Operation *symbol, Block::iterator insertPt={})
Insert a new symbol into the table, and rename it as necessary to avoid collisions.
void remove(Operation *op)
Remove the given symbol from the table, without deleting it.
static Operation * getNearestSymbolTable(Operation *from)
Returns the nearest symbol table from a given operation from.
void replaceAllUsesWith(Operation *symbol, StringAttr newSymbolName)
Replace all of the uses of the given symbol with newSymbolName.
SymbolUserMap(SymbolTableCollection &symbolTable, Operation *symbolTableOp)
Build a user map for all of the symbols defined in regions nested under 'symbolTableOp'.
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
static WalkResult interrupt()
void addReplacement(ReplaceFn< Attribute > fn)
AttrTypeReplacerBase.
void replaceElementsIn(Operation *op, bool replaceAttrs=true, bool replaceLocs=false, bool replaceTypes=false)
Replace the elements within the given operation.
void walk(Operation *op, function_ref< void(Region *)> callback, WalkOrder order)
Walk all of the regions, blocks, or operations nested under (and including) the given operation.
LogicalResult verifySymbol(Operation *op)
LogicalResult verifySymbolTable(Operation *op)
ParseResult parseOptionalVisibilityKeyword(OpAsmParser &parser, NamedAttrList &attrs)
Parse an optional visibility attribute keyword (i.e., public, private, or nested) without quotes in a...
Include the generated interface declarations.
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
llvm::SetVector< T, Vector, Set, N > SetVector
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
llvm::function_ref< Fn > function_ref