summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/ClangASTNodesEmitter.cpp10
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp264
-rw-r--r--utils/TableGen/ClangCommentCommandInfoEmitter.cpp8
-rw-r--r--utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp9
-rw-r--r--utils/TableGen/ClangDataCollectorsEmitter.cpp5
-rw-r--r--utils/TableGen/ClangDiagnosticsEmitter.cpp18
-rw-r--r--utils/TableGen/ClangOpcodesEmitter.cpp357
-rw-r--r--utils/TableGen/ClangOpenCLBuiltinEmitter.cpp540
-rw-r--r--utils/TableGen/ClangOptionDocEmitter.cpp9
-rw-r--r--utils/TableGen/ClangSACheckersEmitter.cpp5
-rw-r--r--utils/TableGen/ClangTypeNodesEmitter.cpp220
-rw-r--r--utils/TableGen/NeonEmitter.cpp60
-rw-r--r--utils/TableGen/TableGen.cpp12
-rw-r--r--utils/TableGen/TableGenBackends.h2
14 files changed, 1251 insertions, 268 deletions
diff --git a/utils/TableGen/ClangASTNodesEmitter.cpp b/utils/TableGen/ClangASTNodesEmitter.cpp
index a0bbdbab33542..3ece9be6a5c77 100644
--- a/utils/TableGen/ClangASTNodesEmitter.cpp
+++ b/utils/TableGen/ClangASTNodesEmitter.cpp
@@ -10,6 +10,8 @@
//
//===----------------------------------------------------------------------===//
+#include "TableGenBackends.h"
+
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cctype>
@@ -173,15 +175,14 @@ void ClangASTNodesEmitter::run(raw_ostream &OS) {
OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n";
}
-namespace clang {
-void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
- const std::string &N, const std::string &S) {
+void clang::EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
+ const std::string &N, const std::string &S) {
ClangASTNodesEmitter(RK, N, S).run(OS);
}
// Emits and addendum to a .inc file to enumerate the clang declaration
// contexts.
-void EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) {
// FIXME: Find a .td file format to allow for this to be represented better.
emitSourceFileHeader("List of AST Decl nodes", OS);
@@ -225,4 +226,3 @@ void EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) {
OS << "#undef DECL_CONTEXT\n";
OS << "#undef DECL_CONTEXT_BASE\n";
}
-} // end namespace clang
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index f315262ad0f40..0d92a321c7475 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -10,6 +10,8 @@
//
//===----------------------------------------------------------------------===//
+#include "TableGenBackends.h"
+
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
@@ -303,6 +305,8 @@ namespace {
std::string getIsOmitted() const override {
if (type == "IdentifierInfo *")
return "!get" + getUpperName().str() + "()";
+ if (type == "TypeSourceInfo *")
+ return "!get" + getUpperName().str() + "Loc()";
if (type == "ParamIdx")
return "!get" + getUpperName().str() + "().isValid()";
return "false";
@@ -336,6 +340,8 @@ namespace {
<< " OS << \" \" << SA->get" << getUpperName()
<< "()->getName();\n";
} else if (type == "TypeSourceInfo *") {
+ if (isOptional())
+ OS << " if (SA->get" << getUpperName() << "Loc())";
OS << " OS << \" \" << SA->get" << getUpperName()
<< "().getAsString();\n";
} else if (type == "bool") {
@@ -1251,51 +1257,51 @@ createArgument(const Record &Arg, StringRef Attr,
llvm::StringRef ArgName = Search->getName();
if (ArgName == "AlignedArgument")
- Ptr = llvm::make_unique<AlignedArgument>(Arg, Attr);
+ Ptr = std::make_unique<AlignedArgument>(Arg, Attr);
else if (ArgName == "EnumArgument")
- Ptr = llvm::make_unique<EnumArgument>(Arg, Attr);
+ Ptr = std::make_unique<EnumArgument>(Arg, Attr);
else if (ArgName == "ExprArgument")
- Ptr = llvm::make_unique<ExprArgument>(Arg, Attr);
+ Ptr = std::make_unique<ExprArgument>(Arg, Attr);
else if (ArgName == "FunctionArgument")
- Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "FunctionDecl *");
+ Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "FunctionDecl *");
else if (ArgName == "NamedArgument")
- Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "NamedDecl *");
+ Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "NamedDecl *");
else if (ArgName == "IdentifierArgument")
- Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "IdentifierInfo *");
+ Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "IdentifierInfo *");
else if (ArgName == "DefaultBoolArgument")
- Ptr = llvm::make_unique<DefaultSimpleArgument>(
+ Ptr = std::make_unique<DefaultSimpleArgument>(
Arg, Attr, "bool", Arg.getValueAsBit("Default"));
else if (ArgName == "BoolArgument")
- Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "bool");
+ Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "bool");
else if (ArgName == "DefaultIntArgument")
- Ptr = llvm::make_unique<DefaultSimpleArgument>(
+ Ptr = std::make_unique<DefaultSimpleArgument>(
Arg, Attr, "int", Arg.getValueAsInt("Default"));
else if (ArgName == "IntArgument")
- Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "int");
+ Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "int");
else if (ArgName == "StringArgument")
- Ptr = llvm::make_unique<StringArgument>(Arg, Attr);
+ Ptr = std::make_unique<StringArgument>(Arg, Attr);
else if (ArgName == "TypeArgument")
- Ptr = llvm::make_unique<TypeArgument>(Arg, Attr);
+ Ptr = std::make_unique<TypeArgument>(Arg, Attr);
else if (ArgName == "UnsignedArgument")
- Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "unsigned");
+ Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "unsigned");
else if (ArgName == "VariadicUnsignedArgument")
- Ptr = llvm::make_unique<VariadicArgument>(Arg, Attr, "unsigned");
+ Ptr = std::make_unique<VariadicArgument>(Arg, Attr, "unsigned");
else if (ArgName == "VariadicStringArgument")
- Ptr = llvm::make_unique<VariadicStringArgument>(Arg, Attr);
+ Ptr = std::make_unique<VariadicStringArgument>(Arg, Attr);
else if (ArgName == "VariadicEnumArgument")
- Ptr = llvm::make_unique<VariadicEnumArgument>(Arg, Attr);
+ Ptr = std::make_unique<VariadicEnumArgument>(Arg, Attr);
else if (ArgName == "VariadicExprArgument")
- Ptr = llvm::make_unique<VariadicExprArgument>(Arg, Attr);
+ Ptr = std::make_unique<VariadicExprArgument>(Arg, Attr);
else if (ArgName == "VariadicParamIdxArgument")
- Ptr = llvm::make_unique<VariadicParamIdxArgument>(Arg, Attr);
+ Ptr = std::make_unique<VariadicParamIdxArgument>(Arg, Attr);
else if (ArgName == "VariadicParamOrParamIdxArgument")
- Ptr = llvm::make_unique<VariadicParamOrParamIdxArgument>(Arg, Attr);
+ Ptr = std::make_unique<VariadicParamOrParamIdxArgument>(Arg, Attr);
else if (ArgName == "ParamIdxArgument")
- Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "ParamIdx");
+ Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "ParamIdx");
else if (ArgName == "VariadicIdentifierArgument")
- Ptr = llvm::make_unique<VariadicIdentifierArgument>(Arg, Attr);
+ Ptr = std::make_unique<VariadicIdentifierArgument>(Arg, Attr);
else if (ArgName == "VersionArgument")
- Ptr = llvm::make_unique<VersionArgument>(Arg, Attr);
+ Ptr = std::make_unique<VersionArgument>(Arg, Attr);
if (!Ptr) {
// Search in reverse order so that the most-derived type is handled first.
@@ -1343,7 +1349,7 @@ static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
return;
}
- OS << " switch (SpellingListIndex) {\n"
+ OS << " switch (getAttributeSpellingListIndex()) {\n"
" default:\n"
" llvm_unreachable(\"Unknown attribute spelling!\");\n"
" return \"(No spelling)\";\n";
@@ -1371,11 +1377,10 @@ writePrettyPrintFunction(Record &R,
return;
}
- OS <<
- " switch (SpellingListIndex) {\n"
- " default:\n"
- " llvm_unreachable(\"Unknown attribute spelling!\");\n"
- " break;\n";
+ OS << " switch (getAttributeSpellingListIndex()) {\n"
+ " default:\n"
+ " llvm_unreachable(\"Unknown attribute spelling!\");\n"
+ " break;\n";
for (unsigned I = 0; I < Spellings.size(); ++ I) {
llvm::SmallString<16> Prefix;
@@ -1556,11 +1561,12 @@ static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {
const StringRef Name = Accessor->getValueAsString("Name");
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Accessor);
- OS << " bool " << Name << "() const { return SpellingListIndex == ";
+ OS << " bool " << Name
+ << "() const { return getAttributeSpellingListIndex() == ";
for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
OS << getSpellingListIndex(SpellingList, Spellings[Index]);
if (Index != Spellings.size() - 1)
- OS << " ||\n SpellingListIndex == ";
+ OS << " ||\n getAttributeSpellingListIndex() == ";
else
OS << "; }\n";
}
@@ -1592,6 +1598,13 @@ CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
std::string Ret(" enum Spelling {\n");
std::set<std::string> Uniques;
unsigned Idx = 0;
+
+ // If we have a need to have this many spellings we likely need to add an
+ // extra bit to the SpellingIndex in AttributeCommonInfo, then increase the
+ // value of SpellingNotCalculated there and here.
+ assert(Spellings.size() < 15 &&
+ "Too many spellings, would step on SpellingNotCalculated in "
+ "AttributeCommonInfo");
for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) {
const FlattenedSpelling &S = *I;
const std::string &Variety = S.variety();
@@ -1625,6 +1638,7 @@ CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
// enumerator.
Ret += " " + EnumName + " = " + llvm::utostr(Idx);
}
+ Ret += ",\n SpellingNotCalculated = 15\n";
Ret += "\n };\n\n";
return Ret;
}
@@ -2207,16 +2221,15 @@ static void emitClangAttrThisIsaIdentifierArgList(RecordKeeper &Records,
OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n";
}
-namespace clang {
-
// Emits the class definitions for attributes.
-void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Attribute classes' definitions", OS);
OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+ ParsedAttrMap AttrMap = getParsedAttrList(Records);
for (const auto *Attr : Attrs) {
const Record &R = *Attr;
@@ -2285,38 +2298,97 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
if (!ElideSpelling)
OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
+ const auto &ParsedAttrSpellingItr = llvm::find_if(
+ AttrMap, [R](const std::pair<std::string, const Record *> &P) {
+ return &R == P.second;
+ });
+
// Emit CreateImplicit factory methods.
- auto emitCreateImplicit = [&](bool emitFake) {
- OS << " static " << R.getName() << "Attr *CreateImplicit(";
+ auto emitCreate = [&](bool Implicit, bool emitFake) {
+ OS << " static " << R.getName() << "Attr *Create";
+ if (Implicit)
+ OS << "Implicit";
+ OS << "(";
OS << "ASTContext &Ctx";
- if (!ElideSpelling)
- OS << ", Spelling S";
for (auto const &ai : Args) {
if (ai->isFake() && !emitFake) continue;
OS << ", ";
ai->writeCtorParameters(OS);
}
- OS << ", SourceRange Loc = SourceRange()";
- OS << ") {\n";
+ OS << ", const AttributeCommonInfo &CommonInfo = {SourceRange{}}) {\n";
OS << " auto *A = new (Ctx) " << R.getName();
- OS << "Attr(Loc, Ctx, ";
+ OS << "Attr(Ctx, CommonInfo";
for (auto const &ai : Args) {
if (ai->isFake() && !emitFake) continue;
- ai->writeImplicitCtorArgs(OS);
OS << ", ";
+ ai->writeImplicitCtorArgs(OS);
+ }
+ OS << ");\n";
+ if (Implicit) {
+ OS << " A->setImplicit(true);\n";
+ }
+ if (Implicit || ElideSpelling) {
+ OS << " if (!A->isAttributeSpellingListCalculated() && "
+ "!A->getAttrName())\n";
+ OS << " A->setAttributeSpellingListIndex(0);\n";
}
- OS << (ElideSpelling ? "0" : "S") << ");\n";
- OS << " A->setImplicit(true);\n";
OS << " return A;\n }\n\n";
};
+ auto emitCreateNoCI = [&](bool Implicit, bool emitFake) {
+ OS <<" static " << R.getName() << "Attr *Create";
+ if (Implicit)
+ OS << "Implicit";
+ OS << "(";
+ OS << "ASTContext &Ctx";
+ for (auto const &ai : Args) {
+ if (ai->isFake() && !emitFake) continue;
+ OS << ", ";
+ ai->writeCtorParameters(OS);
+ }
+ OS << ", SourceRange Range, AttributeCommonInfo::Syntax Syntax";
+ if (!ElideSpelling)
+ OS << ", " << R.getName()
+ << "Attr::Spelling S = "
+ "static_cast<Spelling>(SpellingNotCalculated)";
+ OS << ") {\n";
+ OS << " AttributeCommonInfo I(Range, ";
+
+ if (ParsedAttrSpellingItr != std::end(AttrMap))
+ OS << "AT_" << ParsedAttrSpellingItr->first;
+ else
+ OS << "NoSemaHandlerAttribute";
+
+ OS << ", Syntax";
+ if (!ElideSpelling)
+ OS << ", S";
+ OS << ");\n";
+ OS << " return Create";
+ if (Implicit)
+ OS << "Implicit";
+ OS << "(Ctx";
+ for (auto const &ai : Args) {
+ if (ai->isFake() && !emitFake) continue;
+ OS << ", ";
+ ai->writeImplicitCtorArgs(OS);
+ }
+ OS << ", I);\n";
+ OS << " }\n";
+ };
+
+ auto emitCreates = [&](bool emitFake) {
+ emitCreate(true, emitFake);
+ emitCreate(false, emitFake);
+ emitCreateNoCI(true, emitFake);
+ emitCreateNoCI(false, emitFake);
+ };
+
// Emit a CreateImplicit that takes all the arguments.
- emitCreateImplicit(true);
+ emitCreates(true);
// Emit a CreateImplicit that takes all the non-fake arguments.
- if (HasFakeArg) {
- emitCreateImplicit(false);
- }
+ if (HasFakeArg)
+ emitCreates(false);
// Emit constructors.
auto emitCtor = [&](bool emitOpt, bool emitFake) {
@@ -2325,8 +2397,9 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
if (arg->isOptional()) return emitOpt;
return true;
};
-
- OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
+ OS << " " << R.getName()
+ << "Attr(ASTContext &Ctx, const AttributeCommonInfo &CommonInfo";
+ OS << '\n';
for (auto const &ai : Args) {
if (!shouldEmitArg(ai)) continue;
OS << " , ";
@@ -2334,12 +2407,10 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
OS << "\n";
}
- OS << " , ";
- OS << "unsigned SI\n";
-
OS << " )\n";
- OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, "
- << ( R.getValueAsBit("LateParsed") ? "true" : "false" );
+ OS << " : " << SuperName << "(Ctx, CommonInfo, ";
+ OS << "attr::" << R.getName() << ", "
+ << (R.getValueAsBit("LateParsed") ? "true" : "false");
if (Inheritable) {
OS << ", "
<< (R.getValueAsBit("InheritEvenIfAlreadyPresent") ? "true"
@@ -2371,14 +2442,12 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
emitCtor(true, true);
// Emit a constructor that takes all the non-fake arguments.
- if (HasFakeArg) {
+ if (HasFakeArg)
emitCtor(true, false);
- }
// Emit a constructor that takes all the non-fake, non-optional arguments.
- if (HasOptArg) {
+ if (HasOptArg)
emitCtor(false, false);
- }
OS << " " << R.getName() << "Attr *clone(ASTContext &C) const;\n";
OS << " void printPretty(raw_ostream &OS,\n"
@@ -2388,8 +2457,8 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
if (!ElideSpelling) {
assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
OS << " Spelling getSemanticSpelling() const {\n";
- WriteSemanticSpellingSwitch("SpellingListIndex", SemanticToSyntacticMap,
- OS);
+ WriteSemanticSpellingSwitch("getAttributeSpellingListIndex()",
+ SemanticToSyntacticMap, OS);
OS << " }\n";
}
@@ -2422,7 +2491,7 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
}
// Emits the class method definitions for attributes.
-void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Attribute classes' member function definitions", OS);
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
@@ -2443,15 +2512,15 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
OS << R.getName() << "Attr *" << R.getName()
<< "Attr::clone(ASTContext &C) const {\n";
- OS << " auto *A = new (C) " << R.getName() << "Attr(getLocation(), C";
+ OS << " auto *A = new (C) " << R.getName() << "Attr(C, *this";
for (auto const &ai : Args) {
OS << ", ";
ai->writeCloneArgs(OS);
}
- OS << ", getSpellingListIndex());\n";
+ OS << ");\n";
OS << " A->Inherited = Inherited;\n";
OS << " A->IsPackExpansion = IsPackExpansion;\n";
- OS << " A->Implicit = Implicit;\n";
+ OS << " A->setImplicit(Implicit);\n";
OS << " return A;\n}\n\n";
writePrettyPrintFunction(R, Args, OS);
@@ -2487,8 +2556,6 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
EmitFunc("printPretty(OS, Policy)");
}
-} // end namespace clang
-
static void emitAttrList(raw_ostream &OS, StringRef Class,
const std::vector<Record*> &AttrList) {
for (auto Cur : AttrList) {
@@ -2751,24 +2818,23 @@ void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
const Record &R = *Attr;
if (!R.getValueAsBit("ASTNode"))
continue;
-
+
OS << " case attr::" << R.getName() << ": {\n";
if (R.isSubClassOf(InhClass))
OS << " bool isInherited = Record.readInt();\n";
OS << " bool isImplicit = Record.readInt();\n";
- OS << " unsigned Spelling = Record.readInt();\n";
ArgRecords = R.getValueAsListOfDefs("Args");
Args.clear();
for (const auto *Arg : ArgRecords) {
Args.emplace_back(createArgument(*Arg, R.getName()));
Args.back()->writePCHReadDecls(OS);
}
- OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
+ OS << " New = new (Context) " << R.getName() << "Attr(Context, Info";
for (auto const &ri : Args) {
OS << ", ";
ri->writePCHReadArgs(OS);
}
- OS << ", Spelling);\n";
+ OS << ");\n";
if (R.isSubClassOf(InhClass))
OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
OS << " New->setImplicit(isImplicit);\n";
@@ -2798,7 +2864,6 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
if (R.isSubClassOf(InhClass))
OS << " Record.push_back(SA->isInherited());\n";
OS << " Record.push_back(A->isImplicit());\n";
- OS << " Record.push_back(A->getSpellingListIndex());\n";
for (const auto *Arg : Args)
createArgument(*Arg, R.getName())->writePCHWrite(OS);
@@ -3015,7 +3080,11 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Code to translate different attribute spellings "
"into internal identifiers", OS);
- OS << " switch (AttrKind) {\n";
+ OS << " switch (getParsedKind()) {\n";
+ OS << " case IgnoredAttribute:\n";
+ OS << " case UnknownAttribute:\n";
+ OS << " case NoSemaHandlerAttribute:\n";
+ OS << " llvm_unreachable(\"Ignored/unknown shouldn't get here\");\n";
ParsedAttrMap Attrs = getParsedAttrList(Records);
for (const auto &I : Attrs) {
@@ -3024,16 +3093,7 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
OS << " case AT_" << I.first << ": {\n";
for (unsigned I = 0; I < Spellings.size(); ++ I) {
OS << " if (Name == \"" << Spellings[I].name() << "\" && "
- << "SyntaxUsed == "
- << StringSwitch<unsigned>(Spellings[I].variety())
- .Case("GNU", 0)
- .Case("CXX11", 1)
- .Case("C2x", 2)
- .Case("Declspec", 3)
- .Case("Microsoft", 4)
- .Case("Keyword", 5)
- .Case("Pragma", 6)
- .Default(0)
+ << "getSyntax() == AttributeCommonInfo::AS_" << Spellings[I].variety()
<< " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
<< " return " << I << ";\n";
}
@@ -3154,12 +3214,12 @@ void EmitClangAttrTemplateInstantiateHelper(const std::vector<Record *> &Attrs,
for (auto const &ai : Args)
ai->writeTemplateInstantiation(OS);
- OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
+ OS << " return new (C) " << R.getName() << "Attr(C, *A";
for (auto const &ai : Args) {
OS << ", ";
ai->writeTemplateInstantiationArgs(OS);
}
- OS << ", A->getSpellingListIndex());\n }\n";
+ OS << ");\n }\n";
}
OS << " } // end switch\n"
<< " llvm_unreachable(\"Unknown attribute!\");\n"
@@ -3477,7 +3537,7 @@ static std::string GenerateLangOptRequirements(const Record &R,
OS << " if (" << GenerateTestExpression(LangOpts) << ")\n";
OS << " return true;\n\n";
OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
- OS << "<< Attr.getName();\n";
+ OS << "<< Attr;\n";
OS << " return false;\n";
OS << "}\n\n";
@@ -3671,10 +3731,10 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
// specific attribute, or MSP430-specific attribute. Additionally, an
// attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">
// for the same semantic attribute. Ultimately, we need to map each of
- // these to a single ParsedAttr::Kind value, but the StringMatcher
- // class cannot handle duplicate match strings. So we generate a list of
- // string to match based on the syntax, and emit multiple string matchers
- // depending on the syntax used.
+ // these to a single AttributeCommonInfo::Kind value, but the
+ // StringMatcher class cannot handle duplicate match strings. So we
+ // generate a list of string to match based on the syntax, and emit
+ // multiple string matchers depending on the syntax used.
std::string AttrName;
if (Attr.isSubClassOf("TargetSpecificAttr") &&
!Attr.isValueUnset("ParseKind")) {
@@ -3719,33 +3779,33 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
if (SemaHandler)
Matches->push_back(StringMatcher::StringPair(
- Spelling, "return ParsedAttr::AT_" + AttrName + ";"));
+ Spelling, "return AttributeCommonInfo::AT_" + AttrName + ";"));
else
Matches->push_back(StringMatcher::StringPair(
- Spelling, "return ParsedAttr::IgnoredAttribute;"));
+ Spelling, "return AttributeCommonInfo::IgnoredAttribute;"));
}
}
}
- OS << "static ParsedAttr::Kind getAttrKind(StringRef Name, ";
- OS << "ParsedAttr::Syntax Syntax) {\n";
- OS << " if (ParsedAttr::AS_GNU == Syntax) {\n";
+ OS << "static AttributeCommonInfo::Kind getAttrKind(StringRef Name, ";
+ OS << "AttributeCommonInfo::Syntax Syntax) {\n";
+ OS << " if (AttributeCommonInfo::AS_GNU == Syntax) {\n";
StringMatcher("Name", GNU, OS).Emit();
- OS << " } else if (ParsedAttr::AS_Declspec == Syntax) {\n";
+ OS << " } else if (AttributeCommonInfo::AS_Declspec == Syntax) {\n";
StringMatcher("Name", Declspec, OS).Emit();
- OS << " } else if (ParsedAttr::AS_Microsoft == Syntax) {\n";
+ OS << " } else if (AttributeCommonInfo::AS_Microsoft == Syntax) {\n";
StringMatcher("Name", Microsoft, OS).Emit();
- OS << " } else if (ParsedAttr::AS_CXX11 == Syntax) {\n";
+ OS << " } else if (AttributeCommonInfo::AS_CXX11 == Syntax) {\n";
StringMatcher("Name", CXX11, OS).Emit();
- OS << " } else if (ParsedAttr::AS_C2x == Syntax) {\n";
+ OS << " } else if (AttributeCommonInfo::AS_C2x == Syntax) {\n";
StringMatcher("Name", C2x, OS).Emit();
- OS << " } else if (ParsedAttr::AS_Keyword == Syntax || ";
- OS << "ParsedAttr::AS_ContextSensitiveKeyword == Syntax) {\n";
+ OS << " } else if (AttributeCommonInfo::AS_Keyword == Syntax || ";
+ OS << "AttributeCommonInfo::AS_ContextSensitiveKeyword == Syntax) {\n";
StringMatcher("Name", Keywords, OS).Emit();
- OS << " } else if (ParsedAttr::AS_Pragma == Syntax) {\n";
+ OS << " } else if (AttributeCommonInfo::AS_Pragma == Syntax) {\n";
StringMatcher("Name", Pragma, OS).Emit();
OS << " }\n";
- OS << " return ParsedAttr::UnknownAttribute;\n"
+ OS << " return AttributeCommonInfo::UnknownAttribute;\n"
<< "}\n";
}
diff --git a/utils/TableGen/ClangCommentCommandInfoEmitter.cpp b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
index c0dd70281a4d9..fc79d59713d69 100644
--- a/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
+++ b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
@@ -11,6 +11,8 @@
//
//===----------------------------------------------------------------------===//
+#include "TableGenBackends.h"
+
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h"
#include "llvm/TableGen/TableGenBackend.h"
@@ -18,8 +20,7 @@
using namespace llvm;
-namespace clang {
-void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("A list of commands useable in documentation "
"comments", OS);
@@ -105,7 +106,7 @@ static std::string MangleName(StringRef Str) {
return Mangled;
}
-void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("A list of commands useable in documentation "
"comments", OS);
@@ -121,4 +122,3 @@ void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) {
OS << "COMMENT_COMMAND(" << MangledName << ")\n";
}
}
-} // end namespace clang
diff --git a/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp b/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
index 81af5b4b95f19..ed3f4bd6ef6c1 100644
--- a/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
+++ b/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "TableGenBackends.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/TableGen/Error.h"
@@ -45,9 +46,8 @@ static bool translateCodePointToUTF8(unsigned CodePoint,
return true;
}
-namespace clang {
-void EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper &Records,
- raw_ostream &OS) {
+void clang::EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper &Records,
+ raw_ostream &OS) {
std::vector<Record *> Tags = Records.getAllDerivedDefinitions("NCR");
std::vector<StringMatcher::StringPair> NameToUTF8;
SmallString<32> CLiteral;
@@ -79,6 +79,3 @@ void EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper &Records,
OS << " return StringRef();\n"
<< "}\n\n";
}
-
-} // end namespace clang
-
diff --git a/utils/TableGen/ClangDataCollectorsEmitter.cpp b/utils/TableGen/ClangDataCollectorsEmitter.cpp
index 4079efc808231..45082935c1f79 100644
--- a/utils/TableGen/ClangDataCollectorsEmitter.cpp
+++ b/utils/TableGen/ClangDataCollectorsEmitter.cpp
@@ -1,10 +1,10 @@
+#include "TableGenBackends.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
using namespace llvm;
-namespace clang {
-void EmitClangDataCollectors(RecordKeeper &RK, raw_ostream &OS) {
+void clang::EmitClangDataCollectors(RecordKeeper &RK, raw_ostream &OS) {
const auto &Defs = RK.getClasses();
for (const auto &Entry : Defs) {
Record &R = *Entry.second;
@@ -15,4 +15,3 @@ void EmitClangDataCollectors(RecordKeeper &RK, raw_ostream &OS) {
}
OS << "#undef DEF_ADD_DATA\n";
}
-} // end namespace clang
diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp
index 13e564e130ce4..778375010041d 100644
--- a/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "TableGenBackends.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.h"
@@ -1187,9 +1188,8 @@ static bool isRemark(const Record &Diag) {
/// ClangDiagsDefsEmitter - The top-level class emits .def files containing
/// declarations of Clang diagnostics.
-namespace clang {
-void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
- const std::string &Component) {
+void clang::EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
+ const std::string &Component) {
// Write the #if guard
if (!Component.empty()) {
std::string ComponentName = StringRef(Component).upper();
@@ -1288,7 +1288,6 @@ void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
OS << ")\n";
}
}
-} // end namespace clang
//===----------------------------------------------------------------------===//
// Warning Group Tables generation
@@ -1528,8 +1527,7 @@ static void emitCategoryTable(RecordKeeper &Records, raw_ostream &OS) {
OS << "#endif // GET_CATEGORY_TABLE\n\n";
}
-namespace clang {
-void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
// Compute a mapping from a DiagGroup to all of its parents.
DiagGroupParentMap DGParentMap(Records);
@@ -1565,7 +1563,6 @@ void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
OS);
emitCategoryTable(Records, OS);
}
-} // end namespace clang
//===----------------------------------------------------------------------===//
// Diagnostic name index generation
@@ -1582,8 +1579,7 @@ struct RecordIndexElement
};
} // end anonymous namespace.
-namespace clang {
-void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
const std::vector<Record*> &Diags =
Records.getAllDerivedDefinitions("Diagnostic");
@@ -1673,7 +1669,7 @@ void writeDiagnosticText(DiagnosticTextBuilder &Builder, const Record *R,
} // namespace
} // namespace docs
-void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
using namespace docs;
// Get the documentation introduction paragraph.
@@ -1792,5 +1788,3 @@ void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
OS << "\n";
}
}
-
-} // end namespace clang
diff --git a/utils/TableGen/ClangOpcodesEmitter.cpp b/utils/TableGen/ClangOpcodesEmitter.cpp
new file mode 100644
index 0000000000000..e5bfac5ba1b6f
--- /dev/null
+++ b/utils/TableGen/ClangOpcodesEmitter.cpp
@@ -0,0 +1,357 @@
+//=== ClangOpcodesEmitter.cpp - constexpr interpreter opcodes ---*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang AST node tables
+//
+//===----------------------------------------------------------------------===//
+
+#include "TableGenBackends.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+using namespace llvm;
+
+namespace {
+class ClangOpcodesEmitter {
+ RecordKeeper &Records;
+ Record Root;
+ unsigned NumTypes;
+
+public:
+ ClangOpcodesEmitter(RecordKeeper &R)
+ : Records(R), Root("Opcode", SMLoc(), R),
+ NumTypes(Records.getAllDerivedDefinitions("Type").size()) {}
+
+ void run(raw_ostream &OS);
+
+private:
+ /// Emits the opcode name for the opcode enum.
+ /// The name is obtained by concatenating the name with the list of types.
+ void EmitEnum(raw_ostream &OS, StringRef N, Record *R);
+
+ /// Emits the switch case and the invocation in the interpreter.
+ void EmitInterp(raw_ostream &OS, StringRef N, Record *R);
+
+ /// Emits the disassembler.
+ void EmitDisasm(raw_ostream &OS, StringRef N, Record *R);
+
+ /// Emits the byte code emitter method.
+ void EmitEmitter(raw_ostream &OS, StringRef N, Record *R);
+
+ /// Emits the prototype.
+ void EmitProto(raw_ostream &OS, StringRef N, Record *R);
+
+ /// Emits the prototype to dispatch from a type.
+ void EmitGroup(raw_ostream &OS, StringRef N, Record *R);
+
+ /// Emits the evaluator method.
+ void EmitEval(raw_ostream &OS, StringRef N, Record *R);
+
+ void PrintTypes(raw_ostream &OS, ArrayRef<Record *> Types);
+};
+
+void Enumerate(const Record *R,
+ StringRef N,
+ std::function<void(ArrayRef<Record *>, Twine)> &&F) {
+ llvm::SmallVector<Record *, 2> TypePath;
+ auto *Types = R->getValueAsListInit("Types");
+
+ std::function<void(size_t, const Twine &)> Rec;
+ Rec = [&TypePath, Types, &Rec, &F](size_t I, const Twine &ID) {
+ if (I >= Types->size()) {
+ F(TypePath, ID);
+ return;
+ }
+
+ if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) {
+ for (auto *Type : TypeClass->getDef()->getValueAsListOfDefs("Types")) {
+ TypePath.push_back(Type);
+ Rec(I + 1, ID + Type->getName());
+ TypePath.pop_back();
+ }
+ } else {
+ PrintFatalError("Expected a type class");
+ }
+ };
+ Rec(0, N);
+}
+
+} // namespace
+
+void ClangOpcodesEmitter::run(raw_ostream &OS) {
+ for (auto *Opcode : Records.getAllDerivedDefinitions(Root.getName())) {
+ // The name is the record name, unless overriden.
+ StringRef N = Opcode->getValueAsString("Name");
+ if (N.empty())
+ N = Opcode->getName();
+
+ EmitEnum(OS, N, Opcode);
+ EmitInterp(OS, N, Opcode);
+ EmitDisasm(OS, N, Opcode);
+ EmitProto(OS, N, Opcode);
+ EmitGroup(OS, N, Opcode);
+ EmitEmitter(OS, N, Opcode);
+ EmitEval(OS, N, Opcode);
+ }
+}
+
+void ClangOpcodesEmitter::EmitEnum(raw_ostream &OS, StringRef N, Record *R) {
+ OS << "#ifdef GET_OPCODE_NAMES\n";
+ Enumerate(R, N, [&OS](ArrayRef<Record *>, const Twine &ID) {
+ OS << "OP_" << ID << ",\n";
+ });
+ OS << "#endif\n";
+}
+
+void ClangOpcodesEmitter::EmitInterp(raw_ostream &OS, StringRef N, Record *R) {
+ OS << "#ifdef GET_INTERP\n";
+
+ Enumerate(R, N, [this, R, &OS, &N](ArrayRef<Record *> TS, const Twine &ID) {
+ bool CanReturn = R->getValueAsBit("CanReturn");
+ bool ChangesPC = R->getValueAsBit("ChangesPC");
+ auto Args = R->getValueAsListOfDefs("Args");
+
+ OS << "case OP_" << ID << ": {\n";
+
+ // Emit calls to read arguments.
+ for (size_t I = 0, N = Args.size(); I < N; ++I) {
+ OS << "\tauto V" << I;
+ OS << " = ";
+ OS << "PC.read<" << Args[I]->getValueAsString("Name") << ">();\n";
+ }
+
+ // Emit a call to the template method and pass arguments.
+ OS << "\tif (!" << N;
+ PrintTypes(OS, TS);
+ OS << "(S";
+ if (ChangesPC)
+ OS << ", PC";
+ else
+ OS << ", OpPC";
+ if (CanReturn)
+ OS << ", Result";
+ for (size_t I = 0, N = Args.size(); I < N; ++I)
+ OS << ", V" << I;
+ OS << "))\n";
+ OS << "\t\treturn false;\n";
+
+ // Bail out if interpreter returned.
+ if (CanReturn) {
+ OS << "\tif (!S.Current || S.Current->isRoot())\n";
+ OS << "\t\treturn true;\n";
+ }
+
+ OS << "\tcontinue;\n";
+ OS << "}\n";
+ });
+ OS << "#endif\n";
+}
+
+void ClangOpcodesEmitter::EmitDisasm(raw_ostream &OS, StringRef N, Record *R) {
+ OS << "#ifdef GET_DISASM\n";
+ Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) {
+ OS << "case OP_" << ID << ":\n";
+ OS << "\tPrintName(\"" << ID << "\");\n";
+ OS << "\tOS << \"\\t\"";
+
+ for (auto *Arg : R->getValueAsListOfDefs("Args"))
+ OS << " << PC.read<" << Arg->getValueAsString("Name") << ">() << \" \"";
+
+ OS << "<< \"\\n\";\n";
+ OS << "\tcontinue;\n";
+ });
+ OS << "#endif\n";
+}
+
+void ClangOpcodesEmitter::EmitEmitter(raw_ostream &OS, StringRef N, Record *R) {
+ if (R->getValueAsBit("HasCustomLink"))
+ return;
+
+ OS << "#ifdef GET_LINK_IMPL\n";
+ Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) {
+ auto Args = R->getValueAsListOfDefs("Args");
+
+ // Emit the list of arguments.
+ OS << "bool ByteCodeEmitter::emit" << ID << "(";
+ for (size_t I = 0, N = Args.size(); I < N; ++I)
+ OS << Args[I]->getValueAsString("Name") << " A" << I << ",";
+ OS << "const SourceInfo &L) {\n";
+
+ // Emit a call to write the opcodes.
+ OS << "\treturn emitOp<";
+ for (size_t I = 0, N = Args.size(); I < N; ++I) {
+ if (I != 0)
+ OS << ", ";
+ OS << Args[I]->getValueAsString("Name");
+ }
+ OS << ">(OP_" << ID;
+ for (size_t I = 0, N = Args.size(); I < N; ++I)
+ OS << ", A" << I;
+ OS << ", L);\n";
+ OS << "}\n";
+ });
+ OS << "#endif\n";
+}
+
+void ClangOpcodesEmitter::EmitProto(raw_ostream &OS, StringRef N, Record *R) {
+ OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
+ auto Args = R->getValueAsListOfDefs("Args");
+ Enumerate(R, N, [&OS, &Args](ArrayRef<Record *> TS, const Twine &ID) {
+ OS << "bool emit" << ID << "(";
+ for (auto *Arg : Args)
+ OS << Arg->getValueAsString("Name") << ", ";
+ OS << "const SourceInfo &);\n";
+ });
+
+ // Emit a template method for custom emitters to have less to implement.
+ auto TypeCount = R->getValueAsListInit("Types")->size();
+ if (R->getValueAsBit("HasCustomEval") && TypeCount) {
+ OS << "#if defined(GET_EVAL_PROTO)\n";
+ OS << "template<";
+ for (size_t I = 0; I < TypeCount; ++I) {
+ if (I != 0)
+ OS << ", ";
+ OS << "PrimType";
+ }
+ OS << ">\n";
+ OS << "bool emit" << N << "(";
+ for (auto *Arg : Args)
+ OS << Arg->getValueAsString("Name") << ", ";
+ OS << "const SourceInfo &);\n";
+ OS << "#endif\n";
+ }
+
+ OS << "#endif\n";
+}
+
+void ClangOpcodesEmitter::EmitGroup(raw_ostream &OS, StringRef N, Record *R) {
+ if (!R->getValueAsBit("HasGroup"))
+ return;
+
+ auto *Types = R->getValueAsListInit("Types");
+ auto Args = R->getValueAsListOfDefs("Args");
+
+ // Emit the prototype of the group emitter in the header.
+ OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
+ OS << "bool emit" << N << "(";
+ for (size_t I = 0, N = Types->size(); I < N; ++I)
+ OS << "PrimType, ";
+ for (auto *Arg : Args)
+ OS << Arg->getValueAsString("Name") << ", ";
+ OS << "const SourceInfo &I);\n";
+ OS << "#endif\n";
+
+ // Emit the dispatch implementation in the source.
+ OS << "#if defined(GET_EVAL_IMPL) || defined(GET_LINK_IMPL)\n";
+ OS << "bool \n";
+ OS << "#if defined(GET_EVAL_IMPL)\n";
+ OS << "EvalEmitter\n";
+ OS << "#else\n";
+ OS << "ByteCodeEmitter\n";
+ OS << "#endif\n";
+ OS << "::emit" << N << "(";
+ for (size_t I = 0, N = Types->size(); I < N; ++I)
+ OS << "PrimType T" << I << ", ";
+ for (size_t I = 0, N = Args.size(); I < N; ++I)
+ OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
+ OS << "const SourceInfo &I) {\n";
+
+ std::function<void(size_t, const Twine &)> Rec;
+ llvm::SmallVector<Record *, 2> TS;
+ Rec = [this, &Rec, &OS, Types, &Args, R, &TS, N](size_t I, const Twine &ID) {
+ if (I >= Types->size()) {
+ // Print a call to the emitter method.
+ // Custom evaluator methods dispatch to template methods.
+ if (R->getValueAsBit("HasCustomEval")) {
+ OS << "#ifdef GET_LINK_IMPL\n";
+ OS << "return emit" << ID << "\n";
+ OS << "#else\n";
+ OS << "return emit" << N;
+ PrintTypes(OS, TS);
+ OS << "\n#endif\n";
+ } else {
+ OS << "return emit" << ID;
+ }
+
+ OS << "(";
+ for (size_t I = 0; I < Args.size(); ++I) {
+ OS << "A" << I << ", ";
+ }
+ OS << "I);\n";
+ return;
+ }
+
+ // Print a switch statement selecting T.
+ if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) {
+ OS << "switch (T" << I << "){\n";
+ auto Cases = TypeClass->getDef()->getValueAsListOfDefs("Types");
+ for (auto *Case : Cases) {
+ OS << "case PT_" << Case->getName() << ":\n";
+ TS.push_back(Case);
+ Rec(I + 1, ID + Case->getName());
+ TS.pop_back();
+ }
+ // Emit a default case if not all types are present.
+ if (Cases.size() < NumTypes)
+ OS << "default: llvm_unreachable(\"invalid type\");\n";
+ OS << "}\n";
+ OS << "llvm_unreachable(\"invalid enum value\");\n";
+ } else {
+ PrintFatalError("Expected a type class");
+ }
+ };
+ Rec(0, N);
+
+ OS << "}\n";
+ OS << "#endif\n";
+}
+
+void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N, Record *R) {
+ if (R->getValueAsBit("HasCustomEval"))
+ return;
+
+ OS << "#ifdef GET_EVAL_IMPL\n";
+ Enumerate(R, N, [this, R, &N, &OS](ArrayRef<Record *> TS, const Twine &ID) {
+ auto Args = R->getValueAsListOfDefs("Args");
+
+ OS << "bool EvalEmitter::emit" << ID << "(";
+ for (size_t I = 0, N = Args.size(); I < N; ++I)
+ OS << Args[I]->getValueAsString("Name") << " A" << I << ",";
+ OS << "const SourceInfo &L) {\n";
+ OS << "if (!isActive()) return true;\n";
+ OS << "CurrentSource = L;\n";
+
+ OS << "return " << N;
+ PrintTypes(OS, TS);
+ OS << "(S, OpPC";
+ for (size_t I = 0, N = Args.size(); I < N; ++I)
+ OS << ", A" << I;
+ OS << ");\n";
+ OS << "}\n";
+ });
+
+ OS << "#endif\n";
+}
+
+void ClangOpcodesEmitter::PrintTypes(raw_ostream &OS, ArrayRef<Record *> Types) {
+ if (Types.empty())
+ return;
+ OS << "<";
+ for (size_t I = 0, N = Types.size(); I < N; ++I) {
+ if (I != 0)
+ OS << ", ";
+ OS << "PT_" << Types[I]->getName();
+ }
+ OS << ">";
+}
+
+void clang::EmitClangOpcodes(RecordKeeper &Records, raw_ostream &OS) {
+ ClangOpcodesEmitter(Records).run(OS);
+}
diff --git a/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp b/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
index 8d83b1c7fa6b9..c8975d7bf615d 100644
--- a/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
+++ b/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
@@ -15,20 +15,49 @@
//
// For a successful lookup of e.g. the "cos" builtin, isOpenCLBuiltin("cos")
// returns a pair <Index, Len>.
-// OpenCLBuiltins[Index] to OpenCLBuiltins[Index + Len] contains the pairs
+// BuiltinTable[Index] to BuiltinTable[Index + Len] contains the pairs
// <SigIndex, SigLen> of the overloads of "cos".
-// OpenCLSignature[SigIndex] to OpenCLSignature[SigIndex + SigLen] contains
-// one of the signatures of "cos". The OpenCLSignature entry can be
-// referenced by other functions, i.e. "sin", since multiple OpenCL builtins
-// share the same signature.
+// SignatureTable[SigIndex] to SignatureTable[SigIndex + SigLen] contains
+// one of the signatures of "cos". The SignatureTable entry can be
+// referenced by other functions, e.g. "sin", to exploit the fact that
+// many OpenCL builtins share the same signature.
+//
+// The file generated by this TableGen emitter contains the following:
+//
+// * Structs and enums to represent types and function signatures.
+//
+// * OpenCLTypeStruct TypeTable[]
+// Type information for return types and arguments.
+//
+// * unsigned SignatureTable[]
+// A list of types representing function signatures. Each entry is an index
+// into the above TypeTable. Multiple entries following each other form a
+// signature, where the first entry is the return type and subsequent
+// entries are the argument types.
+//
+// * OpenCLBuiltinStruct BuiltinTable[]
+// Each entry represents one overload of an OpenCL builtin function and
+// consists of an index into the SignatureTable and the number of arguments.
+//
+// * std::pair<unsigned, unsigned> isOpenCLBuiltin(llvm::StringRef Name)
+// Find out whether a string matches an existing OpenCL builtin function
+// name and return an index into BuiltinTable and the number of overloads.
+//
+// * void OCL2Qual(ASTContext&, OpenCLTypeStruct, std::vector<QualType>&)
+// Convert an OpenCLTypeStruct type to a list of QualType instances.
+// One OpenCLTypeStruct can represent multiple types, primarily when using
+// GenTypes.
+//
//===----------------------------------------------------------------------===//
+#include "TableGenBackends.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
@@ -57,34 +86,49 @@ private:
// The output file.
raw_ostream &OS;
- // Emit the enums and structs.
+ // Helper function for BuiltinNameEmitter::EmitDeclarations. Generate enum
+ // definitions in the Output string parameter, and save their Record instances
+ // in the List parameter.
+ // \param Types (in) List containing the Types to extract.
+ // \param TypesSeen (inout) List containing the Types already extracted.
+ // \param Output (out) String containing the enums to emit in the output file.
+ // \param List (out) List containing the extracted Types, except the Types in
+ // TypesSeen.
+ void ExtractEnumTypes(std::vector<Record *> &Types,
+ StringMap<bool> &TypesSeen, std::string &Output,
+ std::vector<const Record *> &List);
+
+ // Emit the enum or struct used in the generated file.
+ // Populate the TypeList at the same time.
void EmitDeclarations();
- // Parse the Records generated by TableGen and populate OverloadInfo and
- // SignatureSet.
+ // Parse the Records generated by TableGen to populate the SignaturesList,
+ // FctOverloadMap and TypeMap.
void GetOverloads();
- // Emit the OpenCLSignature table. This table contains all possible
- // signatures, and is a struct OpenCLType. A signature is composed of a
- // return type (mandatory), followed by zero or more argument types.
+ // Emit the TypeTable containing all types used by OpenCL builtins.
+ void EmitTypeTable();
+
+ // Emit the SignatureTable. This table contains all the possible signatures.
+ // A signature is stored as a list of indexes of the TypeTable.
+ // The first index references the return type (mandatory), and the followings
+ // reference its arguments.
// E.g.:
- // // 12
- // { OCLT_uchar, 4, clang::LangAS::Default, false },
- // { OCLT_float, 4, clang::LangAS::Default, false },
- // This means that index 12 represents a signature
- // - returning a uchar vector of 4 elements, and
- // - taking as first argument a float vector of 4 elements.
+ // 15, 2, 15 can represent a function with the signature:
+ // int func(float, int)
+ // The "int" type being at the index 15 in the TypeTable.
void EmitSignatureTable();
- // Emit the OpenCLBuiltins table. This table contains all overloads of
+ // Emit the BuiltinTable table. This table contains all the overloads of
// each function, and is a struct OpenCLBuiltinDecl.
// E.g.:
- // // acos
- // { 2, 0, "", 100 },
- // This means that the signature of this acos overload is defined in OpenCL
- // version 1.0 (100) and does not belong to any extension (""). It has a
- // 1 argument (+1 for the return type), stored at index 0 in the
- // OpenCLSignature table.
+ // // 891 convert_float2_rtn
+ // { 58, 2, 100, 0 },
+ // This means that the signature of this convert_float2_rtn overload has
+ // 1 argument (+1 for the return type), stored at index 58 in
+ // the SignatureTable. The last two values represent the minimum (1.0) and
+ // maximum (0, meaning no max version) OpenCL version in which this overload
+ // is supported.
void EmitBuiltinTable();
// Emit a StringMatcher function to check whether a function name is an
@@ -102,20 +146,30 @@ private:
// <<float>, 5>,
// ...
// <<double, double>, 35>.
- std::vector<std::pair<std::vector<Record *>, unsigned>> SignatureSet;
+ std::vector<std::pair<std::vector<Record *>, unsigned>> SignaturesList;
// Map the name of a builtin function to its prototypes (instances of the
// TableGen "Builtin" class).
// Each prototype is registered as a pair of:
// <pointer to the "Builtin" instance,
- // cumulative index of the associated signature in the SignatureSet>
+ // cumulative index of the associated signature in the SignaturesList>
// E.g.: The function cos: (float cos(float), double cos(double), ...)
// <"cos", <<ptrToPrototype0, 5>,
- // <ptrToPrototype1, 35>>
- // <ptrToPrototype2, 79>>
+ // <ptrToPrototype1, 35>,
+ // <ptrToPrototype2, 79>>
// ptrToPrototype1 has the following signature: <double, double>
MapVector<StringRef, std::vector<std::pair<const Record *, unsigned>>>
- OverloadInfo;
+ FctOverloadMap;
+
+ // Contains the map of OpenCL types to their index in the TypeTable.
+ MapVector<const Record *, unsigned> TypeMap;
+
+ // List of OpenCL type names in the same order as in enum OpenCLTypeID.
+ // This list does not contain generic types.
+ std::vector<const Record *> TypeList;
+
+ // Same as TypeList, but for generic types only.
+ std::vector<const Record *> GenTypeList;
};
} // namespace
@@ -125,12 +179,14 @@ void BuiltinNameEmitter::Emit() {
OS << "#include \"llvm/ADT/StringRef.h\"\n";
OS << "using namespace clang;\n\n";
+ // Emit enums and structs.
EmitDeclarations();
GetOverloads();
+ // Emit tables.
+ EmitTypeTable();
EmitSignatureTable();
-
EmitBuiltinTable();
EmitStringMatcher();
@@ -138,100 +194,226 @@ void BuiltinNameEmitter::Emit() {
EmitQualTypeFinder();
}
+void BuiltinNameEmitter::ExtractEnumTypes(std::vector<Record *> &Types,
+ StringMap<bool> &TypesSeen,
+ std::string &Output,
+ std::vector<const Record *> &List) {
+ raw_string_ostream SS(Output);
+
+ for (const auto *T : Types) {
+ if (TypesSeen.find(T->getValueAsString("Name")) == TypesSeen.end()) {
+ SS << " OCLT_" + T->getValueAsString("Name") << ",\n";
+ // Save the type names in the same order as their enum value. Note that
+ // the Record can be a VectorType or something else, only the name is
+ // important.
+ List.push_back(T);
+ TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true));
+ }
+ }
+ SS.flush();
+}
+
void BuiltinNameEmitter::EmitDeclarations() {
+ // Enum of scalar type names (float, int, ...) and generic type sets.
OS << "enum OpenCLTypeID {\n";
- std::vector<Record *> Types = Records.getAllDerivedDefinitions("Type");
+
StringMap<bool> TypesSeen;
- for (const auto *T : Types) {
- if (TypesSeen.find(T->getValueAsString("Name")) == TypesSeen.end())
- OS << " OCLT_" + T->getValueAsString("Name") << ",\n";
- TypesSeen.insert(std::make_pair(T->getValueAsString("Name"), true));
- }
+ std::string GenTypeEnums;
+ std::string TypeEnums;
+
+ // Extract generic types and non-generic types separately, to keep
+ // gentypes at the end of the enum which simplifies the special handling
+ // for gentypes in SemaLookup.
+ std::vector<Record *> GenTypes =
+ Records.getAllDerivedDefinitions("GenericType");
+ ExtractEnumTypes(GenTypes, TypesSeen, GenTypeEnums, GenTypeList);
+
+ std::vector<Record *> Types = Records.getAllDerivedDefinitions("Type");
+ ExtractEnumTypes(Types, TypesSeen, TypeEnums, TypeList);
+
+ OS << TypeEnums;
+ OS << GenTypeEnums;
OS << "};\n";
+ // Structure definitions.
OS << R"(
+// Image access qualifier.
+enum OpenCLAccessQual : unsigned char {
+ OCLAQ_None,
+ OCLAQ_ReadOnly,
+ OCLAQ_WriteOnly,
+ OCLAQ_ReadWrite
+};
-// Type used in a prototype of an OpenCL builtin function.
-struct OpenCLType {
- // A type (e.g.: float, int, ...)
- OpenCLTypeID ID;
- // Size of vector (if applicable)
- unsigned VectorWidth;
- // Address space of the pointer (if applicable)
- LangAS AS;
- // Whether the type is a pointer
- bool isPointer;
+// Represents a return type or argument type.
+struct OpenCLTypeStruct {
+ // A type (e.g. float, int, ...).
+ const OpenCLTypeID ID;
+ // Vector size (if applicable; 0 for scalars and generic types).
+ const unsigned VectorWidth;
+ // 0 if the type is not a pointer.
+ const bool IsPointer;
+ // 0 if the type is not const.
+ const bool IsConst;
+ // 0 if the type is not volatile.
+ const bool IsVolatile;
+ // Access qualifier.
+ const OpenCLAccessQual AccessQualifier;
+ // Address space of the pointer (if applicable).
+ const LangAS AS;
};
// One overload of an OpenCL builtin function.
-struct OpenCLBuiltinDecl {
- // Number of arguments for the signature
- unsigned NumArgs;
- // Index in the OpenCLSignature table to get the required types
- unsigned ArgTableIndex;
- // Extension to which it belongs (e.g. cl_khr_subgroups)
- const char *Extension;
- // Version in which it was introduced (e.g. CL20)
- unsigned Version;
+struct OpenCLBuiltinStruct {
+ // Index of the signature in the OpenCLTypeStruct table.
+ const unsigned SigTableIndex;
+ // Entries between index SigTableIndex and (SigTableIndex + NumTypes - 1) in
+ // the SignatureTable represent the complete signature. The first type at
+ // index SigTableIndex is the return type.
+ const unsigned NumTypes;
+ // First OpenCL version in which this overload was introduced (e.g. CL20).
+ const unsigned short MinVersion;
+ // First OpenCL version in which this overload was removed (e.g. CL20).
+ const unsigned short MaxVersion;
};
)";
}
+// Verify that the combination of GenTypes in a signature is supported.
+// To simplify the logic for creating overloads in SemaLookup, only allow
+// a signature to contain different GenTypes if these GenTypes represent
+// the same number of actual scalar or vector types.
+//
+// Exit with a fatal error if an unsupported construct is encountered.
+static void VerifySignature(const std::vector<Record *> &Signature,
+ const Record *BuiltinRec) {
+ unsigned GenTypeVecSizes = 1;
+ unsigned GenTypeTypes = 1;
+
+ for (const auto *T : Signature) {
+ // Check all GenericType arguments in this signature.
+ if (T->isSubClassOf("GenericType")) {
+ // Check number of vector sizes.
+ unsigned NVecSizes =
+ T->getValueAsDef("VectorList")->getValueAsListOfInts("List").size();
+ if (NVecSizes != GenTypeVecSizes && NVecSizes != 1) {
+ if (GenTypeVecSizes > 1) {
+ // We already saw a gentype with a different number of vector sizes.
+ PrintFatalError(BuiltinRec->getLoc(),
+ "number of vector sizes should be equal or 1 for all gentypes "
+ "in a declaration");
+ }
+ GenTypeVecSizes = NVecSizes;
+ }
+
+ // Check number of data types.
+ unsigned NTypes =
+ T->getValueAsDef("TypeList")->getValueAsListOfDefs("List").size();
+ if (NTypes != GenTypeTypes && NTypes != 1) {
+ if (GenTypeTypes > 1) {
+ // We already saw a gentype with a different number of types.
+ PrintFatalError(BuiltinRec->getLoc(),
+ "number of types should be equal or 1 for all gentypes "
+ "in a declaration");
+ }
+ GenTypeTypes = NTypes;
+ }
+ }
+ }
+}
+
void BuiltinNameEmitter::GetOverloads() {
+ // Populate the TypeMap.
+ std::vector<Record *> Types = Records.getAllDerivedDefinitions("Type");
+ unsigned I = 0;
+ for (const auto &T : Types) {
+ TypeMap.insert(std::make_pair(T, I++));
+ }
+
+ // Populate the SignaturesList and the FctOverloadMap.
unsigned CumulativeSignIndex = 0;
std::vector<Record *> Builtins = Records.getAllDerivedDefinitions("Builtin");
for (const auto *B : Builtins) {
StringRef BName = B->getValueAsString("Name");
- if (OverloadInfo.find(BName) == OverloadInfo.end()) {
- OverloadInfo.insert(std::make_pair(
+ if (FctOverloadMap.find(BName) == FctOverloadMap.end()) {
+ FctOverloadMap.insert(std::make_pair(
BName, std::vector<std::pair<const Record *, unsigned>>{}));
}
auto Signature = B->getValueAsListOfDefs("Signature");
+ // Reuse signatures to avoid unnecessary duplicates.
auto it =
- std::find_if(SignatureSet.begin(), SignatureSet.end(),
+ std::find_if(SignaturesList.begin(), SignaturesList.end(),
[&](const std::pair<std::vector<Record *>, unsigned> &a) {
return a.first == Signature;
});
unsigned SignIndex;
- if (it == SignatureSet.end()) {
- SignatureSet.push_back(std::make_pair(Signature, CumulativeSignIndex));
+ if (it == SignaturesList.end()) {
+ VerifySignature(Signature, B);
+ SignaturesList.push_back(std::make_pair(Signature, CumulativeSignIndex));
SignIndex = CumulativeSignIndex;
CumulativeSignIndex += Signature.size();
} else {
SignIndex = it->second;
}
- OverloadInfo[BName].push_back(std::make_pair(B, SignIndex));
+ FctOverloadMap[BName].push_back(std::make_pair(B, SignIndex));
}
}
+void BuiltinNameEmitter::EmitTypeTable() {
+ OS << "static const OpenCLTypeStruct TypeTable[] = {\n";
+ for (const auto &T : TypeMap) {
+ const char *AccessQual =
+ StringSwitch<const char *>(T.first->getValueAsString("AccessQualifier"))
+ .Case("RO", "OCLAQ_ReadOnly")
+ .Case("WO", "OCLAQ_WriteOnly")
+ .Case("RW", "OCLAQ_ReadWrite")
+ .Default("OCLAQ_None");
+
+ OS << " // " << T.second << "\n"
+ << " {OCLT_" << T.first->getValueAsString("Name") << ", "
+ << T.first->getValueAsInt("VecWidth") << ", "
+ << T.first->getValueAsBit("IsPointer") << ", "
+ << T.first->getValueAsBit("IsConst") << ", "
+ << T.first->getValueAsBit("IsVolatile") << ", "
+ << AccessQual << ", "
+ << T.first->getValueAsString("AddrSpace") << "},\n";
+ }
+ OS << "};\n\n";
+}
+
void BuiltinNameEmitter::EmitSignatureTable() {
- OS << "static const OpenCLType OpenCLSignature[] = {\n";
- for (auto &P : SignatureSet) {
- OS << "// " << P.second << "\n";
- for (Record *R : P.first) {
- OS << "{ OCLT_" << R->getValueAsString("Name") << ", "
- << R->getValueAsInt("VecWidth") << ", "
- << R->getValueAsString("AddrSpace") << ", "
- << R->getValueAsBit("IsPointer") << "},";
- OS << "\n";
+ // Store a type (e.g. int, float, int2, ...). The type is stored as an index
+ // of a struct OpenCLType table. Multiple entries following each other form a
+ // signature.
+ OS << "static const unsigned SignatureTable[] = {\n";
+ for (const auto &P : SignaturesList) {
+ OS << " // " << P.second << "\n ";
+ for (const Record *R : P.first) {
+ OS << TypeMap.find(R)->second << ", ";
}
+ OS << "\n";
}
OS << "};\n\n";
}
void BuiltinNameEmitter::EmitBuiltinTable() {
- OS << "static const OpenCLBuiltinDecl OpenCLBuiltins[] = {\n";
- for (auto &i : OverloadInfo) {
- StringRef Name = i.first;
- OS << "// " << Name << "\n";
- for (auto &Overload : i.second) {
- OS << " { " << Overload.first->getValueAsListOfDefs("Signature").size()
- << ", " << Overload.second << ", " << '"'
- << Overload.first->getValueAsString("Extension") << "\", "
- << Overload.first->getValueAsDef("Version")->getValueAsInt("Version")
+ unsigned Index = 0;
+
+ OS << "static const OpenCLBuiltinStruct BuiltinTable[] = {\n";
+ for (const auto &FOM : FctOverloadMap) {
+
+ OS << " // " << (Index + 1) << ": " << FOM.first << "\n";
+
+ for (const auto &Overload : FOM.second) {
+ OS << " { " << Overload.second << ", "
+ << Overload.first->getValueAsListOfDefs("Signature").size() << ", "
+ << Overload.first->getValueAsDef("MinVersion")->getValueAsInt("ID")
+ << ", "
+ << Overload.first->getValueAsDef("MaxVersion")->getValueAsInt("ID")
<< " },\n";
+ Index++;
}
}
OS << "};\n\n";
@@ -240,7 +422,7 @@ void BuiltinNameEmitter::EmitBuiltinTable() {
void BuiltinNameEmitter::EmitStringMatcher() {
std::vector<StringMatcher::StringPair> ValidBuiltins;
unsigned CumulativeIndex = 1;
- for (auto &i : OverloadInfo) {
+ for (auto &i : FctOverloadMap) {
auto &Ov = i.second;
std::string RetStmt;
raw_string_ostream SS(RetStmt);
@@ -253,30 +435,137 @@ void BuiltinNameEmitter::EmitStringMatcher() {
}
OS << R"(
-// Return 0 if name is not a recognized OpenCL builtin, or an index
-// into a table of declarations if it is an OpenCL builtin.
-static std::pair<unsigned, unsigned> isOpenCLBuiltin(llvm::StringRef name) {
+// Find out whether a string matches an existing OpenCL builtin function name.
+// Returns: A pair <0, 0> if no name matches.
+// A pair <Index, Len> indexing the BuiltinTable if the name is
+// matching an OpenCL builtin function.
+static std::pair<unsigned, unsigned> isOpenCLBuiltin(llvm::StringRef Name) {
)";
- StringMatcher("name", ValidBuiltins, OS).Emit(0, true);
+ StringMatcher("Name", ValidBuiltins, OS).Emit(0, true);
OS << " return std::make_pair(0, 0);\n";
- OS << "}\n";
+ OS << "} // isOpenCLBuiltin\n";
}
void BuiltinNameEmitter::EmitQualTypeFinder() {
OS << R"(
-static QualType OCL2Qual(ASTContext &Context, OpenCLType Ty) {
- QualType RT = Context.VoidTy;
- switch (Ty.ID) {
+// Convert an OpenCLTypeStruct type to a list of QualTypes.
+// Generic types represent multiple types and vector sizes, thus a vector
+// is returned. The conversion is done in two steps:
+// Step 1: A switch statement fills a vector with scalar base types for the
+// Cartesian product of (vector sizes) x (types) for generic types,
+// or a single scalar type for non generic types.
+// Step 2: Qualifiers and other type properties such as vector size are
+// applied.
+static void OCL2Qual(ASTContext &Context, const OpenCLTypeStruct &Ty,
+ llvm::SmallVectorImpl<QualType> &QT) {
+ // Number of scalar types in the GenType.
+ unsigned GenTypeNumTypes;
+ // Pointer to the list of vector sizes for the GenType.
+ llvm::ArrayRef<unsigned> GenVectorSizes;
)";
+ // Generate list of vector sizes for each generic type.
+ for (const auto *VectList : Records.getAllDerivedDefinitions("IntList")) {
+ OS << " constexpr unsigned List"
+ << VectList->getValueAsString("Name") << "[] = {";
+ for (const auto V : VectList->getValueAsListOfInts("List")) {
+ OS << V << ", ";
+ }
+ OS << "};\n";
+ }
+
+ // Step 1.
+ // Start of switch statement over all types.
+ OS << "\n switch (Ty.ID) {\n";
+
+ // Switch cases for image types (Image2d, Image3d, ...)
+ std::vector<Record *> ImageTypes =
+ Records.getAllDerivedDefinitions("ImageType");
+
+ // Map an image type name to its 3 access-qualified types (RO, WO, RW).
+ std::map<StringRef, SmallVector<Record *, 3>> ImageTypesMap;
+ for (auto *IT : ImageTypes) {
+ auto Entry = ImageTypesMap.find(IT->getValueAsString("Name"));
+ if (Entry == ImageTypesMap.end()) {
+ SmallVector<Record *, 3> ImageList;
+ ImageList.push_back(IT);
+ ImageTypesMap.insert(
+ std::make_pair(IT->getValueAsString("Name"), ImageList));
+ } else {
+ Entry->second.push_back(IT);
+ }
+ }
+
+ // Emit the cases for the image types. For an image type name, there are 3
+ // corresponding QualTypes ("RO", "WO", "RW"). The "AccessQualifier" field
+ // tells which one is needed. Emit a switch statement that puts the
+ // corresponding QualType into "QT".
+ for (const auto &ITE : ImageTypesMap) {
+ OS << " case OCLT_" << ITE.first.str() << ":\n"
+ << " switch (Ty.AccessQualifier) {\n"
+ << " case OCLAQ_None:\n"
+ << " llvm_unreachable(\"Image without access qualifier\");\n";
+ for (const auto &Image : ITE.second) {
+ OS << StringSwitch<const char *>(
+ Image->getValueAsString("AccessQualifier"))
+ .Case("RO", " case OCLAQ_ReadOnly:\n")
+ .Case("WO", " case OCLAQ_WriteOnly:\n")
+ .Case("RW", " case OCLAQ_ReadWrite:\n")
+ << " QT.push_back(Context."
+ << Image->getValueAsDef("QTName")->getValueAsString("Name") << ");\n"
+ << " break;\n";
+ }
+ OS << " }\n"
+ << " break;\n";
+ }
+
+ // Switch cases for generic types.
+ for (const auto *GenType : Records.getAllDerivedDefinitions("GenericType")) {
+ OS << " case OCLT_" << GenType->getValueAsString("Name") << ":\n";
+ OS << " QT.append({";
+
+ // Build the Cartesian product of (vector sizes) x (types). Only insert
+ // the plain scalar types for now; other type information such as vector
+ // size and type qualifiers will be added after the switch statement.
+ for (unsigned I = 0; I < GenType->getValueAsDef("VectorList")
+ ->getValueAsListOfInts("List")
+ .size();
+ I++) {
+ for (const auto *T :
+ GenType->getValueAsDef("TypeList")->getValueAsListOfDefs("List")) {
+ OS << "Context."
+ << T->getValueAsDef("QTName")->getValueAsString("Name") << ", ";
+ }
+ }
+ OS << "});\n";
+ // GenTypeNumTypes is the number of types in the GenType
+ // (e.g. float/double/half).
+ OS << " GenTypeNumTypes = "
+ << GenType->getValueAsDef("TypeList")->getValueAsListOfDefs("List")
+ .size()
+ << ";\n";
+ // GenVectorSizes is the list of vector sizes for this GenType.
+ // QT contains GenTypeNumTypes * #GenVectorSizes elements.
+ OS << " GenVectorSizes = List"
+ << GenType->getValueAsDef("VectorList")->getValueAsString("Name")
+ << ";\n";
+ OS << " break;\n";
+ }
+
+ // Switch cases for non generic, non image types (int, int4, float, ...).
+ // Only insert the plain scalar type; vector information and type qualifiers
+ // are added in step 2.
std::vector<Record *> Types = Records.getAllDerivedDefinitions("Type");
StringMap<bool> TypesSeen;
for (const auto *T : Types) {
+ // Check this is not an image type
+ if (ImageTypesMap.find(T->getValueAsString("Name")) != ImageTypesMap.end())
+ continue;
// Check we have not seen this Type
if (TypesSeen.find(T->getValueAsString("Name")) != TypesSeen.end())
continue;
@@ -284,35 +573,74 @@ static QualType OCL2Qual(ASTContext &Context, OpenCLType Ty) {
// Check the Type does not have an "abstract" QualType
auto QT = T->getValueAsDef("QTName");
- if (QT->getValueAsString("Name") == "null")
+ if (QT->getValueAsBit("IsAbstract") == 1)
continue;
+ // Emit the cases for non generic, non image types.
+ OS << " case OCLT_" << T->getValueAsString("Name") << ":\n";
+ OS << " QT.push_back(Context." << QT->getValueAsString("Name")
+ << ");\n";
+ OS << " break;\n";
+ }
- OS << " case OCLT_" << T->getValueAsString("Name") << ":\n";
- OS << " RT = Context." << QT->getValueAsString("Name") << ";\n";
- OS << " break;\n";
+ // End of switch statement.
+ OS << " default:\n"
+ << " llvm_unreachable(\"OpenCL builtin type not handled yet\");\n"
+ << " } // end of switch (Ty.ID)\n\n";
+
+ // Step 2.
+ // Add ExtVector types if this was a generic type, as the switch statement
+ // above only populated the list with scalar types. This completes the
+ // construction of the Cartesian product of (vector sizes) x (types).
+ OS << " // Construct the different vector types for each generic type.\n";
+ OS << " if (Ty.ID >= " << TypeList.size() << ") {";
+ OS << R"(
+ for (unsigned I = 0; I < QT.size(); I++) {
+ // For scalars, size is 1.
+ if (GenVectorSizes[I / GenTypeNumTypes] != 1) {
+ QT[I] = Context.getExtVectorType(QT[I],
+ GenVectorSizes[I / GenTypeNumTypes]);
+ }
+ }
}
- OS << " }\n";
+)";
- // Special cases
+ // Assign the right attributes to the types (e.g. vector size).
OS << R"(
- if (Ty.VectorWidth > 0)
- RT = Context.getExtVectorType(RT, Ty.VectorWidth);
+ // Set vector size for non-generic vector types.
+ if (Ty.VectorWidth > 1) {
+ for (unsigned Index = 0; Index < QT.size(); Index++) {
+ QT[Index] = Context.getExtVectorType(QT[Index], Ty.VectorWidth);
+ }
+ }
+
+ if (Ty.IsVolatile != 0) {
+ for (unsigned Index = 0; Index < QT.size(); Index++) {
+ QT[Index] = Context.getVolatileType(QT[Index]);
+ }
+ }
- if (Ty.isPointer) {
- RT = Context.getAddrSpaceQualType(RT, Ty.AS);
- RT = Context.getPointerType(RT);
+ if (Ty.IsConst != 0) {
+ for (unsigned Index = 0; Index < QT.size(); Index++) {
+ QT[Index] = Context.getConstType(QT[Index]);
+ }
}
- return RT;
-}
+ // Transform the type to a pointer as the last step, if necessary.
+ // Builtin functions only have pointers on [const|volatile], no
+ // [const|volatile] pointers, so this is ok to do it as a last step.
+ if (Ty.IsPointer != 0) {
+ for (unsigned Index = 0; Index < QT.size(); Index++) {
+ QT[Index] = Context.getAddrSpaceQualType(QT[Index], Ty.AS);
+ QT[Index] = Context.getPointerType(QT[Index]);
+ }
+ }
)";
-}
-namespace clang {
+ // End of the "OCL2Qual" function.
+ OS << "\n} // OCL2Qual\n";
+}
-void EmitClangOpenCLBuiltins(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitClangOpenCLBuiltins(RecordKeeper &Records, raw_ostream &OS) {
BuiltinNameEmitter NameChecker(Records, OS);
NameChecker.Emit();
}
-
-} // end namespace clang
diff --git a/utils/TableGen/ClangOptionDocEmitter.cpp b/utils/TableGen/ClangOptionDocEmitter.cpp
index 7027113c4fa81..b944ad9608f5e 100644
--- a/utils/TableGen/ClangOptionDocEmitter.cpp
+++ b/utils/TableGen/ClangOptionDocEmitter.cpp
@@ -8,6 +8,7 @@
//
//===----------------------------------------------------------------------===//
+#include "TableGenBackends.h"
#include "llvm/TableGen/Error.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
@@ -21,8 +22,6 @@
using namespace llvm;
-namespace clang {
-namespace docs {
namespace {
struct DocumentedOption {
Record *Option;
@@ -380,11 +379,8 @@ void emitDocumentation(int Depth, const Documentation &Doc,
}
} // namespace
-} // namespace docs
-
-void EmitClangOptDocs(RecordKeeper &Records, raw_ostream &OS) {
- using namespace docs;
+void clang::EmitClangOptDocs(RecordKeeper &Records, raw_ostream &OS) {
const Record *DocInfo = Records.getDef("GlobalDocumentation");
if (!DocInfo) {
PrintFatalError("The GlobalDocumentation top-level definition is missing, "
@@ -396,4 +392,3 @@ void EmitClangOptDocs(RecordKeeper &Records, raw_ostream &OS) {
emitDocumentation(0, extractDocumentation(Records), DocInfo, OS);
}
-} // end namespace clang
diff --git a/utils/TableGen/ClangSACheckersEmitter.cpp b/utils/TableGen/ClangSACheckersEmitter.cpp
index 7dd0895b76d45..feefbeb411387 100644
--- a/utils/TableGen/ClangSACheckersEmitter.cpp
+++ b/utils/TableGen/ClangSACheckersEmitter.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "TableGenBackends.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
@@ -174,8 +175,7 @@ static void printOption(llvm::raw_ostream &OS, StringRef FullName,
OS << "true";
}
-namespace clang {
-void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) {
std::vector<Record*> checkers = Records.getAllDerivedDefinitions("Checker");
std::vector<Record*> packages = Records.getAllDerivedDefinitions("Package");
@@ -315,4 +315,3 @@ void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) {
OS << "#endif // GET_CHECKER_OPTIONS\n"
"\n";
}
-} // end namespace clang
diff --git a/utils/TableGen/ClangTypeNodesEmitter.cpp b/utils/TableGen/ClangTypeNodesEmitter.cpp
new file mode 100644
index 0000000000000..c9986c8fa496b
--- /dev/null
+++ b/utils/TableGen/ClangTypeNodesEmitter.cpp
@@ -0,0 +1,220 @@
+//=== ClangTypeNodesEmitter.cpp - Generate type node tables -----*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This tblgen backend emits the node table (the .def file) for Clang
+// type nodes.
+//
+// This file defines the AST type info database. Each type node is
+// enumerated by providing its name (e.g., "Builtin" or "Enum") and
+// base class (e.g., "Type" or "TagType"). Depending on where in the
+// abstract syntax tree the type will show up, the enumeration uses
+// one of five different macros:
+//
+// TYPE(Class, Base) - A type that can show up anywhere in the AST,
+// and might be dependent, canonical, or non-canonical. All clients
+// will need to understand these types.
+//
+// ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
+// the type hierarchy but has no concrete instances.
+//
+// NON_CANONICAL_TYPE(Class, Base) - A type that can show up
+// anywhere in the AST but will never be a part of a canonical
+// type. Clients that only need to deal with canonical types
+// (ignoring, e.g., typedefs and other type aliases used for
+// pretty-printing) can ignore these types.
+//
+// DEPENDENT_TYPE(Class, Base) - A type that will only show up
+// within a C++ template that has not been instantiated, e.g., a
+// type that is always dependent. Clients that do not need to deal
+// with uninstantiated C++ templates can ignore these types.
+//
+// NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that
+// is non-canonical unless it is dependent. Defaults to TYPE because
+// it is neither reliably dependent nor reliably non-canonical.
+//
+// There is a sixth macro, independent of the others. Most clients
+// will not need to use it.
+//
+// LEAF_TYPE(Class) - A type that never has inner types. Clients
+// which can operate on such types more efficiently may wish to do so.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <set>
+#include <string>
+#include <vector>
+#include "TableGenBackends.h"
+
+using namespace llvm;
+
+// These are spellings in the generated output.
+#define TypeMacroName "TYPE"
+#define AbstractTypeMacroName "ABSTRACT_TYPE"
+#define DependentTypeMacroName "DEPENDENT_TYPE"
+#define NonCanonicalTypeMacroName "NON_CANONICAL_TYPE"
+#define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE"
+#define TypeMacroArgs "(Class, Base)"
+#define LastTypeMacroName "LAST_TYPE"
+#define LeafTypeMacroName "LEAF_TYPE"
+
+// These are spellings in the tblgen file.
+// (Type is also used for the spelling of the AST class.)
+#define TypeClassName "Type"
+#define DerivedTypeClassName "DerivedType"
+#define AlwaysDependentClassName "AlwaysDependent"
+#define NeverCanonicalClassName "NeverCanonical"
+#define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
+#define LeafTypeClassName "LeafType"
+#define AbstractFieldName "Abstract"
+#define BaseFieldName "Base"
+
+static StringRef getIdForType(Record *type) {
+ // The record name is expected to be the full C++ class name,
+ // including "Type". Check for that and strip it off.
+ auto fullName = type->getName();
+ if (!fullName.endswith("Type"))
+ PrintFatalError(type->getLoc(), "name of Type node doesn't end in Type");
+ return fullName.drop_back(4);
+}
+
+namespace {
+class TypeNodeEmitter {
+ RecordKeeper &Records;
+ raw_ostream &Out;
+ const std::vector<Record*> Types;
+ std::vector<StringRef> MacrosToUndef;
+
+public:
+ TypeNodeEmitter(RecordKeeper &records, raw_ostream &out)
+ : Records(records), Out(out),
+ Types(Records.getAllDerivedDefinitions("Type")) {
+ }
+
+ void emit();
+
+private:
+ void emitFallbackDefine(StringRef macroName, StringRef fallbackMacroName,
+ StringRef args);
+
+ void emitNodeInvocations();
+ void emitLastNodeInvocation();
+ void emitLeafNodeInvocations();
+
+ void addMacroToUndef(StringRef macroName);
+ void emitUndefs();
+};
+}
+
+void TypeNodeEmitter::emit() {
+ if (Types.empty())
+ PrintFatalError("no Type records in input!");
+
+ emitSourceFileHeader("An x-macro database of Clang type nodes", Out);
+
+ // Preamble
+ addMacroToUndef(TypeMacroName);
+ addMacroToUndef(AbstractTypeMacroName);
+ emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs);
+ emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs);
+ emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs);
+ emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName,
+ TypeMacroArgs);
+
+ // Invocations.
+ emitNodeInvocations();
+ emitLastNodeInvocation();
+ emitLeafNodeInvocations();
+
+ // Postmatter
+ emitUndefs();
+}
+
+void TypeNodeEmitter::emitFallbackDefine(StringRef macroName,
+ StringRef fallbackMacroName,
+ StringRef args) {
+ Out << "#ifndef " << macroName << "\n";
+ Out << "# define " << macroName << args
+ << " " << fallbackMacroName << args << "\n";
+ Out << "#endif\n";
+
+ addMacroToUndef(macroName);
+}
+
+void TypeNodeEmitter::emitNodeInvocations() {
+ for (auto type : Types) {
+ // The name with the Type suffix.
+ StringRef id = getIdForType(type);
+
+ // Figure out which macro to use.
+ StringRef macroName;
+ auto setMacroName = [&](StringRef newName) {
+ if (!macroName.empty())
+ PrintFatalError(type->getLoc(),
+ Twine("conflict when computing macro name for "
+ "Type node: trying to use both \"")
+ + macroName + "\" and \"" + newName + "\"");
+ macroName = newName;
+ };
+ if (type->isSubClassOf(AlwaysDependentClassName))
+ setMacroName(DependentTypeMacroName);
+ if (type->isSubClassOf(NeverCanonicalClassName))
+ setMacroName(NonCanonicalTypeMacroName);
+ if (type->isSubClassOf(NeverCanonicalUnlessDependentClassName))
+ setMacroName(NonCanonicalUnlessDependentTypeMacroName);
+ if (type->getValueAsBit(AbstractFieldName))
+ setMacroName(AbstractTypeMacroName);
+ if (macroName.empty())
+ macroName = TypeMacroName;
+
+ // Compute the base class.
+ StringRef baseName = TypeClassName;
+ if (type->isSubClassOf(DerivedTypeClassName))
+ baseName = type->getValueAsDef(BaseFieldName)->getName();
+
+ // Generate the invocation line.
+ Out << macroName << "(" << id << ", " << baseName << ")\n";
+ }
+}
+
+void TypeNodeEmitter::emitLastNodeInvocation() {
+ // We check that this is non-empty earlier.
+ Out << "#ifdef " LastTypeMacroName "\n"
+ LastTypeMacroName "(" << getIdForType(Types.back()) << ")\n"
+ "#undef " LastTypeMacroName "\n"
+ "#endif\n";
+}
+
+void TypeNodeEmitter::emitLeafNodeInvocations() {
+ Out << "#ifdef " LeafTypeMacroName "\n";
+
+ for (auto type : Types) {
+ if (!type->isSubClassOf(LeafTypeClassName)) continue;
+ Out << LeafTypeMacroName "(" << getIdForType(type) << ")\n";
+ }
+
+ Out << "#undef " LeafTypeMacroName "\n"
+ "#endif\n";
+}
+
+void TypeNodeEmitter::addMacroToUndef(StringRef macroName) {
+ MacrosToUndef.push_back(macroName);
+}
+
+void TypeNodeEmitter::emitUndefs() {
+ for (auto &macroName : MacrosToUndef) {
+ Out << "#undef " << macroName << "\n";
+ }
+}
+
+void clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) {
+ TypeNodeEmitter(records, out).emit();
+}
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 5cb688061dcb8..9d668a2815341 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -23,6 +23,7 @@
//
//===----------------------------------------------------------------------===//
+#include "TableGenBackends.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/None.h"
@@ -332,6 +333,17 @@ class Intrinsic {
NeonEmitter &Emitter;
std::stringstream OS;
+ bool isBigEndianSafe() const {
+ if (BigEndianSafe)
+ return true;
+
+ for (const auto &T : Types){
+ if (T.isVector() && T.getNumElements() > 1)
+ return false;
+ }
+ return true;
+ }
+
public:
Intrinsic(Record *R, StringRef Name, StringRef Proto, TypeSpec OutTS,
TypeSpec InTS, ClassKind CK, ListInit *Body, NeonEmitter &Emitter,
@@ -624,7 +636,7 @@ std::string Type::builtin_str() const {
default: llvm_unreachable("Unhandled case!");
}
- if (isChar() && !Pointer)
+ if (isChar() && !Pointer && Signed)
// Make chars explicitly signed.
S = "S" + S;
else if (isInteger() && !Pointer && !Signed)
@@ -1293,7 +1305,7 @@ void Intrinsic::emitReverseVariable(Variable &Dest, Variable &Src) {
}
void Intrinsic::emitArgumentReversal() {
- if (BigEndianSafe)
+ if (isBigEndianSafe())
return;
// Reverse all vector arguments.
@@ -1314,7 +1326,7 @@ void Intrinsic::emitArgumentReversal() {
}
void Intrinsic::emitReturnReversal() {
- if (BigEndianSafe)
+ if (isBigEndianSafe())
return;
if (!getReturnType().isVector() || getReturnType().isVoid() ||
getReturnType().getNumElements() == 1)
@@ -1401,7 +1413,7 @@ void Intrinsic::emitBodyAsBuiltinCall() {
if (T.getNumVectors() > 1) {
// Check if an explicit cast is needed.
std::string Cast;
- if (T.isChar() || T.isPoly() || !T.isSigned()) {
+ if (LocalCK == ClassB) {
Type T2 = T;
T2.makeOneVector();
T2.makeInteger(8, /*Signed=*/true);
@@ -1430,9 +1442,13 @@ void Intrinsic::emitBodyAsBuiltinCall() {
}
// Check if an explicit cast is needed.
- if (CastToType.isVector()) {
+ if (CastToType.isVector() &&
+ (LocalCK == ClassB || (T.isHalf() && !T.isScalarForMangling()))) {
CastToType.makeInteger(8, true);
Arg = "(" + CastToType.str() + ")" + Arg;
+ } else if (CastToType.isVector() && LocalCK == ClassI) {
+ CastToType.makeSigned();
+ Arg = "(" + CastToType.str() + ")" + Arg;
}
S += Arg + ", ";
@@ -1578,7 +1594,10 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) {
Intr.Dependencies.insert(&Callee);
// Now create the call itself.
- std::string S = CallPrefix.str() + Callee.getMangledName(true) + "(";
+ std::string S = "";
+ if (!Callee.isBigEndianSafe())
+ S += CallPrefix.str();
+ S += Callee.getMangledName(true) + "(";
for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) {
if (I != 0)
S += ", ";
@@ -1732,12 +1751,12 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){
SetTheory ST;
SetTheory::RecSet Elts;
- ST.addOperator("lowhalf", llvm::make_unique<LowHalf>());
- ST.addOperator("highhalf", llvm::make_unique<HighHalf>());
+ ST.addOperator("lowhalf", std::make_unique<LowHalf>());
+ ST.addOperator("highhalf", std::make_unique<HighHalf>());
ST.addOperator("rev",
- llvm::make_unique<Rev>(Arg1.first.getElementSizeInBits()));
+ std::make_unique<Rev>(Arg1.first.getElementSizeInBits()));
ST.addExpander("MaskExpand",
- llvm::make_unique<MaskExpander>(Arg1.first.getNumElements()));
+ std::make_unique<MaskExpander>(Arg1.first.getNumElements()));
ST.evaluate(DI->getArg(2), Elts, None);
std::string S = "__builtin_shufflevector(" + Arg1.second + ", " + Arg2.second;
@@ -1889,6 +1908,11 @@ Intrinsic::DagEmitter::emitDagArg(Init *Arg, std::string ArgName) {
}
std::string Intrinsic::generate() {
+ // Avoid duplicated code for big and little endian
+ if (isBigEndianSafe()) {
+ generateImpl(false, "", "");
+ return OS.str();
+ }
// Little endian intrinsics are simple and don't require any argument
// swapping.
OS << "#ifdef __LITTLE_ENDIAN__\n";
@@ -2456,7 +2480,7 @@ void NeonEmitter::run(raw_ostream &OS) {
for (auto *I : Defs)
I->indexBody();
- llvm::stable_sort(Defs, llvm::less_ptr<Intrinsic>());
+ llvm::stable_sort(Defs, llvm::deref<std::less<>>());
// Only emit a def when its requirements have been met.
// FIXME: This loop could be made faster, but it's fast enough for now.
@@ -2563,7 +2587,7 @@ void NeonEmitter::runFP16(raw_ostream &OS) {
for (auto *I : Defs)
I->indexBody();
- llvm::stable_sort(Defs, llvm::less_ptr<Intrinsic>());
+ llvm::stable_sort(Defs, llvm::deref<std::less<>>());
// Only emit a def when its requirements have been met.
// FIXME: This loop could be made faster, but it's fast enough for now.
@@ -2610,22 +2634,18 @@ void NeonEmitter::runFP16(raw_ostream &OS) {
OS << "#endif /* __ARM_FP16_H */\n";
}
-namespace clang {
-
-void EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).run(OS);
}
-void EmitFP16(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitFP16(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).runFP16(OS);
}
-void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).runHeader(OS);
}
-void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
+void clang::EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
llvm_unreachable("Neon test generation no longer implemented!");
}
-
-} // end namespace clang
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index b9ec90fd5bccc..d0f8a7564496b 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -47,6 +47,8 @@ enum ActionType {
GenClangCommentNodes,
GenClangDeclNodes,
GenClangStmtNodes,
+ GenClangTypeNodes,
+ GenClangOpcodes,
GenClangSACheckers,
GenClangCommentHTMLTags,
GenClangCommentHTMLTagsProperties,
@@ -129,6 +131,10 @@ cl::opt<ActionType> Action(
"Generate Clang AST declaration nodes"),
clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
"Generate Clang AST statement nodes"),
+ clEnumValN(GenClangTypeNodes, "gen-clang-type-nodes",
+ "Generate Clang AST type nodes"),
+ clEnumValN(GenClangOpcodes, "gen-clang-opcodes",
+ "Generate Clang constexpr interpreter opcodes"),
clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
"Generate Clang Static Analyzer checkers"),
clEnumValN(GenClangCommentHTMLTags, "gen-clang-comment-html-tags",
@@ -251,6 +257,12 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenClangStmtNodes:
EmitClangASTNodes(Records, OS, "Stmt", "");
break;
+ case GenClangTypeNodes:
+ EmitClangTypeNodes(Records, OS);
+ break;
+ case GenClangOpcodes:
+ EmitClangOpcodes(Records, OS);
+ break;
case GenClangSACheckers:
EmitClangSACheckers(Records, OS);
break;
diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
index 02af66c5bf814..cdd492b4e558d 100644
--- a/utils/TableGen/TableGenBackends.h
+++ b/utils/TableGen/TableGenBackends.h
@@ -27,6 +27,7 @@ namespace clang {
void EmitClangDeclContext(llvm::RecordKeeper &RK, llvm::raw_ostream &OS);
void EmitClangASTNodes(llvm::RecordKeeper &RK, llvm::raw_ostream &OS,
const std::string &N, const std::string &S);
+void EmitClangTypeNodes(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitClangAttrParserStringSwitches(llvm::RecordKeeper &Records,
llvm::raw_ostream &OS);
@@ -77,6 +78,7 @@ void EmitClangCommentCommandInfo(llvm::RecordKeeper &Records,
llvm::raw_ostream &OS);
void EmitClangCommentCommandList(llvm::RecordKeeper &Records,
llvm::raw_ostream &OS);
+void EmitClangOpcodes(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);