20#include <mlir/IR/BuiltinOps.h>
21#include <mlir/IR/Operation.h>
22#include <mlir/IR/OwningOpRef.h>
24#include <llvm/ADT/STLExtras.h>
25#include <llvm/ADT/StringRef.h>
26#include <llvm/Support/Debug.h>
28#define DEBUG_TYPE "llzk-symbol-lookup"
32using namespace include;
35SymbolLookupResultUntyped
36lookupSymbolRec(SymbolTableCollection &tables, SymbolRefAttr symbol, Operation *symTableOp) {
40 SmallVector<Operation *, 4> symbolsFound;
41 if (succeeded(tables.lookupSymbolIn(symTableOp, symbol, symbolsFound))) {
42 SymbolLookupResultUntyped ret(symbolsFound.back());
43 for (
auto it = symbolsFound.rbegin(); it != symbolsFound.rend(); ++it) {
46 auto symName = op->getAttrOfType<StringAttr>(SymbolTable::getSymbolAttrName());
47 ret.pushNamespace(symName);
48 if (!llvm::isa<ModuleOp>(op)) {
49 LLVM_DEBUG({ llvm::dbgs() <<
"[lookupSymbolRec] tracking op as include\n"; });
51 ret.trackIncludeAsName(symName);
60 if (Operation *rootOp = tables.lookupSymbolIn(symTableOp, symbol.getRootReference())) {
61 if (IncludeOp rootOpInc = llvm::dyn_cast<IncludeOp>(rootOp)) {
62 FailureOr<OwningOpRef<ModuleOp>> otherMod = rootOpInc.openModule();
63 if (succeeded(otherMod)) {
68 SymbolTableCollection external;
71 result.manage(std::move(*otherMod), std::move(external));
72 auto symName = rootOpInc.getSymName();
73 result.pushNamespace(symName);
74 result.trackIncludeAsName(symName);
78 }
else if (ModuleOp rootOpMod = llvm::dyn_cast<ModuleOp>(rootOp)) {
83 return SymbolLookupResultUntyped();
99SymbolLookupResultUntyped::operator bool()
const {
return op !=
nullptr; }
103 OwningOpRef<ModuleOp> &&ptr, SymbolTableCollection &&tables
108 if (!managedResources) {
109 managedResources = std::make_shared<std::pair<OwningOpRef<ModuleOp>, SymbolTableCollection>>(
110 std::make_pair(std::move(ptr), std::move(tables))
117 includeSymNameStack.push_back(includeOpSymName);
121 namespaceStack.push_back(symName);
125 std::vector<llvm::StringRef> newNamespace = ns;
126 newNamespace.insert(newNamespace.end(), namespaceStack.begin(), namespaceStack.end());
127 namespaceStack = newNamespace;
135 if (
this != &other) {
136 from = std::move(other.from);
142 SymbolTableCollection &tables, SymbolRefAttr symbol, Operation *origin,
bool reportMissing
147 SymbolTableCollection *cachedTablesForRes = priorRes->getSymbolTableCache();
148 if (!cachedTablesForRes) {
149 cachedTablesForRes = &tables;
151 if (
auto found = lookupSymbolRec(*cachedTablesForRes, symbol, priorRes->op)) {
152 assert(!found.managedResources &&
"should not have loaded additional modules");
155 assert(found.includeSymNameStack.empty() &&
"should not have loaded additional modules");
157 found.managedResources = std::move(priorRes->managedResources);
158 found.includeSymNameStack = std::move(priorRes->includeSymNameStack);
163 Operation *lookupFrom = std::get<Operation *>(this->from);
169 lookupFrom =
root.value();
171 if (
auto found = lookupSymbolRec(tables, symbol, lookupFrom)) {
177 return origin->emitOpError() <<
"references unknown symbol \"" << symbol <<
'"';
This file defines methods symbol lookup across LLZK operations and included files.
void manage(mlir::OwningOpRef< mlir::ModuleOp > &&ptr, mlir::SymbolTableCollection &&tables)
Adds a pointer to the set of resources the result has to manage the lifetime of.
void prependNamespace(llvm::ArrayRef< llvm::StringRef > ns)
Adds the given namespace to the beginning of this result's namespace.
void trackIncludeAsName(llvm::StringRef includeOpSymName)
Adds the symbol name from the IncludeOp that caused the module to be loaded.
mlir::Operation & operator*()
void pushNamespace(llvm::StringRef symName)
Adds the symbol name from an IncludeOp or ModuleOp where the op is contained.
mlir::Operation * operator->()
Access the internal operation.
mlir::FailureOr< SymbolLookupResultUntyped > lookup(mlir::SymbolTableCollection &tables, mlir::SymbolRefAttr symbol, mlir::Operation *origin, bool reportMissing=true) &&
Within()
Lookup within the top-level (root) module.
Within & operator=(const Within &)=delete
constexpr char LANG_ATTR_NAME[]
Name of the attribute on the top-level ModuleOp that identifies the ModuleOp as the root module and s...
FailureOr< ModuleOp > getRootModule(Operation *from)
mlir::SymbolRefAttr getTailAsSymbolRefAttr(mlir::SymbolRefAttr symbol)
Return SymbolRefAttr like the one given but with the root/head element removed.