1//===- Class.h - Helper classes for C++ code emission -----------*- C++ -*-===//
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 file defines several classes for C++ code emission. They are only
10// expected to be used by MLIR TableGen backends.
11//
12// We emit the declarations and definitions into separate files: *.h.inc and
13// *.cpp.inc. The former is to be included in the dialect *.h and the latter for
14// dialect *.cpp. This way provides a cleaner interface.
15//
16// In order to do this split, we need to track method signature and
17// implementation logic separately. Signature information is used for both
18// declaration and definition, while implementation logic is only for
19// definition. So we have the following classes for C++ code emission.
20//
21//===----------------------------------------------------------------------===//
22
23#ifndef MLIR_TABLEGEN_CLASS_H_
24#define MLIR_TABLEGEN_CLASS_H_
25
26#include "mlir/Support/IndentedOstream.h"
27#include "mlir/Support/LLVM.h"
28#include "mlir/TableGen/CodeGenHelpers.h"
29#include "llvm/ADT/SetVector.h"
30#include "llvm/ADT/SmallVector.h"
31#include "llvm/ADT/StringRef.h"
32#include "llvm/ADT/StringSet.h"
33#include "llvm/ADT/Twine.h"
34
35#include <set>
36#include <string>
37
38namespace mlir {
39namespace tblgen {
40class FmtObjectBase;
41
42/// This class contains a single method parameter for a C++ function.
43class MethodParameter {
44public:
45 /// Create a method parameter with a C++ type, parameter name, and an optional
46 /// default value. Marking a parameter as "optional" is a cosmetic effect on
47 /// the generated code.
48 template <typename TypeT, typename NameT, typename DefaultT>
49 MethodParameter(TypeT &&type, NameT &&name, DefaultT &&defaultValue,
50 bool optional = false)
51 : type(stringify(std::forward<TypeT>(type))),
52 name(stringify(std::forward<NameT>(name))),
53 defaultValue(stringify(std::forward<DefaultT>(defaultValue))),
54 optional(optional) {}
55
56 /// Create a method parameter with a C++ type, parameter name, and no default
57 /// value.
58 template <typename TypeT, typename NameT>
59 MethodParameter(TypeT &&type, NameT &&name, bool optional = false)
60 : MethodParameter(std::forward<TypeT>(type), std::forward<NameT>(name),
61 /*defaultValue=*/"", optional) {}
62
63 /// Write the parameter as part of a method declaration.
64 void writeDeclTo(raw_indented_ostream &os) const;
65 /// Write the parameter as part of a method definition.
66 void writeDefTo(raw_indented_ostream &os) const;
67
68 /// Get the C++ type.
69 StringRef getType() const { return type; }
70 /// Returns true if the parameter has a default value.
71 bool hasDefaultValue() const { return !defaultValue.empty(); }
72
73private:
74 /// The C++ type.
75 std::string type;
76 /// The variable name.
77 std::string name;
78 /// An optional default value. The default value exists if the string is not
79 /// empty.
80 std::string defaultValue;
81 /// Whether the parameter should be indicated as "optional".
82 bool optional;
83};
84
85/// This class contains a list of method parameters for constructor, class
86/// methods, and method signatures.
87class MethodParameters {
88public:
89 /// Create a list of method parameters.
90 MethodParameters(std::initializer_list<MethodParameter> parameters)
91 : parameters(parameters) {}
92 MethodParameters(SmallVector<MethodParameter> parameters)
93 : parameters(std::move(parameters)) {}
94
95 /// Write the parameters as part of a method declaration.
96 void writeDeclTo(raw_indented_ostream &os) const;
97 /// Write the parameters as part of a method definition.
98 void writeDefTo(raw_indented_ostream &os) const;
99
100 /// Determine whether this list of parameters "subsumes" another, which occurs
101 /// when this parameter list is identical to the other and has zero or more
102 /// additional default-valued parameters.
103 bool subsumes(const MethodParameters &other) const;
104
105 /// Return the number of parameters.
106 unsigned getNumParameters() const { return parameters.size(); }
107
108private:
109 /// The list of parameters.
110 SmallVector<MethodParameter> parameters;
111};
112
113/// This class contains the signature of a C++ method, including the return
114/// type. method name, and method parameters.
115class MethodSignature {
116public:
117 /// Create a method signature with a return type, a method name, and a list of
118 /// parameters. Take ownership of the list.
119 template <typename RetTypeT, typename NameT>
120 MethodSignature(RetTypeT &&retType, NameT &&name,
121 SmallVector<MethodParameter> &&parameters)
122 : returnType(stringify(std::forward<RetTypeT>(retType))),
123 methodName(stringify(std::forward<NameT>(name))),
124 parameters(std::move(parameters)) {}
125 /// Create a method signature with a return type, a method name, and a list of
126 /// parameters.
127 template <typename RetTypeT, typename NameT>
128 MethodSignature(RetTypeT &&retType, NameT &&name,
129 ArrayRef<MethodParameter> parameters)
130 : MethodSignature(std::forward<RetTypeT>(retType),
131 std::forward<NameT>(name),
132 SmallVector<MethodParameter>(parameters.begin(),
133 parameters.end())) {}
134 /// Create a method signature with a return type, a method name, and a
135 /// variadic list of parameters.
136 template <typename RetTypeT, typename NameT, typename... Parameters>
137 MethodSignature(RetTypeT &&retType, NameT &&name, Parameters &&...parameters)
138 : MethodSignature(std::forward<RetTypeT>(retType),
139 std::forward<NameT>(name),
140 ArrayRef<MethodParameter>(
141 {std::forward<Parameters>(parameters)...})) {}
142
143 /// Determine whether a method with this signature makes a method with
144 /// `other` signature redundant. This occurs if the signatures have the same
145 /// name and this signature's parameteres subsume the other's.
146 ///
147 /// A method that makes another method redundant with a different return type
148 /// can replace the other, the assumption being that the subsuming method
149 /// provides a more resolved return type, e.g. IntegerAttr vs. Attribute.
150 bool makesRedundant(const MethodSignature &other) const;
151
152 /// Get the name of the method.
153 StringRef getName() const { return methodName; }
154
155 /// Get the return type of the method
156 StringRef getReturnType() const { return returnType; }
157
158 /// Get the number of parameters.
159 unsigned getNumParameters() const { return parameters.getNumParameters(); }
160
161 /// Write the signature as part of a method declaration.
162 void writeDeclTo(raw_indented_ostream &os) const;
163
164 /// Write the signature as part of a method definition. `namePrefix` is to be
165 /// prepended to the method name (typically namespaces for qualifying the
166 /// method definition).
167 void writeDefTo(raw_indented_ostream &os, StringRef namePrefix) const;
168
169 /// Write the template parameters of the signature.
170 void writeTemplateParamsTo(raw_indented_ostream &os) const;
171
172 /// Add a template parameter.
173 template <typename ParamT>
174 void addTemplateParam(ParamT param) {
175 templateParams.push_back(stringify(param));
176 }
177
178 /// Add a list of template parameters.
179 template <typename ContainerT>
180 void addTemplateParams(ContainerT &&container) {
181 templateParams.insert(std::begin(container), std::end(container));
182 }
183
184private:
185 /// The method's C++ return type.
186 std::string returnType;
187 /// The method name.
188 std::string methodName;
189 /// The method's parameter list.
190 MethodParameters parameters;
191 /// An optional list of template parameters.
192 SmallVector<std::string, 0> templateParams;
193};
194
195/// This class contains the body of a C++ method.
196class MethodBody {
197public:
198 /// Create a method body, indicating whether it should be elided for methods
199 /// that are declaration-only.
200 MethodBody(bool declOnly);
201
202 /// Define a move constructor to correctly initialize the streams.
203 MethodBody(MethodBody &&other)
204 : declOnly(other.declOnly), body(std::move(other.body)), stringOs(body),
205 os(stringOs) {}
206 /// Define a move assignment operator. `raw_ostream` has deleted assignment
207 /// operators, so reinitialize the whole object.
208 MethodBody &operator=(MethodBody &&body) {
209 this->~MethodBody();
210 new (this) MethodBody(std::move(body));
211 return *this;
212 }
213
214 /// Write a value to the method body.
215 template <typename ValueT>
216 MethodBody &operator<<(ValueT &&value) {
217 if (!declOnly) {
218 os << std::forward<ValueT>(value);
219 os.flush();
220 }
221 return *this;
222 }
223
224 /// Write the method body to the output stream. The body can be written as
225 /// part of the declaration of an inline method or just in the definition.
226 void writeTo(raw_indented_ostream &os) const;
227
228 /// Indent the output stream.
229 MethodBody &indent() {
230 os.indent();
231 return *this;
232 }
233 /// Unindent the output stream.
234 MethodBody &unindent() {
235 os.unindent();
236 return *this;
237 }
238 /// Create a delimited scope: immediately print `open`, indent if `indent` is
239 /// true, and print `close` on object destruction.
240 raw_indented_ostream::DelimitedScope
241 scope(StringRef open = "", StringRef close = "", bool indent = false) {
242 return os.scope(open, close, indent);
243 }
244
245 /// Get the underlying indented output stream.
246 raw_indented_ostream &getStream() { return os; }
247
248private:
249 /// Whether the body should be elided.
250 bool declOnly;
251 /// The body data.
252 std::string body;
253 /// The string output stream.
254 llvm::raw_string_ostream stringOs;
255 /// An indented output stream for formatting input.
256 raw_indented_ostream os;
257};
258
259/// A class declaration is a class element that appears as part of its
260/// declaration.
261class ClassDeclaration {
262public:
263 virtual ~ClassDeclaration() = default;
264
265 /// Kinds for LLVM-style RTTI.
266 enum Kind {
267 Method,
268 UsingDeclaration,
269 VisibilityDeclaration,
270 Field,
271 ExtraClassDeclaration
272 };
273 /// Create a class declaration with a given kind.
274 ClassDeclaration(Kind kind) : kind(kind) {}
275
276 /// Get the class declaration kind.
277 Kind getKind() const { return kind; }
278
279 /// Write the declaration.
280 virtual void writeDeclTo(raw_indented_ostream &os) const = 0;
281
282 /// Write the definition, if any. `namePrefix` is the namespace prefix, which
283 /// may contains a class name.
284 virtual void writeDefTo(raw_indented_ostream &os,
285 StringRef namePrefix) const {}
286
287private:
288 /// The class declaration kind.
289 Kind kind;
290};
291
292/// Base class for class declarations.
293template <ClassDeclaration::Kind DeclKind>
294class ClassDeclarationBase : public ClassDeclaration {
295public:
296 using Base = ClassDeclarationBase<DeclKind>;
297 ClassDeclarationBase() : ClassDeclaration(DeclKind) {}
298
299 static bool classof(const ClassDeclaration *other) {
300 return other->getKind() == DeclKind;
301 }
302};
303
304/// Class for holding an op's method for C++ code emission
305class Method : public ClassDeclarationBase<ClassDeclaration::Method> {
306public:
307 /// Properties (qualifiers) of class methods. Bitfield is used here to help
308 /// querying properties.
309 enum Properties {
310 None = 0x0,
311 Static = 0x1,
312 Constructor = 0x2,
313 Private = 0x4,
314 Declaration = 0x8,
315 Inline = 0x10,
316 ConstexprValue = 0x20,
317 Const = 0x40,
318
319 Constexpr = ConstexprValue | Inline,
320 StaticDeclaration = Static | Declaration,
321 StaticInline = Static | Inline,
322 ConstInline = Const | Inline,
323 ConstDeclaration = Const | Declaration
324 };
325
326 /// Create a method with a return type, a name, method properties, and a some
327 /// parameters. The parameteres may be passed as a list or as a variadic pack.
328 template <typename RetTypeT, typename NameT, typename... Args>
329 Method(RetTypeT &&retType, NameT &&name, Properties properties,
330 Args &&...args)
331 : properties(properties),
332 methodSignature(std::forward<RetTypeT>(retType),
333 std::forward<NameT>(name), std::forward<Args>(args)...),
334 methodBody(properties & Declaration) {}
335 /// Create a method with a return type, a name, method properties, and a list
336 /// of parameters.
337 Method(StringRef retType, StringRef name, Properties properties,
338 std::initializer_list<MethodParameter> params)
339 : properties(properties), methodSignature(retType, name, params),
340 methodBody(properties & Declaration) {}
341
342 // Define move constructor and assignment operator to prevent copying.
343 Method(Method &&) = default;
344 Method &operator=(Method &&) = default;
345
346 /// Get the method body.
347 MethodBody &body() { return methodBody; }
348
349 /// Sets or removes the deprecation message of the method.
350 void setDeprecated(std::optional<StringRef> message) {
351 this->deprecationMessage = message;
352 }
353
354 /// Returns true if this is a static method.
355 bool isStatic() const { return properties & Static; }
356
357 /// Returns true if this is a private method.
358 bool isPrivate() const { return properties & Private; }
359
360 /// Returns true if this is an inline method.
361 bool isInline() const { return properties & Inline; }
362
363 /// Returns true if this is a constructor.
364 bool isConstructor() const { return properties & Constructor; }
365
366 /// Returns true if this class method is const.
367 bool isConst() const { return properties & Const; }
368
369 /// Returns the name of this method.
370 StringRef getName() const { return methodSignature.getName(); }
371
372 /// Returns the return type of this method
373 StringRef getReturnType() const { return methodSignature.getReturnType(); }
374
375 /// Returns if this method makes the `other` method redundant.
376 bool makesRedundant(const Method &other) const {
377 return methodSignature.makesRedundant(other: other.methodSignature);
378 }
379
380 /// Write the method declaration, including the definition if inline.
381 void writeDeclTo(raw_indented_ostream &os) const override;
382
383 /// Write the method definition. This is a no-op for inline methods.
384 void writeDefTo(raw_indented_ostream &os,
385 StringRef namePrefix) const override;
386
387 /// Add a template parameter.
388 template <typename ParamT>
389 void addTemplateParam(ParamT param);
390
391 /// Add a list of template parameters.
392 template <typename ContainerT>
393 void addTemplateParams(ContainerT &&container);
394
395protected:
396 /// A collection of method properties.
397 Properties properties;
398 /// The signature of the method.
399 MethodSignature methodSignature;
400 /// The body of the method, if it has one.
401 MethodBody methodBody;
402 /// Deprecation message if the method is deprecated.
403 std::optional<std::string> deprecationMessage;
404};
405
406/// This enum describes C++ inheritance visibility.
407enum class Visibility { Public, Protected, Private };
408
409/// Write "public", "protected", or "private".
410llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
411 mlir::tblgen::Visibility visibility);
412
413// Class for holding an op's constructor method for C++ code emission.
414class Constructor : public Method {
415public:
416 /// Create a constructor for a given class, with method properties, and
417 /// parameters specified either as a list of a variadic pack.
418 template <typename NameT, typename... Args>
419 Constructor(NameT &&className, Properties properties, Args &&...args)
420 : Method("", std::forward<NameT>(className), properties,
421 std::forward<Args>(args)...) {}
422
423 /// Add member initializer to constructor initializing `name` with `value`.
424 template <typename NameT, typename ValueT>
425 void addMemberInitializer(NameT &&name, ValueT &&value) {
426 initializers.emplace_back(stringify(std::forward<NameT>(name)),
427 stringify(std::forward<ValueT>(value)));
428 }
429
430 /// Write the declaration of the constructor, and its definition if inline.
431 void writeDeclTo(raw_indented_ostream &os) const override;
432
433 /// Write the definition of the constructor if it is not inline.
434 void writeDefTo(raw_indented_ostream &os,
435 StringRef namePrefix) const override;
436
437 /// Return true if a method is a constructor.
438 static bool classof(const ClassDeclaration *other) {
439 return isa<Method>(Val: other) && cast<Method>(Val: other)->isConstructor();
440 }
441
442 /// Initialization of a class field in a constructor.
443 class MemberInitializer {
444 public:
445 /// Create a member initializer in a constructor that initializes the class
446 /// field `name` with `value`.
447 MemberInitializer(std::string name, std::string value)
448 : name(std::move(name)), value(std::move(value)) {}
449
450 /// Write the member initializer.
451 void writeTo(raw_indented_ostream &os) const;
452
453 private:
454 /// The name of the class field.
455 std::string name;
456 /// The value with which to initialize it.
457 std::string value;
458 };
459
460private:
461 /// The list of member initializers.
462 SmallVector<MemberInitializer> initializers;
463};
464
465} // namespace tblgen
466} // namespace mlir
467
468/// The OR of two method properties should return method properties. Ensure that
469/// this function is visible to `Class`.
470inline constexpr mlir::tblgen::Method::Properties
471operator|(mlir::tblgen::Method::Properties lhs,
472 mlir::tblgen::Method::Properties rhs) {
473 return mlir::tblgen::Method::Properties(static_cast<unsigned>(lhs) |
474 static_cast<unsigned>(rhs));
475}
476
477inline constexpr mlir::tblgen::Method::Properties &
478operator|=(mlir::tblgen::Method::Properties &lhs,
479 mlir::tblgen::Method::Properties rhs) {
480 return lhs = mlir::tblgen::Method::Properties(static_cast<unsigned>(lhs) |
481 static_cast<unsigned>(rhs));
482}
483
484namespace mlir {
485namespace tblgen {
486
487template <typename ParamT>
488void Method::addTemplateParam(ParamT param) {
489 // Templates imply inline.
490 properties |= Method::Inline;
491 methodSignature.addTemplateParam(param);
492}
493
494template <typename ContainerT>
495void Method::addTemplateParams(ContainerT &&container) {
496 // Templates imply inline.
497 properties |= Method::Inline;
498 methodSignature.addTemplateParam(std::forward<ContainerT>(container));
499}
500
501/// This class describes a C++ parent class declaration.
502class ParentClass {
503public:
504 /// Create a parent class with a class name and visibility.
505 template <typename NameT>
506 ParentClass(NameT &&name, Visibility visibility = Visibility::Public)
507 : name(stringify(std::forward<NameT>(name))), visibility(visibility) {}
508
509 /// Add a template parameter.
510 template <typename ParamT>
511 void addTemplateParam(ParamT param) {
512 templateParams.insert(stringify(param));
513 }
514 /// Add a list of template parameters.
515 template <typename ContainerT>
516 void addTemplateParams(ContainerT &&container) {
517 templateParams.insert(std::begin(container), std::end(container));
518 }
519
520 /// Write the parent class declaration.
521 void writeTo(raw_indented_ostream &os) const;
522
523private:
524 /// The fully resolved C++ name of the parent class.
525 std::string name;
526 /// The visibility of the parent class.
527 Visibility visibility;
528 /// An optional list of class template parameters.
529 SetVector<std::string, SmallVector<std::string>, StringSet<>> templateParams;
530};
531
532/// This class describes a using-declaration for a class. E.g.
533///
534/// using Op::Op;
535/// using Adaptor = OpAdaptor;
536///
537class UsingDeclaration
538 : public ClassDeclarationBase<ClassDeclaration::UsingDeclaration> {
539public:
540 /// Create a using declaration that either aliases `name` to `value` or
541 /// inherits the parent methods `name.
542 template <typename NameT, typename ValueT = std::string>
543 UsingDeclaration(NameT &&name, ValueT &&value = "")
544 : name(stringify(std::forward<NameT>(name))),
545 value(stringify(std::forward<ValueT>(value))) {}
546
547 /// Write the using declaration.
548 void writeDeclTo(raw_indented_ostream &os) const override;
549
550 /// Add a template parameter.
551 template <typename ParamT>
552 void addTemplateParam(ParamT param) {
553 templateParams.insert(stringify(param));
554 }
555
556 /// Add a list of template parameters.
557 template <typename ContainerT>
558 void addTemplateParams(ContainerT &&container) {
559 templateParams.insert(std::begin(container), std::end(container));
560 }
561
562private:
563 /// The name of the declaration, or a resolved name to an inherited function.
564 std::string name;
565 /// The type that is being aliased. Leave empty for inheriting functions.
566 std::string value;
567 /// An optional list of class template parameters.
568 /// This is simply a ordered list of parameter names that are then added as
569 /// template type parameters when the using declaration is emitted.
570 SetVector<std::string, SmallVector<std::string>, StringSet<>> templateParams;
571};
572
573/// This class describes a class field.
574class Field : public ClassDeclarationBase<ClassDeclaration::Field> {
575public:
576 /// Create a class field with a type and variable name.
577 template <typename TypeT, typename NameT>
578 Field(TypeT &&type, NameT &&name)
579 : type(stringify(std::forward<TypeT>(type))),
580 name(stringify(std::forward<NameT>(name))) {}
581
582 /// Write the declaration of the field.
583 void writeDeclTo(raw_indented_ostream &os) const override;
584
585private:
586 /// The C++ type of the field.
587 std::string type;
588 /// The variable name of the class whether.
589 std::string name;
590};
591
592/// A declaration for the visibility of subsequent declarations.
593class VisibilityDeclaration
594 : public ClassDeclarationBase<ClassDeclaration::VisibilityDeclaration> {
595public:
596 /// Create a declaration for the given visibility.
597 VisibilityDeclaration(Visibility visibility) : visibility(visibility) {}
598
599 /// Get the visibility.
600 Visibility getVisibility() const { return visibility; }
601
602 /// Write the visibility declaration.
603 void writeDeclTo(raw_indented_ostream &os) const override;
604
605private:
606 /// The visibility of subsequent class declarations.
607 Visibility visibility;
608};
609
610/// Unstructured extra class declarations and definitions, from TableGen
611/// definitions. The default visibility of extra class declarations is up to the
612/// owning class.
613class ExtraClassDeclaration
614 : public ClassDeclarationBase<ClassDeclaration::ExtraClassDeclaration> {
615public:
616 /// Create an extra class declaration.
617 ExtraClassDeclaration(StringRef extraClassDeclaration,
618 std::string extraClassDefinition = "")
619 : ExtraClassDeclaration(extraClassDeclaration.str(),
620 std::move(extraClassDefinition)) {}
621
622 ExtraClassDeclaration(std::string extraClassDeclaration,
623 std::string extraClassDefinition = "")
624 : extraClassDeclaration(extraClassDeclaration),
625 extraClassDefinition(extraClassDefinition) {}
626
627 /// Write the extra class declarations.
628 void writeDeclTo(raw_indented_ostream &os) const override;
629
630 /// Write the extra class definitions.
631 void writeDefTo(raw_indented_ostream &os,
632 StringRef namePrefix) const override;
633
634private:
635 /// The string of the extra class declarations. It is re-indented before
636 /// printed.
637 std::string extraClassDeclaration;
638 /// The string of the extra class definitions. It is re-indented before
639 /// printed.
640 std::string extraClassDefinition;
641};
642
643/// A class used to emit C++ classes from Tablegen. Contains a list of public
644/// methods and a list of private fields to be emitted.
645class Class {
646public:
647 virtual ~Class() = default;
648
649 /// Explicitly delete the copy constructor. This is to work around a gcc-5 bug
650 /// with std::is_trivially_move_constructible.
651 Class(const Class &) = delete;
652
653 /// Create a class with a name, and whether it should be declared as a `class`
654 /// or `struct`. Also, prevent this from being mistaken as a move constructor
655 /// candidate.
656 template <typename NameT,
657 typename = std::enable_if_t<!std::is_same<NameT, Class>::value>>
658 Class(NameT &&name, bool isStruct = false)
659 : className(stringify(std::forward<NameT>(name))), isStruct(isStruct) {}
660
661 /// Add a new constructor to this class and prune and constructors made
662 /// redundant by it. Returns null if the constructor was not added. Else,
663 /// returns a pointer to the new constructor.
664 template <Method::Properties Properties = Method::None, typename... Args>
665 Constructor *addConstructor(Args &&...args) {
666 Method::Properties defaultProperties = Method::Constructor;
667 // If the class has template parameters, the constructor has to be defined
668 // inline.
669 if (!templateParams.empty())
670 defaultProperties |= Method::Inline;
671 return addConstructorAndPrune(newCtor: Constructor(getClassName(),
672 Properties | defaultProperties,
673 std::forward<Args>(args)...));
674 }
675
676 /// Add a new method to this class and prune any methods made redundant by it.
677 /// Returns null if the method was not added (because an existing method would
678 /// make it redundant). Else, returns a pointer to the new method.
679 template <Method::Properties Properties = Method::None, typename RetTypeT,
680 typename NameT>
681 Method *addMethod(RetTypeT &&retType, NameT &&name,
682 Method::Properties properties,
683 ArrayRef<MethodParameter> parameters) {
684 // If the class has template parameters, then it has to be defined inline.
685 if (!templateParams.empty())
686 properties |= Method::Inline;
687 return addMethodAndPrune(newMethod: Method(std::forward<RetTypeT>(retType),
688 std::forward<NameT>(name),
689 Properties | properties, parameters));
690 }
691
692 /// Add a method with statically-known properties.
693 template <Method::Properties Properties = Method::None, typename RetTypeT,
694 typename NameT>
695 Method *addMethod(RetTypeT &&retType, NameT &&name,
696 ArrayRef<MethodParameter> parameters) {
697 return addMethod(std::forward<RetTypeT>(retType), std::forward<NameT>(name),
698 Properties, parameters);
699 }
700
701 template <Method::Properties Properties = Method::None, typename RetTypeT,
702 typename NameT, typename... Args>
703 Method *addMethod(RetTypeT &&retType, NameT &&name,
704 Method::Properties properties, Args &&...args) {
705 return addMethod(std::forward<RetTypeT>(retType), std::forward<NameT>(name),
706 properties | Properties, {std::forward<Args>(args)...});
707 }
708
709 /// Add a method with statically-known properties.
710 template <Method::Properties Properties = Method::None, typename RetTypeT,
711 typename NameT, typename... Args>
712 Method *addMethod(RetTypeT &&retType, NameT &&name, Args &&...args) {
713 return addMethod(std::forward<RetTypeT>(retType), std::forward<NameT>(name),
714 Properties, std::forward<Args>(args)...);
715 }
716
717 /// Add a static method.
718 template <Method::Properties Properties = Method::None, typename RetTypeT,
719 typename NameT, typename... Args>
720 Method *addStaticMethod(RetTypeT &&retType, NameT &&name, Args &&...args) {
721 return addMethod<Properties | Method::Static>(
722 std::forward<RetTypeT>(retType), std::forward<NameT>(name),
723 std::forward<Args>(args)...);
724 }
725
726 /// Add an inline static method.
727 template <Method::Properties Properties = Method::None, typename RetTypeT,
728 typename NameT, typename... Args>
729 Method *addStaticInlineMethod(RetTypeT &&retType, NameT &&name,
730 Args &&...args) {
731 return addMethod<Properties | Method::StaticInline>(
732 std::forward<RetTypeT>(retType), std::forward<NameT>(name),
733 std::forward<Args>(args)...);
734 }
735
736 /// Add an inline method.
737 template <Method::Properties Properties = Method::None, typename RetTypeT,
738 typename NameT, typename... Args>
739 Method *addInlineMethod(RetTypeT &&retType, NameT &&name, Args &&...args) {
740 return addMethod<Properties | Method::Inline>(
741 std::forward<RetTypeT>(retType), std::forward<NameT>(name),
742 std::forward<Args>(args)...);
743 }
744
745 /// Add a const method.
746 template <Method::Properties Properties = Method::None, typename RetTypeT,
747 typename NameT, typename... Args>
748 Method *addConstMethod(RetTypeT &&retType, NameT &&name, Args &&...args) {
749 return addMethod<Properties | Method::Const>(
750 std::forward<RetTypeT>(retType), std::forward<NameT>(name),
751 std::forward<Args>(args)...);
752 }
753
754 /// Add a declaration for a method.
755 template <Method::Properties Properties = Method::None, typename RetTypeT,
756 typename NameT, typename... Args>
757 Method *declareMethod(RetTypeT &&retType, NameT &&name, Args &&...args) {
758 return addMethod<Properties | Method::Declaration>(
759 std::forward<RetTypeT>(retType), std::forward<NameT>(name),
760 std::forward<Args>(args)...);
761 }
762
763 /// Add a declaration for a static method.
764 template <Method::Properties Properties = Method::None, typename RetTypeT,
765 typename NameT, typename... Args>
766 Method *declareStaticMethod(RetTypeT &&retType, NameT &&name,
767 Args &&...args) {
768 return addMethod<Properties | Method::StaticDeclaration>(
769 std::forward<RetTypeT>(retType), std::forward<NameT>(name),
770 std::forward<Args>(args)...);
771 }
772
773 /// Add a new field to the class. Class fields added this way are always
774 /// private.
775 template <typename TypeT, typename NameT>
776 void addField(TypeT &&type, NameT &&name) {
777 fields.emplace_back(std::forward<TypeT>(type), std::forward<NameT>(name));
778 }
779
780 /// Add a parent class.
781 ParentClass &addParent(ParentClass parent);
782
783 /// Add a template parameter.
784 template <typename ParamT>
785 void addTemplateParam(ParamT param) {
786 templateParams.insert(stringify(param));
787 }
788
789 /// Add a list of template parameters.
790 template <typename ContainerT>
791 void addTemplateParams(ContainerT &&container) {
792 templateParams.insert(std::begin(container), std::end(container));
793 }
794
795 /// Return the C++ name of the class.
796 StringRef getClassName() const { return className; }
797
798 /// Write the declaration of this class, all declarations, and definitions of
799 /// inline functions. Wrap the output stream in an indented stream.
800 void writeDeclTo(raw_ostream &rawOs) const {
801 raw_indented_ostream os(rawOs);
802 writeDeclTo(os);
803 }
804 /// Write the definitions of thiss class's out-of-line constructors and
805 /// methods. Wrap the output stream in an indented stream.
806 void writeDefTo(raw_ostream &rawOs) const {
807 raw_indented_ostream os(rawOs);
808 writeDefTo(os);
809 }
810
811 /// Write the declaration of this class, all declarations, and definitions of
812 /// inline functions.
813 void writeDeclTo(raw_indented_ostream &os) const;
814 /// Write the definitions of thiss class's out-of-line constructors and
815 /// methods.
816 void writeDefTo(raw_indented_ostream &os) const;
817
818 /// Add a declaration. The declaration is appended directly to the list of
819 /// class declarations.
820 template <typename DeclT, typename... Args>
821 DeclT *declare(Args &&...args) {
822 auto decl = std::make_unique<DeclT>(std::forward<Args>(args)...);
823 auto *ret = decl.get();
824 declarations.push_back(std::move(decl));
825 return ret;
826 }
827
828 /// The declaration of a class needs to be "finalized".
829 ///
830 /// Class constructors, methods, and fields can be added in any order,
831 /// regardless of whether they are public or private. These are stored in
832 /// lists separate from list of declarations `declarations`.
833 ///
834 /// So that the generated C++ code is somewhat organised, public methods are
835 /// declared together, and so are private methods and class fields. This
836 /// function iterates through all the added methods and fields and organises
837 /// them into the list of declarations, adding visibility declarations as
838 /// needed, as follows:
839 ///
840 /// 1. public methods and constructors
841 /// 2. private methods and constructors
842 /// 3. class fields -- all are private
843 ///
844 /// `Class::finalize` clears the lists of pending methods and fields, and can
845 /// be called multiple times.
846 virtual void finalize();
847
848protected:
849 /// Add a new constructor if it is not made redundant by any existing
850 /// constructors and prune and existing constructors made redundant.
851 Constructor *addConstructorAndPrune(Constructor &&newCtor);
852 /// Add a new method if it is not made redundant by any existing methods and
853 /// prune and existing methods made redundant.
854 Method *addMethodAndPrune(Method &&newMethod);
855
856 /// Get the last visibility declaration.
857 Visibility getLastVisibilityDecl() const;
858
859 /// The C++ class name.
860 std::string className;
861 /// The list of parent classes.
862 SmallVector<ParentClass> parents;
863 /// The pending list of methods and constructors.
864 std::vector<std::unique_ptr<Method>> methods;
865 /// The pending list of private class fields.
866 SmallVector<Field> fields;
867 /// Whether this is a `class` or a `struct`.
868 bool isStruct;
869
870 /// A list of declarations in the class, emitted in order.
871 std::vector<std::unique_ptr<ClassDeclaration>> declarations;
872
873 /// An optional list of class template parameters.
874 SetVector<std::string, SmallVector<std::string>, StringSet<>> templateParams;
875};
876
877} // namespace tblgen
878} // namespace mlir
879
880#endif // MLIR_TABLEGEN_CLASS_H_
881

source code of mlir/include/mlir/TableGen/Class.h