MLIR  19.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  StaticVerifierFunctionEmitter(raw_ostream &os,
103  const llvm::RecordKeeper &records);
104 
105  /// Collect and unique all compatible type, attribute, successor, and region
106  /// constraints from the operations in the file and emit them at the top of
107  /// the generated file.
108  ///
109  /// Constraints that do not meet the restriction that they can only reference
110  /// `$_self` and `$_op` are not uniqued.
111  void emitOpConstraints(ArrayRef<llvm::Record *> opDefs, bool emitDecl);
112 
113  /// Unique all compatible type and attribute constraints from a pattern file
114  /// and emit them at the top of the generated file.
115  ///
116  /// Constraints that do not meet the restriction that they can only reference
117  /// `$_self`, `$_op`, and `$_builder` are not uniqued.
118  void emitPatternConstraints(const ArrayRef<DagLeaf> constraints);
119 
120  /// Get the name of the static function used for the given type constraint.
121  /// These functions are used for operand and result constraints and have the
122  /// form:
123  ///
124  /// LogicalResult(Operation *op, Type type, StringRef valueKind,
125  /// unsigned valueIndex);
126  ///
127  /// Pattern constraints have the form:
128  ///
129  /// LogicalResult(PatternRewriter &rewriter, Operation *op, Type type,
130  /// StringRef failureStr);
131  ///
132  StringRef getTypeConstraintFn(const Constraint &constraint) const;
133 
134  /// Get the name of the static function used for the given attribute
135  /// constraint. These functions are in the form:
136  ///
137  /// LogicalResult(Operation *op, Attribute attr, StringRef attrName);
138  ///
139  /// If a uniqued constraint was not found, this function returns std::nullopt.
140  /// The uniqued constraints cannot be used in the context of an OpAdaptor.
141  ///
142  /// Pattern constraints have the form:
143  ///
144  /// LogicalResult(PatternRewriter &rewriter, Operation *op, Attribute attr,
145  /// StringRef failureStr);
146  ///
147  std::optional<StringRef>
148  getAttrConstraintFn(const Constraint &constraint) const;
149 
150  /// Get the name of the static function used for the given successor
151  /// constraint. These functions are in the form:
152  ///
153  /// LogicalResult(Operation *op, Block *successor, StringRef successorName,
154  /// unsigned successorIndex);
155  ///
156  StringRef getSuccessorConstraintFn(const Constraint &constraint) const;
157 
158  /// Get the name of the static function used for the given region constraint.
159  /// These functions are in the form:
160  ///
161  /// LogicalResult(Operation *op, Region &region, StringRef regionName,
162  /// unsigned regionIndex);
163  ///
164  /// The region name may be empty.
165  StringRef getRegionConstraintFn(const Constraint &constraint) const;
166 
167 private:
168  /// Emit static type constraint functions.
169  void emitTypeConstraints();
170  /// Emit static attribute constraint functions.
171  void emitAttrConstraints();
172  /// Emit static successor constraint functions.
173  void emitSuccessorConstraints();
174  /// Emit static region constraint functions.
175  void emitRegionConstraints();
176 
177  /// Emit pattern constraints.
178  void emitPatternConstraints();
179 
180  /// Collect and unique all the constraints used by operations.
181  void collectOpConstraints(ArrayRef<llvm::Record *> opDefs);
182  /// Collect and unique all pattern constraints.
183  void collectPatternConstraints(ArrayRef<DagLeaf> constraints);
184 
185  /// The output stream.
186  raw_ostream &os;
187 
188  /// A unique label for the file currently being generated. This is used to
189  /// ensure that the static functions have a unique name.
190  std::string uniqueOutputLabel;
191 
192  /// Use a MapVector to ensure that functions are generated deterministically.
193  using ConstraintMap = llvm::MapVector<Constraint, std::string,
195 
196  /// A generic function to emit constraints
197  void emitConstraints(const ConstraintMap &constraints, StringRef selfName,
198  const char *codeTemplate);
199 
200  /// Assign a unique name to a unique constraint.
201  std::string getUniqueName(StringRef kind, unsigned index);
202  /// Unique a constraint in the map.
203  void collectConstraint(ConstraintMap &map, StringRef kind,
204  Constraint constraint);
205 
206  /// The set of type constraints used for operand and result verification in
207  /// the current file.
208  ConstraintMap typeConstraints;
209  /// The set of attribute constraints used in the current file.
210  ConstraintMap attrConstraints;
211  /// The set of successor constraints used in the current file.
212  ConstraintMap successorConstraints;
213  /// The set of region constraints used in the current file.
214  ConstraintMap regionConstraints;
215 };
216 
217 /// Escape a string using C++ encoding. E.g. foo"bar -> foo\x22bar.
218 std::string escapeString(StringRef value);
219 
220 namespace detail {
221 template <typename>
222 struct stringifier {
223  template <typename T>
224  static std::string apply(T &&t) {
225  return std::string(std::forward<T>(t));
226  }
227 };
228 template <>
229 struct stringifier<Twine> {
230  static std::string apply(const Twine &twine) { return twine.str(); }
231 };
232 template <typename OptionalT>
233 struct stringifier<std::optional<OptionalT>> {
234  static std::string apply(std::optional<OptionalT> optional) {
235  return optional ? stringifier<OptionalT>::apply(*optional) : std::string();
236  }
237 };
238 } // namespace detail
239 
240 /// Generically convert a value to a std::string.
241 template <typename T>
242 std::string stringify(T &&t) {
244  apply(std::forward<T>(t));
245 }
246 
247 } // namespace tblgen
248 } // namespace mlir
249 
250 #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 ...
void emitOpConstraints(ArrayRef< llvm::Record * > opDefs, bool emitDecl)
Collect and unique all compatible type, attribute, successor, and region constraints from the operati...
std::optional< StringRef > getAttrConstraintFn(const Constraint &constraint) const
Get the name of the static function used for the given attribute constraint.
StaticVerifierFunctionEmitter(raw_ostream &os, const llvm::RecordKeeper &records)
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.
Include the generated interface declarations.
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)