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