aboutsummaryrefslogtreecommitdiff
path: root/clang/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/utils/TableGen')
-rw-r--r--clang/utils/TableGen/ClangASTPropertiesEmitter.cpp12
-rw-r--r--clang/utils/TableGen/ClangAttrEmitter.cpp56
-rw-r--r--clang/utils/TableGen/ClangDiagnosticsEmitter.cpp5
-rw-r--r--clang/utils/TableGen/ClangOptionDocEmitter.cpp2
-rw-r--r--clang/utils/TableGen/ClangSyntaxEmitter.cpp236
-rw-r--r--clang/utils/TableGen/NeonEmitter.cpp25
-rw-r--r--clang/utils/TableGen/SveEmitter.cpp20
-rw-r--r--clang/utils/TableGen/TableGen.cpp12
-rw-r--r--clang/utils/TableGen/TableGenBackends.h8
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);