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
86 namespace clang {
87 namespace tblgen {
88
89 class WrappedRecord {
90 llvm::Record *Record;
91
92 protected:
Record(record)93 WrappedRecord(llvm::Record *record = nullptr) : Record(record) {}
94
get()95 llvm::Record *get() const {
96 assert(Record && "accessing null record");
97 return Record;
98 }
99
100 public:
getRecord()101 llvm::Record *getRecord() const { return Record; }
102
103 explicit operator bool() const { return Record != nullptr; }
104
getLoc()105 llvm::ArrayRef<llvm::SMLoc> getLoc() const {
106 return get()->getLoc();
107 }
108
109 /// Does the node inherit from the given TableGen class?
isSubClassOf(llvm::StringRef className)110 bool isSubClassOf(llvm::StringRef className) const {
111 return get()->isSubClassOf(className);
112 }
113
114 template <class NodeClass>
getAs()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.
143 class HasProperties : public WrappedRecord {
144 public:
145 static constexpr llvm::StringRef ClassName = HasPropertiesClassName;
146
WrappedRecord(record)147 HasProperties(llvm::Record *record = nullptr) : WrappedRecord(record) {}
148
149 llvm::StringRef getName() const;
150
getTableGenNodeClassName()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.
158 class ASTNode : public HasProperties {
159 public:
HasProperties(record)160 ASTNode(llvm::Record *record = nullptr) : HasProperties(record) {}
161
getName()162 llvm::StringRef getName() const {
163 return get()->getName();
164 }
165
166 /// Return the node for the base, if there is one.
getBase()167 ASTNode getBase() const {
168 return get()->getValueAsOptionalDef(BaseFieldName);
169 }
170
171 /// Is the corresponding class abstract?
isAbstract()172 bool isAbstract() const {
173 return get()->getValueAsBit(AbstractFieldName);
174 }
175
getTableGenNodeClassName()176 static llvm::StringRef getTableGenNodeClassName() {
177 return ASTNodeClassName;
178 }
179 };
180
181 class DeclNode : public ASTNode {
182 public:
ASTNode(record)183 DeclNode(llvm::Record *record = nullptr) : ASTNode(record) {}
184
185 llvm::StringRef getId() const;
186 std::string getClassName() const;
getBase()187 DeclNode getBase() const { return DeclNode(ASTNode::getBase().getRecord()); }
188
getASTHierarchyName()189 static llvm::StringRef getASTHierarchyName() {
190 return "Decl";
191 }
getASTIdTypeName()192 static llvm::StringRef getASTIdTypeName() {
193 return "Decl::Kind";
194 }
getASTIdAccessorName()195 static llvm::StringRef getASTIdAccessorName() {
196 return "getKind";
197 }
getTableGenNodeClassName()198 static llvm::StringRef getTableGenNodeClassName() {
199 return DeclNodeClassName;
200 }
201 };
202
203 class TypeNode : public ASTNode {
204 public:
ASTNode(record)205 TypeNode(llvm::Record *record = nullptr) : ASTNode(record) {}
206
207 llvm::StringRef getId() const;
208 llvm::StringRef getClassName() const;
getBase()209 TypeNode getBase() const { return TypeNode(ASTNode::getBase().getRecord()); }
210
getASTHierarchyName()211 static llvm::StringRef getASTHierarchyName() {
212 return "Type";
213 }
getASTIdTypeName()214 static llvm::StringRef getASTIdTypeName() {
215 return "Type::TypeClass";
216 }
getASTIdAccessorName()217 static llvm::StringRef getASTIdAccessorName() {
218 return "getTypeClass";
219 }
getTableGenNodeClassName()220 static llvm::StringRef getTableGenNodeClassName() {
221 return TypeNodeClassName;
222 }
223 };
224
225 class StmtNode : public ASTNode {
226 public:
ASTNode(record)227 StmtNode(llvm::Record *record = nullptr) : ASTNode(record) {}
228
229 std::string getId() const;
230 llvm::StringRef getClassName() const;
getBase()231 StmtNode getBase() const { return StmtNode(ASTNode::getBase().getRecord()); }
232
getASTHierarchyName()233 static llvm::StringRef getASTHierarchyName() {
234 return "Stmt";
235 }
getASTIdTypeName()236 static llvm::StringRef getASTIdTypeName() {
237 return "Stmt::StmtClass";
238 }
getASTIdAccessorName()239 static llvm::StringRef getASTIdAccessorName() {
240 return "getStmtClass";
241 }
getTableGenNodeClassName()242 static llvm::StringRef getTableGenNodeClassName() {
243 return StmtNodeClassName;
244 }
245 };
246
247 /// The type of a property.
248 class PropertyType : public WrappedRecord {
249 public:
WrappedRecord(record)250 PropertyType(llvm::Record *record = nullptr) : WrappedRecord(record) {}
251
252 /// Is this a generic specialization (i.e. `Array<T>` or `Optional<T>`)?
isGenericSpecialization()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.
getAbstractTypeName()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.
getCXXTypeName()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.
shouldPassByReference()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.
isConstWhenWriting()277 bool isConstWhenWriting() const {
278 return get()->getValueAsBit(ConstWhenWritingFieldName);
279 }
280
281 /// If this is `Array<T>`, return `T`; otherwise return null.
getArrayElementType()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.
getOptionalElementType()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.
getSuperclassType()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<>`.
getSubclassClassName()305 llvm::StringRef getSubclassClassName() const {
306 return get()->getValueAsString(SubclassClassNameFieldName);
307 }
308
309 /// Does this represent an enum type?
isEnum()310 bool isEnum() const {
311 return isSubClassOf(EnumPropertyTypeClassName);
312 }
313
getPackOptionalCode()314 llvm::StringRef getPackOptionalCode() const {
315 return get()->getValueAsString(PackOptionalCodeFieldName);
316 }
317
getUnpackOptionalCode()318 llvm::StringRef getUnpackOptionalCode() const {
319 return get()->getValueAsString(UnpackOptionalCodeFieldName);
320 }
321
getBufferElementTypes()322 std::vector<llvm::Record*> getBufferElementTypes() const {
323 return get()->getValueAsListOfDefs(BufferElementTypesFieldName);
324 }
325
getTableGenNodeClassName()326 static llvm::StringRef getTableGenNodeClassName() {
327 return PropertyTypeClassName;
328 }
329 };
330
331 /// A rule for returning the kind of a type.
332 class TypeKindRule : public WrappedRecord {
333 public:
WrappedRecord(record)334 TypeKindRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
335
336 /// Return the type to which this applies.
getParentType()337 PropertyType getParentType() const {
338 return get()->getValueAsDef(TypeFieldName);
339 }
340
341 /// Return the type of the kind.
getKindType()342 PropertyType getKindType() const {
343 return get()->getValueAsDef(KindTypeFieldName);
344 }
345
346 /// Return the name to use for the kind property.
getKindPropertyName()347 llvm::StringRef getKindPropertyName() const {
348 return get()->getValueAsString(KindPropertyNameFieldName);
349 }
350
351 /// Return the code for reading the kind value.
getReadCode()352 llvm::StringRef getReadCode() const {
353 return get()->getValueAsString(ReadFieldName);
354 }
355
getTableGenNodeClassName()356 static llvm::StringRef getTableGenNodeClassName() {
357 return TypeKindClassName;
358 }
359 };
360
361 /// An implementation case of a property type.
362 class TypeCase : public HasProperties {
363 public:
HasProperties(record)364 TypeCase(llvm::Record *record = nullptr) : HasProperties(record) {}
365
366 /// Return the name of this case.
getCaseName()367 llvm::StringRef getCaseName() const {
368 return get()->getValueAsString(NameFieldName);
369 }
370
371 /// Return the type of which this is a case.
getParentType()372 PropertyType getParentType() const {
373 return get()->getValueAsDef(TypeFieldName);
374 }
375
getTableGenNodeClassName()376 static llvm::StringRef getTableGenNodeClassName() {
377 return TypeCaseClassName;
378 }
379 };
380
381 /// A property of an AST node.
382 class Property : public WrappedRecord {
383 public:
WrappedRecord(record)384 Property(llvm::Record *record = nullptr) : WrappedRecord(record) {}
385
386 /// Return the name of this property.
getName()387 llvm::StringRef getName() const {
388 return get()->getValueAsString(NameFieldName);
389 }
390
391 /// Return the type of this property.
getType()392 PropertyType getType() const {
393 return get()->getValueAsDef(TypeFieldName);
394 }
395
396 /// Return the class of which this is a property.
getClass()397 HasProperties getClass() const {
398 return get()->getValueAsDef(ClassFieldName);
399 }
400
401 /// Return the code for reading this property.
getReadCode()402 llvm::StringRef getReadCode() const {
403 return get()->getValueAsString(ReadFieldName);
404 }
405
406 /// Return the code for determining whether to add this property.
getCondition()407 llvm::StringRef getCondition() const {
408 return get()->getValueAsString(ConditionalCodeFieldName);
409 }
410
getTableGenNodeClassName()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).
418 class ReadHelperRule : public WrappedRecord {
419 public:
WrappedRecord(record)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.
getClass()424 HasProperties getClass() const {
425 return get()->getValueAsDef(ClassFieldName);
426 }
427
getHelperCode()428 llvm::StringRef getHelperCode() const {
429 return get()->getValueAsString(HelperCodeFieldName);
430 }
431
getTableGenNodeClassName()432 static llvm::StringRef getTableGenNodeClassName() {
433 return ReadHelperRuleClassName;
434 }
435 };
436
437 /// A rule for how to create an AST node from its properties.
438 class CreationRule : public WrappedRecord {
439 public:
WrappedRecord(record)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.
getClass()444 HasProperties getClass() const {
445 return get()->getValueAsDef(ClassFieldName);
446 }
447
getCreationCode()448 llvm::StringRef getCreationCode() const {
449 return get()->getValueAsString(CreateFieldName);
450 }
451
getTableGenNodeClassName()452 static llvm::StringRef getTableGenNodeClassName() {
453 return CreationRuleClassName;
454 }
455 };
456
457 /// A rule which overrides the standard rules for serializing an AST node.
458 class OverrideRule : public WrappedRecord {
459 public:
WrappedRecord(record)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.
getClass()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.
getIgnoredProperties()471 std::vector<llvm::StringRef> getIgnoredProperties() const {
472 return get()->getValueAsListOfStrings(IgnoredPropertiesFieldName);
473 }
474
getTableGenNodeClassName()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.
482 template <class NodeClass>
483 using ASTNodeHierarchyVisitor =
484 llvm::function_ref<void(NodeClass node, NodeClass base)>;
485
486 void visitASTNodeHierarchyImpl(llvm::RecordKeeper &records,
487 llvm::StringRef nodeClassName,
488 ASTNodeHierarchyVisitor<ASTNode> visit);
489
490 template <class NodeClass>
visitASTNodeHierarchy(llvm::RecordKeeper & records,ASTNodeHierarchyVisitor<NodeClass> visit)491 void 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