diff options
Diffstat (limited to 'clang/utils/TableGen')
| -rw-r--r-- | clang/utils/TableGen/ClangASTPropertiesEmitter.cpp | 12 | ||||
| -rw-r--r-- | clang/utils/TableGen/ClangAttrEmitter.cpp | 56 | ||||
| -rw-r--r-- | clang/utils/TableGen/ClangDiagnosticsEmitter.cpp | 5 | ||||
| -rw-r--r-- | clang/utils/TableGen/ClangOptionDocEmitter.cpp | 2 | ||||
| -rw-r--r-- | clang/utils/TableGen/ClangSyntaxEmitter.cpp | 236 | ||||
| -rw-r--r-- | clang/utils/TableGen/NeonEmitter.cpp | 25 | ||||
| -rw-r--r-- | clang/utils/TableGen/SveEmitter.cpp | 20 | ||||
| -rw-r--r-- | clang/utils/TableGen/TableGen.cpp | 12 | ||||
| -rw-r--r-- | clang/utils/TableGen/TableGenBackends.h | 8 |
9 files changed, 324 insertions, 52 deletions
diff --git a/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp b/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp index 256ca42e9aab..caced02e1e11 100644 --- a/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp +++ b/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp @@ -708,15 +708,13 @@ ASTPropsEmitter::emitBasicReaderWriterTemplate(const ReaderWriterInfo &info) { // Emit the Basic{Reader,Writer}Base template. Out << "template <class Impl>\n" "class Basic" << info.ClassSuffix << "Base {\n"; - if (info.IsReader) - Out << " ASTContext &C;\n"; + Out << " ASTContext &C;\n"; Out << "protected:\n" - " Basic" << info.ClassSuffix << "Base" - << (info.IsReader ? "(ASTContext &ctx) : C(ctx)" : "()") - << " {}\n" + " Basic" + << info.ClassSuffix << "Base" << ("(ASTContext &ctx) : C(ctx)") + << " {}\n" "public:\n"; - if (info.IsReader) - Out << " ASTContext &getASTContext() { return C; }\n"; + Out << " ASTContext &getASTContext() { return C; }\n"; Out << " Impl &asImpl() { return static_cast<Impl&>(*this); }\n"; auto enterReaderWriterMethod = [&](StringRef cxxTypeName, diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index bd20e447a950..d435c5780531 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -329,6 +329,8 @@ namespace { // empty string but are then recorded as a nullptr. OS << "\" << (get" << getUpperName() << "() ? get" << getUpperName() << "()->getName() : \"\") << \""; + else if (type == "VarDecl *") + OS << "\" << get" << getUpperName() << "()->getName() << \""; else if (type == "TypeSourceInfo *") OS << "\" << get" << getUpperName() << "().getAsString() << \""; else if (type == "ParamIdx") @@ -1147,8 +1149,9 @@ namespace { << "Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);\n"; OS << " ExprResult " << "Result = S.SubstExpr(" << "A->get" << getUpperName() << "(), TemplateArgs);\n"; - OS << " tempInst" << getUpperName() << " = " - << "Result.getAs<Expr>();\n"; + OS << " if (Result.isInvalid())\n"; + OS << " return nullptr;\n"; + OS << " tempInst" << getUpperName() << " = Result.get();\n"; OS << " }\n"; } @@ -1200,7 +1203,9 @@ namespace { << "_end();\n"; OS << " for (; I != E; ++I, ++TI) {\n"; OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n"; - OS << " *TI = Result.getAs<Expr>();\n"; + OS << " if (Result.isInvalid())\n"; + OS << " return nullptr;\n"; + OS << " *TI = Result.get();\n"; OS << " }\n"; OS << " }\n"; } @@ -1271,8 +1276,16 @@ namespace { OS << " return false;\n"; } + void writeTemplateInstantiation(raw_ostream &OS) const override { + OS << " " << getType() << " tempInst" << getUpperName() << " =\n"; + OS << " S.SubstType(A->get" << getUpperName() << "Loc(), " + << "TemplateArgs, A->getLoc(), A->getAttrName());\n"; + OS << " if (!tempInst" << getUpperName() << ")\n"; + OS << " return nullptr;\n"; + } + void writeTemplateInstantiationArgs(raw_ostream &OS) const override { - OS << "A->get" << getUpperName() << "Loc()"; + OS << "tempInst" << getUpperName(); } void writePCHWrite(raw_ostream &OS) const override { @@ -2365,7 +2378,7 @@ static void emitAttributes(RecordKeeper &Records, raw_ostream &OS, ai->writeCtorParameters(OS); } OS << ", const AttributeCommonInfo &CommonInfo"; - if (Header) + if (Header && Implicit) OS << " = {SourceRange{}}"; OS << ")"; if (Header) { @@ -2680,6 +2693,7 @@ static const AttrClassDescriptor AttrClassDescriptors[] = { { "ATTR", "Attr" }, { "TYPE_ATTR", "TypeAttr" }, { "STMT_ATTR", "StmtAttr" }, + { "DECL_OR_STMT_ATTR", "DeclOrStmtAttr" }, { "INHERITABLE_ATTR", "InheritableAttr" }, { "DECL_OR_TYPE_ATTR", "DeclOrTypeAttr" }, { "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" }, @@ -3064,18 +3078,22 @@ static void GenerateHasAttrSpellingStringSwitch( // attribute version information should be taken from the SD-6 standing // document, which can be found at: // https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations + // + // C2x-style attributes have the same kind of version information + // associated with them. The unscoped attribute version information should + // be taken from the specification of the attribute in the C Standard. int Version = 1; - if (Variety == "CXX11") { - std::vector<Record *> Spellings = Attr->getValueAsListOfDefs("Spellings"); - for (const auto &Spelling : Spellings) { - if (Spelling->getValueAsString("Variety") == "CXX11") { - Version = static_cast<int>(Spelling->getValueAsInt("Version")); - if (Scope.empty() && Version == 1) - PrintError(Spelling->getLoc(), "C++ standard attributes must " - "have valid version information."); - break; - } + if (Variety == "CXX11" || Variety == "C2x") { + std::vector<Record *> Spellings = Attr->getValueAsListOfDefs("Spellings"); + for (const auto &Spelling : Spellings) { + if (Spelling->getValueAsString("Variety") == Variety) { + Version = static_cast<int>(Spelling->getValueAsInt("Version")); + if (Scope.empty() && Version == 1) + PrintError(Spelling->getLoc(), "Standard attributes must have " + "valid version information."); + break; + } } } @@ -3313,12 +3331,13 @@ void EmitClangAttrTemplateInstantiateHelper(const std::vector<Record *> &Attrs, for (auto const &ai : Args) ai->writeTemplateInstantiation(OS); - OS << " return new (C) " << R.getName() << "Attr(C, *A"; + OS << " return new (C) " << R.getName() << "Attr(C, *A"; for (auto const &ai : Args) { OS << ", "; ai->writeTemplateInstantiationArgs(OS); } - OS << ");\n }\n"; + OS << ");\n" + << " }\n"; } OS << " } // end switch\n" << " llvm_unreachable(\"Unknown attribute!\");\n" @@ -3761,7 +3780,8 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << (Attr.isSubClassOf("TypeAttr") || Attr.isSubClassOf("DeclOrTypeAttr")) << ";\n"; OS << " IsStmt = "; - OS << Attr.isSubClassOf("StmtAttr") << ";\n"; + OS << (Attr.isSubClassOf("StmtAttr") || Attr.isSubClassOf("DeclOrStmtAttr")) + << ";\n"; OS << " IsKnownToGCC = "; OS << IsKnownToGCC(Attr) << ";\n"; OS << " IsSupportedByPragmaAttribute = "; diff --git a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp index 76d412203009..430895d8425f 100644 --- a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -1294,6 +1294,11 @@ void clang::EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS, else OS << ", false"; + if (R.getValueAsBit("Deferrable")) + OS << ", true"; + else + OS << ", false"; + // Category number. OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap)); OS << ")\n"; diff --git a/clang/utils/TableGen/ClangOptionDocEmitter.cpp b/clang/utils/TableGen/ClangOptionDocEmitter.cpp index 23aa31cc732f..0e079b6b505a 100644 --- a/clang/utils/TableGen/ClangOptionDocEmitter.cpp +++ b/clang/utils/TableGen/ClangOptionDocEmitter.cpp @@ -217,8 +217,6 @@ std::string getRSTStringWithTextFallback(const Record *R, StringRef Primary, StringRef Value; if (auto *SV = dyn_cast_or_null<StringInit>(V->getValue())) Value = SV->getValue(); - else if (auto *CV = dyn_cast_or_null<CodeInit>(V->getValue())) - Value = CV->getValue(); if (!Value.empty()) return Field == Primary ? Value.str() : escapeRST(Value); } diff --git a/clang/utils/TableGen/ClangSyntaxEmitter.cpp b/clang/utils/TableGen/ClangSyntaxEmitter.cpp new file mode 100644 index 000000000000..a940edbb1d24 --- /dev/null +++ b/clang/utils/TableGen/ClangSyntaxEmitter.cpp @@ -0,0 +1,236 @@ +//===- ClangSyntaxEmitter.cpp - Generate clang Syntax Tree nodes ----------===// +// +// The LLVM Compiler Infrastructure +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// These backends consume the definitions of Syntax Tree nodes. +// See clang/include/clang/Tooling/Syntax/{Syntax,Nodes}.td +// +// The -gen-clang-syntax-node-list backend produces a .inc with macro calls +// NODE(Kind, BaseKind) +// ABSTRACT_NODE(Type, Base, FirstKind, LastKind) +// similar to those for AST nodes such as AST/DeclNodes.inc. +// +// The -gen-clang-syntax-node-classes backend produces definitions for the +// syntax::Node subclasses (except those marked as External). +// +// In future, another backend will encode the structure of the various node +// types in tables so their invariants can be checked and enforced. +// +//===----------------------------------------------------------------------===// +#include "TableGenBackends.h" + +#include <deque> + +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" + +namespace { +using llvm::formatv; + +// The class hierarchy of Node types. +// We assemble this in order to be able to define the NodeKind enum in a +// stable and useful way, where abstract Node subclasses correspond to ranges. +class Hierarchy { +public: + Hierarchy(const llvm::RecordKeeper &Records) { + for (llvm::Record *T : Records.getAllDerivedDefinitions("NodeType")) + add(T); + for (llvm::Record *Derived : Records.getAllDerivedDefinitions("NodeType")) + if (llvm::Record *Base = Derived->getValueAsOptionalDef("base")) + link(Derived, Base); + for (NodeType &N : AllTypes) { + llvm::sort(N.Derived, [](const NodeType *L, const NodeType *R) { + return L->Record->getName() < R->Record->getName(); + }); + // Alternatives nodes must have subclasses, External nodes may do. + assert(N.Record->isSubClassOf("Alternatives") || + N.Record->isSubClassOf("External") || N.Derived.empty()); + assert(!N.Record->isSubClassOf("Alternatives") || !N.Derived.empty()); + } + } + + struct NodeType { + const llvm::Record *Record = nullptr; + const NodeType *Base = nullptr; + std::vector<const NodeType *> Derived; + llvm::StringRef name() const { return Record->getName(); } + }; + + NodeType &get(llvm::StringRef Name = "Node") { + auto NI = ByName.find(Name); + assert(NI != ByName.end() && "no such node"); + return *NI->second; + } + + // Traverse the hierarchy in pre-order (base classes before derived). + void visit(llvm::function_ref<void(const NodeType &)> CB, + const NodeType *Start = nullptr) { + if (Start == nullptr) + Start = &get(); + CB(*Start); + for (const NodeType *D : Start->Derived) + visit(CB, D); + } + +private: + void add(const llvm::Record *R) { + AllTypes.emplace_back(); + AllTypes.back().Record = R; + bool Inserted = ByName.try_emplace(R->getName(), &AllTypes.back()).second; + assert(Inserted && "Duplicate node name"); + (void)Inserted; + } + + void link(const llvm::Record *Derived, const llvm::Record *Base) { + auto &CN = get(Derived->getName()), &PN = get(Base->getName()); + assert(CN.Base == nullptr && "setting base twice"); + PN.Derived.push_back(&CN); + CN.Base = &PN; + } + + std::deque<NodeType> AllTypes; + llvm::DenseMap<llvm::StringRef, NodeType *> ByName; +}; + +const Hierarchy::NodeType &firstConcrete(const Hierarchy::NodeType &N) { + return N.Derived.empty() ? N : firstConcrete(*N.Derived.front()); +} +const Hierarchy::NodeType &lastConcrete(const Hierarchy::NodeType &N) { + return N.Derived.empty() ? N : lastConcrete(*N.Derived.back()); +} + +struct SyntaxConstraint { + SyntaxConstraint(const llvm::Record &R) { + if (R.isSubClassOf("Optional")) { + *this = SyntaxConstraint(*R.getValueAsDef("inner")); + } else if (R.isSubClassOf("AnyToken")) { + NodeType = "Leaf"; + } else if (R.isSubClassOf("NodeType")) { + NodeType = R.getName().str(); + } else { + assert(false && "Unhandled Syntax kind"); + } + } + + std::string NodeType; + // optional and leaf types also go here, once we want to use them. +}; + +} // namespace + +void clang::EmitClangSyntaxNodeList(llvm::RecordKeeper &Records, + llvm::raw_ostream &OS) { + llvm::emitSourceFileHeader("Syntax tree node list", OS); + Hierarchy H(Records); + OS << R"cpp( +#ifndef NODE +#define NODE(Kind, Base) +#endif + +#ifndef CONCRETE_NODE +#define CONCRETE_NODE(Kind, Base) NODE(Kind, Base) +#endif + +#ifndef ABSTRACT_NODE +#define ABSTRACT_NODE(Kind, Base, First, Last) NODE(Kind, Base) +#endif + +)cpp"; + H.visit([&](const Hierarchy::NodeType &N) { + // Don't emit ABSTRACT_NODE for node itself, which has no parent. + if (N.Base == nullptr) + return; + if (N.Derived.empty()) + OS << formatv("CONCRETE_NODE({0},{1})\n", N.name(), N.Base->name()); + else + OS << formatv("ABSTRACT_NODE({0},{1},{2},{3})\n", N.name(), + N.Base->name(), firstConcrete(N).name(), + lastConcrete(N).name()); + }); + OS << R"cpp( +#undef NODE +#undef CONCRETE_NODE +#undef ABSTRACT_NODE +)cpp"; +} + +// Format a documentation string as a C++ comment. +// Trims leading whitespace handling since comments come from a TableGen file: +// documentation = [{ +// This is a widget. Example: +// widget.explode() +// }]; +// and should be formatted as: +// /// This is a widget. Example: +// /// widget.explode() +// Leading and trailing whitespace lines are stripped. +// The indentation of the first line is stripped from all lines. +static void printDoc(llvm::StringRef Doc, llvm::raw_ostream &OS) { + Doc = Doc.rtrim(); + llvm::StringRef Line; + while (Line.trim().empty() && !Doc.empty()) + std::tie(Line, Doc) = Doc.split('\n'); + llvm::StringRef Indent = Line.take_while(llvm::isSpace); + for (; !Line.empty() || !Doc.empty(); std::tie(Line, Doc) = Doc.split('\n')) { + Line.consume_front(Indent); + OS << "/// " << Line << "\n"; + } +} + +void clang::EmitClangSyntaxNodeClasses(llvm::RecordKeeper &Records, + llvm::raw_ostream &OS) { + llvm::emitSourceFileHeader("Syntax tree node list", OS); + Hierarchy H(Records); + + OS << "\n// Forward-declare node types so we don't have to carefully " + "sequence definitions.\n"; + H.visit([&](const Hierarchy::NodeType &N) { + OS << "class " << N.name() << ";\n"; + }); + + OS << "\n// Node definitions\n\n"; + H.visit([&](const Hierarchy::NodeType &N) { + if (N.Record->isSubClassOf("External")) + return; + printDoc(N.Record->getValueAsString("documentation"), OS); + OS << formatv("class {0}{1} : public {2} {{\n", N.name(), + N.Derived.empty() ? " final" : "", N.Base->name()); + + // Constructor. + if (N.Derived.empty()) + OS << formatv("public:\n {0}() : {1}(NodeKind::{0}) {{}\n", N.name(), + N.Base->name()); + else + OS << formatv("protected:\n {0}(NodeKind K) : {1}(K) {{}\npublic:\n", + N.name(), N.Base->name()); + + if (N.Record->isSubClassOf("Sequence")) { + // Getters for sequence elements. + for (const auto &C : N.Record->getValueAsListOfDefs("children")) { + assert(C->isSubClassOf("Role")); + llvm::StringRef Role = C->getValueAsString("role"); + SyntaxConstraint Constraint(*C->getValueAsDef("syntax")); + for (const char *Const : {"", "const "}) + OS << formatv( + " {2}{1} *get{0}() {2} {{\n" + " return llvm::cast_or_null<{1}>(findChild(NodeRole::{0}));\n" + " }\n", + Role, Constraint.NodeType, Const); + } + } + + // classof. FIXME: move definition inline once ~all nodes are generated. + OS << " static bool classof(const Node *N);\n"; + + OS << "};\n\n"; + }); +} diff --git a/clang/utils/TableGen/NeonEmitter.cpp b/clang/utils/TableGen/NeonEmitter.cpp index d5bf59ef04ad..ba952f220037 100644 --- a/clang/utils/TableGen/NeonEmitter.cpp +++ b/clang/utils/TableGen/NeonEmitter.cpp @@ -382,7 +382,7 @@ public: StringRef Mods = getNextModifiers(Proto, Pos); while (!Mods.empty()) { Types.emplace_back(InTS, Mods); - if (Mods.find("!") != StringRef::npos) + if (Mods.find('!') != StringRef::npos) PolymorphicKeyType = Types.size() - 1; Mods = getNextModifiers(Proto, Pos); @@ -580,21 +580,18 @@ public: ClassMap[NoTestOpI] = ClassNoTest; } - // run - Emit arm_neon.h.inc + // Emit arm_neon.h.inc void run(raw_ostream &o); - // runFP16 - Emit arm_fp16.h.inc + // Emit arm_fp16.h.inc void runFP16(raw_ostream &o); - // runBF16 - Emit arm_bf16.h.inc + // Emit arm_bf16.h.inc void runBF16(raw_ostream &o); - // runHeader - Emit all the __builtin prototypes used in arm_neon.h, - // arm_fp16.h and arm_bf16.h + // Emit all the __builtin prototypes used in arm_neon.h, arm_fp16.h and + // arm_bf16.h void runHeader(raw_ostream &o); - - // runTests - Emit tests for all the Neon intrinsics. - void runTests(raw_ostream &o); }; } // end anonymous namespace @@ -1693,14 +1690,18 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) { std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDupTyped(DagInit *DI) { assert_with_loc(DI->getNumArgs() == 2, "dup_typed() expects two arguments"); - std::pair<Type, std::string> A = - emitDagArg(DI->getArg(0), std::string(DI->getArgNameStr(0))); std::pair<Type, std::string> B = emitDagArg(DI->getArg(1), std::string(DI->getArgNameStr(1))); assert_with_loc(B.first.isScalar(), "dup_typed() requires a scalar as the second argument"); + Type T; + // If the type argument is a constant string, construct the type directly. + if (StringInit *SI = dyn_cast<StringInit>(DI->getArg(0))) { + T = Type::fromTypedefName(SI->getAsUnquotedString()); + assert_with_loc(!T.isVoid(), "Unknown typedef"); + } else + T = emitDagArg(DI->getArg(0), std::string(DI->getArgNameStr(0))).first; - Type T = A.first; assert_with_loc(T.isVector(), "dup_typed() used but target type is scalar!"); std::string S = "(" + T.str() + ") {"; for (unsigned I = 0; I < T.getNumElements(); ++I) { diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp index 1d42edd8a94a..0e69600ef861 100644 --- a/clang/utils/TableGen/SveEmitter.cpp +++ b/clang/utils/TableGen/SveEmitter.cpp @@ -207,7 +207,7 @@ public: /// a short form without the type-specifiers, e.g. 'svld1(..)' instead of /// 'svld1_u32(..)'. static bool isOverloadedIntrinsic(StringRef Name) { - auto BrOpen = Name.find("["); + auto BrOpen = Name.find('['); auto BrClose = Name.find(']'); return BrOpen != std::string::npos && BrClose != std::string::npos; } @@ -416,10 +416,10 @@ std::string SVEType::builtin_str() const { std::string SVEType::str() const { if (isPredicatePattern()) - return "sv_pattern"; + return "enum svpattern"; if (isPrefetchOp()) - return "sv_prfop"; + return "enum svprfop"; std::string S; if (Void) @@ -893,14 +893,14 @@ std::string Intrinsic::mangleName(ClassKind LocalCK) const { if (LocalCK == ClassG) { // Remove the square brackets and everything in between. - while (S.find("[") != std::string::npos) { - auto Start = S.find("["); + while (S.find('[') != std::string::npos) { + auto Start = S.find('['); auto End = S.find(']'); S.erase(Start, (End-Start)+1); } } else { // Remove the square brackets. - while (S.find("[") != std::string::npos) { + while (S.find('[') != std::string::npos) { auto BrPos = S.find('['); if (BrPos != std::string::npos) S.erase(BrPos, 1); @@ -1163,7 +1163,7 @@ void SVEEmitter::createHeader(raw_ostream &OS) { OS << "typedef __clang_svbfloat16x4_t svbfloat16x4_t;\n"; OS << "#endif\n"; - OS << "typedef enum\n"; + OS << "enum svpattern\n"; OS << "{\n"; OS << " SV_POW2 = 0,\n"; OS << " SV_VL1 = 1,\n"; @@ -1182,9 +1182,9 @@ void SVEEmitter::createHeader(raw_ostream &OS) { OS << " SV_MUL4 = 29,\n"; OS << " SV_MUL3 = 30,\n"; OS << " SV_ALL = 31\n"; - OS << "} sv_pattern;\n\n"; + OS << "};\n\n"; - OS << "typedef enum\n"; + OS << "enum svprfop\n"; OS << "{\n"; OS << " SV_PLDL1KEEP = 0,\n"; OS << " SV_PLDL1STRM = 1,\n"; @@ -1198,7 +1198,7 @@ void SVEEmitter::createHeader(raw_ostream &OS) { OS << " SV_PSTL2STRM = 11,\n"; OS << " SV_PSTL3KEEP = 12,\n"; OS << " SV_PSTL3STRM = 13\n"; - OS << "} sv_prfop;\n\n"; + OS << "};\n\n"; OS << "/* Function attributes */\n"; OS << "#define __aio static inline __attribute__((__always_inline__, " diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp index 1d6ef8065bb8..1b919a77988b 100644 --- a/clang/utils/TableGen/TableGen.cpp +++ b/clang/utils/TableGen/TableGen.cpp @@ -55,6 +55,8 @@ enum ActionType { GenClangTypeWriter, GenClangOpcodes, GenClangSACheckers, + GenClangSyntaxNodeList, + GenClangSyntaxNodeClasses, GenClangCommentHTMLTags, GenClangCommentHTMLTagsProperties, GenClangCommentHTMLNamedCharacterReferences, @@ -166,6 +168,10 @@ cl::opt<ActionType> Action( "Generate Clang constexpr interpreter opcodes"), clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers", "Generate Clang Static Analyzer checkers"), + clEnumValN(GenClangSyntaxNodeList, "gen-clang-syntax-node-list", + "Generate list of Clang Syntax Tree node types"), + clEnumValN(GenClangSyntaxNodeClasses, "gen-clang-syntax-node-classes", + "Generate definitions of Clang Syntax Tree node clasess"), clEnumValN(GenClangCommentHTMLTags, "gen-clang-comment-html-tags", "Generate efficient matchers for HTML tag " "names that are used in documentation comments"), @@ -356,6 +362,12 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenClangOpenCLBuiltins: EmitClangOpenCLBuiltins(Records, OS); break; + case GenClangSyntaxNodeList: + EmitClangSyntaxNodeList(Records, OS); + break; + case GenClangSyntaxNodeClasses: + EmitClangSyntaxNodeClasses(Records, OS); + break; case GenArmNeon: EmitNeon(Records, OS); break; diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h index 9717903ba52c..33a06bfe4469 100644 --- a/clang/utils/TableGen/TableGenBackends.h +++ b/clang/utils/TableGen/TableGenBackends.h @@ -83,14 +83,16 @@ void EmitClangCommentCommandList(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitClangOpcodes(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); +void EmitClangSyntaxNodeList(llvm::RecordKeeper &Records, + llvm::raw_ostream &OS); +void EmitClangSyntaxNodeClasses(llvm::RecordKeeper &Records, + llvm::raw_ostream &OS); + void EmitNeon(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitFP16(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitBF16(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitNeonSema(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitNeonTest(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); -void EmitNeon2(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); -void EmitNeonSema2(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); -void EmitNeonTest2(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitSveHeader(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitSveBuiltins(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); |
