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:
Record(record)92 WrappedRecord(llvm::Record *record = nullptr) : Record(record) {}
93
get()94 llvm::Record *get() const {
95 assert(Record && "accessing null record");
96 return Record;
97 }
98
99 public:
getRecord()100 llvm::Record *getRecord() const { return Record; }
101
102 explicit operator bool() const { return Record != nullptr; }
103
getLoc()104 llvm::ArrayRef<llvm::SMLoc> getLoc() const {
105 return get()->getLoc();
106 }
107
108 /// Does the node inherit from the given TableGen class?
isSubClassOf(llvm::StringRef className)109 bool isSubClassOf(llvm::StringRef className) const {
110 return get()->isSubClassOf(className);
111 }
112
113 template <class NodeClass>
getAs()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
WrappedRecord(record)146 HasProperties(llvm::Record *record = nullptr) : WrappedRecord(record) {}
147
148 llvm::StringRef getName() const;
149
getTableGenNodeClassName()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:
HasProperties(record)159 ASTNode(llvm::Record *record = nullptr) : HasProperties(record) {}
160
getName()161 llvm::StringRef getName() const {
162 return get()->getName();
163 }
164
165 /// Return the node for the base, if there is one.
getBase()166 ASTNode getBase() const {
167 return get()->getValueAsOptionalDef(BaseFieldName);
168 }
169
170 /// Is the corresponding class abstract?
isAbstract()171 bool isAbstract() const {
172 return get()->getValueAsBit(AbstractFieldName);
173 }
174
getTableGenNodeClassName()175 static llvm::StringRef getTableGenNodeClassName() {
176 return ASTNodeClassName;
177 }
178 };
179
180 class DeclNode : public ASTNode {
181 public:
ASTNode(record)182 DeclNode(llvm::Record *record = nullptr) : ASTNode(record) {}
183
184 llvm::StringRef getId() const;
185 std::string getClassName() const;
getBase()186 DeclNode getBase() const { return DeclNode(ASTNode::getBase().getRecord()); }
187
getASTHierarchyName()188 static llvm::StringRef getASTHierarchyName() {
189 return "Decl";
190 }
getASTIdTypeName()191 static llvm::StringRef getASTIdTypeName() {
192 return "Decl::Kind";
193 }
getASTIdAccessorName()194 static llvm::StringRef getASTIdAccessorName() {
195 return "getKind";
196 }
getTableGenNodeClassName()197 static llvm::StringRef getTableGenNodeClassName() {
198 return DeclNodeClassName;
199 }
200 };
201
202 class TypeNode : public ASTNode {
203 public:
ASTNode(record)204 TypeNode(llvm::Record *record = nullptr) : ASTNode(record) {}
205
206 llvm::StringRef getId() const;
207 llvm::StringRef getClassName() const;
getBase()208 TypeNode getBase() const { return TypeNode(ASTNode::getBase().getRecord()); }
209
getASTHierarchyName()210 static llvm::StringRef getASTHierarchyName() {
211 return "Type";
212 }
getASTIdTypeName()213 static llvm::StringRef getASTIdTypeName() {
214 return "Type::TypeClass";
215 }
getASTIdAccessorName()216 static llvm::StringRef getASTIdAccessorName() {
217 return "getTypeClass";
218 }
getTableGenNodeClassName()219 static llvm::StringRef getTableGenNodeClassName() {
220 return TypeNodeClassName;
221 }
222 };
223
224 class StmtNode : public ASTNode {
225 public:
ASTNode(record)226 StmtNode(llvm::Record *record = nullptr) : ASTNode(record) {}
227
228 std::string getId() const;
229 llvm::StringRef getClassName() const;
getBase()230 StmtNode getBase() const { return StmtNode(ASTNode::getBase().getRecord()); }
231
getASTHierarchyName()232 static llvm::StringRef getASTHierarchyName() {
233 return "Stmt";
234 }
getASTIdTypeName()235 static llvm::StringRef getASTIdTypeName() {
236 return "Stmt::StmtClass";
237 }
getASTIdAccessorName()238 static llvm::StringRef getASTIdAccessorName() {
239 return "getStmtClass";
240 }
getTableGenNodeClassName()241 static llvm::StringRef getTableGenNodeClassName() {
242 return StmtNodeClassName;
243 }
244 };
245
246 /// The type of a property.
247 class PropertyType : public WrappedRecord {
248 public:
WrappedRecord(record)249 PropertyType(llvm::Record *record = nullptr) : WrappedRecord(record) {}
250
251 /// Is this a generic specialization (i.e. `Array<T>` or `Optional<T>`)?
isGenericSpecialization()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.
getAbstractTypeName()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.
getCXXTypeName()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.
shouldPassByReference()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.
isConstWhenWriting()276 bool isConstWhenWriting() const {
277 return get()->getValueAsBit(ConstWhenWritingFieldName);
278 }
279
280 /// If this is `Array<T>`, return `T`; otherwise return null.
getArrayElementType()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.
getOptionalElementType()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.
getSuperclassType()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<>`.
getSubclassClassName()304 llvm::StringRef getSubclassClassName() const {
305 return get()->getValueAsString(SubclassClassNameFieldName);
306 }
307
308 /// Does this represent an enum type?
isEnum()309 bool isEnum() const {
310 return isSubClassOf(EnumPropertyTypeClassName);
311 }
312
getPackOptionalCode()313 llvm::StringRef getPackOptionalCode() const {
314 return get()->getValueAsString(PackOptionalCodeFieldName);
315 }
316
getUnpackOptionalCode()317 llvm::StringRef getUnpackOptionalCode() const {
318 return get()->getValueAsString(UnpackOptionalCodeFieldName);
319 }
320
getBufferElementTypes()321 std::vector<llvm::Record*> getBufferElementTypes() const {
322 return get()->getValueAsListOfDefs(BufferElementTypesFieldName);
323 }
324
getTableGenNodeClassName()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:
WrappedRecord(record)333 TypeKindRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
334
335 /// Return the type to which this applies.
getParentType()336 PropertyType getParentType() const {
337 return get()->getValueAsDef(TypeFieldName);
338 }
339
340 /// Return the type of the kind.
getKindType()341 PropertyType getKindType() const {
342 return get()->getValueAsDef(KindTypeFieldName);
343 }
344
345 /// Return the name to use for the kind property.
getKindPropertyName()346 llvm::StringRef getKindPropertyName() const {
347 return get()->getValueAsString(KindPropertyNameFieldName);
348 }
349
350 /// Return the code for reading the kind value.
getReadCode()351 llvm::StringRef getReadCode() const {
352 return get()->getValueAsString(ReadFieldName);
353 }
354
getTableGenNodeClassName()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:
HasProperties(record)363 TypeCase(llvm::Record *record = nullptr) : HasProperties(record) {}
364
365 /// Return the name of this case.
getCaseName()366 llvm::StringRef getCaseName() const {
367 return get()->getValueAsString(NameFieldName);
368 }
369
370 /// Return the type of which this is a case.
getParentType()371 PropertyType getParentType() const {
372 return get()->getValueAsDef(TypeFieldName);
373 }
374
getTableGenNodeClassName()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:
WrappedRecord(record)383 Property(llvm::Record *record = nullptr) : WrappedRecord(record) {}
384
385 /// Return the name of this property.
getName()386 llvm::StringRef getName() const {
387 return get()->getValueAsString(NameFieldName);
388 }
389
390 /// Return the type of this property.
getType()391 PropertyType getType() const {
392 return get()->getValueAsDef(TypeFieldName);
393 }
394
395 /// Return the class of which this is a property.
getClass()396 HasProperties getClass() const {
397 return get()->getValueAsDef(ClassFieldName);
398 }
399
400 /// Return the code for reading this property.
getReadCode()401 llvm::StringRef getReadCode() const {
402 return get()->getValueAsString(ReadFieldName);
403 }
404
405 /// Return the code for determining whether to add this property.
getCondition()406 llvm::StringRef getCondition() const {
407 return get()->getValueAsString(ConditionalCodeFieldName);
408 }
409
getTableGenNodeClassName()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:
WrappedRecord(record)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.
getClass()423 HasProperties getClass() const {
424 return get()->getValueAsDef(ClassFieldName);
425 }
426
getHelperCode()427 llvm::StringRef getHelperCode() const {
428 return get()->getValueAsString(HelperCodeFieldName);
429 }
430
getTableGenNodeClassName()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:
WrappedRecord(record)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.
getClass()443 HasProperties getClass() const {
444 return get()->getValueAsDef(ClassFieldName);
445 }
446
getCreationCode()447 llvm::StringRef getCreationCode() const {
448 return get()->getValueAsString(CreateFieldName);
449 }
450
getTableGenNodeClassName()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:
WrappedRecord(record)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.
getClass()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.
getIgnoredProperties()470 std::vector<llvm::StringRef> getIgnoredProperties() const {
471 return get()->getValueAsListOfStrings(IgnoredPropertiesFieldName);
472 }
473
getTableGenNodeClassName()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>
visitASTNodeHierarchy(llvm::RecordKeeper & records,ASTNodeHierarchyVisitor<NodeClass> visit)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