MLIR  20.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 successor
157  /// constraint. These functions are in the form:
158  ///
159  /// LogicalResult(Operation *op, Block *successor, StringRef successorName,
160  /// unsigned successorIndex);
161  ///
162  StringRef getSuccessorConstraintFn(const Constraint &constraint) const;
163 
164  /// Get the name of the static function used for the given region constraint.
165  /// These functions are in the form:
166  ///
167  /// LogicalResult(Operation *op, Region &region, StringRef regionName,
168  /// unsigned regionIndex);
169  ///
170  /// The region name may be empty.
171  StringRef getRegionConstraintFn(const Constraint &constraint) const;
172 
173 private:
174  /// Emit static type constraint functions.
175  void emitTypeConstraints();
176  /// Emit static attribute constraint functions.
177  void emitAttrConstraints();
178  /// Emit static successor constraint functions.
179  void emitSuccessorConstraints();
180  /// Emit static region constraint functions.
181  void emitRegionConstraints();
182 
183  /// Emit pattern constraints.
184  void emitPatternConstraints();
185 
186  /// Collect and unique all pattern constraints.
187  void collectPatternConstraints(ArrayRef<DagLeaf> constraints);
188 
189  /// The output stream.
190  raw_ostream &os;
191 
192  /// A unique label for the file currently being generated. This is used to
193  /// ensure that the static functions have a unique name.
194  std::string uniqueOutputLabel;
195 
196  /// Use a MapVector to ensure that functions are generated deterministically.
197  using ConstraintMap = llvm::MapVector<Constraint, std::string,
199 
200  /// A generic function to emit constraints
201  void emitConstraints(const ConstraintMap &constraints, StringRef selfName,
202  const char *codeTemplate);
203 
204  /// Assign a unique name to a unique constraint.
205  std::string getUniqueName(StringRef kind, unsigned index);
206  /// Unique a constraint in the map.
207  void collectConstraint(ConstraintMap &map, StringRef kind,
208  Constraint constraint);
209 
210  /// The set of type constraints used for operand and result verification in
211  /// the current file.
212  ConstraintMap typeConstraints;
213  /// The set of attribute constraints used in the current file.
214  ConstraintMap attrConstraints;
215  /// The set of successor constraints used in the current file.
216  ConstraintMap successorConstraints;
217  /// The set of region constraints used in the current file.
218  ConstraintMap regionConstraints;
219 };
220 
221 /// Escape a string using C++ encoding. E.g. foo"bar -> foo\x22bar.
222 std::string escapeString(StringRef value);
223 
224 namespace detail {
225 template <typename>
226 struct stringifier {
227  template <typename T>
228  static std::string apply(T &&t) {
229  return std::string(std::forward<T>(t));
230  }
231 };
232 template <>
233 struct stringifier<Twine> {
234  static std::string apply(const Twine &twine) { return twine.str(); }
235 };
236 template <typename OptionalT>
237 struct stringifier<std::optional<OptionalT>> {
238  static std::string apply(std::optional<OptionalT> optional) {
239  return optional ? stringifier<OptionalT>::apply(*optional) : std::string();
240  }
241 };
242 } // namespace detail
243 
244 /// Generically convert a value to a std::string.
245 template <typename T>
246 std::string stringify(T &&t) {
248  apply(std::forward<T>(t));
249 }
250 
251 } // namespace tblgen
252 } // namespace mlir
253 
254 #endif // MLIR_TABLEGEN_CODEGENHELPERS_H
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.
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)