MLIR  15.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 
16 #include "mlir/TableGen/Dialect.h"
17 #include "mlir/TableGen/Format.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/MapVector.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/StringRef.h"
22 
23 namespace llvm {
24 class RecordKeeper;
25 } // namespace llvm
26 
27 namespace mlir {
28 namespace tblgen {
29 class Constraint;
30 class DagLeaf;
31 
32 // Format into a std::string
33 template <typename... Parameters>
34 std::string strfmt(const char *fmt, Parameters &&...parameters) {
35  return llvm::formatv(fmt, std::forward<Parameters>(parameters)...).str();
36 }
37 
38 // Simple RAII helper for defining ifdef-undef-endif scopes.
39 class IfDefScope {
40 public:
41  IfDefScope(llvm::StringRef name, llvm::raw_ostream &os)
42  : name(name.str()), os(os) {
43  os << "#ifdef " << name << "\n"
44  << "#undef " << name << "\n\n";
45  }
46  ~IfDefScope() { os << "\n#endif // " << name << "\n\n"; }
47 
48 private:
49  std::string name;
50  llvm::raw_ostream &os;
51 };
52 
53 // A helper RAII class to emit nested namespaces for this op.
55 public:
56  NamespaceEmitter(raw_ostream &os, const Dialect &dialect) : os(os) {
57  if (!dialect)
58  return;
59  emitNamespaceStarts(os, dialect.getCppNamespace());
60  }
61  NamespaceEmitter(raw_ostream &os, StringRef cppNamespace) : os(os) {
62  emitNamespaceStarts(os, cppNamespace);
63  }
64 
66  for (StringRef ns : llvm::reverse(namespaces))
67  os << "} // namespace " << ns << "\n";
68  }
69 
70 private:
71  void emitNamespaceStarts(raw_ostream &os, StringRef cppNamespace) {
72  llvm::SplitString(cppNamespace, namespaces, "::");
73  for (StringRef ns : namespaces)
74  os << "namespace " << ns << " {\n";
75  }
76  raw_ostream &os;
77  SmallVector<StringRef, 2> namespaces;
78 };
79 
80 /// This class deduplicates shared operation verification code by emitting
81 /// static functions alongside the op definitions. These methods are local to
82 /// the definition file, and are invoked within the operation verify methods.
83 /// An example is shown below:
84 ///
85 /// static LogicalResult localVerify(...)
86 ///
87 /// LogicalResult OpA::verify(...) {
88 /// if (failed(localVerify(...)))
89 /// return failure();
90 /// ...
91 /// }
92 ///
93 /// LogicalResult OpB::verify(...) {
94 /// if (failed(localVerify(...)))
95 /// return failure();
96 /// ...
97 /// }
98 ///
100 public:
101  StaticVerifierFunctionEmitter(raw_ostream &os,
102  const llvm::RecordKeeper &records);
103 
104  /// Collect and unique all compatible type, attribute, successor, and region
105  /// constraints from the operations in the file and emit them at the top of
106  /// the generated file.
107  ///
108  /// Constraints that do not meet the restriction that they can only reference
109  /// `$_self` and `$_op` are not uniqued.
110  void emitOpConstraints(ArrayRef<llvm::Record *> opDefs, bool emitDecl);
111 
112  /// Unique all compatible type and attribute constraints from a pattern file
113  /// and emit them at the top of the generated file.
114  ///
115  /// Constraints that do not meet the restriction that they can only reference
116  /// `$_self`, `$_op`, and `$_builder` are not uniqued.
117  void emitPatternConstraints(const ArrayRef<DagLeaf> constraints);
118 
119  /// Get the name of the static function used for the given type constraint.
120  /// These functions are used for operand and result constraints and have the
121  /// form:
122  ///
123  /// LogicalResult(Operation *op, Type type, StringRef valueKind,
124  /// unsigned valueIndex);
125  ///
126  /// Pattern constraints have the form:
127  ///
128  /// LogicalResult(PatternRewriter &rewriter, Operation *op, Type type,
129  /// StringRef failureStr);
130  ///
131  StringRef getTypeConstraintFn(const Constraint &constraint) const;
132 
133  /// Get the name of the static function used for the given attribute
134  /// constraint. These functions are in the form:
135  ///
136  /// LogicalResult(Operation *op, Attribute attr, StringRef attrName);
137  ///
138  /// If a uniqued constraint was not found, this function returns None. The
139  /// uniqued constraints cannot be used in the context of an OpAdaptor.
140  ///
141  /// Pattern constraints have the form:
142  ///
143  /// LogicalResult(PatternRewriter &rewriter, Operation *op, Attribute attr,
144  /// StringRef failureStr);
145  ///
146  Optional<StringRef> getAttrConstraintFn(const Constraint &constraint) const;
147 
148  /// Get the name of the static function used for the given successor
149  /// constraint. These functions are in the form:
150  ///
151  /// LogicalResult(Operation *op, Block *successor, StringRef successorName,
152  /// unsigned successorIndex);
153  ///
154  StringRef getSuccessorConstraintFn(const Constraint &constraint) const;
155 
156  /// Get the name of the static function used for the given region constraint.
157  /// These functions are in the form:
158  ///
159  /// LogicalResult(Operation *op, Region &region, StringRef regionName,
160  /// unsigned regionIndex);
161  ///
162  /// The region name may be empty.
163  StringRef getRegionConstraintFn(const Constraint &constraint) const;
164 
165 private:
166  /// Emit static type constraint functions.
167  void emitTypeConstraints();
168  /// Emit static attribute constraint functions.
169  void emitAttrConstraints();
170  /// Emit static successor constraint functions.
171  void emitSuccessorConstraints();
172  /// Emit static region constraint functions.
173  void emitRegionConstraints();
174 
175  /// Emit pattern constraints.
176  void emitPatternConstraints();
177 
178  /// Collect and unique all the constraints used by operations.
179  void collectOpConstraints(ArrayRef<llvm::Record *> opDefs);
180  /// Collect and unique all pattern constraints.
181  void collectPatternConstraints(ArrayRef<DagLeaf> constraints);
182 
183  /// The output stream.
184  raw_ostream &os;
185 
186  /// A unique label for the file currently being generated. This is used to
187  /// ensure that the static functions have a unique name.
188  std::string uniqueOutputLabel;
189 
190  /// Use a MapVector to ensure that functions are generated deterministically.
191  using ConstraintMap = llvm::MapVector<Constraint, std::string,
193 
194  /// A generic function to emit constraints
195  void emitConstraints(const ConstraintMap &constraints, StringRef selfName,
196  const char *codeTemplate);
197 
198  /// Assign a unique name to a unique constraint.
199  std::string getUniqueName(StringRef kind, unsigned index);
200  /// Unique a constraint in the map.
201  void collectConstraint(ConstraintMap &map, StringRef kind,
202  Constraint constraint);
203 
204  /// The set of type constraints used for operand and result verification in
205  /// the current file.
206  ConstraintMap typeConstraints;
207  /// The set of attribute constraints used in the current file.
208  ConstraintMap attrConstraints;
209  /// The set of successor constraints used in the current file.
210  ConstraintMap successorConstraints;
211  /// The set of region constraints used in the current file.
212  ConstraintMap regionConstraints;
213 };
214 
215 /// Escape a string using C++ encoding. E.g. foo"bar -> foo\x22bar.
216 std::string escapeString(StringRef value);
217 
218 namespace detail {
219 template <typename> struct stringifier {
220  template <typename T> static std::string apply(T &&t) {
221  return std::string(std::forward<T>(t));
222  }
223 };
224 template <> struct stringifier<Twine> {
225  static std::string apply(const Twine &twine) {
226  return twine.str();
227  }
228 };
229 template <typename OptionalT>
230 struct stringifier<Optional<OptionalT>> {
231  static std::string apply(Optional<OptionalT> optional) {
232  return optional.hasValue() ? stringifier<OptionalT>::apply(*optional)
233  : std::string();
234  }
235 };
236 } // namespace detail
237 
238 /// Generically convert a value to a std::string.
239 template <typename T> std::string stringify(T &&t) {
241  apply(std::forward<T>(t));
242 }
243 
244 } // namespace tblgen
245 } // namespace mlir
246 
247 #endif // MLIR_TABLEGEN_CODEGENHELPERS_H
Include the generated interface declarations.
Explicitly register a set of "builtin" types.
Definition: CallGraph.h:221
static std::string apply(const Twine &twine)
static std::string apply(T &&t)
IfDefScope(llvm::StringRef name, llvm::raw_ostream &os)
static constexpr const bool value
static std::string apply(Optional< OptionalT > optional)
StringRef getCppNamespace() const
Definition: Dialect.cpp:28
std::string strfmt(const char *fmt, Parameters &&...parameters)
This class deduplicates shared operation verification code by emitting static functions alongside the...
static std::string escapeString(std::string str)
Escape special characters such as &#39; &#39; and quotation marks.
Definition: ViewOpGraph.cpp:43
std::string stringify(T &&t)
Generically convert a value to a std::string.
NamespaceEmitter(raw_ostream &os, StringRef cppNamespace)
NamespaceEmitter(raw_ostream &os, const Dialect &dialect)