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