1 //=== ASTTableGen.h - Common definitions for AST node tablegen --*- 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 #ifndef CLANG_AST_TABLEGEN_H 10 #define CLANG_AST_TABLEGEN_H 11 12 #include "llvm/TableGen/Record.h" 13 #include "llvm/ADT/STLExtras.h" 14 #include <optional> 15 16 // These are spellings in the tblgen files. 17 18 #define HasPropertiesClassName "HasProperties" 19 20 // ASTNodes and their common fields. `Base` is actually defined 21 // in subclasses, but it's still common across the hierarchies. 22 #define ASTNodeClassName "ASTNode" 23 #define BaseFieldName "Base" 24 #define AbstractFieldName "Abstract" 25 26 // Comment node hierarchy. 27 #define CommentNodeClassName "CommentNode" 28 29 // Decl node hierarchy. 30 #define DeclNodeClassName "DeclNode" 31 #define DeclContextNodeClassName "DeclContext" 32 33 // Stmt node hierarchy. 34 #define StmtNodeClassName "StmtNode" 35 36 // Type node hierarchy. 37 #define TypeNodeClassName "TypeNode" 38 #define AlwaysDependentClassName "AlwaysDependent" 39 #define NeverCanonicalClassName "NeverCanonical" 40 #define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent" 41 #define LeafTypeClassName "LeafType" 42 43 // Cases of various non-ASTNode structured types like DeclarationName. 44 #define TypeKindClassName "PropertyTypeKind" 45 #define KindTypeFieldName "KindType" 46 #define KindPropertyNameFieldName "KindPropertyName" 47 #define TypeCaseClassName "PropertyTypeCase" 48 49 // Properties of AST nodes. 50 #define PropertyClassName "Property" 51 #define ClassFieldName "Class" 52 #define NameFieldName "Name" 53 #define TypeFieldName "Type" 54 #define ReadFieldName "Read" 55 56 // Types of properties. 57 #define PropertyTypeClassName "PropertyType" 58 #define CXXTypeNameFieldName "CXXName" 59 #define PassByReferenceFieldName "PassByReference" 60 #define ConstWhenWritingFieldName "ConstWhenWriting" 61 #define ConditionalCodeFieldName "Conditional" 62 #define PackOptionalCodeFieldName "PackOptional" 63 #define UnpackOptionalCodeFieldName "UnpackOptional" 64 #define BufferElementTypesFieldName "BufferElementTypes" 65 #define ArrayTypeClassName "Array" 66 #define ArrayElementTypeFieldName "Element" 67 #define OptionalTypeClassName "Optional" 68 #define OptionalElementTypeFieldName "Element" 69 #define SubclassPropertyTypeClassName "SubclassPropertyType" 70 #define SubclassBaseTypeFieldName "Base" 71 #define SubclassClassNameFieldName "SubclassName" 72 #define EnumPropertyTypeClassName "EnumPropertyType" 73 74 // Write helper rules. 75 #define ReadHelperRuleClassName "ReadHelper" 76 #define HelperCodeFieldName "Code" 77 78 // Creation rules. 79 #define CreationRuleClassName "Creator" 80 #define CreateFieldName "Create" 81 82 // Override rules. 83 #define OverrideRuleClassName "Override" 84 #define IgnoredPropertiesFieldName "IgnoredProperties" 85 86 namespace clang { 87 namespace tblgen { 88 89 class WrappedRecord { 90 llvm::Record *Record; 91 92 protected: 93 WrappedRecord(llvm::Record *record = nullptr) : Record(record) {} 94 95 llvm::Record *get() const { 96 assert(Record && "accessing null record"); 97 return Record; 98 } 99 100 public: 101 llvm::Record *getRecord() const { return Record; } 102 103 explicit operator bool() const { return Record != nullptr; } 104 105 llvm::ArrayRef<llvm::SMLoc> getLoc() const { 106 return get()->getLoc(); 107 } 108 109 /// Does the node inherit from the given TableGen class? 110 bool isSubClassOf(llvm::StringRef className) const { 111 return get()->isSubClassOf(className); 112 } 113 114 template <class NodeClass> 115 NodeClass getAs() const { 116 return (isSubClassOf(NodeClass::getTableGenNodeClassName()) 117 ? NodeClass(get()) : NodeClass()); 118 } 119 120 friend bool operator<(WrappedRecord lhs, WrappedRecord rhs) { 121 assert(lhs && rhs && "sorting null nodes"); 122 return lhs.get()->getName() < rhs.get()->getName(); 123 } 124 friend bool operator>(WrappedRecord lhs, WrappedRecord rhs) { 125 return rhs < lhs; 126 } 127 friend bool operator<=(WrappedRecord lhs, WrappedRecord rhs) { 128 return !(rhs < lhs); 129 } 130 friend bool operator>=(WrappedRecord lhs, WrappedRecord rhs) { 131 return !(lhs < rhs); 132 } 133 friend bool operator==(WrappedRecord lhs, WrappedRecord rhs) { 134 // This should handle null nodes. 135 return lhs.getRecord() == rhs.getRecord(); 136 } 137 friend bool operator!=(WrappedRecord lhs, WrappedRecord rhs) { 138 return !(lhs == rhs); 139 } 140 }; 141 142 /// Anything in the AST that has properties. 143 class HasProperties : public WrappedRecord { 144 public: 145 static constexpr llvm::StringRef ClassName = HasPropertiesClassName; 146 147 HasProperties(llvm::Record *record = nullptr) : WrappedRecord(record) {} 148 149 llvm::StringRef getName() const; 150 151 static llvm::StringRef getTableGenNodeClassName() { 152 return HasPropertiesClassName; 153 } 154 }; 155 156 /// An (optional) reference to a TableGen node representing a class 157 /// in one of Clang's AST hierarchies. 158 class ASTNode : public HasProperties { 159 public: 160 ASTNode(llvm::Record *record = nullptr) : HasProperties(record) {} 161 162 llvm::StringRef getName() const { 163 return get()->getName(); 164 } 165 166 /// Return the node for the base, if there is one. 167 ASTNode getBase() const { 168 return get()->getValueAsOptionalDef(BaseFieldName); 169 } 170 171 /// Is the corresponding class abstract? 172 bool isAbstract() const { 173 return get()->getValueAsBit(AbstractFieldName); 174 } 175 176 static llvm::StringRef getTableGenNodeClassName() { 177 return ASTNodeClassName; 178 } 179 }; 180 181 class DeclNode : public ASTNode { 182 public: 183 DeclNode(llvm::Record *record = nullptr) : ASTNode(record) {} 184 185 llvm::StringRef getId() const; 186 std::string getClassName() const; 187 DeclNode getBase() const { return DeclNode(ASTNode::getBase().getRecord()); } 188 189 static llvm::StringRef getASTHierarchyName() { 190 return "Decl"; 191 } 192 static llvm::StringRef getASTIdTypeName() { 193 return "Decl::Kind"; 194 } 195 static llvm::StringRef getASTIdAccessorName() { 196 return "getKind"; 197 } 198 static llvm::StringRef getTableGenNodeClassName() { 199 return DeclNodeClassName; 200 } 201 }; 202 203 class TypeNode : public ASTNode { 204 public: 205 TypeNode(llvm::Record *record = nullptr) : ASTNode(record) {} 206 207 llvm::StringRef getId() const; 208 llvm::StringRef getClassName() const; 209 TypeNode getBase() const { return TypeNode(ASTNode::getBase().getRecord()); } 210 211 static llvm::StringRef getASTHierarchyName() { 212 return "Type"; 213 } 214 static llvm::StringRef getASTIdTypeName() { 215 return "Type::TypeClass"; 216 } 217 static llvm::StringRef getASTIdAccessorName() { 218 return "getTypeClass"; 219 } 220 static llvm::StringRef getTableGenNodeClassName() { 221 return TypeNodeClassName; 222 } 223 }; 224 225 class StmtNode : public ASTNode { 226 public: 227 StmtNode(llvm::Record *record = nullptr) : ASTNode(record) {} 228 229 std::string getId() const; 230 llvm::StringRef getClassName() const; 231 StmtNode getBase() const { return StmtNode(ASTNode::getBase().getRecord()); } 232 233 static llvm::StringRef getASTHierarchyName() { 234 return "Stmt"; 235 } 236 static llvm::StringRef getASTIdTypeName() { 237 return "Stmt::StmtClass"; 238 } 239 static llvm::StringRef getASTIdAccessorName() { 240 return "getStmtClass"; 241 } 242 static llvm::StringRef getTableGenNodeClassName() { 243 return StmtNodeClassName; 244 } 245 }; 246 247 /// The type of a property. 248 class PropertyType : public WrappedRecord { 249 public: 250 PropertyType(llvm::Record *record = nullptr) : WrappedRecord(record) {} 251 252 /// Is this a generic specialization (i.e. `Array<T>` or `Optional<T>`)? 253 bool isGenericSpecialization() const { 254 return get()->isAnonymous(); 255 } 256 257 /// The abstract type name of the property. Doesn't work for generic 258 /// specializations. 259 llvm::StringRef getAbstractTypeName() const { 260 return get()->getName(); 261 } 262 263 /// The C++ type name of the property. Doesn't work for generic 264 /// specializations. 265 llvm::StringRef getCXXTypeName() const { 266 return get()->getValueAsString(CXXTypeNameFieldName); 267 } 268 void emitCXXValueTypeName(bool forRead, llvm::raw_ostream &out) const; 269 270 /// Whether the C++ type should be passed around by reference. 271 bool shouldPassByReference() const { 272 return get()->getValueAsBit(PassByReferenceFieldName); 273 } 274 275 /// Whether the C++ type should have 'const' prepended when working with 276 /// a value of the type being written. 277 bool isConstWhenWriting() const { 278 return get()->getValueAsBit(ConstWhenWritingFieldName); 279 } 280 281 /// If this is `Array<T>`, return `T`; otherwise return null. 282 PropertyType getArrayElementType() const { 283 if (isSubClassOf(ArrayTypeClassName)) 284 return get()->getValueAsDef(ArrayElementTypeFieldName); 285 return nullptr; 286 } 287 288 /// If this is `Optional<T>`, return `T`; otherwise return null. 289 PropertyType getOptionalElementType() const { 290 if (isSubClassOf(OptionalTypeClassName)) 291 return get()->getValueAsDef(OptionalElementTypeFieldName); 292 return nullptr; 293 } 294 295 /// If this is a subclass type, return its superclass type. 296 PropertyType getSuperclassType() const { 297 if (isSubClassOf(SubclassPropertyTypeClassName)) 298 return get()->getValueAsDef(SubclassBaseTypeFieldName); 299 return nullptr; 300 } 301 302 // Given that this is a subclass type, return the C++ name of its 303 // subclass type. This is just the bare class name, suitable for 304 // use in `cast<>`. 305 llvm::StringRef getSubclassClassName() const { 306 return get()->getValueAsString(SubclassClassNameFieldName); 307 } 308 309 /// Does this represent an enum type? 310 bool isEnum() const { 311 return isSubClassOf(EnumPropertyTypeClassName); 312 } 313 314 llvm::StringRef getPackOptionalCode() const { 315 return get()->getValueAsString(PackOptionalCodeFieldName); 316 } 317 318 llvm::StringRef getUnpackOptionalCode() const { 319 return get()->getValueAsString(UnpackOptionalCodeFieldName); 320 } 321 322 std::vector<llvm::Record*> getBufferElementTypes() const { 323 return get()->getValueAsListOfDefs(BufferElementTypesFieldName); 324 } 325 326 static llvm::StringRef getTableGenNodeClassName() { 327 return PropertyTypeClassName; 328 } 329 }; 330 331 /// A rule for returning the kind of a type. 332 class TypeKindRule : public WrappedRecord { 333 public: 334 TypeKindRule(llvm::Record *record = nullptr) : WrappedRecord(record) {} 335 336 /// Return the type to which this applies. 337 PropertyType getParentType() const { 338 return get()->getValueAsDef(TypeFieldName); 339 } 340 341 /// Return the type of the kind. 342 PropertyType getKindType() const { 343 return get()->getValueAsDef(KindTypeFieldName); 344 } 345 346 /// Return the name to use for the kind property. 347 llvm::StringRef getKindPropertyName() const { 348 return get()->getValueAsString(KindPropertyNameFieldName); 349 } 350 351 /// Return the code for reading the kind value. 352 llvm::StringRef getReadCode() const { 353 return get()->getValueAsString(ReadFieldName); 354 } 355 356 static llvm::StringRef getTableGenNodeClassName() { 357 return TypeKindClassName; 358 } 359 }; 360 361 /// An implementation case of a property type. 362 class TypeCase : public HasProperties { 363 public: 364 TypeCase(llvm::Record *record = nullptr) : HasProperties(record) {} 365 366 /// Return the name of this case. 367 llvm::StringRef getCaseName() const { 368 return get()->getValueAsString(NameFieldName); 369 } 370 371 /// Return the type of which this is a case. 372 PropertyType getParentType() const { 373 return get()->getValueAsDef(TypeFieldName); 374 } 375 376 static llvm::StringRef getTableGenNodeClassName() { 377 return TypeCaseClassName; 378 } 379 }; 380 381 /// A property of an AST node. 382 class Property : public WrappedRecord { 383 public: 384 Property(llvm::Record *record = nullptr) : WrappedRecord(record) {} 385 386 /// Return the name of this property. 387 llvm::StringRef getName() const { 388 return get()->getValueAsString(NameFieldName); 389 } 390 391 /// Return the type of this property. 392 PropertyType getType() const { 393 return get()->getValueAsDef(TypeFieldName); 394 } 395 396 /// Return the class of which this is a property. 397 HasProperties getClass() const { 398 return get()->getValueAsDef(ClassFieldName); 399 } 400 401 /// Return the code for reading this property. 402 llvm::StringRef getReadCode() const { 403 return get()->getValueAsString(ReadFieldName); 404 } 405 406 /// Return the code for determining whether to add this property. 407 llvm::StringRef getCondition() const { 408 return get()->getValueAsString(ConditionalCodeFieldName); 409 } 410 411 static llvm::StringRef getTableGenNodeClassName() { 412 return PropertyClassName; 413 } 414 }; 415 416 /// A rule for running some helper code for reading properties from 417 /// a value (which is actually done when writing the value out). 418 class ReadHelperRule : public WrappedRecord { 419 public: 420 ReadHelperRule(llvm::Record *record = nullptr) : WrappedRecord(record) {} 421 422 /// Return the class for which this is a creation rule. 423 /// Should never be abstract. 424 HasProperties getClass() const { 425 return get()->getValueAsDef(ClassFieldName); 426 } 427 428 llvm::StringRef getHelperCode() const { 429 return get()->getValueAsString(HelperCodeFieldName); 430 } 431 432 static llvm::StringRef getTableGenNodeClassName() { 433 return ReadHelperRuleClassName; 434 } 435 }; 436 437 /// A rule for how to create an AST node from its properties. 438 class CreationRule : public WrappedRecord { 439 public: 440 CreationRule(llvm::Record *record = nullptr) : WrappedRecord(record) {} 441 442 /// Return the class for which this is a creation rule. 443 /// Should never be abstract. 444 HasProperties getClass() const { 445 return get()->getValueAsDef(ClassFieldName); 446 } 447 448 llvm::StringRef getCreationCode() const { 449 return get()->getValueAsString(CreateFieldName); 450 } 451 452 static llvm::StringRef getTableGenNodeClassName() { 453 return CreationRuleClassName; 454 } 455 }; 456 457 /// A rule which overrides the standard rules for serializing an AST node. 458 class OverrideRule : public WrappedRecord { 459 public: 460 OverrideRule(llvm::Record *record = nullptr) : WrappedRecord(record) {} 461 462 /// Return the class for which this is an override rule. 463 /// Should never be abstract. 464 HasProperties getClass() const { 465 return get()->getValueAsDef(ClassFieldName); 466 } 467 468 /// Return a set of properties that are unnecessary when serializing 469 /// this AST node. Generally this is used for inherited properties 470 /// that are derived for this subclass. 471 std::vector<llvm::StringRef> getIgnoredProperties() const { 472 return get()->getValueAsListOfStrings(IgnoredPropertiesFieldName); 473 } 474 475 static llvm::StringRef getTableGenNodeClassName() { 476 return OverrideRuleClassName; 477 } 478 }; 479 480 /// A visitor for an AST node hierarchy. Note that `base` can be null for 481 /// the root class. 482 template <class NodeClass> 483 using ASTNodeHierarchyVisitor = 484 llvm::function_ref<void(NodeClass node, NodeClass base)>; 485 486 void visitASTNodeHierarchyImpl(llvm::RecordKeeper &records, 487 llvm::StringRef nodeClassName, 488 ASTNodeHierarchyVisitor<ASTNode> visit); 489 490 template <class NodeClass> 491 void visitASTNodeHierarchy(llvm::RecordKeeper &records, 492 ASTNodeHierarchyVisitor<NodeClass> visit) { 493 visitASTNodeHierarchyImpl(records, NodeClass::getTableGenNodeClassName(), 494 [visit](ASTNode node, ASTNode base) { 495 visit(NodeClass(node.getRecord()), 496 NodeClass(base.getRecord())); 497 }); 498 } 499 500 } // end namespace clang::tblgen 501 } // end namespace clang 502 503 #endif 504