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 38 namespace mlir { 39 namespace tblgen { 40 class FmtObjectBase; 41 42 /// This class contains a single method parameter for a C++ function. 43 class MethodParameter { 44 public: 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) type(stringify (std::forward<TypeT> (type)))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. getType()69 StringRef getType() const { return type; } 70 /// Returns true if the parameter has a default value. hasDefaultValue()71 bool hasDefaultValue() const { return !defaultValue.empty(); } 72 73 private: 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. 87 class MethodParameters { 88 public: 89 /// Create a list of method parameters. MethodParameters(std::initializer_list<MethodParameter> parameters)90 MethodParameters(std::initializer_list<MethodParameter> parameters) 91 : parameters(parameters) {} MethodParameters(SmallVector<MethodParameter> 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. getNumParameters()106 unsigned getNumParameters() const { return parameters.size(); } 107 108 private: 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. 115 class MethodSignature { 116 public: 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> MethodSignature(RetTypeT && retType,NameT && name,SmallVector<MethodParameter> && parameters)120 MethodSignature(RetTypeT &&retType, NameT &&name, 121 SmallVector<MethodParameter> &¶meters) 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> MethodSignature(RetTypeT && retType,NameT && name,ArrayRef<MethodParameter> parameters)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> MethodSignature(RetTypeT && retType,NameT && name,Parameters &&...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. getName()153 StringRef getName() const { return methodName; } 154 155 /// Get the number of parameters. getNumParameters()156 unsigned getNumParameters() const { return parameters.getNumParameters(); } 157 158 /// Write the signature as part of a method declaration. 159 void writeDeclTo(raw_indented_ostream &os) const; 160 161 /// Write the signature as part of a method definition. `namePrefix` is to be 162 /// prepended to the method name (typically namespaces for qualifying the 163 /// method definition). 164 void writeDefTo(raw_indented_ostream &os, StringRef namePrefix) const; 165 166 private: 167 /// The method's C++ return type. 168 std::string returnType; 169 /// The method name. 170 std::string methodName; 171 /// The method's parameter list. 172 MethodParameters parameters; 173 }; 174 175 /// This class contains the body of a C++ method. 176 class MethodBody { 177 public: 178 /// Create a method body, indicating whether it should be elided for methods 179 /// that are declaration-only. 180 MethodBody(bool declOnly); 181 182 /// Define a move constructor to correctly initialize the streams. MethodBody(MethodBody && other)183 MethodBody(MethodBody &&other) 184 : declOnly(other.declOnly), body(std::move(other.body)), stringOs(body), 185 os(stringOs) {} 186 /// Define a move assignment operator. `raw_ostream` has deleted assignment 187 /// operators, so reinitialize the whole object. 188 MethodBody &operator=(MethodBody &&body) { 189 this->~MethodBody(); 190 new (this) MethodBody(std::move(body)); 191 return *this; 192 } 193 194 /// Write a value to the method body. 195 template <typename ValueT> 196 MethodBody &operator<<(ValueT &&value) { 197 if (!declOnly) { 198 os << std::forward<ValueT>(value); 199 os.flush(); 200 } 201 return *this; 202 } 203 204 /// Write the method body to the output stream. The body can be written as 205 /// part of the declaration of an inline method or just in the definition. 206 void writeTo(raw_indented_ostream &os) const; 207 208 /// Indent the output stream. indent()209 MethodBody &indent() { 210 os.indent(); 211 return *this; 212 } 213 /// Unindent the output stream. unindent()214 MethodBody &unindent() { 215 os.unindent(); 216 return *this; 217 } 218 /// Create a delimited scope: immediately print `open`, indent if `indent` is 219 /// true, and print `close` on object destruction. 220 raw_indented_ostream::DelimitedScope 221 scope(StringRef open = "", StringRef close = "", bool indent = false) { 222 return os.scope(open, close, indent); 223 } 224 225 /// Get the underlying indented output stream. getStream()226 raw_indented_ostream &getStream() { return os; } 227 228 private: 229 /// Whether the body should be elided. 230 bool declOnly; 231 /// The body data. 232 std::string body; 233 /// The string output stream. 234 llvm::raw_string_ostream stringOs; 235 /// An indented output stream for formatting input. 236 raw_indented_ostream os; 237 }; 238 239 /// A class declaration is a class element that appears as part of its 240 /// declaration. 241 class ClassDeclaration { 242 public: 243 virtual ~ClassDeclaration() = default; 244 245 /// Kinds for LLVM-style RTTI. 246 enum Kind { 247 Method, 248 UsingDeclaration, 249 VisibilityDeclaration, 250 Field, 251 ExtraClassDeclaration 252 }; 253 /// Create a class declaration with a given kind. ClassDeclaration(Kind kind)254 ClassDeclaration(Kind kind) : kind(kind) {} 255 256 /// Get the class declaration kind. getKind()257 Kind getKind() const { return kind; } 258 259 /// Write the declaration. 260 virtual void writeDeclTo(raw_indented_ostream &os) const = 0; 261 262 /// Write the definition, if any. `namePrefix` is the namespace prefix, which 263 /// may contains a class name. writeDefTo(raw_indented_ostream & os,StringRef namePrefix)264 virtual void writeDefTo(raw_indented_ostream &os, 265 StringRef namePrefix) const {} 266 267 private: 268 /// The class declaration kind. 269 Kind kind; 270 }; 271 272 /// Base class for class declarations. 273 template <ClassDeclaration::Kind DeclKind> 274 class ClassDeclarationBase : public ClassDeclaration { 275 public: 276 using Base = ClassDeclarationBase<DeclKind>; ClassDeclarationBase()277 ClassDeclarationBase() : ClassDeclaration(DeclKind) {} 278 classof(const ClassDeclaration * other)279 static bool classof(const ClassDeclaration *other) { 280 return other->getKind() == DeclKind; 281 } 282 }; 283 284 /// Class for holding an op's method for C++ code emission 285 class Method : public ClassDeclarationBase<ClassDeclaration::Method> { 286 public: 287 /// Properties (qualifiers) of class methods. Bitfield is used here to help 288 /// querying properties. 289 enum Properties { 290 None = 0x0, 291 Static = 0x1, 292 Constructor = 0x2, 293 Private = 0x4, 294 Declaration = 0x8, 295 Inline = 0x10, 296 ConstexprValue = 0x20, 297 Const = 0x40, 298 299 Constexpr = ConstexprValue | Inline, 300 StaticDeclaration = Static | Declaration, 301 StaticInline = Static | Inline, 302 ConstInline = Const | Inline, 303 ConstDeclaration = Const | Declaration 304 }; 305 306 /// Create a method with a return type, a name, method properties, and a some 307 /// parameters. The parameteres may be passed as a list or as a variadic pack. 308 template <typename RetTypeT, typename NameT, typename... Args> Method(RetTypeT && retType,NameT && name,Properties properties,Args &&...args)309 Method(RetTypeT &&retType, NameT &&name, Properties properties, 310 Args &&...args) 311 : properties(properties), 312 methodSignature(std::forward<RetTypeT>(retType), 313 std::forward<NameT>(name), std::forward<Args>(args)...), 314 methodBody(properties & Declaration) {} 315 /// Create a method with a return type, a name, method properties, and a list 316 /// of parameters. Method(StringRef retType,StringRef name,Properties properties,std::initializer_list<MethodParameter> params)317 Method(StringRef retType, StringRef name, Properties properties, 318 std::initializer_list<MethodParameter> params) 319 : properties(properties), methodSignature(retType, name, params), 320 methodBody(properties & Declaration) {} 321 322 // Define move constructor and assignment operator to prevent copying. 323 Method(Method &&) = default; 324 Method &operator=(Method &&) = default; 325 326 /// Get the method body. body()327 MethodBody &body() { return methodBody; } 328 329 /// Returns true if this is a static method. isStatic()330 bool isStatic() const { return properties & Static; } 331 332 /// Returns true if this is a private method. isPrivate()333 bool isPrivate() const { return properties & Private; } 334 335 /// Returns true if this is an inline method. isInline()336 bool isInline() const { return properties & Inline; } 337 338 /// Returns true if this is a constructor. isConstructor()339 bool isConstructor() const { return properties & Constructor; } 340 341 /// Returns true if this class method is const. isConst()342 bool isConst() const { return properties & Const; } 343 344 /// Returns the name of this method. getName()345 StringRef getName() const { return methodSignature.getName(); } 346 347 /// Returns if this method makes the `other` method redundant. makesRedundant(const Method & other)348 bool makesRedundant(const Method &other) const { 349 return methodSignature.makesRedundant(other.methodSignature); 350 } 351 352 /// Write the method declaration, including the definition if inline. 353 void writeDeclTo(raw_indented_ostream &os) const override; 354 355 /// Write the method definition. This is a no-op for inline methods. 356 void writeDefTo(raw_indented_ostream &os, 357 StringRef namePrefix) const override; 358 359 protected: 360 /// A collection of method properties. 361 Properties properties; 362 /// The signature of the method. 363 MethodSignature methodSignature; 364 /// The body of the method, if it has one. 365 MethodBody methodBody; 366 }; 367 368 /// This enum describes C++ inheritance visibility. 369 enum class Visibility { Public, Protected, Private }; 370 371 /// Write "public", "protected", or "private". 372 llvm::raw_ostream &operator<<(llvm::raw_ostream &os, 373 mlir::tblgen::Visibility visibility); 374 375 // Class for holding an op's constructor method for C++ code emission. 376 class Constructor : public Method { 377 public: 378 /// Create a constructor for a given class, with method properties, and 379 /// parameters specified either as a list of a variadic pack. 380 template <typename NameT, typename... Args> Constructor(NameT && className,Properties properties,Args &&...args)381 Constructor(NameT &&className, Properties properties, Args &&...args) 382 : Method("", std::forward<NameT>(className), properties, 383 std::forward<Args>(args)...) {} 384 385 /// Add member initializer to constructor initializing `name` with `value`. 386 template <typename NameT, typename ValueT> addMemberInitializer(NameT && name,ValueT && value)387 void addMemberInitializer(NameT &&name, ValueT &&value) { 388 initializers.emplace_back(stringify(std::forward<NameT>(name)), 389 stringify(std::forward<ValueT>(value))); 390 } 391 392 /// Write the declaration of the constructor, and its definition if inline. 393 void writeDeclTo(raw_indented_ostream &os) const override; 394 395 /// Write the definition of the constructor if it is not inline. 396 void writeDefTo(raw_indented_ostream &os, 397 StringRef namePrefix) const override; 398 399 /// Return true if a method is a constructor. classof(const ClassDeclaration * other)400 static bool classof(const ClassDeclaration *other) { 401 return isa<Method>(other) && cast<Method>(other)->isConstructor(); 402 } 403 404 /// Initialization of a class field in a constructor. 405 class MemberInitializer { 406 public: 407 /// Create a member initializer in a constructor that initializes the class 408 /// field `name` with `value`. MemberInitializer(std::string name,std::string value)409 MemberInitializer(std::string name, std::string value) 410 : name(std::move(name)), value(std::move(value)) {} 411 412 /// Write the member initializer. 413 void writeTo(raw_indented_ostream &os) const; 414 415 private: 416 /// The name of the class field. 417 std::string name; 418 /// The value with which to initialize it. 419 std::string value; 420 }; 421 422 private: 423 /// The list of member initializers. 424 SmallVector<MemberInitializer> initializers; 425 }; 426 427 } // namespace tblgen 428 } // namespace mlir 429 430 /// The OR of two method properties should return method properties. Ensure that 431 /// this function is visible to `Class`. 432 inline constexpr mlir::tblgen::Method::Properties 433 operator|(mlir::tblgen::Method::Properties lhs, 434 mlir::tblgen::Method::Properties rhs) { 435 return mlir::tblgen::Method::Properties(static_cast<unsigned>(lhs) | 436 static_cast<unsigned>(rhs)); 437 } 438 439 namespace mlir { 440 namespace tblgen { 441 442 /// This class describes a C++ parent class declaration. 443 class ParentClass { 444 public: 445 /// Create a parent class with a class name and visibility. 446 template <typename NameT> 447 ParentClass(NameT &&name, Visibility visibility = Visibility::Public) name(stringify (std::forward<NameT> (name)))448 : name(stringify(std::forward<NameT>(name))), visibility(visibility) {} 449 450 /// Add a template parameter. 451 template <typename ParamT> addTemplateParam(ParamT param)452 void addTemplateParam(ParamT param) { 453 templateParams.insert(stringify(param)); 454 } 455 /// Add a list of template parameters. 456 template <typename ContainerT> addTemplateParams(ContainerT && container)457 void addTemplateParams(ContainerT &&container) { 458 templateParams.insert(std::begin(container), std::end(container)); 459 } 460 461 /// Write the parent class declaration. 462 void writeTo(raw_indented_ostream &os) const; 463 464 private: 465 /// The fully resolved C++ name of the parent class. 466 std::string name; 467 /// The visibility of the parent class. 468 Visibility visibility; 469 /// An optional list of class template parameters. 470 SetVector<std::string, SmallVector<std::string>, StringSet<>> templateParams; 471 }; 472 473 /// This class describes a using-declaration for a class. E.g. 474 /// 475 /// using Op::Op; 476 /// using Adaptor = OpAdaptor; 477 /// 478 class UsingDeclaration 479 : public ClassDeclarationBase<ClassDeclaration::UsingDeclaration> { 480 public: 481 /// Create a using declaration that either aliases `name` to `value` or 482 /// inherits the parent methods `name. 483 template <typename NameT, typename ValueT = std::string> 484 UsingDeclaration(NameT &&name, ValueT &&value = "") name(stringify (std::forward<NameT> (name)))485 : name(stringify(std::forward<NameT>(name))), 486 value(stringify(std::forward<ValueT>(value))) {} 487 488 /// Write the using declaration. 489 void writeDeclTo(raw_indented_ostream &os) const override; 490 491 private: 492 /// The name of the declaration, or a resolved name to an inherited function. 493 std::string name; 494 /// The type that is being aliased. Leave empty for inheriting functions. 495 std::string value; 496 }; 497 498 /// This class describes a class field. 499 class Field : public ClassDeclarationBase<ClassDeclaration::Field> { 500 public: 501 /// Create a class field with a type and variable name. 502 template <typename TypeT, typename NameT> Field(TypeT && type,NameT && name)503 Field(TypeT &&type, NameT &&name) 504 : type(stringify(std::forward<TypeT>(type))), 505 name(stringify(std::forward<NameT>(name))) {} 506 507 /// Write the declaration of the field. 508 void writeDeclTo(raw_indented_ostream &os) const override; 509 510 private: 511 /// The C++ type of the field. 512 std::string type; 513 /// The variable name of the class whether. 514 std::string name; 515 }; 516 517 /// A declaration for the visibility of subsequent declarations. 518 class VisibilityDeclaration 519 : public ClassDeclarationBase<ClassDeclaration::VisibilityDeclaration> { 520 public: 521 /// Create a declaration for the given visibility. VisibilityDeclaration(Visibility visibility)522 VisibilityDeclaration(Visibility visibility) : visibility(visibility) {} 523 524 /// Get the visibility. getVisibility()525 Visibility getVisibility() const { return visibility; } 526 527 /// Write the visibility declaration. 528 void writeDeclTo(raw_indented_ostream &os) const override; 529 530 private: 531 /// The visibility of subsequent class declarations. 532 Visibility visibility; 533 }; 534 535 /// Unstructured extra class declarations and definitions, from TableGen 536 /// definitions. The default visibility of extra class declarations is up to the 537 /// owning class. 538 class ExtraClassDeclaration 539 : public ClassDeclarationBase<ClassDeclaration::ExtraClassDeclaration> { 540 public: 541 /// Create an extra class declaration. 542 ExtraClassDeclaration(StringRef extraClassDeclaration, 543 StringRef extraClassDefinition = "") extraClassDeclaration(extraClassDeclaration)544 : extraClassDeclaration(extraClassDeclaration), 545 extraClassDefinition(extraClassDefinition) {} 546 547 /// Write the extra class declarations. 548 void writeDeclTo(raw_indented_ostream &os) const override; 549 550 /// Write the extra class definitions. 551 void writeDefTo(raw_indented_ostream &os, 552 StringRef namePrefix) const override; 553 554 private: 555 /// The string of the extra class declarations. It is re-indented before 556 /// printed. 557 StringRef extraClassDeclaration; 558 /// The string of the extra class definitions. It is re-indented before 559 /// printed. 560 std::string extraClassDefinition; 561 }; 562 563 /// A class used to emit C++ classes from Tablegen. Contains a list of public 564 /// methods and a list of private fields to be emitted. 565 class Class { 566 public: 567 virtual ~Class() = default; 568 569 /// Explicitly delete the copy constructor. This is to work around a gcc-5 bug 570 /// with std::is_trivially_move_constructible. 571 Class(const Class &) = delete; 572 573 /// Create a class with a name, and whether it should be declared as a `class` 574 /// or `struct`. Also, prevent this from being mistaken as a move constructor 575 /// candidate. 576 template <typename NameT, typename = typename std::enable_if_t< 577 !std::is_same<NameT, Class>::value>> 578 Class(NameT &&name, bool isStruct = false) className(stringify (std::forward<NameT> (name)))579 : className(stringify(std::forward<NameT>(name))), isStruct(isStruct) {} 580 581 /// Add a new constructor to this class and prune and constructors made 582 /// redundant by it. Returns null if the constructor was not added. Else, 583 /// returns a pointer to the new constructor. 584 template <Method::Properties Properties = Method::None, typename... Args> addConstructor(Args &&...args)585 Constructor *addConstructor(Args &&...args) { 586 return addConstructorAndPrune(Constructor(getClassName(), 587 Properties | Method::Constructor, 588 std::forward<Args>(args)...)); 589 } 590 591 /// Add a new method to this class and prune any methods made redundant by it. 592 /// Returns null if the method was not added (because an existing method would 593 /// make it redundant). Else, returns a pointer to the new method. 594 template <Method::Properties Properties = Method::None, typename RetTypeT, 595 typename NameT, typename... Args> addMethod(RetTypeT && retType,NameT && name,Method::Properties properties,Args &&...args)596 Method *addMethod(RetTypeT &&retType, NameT &&name, 597 Method::Properties properties, Args &&...args) { 598 return addMethodAndPrune( 599 Method(std::forward<RetTypeT>(retType), std::forward<NameT>(name), 600 Properties | properties, std::forward<Args>(args)...)); 601 } 602 603 /// Add a method with statically-known properties. 604 template <Method::Properties Properties = Method::None, typename RetTypeT, 605 typename NameT, typename... Args> addMethod(RetTypeT && retType,NameT && name,Args &&...args)606 Method *addMethod(RetTypeT &&retType, NameT &&name, Args &&...args) { 607 return addMethod(std::forward<RetTypeT>(retType), std::forward<NameT>(name), 608 Properties, std::forward<Args>(args)...); 609 } 610 611 /// Add a static method. 612 template <Method::Properties Properties = Method::None, typename RetTypeT, 613 typename NameT, typename... Args> addStaticMethod(RetTypeT && retType,NameT && name,Args &&...args)614 Method *addStaticMethod(RetTypeT &&retType, NameT &&name, Args &&...args) { 615 return addMethod<Properties | Method::Static>( 616 std::forward<RetTypeT>(retType), std::forward<NameT>(name), 617 std::forward<Args>(args)...); 618 } 619 620 /// Add an inline static method. 621 template <Method::Properties Properties = Method::None, typename RetTypeT, 622 typename NameT, typename... Args> addStaticInlineMethod(RetTypeT && retType,NameT && name,Args &&...args)623 Method *addStaticInlineMethod(RetTypeT &&retType, NameT &&name, 624 Args &&...args) { 625 return addMethod<Properties | Method::StaticInline>( 626 std::forward<RetTypeT>(retType), std::forward<NameT>(name), 627 std::forward<Args>(args)...); 628 } 629 630 /// Add an inline method. 631 template <Method::Properties Properties = Method::None, typename RetTypeT, 632 typename NameT, typename... Args> addInlineMethod(RetTypeT && retType,NameT && name,Args &&...args)633 Method *addInlineMethod(RetTypeT &&retType, NameT &&name, Args &&...args) { 634 return addMethod<Properties | Method::Inline>( 635 std::forward<RetTypeT>(retType), std::forward<NameT>(name), 636 std::forward<Args>(args)...); 637 } 638 639 /// Add a const method. 640 template <Method::Properties Properties = Method::None, typename RetTypeT, 641 typename NameT, typename... Args> addConstMethod(RetTypeT && retType,NameT && name,Args &&...args)642 Method *addConstMethod(RetTypeT &&retType, NameT &&name, Args &&...args) { 643 return addMethod<Properties | Method::Const>( 644 std::forward<RetTypeT>(retType), std::forward<NameT>(name), 645 std::forward<Args>(args)...); 646 } 647 648 /// Add a declaration for a method. 649 template <Method::Properties Properties = Method::None, typename RetTypeT, 650 typename NameT, typename... Args> declareMethod(RetTypeT && retType,NameT && name,Args &&...args)651 Method *declareMethod(RetTypeT &&retType, NameT &&name, Args &&...args) { 652 return addMethod<Properties | Method::Declaration>( 653 std::forward<RetTypeT>(retType), std::forward<NameT>(name), 654 std::forward<Args>(args)...); 655 } 656 657 /// Add a declaration for a static method. 658 template <Method::Properties Properties = Method::None, typename RetTypeT, 659 typename NameT, typename... Args> declareStaticMethod(RetTypeT && retType,NameT && name,Args &&...args)660 Method *declareStaticMethod(RetTypeT &&retType, NameT &&name, 661 Args &&...args) { 662 return addMethod<Properties | Method::StaticDeclaration>( 663 std::forward<RetTypeT>(retType), std::forward<NameT>(name), 664 std::forward<Args>(args)...); 665 } 666 667 /// Add a new field to the class. Class fields added this way are always 668 /// private. 669 template <typename TypeT, typename NameT> addField(TypeT && type,NameT && name)670 void addField(TypeT &&type, NameT &&name) { 671 fields.emplace_back(std::forward<TypeT>(type), std::forward<NameT>(name)); 672 } 673 674 /// Add a parent class. 675 ParentClass &addParent(ParentClass parent); 676 677 /// Return the C++ name of the class. getClassName()678 StringRef getClassName() const { return className; } 679 680 /// Write the declaration of this class, all declarations, and definitions of 681 /// inline functions. Wrap the output stream in an indented stream. writeDeclTo(raw_ostream & rawOs)682 void writeDeclTo(raw_ostream &rawOs) const { 683 raw_indented_ostream os(rawOs); 684 writeDeclTo(os); 685 } 686 /// Write the definitions of thiss class's out-of-line constructors and 687 /// methods. Wrap the output stream in an indented stream. writeDefTo(raw_ostream & rawOs)688 void writeDefTo(raw_ostream &rawOs) const { 689 raw_indented_ostream os(rawOs); 690 writeDefTo(os); 691 } 692 693 /// Write the declaration of this class, all declarations, and definitions of 694 /// inline functions. 695 void writeDeclTo(raw_indented_ostream &os) const; 696 /// Write the definitions of thiss class's out-of-line constructors and 697 /// methods. 698 void writeDefTo(raw_indented_ostream &os) const; 699 700 /// Add a declaration. The declaration is appended directly to the list of 701 /// class declarations. 702 template <typename DeclT, typename... Args> declare(Args &&...args)703 DeclT *declare(Args &&...args) { 704 auto decl = std::make_unique<DeclT>(std::forward<Args>(args)...); 705 auto *ret = decl.get(); 706 declarations.push_back(std::move(decl)); 707 return ret; 708 } 709 710 /// The declaration of a class needs to be "finalized". 711 /// 712 /// Class constructors, methods, and fields can be added in any order, 713 /// regardless of whether they are public or private. These are stored in 714 /// lists separate from list of declarations `declarations`. 715 /// 716 /// So that the generated C++ code is somewhat organised, public methods are 717 /// declared together, and so are private methods and class fields. This 718 /// function iterates through all the added methods and fields and organises 719 /// them into the list of declarations, adding visibility declarations as 720 /// needed, as follows: 721 /// 722 /// 1. public methods and constructors 723 /// 2. private methods and constructors 724 /// 3. class fields -- all are private 725 /// 726 /// `Class::finalize` clears the lists of pending methods and fields, and can 727 /// be called multiple times. 728 virtual void finalize(); 729 730 protected: 731 /// Add a new constructor if it is not made redundant by any existing 732 /// constructors and prune and existing constructors made redundant. 733 Constructor *addConstructorAndPrune(Constructor &&newCtor); 734 /// Add a new method if it is not made redundant by any existing methods and 735 /// prune and existing methods made redundant. 736 Method *addMethodAndPrune(Method &&newMethod); 737 738 /// Get the last visibility declaration. 739 Visibility getLastVisibilityDecl() const; 740 741 /// The C++ class name. 742 std::string className; 743 /// The list of parent classes. 744 SmallVector<ParentClass> parents; 745 /// The pending list of methods and constructors. 746 std::vector<std::unique_ptr<Method>> methods; 747 /// The pending list of private class fields. 748 SmallVector<Field> fields; 749 /// Whether this is a `class` or a `struct`. 750 bool isStruct; 751 752 /// A list of declarations in the class, emitted in order. 753 std::vector<std::unique_ptr<ClassDeclaration>> declarations; 754 }; 755 756 } // namespace tblgen 757 } // namespace mlir 758 759 #endif // MLIR_TABLEGEN_CLASS_H_ 760