MLIR  21.0.0git
CodeGenHelpers.h
Go to the documentation of this file.
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file defines common utilities for generating C++ from tablegen
9 // structures.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_TABLEGEN_CODEGENHELPERS_H
14 #define MLIR_TABLEGEN_CODEGENHELPERS_H
15 
17 #include "mlir/TableGen/Dialect.h"
18 #include "mlir/TableGen/Format.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/MapVector.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/ADT/StringRef.h"
23 
24 namespace llvm {
25 class RecordKeeper;
26 } // namespace llvm
27 
28 namespace mlir {
29 namespace tblgen {
30 class Constraint;
31 class DagLeaf;
32 
33 // Format into a std::string
34 template <typename... Parameters>
35 std::string strfmt(const char *fmt, Parameters &&...parameters) {
36  return llvm::formatv(fmt, std::forward<Parameters>(parameters)...).str();
37 }
38 
39 // Simple RAII helper for defining ifdef-undef-endif scopes.
40 class IfDefScope {
41 public:
42  IfDefScope(llvm::StringRef name, llvm::raw_ostream &os)
43  : name(name.str()), os(os) {
44  os << "#ifdef " << name << "\n"
45  << "#undef " << name << "\n\n";
46  }
47  ~IfDefScope() { os << "\n#endif // " << name << "\n\n"; }
48 
49 private:
50  std::string name;
51  llvm::raw_ostream &os;
52 };
53 
54 // A helper RAII class to emit nested namespaces for this op.
56 public:
57  NamespaceEmitter(raw_ostream &os, const Dialect &dialect) : os(os) {
58  if (!dialect)
59  return;
60  emitNamespaceStarts(os, dialect.getCppNamespace());
61  }
62  NamespaceEmitter(raw_ostream &os, StringRef cppNamespace) : os(os) {
63  emitNamespaceStarts(os, cppNamespace);
64  }
65 
67  for (StringRef ns : llvm::reverse(namespaces))
68  os << "} // namespace " << ns << "\n";
69  }
70 
71 private:
72  void emitNamespaceStarts(raw_ostream &os, StringRef cppNamespace) {
73  llvm::SplitString(cppNamespace, namespaces, "::");
74  for (StringRef ns : namespaces)
75  os << "namespace " << ns << " {\n";
76  }
77  raw_ostream &os;
78  SmallVector<StringRef, 2> namespaces;
79 };
80 
81 /// This class deduplicates shared operation verification code by emitting
82 /// static functions alongside the op definitions. These methods are local to
83 /// the definition file, and are invoked within the operation verify methods.
84 /// An example is shown below:
85 ///
86 /// static LogicalResult localVerify(...)
87 ///
88 /// LogicalResult OpA::verify(...) {
89 /// if (failed(localVerify(...)))
90 /// return failure();
91 /// ...
92 /// }
93 ///
94 /// LogicalResult OpB::verify(...) {
95 /// if (failed(localVerify(...)))
96 /// return failure();
97 /// ...
98 /// }
99 ///
101 public:
102  /// Create a constraint uniquer with a unique prefix derived from the record
103  /// keeper with an optional tag.
104  StaticVerifierFunctionEmitter(raw_ostream &os,
105  const llvm::RecordKeeper &records,
106  StringRef tag = "");
107 
108  /// Collect and unique all the constraints used by operations.
110 
111  /// Collect and unique all compatible type, attribute, successor, and region
112  /// constraints from the operations in the file and emit them at the top of
113  /// the generated file.
114  ///
115  /// Constraints that do not meet the restriction that they can only reference
116  /// `$_self` and `$_op` are not uniqued.
118 
119  /// Unique all compatible type and attribute constraints from a pattern file
120  /// and emit them at the top of the generated file.
121  ///
122  /// Constraints that do not meet the restriction that they can only reference
123  /// `$_self`, `$_op`, and `$_builder` are not uniqued.
124  void emitPatternConstraints(const ArrayRef<DagLeaf> constraints);
125 
126  /// Get the name of the static function used for the given type constraint.
127  /// These functions are used for operand and result constraints and have the
128  /// form:
129  ///
130  /// LogicalResult(Operation *op, Type type, StringRef valueKind,
131  /// unsigned valueIndex);
132  ///
133  /// Pattern constraints have the form:
134  ///
135  /// LogicalResult(PatternRewriter &rewriter, Operation *op, Type type,
136  /// StringRef failureStr);
137  ///
138  StringRef getTypeConstraintFn(const Constraint &constraint) const;
139 
140  /// Get the name of the static function used for the given attribute
141  /// constraint. These functions are in the form:
142  ///
143  /// LogicalResult(Operation *op, Attribute attr, StringRef attrName);
144  ///
145  /// If a uniqued constraint was not found, this function returns std::nullopt.
146  /// The uniqued constraints cannot be used in the context of an OpAdaptor.
147  ///
148  /// Pattern constraints have the form:
149  ///
150  /// LogicalResult(PatternRewriter &rewriter, Operation *op, Attribute attr,
151  /// StringRef failureStr);
152  ///
153  std::optional<StringRef>
154  getAttrConstraintFn(const Constraint &constraint) const;
155 
156  /// Get the name of the static function used for the given property
157  /// constraint. These functions are in the form:
158  ///
159  /// LogicalResult(Operation *op, T property, StringRef propName);
160  ///
161  /// where T is the interface type specified in the constraint.
162  /// If a uniqued constraint was not found, this function returns std::nullopt.
163  /// The uniqued constraints cannot be used in the context of an OpAdaptor.
164  ///
165  /// Pattern constraints have the form:
166  ///
167  /// LogicalResult(PatternRewriter &rewriter, Operation *op, T property,
168  /// StringRef failureStr);
169  ///
170  std::optional<StringRef>
171  getPropConstraintFn(const Constraint &constraint) const;
172 
173  /// Get the name of the static function used for the given successor
174  /// constraint. These functions are in the form:
175  ///
176  /// LogicalResult(Operation *op, Block *successor, StringRef successorName,
177  /// unsigned successorIndex);
178  ///
179  StringRef getSuccessorConstraintFn(const Constraint &constraint) const;
180 
181  /// Get the name of the static function used for the given region constraint.
182  /// These functions are in the form:
183  ///
184  /// LogicalResult(Operation *op, Region &region, StringRef regionName,
185  /// unsigned regionIndex);
186  ///
187  /// The region name may be empty.
188  StringRef getRegionConstraintFn(const Constraint &constraint) const;
189 
190 private:
191  /// Emit static type constraint functions.
192  void emitTypeConstraints();
193  /// Emit static attribute constraint functions.
194  void emitAttrConstraints();
195  /// Emit static property constraint functions.
196  void emitPropConstraints();
197  /// Emit static successor constraint functions.
198  void emitSuccessorConstraints();
199  /// Emit static region constraint functions.
200  void emitRegionConstraints();
201 
202  /// Emit pattern constraints.
203  void emitPatternConstraints();
204 
205  /// Collect and unique all pattern constraints.
206  void collectPatternConstraints(ArrayRef<DagLeaf> constraints);
207 
208  /// The output stream.
209  raw_ostream &os;
210 
211  /// A unique label for the file currently being generated. This is used to
212  /// ensure that the static functions have a unique name.
213  std::string uniqueOutputLabel;
214 
215  /// Use a MapVector to ensure that functions are generated deterministically.
216  using ConstraintMap = llvm::MapVector<Constraint, std::string,
218 
219  /// A generic function to emit constraints
220  void emitConstraints(const ConstraintMap &constraints, StringRef selfName,
221  const char *codeTemplate);
222 
223  /// Assign a unique name to a unique constraint.
224  std::string getUniqueName(StringRef kind, unsigned index);
225  /// Unique a constraint in the map.
226  void collectConstraint(ConstraintMap &map, StringRef kind,
227  Constraint constraint);
228 
229  /// The set of type constraints used for operand and result verification in
230  /// the current file.
231  ConstraintMap typeConstraints;
232  /// The set of attribute constraints used in the current file.
233  ConstraintMap attrConstraints;
234  /// The set of property constraints used in the current file.
235  ConstraintMap propConstraints;
236  /// The set of successor constraints used in the current file.
237  ConstraintMap successorConstraints;
238  /// The set of region constraints used in the current file.
239  ConstraintMap regionConstraints;
240 };
241 
242 /// Escape a string using C++ encoding. E.g. foo"bar -> foo\x22bar.
243 std::string escapeString(StringRef value);
244 
245 namespace detail {
246 template <typename>
247 struct stringifier {
248  template <typename T>
249  static std::string apply(T &&t) {
250  return std::string(std::forward<T>(t));
251  }
252 };
253 template <>
254 struct stringifier<Twine> {
255  static std::string apply(const Twine &twine) { return twine.str(); }
256 };
257 template <typename OptionalT>
258 struct stringifier<std::optional<OptionalT>> {
259  static std::string apply(std::optional<OptionalT> optional) {
260  return optional ? stringifier<OptionalT>::apply(*optional) : std::string();
261  }
262 };
263 } // namespace detail
264 
265 /// Generically convert a value to a std::string.
266 template <typename T>
267 std::string stringify(T &&t) {
269  apply(std::forward<T>(t));
270 }
271 
272 } // namespace tblgen
273 } // namespace mlir
274 
275 #endif // MLIR_TABLEGEN_CODEGENHELPERS_H
union mlir::linalg::@1203::ArityGroupAndKind::Kind kind
StringRef getCppNamespace() const
Definition: Dialect.cpp:28
IfDefScope(llvm::StringRef name, llvm::raw_ostream &os)
NamespaceEmitter(raw_ostream &os, const Dialect &dialect)
NamespaceEmitter(raw_ostream &os, StringRef cppNamespace)
This class deduplicates shared operation verification code by emitting static functions alongside the...
StringRef getRegionConstraintFn(const Constraint &constraint) const
Get the name of the static function used for the given region constraint.
void emitPatternConstraints(const ArrayRef< DagLeaf > constraints)
Unique all compatible type and attribute constraints from a pattern file and emit them at the top of ...
std::optional< StringRef > getAttrConstraintFn(const Constraint &constraint) const
Get the name of the static function used for the given attribute constraint.
std::optional< StringRef > getPropConstraintFn(const Constraint &constraint) const
Get the name of the static function used for the given property constraint.
void emitOpConstraints(ArrayRef< const llvm::Record * > opDefs)
Collect and unique all compatible type, attribute, successor, and region constraints from the operati...
StaticVerifierFunctionEmitter(raw_ostream &os, const llvm::RecordKeeper &records, StringRef tag="")
Create a constraint uniquer with a unique prefix derived from the record keeper with an optional tag.
void collectOpConstraints(ArrayRef< const llvm::Record * > opDefs)
Collect and unique all the constraints used by operations.
StringRef getTypeConstraintFn(const Constraint &constraint) const
Get the name of the static function used for the given type constraint.
StringRef getSuccessorConstraintFn(const Constraint &constraint) const
Get the name of the static function used for the given successor constraint.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition: CallGraph.h:229
std::string escapeString(StringRef value)
Escape a string using C++ encoding. E.g. foo"bar -> foo\x22bar.
std::string strfmt(const char *fmt, Parameters &&...parameters)
std::string stringify(T &&t)
Generically convert a value to a std::string.
Include the generated interface declarations.
static std::string apply(const Twine &twine)
static std::string apply(std::optional< OptionalT > optional)
static std::string apply(T &&t)