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 85namespace clang { 86namespace tblgen { 87 88class WrappedRecord { 89 llvm::Record *Record; 90 91protected: 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 99public: 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. 142class HasProperties : public WrappedRecord { 143public: 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. 157class ASTNode : public HasProperties { 158public: 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 180class DeclNode : public ASTNode { 181public: 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 202class TypeNode : public ASTNode { 203public: 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 224class StmtNode : public ASTNode { 225public: 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. 247class PropertyType : public WrappedRecord { 248public: 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. 331class TypeKindRule : public WrappedRecord { 332public: 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. 361class TypeCase : public HasProperties { 362public: 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. 381class Property : public WrappedRecord { 382public: 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). 417class ReadHelperRule : public WrappedRecord { 418public: 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. 437class CreationRule : public WrappedRecord { 438public: 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. 457class OverrideRule : public WrappedRecord { 458public: 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. 481template <class NodeClass> 482using ASTNodeHierarchyVisitor = 483 llvm::function_ref<void(NodeClass node, NodeClass base)>; 484 485void visitASTNodeHierarchyImpl(llvm::RecordKeeper &records, 486 llvm::StringRef nodeClassName, 487 ASTNodeHierarchyVisitor<ASTNode> visit); 488 489template <class NodeClass> 490void 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