summaryrefslogtreecommitdiff
path: root/clang/utils/TableGen/ASTTableGen.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang/utils/TableGen/ASTTableGen.h')
-rw-r--r--clang/utils/TableGen/ASTTableGen.h502
1 files changed, 502 insertions, 0 deletions
diff --git a/clang/utils/TableGen/ASTTableGen.h b/clang/utils/TableGen/ASTTableGen.h
new file mode 100644
index 000000000000..ab9429f3feee
--- /dev/null
+++ b/clang/utils/TableGen/ASTTableGen.h
@@ -0,0 +1,502 @@
+//=== ASTTableGen.h - Common definitions for AST node tablegen --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_AST_TABLEGEN_H
+#define CLANG_AST_TABLEGEN_H
+
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/STLExtras.h"
+
+// These are spellings in the tblgen files.
+
+#define HasPropertiesClassName "HasProperties"
+
+// ASTNodes and their common fields. `Base` is actually defined
+// in subclasses, but it's still common across the hierarchies.
+#define ASTNodeClassName "ASTNode"
+#define BaseFieldName "Base"
+#define AbstractFieldName "Abstract"
+
+// Comment node hierarchy.
+#define CommentNodeClassName "CommentNode"
+
+// Decl node hierarchy.
+#define DeclNodeClassName "DeclNode"
+#define DeclContextNodeClassName "DeclContext"
+
+// Stmt node hierarchy.
+#define StmtNodeClassName "StmtNode"
+
+// Type node hierarchy.
+#define TypeNodeClassName "TypeNode"
+#define AlwaysDependentClassName "AlwaysDependent"
+#define NeverCanonicalClassName "NeverCanonical"
+#define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
+#define LeafTypeClassName "LeafType"
+
+// Cases of various non-ASTNode structured types like DeclarationName.
+#define TypeKindClassName "PropertyTypeKind"
+#define KindTypeFieldName "KindType"
+#define KindPropertyNameFieldName "KindPropertyName"
+#define TypeCaseClassName "PropertyTypeCase"
+
+// Properties of AST nodes.
+#define PropertyClassName "Property"
+#define ClassFieldName "Class"
+#define NameFieldName "Name"
+#define TypeFieldName "Type"
+#define ReadFieldName "Read"
+
+// Types of properties.
+#define PropertyTypeClassName "PropertyType"
+#define CXXTypeNameFieldName "CXXName"
+#define PassByReferenceFieldName "PassByReference"
+#define ConstWhenWritingFieldName "ConstWhenWriting"
+#define ConditionalCodeFieldName "Conditional"
+#define PackOptionalCodeFieldName "PackOptional"
+#define UnpackOptionalCodeFieldName "UnpackOptional"
+#define BufferElementTypesFieldName "BufferElementTypes"
+#define ArrayTypeClassName "Array"
+#define ArrayElementTypeFieldName "Element"
+#define OptionalTypeClassName "Optional"
+#define OptionalElementTypeFieldName "Element"
+#define SubclassPropertyTypeClassName "SubclassPropertyType"
+#define SubclassBaseTypeFieldName "Base"
+#define SubclassClassNameFieldName "SubclassName"
+#define EnumPropertyTypeClassName "EnumPropertyType"
+
+// Write helper rules.
+#define ReadHelperRuleClassName "ReadHelper"
+#define HelperCodeFieldName "Code"
+
+// Creation rules.
+#define CreationRuleClassName "Creator"
+#define CreateFieldName "Create"
+
+// Override rules.
+#define OverrideRuleClassName "Override"
+#define IgnoredPropertiesFieldName "IgnoredProperties"
+
+namespace clang {
+namespace tblgen {
+
+class WrappedRecord {
+ llvm::Record *Record;
+
+protected:
+ WrappedRecord(llvm::Record *record = nullptr) : Record(record) {}
+
+ llvm::Record *get() const {
+ assert(Record && "accessing null record");
+ return Record;
+ }
+
+public:
+ llvm::Record *getRecord() const { return Record; }
+
+ explicit operator bool() const { return Record != nullptr; }
+
+ llvm::ArrayRef<llvm::SMLoc> getLoc() const {
+ return get()->getLoc();
+ }
+
+ /// Does the node inherit from the given TableGen class?
+ bool isSubClassOf(llvm::StringRef className) const {
+ return get()->isSubClassOf(className);
+ }
+
+ template <class NodeClass>
+ NodeClass getAs() const {
+ return (isSubClassOf(NodeClass::getTableGenNodeClassName())
+ ? NodeClass(get()) : NodeClass());
+ }
+
+ friend bool operator<(WrappedRecord lhs, WrappedRecord rhs) {
+ assert(lhs && rhs && "sorting null nodes");
+ return lhs.get()->getName() < rhs.get()->getName();
+ }
+ friend bool operator>(WrappedRecord lhs, WrappedRecord rhs) {
+ return rhs < lhs;
+ }
+ friend bool operator<=(WrappedRecord lhs, WrappedRecord rhs) {
+ return !(rhs < lhs);
+ }
+ friend bool operator>=(WrappedRecord lhs, WrappedRecord rhs) {
+ return !(lhs < rhs);
+ }
+ friend bool operator==(WrappedRecord lhs, WrappedRecord rhs) {
+ // This should handle null nodes.
+ return lhs.getRecord() == rhs.getRecord();
+ }
+ friend bool operator!=(WrappedRecord lhs, WrappedRecord rhs) {
+ return !(lhs == rhs);
+ }
+};
+
+/// Anything in the AST that has properties.
+class HasProperties : public WrappedRecord {
+public:
+ static constexpr llvm::StringRef ClassName = HasPropertiesClassName;
+
+ HasProperties(llvm::Record *record = nullptr) : WrappedRecord(record) {}
+
+ llvm::StringRef getName() const;
+
+ static llvm::StringRef getTableGenNodeClassName() {
+ return HasPropertiesClassName;
+ }
+};
+
+/// An (optional) reference to a TableGen node representing a class
+/// in one of Clang's AST hierarchies.
+class ASTNode : public HasProperties {
+public:
+ ASTNode(llvm::Record *record = nullptr) : HasProperties(record) {}
+
+ llvm::StringRef getName() const {
+ return get()->getName();
+ }
+
+ /// Return the node for the base, if there is one.
+ ASTNode getBase() const {
+ return get()->getValueAsOptionalDef(BaseFieldName);
+ }
+
+ /// Is the corresponding class abstract?
+ bool isAbstract() const {
+ return get()->getValueAsBit(AbstractFieldName);
+ }
+
+ static llvm::StringRef getTableGenNodeClassName() {
+ return ASTNodeClassName;
+ }
+};
+
+class DeclNode : public ASTNode {
+public:
+ DeclNode(llvm::Record *record = nullptr) : ASTNode(record) {}
+
+ llvm::StringRef getId() const;
+ std::string getClassName() const;
+ DeclNode getBase() const { return DeclNode(ASTNode::getBase().getRecord()); }
+
+ static llvm::StringRef getASTHierarchyName() {
+ return "Decl";
+ }
+ static llvm::StringRef getASTIdTypeName() {
+ return "Decl::Kind";
+ }
+ static llvm::StringRef getASTIdAccessorName() {
+ return "getKind";
+ }
+ static llvm::StringRef getTableGenNodeClassName() {
+ return DeclNodeClassName;
+ }
+};
+
+class TypeNode : public ASTNode {
+public:
+ TypeNode(llvm::Record *record = nullptr) : ASTNode(record) {}
+
+ llvm::StringRef getId() const;
+ llvm::StringRef getClassName() const;
+ TypeNode getBase() const { return TypeNode(ASTNode::getBase().getRecord()); }
+
+ static llvm::StringRef getASTHierarchyName() {
+ return "Type";
+ }
+ static llvm::StringRef getASTIdTypeName() {
+ return "Type::TypeClass";
+ }
+ static llvm::StringRef getASTIdAccessorName() {
+ return "getTypeClass";
+ }
+ static llvm::StringRef getTableGenNodeClassName() {
+ return TypeNodeClassName;
+ }
+};
+
+class StmtNode : public ASTNode {
+public:
+ StmtNode(llvm::Record *record = nullptr) : ASTNode(record) {}
+
+ std::string getId() const;
+ llvm::StringRef getClassName() const;
+ StmtNode getBase() const { return StmtNode(ASTNode::getBase().getRecord()); }
+
+ static llvm::StringRef getASTHierarchyName() {
+ return "Stmt";
+ }
+ static llvm::StringRef getASTIdTypeName() {
+ return "Stmt::StmtClass";
+ }
+ static llvm::StringRef getASTIdAccessorName() {
+ return "getStmtClass";
+ }
+ static llvm::StringRef getTableGenNodeClassName() {
+ return StmtNodeClassName;
+ }
+};
+
+/// The type of a property.
+class PropertyType : public WrappedRecord {
+public:
+ PropertyType(llvm::Record *record = nullptr) : WrappedRecord(record) {}
+
+ /// Is this a generic specialization (i.e. `Array<T>` or `Optional<T>`)?
+ bool isGenericSpecialization() const {
+ return get()->isAnonymous();
+ }
+
+ /// The abstract type name of the property. Doesn't work for generic
+ /// specializations.
+ llvm::StringRef getAbstractTypeName() const {
+ return get()->getName();
+ }
+
+ /// The C++ type name of the property. Doesn't work for generic
+ /// specializations.
+ llvm::StringRef getCXXTypeName() const {
+ return get()->getValueAsString(CXXTypeNameFieldName);
+ }
+ void emitCXXValueTypeName(bool forRead, llvm::raw_ostream &out) const;
+
+ /// Whether the C++ type should be passed around by reference.
+ bool shouldPassByReference() const {
+ return get()->getValueAsBit(PassByReferenceFieldName);
+ }
+
+ /// Whether the C++ type should have 'const' prepended when working with
+ /// a value of the type being written.
+ bool isConstWhenWriting() const {
+ return get()->getValueAsBit(ConstWhenWritingFieldName);
+ }
+
+ /// If this is `Array<T>`, return `T`; otherwise return null.
+ PropertyType getArrayElementType() const {
+ if (isSubClassOf(ArrayTypeClassName))
+ return get()->getValueAsDef(ArrayElementTypeFieldName);
+ return nullptr;
+ }
+
+ /// If this is `Optional<T>`, return `T`; otherwise return null.
+ PropertyType getOptionalElementType() const {
+ if (isSubClassOf(OptionalTypeClassName))
+ return get()->getValueAsDef(OptionalElementTypeFieldName);
+ return nullptr;
+ }
+
+ /// If this is a subclass type, return its superclass type.
+ PropertyType getSuperclassType() const {
+ if (isSubClassOf(SubclassPropertyTypeClassName))
+ return get()->getValueAsDef(SubclassBaseTypeFieldName);
+ return nullptr;
+ }
+
+ // Given that this is a subclass type, return the C++ name of its
+ // subclass type. This is just the bare class name, suitable for
+ // use in `cast<>`.
+ llvm::StringRef getSubclassClassName() const {
+ return get()->getValueAsString(SubclassClassNameFieldName);
+ }
+
+ /// Does this represent an enum type?
+ bool isEnum() const {
+ return isSubClassOf(EnumPropertyTypeClassName);
+ }
+
+ llvm::StringRef getPackOptionalCode() const {
+ return get()->getValueAsString(PackOptionalCodeFieldName);
+ }
+
+ llvm::StringRef getUnpackOptionalCode() const {
+ return get()->getValueAsString(UnpackOptionalCodeFieldName);
+ }
+
+ std::vector<llvm::Record*> getBufferElementTypes() const {
+ return get()->getValueAsListOfDefs(BufferElementTypesFieldName);
+ }
+
+ static llvm::StringRef getTableGenNodeClassName() {
+ return PropertyTypeClassName;
+ }
+};
+
+/// A rule for returning the kind of a type.
+class TypeKindRule : public WrappedRecord {
+public:
+ TypeKindRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
+
+ /// Return the type to which this applies.
+ PropertyType getParentType() const {
+ return get()->getValueAsDef(TypeFieldName);
+ }
+
+ /// Return the type of the kind.
+ PropertyType getKindType() const {
+ return get()->getValueAsDef(KindTypeFieldName);
+ }
+
+ /// Return the name to use for the kind property.
+ llvm::StringRef getKindPropertyName() const {
+ return get()->getValueAsString(KindPropertyNameFieldName);
+ }
+
+ /// Return the code for reading the kind value.
+ llvm::StringRef getReadCode() const {
+ return get()->getValueAsString(ReadFieldName);
+ }
+
+ static llvm::StringRef getTableGenNodeClassName() {
+ return TypeKindClassName;
+ }
+};
+
+/// An implementation case of a property type.
+class TypeCase : public HasProperties {
+public:
+ TypeCase(llvm::Record *record = nullptr) : HasProperties(record) {}
+
+ /// Return the name of this case.
+ llvm::StringRef getCaseName() const {
+ return get()->getValueAsString(NameFieldName);
+ }
+
+ /// Return the type of which this is a case.
+ PropertyType getParentType() const {
+ return get()->getValueAsDef(TypeFieldName);
+ }
+
+ static llvm::StringRef getTableGenNodeClassName() {
+ return TypeCaseClassName;
+ }
+};
+
+/// A property of an AST node.
+class Property : public WrappedRecord {
+public:
+ Property(llvm::Record *record = nullptr) : WrappedRecord(record) {}
+
+ /// Return the name of this property.
+ llvm::StringRef getName() const {
+ return get()->getValueAsString(NameFieldName);
+ }
+
+ /// Return the type of this property.
+ PropertyType getType() const {
+ return get()->getValueAsDef(TypeFieldName);
+ }
+
+ /// Return the class of which this is a property.
+ HasProperties getClass() const {
+ return get()->getValueAsDef(ClassFieldName);
+ }
+
+ /// Return the code for reading this property.
+ llvm::StringRef getReadCode() const {
+ return get()->getValueAsString(ReadFieldName);
+ }
+
+ /// Return the code for determining whether to add this property.
+ llvm::StringRef getCondition() const {
+ return get()->getValueAsString(ConditionalCodeFieldName);
+ }
+
+ static llvm::StringRef getTableGenNodeClassName() {
+ return PropertyClassName;
+ }
+};
+
+/// A rule for running some helper code for reading properties from
+/// a value (which is actually done when writing the value out).
+class ReadHelperRule : public WrappedRecord {
+public:
+ ReadHelperRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
+
+ /// Return the class for which this is a creation rule.
+ /// Should never be abstract.
+ HasProperties getClass() const {
+ return get()->getValueAsDef(ClassFieldName);
+ }
+
+ llvm::StringRef getHelperCode() const {
+ return get()->getValueAsString(HelperCodeFieldName);
+ }
+
+ static llvm::StringRef getTableGenNodeClassName() {
+ return ReadHelperRuleClassName;
+ }
+};
+
+/// A rule for how to create an AST node from its properties.
+class CreationRule : public WrappedRecord {
+public:
+ CreationRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
+
+ /// Return the class for which this is a creation rule.
+ /// Should never be abstract.
+ HasProperties getClass() const {
+ return get()->getValueAsDef(ClassFieldName);
+ }
+
+ llvm::StringRef getCreationCode() const {
+ return get()->getValueAsString(CreateFieldName);
+ }
+
+ static llvm::StringRef getTableGenNodeClassName() {
+ return CreationRuleClassName;
+ }
+};
+
+/// A rule which overrides the standard rules for serializing an AST node.
+class OverrideRule : public WrappedRecord {
+public:
+ OverrideRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
+
+ /// Return the class for which this is an override rule.
+ /// Should never be abstract.
+ HasProperties getClass() const {
+ return get()->getValueAsDef(ClassFieldName);
+ }
+
+ /// Return a set of properties that are unnecessary when serializing
+ /// this AST node. Generally this is used for inherited properties
+ /// that are derived for this subclass.
+ std::vector<llvm::StringRef> getIgnoredProperties() const {
+ return get()->getValueAsListOfStrings(IgnoredPropertiesFieldName);
+ }
+
+ static llvm::StringRef getTableGenNodeClassName() {
+ return OverrideRuleClassName;
+ }
+};
+
+/// A visitor for an AST node hierarchy. Note that `base` can be null for
+/// the root class.
+template <class NodeClass>
+using ASTNodeHierarchyVisitor =
+ llvm::function_ref<void(NodeClass node, NodeClass base)>;
+
+void visitASTNodeHierarchyImpl(llvm::RecordKeeper &records,
+ llvm::StringRef nodeClassName,
+ ASTNodeHierarchyVisitor<ASTNode> visit);
+
+template <class NodeClass>
+void visitASTNodeHierarchy(llvm::RecordKeeper &records,
+ ASTNodeHierarchyVisitor<NodeClass> visit) {
+ visitASTNodeHierarchyImpl(records, NodeClass::getTableGenNodeClassName(),
+ [visit](ASTNode node, ASTNode base) {
+ visit(NodeClass(node.getRecord()),
+ NodeClass(base.getRecord()));
+ });
+}
+
+} // end namespace clang::tblgen
+} // end namespace clang
+
+#endif