blob: ab9429f3feee0e3d4d96310830d349308c97da07 [file] [log] [blame]
John McCallb6f03a52019-10-25 18:38:07 -07001//=== ASTTableGen.h - Common definitions for AST node tablegen --*- C++ -*-===//
John McCallbaf91d02019-10-25 16:28:03 -07002//
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
John McCallb6f03a52019-10-25 18:38:07 -07009#ifndef CLANG_AST_TABLEGEN_H
10#define CLANG_AST_TABLEGEN_H
John McCallbaf91d02019-10-25 16:28:03 -070011
12#include "llvm/TableGen/Record.h"
13#include "llvm/ADT/STLExtras.h"
14
15// These are spellings in the tblgen files.
16
John McCallefd0dfb2019-12-16 02:10:15 -050017#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"
John McCallbaf91d02019-10-25 16:28:03 -070022#define BaseFieldName "Base"
John McCall91dd67e2019-10-28 09:45:53 -070023#define AbstractFieldName "Abstract"
John McCallbaf91d02019-10-25 16:28:03 -070024
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"
John McCall91dd67e2019-10-28 09:45:53 -070041
John McCallefd0dfb2019-12-16 02:10:15 -050042// 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
John McCall6404bd22019-12-13 21:52:16 -050048// Properties of AST nodes.
John McCall91dd67e2019-10-28 09:45:53 -070049#define PropertyClassName "Property"
50#define ClassFieldName "Class"
John McCall6404bd22019-12-13 21:52:16 -050051#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"
John McCall6887ccf2019-12-16 03:51:16 -050060#define ConditionalCodeFieldName "Conditional"
John McCall6404bd22019-12-13 21:52:16 -050061#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
John McCall256ec992019-12-16 02:56:32 -050073// Write helper rules.
74#define ReadHelperRuleClassName "ReadHelper"
75#define HelperCodeFieldName "Code"
76
John McCall6404bd22019-12-13 21:52:16 -050077// Creation rules.
78#define CreationRuleClassName "Creator"
79#define CreateFieldName "Create"
80
81// Override rules.
82#define OverrideRuleClassName "Override"
83#define IgnoredPropertiesFieldName "IgnoredProperties"
John McCall91dd67e2019-10-28 09:45:53 -070084
85namespace clang {
86namespace tblgen {
87
John McCall30066e52019-12-10 16:20:36 -050088class WrappedRecord {
John McCall91dd67e2019-10-28 09:45:53 -070089 llvm::Record *Record;
John McCall30066e52019-12-10 16:20:36 -050090
91protected:
92 WrappedRecord(llvm::Record *record = nullptr) : Record(record) {}
93
94 llvm::Record *get() const {
95 assert(Record && "accessing null record");
96 return Record;
97 }
98
John McCall91dd67e2019-10-28 09:45:53 -070099public:
John McCall30066e52019-12-10 16:20:36 -0500100 llvm::Record *getRecord() const { return Record; }
John McCall91dd67e2019-10-28 09:45:53 -0700101
102 explicit operator bool() const { return Record != nullptr; }
103
John McCall91dd67e2019-10-28 09:45:53 -0700104 llvm::ArrayRef<llvm::SMLoc> getLoc() const {
John McCall30066e52019-12-10 16:20:36 -0500105 return get()->getLoc();
John McCall91dd67e2019-10-28 09:45:53 -0700106 }
107
108 /// Does the node inherit from the given TableGen class?
109 bool isSubClassOf(llvm::StringRef className) const {
John McCall30066e52019-12-10 16:20:36 -0500110 return get()->isSubClassOf(className);
111 }
John McCallefd0dfb2019-12-16 02:10:15 -0500112
113 template <class NodeClass>
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.
142class HasProperties : public WrappedRecord {
143public:
144 static constexpr llvm::StringRef ClassName = HasPropertiesClassName;
145
146 HasProperties(llvm::Record *record = nullptr) : WrappedRecord(record) {}
147
148 llvm::StringRef getName() const;
149
150 static llvm::StringRef getTableGenNodeClassName() {
151 return HasPropertiesClassName;
152 }
John McCall30066e52019-12-10 16:20:36 -0500153};
154
155/// An (optional) reference to a TableGen node representing a class
156/// in one of Clang's AST hierarchies.
John McCallefd0dfb2019-12-16 02:10:15 -0500157class ASTNode : public HasProperties {
John McCall30066e52019-12-10 16:20:36 -0500158public:
John McCallefd0dfb2019-12-16 02:10:15 -0500159 ASTNode(llvm::Record *record = nullptr) : HasProperties(record) {}
John McCall30066e52019-12-10 16:20:36 -0500160
161 llvm::StringRef getName() const {
162 return get()->getName();
163 }
164
165 /// Return the node for the base, if there is one.
166 ASTNode getBase() const {
167 return get()->getValueAsOptionalDef(BaseFieldName);
168 }
169
170 /// Is the corresponding class abstract?
171 bool isAbstract() const {
172 return get()->getValueAsBit(AbstractFieldName);
John McCall91dd67e2019-10-28 09:45:53 -0700173 }
174
John McCallefd0dfb2019-12-16 02:10:15 -0500175 static llvm::StringRef getTableGenNodeClassName() {
176 return ASTNodeClassName;
John McCall91dd67e2019-10-28 09:45:53 -0700177 }
John McCall91dd67e2019-10-28 09:45:53 -0700178};
179
180class DeclNode : public ASTNode {
181public:
182 DeclNode(llvm::Record *record = nullptr) : ASTNode(record) {}
183
184 llvm::StringRef getId() const;
185 std::string getClassName() const;
186 DeclNode getBase() const { return DeclNode(ASTNode::getBase().getRecord()); }
John McCallf6da0cf2019-12-10 16:23:43 -0500187
188 static llvm::StringRef getASTHierarchyName() {
189 return "Decl";
190 }
191 static llvm::StringRef getASTIdTypeName() {
192 return "Decl::Kind";
193 }
194 static llvm::StringRef getASTIdAccessorName() {
195 return "getKind";
196 }
197 static llvm::StringRef getTableGenNodeClassName() {
198 return DeclNodeClassName;
199 }
John McCall91dd67e2019-10-28 09:45:53 -0700200};
201
202class TypeNode : public ASTNode {
203public:
204 TypeNode(llvm::Record *record = nullptr) : ASTNode(record) {}
205
206 llvm::StringRef getId() const;
207 llvm::StringRef getClassName() const;
208 TypeNode getBase() const { return TypeNode(ASTNode::getBase().getRecord()); }
John McCallf6da0cf2019-12-10 16:23:43 -0500209
210 static llvm::StringRef getASTHierarchyName() {
211 return "Type";
212 }
213 static llvm::StringRef getASTIdTypeName() {
214 return "Type::TypeClass";
215 }
216 static llvm::StringRef getASTIdAccessorName() {
217 return "getTypeClass";
218 }
219 static llvm::StringRef getTableGenNodeClassName() {
220 return TypeNodeClassName;
221 }
John McCall91dd67e2019-10-28 09:45:53 -0700222};
223
224class StmtNode : public ASTNode {
225public:
226 StmtNode(llvm::Record *record = nullptr) : ASTNode(record) {}
227
228 std::string getId() const;
229 llvm::StringRef getClassName() const;
230 StmtNode getBase() const { return StmtNode(ASTNode::getBase().getRecord()); }
John McCallf6da0cf2019-12-10 16:23:43 -0500231
232 static llvm::StringRef getASTHierarchyName() {
233 return "Stmt";
234 }
235 static llvm::StringRef getASTIdTypeName() {
236 return "Stmt::StmtClass";
237 }
238 static llvm::StringRef getASTIdAccessorName() {
239 return "getStmtClass";
240 }
241 static llvm::StringRef getTableGenNodeClassName() {
242 return StmtNodeClassName;
243 }
John McCall91dd67e2019-10-28 09:45:53 -0700244};
245
John McCall6404bd22019-12-13 21:52:16 -0500246/// The type of a property.
247class PropertyType : public WrappedRecord {
248public:
249 PropertyType(llvm::Record *record = nullptr) : WrappedRecord(record) {}
250
251 /// Is this a generic specialization (i.e. `Array<T>` or `Optional<T>`)?
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.
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.
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.
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.
276 bool isConstWhenWriting() const {
277 return get()->getValueAsBit(ConstWhenWritingFieldName);
278 }
279
280 /// If this is `Array<T>`, return `T`; otherwise return null.
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.
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.
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<>`.
304 llvm::StringRef getSubclassClassName() const {
305 return get()->getValueAsString(SubclassClassNameFieldName);
306 }
307
308 /// Does this represent an enum type?
309 bool isEnum() const {
310 return isSubClassOf(EnumPropertyTypeClassName);
311 }
312
313 llvm::StringRef getPackOptionalCode() const {
314 return get()->getValueAsString(PackOptionalCodeFieldName);
315 }
316
317 llvm::StringRef getUnpackOptionalCode() const {
318 return get()->getValueAsString(UnpackOptionalCodeFieldName);
319 }
320
321 std::vector<llvm::Record*> getBufferElementTypes() const {
322 return get()->getValueAsListOfDefs(BufferElementTypesFieldName);
323 }
John McCallefd0dfb2019-12-16 02:10:15 -0500324
325 static llvm::StringRef getTableGenNodeClassName() {
326 return PropertyTypeClassName;
327 }
328};
329
330/// A rule for returning the kind of a type.
331class TypeKindRule : public WrappedRecord {
332public:
333 TypeKindRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
334
335 /// Return the type to which this applies.
336 PropertyType getParentType() const {
337 return get()->getValueAsDef(TypeFieldName);
338 }
339
340 /// Return the type of the kind.
341 PropertyType getKindType() const {
342 return get()->getValueAsDef(KindTypeFieldName);
343 }
344
345 /// Return the name to use for the kind property.
346 llvm::StringRef getKindPropertyName() const {
347 return get()->getValueAsString(KindPropertyNameFieldName);
348 }
349
350 /// Return the code for reading the kind value.
351 llvm::StringRef getReadCode() const {
352 return get()->getValueAsString(ReadFieldName);
353 }
354
355 static llvm::StringRef getTableGenNodeClassName() {
356 return TypeKindClassName;
357 }
358};
359
360/// An implementation case of a property type.
361class TypeCase : public HasProperties {
362public:
363 TypeCase(llvm::Record *record = nullptr) : HasProperties(record) {}
364
365 /// Return the name of this case.
366 llvm::StringRef getCaseName() const {
367 return get()->getValueAsString(NameFieldName);
368 }
369
370 /// Return the type of which this is a case.
371 PropertyType getParentType() const {
372 return get()->getValueAsDef(TypeFieldName);
373 }
374
375 static llvm::StringRef getTableGenNodeClassName() {
376 return TypeCaseClassName;
377 }
John McCall6404bd22019-12-13 21:52:16 -0500378};
379
380/// A property of an AST node.
381class Property : public WrappedRecord {
382public:
383 Property(llvm::Record *record = nullptr) : WrappedRecord(record) {}
384
385 /// Return the name of this property.
386 llvm::StringRef getName() const {
387 return get()->getValueAsString(NameFieldName);
388 }
389
390 /// Return the type of this property.
391 PropertyType getType() const {
392 return get()->getValueAsDef(TypeFieldName);
393 }
394
395 /// Return the class of which this is a property.
John McCall256ec992019-12-16 02:56:32 -0500396 HasProperties getClass() const {
John McCall6404bd22019-12-13 21:52:16 -0500397 return get()->getValueAsDef(ClassFieldName);
398 }
399
400 /// Return the code for reading this property.
401 llvm::StringRef getReadCode() const {
402 return get()->getValueAsString(ReadFieldName);
403 }
John McCallefd0dfb2019-12-16 02:10:15 -0500404
John McCall6887ccf2019-12-16 03:51:16 -0500405 /// Return the code for determining whether to add this property.
406 llvm::StringRef getCondition() const {
407 return get()->getValueAsString(ConditionalCodeFieldName);
408 }
409
John McCallefd0dfb2019-12-16 02:10:15 -0500410 static llvm::StringRef getTableGenNodeClassName() {
411 return PropertyClassName;
412 }
John McCall6404bd22019-12-13 21:52:16 -0500413};
414
John McCall256ec992019-12-16 02:56:32 -0500415/// A rule for running some helper code for reading properties from
416/// a value (which is actually done when writing the value out).
417class ReadHelperRule : public WrappedRecord {
418public:
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.
423 HasProperties getClass() const {
424 return get()->getValueAsDef(ClassFieldName);
425 }
426
427 llvm::StringRef getHelperCode() const {
428 return get()->getValueAsString(HelperCodeFieldName);
429 }
430
431 static llvm::StringRef getTableGenNodeClassName() {
432 return ReadHelperRuleClassName;
433 }
434};
435
John McCall6404bd22019-12-13 21:52:16 -0500436/// A rule for how to create an AST node from its properties.
437class CreationRule : public WrappedRecord {
438public:
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.
John McCall256ec992019-12-16 02:56:32 -0500443 HasProperties getClass() const {
John McCall6404bd22019-12-13 21:52:16 -0500444 return get()->getValueAsDef(ClassFieldName);
445 }
446
447 llvm::StringRef getCreationCode() const {
448 return get()->getValueAsString(CreateFieldName);
449 }
John McCallefd0dfb2019-12-16 02:10:15 -0500450
451 static llvm::StringRef getTableGenNodeClassName() {
452 return CreationRuleClassName;
453 }
John McCall6404bd22019-12-13 21:52:16 -0500454};
455
456/// A rule which overrides the standard rules for serializing an AST node.
457class OverrideRule : public WrappedRecord {
458public:
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.
John McCall256ec992019-12-16 02:56:32 -0500463 HasProperties getClass() const {
John McCall6404bd22019-12-13 21:52:16 -0500464 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.
470 std::vector<llvm::StringRef> getIgnoredProperties() const {
471 return get()->getValueAsListOfStrings(IgnoredPropertiesFieldName);
472 }
John McCallefd0dfb2019-12-16 02:10:15 -0500473
474 static llvm::StringRef getTableGenNodeClassName() {
475 return OverrideRuleClassName;
476 }
John McCall6404bd22019-12-13 21:52:16 -0500477};
478
John McCall91dd67e2019-10-28 09:45:53 -0700479/// A visitor for an AST node hierarchy. Note that `base` can be null for
480/// the root class.
481template <class NodeClass>
482using ASTNodeHierarchyVisitor =
483 llvm::function_ref<void(NodeClass node, NodeClass base)>;
484
John McCallf6da0cf2019-12-10 16:23:43 -0500485void visitASTNodeHierarchyImpl(llvm::RecordKeeper &records,
486 llvm::StringRef nodeClassName,
487 ASTNodeHierarchyVisitor<ASTNode> visit);
488
489template <class NodeClass>
John McCall91dd67e2019-10-28 09:45:53 -0700490void visitASTNodeHierarchy(llvm::RecordKeeper &records,
John McCallf6da0cf2019-12-10 16:23:43 -0500491 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}
John McCall91dd67e2019-10-28 09:45:53 -0700498
499} // end namespace clang::tblgen
500} // end namespace clang
John McCallbaf91d02019-10-25 16:28:03 -0700501
502#endif