CIRCT  19.0.0git
EmissionPattern.h
Go to the documentation of this file.
1 //===- EmissionPattern.h - Emission Pattern Base and Utility --------------===//
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 declares the emission pattern base and utility classes.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 // NOLINTNEXTLINE(llvm-header-guard)
14 #ifndef CIRCT_TARGET_EXPORTSYSTEMC_EMISSIONPATTERN_H
15 #define CIRCT_TARGET_EXPORTSYSTEMC_EMISSIONPATTERN_H
16 
17 #include "EmissionPatternSupport.h"
18 #include "mlir/IR/Operation.h"
19 #include <any>
20 
21 namespace circt {
22 namespace ExportSystemC {
23 // Forward declarations.
24 class EmissionPrinter;
25 
26 //===----------------------------------------------------------------------===//
27 // Inline emission utilities.
28 //===----------------------------------------------------------------------===//
29 
30 /// This enum encodes the precedence of C++ expressions. A lower number means
31 /// higher precedence. Source:
32 /// https://en.cppreference.com/w/cpp/language/operator_precedence
33 enum class Precedence {
34  LIT = 0,
35  VAR = 0,
36  SCOPE_RESOLUTION = 1,
37  POSTFIX_INC = 2,
38  POSTFIX_DEC = 2,
39  FUNCTIONAL_CAST = 2,
40  FUNCTION_CALL = 2,
41  SUBSCRIPT = 2,
42  MEMBER_ACCESS = 2,
43  PREFIX_INC = 3,
44  PREFIX_DEC = 3,
45  NOT = 3,
46  CAST = 3,
47  DEREFERENCE = 3,
48  ADDRESS_OF = 3,
49  SIZEOF = 3,
50  NEW = 3,
51  DELETE = 3,
53  MUL = 5,
54  DIV = 5,
55  MOD = 5,
56  ADD = 6,
57  SUB = 6,
58  SHL = 7,
59  SHR = 7,
60  RELATIONAL = 9,
61  EQUALITY = 10,
62  BITWISE_AND = 11,
63  BITWISE_XOR = 12,
64  BITWISE_OR = 13,
65  LOGICAL_AND = 14,
66  LOGICAL_OR = 15,
67  TERNARY = 16,
68  THROW = 16,
69  ASSIGN = 16,
70  COMMA = 17
71 };
72 
73 /// This class allows a pattern's match function for inlining to pass its
74 /// result's precedence to the pattern that requested the expression.
75 class MatchResult {
76 public:
77  MatchResult() = default;
79  : isFailure(false), precedence(precedence) {}
80 
81  bool failed() const { return isFailure; }
82  Precedence getPrecedence() const { return precedence; }
83 
84 private:
85  bool isFailure = true;
87 };
88 
89 //===----------------------------------------------------------------------===//
90 // Emission pattern base classes.
91 //===----------------------------------------------------------------------===//
92 
93 /// This is indented to be the base class for all emission patterns.
94 class PatternBase {
95 public:
96  explicit PatternBase(const void *rootValue) : rootValue(rootValue) {}
97 
98  template <typename E, typename... Args>
99  static std::unique_ptr<E> create(Args &&...args) {
100  std::unique_ptr<E> pattern =
101  std::make_unique<E>(std::forward<Args>(args)...);
102  return pattern;
103  }
104 
105  /// Get a unique identifier for the C++ type the pattern is matching on. This
106  /// could be a specific MLIR type or operation.
107  const void *getRootValue() const { return rootValue; }
108 
109 private:
110  const void *rootValue;
111 };
112 
113 /// This is intended to be the base class for all emission patterns matching on
114 /// operations.
116  OpEmissionPatternBase(StringRef operationName, MLIRContext *context)
117  : PatternBase(
118  OperationName(operationName, context).getAsOpaquePointer()) {}
119  virtual ~OpEmissionPatternBase() = default;
120 
121  /// Checks if this pattern is applicable to the given value to emit an
122  /// inlinable expression. Additionally returns information such as the
123  /// precedence to the pattern where this pattern's result is to be inlined.
124  virtual MatchResult matchInlinable(Value value) = 0;
125 
126  /// Checks if this pattern is applicable to the given operation for statement
127  /// emission.
128  virtual bool matchStatement(mlir::Operation *op) = 0;
129 
130  /// Emit the expression for the given value.
131  virtual void emitInlined(mlir::Value value, EmissionPrinter &p) = 0;
132 
133  /// Emit zero or more statements for the given operation.
134  virtual void emitStatement(mlir::Operation *op, EmissionPrinter &p) = 0;
135 };
136 
137 /// This is intended to be the base class for all emission patterns matching on
138 /// types.
140  explicit TypeEmissionPatternBase(TypeID typeId)
141  : PatternBase(typeId.getAsOpaquePointer()) {}
142  virtual ~TypeEmissionPatternBase() = default;
143 
144  /// Checks if this pattern is applicable to the given type.
145  virtual bool match(Type type) = 0;
146 
147  /// Emit the given type to the emission printer.
148  virtual void emitType(Type type, EmissionPrinter &p) = 0;
149 };
150 
151 /// This is intended to be the base class for all emission patterns matching on
152 /// attributes.
154  explicit AttrEmissionPatternBase(TypeID typeId)
155  : PatternBase(typeId.getAsOpaquePointer()) {}
156  virtual ~AttrEmissionPatternBase() = default;
157 
158  /// Checks if this pattern is applicable to the given attribute.
159  virtual bool match(Attribute attr) = 0;
160 
161  /// Emit the given attribute to the emission printer.
162  virtual void emitAttr(Attribute attr, EmissionPrinter &p) = 0;
163 };
164 
165 /// This is a convenience class providing default implementations for operation
166 /// emission patterns.
167 template <typename Op>
169  explicit OpEmissionPattern(MLIRContext *context)
170  : OpEmissionPatternBase(Op::getOperationName(), context) {}
171 
172  void emitStatement(mlir::Operation *op, EmissionPrinter &p) final {
173  return emitStatement(cast<Op>(op), p);
174  }
175 
176  /// Checks if this pattern is applicable to the given value to emit an
177  /// inlinable expression. Additionally returns information such as the
178  /// precedence to the pattern where this pattern's result is to be inlined.
179  /// Defaults to never match.
180  MatchResult matchInlinable(Value value) override { return MatchResult(); }
181 
182  /// Checks if this pattern is applicable to the given operation for statement
183  /// emission. When not overriden this matches on all operations of the type
184  /// given as template parameter and emits nothing.
185  bool matchStatement(mlir::Operation *op) override { return isa<Op>(op); }
186 
187  /// Emit the expression for the given value. This has to be overriden whenever
188  /// the 'matchInlinable' function is overriden and emit a valid expression.
189  void emitInlined(mlir::Value value, EmissionPrinter &p) override {}
190 
191  /// Emit zero (default) or more statements for the given operation.
192  virtual void emitStatement(Op op, EmissionPrinter &p) {}
193 };
194 
195 /// This is a convenience class providing default implementations for type
196 /// emission patterns.
197 template <typename Ty>
200 
201  void emitType(Type type, EmissionPrinter &p) final {
202  emitType(cast<Ty>(type), p);
203  }
204 
205  /// Checks if this pattern is applicable to the given type. Matches to the
206  /// type given as template argument by default.
207  bool match(Type type) override { return isa<Ty>(type); }
208 
209  /// Emit the given type to the emission printer.
210  virtual void emitType(Ty type, EmissionPrinter &p) = 0;
211 };
212 
213 /// This is a convenience class providing default implementations for attribute
214 /// emission patterns.
215 template <typename A>
218 
219  void emitAttr(Attribute attr, EmissionPrinter &p) final {
220  emitAttr(cast<A>(attr), p);
221  }
222 
223  /// Checks if this pattern is applicable to the given attribute. Matches to
224  /// the attribute given as template argument by default.
225  bool match(Attribute attr) override { return isa<A>(attr); }
226 
227  /// Emit the given attribute to the emission printer.
228  virtual void emitAttr(A attr, EmissionPrinter &p) = 0;
229 };
230 
231 //===----------------------------------------------------------------------===//
232 // Emission pattern sets.
233 //===----------------------------------------------------------------------===//
234 
235 /// This class collects a set of emission patterns with base type 'PatternTy'.
236 template <typename PatternTy>
238 public:
239  /// Add a new emission pattern that requires additional constructor arguments
240  /// to this set.
241  template <typename... Es, typename ConstructorArg,
242  typename... ConstructorArgs,
243  typename = std::enable_if_t<sizeof...(Es) != 0>>
244  void add(ConstructorArg &&arg, ConstructorArgs &&...args) {
245  (void)std::initializer_list<int>{
246  0, (addImpl<Es>(std::forward<ConstructorArg>(arg),
247  std::forward<ConstructorArgs>(args)...),
248  0)...};
249  }
250 
251  /// Add a new emission pattern to the set.
252  template <typename... Es, typename = std::enable_if_t<sizeof...(Es) != 0>>
253  void add() {
254  (void)std::initializer_list<int>{0, (addImpl<Es>(), 0)...};
255  }
256 
257  /// Get all the emission patterns added to this set.
258  std::vector<std::unique_ptr<PatternTy>> &getNativePatterns() {
259  return patterns;
260  }
261 
262 private:
263  template <typename E, typename... Args>
264  std::enable_if_t<std::is_base_of<PatternTy, E>::value>
265  addImpl(Args &&...args) {
266  std::unique_ptr<E> pattern =
267  PatternBase::create<E>(std::forward<Args>(args)...);
268  patterns.emplace_back(std::move(pattern));
269  }
270 
271 private:
272  std::vector<std::unique_ptr<PatternTy>> patterns;
273 };
274 
275 /// This class intends to collect a set of emission patterns in a way to provide
276 /// fast lookups, but does not allow to add more patterns after construction.
277 template <typename PatternTy, typename KeyTy>
279  using NativePatternListT = std::vector<std::unique_ptr<PatternTy>>;
280 
281 public:
282  /// A map of type specific native patterns.
284  DenseMap<KeyTy, std::vector<PatternTy *>>;
285 
286  FrozenEmissionPatternSet() : impl(std::make_shared<Impl>()) {}
287 
288  /// Freeze the patterns held in `patterns`, and take ownership.
290  : impl(std::make_shared<Impl>()) {
291  for (std::unique_ptr<PatternTy> &pat : patterns.getNativePatterns()) {
292  impl->nativeOpSpecificPatternMap[KeyTy::getFromOpaquePointer(
293  pat->getRootValue())]
294  .push_back(pat.get());
295  impl->nativeOpSpecificPatternList.push_back(std::move(pat));
296  }
297  }
298 
299  /// Return the native patterns held by this set.
301  return impl->nativeOpSpecificPatternMap;
302  }
303 
304 private:
305  /// The internal implementation of the frozen pattern set.
306  struct Impl {
307  /// The set of emission patterns that are matched to specific kinds.
309 
310  /// The full native rewrite list. This allows for the map above
311  /// to contain duplicate patterns, e.g. for interfaces and traits.
313  };
314 
315  /// A pointer to the internal pattern list. This uses a shared_ptr to avoid
316  /// the need to compile the same pattern list multiple times. For example,
317  /// during multi-threaded pass execution, all copies of a pass can share the
318  /// same pattern list.
319  std::shared_ptr<Impl> impl;
320 };
321 
322 } // namespace ExportSystemC
323 } // namespace circt
324 
325 #endif // CIRCT_TARGET_EXPORTSYSTEMC_EMISSIONPATTERN_H
This class collects a set of emission patterns with base type 'PatternTy'.
std::vector< std::unique_ptr< PatternTy > > & getNativePatterns()
Get all the emission patterns added to this set.
std::vector< std::unique_ptr< PatternTy > > patterns
std::enable_if_t< std::is_base_of< PatternTy, E >::value > addImpl(Args &&...args)
void add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add a new emission pattern that requires additional constructor arguments to this set.
void add()
Add a new emission pattern to the set.
This is intended to be the driving class for all pattern-based IR emission.
This class intends to collect a set of emission patterns in a way to provide fast lookups,...
DenseMap< KeyTy, std::vector< PatternTy * > > OpSpecificNativePatternListT
A map of type specific native patterns.
const OpSpecificNativePatternListT & getSpecificNativePatterns() const
Return the native patterns held by this set.
std::vector< std::unique_ptr< PatternTy > > NativePatternListT
std::shared_ptr< Impl > impl
A pointer to the internal pattern list.
FrozenEmissionPatternSet(EmissionPatternSet< PatternTy > &&patterns)
Freeze the patterns held in patterns, and take ownership.
This class allows a pattern's match function for inlining to pass its result's precedence to the patt...
MatchResult(Precedence precedence)
This is indented to be the base class for all emission patterns.
const void * getRootValue() const
Get a unique identifier for the C++ type the pattern is matching on.
PatternBase(const void *rootValue)
static std::unique_ptr< E > create(Args &&...args)
Precedence
This enum encodes the precedence of C++ expressions.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:54
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
This is intended to be the base class for all emission patterns matching on attributes.
virtual bool match(Attribute attr)=0
Checks if this pattern is applicable to the given attribute.
virtual void emitAttr(Attribute attr, EmissionPrinter &p)=0
Emit the given attribute to the emission printer.
This is a convenience class providing default implementations for attribute emission patterns.
bool match(Attribute attr) override
Checks if this pattern is applicable to the given attribute.
virtual void emitAttr(A attr, EmissionPrinter &p)=0
Emit the given attribute to the emission printer.
void emitAttr(Attribute attr, EmissionPrinter &p) final
Emit the given attribute to the emission printer.
The internal implementation of the frozen pattern set.
OpSpecificNativePatternListT nativeOpSpecificPatternMap
The set of emission patterns that are matched to specific kinds.
NativePatternListT nativeOpSpecificPatternList
The full native rewrite list.
This is intended to be the base class for all emission patterns matching on operations.
virtual void emitInlined(mlir::Value value, EmissionPrinter &p)=0
Emit the expression for the given value.
OpEmissionPatternBase(StringRef operationName, MLIRContext *context)
virtual bool matchStatement(mlir::Operation *op)=0
Checks if this pattern is applicable to the given operation for statement emission.
virtual void emitStatement(mlir::Operation *op, EmissionPrinter &p)=0
Emit zero or more statements for the given operation.
virtual MatchResult matchInlinable(Value value)=0
Checks if this pattern is applicable to the given value to emit an inlinable expression.
This is a convenience class providing default implementations for operation emission patterns.
void emitInlined(mlir::Value value, EmissionPrinter &p) override
Emit the expression for the given value.
bool matchStatement(mlir::Operation *op) override
Checks if this pattern is applicable to the given operation for statement emission.
void emitStatement(mlir::Operation *op, EmissionPrinter &p) final
Emit zero or more statements for the given operation.
virtual void emitStatement(Op op, EmissionPrinter &p)
Emit zero (default) or more statements for the given operation.
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
This is intended to be the base class for all emission patterns matching on types.
virtual bool match(Type type)=0
Checks if this pattern is applicable to the given type.
virtual void emitType(Type type, EmissionPrinter &p)=0
Emit the given type to the emission printer.
This is a convenience class providing default implementations for type emission patterns.
void emitType(Type type, EmissionPrinter &p) final
Emit the given type to the emission printer.
virtual void emitType(Ty type, EmissionPrinter &p)=0
Emit the given type to the emission printer.
bool match(Type type) override
Checks if this pattern is applicable to the given type.