1480093f4SDimitry Andric //=== ASTTableGen.h - Common definitions for AST node tablegen --*- C++ -*-===//
2480093f4SDimitry Andric //
3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6480093f4SDimitry Andric //
7480093f4SDimitry Andric //===----------------------------------------------------------------------===//
8480093f4SDimitry Andric
9480093f4SDimitry Andric #ifndef CLANG_AST_TABLEGEN_H
10480093f4SDimitry Andric #define CLANG_AST_TABLEGEN_H
11480093f4SDimitry Andric
12480093f4SDimitry Andric #include "llvm/TableGen/Record.h"
13480093f4SDimitry Andric #include "llvm/ADT/STLExtras.h"
14*bdd1243dSDimitry Andric #include <optional>
15480093f4SDimitry Andric
16480093f4SDimitry Andric // These are spellings in the tblgen files.
17480093f4SDimitry Andric
18480093f4SDimitry Andric #define HasPropertiesClassName "HasProperties"
19480093f4SDimitry Andric
20480093f4SDimitry Andric // ASTNodes and their common fields. `Base` is actually defined
21480093f4SDimitry Andric // in subclasses, but it's still common across the hierarchies.
22480093f4SDimitry Andric #define ASTNodeClassName "ASTNode"
23480093f4SDimitry Andric #define BaseFieldName "Base"
24480093f4SDimitry Andric #define AbstractFieldName "Abstract"
25480093f4SDimitry Andric
26480093f4SDimitry Andric // Comment node hierarchy.
27480093f4SDimitry Andric #define CommentNodeClassName "CommentNode"
28480093f4SDimitry Andric
29480093f4SDimitry Andric // Decl node hierarchy.
30480093f4SDimitry Andric #define DeclNodeClassName "DeclNode"
31480093f4SDimitry Andric #define DeclContextNodeClassName "DeclContext"
32480093f4SDimitry Andric
33480093f4SDimitry Andric // Stmt node hierarchy.
34480093f4SDimitry Andric #define StmtNodeClassName "StmtNode"
35480093f4SDimitry Andric
36480093f4SDimitry Andric // Type node hierarchy.
37480093f4SDimitry Andric #define TypeNodeClassName "TypeNode"
38480093f4SDimitry Andric #define AlwaysDependentClassName "AlwaysDependent"
39480093f4SDimitry Andric #define NeverCanonicalClassName "NeverCanonical"
40480093f4SDimitry Andric #define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
41480093f4SDimitry Andric #define LeafTypeClassName "LeafType"
42480093f4SDimitry Andric
43480093f4SDimitry Andric // Cases of various non-ASTNode structured types like DeclarationName.
44480093f4SDimitry Andric #define TypeKindClassName "PropertyTypeKind"
45480093f4SDimitry Andric #define KindTypeFieldName "KindType"
46480093f4SDimitry Andric #define KindPropertyNameFieldName "KindPropertyName"
47480093f4SDimitry Andric #define TypeCaseClassName "PropertyTypeCase"
48480093f4SDimitry Andric
49480093f4SDimitry Andric // Properties of AST nodes.
50480093f4SDimitry Andric #define PropertyClassName "Property"
51480093f4SDimitry Andric #define ClassFieldName "Class"
52480093f4SDimitry Andric #define NameFieldName "Name"
53480093f4SDimitry Andric #define TypeFieldName "Type"
54480093f4SDimitry Andric #define ReadFieldName "Read"
55480093f4SDimitry Andric
56480093f4SDimitry Andric // Types of properties.
57480093f4SDimitry Andric #define PropertyTypeClassName "PropertyType"
58480093f4SDimitry Andric #define CXXTypeNameFieldName "CXXName"
59480093f4SDimitry Andric #define PassByReferenceFieldName "PassByReference"
60480093f4SDimitry Andric #define ConstWhenWritingFieldName "ConstWhenWriting"
61480093f4SDimitry Andric #define ConditionalCodeFieldName "Conditional"
62480093f4SDimitry Andric #define PackOptionalCodeFieldName "PackOptional"
63480093f4SDimitry Andric #define UnpackOptionalCodeFieldName "UnpackOptional"
64480093f4SDimitry Andric #define BufferElementTypesFieldName "BufferElementTypes"
65480093f4SDimitry Andric #define ArrayTypeClassName "Array"
66480093f4SDimitry Andric #define ArrayElementTypeFieldName "Element"
67480093f4SDimitry Andric #define OptionalTypeClassName "Optional"
68480093f4SDimitry Andric #define OptionalElementTypeFieldName "Element"
69480093f4SDimitry Andric #define SubclassPropertyTypeClassName "SubclassPropertyType"
70480093f4SDimitry Andric #define SubclassBaseTypeFieldName "Base"
71480093f4SDimitry Andric #define SubclassClassNameFieldName "SubclassName"
72480093f4SDimitry Andric #define EnumPropertyTypeClassName "EnumPropertyType"
73480093f4SDimitry Andric
74480093f4SDimitry Andric // Write helper rules.
75480093f4SDimitry Andric #define ReadHelperRuleClassName "ReadHelper"
76480093f4SDimitry Andric #define HelperCodeFieldName "Code"
77480093f4SDimitry Andric
78480093f4SDimitry Andric // Creation rules.
79480093f4SDimitry Andric #define CreationRuleClassName "Creator"
80480093f4SDimitry Andric #define CreateFieldName "Create"
81480093f4SDimitry Andric
82480093f4SDimitry Andric // Override rules.
83480093f4SDimitry Andric #define OverrideRuleClassName "Override"
84480093f4SDimitry Andric #define IgnoredPropertiesFieldName "IgnoredProperties"
85480093f4SDimitry Andric
86480093f4SDimitry Andric namespace clang {
87480093f4SDimitry Andric namespace tblgen {
88480093f4SDimitry Andric
89480093f4SDimitry Andric class WrappedRecord {
90480093f4SDimitry Andric llvm::Record *Record;
91480093f4SDimitry Andric
92480093f4SDimitry Andric protected:
Record(record)93480093f4SDimitry Andric WrappedRecord(llvm::Record *record = nullptr) : Record(record) {}
94480093f4SDimitry Andric
get()95480093f4SDimitry Andric llvm::Record *get() const {
96480093f4SDimitry Andric assert(Record && "accessing null record");
97480093f4SDimitry Andric return Record;
98480093f4SDimitry Andric }
99480093f4SDimitry Andric
100480093f4SDimitry Andric public:
getRecord()101480093f4SDimitry Andric llvm::Record *getRecord() const { return Record; }
102480093f4SDimitry Andric
103480093f4SDimitry Andric explicit operator bool() const { return Record != nullptr; }
104480093f4SDimitry Andric
getLoc()105480093f4SDimitry Andric llvm::ArrayRef<llvm::SMLoc> getLoc() const {
106480093f4SDimitry Andric return get()->getLoc();
107480093f4SDimitry Andric }
108480093f4SDimitry Andric
109480093f4SDimitry Andric /// Does the node inherit from the given TableGen class?
isSubClassOf(llvm::StringRef className)110480093f4SDimitry Andric bool isSubClassOf(llvm::StringRef className) const {
111480093f4SDimitry Andric return get()->isSubClassOf(className);
112480093f4SDimitry Andric }
113480093f4SDimitry Andric
114480093f4SDimitry Andric template <class NodeClass>
getAs()115480093f4SDimitry Andric NodeClass getAs() const {
116480093f4SDimitry Andric return (isSubClassOf(NodeClass::getTableGenNodeClassName())
117480093f4SDimitry Andric ? NodeClass(get()) : NodeClass());
118480093f4SDimitry Andric }
119480093f4SDimitry Andric
120480093f4SDimitry Andric friend bool operator<(WrappedRecord lhs, WrappedRecord rhs) {
121480093f4SDimitry Andric assert(lhs && rhs && "sorting null nodes");
122480093f4SDimitry Andric return lhs.get()->getName() < rhs.get()->getName();
123480093f4SDimitry Andric }
124480093f4SDimitry Andric friend bool operator>(WrappedRecord lhs, WrappedRecord rhs) {
125480093f4SDimitry Andric return rhs < lhs;
126480093f4SDimitry Andric }
127480093f4SDimitry Andric friend bool operator<=(WrappedRecord lhs, WrappedRecord rhs) {
128480093f4SDimitry Andric return !(rhs < lhs);
129480093f4SDimitry Andric }
130480093f4SDimitry Andric friend bool operator>=(WrappedRecord lhs, WrappedRecord rhs) {
131480093f4SDimitry Andric return !(lhs < rhs);
132480093f4SDimitry Andric }
133480093f4SDimitry Andric friend bool operator==(WrappedRecord lhs, WrappedRecord rhs) {
134480093f4SDimitry Andric // This should handle null nodes.
135480093f4SDimitry Andric return lhs.getRecord() == rhs.getRecord();
136480093f4SDimitry Andric }
137480093f4SDimitry Andric friend bool operator!=(WrappedRecord lhs, WrappedRecord rhs) {
138480093f4SDimitry Andric return !(lhs == rhs);
139480093f4SDimitry Andric }
140480093f4SDimitry Andric };
141480093f4SDimitry Andric
142480093f4SDimitry Andric /// Anything in the AST that has properties.
143480093f4SDimitry Andric class HasProperties : public WrappedRecord {
144480093f4SDimitry Andric public:
145480093f4SDimitry Andric static constexpr llvm::StringRef ClassName = HasPropertiesClassName;
146480093f4SDimitry Andric
WrappedRecord(record)147480093f4SDimitry Andric HasProperties(llvm::Record *record = nullptr) : WrappedRecord(record) {}
148480093f4SDimitry Andric
149480093f4SDimitry Andric llvm::StringRef getName() const;
150480093f4SDimitry Andric
getTableGenNodeClassName()151480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
152480093f4SDimitry Andric return HasPropertiesClassName;
153480093f4SDimitry Andric }
154480093f4SDimitry Andric };
155480093f4SDimitry Andric
156480093f4SDimitry Andric /// An (optional) reference to a TableGen node representing a class
157480093f4SDimitry Andric /// in one of Clang's AST hierarchies.
158480093f4SDimitry Andric class ASTNode : public HasProperties {
159480093f4SDimitry Andric public:
HasProperties(record)160480093f4SDimitry Andric ASTNode(llvm::Record *record = nullptr) : HasProperties(record) {}
161480093f4SDimitry Andric
getName()162480093f4SDimitry Andric llvm::StringRef getName() const {
163480093f4SDimitry Andric return get()->getName();
164480093f4SDimitry Andric }
165480093f4SDimitry Andric
166480093f4SDimitry Andric /// Return the node for the base, if there is one.
getBase()167480093f4SDimitry Andric ASTNode getBase() const {
168480093f4SDimitry Andric return get()->getValueAsOptionalDef(BaseFieldName);
169480093f4SDimitry Andric }
170480093f4SDimitry Andric
171480093f4SDimitry Andric /// Is the corresponding class abstract?
isAbstract()172480093f4SDimitry Andric bool isAbstract() const {
173480093f4SDimitry Andric return get()->getValueAsBit(AbstractFieldName);
174480093f4SDimitry Andric }
175480093f4SDimitry Andric
getTableGenNodeClassName()176480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
177480093f4SDimitry Andric return ASTNodeClassName;
178480093f4SDimitry Andric }
179480093f4SDimitry Andric };
180480093f4SDimitry Andric
181480093f4SDimitry Andric class DeclNode : public ASTNode {
182480093f4SDimitry Andric public:
ASTNode(record)183480093f4SDimitry Andric DeclNode(llvm::Record *record = nullptr) : ASTNode(record) {}
184480093f4SDimitry Andric
185480093f4SDimitry Andric llvm::StringRef getId() const;
186480093f4SDimitry Andric std::string getClassName() const;
getBase()187480093f4SDimitry Andric DeclNode getBase() const { return DeclNode(ASTNode::getBase().getRecord()); }
188480093f4SDimitry Andric
getASTHierarchyName()189480093f4SDimitry Andric static llvm::StringRef getASTHierarchyName() {
190480093f4SDimitry Andric return "Decl";
191480093f4SDimitry Andric }
getASTIdTypeName()192480093f4SDimitry Andric static llvm::StringRef getASTIdTypeName() {
193480093f4SDimitry Andric return "Decl::Kind";
194480093f4SDimitry Andric }
getASTIdAccessorName()195480093f4SDimitry Andric static llvm::StringRef getASTIdAccessorName() {
196480093f4SDimitry Andric return "getKind";
197480093f4SDimitry Andric }
getTableGenNodeClassName()198480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
199480093f4SDimitry Andric return DeclNodeClassName;
200480093f4SDimitry Andric }
201480093f4SDimitry Andric };
202480093f4SDimitry Andric
203480093f4SDimitry Andric class TypeNode : public ASTNode {
204480093f4SDimitry Andric public:
ASTNode(record)205480093f4SDimitry Andric TypeNode(llvm::Record *record = nullptr) : ASTNode(record) {}
206480093f4SDimitry Andric
207480093f4SDimitry Andric llvm::StringRef getId() const;
208480093f4SDimitry Andric llvm::StringRef getClassName() const;
getBase()209480093f4SDimitry Andric TypeNode getBase() const { return TypeNode(ASTNode::getBase().getRecord()); }
210480093f4SDimitry Andric
getASTHierarchyName()211480093f4SDimitry Andric static llvm::StringRef getASTHierarchyName() {
212480093f4SDimitry Andric return "Type";
213480093f4SDimitry Andric }
getASTIdTypeName()214480093f4SDimitry Andric static llvm::StringRef getASTIdTypeName() {
215480093f4SDimitry Andric return "Type::TypeClass";
216480093f4SDimitry Andric }
getASTIdAccessorName()217480093f4SDimitry Andric static llvm::StringRef getASTIdAccessorName() {
218480093f4SDimitry Andric return "getTypeClass";
219480093f4SDimitry Andric }
getTableGenNodeClassName()220480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
221480093f4SDimitry Andric return TypeNodeClassName;
222480093f4SDimitry Andric }
223480093f4SDimitry Andric };
224480093f4SDimitry Andric
225480093f4SDimitry Andric class StmtNode : public ASTNode {
226480093f4SDimitry Andric public:
ASTNode(record)227480093f4SDimitry Andric StmtNode(llvm::Record *record = nullptr) : ASTNode(record) {}
228480093f4SDimitry Andric
229480093f4SDimitry Andric std::string getId() const;
230480093f4SDimitry Andric llvm::StringRef getClassName() const;
getBase()231480093f4SDimitry Andric StmtNode getBase() const { return StmtNode(ASTNode::getBase().getRecord()); }
232480093f4SDimitry Andric
getASTHierarchyName()233480093f4SDimitry Andric static llvm::StringRef getASTHierarchyName() {
234480093f4SDimitry Andric return "Stmt";
235480093f4SDimitry Andric }
getASTIdTypeName()236480093f4SDimitry Andric static llvm::StringRef getASTIdTypeName() {
237480093f4SDimitry Andric return "Stmt::StmtClass";
238480093f4SDimitry Andric }
getASTIdAccessorName()239480093f4SDimitry Andric static llvm::StringRef getASTIdAccessorName() {
240480093f4SDimitry Andric return "getStmtClass";
241480093f4SDimitry Andric }
getTableGenNodeClassName()242480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
243480093f4SDimitry Andric return StmtNodeClassName;
244480093f4SDimitry Andric }
245480093f4SDimitry Andric };
246480093f4SDimitry Andric
247480093f4SDimitry Andric /// The type of a property.
248480093f4SDimitry Andric class PropertyType : public WrappedRecord {
249480093f4SDimitry Andric public:
WrappedRecord(record)250480093f4SDimitry Andric PropertyType(llvm::Record *record = nullptr) : WrappedRecord(record) {}
251480093f4SDimitry Andric
252480093f4SDimitry Andric /// Is this a generic specialization (i.e. `Array<T>` or `Optional<T>`)?
isGenericSpecialization()253480093f4SDimitry Andric bool isGenericSpecialization() const {
254480093f4SDimitry Andric return get()->isAnonymous();
255480093f4SDimitry Andric }
256480093f4SDimitry Andric
257480093f4SDimitry Andric /// The abstract type name of the property. Doesn't work for generic
258480093f4SDimitry Andric /// specializations.
getAbstractTypeName()259480093f4SDimitry Andric llvm::StringRef getAbstractTypeName() const {
260480093f4SDimitry Andric return get()->getName();
261480093f4SDimitry Andric }
262480093f4SDimitry Andric
263480093f4SDimitry Andric /// The C++ type name of the property. Doesn't work for generic
264480093f4SDimitry Andric /// specializations.
getCXXTypeName()265480093f4SDimitry Andric llvm::StringRef getCXXTypeName() const {
266480093f4SDimitry Andric return get()->getValueAsString(CXXTypeNameFieldName);
267480093f4SDimitry Andric }
268480093f4SDimitry Andric void emitCXXValueTypeName(bool forRead, llvm::raw_ostream &out) const;
269480093f4SDimitry Andric
270480093f4SDimitry Andric /// Whether the C++ type should be passed around by reference.
shouldPassByReference()271480093f4SDimitry Andric bool shouldPassByReference() const {
272480093f4SDimitry Andric return get()->getValueAsBit(PassByReferenceFieldName);
273480093f4SDimitry Andric }
274480093f4SDimitry Andric
275480093f4SDimitry Andric /// Whether the C++ type should have 'const' prepended when working with
276480093f4SDimitry Andric /// a value of the type being written.
isConstWhenWriting()277480093f4SDimitry Andric bool isConstWhenWriting() const {
278480093f4SDimitry Andric return get()->getValueAsBit(ConstWhenWritingFieldName);
279480093f4SDimitry Andric }
280480093f4SDimitry Andric
281480093f4SDimitry Andric /// If this is `Array<T>`, return `T`; otherwise return null.
getArrayElementType()282480093f4SDimitry Andric PropertyType getArrayElementType() const {
283480093f4SDimitry Andric if (isSubClassOf(ArrayTypeClassName))
284480093f4SDimitry Andric return get()->getValueAsDef(ArrayElementTypeFieldName);
285480093f4SDimitry Andric return nullptr;
286480093f4SDimitry Andric }
287480093f4SDimitry Andric
288480093f4SDimitry Andric /// If this is `Optional<T>`, return `T`; otherwise return null.
getOptionalElementType()289480093f4SDimitry Andric PropertyType getOptionalElementType() const {
290480093f4SDimitry Andric if (isSubClassOf(OptionalTypeClassName))
291480093f4SDimitry Andric return get()->getValueAsDef(OptionalElementTypeFieldName);
292480093f4SDimitry Andric return nullptr;
293480093f4SDimitry Andric }
294480093f4SDimitry Andric
295480093f4SDimitry Andric /// If this is a subclass type, return its superclass type.
getSuperclassType()296480093f4SDimitry Andric PropertyType getSuperclassType() const {
297480093f4SDimitry Andric if (isSubClassOf(SubclassPropertyTypeClassName))
298480093f4SDimitry Andric return get()->getValueAsDef(SubclassBaseTypeFieldName);
299480093f4SDimitry Andric return nullptr;
300480093f4SDimitry Andric }
301480093f4SDimitry Andric
302480093f4SDimitry Andric // Given that this is a subclass type, return the C++ name of its
303480093f4SDimitry Andric // subclass type. This is just the bare class name, suitable for
304480093f4SDimitry Andric // use in `cast<>`.
getSubclassClassName()305480093f4SDimitry Andric llvm::StringRef getSubclassClassName() const {
306480093f4SDimitry Andric return get()->getValueAsString(SubclassClassNameFieldName);
307480093f4SDimitry Andric }
308480093f4SDimitry Andric
309480093f4SDimitry Andric /// Does this represent an enum type?
isEnum()310480093f4SDimitry Andric bool isEnum() const {
311480093f4SDimitry Andric return isSubClassOf(EnumPropertyTypeClassName);
312480093f4SDimitry Andric }
313480093f4SDimitry Andric
getPackOptionalCode()314480093f4SDimitry Andric llvm::StringRef getPackOptionalCode() const {
315480093f4SDimitry Andric return get()->getValueAsString(PackOptionalCodeFieldName);
316480093f4SDimitry Andric }
317480093f4SDimitry Andric
getUnpackOptionalCode()318480093f4SDimitry Andric llvm::StringRef getUnpackOptionalCode() const {
319480093f4SDimitry Andric return get()->getValueAsString(UnpackOptionalCodeFieldName);
320480093f4SDimitry Andric }
321480093f4SDimitry Andric
getBufferElementTypes()322480093f4SDimitry Andric std::vector<llvm::Record*> getBufferElementTypes() const {
323480093f4SDimitry Andric return get()->getValueAsListOfDefs(BufferElementTypesFieldName);
324480093f4SDimitry Andric }
325480093f4SDimitry Andric
getTableGenNodeClassName()326480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
327480093f4SDimitry Andric return PropertyTypeClassName;
328480093f4SDimitry Andric }
329480093f4SDimitry Andric };
330480093f4SDimitry Andric
331480093f4SDimitry Andric /// A rule for returning the kind of a type.
332480093f4SDimitry Andric class TypeKindRule : public WrappedRecord {
333480093f4SDimitry Andric public:
WrappedRecord(record)334480093f4SDimitry Andric TypeKindRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
335480093f4SDimitry Andric
336480093f4SDimitry Andric /// Return the type to which this applies.
getParentType()337480093f4SDimitry Andric PropertyType getParentType() const {
338480093f4SDimitry Andric return get()->getValueAsDef(TypeFieldName);
339480093f4SDimitry Andric }
340480093f4SDimitry Andric
341480093f4SDimitry Andric /// Return the type of the kind.
getKindType()342480093f4SDimitry Andric PropertyType getKindType() const {
343480093f4SDimitry Andric return get()->getValueAsDef(KindTypeFieldName);
344480093f4SDimitry Andric }
345480093f4SDimitry Andric
346480093f4SDimitry Andric /// Return the name to use for the kind property.
getKindPropertyName()347480093f4SDimitry Andric llvm::StringRef getKindPropertyName() const {
348480093f4SDimitry Andric return get()->getValueAsString(KindPropertyNameFieldName);
349480093f4SDimitry Andric }
350480093f4SDimitry Andric
351480093f4SDimitry Andric /// Return the code for reading the kind value.
getReadCode()352480093f4SDimitry Andric llvm::StringRef getReadCode() const {
353480093f4SDimitry Andric return get()->getValueAsString(ReadFieldName);
354480093f4SDimitry Andric }
355480093f4SDimitry Andric
getTableGenNodeClassName()356480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
357480093f4SDimitry Andric return TypeKindClassName;
358480093f4SDimitry Andric }
359480093f4SDimitry Andric };
360480093f4SDimitry Andric
361480093f4SDimitry Andric /// An implementation case of a property type.
362480093f4SDimitry Andric class TypeCase : public HasProperties {
363480093f4SDimitry Andric public:
HasProperties(record)364480093f4SDimitry Andric TypeCase(llvm::Record *record = nullptr) : HasProperties(record) {}
365480093f4SDimitry Andric
366480093f4SDimitry Andric /// Return the name of this case.
getCaseName()367480093f4SDimitry Andric llvm::StringRef getCaseName() const {
368480093f4SDimitry Andric return get()->getValueAsString(NameFieldName);
369480093f4SDimitry Andric }
370480093f4SDimitry Andric
371480093f4SDimitry Andric /// Return the type of which this is a case.
getParentType()372480093f4SDimitry Andric PropertyType getParentType() const {
373480093f4SDimitry Andric return get()->getValueAsDef(TypeFieldName);
374480093f4SDimitry Andric }
375480093f4SDimitry Andric
getTableGenNodeClassName()376480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
377480093f4SDimitry Andric return TypeCaseClassName;
378480093f4SDimitry Andric }
379480093f4SDimitry Andric };
380480093f4SDimitry Andric
381480093f4SDimitry Andric /// A property of an AST node.
382480093f4SDimitry Andric class Property : public WrappedRecord {
383480093f4SDimitry Andric public:
WrappedRecord(record)384480093f4SDimitry Andric Property(llvm::Record *record = nullptr) : WrappedRecord(record) {}
385480093f4SDimitry Andric
386480093f4SDimitry Andric /// Return the name of this property.
getName()387480093f4SDimitry Andric llvm::StringRef getName() const {
388480093f4SDimitry Andric return get()->getValueAsString(NameFieldName);
389480093f4SDimitry Andric }
390480093f4SDimitry Andric
391480093f4SDimitry Andric /// Return the type of this property.
getType()392480093f4SDimitry Andric PropertyType getType() const {
393480093f4SDimitry Andric return get()->getValueAsDef(TypeFieldName);
394480093f4SDimitry Andric }
395480093f4SDimitry Andric
396480093f4SDimitry Andric /// Return the class of which this is a property.
getClass()397480093f4SDimitry Andric HasProperties getClass() const {
398480093f4SDimitry Andric return get()->getValueAsDef(ClassFieldName);
399480093f4SDimitry Andric }
400480093f4SDimitry Andric
401480093f4SDimitry Andric /// Return the code for reading this property.
getReadCode()402480093f4SDimitry Andric llvm::StringRef getReadCode() const {
403480093f4SDimitry Andric return get()->getValueAsString(ReadFieldName);
404480093f4SDimitry Andric }
405480093f4SDimitry Andric
406480093f4SDimitry Andric /// Return the code for determining whether to add this property.
getCondition()407480093f4SDimitry Andric llvm::StringRef getCondition() const {
408480093f4SDimitry Andric return get()->getValueAsString(ConditionalCodeFieldName);
409480093f4SDimitry Andric }
410480093f4SDimitry Andric
getTableGenNodeClassName()411480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
412480093f4SDimitry Andric return PropertyClassName;
413480093f4SDimitry Andric }
414480093f4SDimitry Andric };
415480093f4SDimitry Andric
416480093f4SDimitry Andric /// A rule for running some helper code for reading properties from
417480093f4SDimitry Andric /// a value (which is actually done when writing the value out).
418480093f4SDimitry Andric class ReadHelperRule : public WrappedRecord {
419480093f4SDimitry Andric public:
WrappedRecord(record)420480093f4SDimitry Andric ReadHelperRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
421480093f4SDimitry Andric
422480093f4SDimitry Andric /// Return the class for which this is a creation rule.
423480093f4SDimitry Andric /// Should never be abstract.
getClass()424480093f4SDimitry Andric HasProperties getClass() const {
425480093f4SDimitry Andric return get()->getValueAsDef(ClassFieldName);
426480093f4SDimitry Andric }
427480093f4SDimitry Andric
getHelperCode()428480093f4SDimitry Andric llvm::StringRef getHelperCode() const {
429480093f4SDimitry Andric return get()->getValueAsString(HelperCodeFieldName);
430480093f4SDimitry Andric }
431480093f4SDimitry Andric
getTableGenNodeClassName()432480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
433480093f4SDimitry Andric return ReadHelperRuleClassName;
434480093f4SDimitry Andric }
435480093f4SDimitry Andric };
436480093f4SDimitry Andric
437480093f4SDimitry Andric /// A rule for how to create an AST node from its properties.
438480093f4SDimitry Andric class CreationRule : public WrappedRecord {
439480093f4SDimitry Andric public:
WrappedRecord(record)440480093f4SDimitry Andric CreationRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
441480093f4SDimitry Andric
442480093f4SDimitry Andric /// Return the class for which this is a creation rule.
443480093f4SDimitry Andric /// Should never be abstract.
getClass()444480093f4SDimitry Andric HasProperties getClass() const {
445480093f4SDimitry Andric return get()->getValueAsDef(ClassFieldName);
446480093f4SDimitry Andric }
447480093f4SDimitry Andric
getCreationCode()448480093f4SDimitry Andric llvm::StringRef getCreationCode() const {
449480093f4SDimitry Andric return get()->getValueAsString(CreateFieldName);
450480093f4SDimitry Andric }
451480093f4SDimitry Andric
getTableGenNodeClassName()452480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
453480093f4SDimitry Andric return CreationRuleClassName;
454480093f4SDimitry Andric }
455480093f4SDimitry Andric };
456480093f4SDimitry Andric
457480093f4SDimitry Andric /// A rule which overrides the standard rules for serializing an AST node.
458480093f4SDimitry Andric class OverrideRule : public WrappedRecord {
459480093f4SDimitry Andric public:
WrappedRecord(record)460480093f4SDimitry Andric OverrideRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
461480093f4SDimitry Andric
462480093f4SDimitry Andric /// Return the class for which this is an override rule.
463480093f4SDimitry Andric /// Should never be abstract.
getClass()464480093f4SDimitry Andric HasProperties getClass() const {
465480093f4SDimitry Andric return get()->getValueAsDef(ClassFieldName);
466480093f4SDimitry Andric }
467480093f4SDimitry Andric
468480093f4SDimitry Andric /// Return a set of properties that are unnecessary when serializing
469480093f4SDimitry Andric /// this AST node. Generally this is used for inherited properties
470480093f4SDimitry Andric /// that are derived for this subclass.
getIgnoredProperties()471480093f4SDimitry Andric std::vector<llvm::StringRef> getIgnoredProperties() const {
472480093f4SDimitry Andric return get()->getValueAsListOfStrings(IgnoredPropertiesFieldName);
473480093f4SDimitry Andric }
474480093f4SDimitry Andric
getTableGenNodeClassName()475480093f4SDimitry Andric static llvm::StringRef getTableGenNodeClassName() {
476480093f4SDimitry Andric return OverrideRuleClassName;
477480093f4SDimitry Andric }
478480093f4SDimitry Andric };
479480093f4SDimitry Andric
480480093f4SDimitry Andric /// A visitor for an AST node hierarchy. Note that `base` can be null for
481480093f4SDimitry Andric /// the root class.
482480093f4SDimitry Andric template <class NodeClass>
483480093f4SDimitry Andric using ASTNodeHierarchyVisitor =
484480093f4SDimitry Andric llvm::function_ref<void(NodeClass node, NodeClass base)>;
485480093f4SDimitry Andric
486480093f4SDimitry Andric void visitASTNodeHierarchyImpl(llvm::RecordKeeper &records,
487480093f4SDimitry Andric llvm::StringRef nodeClassName,
488480093f4SDimitry Andric ASTNodeHierarchyVisitor<ASTNode> visit);
489480093f4SDimitry Andric
490480093f4SDimitry Andric template <class NodeClass>
visitASTNodeHierarchy(llvm::RecordKeeper & records,ASTNodeHierarchyVisitor<NodeClass> visit)491480093f4SDimitry Andric void visitASTNodeHierarchy(llvm::RecordKeeper &records,
492480093f4SDimitry Andric ASTNodeHierarchyVisitor<NodeClass> visit) {
493480093f4SDimitry Andric visitASTNodeHierarchyImpl(records, NodeClass::getTableGenNodeClassName(),
494480093f4SDimitry Andric [visit](ASTNode node, ASTNode base) {
495480093f4SDimitry Andric visit(NodeClass(node.getRecord()),
496480093f4SDimitry Andric NodeClass(base.getRecord()));
497480093f4SDimitry Andric });
498480093f4SDimitry Andric }
499480093f4SDimitry Andric
500480093f4SDimitry Andric } // end namespace clang::tblgen
501480093f4SDimitry Andric } // end namespace clang
502480093f4SDimitry Andric
503480093f4SDimitry Andric #endif
504