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