Path: blob/main/contrib/llvm-project/clang/utils/TableGen/ASTTableGen.h
35230 views
//=== ASTTableGen.h - Common definitions for AST node tablegen --*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef CLANG_AST_TABLEGEN_H9#define CLANG_AST_TABLEGEN_H1011#include "llvm/TableGen/Record.h"12#include "llvm/ADT/STLExtras.h"13#include <optional>1415// These are spellings in the tblgen files.1617#define HasPropertiesClassName "HasProperties"1819// ASTNodes and their common fields. `Base` is actually defined20// in subclasses, but it's still common across the hierarchies.21#define ASTNodeClassName "ASTNode"22#define BaseFieldName "Base"23#define AbstractFieldName "Abstract"2425// Comment node hierarchy.26#define CommentNodeClassName "CommentNode"2728// Decl node hierarchy.29#define DeclNodeClassName "DeclNode"30#define DeclContextNodeClassName "DeclContext"3132// Stmt node hierarchy.33#define StmtNodeClassName "StmtNode"3435// Type node hierarchy.36#define TypeNodeClassName "TypeNode"37#define AlwaysDependentClassName "AlwaysDependent"38#define NeverCanonicalClassName "NeverCanonical"39#define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"40#define LeafTypeClassName "LeafType"4142// 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"4748// Properties of AST nodes.49#define PropertyClassName "Property"50#define ClassFieldName "Class"51#define NameFieldName "Name"52#define TypeFieldName "Type"53#define ReadFieldName "Read"5455// Types of properties.56#define PropertyTypeClassName "PropertyType"57#define CXXTypeNameFieldName "CXXName"58#define PassByReferenceFieldName "PassByReference"59#define ConstWhenWritingFieldName "ConstWhenWriting"60#define ConditionalCodeFieldName "Conditional"61#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"7273// Write helper rules.74#define ReadHelperRuleClassName "ReadHelper"75#define HelperCodeFieldName "Code"7677// Creation rules.78#define CreationRuleClassName "Creator"79#define CreateFieldName "Create"8081// Override rules.82#define OverrideRuleClassName "Override"83#define IgnoredPropertiesFieldName "IgnoredProperties"8485namespace clang {86namespace tblgen {8788class WrappedRecord {89llvm::Record *Record;9091protected:92WrappedRecord(llvm::Record *record = nullptr) : Record(record) {}9394llvm::Record *get() const {95assert(Record && "accessing null record");96return Record;97}9899public:100llvm::Record *getRecord() const { return Record; }101102explicit operator bool() const { return Record != nullptr; }103104llvm::ArrayRef<llvm::SMLoc> getLoc() const {105return get()->getLoc();106}107108/// Does the node inherit from the given TableGen class?109bool isSubClassOf(llvm::StringRef className) const {110return get()->isSubClassOf(className);111}112113template <class NodeClass>114NodeClass getAs() const {115return (isSubClassOf(NodeClass::getTableGenNodeClassName())116? NodeClass(get()) : NodeClass());117}118119friend bool operator<(WrappedRecord lhs, WrappedRecord rhs) {120assert(lhs && rhs && "sorting null nodes");121return lhs.get()->getName() < rhs.get()->getName();122}123friend bool operator>(WrappedRecord lhs, WrappedRecord rhs) {124return rhs < lhs;125}126friend bool operator<=(WrappedRecord lhs, WrappedRecord rhs) {127return !(rhs < lhs);128}129friend bool operator>=(WrappedRecord lhs, WrappedRecord rhs) {130return !(lhs < rhs);131}132friend bool operator==(WrappedRecord lhs, WrappedRecord rhs) {133// This should handle null nodes.134return lhs.getRecord() == rhs.getRecord();135}136friend bool operator!=(WrappedRecord lhs, WrappedRecord rhs) {137return !(lhs == rhs);138}139};140141/// Anything in the AST that has properties.142class HasProperties : public WrappedRecord {143public:144static constexpr llvm::StringRef ClassName = HasPropertiesClassName;145146HasProperties(llvm::Record *record = nullptr) : WrappedRecord(record) {}147148llvm::StringRef getName() const;149150static llvm::StringRef getTableGenNodeClassName() {151return HasPropertiesClassName;152}153};154155/// An (optional) reference to a TableGen node representing a class156/// in one of Clang's AST hierarchies.157class ASTNode : public HasProperties {158public:159ASTNode(llvm::Record *record = nullptr) : HasProperties(record) {}160161llvm::StringRef getName() const {162return get()->getName();163}164165/// Return the node for the base, if there is one.166ASTNode getBase() const {167return get()->getValueAsOptionalDef(BaseFieldName);168}169170/// Is the corresponding class abstract?171bool isAbstract() const {172return get()->getValueAsBit(AbstractFieldName);173}174175static llvm::StringRef getTableGenNodeClassName() {176return ASTNodeClassName;177}178};179180class DeclNode : public ASTNode {181public:182DeclNode(llvm::Record *record = nullptr) : ASTNode(record) {}183184llvm::StringRef getId() const;185std::string getClassName() const;186DeclNode getBase() const { return DeclNode(ASTNode::getBase().getRecord()); }187188static llvm::StringRef getASTHierarchyName() {189return "Decl";190}191static llvm::StringRef getASTIdTypeName() {192return "Decl::Kind";193}194static llvm::StringRef getASTIdAccessorName() {195return "getKind";196}197static llvm::StringRef getTableGenNodeClassName() {198return DeclNodeClassName;199}200};201202class TypeNode : public ASTNode {203public:204TypeNode(llvm::Record *record = nullptr) : ASTNode(record) {}205206llvm::StringRef getId() const;207llvm::StringRef getClassName() const;208TypeNode getBase() const { return TypeNode(ASTNode::getBase().getRecord()); }209210static llvm::StringRef getASTHierarchyName() {211return "Type";212}213static llvm::StringRef getASTIdTypeName() {214return "Type::TypeClass";215}216static llvm::StringRef getASTIdAccessorName() {217return "getTypeClass";218}219static llvm::StringRef getTableGenNodeClassName() {220return TypeNodeClassName;221}222};223224class StmtNode : public ASTNode {225public:226StmtNode(llvm::Record *record = nullptr) : ASTNode(record) {}227228std::string getId() const;229llvm::StringRef getClassName() const;230StmtNode getBase() const { return StmtNode(ASTNode::getBase().getRecord()); }231232static llvm::StringRef getASTHierarchyName() {233return "Stmt";234}235static llvm::StringRef getASTIdTypeName() {236return "Stmt::StmtClass";237}238static llvm::StringRef getASTIdAccessorName() {239return "getStmtClass";240}241static llvm::StringRef getTableGenNodeClassName() {242return StmtNodeClassName;243}244};245246/// The type of a property.247class PropertyType : public WrappedRecord {248public:249PropertyType(llvm::Record *record = nullptr) : WrappedRecord(record) {}250251/// Is this a generic specialization (i.e. `Array<T>` or `Optional<T>`)?252bool isGenericSpecialization() const {253return get()->isAnonymous();254}255256/// The abstract type name of the property. Doesn't work for generic257/// specializations.258llvm::StringRef getAbstractTypeName() const {259return get()->getName();260}261262/// The C++ type name of the property. Doesn't work for generic263/// specializations.264llvm::StringRef getCXXTypeName() const {265return get()->getValueAsString(CXXTypeNameFieldName);266}267void emitCXXValueTypeName(bool forRead, llvm::raw_ostream &out) const;268269/// Whether the C++ type should be passed around by reference.270bool shouldPassByReference() const {271return get()->getValueAsBit(PassByReferenceFieldName);272}273274/// Whether the C++ type should have 'const' prepended when working with275/// a value of the type being written.276bool isConstWhenWriting() const {277return get()->getValueAsBit(ConstWhenWritingFieldName);278}279280/// If this is `Array<T>`, return `T`; otherwise return null.281PropertyType getArrayElementType() const {282if (isSubClassOf(ArrayTypeClassName))283return get()->getValueAsDef(ArrayElementTypeFieldName);284return nullptr;285}286287/// If this is `Optional<T>`, return `T`; otherwise return null.288PropertyType getOptionalElementType() const {289if (isSubClassOf(OptionalTypeClassName))290return get()->getValueAsDef(OptionalElementTypeFieldName);291return nullptr;292}293294/// If this is a subclass type, return its superclass type.295PropertyType getSuperclassType() const {296if (isSubClassOf(SubclassPropertyTypeClassName))297return get()->getValueAsDef(SubclassBaseTypeFieldName);298return nullptr;299}300301// Given that this is a subclass type, return the C++ name of its302// subclass type. This is just the bare class name, suitable for303// use in `cast<>`.304llvm::StringRef getSubclassClassName() const {305return get()->getValueAsString(SubclassClassNameFieldName);306}307308/// Does this represent an enum type?309bool isEnum() const {310return isSubClassOf(EnumPropertyTypeClassName);311}312313llvm::StringRef getPackOptionalCode() const {314return get()->getValueAsString(PackOptionalCodeFieldName);315}316317llvm::StringRef getUnpackOptionalCode() const {318return get()->getValueAsString(UnpackOptionalCodeFieldName);319}320321std::vector<llvm::Record*> getBufferElementTypes() const {322return get()->getValueAsListOfDefs(BufferElementTypesFieldName);323}324325static llvm::StringRef getTableGenNodeClassName() {326return PropertyTypeClassName;327}328};329330/// A rule for returning the kind of a type.331class TypeKindRule : public WrappedRecord {332public:333TypeKindRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}334335/// Return the type to which this applies.336PropertyType getParentType() const {337return get()->getValueAsDef(TypeFieldName);338}339340/// Return the type of the kind.341PropertyType getKindType() const {342return get()->getValueAsDef(KindTypeFieldName);343}344345/// Return the name to use for the kind property.346llvm::StringRef getKindPropertyName() const {347return get()->getValueAsString(KindPropertyNameFieldName);348}349350/// Return the code for reading the kind value.351llvm::StringRef getReadCode() const {352return get()->getValueAsString(ReadFieldName);353}354355static llvm::StringRef getTableGenNodeClassName() {356return TypeKindClassName;357}358};359360/// An implementation case of a property type.361class TypeCase : public HasProperties {362public:363TypeCase(llvm::Record *record = nullptr) : HasProperties(record) {}364365/// Return the name of this case.366llvm::StringRef getCaseName() const {367return get()->getValueAsString(NameFieldName);368}369370/// Return the type of which this is a case.371PropertyType getParentType() const {372return get()->getValueAsDef(TypeFieldName);373}374375static llvm::StringRef getTableGenNodeClassName() {376return TypeCaseClassName;377}378};379380/// A property of an AST node.381class Property : public WrappedRecord {382public:383Property(llvm::Record *record = nullptr) : WrappedRecord(record) {}384385/// Return the name of this property.386llvm::StringRef getName() const {387return get()->getValueAsString(NameFieldName);388}389390/// Return the type of this property.391PropertyType getType() const {392return get()->getValueAsDef(TypeFieldName);393}394395/// Return the class of which this is a property.396HasProperties getClass() const {397return get()->getValueAsDef(ClassFieldName);398}399400/// Return the code for reading this property.401llvm::StringRef getReadCode() const {402return get()->getValueAsString(ReadFieldName);403}404405/// Return the code for determining whether to add this property.406llvm::StringRef getCondition() const {407return get()->getValueAsString(ConditionalCodeFieldName);408}409410static llvm::StringRef getTableGenNodeClassName() {411return PropertyClassName;412}413};414415/// A rule for running some helper code for reading properties from416/// a value (which is actually done when writing the value out).417class ReadHelperRule : public WrappedRecord {418public:419ReadHelperRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}420421/// Return the class for which this is a creation rule.422/// Should never be abstract.423HasProperties getClass() const {424return get()->getValueAsDef(ClassFieldName);425}426427llvm::StringRef getHelperCode() const {428return get()->getValueAsString(HelperCodeFieldName);429}430431static llvm::StringRef getTableGenNodeClassName() {432return ReadHelperRuleClassName;433}434};435436/// A rule for how to create an AST node from its properties.437class CreationRule : public WrappedRecord {438public:439CreationRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}440441/// Return the class for which this is a creation rule.442/// Should never be abstract.443HasProperties getClass() const {444return get()->getValueAsDef(ClassFieldName);445}446447llvm::StringRef getCreationCode() const {448return get()->getValueAsString(CreateFieldName);449}450451static llvm::StringRef getTableGenNodeClassName() {452return CreationRuleClassName;453}454};455456/// A rule which overrides the standard rules for serializing an AST node.457class OverrideRule : public WrappedRecord {458public:459OverrideRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}460461/// Return the class for which this is an override rule.462/// Should never be abstract.463HasProperties getClass() const {464return get()->getValueAsDef(ClassFieldName);465}466467/// Return a set of properties that are unnecessary when serializing468/// this AST node. Generally this is used for inherited properties469/// that are derived for this subclass.470std::vector<llvm::StringRef> getIgnoredProperties() const {471return get()->getValueAsListOfStrings(IgnoredPropertiesFieldName);472}473474static llvm::StringRef getTableGenNodeClassName() {475return OverrideRuleClassName;476}477};478479/// A visitor for an AST node hierarchy. Note that `base` can be null for480/// the root class.481template <class NodeClass>482using ASTNodeHierarchyVisitor =483llvm::function_ref<void(NodeClass node, NodeClass base)>;484485void visitASTNodeHierarchyImpl(llvm::RecordKeeper &records,486llvm::StringRef nodeClassName,487ASTNodeHierarchyVisitor<ASTNode> visit);488489template <class NodeClass>490void visitASTNodeHierarchy(llvm::RecordKeeper &records,491ASTNodeHierarchyVisitor<NodeClass> visit) {492visitASTNodeHierarchyImpl(records, NodeClass::getTableGenNodeClassName(),493[visit](ASTNode node, ASTNode base) {494visit(NodeClass(node.getRecord()),495NodeClass(base.getRecord()));496});497}498499} // end namespace clang::tblgen500} // end namespace clang501502#endif503504505