CIRCT 20.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
184private:
185 using TableTy = DenseMap<StringAttr, InnerSymTarget>;
186 /// Construct an inner symbol table for the given operation,
187 /// with pre-populated table contents.
188 explicit InnerSymbolTable(Operation *op, TableTy &&table)
189 : innerSymTblOp(op), symbolTable(table){};
190
191 /// This is the operation this table is constructed for, which must have the
192 /// InnerSymbolTable trait.
193 Operation *innerSymTblOp;
194
195 /// This maps inner symbol names to their targets.
197};
198
199/// This class represents a collection of InnerSymbolTable's.
201public:
202 /// Get or create the InnerSymbolTable for the specified operation.
204
205 /// Populate tables in parallel for all InnerSymbolTable operations in the
206 /// given InnerRefNamespace operation, verifying each and returning
207 /// the verification result.
208 LogicalResult populateAndVerifyTables(Operation *innerRefNSOp);
209
210 explicit InnerSymbolTableCollection() = default;
211 explicit InnerSymbolTableCollection(Operation *innerRefNSOp) {
212 // Caller is not interested in verification, no way to report it upwards.
213 auto result = populateAndVerifyTables(innerRefNSOp);
214 (void)result;
215 assert(succeeded(result));
216 }
220
221private:
222 /// This maps Operations to their InnnerSymbolTable's.
223 DenseMap<Operation *, std::unique_ptr<InnerSymbolTable>> symbolTables;
224};
225
226/// This class represents the namespace in which InnerRef's can be resolved.
228 SymbolTable &symTable;
230
231 /// Resolve the InnerRef to its target within this namespace, returning empty
232 /// target if no such name exists.
233 InnerSymTarget lookup(hw::InnerRefAttr inner) const;
234
235 /// Resolve the InnerRef to its target within this namespace, returning
236 /// empty target if no such name exists or it's not an operation.
237 /// Template type can be used to limit results to specified op type.
238 Operation *lookupOp(hw::InnerRefAttr inner) const;
239 template <typename T>
240 T lookupOp(hw::InnerRefAttr inner) const {
241 return dyn_cast_or_null<T>(lookupOp(inner));
242 }
243};
244
245/// Printing InnerSymTarget's.
246template <typename OS>
247OS &operator<<(OS &os, const InnerSymTarget &target) {
248 if (!target)
249 return os << "<invalid target>";
250
251 if (target.isField())
252 os << "field " << target.getField() << " of ";
253
254 if (target.isPort())
255 os << "port " << target.getPort() << " on @"
256 << SymbolTable::getSymbolName(target.getOp()).getValue() << "";
257 else
258 os << "op " << *target.getOp() << "";
259
260 return os;
261}
262
263} // namespace hw
264} // namespace circt
265
266#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.
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