1 //=== ASTTableGen.h - Common definitions for AST node tablegen --*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef CLANG_AST_TABLEGEN_H
10 #define CLANG_AST_TABLEGEN_H
12 #include "llvm/TableGen/Record.h"
13 #include "llvm/ADT/STLExtras.h"
16 // These are spellings in the tblgen files.
18 #define HasPropertiesClassName "HasProperties"
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"
26 // Comment node hierarchy.
27 #define CommentNodeClassName "CommentNode"
29 // Decl node hierarchy.
30 #define DeclNodeClassName "DeclNode"
31 #define DeclContextNodeClassName "DeclContext"
33 // Stmt node hierarchy.
34 #define StmtNodeClassName "StmtNode"
36 // Type node hierarchy.
37 #define TypeNodeClassName "TypeNode"
38 #define AlwaysDependentClassName "AlwaysDependent"
39 #define NeverCanonicalClassName "NeverCanonical"
40 #define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
41 #define LeafTypeClassName "LeafType"
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"
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"
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"
74 // Write helper rules.
75 #define ReadHelperRuleClassName "ReadHelper"
76 #define HelperCodeFieldName "Code"
79 #define CreationRuleClassName "Creator"
80 #define CreateFieldName "Create"
83 #define OverrideRuleClassName "Override"
84 #define IgnoredPropertiesFieldName "IgnoredProperties"
93 WrappedRecord(llvm::Record
*record
= nullptr) : Record(record
) {}
95 llvm::Record
*get() const {
96 assert(Record
&& "accessing null record");
101 llvm::Record
*getRecord() const { return Record
; }
103 explicit operator bool() const { return Record
!= nullptr; }
105 llvm::ArrayRef
<llvm::SMLoc
> getLoc() const {
106 return get()->getLoc();
109 /// Does the node inherit from the given TableGen class?
110 bool isSubClassOf(llvm::StringRef className
) const {
111 return get()->isSubClassOf(className
);
114 template <class NodeClass
>
115 NodeClass
getAs() const {
116 return (isSubClassOf(NodeClass::getTableGenNodeClassName())
117 ? NodeClass(get()) : NodeClass());
120 friend bool operator<(WrappedRecord lhs
, WrappedRecord rhs
) {
121 assert(lhs
&& rhs
&& "sorting null nodes");
122 return lhs
.get()->getName() < rhs
.get()->getName();
124 friend bool operator>(WrappedRecord lhs
, WrappedRecord rhs
) {
127 friend bool operator<=(WrappedRecord lhs
, WrappedRecord rhs
) {
130 friend bool operator>=(WrappedRecord lhs
, WrappedRecord rhs
) {
133 friend bool operator==(WrappedRecord lhs
, WrappedRecord rhs
) {
134 // This should handle null nodes.
135 return lhs
.getRecord() == rhs
.getRecord();
137 friend bool operator!=(WrappedRecord lhs
, WrappedRecord rhs
) {
138 return !(lhs
== rhs
);
142 /// Anything in the AST that has properties.
143 class HasProperties
: public WrappedRecord
{
145 static constexpr llvm::StringRef ClassName
= HasPropertiesClassName
;
147 HasProperties(llvm::Record
*record
= nullptr) : WrappedRecord(record
) {}
149 llvm::StringRef
getName() const;
151 static llvm::StringRef
getTableGenNodeClassName() {
152 return HasPropertiesClassName
;
156 /// An (optional) reference to a TableGen node representing a class
157 /// in one of Clang's AST hierarchies.
158 class ASTNode
: public HasProperties
{
160 ASTNode(llvm::Record
*record
= nullptr) : HasProperties(record
) {}
162 llvm::StringRef
getName() const {
163 return get()->getName();
166 /// Return the node for the base, if there is one.
167 ASTNode
getBase() const {
168 return get()->getValueAsOptionalDef(BaseFieldName
);
171 /// Is the corresponding class abstract?
172 bool isAbstract() const {
173 return get()->getValueAsBit(AbstractFieldName
);
176 static llvm::StringRef
getTableGenNodeClassName() {
177 return ASTNodeClassName
;
181 class DeclNode
: public ASTNode
{
183 DeclNode(llvm::Record
*record
= nullptr) : ASTNode(record
) {}
185 llvm::StringRef
getId() const;
186 std::string
getClassName() const;
187 DeclNode
getBase() const { return DeclNode(ASTNode::getBase().getRecord()); }
189 static llvm::StringRef
getASTHierarchyName() {
192 static llvm::StringRef
getASTIdTypeName() {
195 static llvm::StringRef
getASTIdAccessorName() {
198 static llvm::StringRef
getTableGenNodeClassName() {
199 return DeclNodeClassName
;
203 class TypeNode
: public ASTNode
{
205 TypeNode(llvm::Record
*record
= nullptr) : ASTNode(record
) {}
207 llvm::StringRef
getId() const;
208 llvm::StringRef
getClassName() const;
209 TypeNode
getBase() const { return TypeNode(ASTNode::getBase().getRecord()); }
211 static llvm::StringRef
getASTHierarchyName() {
214 static llvm::StringRef
getASTIdTypeName() {
215 return "Type::TypeClass";
217 static llvm::StringRef
getASTIdAccessorName() {
218 return "getTypeClass";
220 static llvm::StringRef
getTableGenNodeClassName() {
221 return TypeNodeClassName
;
225 class StmtNode
: public ASTNode
{
227 StmtNode(llvm::Record
*record
= nullptr) : ASTNode(record
) {}
229 std::string
getId() const;
230 llvm::StringRef
getClassName() const;
231 StmtNode
getBase() const { return StmtNode(ASTNode::getBase().getRecord()); }
233 static llvm::StringRef
getASTHierarchyName() {
236 static llvm::StringRef
getASTIdTypeName() {
237 return "Stmt::StmtClass";
239 static llvm::StringRef
getASTIdAccessorName() {
240 return "getStmtClass";
242 static llvm::StringRef
getTableGenNodeClassName() {
243 return StmtNodeClassName
;
247 /// The type of a property.
248 class PropertyType
: public WrappedRecord
{
250 PropertyType(llvm::Record
*record
= nullptr) : WrappedRecord(record
) {}
252 /// Is this a generic specialization (i.e. `Array<T>` or `Optional<T>`)?
253 bool isGenericSpecialization() const {
254 return get()->isAnonymous();
257 /// The abstract type name of the property. Doesn't work for generic
259 llvm::StringRef
getAbstractTypeName() const {
260 return get()->getName();
263 /// The C++ type name of the property. Doesn't work for generic
265 llvm::StringRef
getCXXTypeName() const {
266 return get()->getValueAsString(CXXTypeNameFieldName
);
268 void emitCXXValueTypeName(bool forRead
, llvm::raw_ostream
&out
) const;
270 /// Whether the C++ type should be passed around by reference.
271 bool shouldPassByReference() const {
272 return get()->getValueAsBit(PassByReferenceFieldName
);
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
);
281 /// If this is `Array<T>`, return `T`; otherwise return null.
282 PropertyType
getArrayElementType() const {
283 if (isSubClassOf(ArrayTypeClassName
))
284 return get()->getValueAsDef(ArrayElementTypeFieldName
);
288 /// If this is `Optional<T>`, return `T`; otherwise return null.
289 PropertyType
getOptionalElementType() const {
290 if (isSubClassOf(OptionalTypeClassName
))
291 return get()->getValueAsDef(OptionalElementTypeFieldName
);
295 /// If this is a subclass type, return its superclass type.
296 PropertyType
getSuperclassType() const {
297 if (isSubClassOf(SubclassPropertyTypeClassName
))
298 return get()->getValueAsDef(SubclassBaseTypeFieldName
);
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
305 llvm::StringRef
getSubclassClassName() const {
306 return get()->getValueAsString(SubclassClassNameFieldName
);
309 /// Does this represent an enum type?
310 bool isEnum() const {
311 return isSubClassOf(EnumPropertyTypeClassName
);
314 llvm::StringRef
getPackOptionalCode() const {
315 return get()->getValueAsString(PackOptionalCodeFieldName
);
318 llvm::StringRef
getUnpackOptionalCode() const {
319 return get()->getValueAsString(UnpackOptionalCodeFieldName
);
322 std::vector
<llvm::Record
*> getBufferElementTypes() const {
323 return get()->getValueAsListOfDefs(BufferElementTypesFieldName
);
326 static llvm::StringRef
getTableGenNodeClassName() {
327 return PropertyTypeClassName
;
331 /// A rule for returning the kind of a type.
332 class TypeKindRule
: public WrappedRecord
{
334 TypeKindRule(llvm::Record
*record
= nullptr) : WrappedRecord(record
) {}
336 /// Return the type to which this applies.
337 PropertyType
getParentType() const {
338 return get()->getValueAsDef(TypeFieldName
);
341 /// Return the type of the kind.
342 PropertyType
getKindType() const {
343 return get()->getValueAsDef(KindTypeFieldName
);
346 /// Return the name to use for the kind property.
347 llvm::StringRef
getKindPropertyName() const {
348 return get()->getValueAsString(KindPropertyNameFieldName
);
351 /// Return the code for reading the kind value.
352 llvm::StringRef
getReadCode() const {
353 return get()->getValueAsString(ReadFieldName
);
356 static llvm::StringRef
getTableGenNodeClassName() {
357 return TypeKindClassName
;
361 /// An implementation case of a property type.
362 class TypeCase
: public HasProperties
{
364 TypeCase(llvm::Record
*record
= nullptr) : HasProperties(record
) {}
366 /// Return the name of this case.
367 llvm::StringRef
getCaseName() const {
368 return get()->getValueAsString(NameFieldName
);
371 /// Return the type of which this is a case.
372 PropertyType
getParentType() const {
373 return get()->getValueAsDef(TypeFieldName
);
376 static llvm::StringRef
getTableGenNodeClassName() {
377 return TypeCaseClassName
;
381 /// A property of an AST node.
382 class Property
: public WrappedRecord
{
384 Property(llvm::Record
*record
= nullptr) : WrappedRecord(record
) {}
386 /// Return the name of this property.
387 llvm::StringRef
getName() const {
388 return get()->getValueAsString(NameFieldName
);
391 /// Return the type of this property.
392 PropertyType
getType() const {
393 return get()->getValueAsDef(TypeFieldName
);
396 /// Return the class of which this is a property.
397 HasProperties
getClass() const {
398 return get()->getValueAsDef(ClassFieldName
);
401 /// Return the code for reading this property.
402 llvm::StringRef
getReadCode() const {
403 return get()->getValueAsString(ReadFieldName
);
406 /// Return the code for determining whether to add this property.
407 llvm::StringRef
getCondition() const {
408 return get()->getValueAsString(ConditionalCodeFieldName
);
411 static llvm::StringRef
getTableGenNodeClassName() {
412 return PropertyClassName
;
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
{
420 ReadHelperRule(llvm::Record
*record
= nullptr) : WrappedRecord(record
) {}
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
);
428 llvm::StringRef
getHelperCode() const {
429 return get()->getValueAsString(HelperCodeFieldName
);
432 static llvm::StringRef
getTableGenNodeClassName() {
433 return ReadHelperRuleClassName
;
437 /// A rule for how to create an AST node from its properties.
438 class CreationRule
: public WrappedRecord
{
440 CreationRule(llvm::Record
*record
= nullptr) : WrappedRecord(record
) {}
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
);
448 llvm::StringRef
getCreationCode() const {
449 return get()->getValueAsString(CreateFieldName
);
452 static llvm::StringRef
getTableGenNodeClassName() {
453 return CreationRuleClassName
;
457 /// A rule which overrides the standard rules for serializing an AST node.
458 class OverrideRule
: public WrappedRecord
{
460 OverrideRule(llvm::Record
*record
= nullptr) : WrappedRecord(record
) {}
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
);
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
);
475 static llvm::StringRef
getTableGenNodeClassName() {
476 return OverrideRuleClassName
;
480 /// A visitor for an AST node hierarchy. Note that `base` can be null for
482 template <class NodeClass
>
483 using ASTNodeHierarchyVisitor
=
484 llvm::function_ref
<void(NodeClass node
, NodeClass base
)>;
486 void visitASTNodeHierarchyImpl(llvm::RecordKeeper
&records
,
487 llvm::StringRef nodeClassName
,
488 ASTNodeHierarchyVisitor
<ASTNode
> visit
);
490 template <class NodeClass
>
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()));
500 } // end namespace clang::tblgen
501 } // end namespace clang