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 86namespace clang { 87namespace tblgen { 88 89class WrappedRecord { 90 llvm::Record *Record; 91 92protected: 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 100public: 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. 143class HasProperties : public WrappedRecord { 144public: 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. 158class ASTNode : public HasProperties { 159public: 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 181class DeclNode : public ASTNode { 182public: 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 203class TypeNode : public ASTNode { 204public: 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 225class StmtNode : public ASTNode { 226public: 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. 248class PropertyType : public WrappedRecord { 249public: 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. 332class TypeKindRule : public WrappedRecord { 333public: 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. 362class TypeCase : public HasProperties { 363public: 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. 382class Property : public WrappedRecord { 383public: 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). 418class ReadHelperRule : public WrappedRecord { 419public: 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. 438class CreationRule : public WrappedRecord { 439public: 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. 458class OverrideRule : public WrappedRecord { 459public: 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. 482template <class NodeClass> 483using ASTNodeHierarchyVisitor = 484 llvm::function_ref<void(NodeClass node, NodeClass base)>; 485 486void visitASTNodeHierarchyImpl(llvm::RecordKeeper &records, 487 llvm::StringRef nodeClassName, 488 ASTNodeHierarchyVisitor<ASTNode> visit); 489 490template <class NodeClass> 491void 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