aboutsummaryrefslogtreecommitdiff
path: root/utils/TableGen
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
commit45b533945f0851ec234ca846e1af5ee1e4df0b6e (patch)
tree0a5b74c0b9ca73aded34df95c91fcaf3815230d8 /utils/TableGen
parent7e86edd64bfae4e324224452e4ea879b3371a4bd (diff)
downloadsrc-45b533945f0851ec234ca846e1af5ee1e4df0b6e.tar.gz
src-45b533945f0851ec234ca846e1af5ee1e4df0b6e.zip
Vendor import of clang trunk r256633:vendor/clang/clang-trunk-r256633
Notes
Notes: svn path=/vendor/clang/dist/; revision=292920 svn path=/vendor/clang/clang-trunk-r256633/; revision=292923; tag=vendor/clang/clang-trunk-r256633
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp348
-rw-r--r--utils/TableGen/ClangCommentCommandInfoEmitter.cpp3
-rw-r--r--utils/TableGen/NeonEmitter.cpp83
3 files changed, 235 insertions, 199 deletions
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index f2aa4002b99f..f70bff2c3b74 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -54,7 +54,7 @@ public:
const std::string &nameSpace() const { return NS; }
bool knownToGCC() const { return K; }
};
-} // namespace
+} // end anonymous namespace
static std::vector<FlattenedSpelling>
GetFlattenedSpellings(const Record &Attr) {
@@ -166,17 +166,18 @@ namespace {
std::string lowerName, upperName;
StringRef attrName;
bool isOpt;
+ bool Fake;
public:
Argument(const Record &Arg, StringRef Attr)
: lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
- attrName(Attr), isOpt(false) {
+ attrName(Attr), isOpt(false), Fake(false) {
if (!lowerName.empty()) {
lowerName[0] = std::tolower(lowerName[0]);
upperName[0] = std::toupper(upperName[0]);
}
}
- virtual ~Argument() {}
+ virtual ~Argument() = default;
StringRef getLowerName() const { return lowerName; }
StringRef getUpperName() const { return upperName; }
@@ -185,6 +186,9 @@ namespace {
bool isOptional() const { return isOpt; }
void setOptional(bool set) { isOpt = set; }
+ bool isFake() const { return Fake; }
+ void setFake(bool fake) { Fake = fake; }
+
// These functions print the argument contents formatted in different ways.
virtual void writeAccessors(raw_ostream &OS) const = 0;
virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
@@ -275,6 +279,8 @@ namespace {
OS << " OS << \" \";\n";
OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
} else if (type == "IdentifierInfo *") {
+ if (isOptional())
+ OS << " if (SA->get" << getUpperName() << "())\n ";
OS << " OS << \" \" << SA->get" << getUpperName()
<< "()->getName();\n";
} else if (type == "TypeSourceInfo *") {
@@ -348,7 +354,7 @@ namespace {
<< "Length])";
}
void writeCtorDefaultInitializers(raw_ostream &OS) const override {
- OS << getLowerName() << "Length(0)," << getLowerName() << "(0)";
+ OS << getLowerName() << "Length(0)," << getLowerName() << "(nullptr)";
}
void writeCtorParameters(raw_ostream &OS) const override {
OS << "llvm::StringRef " << getUpperName();
@@ -491,7 +497,7 @@ namespace {
// The aligned attribute argument expression is optional.
OS << " if (is" << getLowerName() << "Expr && "
<< getLowerName() << "Expr)\n";
- OS << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n";
+ OS << " " << getLowerName() << "Expr->printPretty(OS, nullptr, Policy);\n";
OS << " OS << \"";
}
void writeDump(raw_ostream &OS) const override {
@@ -613,7 +619,7 @@ namespace {
std::vector<std::string> uniques;
std::set<std::string> unique_set(enums.begin(), enums.end());
for (const auto &i : enums) {
- std::set<std::string>::iterator set_i = unique_set.find(i);
+ auto set_i = unique_set.find(i);
if (set_i != unique_set.end()) {
uniques.push_back(i);
unique_set.erase(set_i);
@@ -659,8 +665,7 @@ namespace {
OS << type << " " << getUpperName();
}
void writeDeclarations(raw_ostream &OS) const override {
- std::vector<std::string>::const_iterator i = uniques.begin(),
- e = uniques.end();
+ auto i = uniques.cbegin(), e = uniques.cend();
// The last one needs to not have a comma.
--e;
@@ -765,8 +770,7 @@ namespace {
bool isVariadicEnumArg() const override { return true; }
void writeDeclarations(raw_ostream &OS) const override {
- std::vector<std::string>::const_iterator i = uniques.begin(),
- e = uniques.end();
+ auto i = uniques.cbegin(), e = uniques.cend();
// The last one needs to not have a comma.
--e;
@@ -952,7 +956,7 @@ namespace {
}
void writeTemplateInstantiation(raw_ostream &OS) const override {
- OS << " " << getType() << " *tempInst" << getUpperName()
+ OS << " auto *tempInst" << getUpperName()
<< " = new (C, 16) " << getType()
<< "[A->" << getLowerName() << "_size()];\n";
OS << " {\n";
@@ -1018,7 +1022,7 @@ namespace {
getType(), "SA->get" + std::string(getUpperName()) + "Loc()");
}
};
-}
+} // end anonymous namespace
static std::unique_ptr<Argument>
createArgument(const Record &Arg, StringRef Attr,
@@ -1078,6 +1082,9 @@ createArgument(const Record &Arg, StringRef Attr,
if (Ptr && Arg.getValueAsBit("Optional"))
Ptr->setOptional(true);
+ if (Ptr && Arg.getValueAsBit("Fake"))
+ Ptr->setFake(true);
+
return Ptr;
}
@@ -1180,28 +1187,39 @@ writePrettyPrintFunction(Record &R,
if (Variety == "Pragma") {
OS << " \";\n";
OS << " printPrettyPragma(OS, Policy);\n";
+ OS << " OS << \"\\n\";";
OS << " break;\n";
OS << " }\n";
continue;
}
+ // Fake arguments aren't part of the parsed form and should not be
+ // pretty-printed.
+ bool hasNonFakeArgs = false;
+ for (const auto &arg : Args) {
+ if (arg->isFake()) continue;
+ hasNonFakeArgs = true;
+ }
+
// FIXME: always printing the parenthesis isn't the correct behavior for
// attributes which have optional arguments that were not provided. For
// instance: __attribute__((aligned)) will be pretty printed as
// __attribute__((aligned())). The logic should check whether there is only
// a single argument, and if it is optional, whether it has been provided.
- if (!Args.empty())
+ if (hasNonFakeArgs)
OS << "(";
if (Spelling == "availability") {
writeAvailabilityValue(OS);
} else {
- for (auto I = Args.begin(), E = Args.end(); I != E; ++ I) {
- if (I != Args.begin()) OS << ", ";
- (*I)->writeValue(OS);
+ unsigned index = 0;
+ for (const auto &arg : Args) {
+ if (arg->isFake()) continue;
+ if (index++) OS << ", ";
+ arg->writeValue(OS);
}
}
- if (!Args.empty())
+ if (hasNonFakeArgs)
OS << ")";
OS << Suffix + "\";\n";
@@ -1473,10 +1491,19 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
std::vector<std::unique_ptr<Argument>> Args;
Args.reserve(ArgRecords.size());
+ bool HasOptArg = false;
+ bool HasFakeArg = false;
for (const auto *ArgRecord : ArgRecords) {
Args.emplace_back(createArgument(*ArgRecord, R.getName()));
Args.back()->writeDeclarations(OS);
OS << "\n\n";
+
+ // For these purposes, fake takes priority over optional.
+ if (Args.back()->isFake()) {
+ HasFakeArg = true;
+ } else if (Args.back()->isOptional()) {
+ HasOptArg = true;
+ }
}
OS << "\npublic:\n";
@@ -1495,69 +1522,53 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
if (!ElideSpelling)
OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
- OS << " static " << R.getName() << "Attr *CreateImplicit(";
- OS << "ASTContext &Ctx";
- if (!ElideSpelling)
- OS << ", Spelling S";
- for (auto const &ai : Args) {
- OS << ", ";
- ai->writeCtorParameters(OS);
- }
- OS << ", SourceRange Loc = SourceRange()";
- OS << ") {\n";
- OS << " " << R.getName() << "Attr *A = new (Ctx) " << R.getName();
- OS << "Attr(Loc, Ctx, ";
- for (auto const &ai : Args) {
- ai->writeImplicitCtorArgs(OS);
- OS << ", ";
- }
- OS << (ElideSpelling ? "0" : "S") << ");\n";
- OS << " A->setImplicit(true);\n";
- OS << " return A;\n }\n\n";
-
- OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
-
- bool HasOpt = false;
- for (auto const &ai : Args) {
- OS << " , ";
- ai->writeCtorParameters(OS);
- OS << "\n";
- if (ai->isOptional())
- HasOpt = true;
- }
-
- OS << " , ";
- OS << "unsigned SI\n";
+ // Emit CreateImplicit factory methods.
+ auto emitCreateImplicit = [&](bool emitFake) {
+ OS << " static " << R.getName() << "Attr *CreateImplicit(";
+ 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 << " auto *A = new (Ctx) " << R.getName();
+ OS << "Attr(Loc, Ctx, ";
+ for (auto const &ai : Args) {
+ if (ai->isFake() && !emitFake) continue;
+ ai->writeImplicitCtorArgs(OS);
+ OS << ", ";
+ }
+ OS << (ElideSpelling ? "0" : "S") << ");\n";
+ OS << " A->setImplicit(true);\n";
+ OS << " return A;\n }\n\n";
+ };
- OS << " )\n";
- OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, "
- << R.getValueAsBit("LateParsed") << ", "
- << R.getValueAsBit("DuplicatesAllowedWhileMerging") << ")\n";
+ // Emit a CreateImplicit that takes all the arguments.
+ emitCreateImplicit(true);
- for (auto const &ai : Args) {
- OS << " , ";
- ai->writeCtorInitializers(OS);
- OS << "\n";
+ // Emit a CreateImplicit that takes all the non-fake arguments.
+ if (HasFakeArg) {
+ emitCreateImplicit(false);
}
- OS << " {\n";
-
- for (auto const &ai : Args) {
- ai->writeCtorBody(OS);
- OS << "\n";
- }
- OS << " }\n\n";
+ // Emit constructors.
+ auto emitCtor = [&](bool emitOpt, bool emitFake) {
+ auto shouldEmitArg = [=](const std::unique_ptr<Argument> &arg) {
+ if (arg->isFake()) return emitFake;
+ if (arg->isOptional()) return emitOpt;
+ return true;
+ };
- // If there are optional arguments, write out a constructor that elides the
- // optional arguments as well.
- if (HasOpt) {
OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
for (auto const &ai : Args) {
- if (!ai->isOptional()) {
- OS << " , ";
- ai->writeCtorParameters(OS);
- OS << "\n";
- }
+ if (!shouldEmitArg(ai)) continue;
+ OS << " , ";
+ ai->writeCtorParameters(OS);
+ OS << "\n";
}
OS << " , ";
@@ -1570,19 +1581,37 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
for (auto const &ai : Args) {
OS << " , ";
- ai->writeCtorDefaultInitializers(OS);
+ if (!shouldEmitArg(ai)) {
+ ai->writeCtorDefaultInitializers(OS);
+ } else {
+ ai->writeCtorInitializers(OS);
+ }
OS << "\n";
}
OS << " {\n";
for (auto const &ai : Args) {
- if (!ai->isOptional()) {
- ai->writeCtorBody(OS);
- OS << "\n";
- }
+ if (!shouldEmitArg(ai)) continue;
+ ai->writeCtorBody(OS);
+ OS << "\n";
}
OS << " }\n\n";
+
+ };
+
+ // Emit a constructor that includes all the arguments.
+ // This is necessary for cloning.
+ emitCtor(true, true);
+
+ // Emit a constructor that takes all the non-fake arguments.
+ if (HasFakeArg) {
+ emitCtor(true, false);
+ }
+
+ // Emit a constructor that takes all the non-fake, non-optional arguments.
+ if (HasOptArg) {
+ emitCtor(false, false);
}
OS << " " << R.getName() << "Attr *clone(ASTContext &C) const;\n";
@@ -1604,6 +1633,9 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
ai->writeAccessors(OS);
OS << "\n\n";
+ // Don't write conversion routines for fake arguments.
+ if (ai->isFake()) continue;
+
if (ai->isEnumArg())
static_cast<const EnumArgument *>(ai.get())->writeConversion(OS);
else if (ai->isVariadicEnumArg())
@@ -1620,7 +1652,7 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
OS << "};\n\n";
}
- OS << "#endif\n";
+ OS << "#endif // LLVM_CLANG_ATTR_CLASSES_INC\n";
}
// Emits the class method definitions for attributes.
@@ -1695,7 +1727,7 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
static void EmitAttrList(raw_ostream &OS, StringRef Class,
const std::vector<Record*> &AttrList) {
- std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
+ auto i = AttrList.cbegin(), e = AttrList.cend();
if (i != e) {
// Move the end iterator back to emit the last attribute.
@@ -1847,7 +1879,7 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
OS << " case attr::" << R.getName() << ": {\n";
Args = R.getValueAsListOfDefs("Args");
if (R.isSubClassOf(InhClass) || !Args.empty())
- OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
+ OS << " const auto *SA = cast<" << R.getName()
<< "Attr>(A);\n";
if (R.isSubClassOf(InhClass))
OS << " Record.push_back(SA->isInherited());\n";
@@ -1862,6 +1894,65 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
OS << " }\n";
}
+// Generate a conditional expression to check if the current target satisfies
+// the conditions for a TargetSpecificAttr record, and append the code for
+// those checks to the Test string. If the FnName string pointer is non-null,
+// append a unique suffix to distinguish this set of target checks from other
+// TargetSpecificAttr records.
+static void GenerateTargetSpecificAttrChecks(const Record *R,
+ std::vector<std::string> &Arches,
+ std::string &Test,
+ std::string *FnName) {
+ // It is assumed that there will be an llvm::Triple object
+ // named "T" and a TargetInfo object named "Target" within
+ // scope that can be used to determine whether the attribute exists in
+ // a given target.
+ Test += "(";
+
+ for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
+ std::string Part = *I;
+ Test += "T.getArch() == llvm::Triple::" + Part;
+ if (I + 1 != E)
+ Test += " || ";
+ if (FnName)
+ *FnName += Part;
+ }
+ Test += ")";
+
+ // If the attribute is specific to particular OSes, check those.
+ if (!R->isValueUnset("OSes")) {
+ // We know that there was at least one arch test, so we need to and in the
+ // OS tests.
+ Test += " && (";
+ std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
+ for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
+ std::string Part = *I;
+
+ Test += "T.getOS() == llvm::Triple::" + Part;
+ if (I + 1 != E)
+ Test += " || ";
+ if (FnName)
+ *FnName += Part;
+ }
+ Test += ")";
+ }
+
+ // If one or more CXX ABIs are specified, check those as well.
+ if (!R->isValueUnset("CXXABIs")) {
+ Test += " && (";
+ std::vector<std::string> CXXABIs = R->getValueAsListOfStrings("CXXABIs");
+ for (auto I = CXXABIs.begin(), E = CXXABIs.end(); I != E; ++I) {
+ std::string Part = *I;
+ Test += "Target.getCXXABI().getKind() == TargetCXXABI::" + Part;
+ if (I + 1 != E)
+ Test += " || ";
+ if (FnName)
+ *FnName += Part;
+ }
+ Test += ")";
+ }
+}
+
static void GenerateHasAttrSpellingStringSwitch(
const std::vector<Record *> &Attrs, raw_ostream &OS,
const std::string &Variety = "", const std::string &Scope = "") {
@@ -1887,37 +1978,12 @@ static void GenerateHasAttrSpellingStringSwitch(
}
}
- // It is assumed that there will be an llvm::Triple object named T within
- // scope that can be used to determine whether the attribute exists in
- // a given target.
std::string Test;
if (Attr->isSubClassOf("TargetSpecificAttr")) {
const Record *R = Attr->getValueAsDef("Target");
std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
+ GenerateTargetSpecificAttrChecks(R, Arches, Test, nullptr);
- Test += "(";
- for (auto AI = Arches.begin(), AE = Arches.end(); AI != AE; ++AI) {
- std::string Part = *AI;
- Test += "T.getArch() == llvm::Triple::" + Part;
- if (AI + 1 != AE)
- Test += " || ";
- }
- Test += ")";
-
- std::vector<std::string> OSes;
- if (!R->isValueUnset("OSes")) {
- Test += " && (";
- std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
- for (auto AI = OSes.begin(), AE = OSes.end(); AI != AE; ++AI) {
- std::string Part = *AI;
-
- Test += "T.getOS() == llvm::Triple::" + Part;
- if (AI + 1 != AE)
- Test += " || ";
- }
- Test += ")";
- }
-
// If this is the C++11 variety, also add in the LangOpts test.
if (Variety == "CXX11")
Test += " && LangOpts.CPlusPlus11";
@@ -1964,6 +2030,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
}
}
+ OS << "const llvm::Triple &T = Target.getTriple();\n";
OS << "switch (Syntax) {\n";
OS << "case AttrSyntax::GNU:\n";
OS << " return llvm::StringSwitch<int>(Name)\n";
@@ -1976,9 +2043,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma");
OS << "case AttrSyntax::CXX: {\n";
// C++11-style attributes are further split out based on the Scope.
- for (std::map<std::string, std::vector<Record *>>::iterator I = CXX.begin(),
- E = CXX.end();
- I != E; ++I) {
+ for (auto I = CXX.cbegin(), E = CXX.cend(); I != E; ++I) {
if (I != CXX.begin())
OS << " else ";
if (I->first.empty())
@@ -2049,7 +2114,7 @@ void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
OS << " bool Visit"
<< R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
<< " return true; \n"
- << " };\n";
+ << " }\n";
}
OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";
@@ -2123,12 +2188,12 @@ void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
bool ShouldClone = R.getValueAsBit("Clone");
if (!ShouldClone) {
- OS << " return NULL;\n";
+ OS << " return nullptr;\n";
OS << " }\n";
continue;
}
- OS << " const " << R.getName() << "Attr *A = cast<"
+ OS << " const auto *A = cast<"
<< R.getName() << "Attr>(At);\n";
bool TDependent = R.getValueAsBit("TemplateDependent");
@@ -2157,7 +2222,7 @@ void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
}
OS << " } // end switch\n"
<< " llvm_unreachable(\"Unknown attribute!\");\n"
- << " return 0;\n"
+ << " return nullptr;\n"
<< "}\n\n"
<< "} // end namespace sema\n"
<< "} // end namespace clang\n";
@@ -2328,6 +2393,7 @@ static std::string GetSubjectWithSuffix(const Record *R) {
return "Decl";
return B + "Decl";
}
+
static std::string GenerateCustomAppertainsTo(const Record &Subject,
raw_ostream &OS) {
std::string FnName = "is" + Subject.getName();
@@ -2335,7 +2401,7 @@ static std::string GenerateCustomAppertainsTo(const Record &Subject,
// If this code has already been generated, simply return the previous
// instance of it.
static std::set<std::string> CustomSubjectSet;
- std::set<std::string>::iterator I = CustomSubjectSet.find(FnName);
+ auto I = CustomSubjectSet.find(FnName);
if (I != CustomSubjectSet.end())
return *I;
@@ -2349,7 +2415,7 @@ static std::string GenerateCustomAppertainsTo(const Record &Subject,
}
OS << "static bool " << FnName << "(const Decl *D) {\n";
- OS << " if (const " << GetSubjectWithSuffix(Base) << " *S = dyn_cast<";
+ OS << " if (const auto *S = dyn_cast<";
OS << GetSubjectWithSuffix(Base);
OS << ">(D))\n";
OS << " return " << Subject.getValueAsString("CheckCode") << ";\n";
@@ -2449,7 +2515,7 @@ static std::string GenerateLangOptRequirements(const Record &R,
// If this code has already been generated, simply return the previous
// instance of it.
static std::set<std::string> CustomLangOptsSet;
- std::set<std::string>::iterator I = CustomLangOptsSet.find(FnName);
+ auto I = CustomLangOptsSet.find(FnName);
if (I != CustomLangOptsSet.end())
return *I;
@@ -2466,7 +2532,7 @@ static std::string GenerateLangOptRequirements(const Record &R,
}
static void GenerateDefaultTargetRequirements(raw_ostream &OS) {
- OS << "static bool defaultTargetRequirements(const llvm::Triple &) {\n";
+ OS << "static bool defaultTargetRequirements(const TargetInfo &) {\n";
OS << " return true;\n";
OS << "}\n\n";
}
@@ -2505,47 +2571,19 @@ static std::string GenerateTargetRequirements(const Record &Attr,
}
}
- std::string FnName = "isTarget", Test = "(";
- for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
- std::string Part = *I;
- Test += "Arch == llvm::Triple::" + Part;
- if (I + 1 != E)
- Test += " || ";
- FnName += Part;
- }
- Test += ")";
-
- // If the target also requires OS testing, generate those tests as well.
- bool UsesOS = false;
- if (!R->isValueUnset("OSes")) {
- UsesOS = true;
-
- // We know that there was at least one arch test, so we need to and in the
- // OS tests.
- Test += " && (";
- std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
- for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
- std::string Part = *I;
-
- Test += "OS == llvm::Triple::" + Part;
- if (I + 1 != E)
- Test += " || ";
- FnName += Part;
- }
- Test += ")";
- }
+ std::string FnName = "isTarget";
+ std::string Test;
+ GenerateTargetSpecificAttrChecks(R, Arches, Test, &FnName);
// If this code has already been generated, simply return the previous
// instance of it.
static std::set<std::string> CustomTargetSet;
- std::set<std::string>::iterator I = CustomTargetSet.find(FnName);
+ auto I = CustomTargetSet.find(FnName);
if (I != CustomTargetSet.end())
return *I;
- OS << "static bool " << FnName << "(const llvm::Triple &T) {\n";
- OS << " llvm::Triple::ArchType Arch = T.getArch();\n";
- if (UsesOS)
- OS << " llvm::Triple::OSType OS = T.getOS();\n";
+ OS << "static bool " << FnName << "(const TargetInfo &Target) {\n";
+ OS << " const llvm::Triple &T = Target.getTriple();\n";
OS << " return " << Test << ";\n";
OS << "}\n\n";
@@ -2758,13 +2796,13 @@ void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
Args = R.getValueAsListOfDefs("Args");
if (!Args.empty()) {
- OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
+ OS << " const auto *SA = cast<" << R.getName()
<< "Attr>(A);\n";
for (const auto *Arg : Args)
createArgument(*Arg, R.getName())->writeDump(OS);
- for (auto AI = Args.begin(), AE = Args.end(); AI != AE; ++AI)
- createArgument(**AI, R.getName())->writeDumpChildren(OS);
+ for (const auto *AI : Args)
+ createArgument(*AI, R.getName())->writeDumpChildren(OS);
}
OS <<
" break;\n"
diff --git a/utils/TableGen/ClangCommentCommandInfoEmitter.cpp b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
index 3349030466fc..3522cd472d9d 100644
--- a/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
+++ b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
@@ -72,7 +72,7 @@ void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n"
<< " StringRef Name) {\n";
StringMatcher("Name", Matches, OS).Emit();
- OS << " return NULL;\n"
+ OS << " return nullptr;\n"
<< "}\n\n";
}
@@ -123,4 +123,3 @@ void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) {
}
}
} // end namespace clang
-
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 7644ae2c04da..6e7bc9057fd7 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -36,6 +36,7 @@
#include "llvm/TableGen/SetTheory.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <algorithm>
+#include <deque>
#include <map>
#include <sstream>
#include <string>
@@ -393,7 +394,7 @@ public:
/// Return true if the prototype has a scalar argument.
/// This does not return true for the "splat" code ('a').
- bool protoHasScalar();
+ bool protoHasScalar() const;
/// Return the index that parameter PIndex will sit at
/// in a generated function call. This is often just PIndex,
@@ -431,9 +432,9 @@ public:
/// Return the name, mangled with type information.
/// If ForceClassS is true, use ClassS (u32/s32) instead
/// of the intrinsic's own type class.
- std::string getMangledName(bool ForceClassS = false);
+ std::string getMangledName(bool ForceClassS = false) const;
/// Return the type code for a builtin function call.
- std::string getInstTypeCode(Type T, ClassKind CK);
+ std::string getInstTypeCode(Type T, ClassKind CK) const;
/// Return the type string for a BUILTIN() macro in Builtins.def.
std::string getBuiltinTypeStr();
@@ -444,7 +445,7 @@ public:
void indexBody();
private:
- std::string mangleName(std::string Name, ClassKind CK);
+ std::string mangleName(std::string Name, ClassKind CK) const;
void initVariables();
std::string replaceParamsIn(std::string S);
@@ -494,7 +495,7 @@ private:
class NeonEmitter {
RecordKeeper &Records;
DenseMap<Record *, ClassKind> ClassMap;
- std::map<std::string, std::vector<Intrinsic *>> IntrinsicMap;
+ std::map<std::string, std::deque<Intrinsic>> IntrinsicMap;
unsigned UniqueNumber;
void createIntrinsic(Record *R, SmallVectorImpl<Intrinsic *> &Out);
@@ -507,7 +508,7 @@ class NeonEmitter {
public:
/// Called by Intrinsic - this attempts to get an intrinsic that takes
/// the given types as arguments.
- Intrinsic *getIntrinsic(StringRef Name, ArrayRef<Type> Types);
+ Intrinsic &getIntrinsic(StringRef Name, ArrayRef<Type> Types);
/// Called by Intrinsic - returns a globally-unique number.
unsigned getUniqueNumber() { return UniqueNumber++; }
@@ -836,10 +837,6 @@ void Type::applyModifier(char Mod) {
Float = true;
break;
case 'f':
- // Special case - if we're half-precision, a floating
- // point argument needs to be 128-bits (double size).
- if (isHalf())
- Bitwidth = 128;
Float = true;
ElementBitwidth = 32;
break;
@@ -954,7 +951,7 @@ void Type::applyModifier(char Mod) {
// Intrinsic implementation
//===----------------------------------------------------------------------===//
-std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) {
+std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const {
char typeCode = '\0';
bool printNumber = true;
@@ -992,6 +989,10 @@ std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) {
return S;
}
+static bool isFloatingPointProtoModifier(char Mod) {
+ return Mod == 'F' || Mod == 'f';
+}
+
std::string Intrinsic::getBuiltinTypeStr() {
ClassKind LocalCK = getClassKind(true);
std::string S;
@@ -1013,7 +1014,7 @@ std::string Intrinsic::getBuiltinTypeStr() {
if (!RetT.isScalar() && !RetT.isSigned())
RetT.makeSigned();
- bool ForcedVectorFloatingType = Proto[0] == 'F' || Proto[0] == 'f';
+ bool ForcedVectorFloatingType = isFloatingPointProtoModifier(Proto[0]);
if (LocalCK == ClassB && !RetT.isScalar() && !ForcedVectorFloatingType)
// Cast to vector of 8-bit elements.
RetT.makeInteger(8, true);
@@ -1026,7 +1027,7 @@ std::string Intrinsic::getBuiltinTypeStr() {
if (T.isPoly())
T.makeInteger(T.getElementSizeInBits(), false);
- bool ForcedFloatingType = Proto[I + 1] == 'F' || Proto[I + 1] == 'f';
+ bool ForcedFloatingType = isFloatingPointProtoModifier(Proto[I + 1]);
if (LocalCK == ClassB && !T.isScalar() && !ForcedFloatingType)
T.makeInteger(8, true);
// Halves always get converted to 8-bit elements.
@@ -1049,7 +1050,7 @@ std::string Intrinsic::getBuiltinTypeStr() {
return S;
}
-std::string Intrinsic::getMangledName(bool ForceClassS) {
+std::string Intrinsic::getMangledName(bool ForceClassS) const {
// Check if the prototype has a scalar operand with the type of the vector
// elements. If not, bitcasting the args will take care of arg checking.
// The actual signedness etc. will be taken care of with special enums.
@@ -1060,12 +1061,12 @@ std::string Intrinsic::getMangledName(bool ForceClassS) {
return mangleName(Name, ForceClassS ? ClassS : LocalCK);
}
-std::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) {
+std::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) const {
std::string typeCode = getInstTypeCode(BaseType, LocalCK);
std::string S = Name;
- if (Name == "vcvt_f32_f16" || Name == "vcvt_f32_f64" ||
- Name == "vcvt_f64_f32")
+ if (Name == "vcvt_f16_f32" || Name == "vcvt_f32_f16" ||
+ Name == "vcvt_f32_f64" || Name == "vcvt_f64_f32")
return Name;
if (typeCode.size() > 0) {
@@ -1278,7 +1279,7 @@ void Intrinsic::emitShadowedArgs() {
// We don't check 'a' in this function, because for builtin function the
// argument matching to 'a' uses a vector type splatted from a scalar type.
-bool Intrinsic::protoHasScalar() {
+bool Intrinsic::protoHasScalar() const {
return (Proto.find('s') != std::string::npos ||
Proto.find('z') != std::string::npos ||
Proto.find('r') != std::string::npos ||
@@ -1363,7 +1364,7 @@ void Intrinsic::emitBodyAsBuiltinCall() {
// Extra constant integer to hold type class enum for this function, e.g. s8
if (getClassKind(true) == ClassB) {
Type ThisTy = getReturnType();
- if (Proto[0] == 'v' || Proto[0] == 'f' || Proto[0] == 'F')
+ if (Proto[0] == 'v' || isFloatingPointProtoModifier(Proto[0]))
ThisTy = getParamType(0);
if (ThisTy.isPointer())
ThisTy = getParamType(1);
@@ -1491,15 +1492,14 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) {
N = SI->getAsUnquotedString();
else
N = emitDagArg(DI->getArg(0), "").second;
- Intrinsic *Callee = Intr.Emitter.getIntrinsic(N, Types);
- assert(Callee && "getIntrinsic should not return us nullptr!");
+ Intrinsic &Callee = Intr.Emitter.getIntrinsic(N, Types);
// Make sure the callee is known as an early def.
- Callee->setNeededEarly();
- Intr.Dependencies.insert(Callee);
+ Callee.setNeededEarly();
+ Intr.Dependencies.insert(&Callee);
// Now create the call itself.
- std::string S = CallPrefix.str() + Callee->getMangledName(true) + "(";
+ std::string S = CallPrefix.str() + Callee.getMangledName(true) + "(";
for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) {
if (I != 0)
S += ", ";
@@ -1507,7 +1507,7 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) {
}
S += ")";
- return std::make_pair(Callee->getReturnType(), S);
+ return std::make_pair(Callee.getReturnType(), S);
}
std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI,
@@ -1855,11 +1855,11 @@ void Intrinsic::indexBody() {
// NeonEmitter implementation
//===----------------------------------------------------------------------===//
-Intrinsic *NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) {
+Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) {
// First, look up the name in the intrinsic map.
assert_with_loc(IntrinsicMap.find(Name.str()) != IntrinsicMap.end(),
("Intrinsic '" + Name + "' not found!").str());
- std::vector<Intrinsic *> &V = IntrinsicMap[Name.str()];
+ auto &V = IntrinsicMap.find(Name.str())->second;
std::vector<Intrinsic *> GoodVec;
// Create a string to print if we end up failing.
@@ -1874,35 +1874,35 @@ Intrinsic *NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) {
// Now, look through each intrinsic implementation and see if the types are
// compatible.
- for (auto *I : V) {
- ErrMsg += " - " + I->getReturnType().str() + " " + I->getMangledName();
+ for (auto &I : V) {
+ ErrMsg += " - " + I.getReturnType().str() + " " + I.getMangledName();
ErrMsg += "(";
- for (unsigned A = 0; A < I->getNumParams(); ++A) {
+ for (unsigned A = 0; A < I.getNumParams(); ++A) {
if (A != 0)
ErrMsg += ", ";
- ErrMsg += I->getParamType(A).str();
+ ErrMsg += I.getParamType(A).str();
}
ErrMsg += ")\n";
- if (I->getNumParams() != Types.size())
+ if (I.getNumParams() != Types.size())
continue;
bool Good = true;
for (unsigned Arg = 0; Arg < Types.size(); ++Arg) {
- if (I->getParamType(Arg) != Types[Arg]) {
+ if (I.getParamType(Arg) != Types[Arg]) {
Good = false;
break;
}
}
if (Good)
- GoodVec.push_back(I);
+ GoodVec.push_back(&I);
}
assert_with_loc(GoodVec.size() > 0,
"No compatible intrinsic found - " + ErrMsg);
assert_with_loc(GoodVec.size() == 1, "Multiple overloads found - " + ErrMsg);
- return GoodVec.front();
+ return *GoodVec.front();
}
void NeonEmitter::createIntrinsic(Record *R,
@@ -1947,13 +1947,12 @@ void NeonEmitter::createIntrinsic(Record *R,
std::sort(NewTypeSpecs.begin(), NewTypeSpecs.end());
NewTypeSpecs.erase(std::unique(NewTypeSpecs.begin(), NewTypeSpecs.end()),
NewTypeSpecs.end());
+ auto &Entry = IntrinsicMap[Name];
for (auto &I : NewTypeSpecs) {
- Intrinsic *IT = new Intrinsic(R, Name, Proto, I.first, I.second, CK, Body,
- *this, Guard, IsUnavailable, BigEndianSafe);
-
- IntrinsicMap[Name].push_back(IT);
- Out.push_back(IT);
+ Entry.emplace_back(R, Name, Proto, I.first, I.second, CK, Body, *this,
+ Guard, IsUnavailable, BigEndianSafe);
+ Out.push_back(&Entry.back());
}
CurrentRecord = nullptr;
@@ -2023,8 +2022,8 @@ void NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS,
uint64_t Mask = 0ULL;
Type Ty = Def->getReturnType();
- if (Def->getProto()[0] == 'v' || Def->getProto()[0] == 'f' ||
- Def->getProto()[0] == 'F')
+ if (Def->getProto()[0] == 'v' ||
+ isFloatingPointProtoModifier(Def->getProto()[0]))
Ty = Def->getParamType(0);
if (Ty.isPointer())
Ty = Def->getParamType(1);