CIRCT 22.0.0git
Loading...
Searching...
No Matches
InnerSymbolTable.h
Go to the documentation of this file.
1//===- InnerSymbolTable.h - Inner Symbol Table -----------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file declares the InnerSymbolTable and related classes, used for
10// managing and tracking "inner symbols".
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef CIRCT_DIALECT_HW_INNERSYMBOLTABLE_H
15#define CIRCT_DIALECT_HW_INNERSYMBOLTABLE_H
16
18#include "circt/Support/LLVM.h"
19#include "mlir/IR/BuiltinAttributes.h"
20#include "mlir/IR/SymbolTable.h"
21#include "llvm/ADT/StringRef.h"
22
23namespace circt {
24namespace hw {
25
26/// The target of an inner symbol, the entity the symbol is a handle for.
28public:
29 /// Default constructor, invalid.
30 InnerSymTarget() { assert(!*this); }
31
32 /// Target an operation.
33 explicit InnerSymTarget(Operation *op) : InnerSymTarget(op, 0) {}
34
35 /// Target an operation and a field (=0 means the op itself).
36 InnerSymTarget(Operation *op, size_t fieldID)
38
39 /// Target a port, and optionally a field (=0 means the port itself).
40 InnerSymTarget(size_t portIdx, Operation *op, size_t fieldID = 0)
42
43 InnerSymTarget(const InnerSymTarget &) = default;
45
46 // Accessors:
47
48 /// Return the target's fieldID.
49 auto getField() const { return fieldID; }
50
51 /// Return the target's base operation. For ports, this is the module.
52 Operation *getOp() const { return op; }
53
54 /// Return the target's port, if valid. Check "isPort()".
55 auto getPort() const {
56 assert(isPort());
57 return portIdx;
58 }
59
60 // Classification:
61
62 /// Return if this targets a field (nonzero fieldID).
63 bool isField() const { return fieldID != 0; }
64
65 /// Return if this targets a port.
66 bool isPort() const { return portIdx != invalidPort; }
67
68 /// Returns if this targets an operation only (not port or field).
69 bool isOpOnly() const { return !isPort() && !isField(); }
70
71 /// Return a target to the specified field within the given base.
72 /// FieldID is relative to the specified base target.
74 size_t fieldID) {
75 if (base.isPort())
76 return InnerSymTarget(base.portIdx, base.op, base.fieldID + fieldID);
77 return InnerSymTarget(base.op, base.fieldID + fieldID);
78 }
79
80private:
81 auto asTuple() const { return std::tie(op, portIdx, fieldID); }
82 Operation *op = nullptr;
83 size_t portIdx = 0;
84 size_t fieldID = 0;
85 static constexpr size_t invalidPort = ~size_t{0};
86
87public:
88 // Operators are defined below.
89
90 // Comparison operators:
91 bool operator==(const InnerSymTarget &rhs) const {
92 return asTuple() == rhs.asTuple();
93 }
94
95 // Assignment operators:
98
99 /// Check if this target is valid.
100 operator bool() const { return op; }
101};
102
103/// A table of inner symbols and their resolutions.
105public:
106 /// Build an inner symbol table for the given operation. The operation must
107 /// have the InnerSymbolTable trait.
108 explicit InnerSymbolTable(Operation *op);
109
110 /// Non-copyable
113
114 // Moveable
117
118 /// Look up a symbol with the specified name, returning empty InnerSymTarget
119 /// if no such name exists. Names never include the @ on them.
120 InnerSymTarget lookup(StringRef name) const;
121 InnerSymTarget lookup(StringAttr name) const;
122
123 /// Look up a symbol with the specified name, returning null if no such
124 /// name exists or doesn't target just an operation.
125 Operation *lookupOp(StringRef name) const;
126 template <typename T>
127 T lookupOp(StringRef name) const {
128 return dyn_cast_or_null<T>(lookupOp(name));
129 }
130
131 /// Look up a symbol with the specified name, returning null if no such
132 /// name exists or doesn't target just an operation.
133 Operation *lookupOp(StringAttr name) const;
134 template <typename T>
135 T lookupOp(StringAttr name) const {
136 return dyn_cast_or_null<T>(lookupOp(name));
137 }
138
139 /// Get InnerSymbol for an operation.
140 static StringAttr getInnerSymbol(Operation *op);
141
142 /// Get InnerSymbol for a target.
143 static StringAttr getInnerSymbol(const InnerSymTarget &target);
144
145 /// Return the name of the attribute used for inner symbol names.
146 static StringRef getInnerSymbolAttrName() { return "inner_sym"; }
147
148 /// Construct an InnerSymbolTable, checking for verification failure.
149 /// Emits diagnostics describing encountered issues.
150 static FailureOr<InnerSymbolTable> get(Operation *op);
151
153 llvm::function_ref<LogicalResult(StringAttr, const InnerSymTarget &)>;
154
155 /// Walk the given IST operation and invoke the callback for all encountered
156 /// inner symbols.
157 /// This variant allows callbacks that return LogicalResult OR void,
158 /// and wraps the underlying implementation.
159 template <typename FuncTy, typename RetTy = typename std::invoke_result_t<
160 FuncTy, StringAttr, const InnerSymTarget &>>
161 static RetTy walkSymbols(Operation *op, FuncTy &&callback) {
162 if constexpr (std::is_void_v<RetTy>)
163 return (void)walkSymbols(
165 [&](StringAttr name, const InnerSymTarget &target) {
166 std::invoke(std::forward<FuncTy>(callback), name, target);
167 return success();
168 }));
169 else
170 return walkSymbols(
171 op, InnerSymCallbackFn([&](StringAttr name,
172 const InnerSymTarget &target) {
173 return std::invoke(std::forward<FuncTy>(callback), name, target);
174 }));
175 }
176
177 /// Walk the given IST operation and invoke the callback for all encountered
178 /// inner symbols.
179 /// This variant is the underlying implementation.
180 /// If callback returns failure, the walk is aborted and failure is returned.
181 /// A successful walk with no failures returns success.
182 static LogicalResult walkSymbols(Operation *op, InnerSymCallbackFn callback);
183
184 /// Invoke the callback for all symbols in this table.
185 LogicalResult walkSymbols(InnerSymCallbackFn callback) const {
186 for (auto [name, target] : symbolTable)
187 if (failed(callback(name, target)))
188 return failure();
189 return success();
190 }
191
192private:
193 using TableTy = DenseMap<StringAttr, InnerSymTarget>;
194 /// Construct an inner symbol table for the given operation,
195 /// with pre-populated table contents.
196 explicit InnerSymbolTable(Operation *op, TableTy &&table)
197 : innerSymTblOp(op), symbolTable(table) {}
198
199 /// This is the operation this table is constructed for, which must have the
200 /// InnerSymbolTable trait.
201 Operation *innerSymTblOp;
202
203 /// This maps inner symbol names to their targets.
205};
206
207/// This class represents a collection of InnerSymbolTable's.
209public:
210 /// Get or create the InnerSymbolTable for the specified operation.
212
213 /// Populate tables in parallel for all InnerSymbolTable operations in the
214 /// given InnerRefNamespace operation, verifying each and returning
215 /// the verification result.
216 LogicalResult populateAndVerifyTables(Operation *innerRefNSOp);
217
218 explicit InnerSymbolTableCollection() = default;
219 explicit InnerSymbolTableCollection(Operation *innerRefNSOp) {
220 // Caller is not interested in verification, no way to report it upwards.
221 auto result = populateAndVerifyTables(innerRefNSOp);
222 (void)result;
223 assert(succeeded(result));
224 }
228
229private:
230 /// This maps Operations to their InnnerSymbolTable's.
231 DenseMap<Operation *, std::unique_ptr<InnerSymbolTable>> symbolTables;
232};
233
234/// This class represents the namespace in which InnerRef's can be resolved.
236 SymbolTable &symTable;
238
239 /// Resolve the InnerRef to its target within this namespace, returning empty
240 /// target if no such name exists.
241 InnerSymTarget lookup(hw::InnerRefAttr inner) const;
242
243 /// Resolve the InnerRef to its target within this namespace, returning
244 /// empty target if no such name exists or it's not an operation.
245 /// Template type can be used to limit results to specified op type.
246 Operation *lookupOp(hw::InnerRefAttr inner) const;
247 template <typename T>
248 T lookupOp(hw::InnerRefAttr inner) const {
249 return dyn_cast_or_null<T>(lookupOp(inner));
250 }
251};
252
253/// Printing InnerSymTarget's.
254template <typename OS>
255OS &operator<<(OS &os, const InnerSymTarget &target) {
256 if (!target)
257 return os << "<invalid target>";
258
259 if (target.isField())
260 os << "field " << target.getField() << " of ";
261
262 if (target.isPort())
263 os << "port " << target.getPort() << " on @"
264 << SymbolTable::getSymbolName(target.getOp()).getValue() << "";
265 else
266 os << "op " << *target.getOp() << "";
267
268 return os;
269}
270
271} // namespace hw
272} // namespace circt
273
274#endif // CIRCT_DIALECT_FIRRTL_INNERSYMBOLTABLE_H
assert(baseType &&"element must be base type")
The target of an inner symbol, the entity the symbol is a handle for.
bool isOpOnly() const
Returns if this targets an operation only (not port or field).
InnerSymTarget(size_t portIdx, Operation *op, size_t fieldID=0)
Target a port, and optionally a field (=0 means the port itself).
auto getField() const
Return the target's fieldID.
bool isField() const
Return if this targets a field (nonzero fieldID).
static InnerSymTarget getTargetForSubfield(const InnerSymTarget &base, size_t fieldID)
Return a target to the specified field within the given base.
InnerSymTarget(InnerSymTarget &&)=default
InnerSymTarget(Operation *op)
Target an operation.
auto getPort() const
Return the target's port, if valid. Check "isPort()".
InnerSymTarget(Operation *op, size_t fieldID)
Target an operation and a field (=0 means the op itself).
InnerSymTarget()
Default constructor, invalid.
bool operator==(const InnerSymTarget &rhs) const
bool isPort() const
Return if this targets a port.
Operation * getOp() const
Return the target's base operation. For ports, this is the module.
InnerSymTarget(const InnerSymTarget &)=default
InnerSymTarget & operator=(InnerSymTarget &&)=default
static constexpr size_t invalidPort
InnerSymTarget & operator=(const InnerSymTarget &)=default
This class represents a collection of InnerSymbolTable's.
InnerSymbolTableCollection & operator=(const InnerSymbolTableCollection &)=delete
DenseMap< Operation *, std::unique_ptr< InnerSymbolTable > > symbolTables
This maps Operations to their InnnerSymbolTable's.
InnerSymbolTableCollection(Operation *innerRefNSOp)
LogicalResult populateAndVerifyTables(Operation *innerRefNSOp)
Populate tables in parallel for all InnerSymbolTable operations in the given InnerRefNamespace operat...
InnerSymbolTableCollection(const InnerSymbolTableCollection &)=delete
InnerSymbolTable & getInnerSymbolTable(Operation *op)
Get or create the InnerSymbolTable for the specified operation.
A table of inner symbols and their resolutions.
Operation * innerSymTblOp
This is the operation this table is constructed for, which must have the InnerSymbolTable trait.
T lookupOp(StringAttr name) const
InnerSymbolTable(const InnerSymbolTable &)=delete
Non-copyable.
LogicalResult walkSymbols(InnerSymCallbackFn callback) const
Invoke the callback for all symbols in this table.
T lookupOp(StringRef name) const
InnerSymTarget lookup(StringRef name) const
Look up a symbol with the specified name, returning empty InnerSymTarget if no such name exists.
DenseMap< StringAttr, InnerSymTarget > TableTy
InnerSymbolTable & operator=(InnerSymbolTable &&)=default
static StringAttr getInnerSymbol(Operation *op)
Get InnerSymbol for an operation.
llvm::function_ref< LogicalResult(StringAttr, const InnerSymTarget &)> InnerSymCallbackFn
InnerSymbolTable(InnerSymbolTable &&)=default
static RetTy walkSymbols(Operation *op, FuncTy &&callback)
Walk the given IST operation and invoke the callback for all encountered inner symbols.
InnerSymbolTable(Operation *op, TableTy &&table)
Construct an inner symbol table for the given operation, with pre-populated table contents.
Operation * lookupOp(StringRef name) const
Look up a symbol with the specified name, returning null if no such name exists or doesn't target jus...
InnerSymbolTable & operator=(const InnerSymbolTable &)=delete
static FailureOr< InnerSymbolTable > get(Operation *op)
Construct an InnerSymbolTable, checking for verification failure.
TableTy symbolTable
This maps inner symbol names to their targets.
static StringRef getInnerSymbolAttrName()
Return the name of the attribute used for inner symbol names.
OS & operator<<(OS &os, const InnerSymTarget &target)
Printing InnerSymTarget's.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition hw.py:1
This class represents the namespace in which InnerRef's can be resolved.
T lookupOp(hw::InnerRefAttr inner) const
InnerSymTarget lookup(hw::InnerRefAttr inner) const
Resolve the InnerRef to its target within this namespace, returning empty target if no such name exis...
Operation * lookupOp(hw::InnerRefAttr inner) const
Resolve the InnerRef to its target within this namespace, returning empty target if no such name exis...
InnerSymbolTableCollection & innerSymTables