diff options
author | dim <dim@FreeBSD.org> | 2017-04-02 17:24:58 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2017-04-02 17:24:58 +0000 |
commit | 60b571e49a90d38697b3aca23020d9da42fc7d7f (patch) | |
tree | 99351324c24d6cb146b6285b6caffa4d26fce188 /contrib/llvm/tools/clang/utils | |
parent | bea1b22c7a9bce1dfdd73e6e5b65bc4752215180 (diff) | |
download | FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.zip FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.tar.gz |
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release:
MFC r309142 (by emaste):
Add WITH_LLD_AS_LD build knob
If set it installs LLD as /usr/bin/ld. LLD (as of version 3.9) is not
capable of linking the world and kernel, but can self-host and link many
substantial applications. GNU ld continues to be used for the world and
kernel build, regardless of how this knob is set.
It is on by default for arm64, and off for all other CPU architectures.
Sponsored by: The FreeBSD Foundation
MFC r310840:
Reapply 310775, now it also builds correctly if lldb is disabled:
Move llvm-objdump from CLANG_EXTRAS to installed by default
We currently install three tools from binutils 2.17.50: as, ld, and
objdump. Work is underway to migrate to a permissively-licensed
tool-chain, with one goal being the retirement of binutils 2.17.50.
LLVM's llvm-objdump is intended to be compatible with GNU objdump
although it is currently missing some options and may have formatting
differences. Enable it by default for testing and further investigation.
It may later be changed to install as /usr/bin/objdump, it becomes a
fully viable replacement.
Reviewed by: emaste
Differential Revision: https://reviews.freebsd.org/D8879
MFC r312855 (by emaste):
Rename LLD_AS_LD to LLD_IS_LD, for consistency with CLANG_IS_CC
Reported by: Dan McGregor <dan.mcgregor usask.ca>
MFC r313559 | glebius | 2017-02-10 18:34:48 +0100 (Fri, 10 Feb 2017) | 5 lines
Don't check struct rtentry on FreeBSD, it is an internal kernel structure.
On other systems it may be API structure for SIOCADDRT/SIOCDELRT.
Reviewed by: emaste, dim
MFC r314152 (by jkim):
Remove an assembler flag, which is redundant since r309124. The upstream
took care of it by introducing a macro NO_EXEC_STACK_DIRECTIVE.
http://llvm.org/viewvc/llvm-project?rev=273500&view=rev
Reviewed by: dim
MFC r314564:
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
4.0.0 (branches/release_40 296509). The release will follow soon.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Also note that as of 4.0.0, lld should be able to link the base system
on amd64 and aarch64. See the WITH_LLD_IS_LLD setting in src.conf(5).
Though please be aware that this is work in progress.
Release notes for llvm, clang and lld will be available here:
<http://releases.llvm.org/4.0.0/docs/ReleaseNotes.html>
<http://releases.llvm.org/4.0.0/tools/clang/docs/ReleaseNotes.html>
<http://releases.llvm.org/4.0.0/tools/lld/docs/ReleaseNotes.html>
Thanks to Ed Maste, Jan Beich, Antoine Brodin and Eric Fiselier for
their help.
Relnotes: yes
Exp-run: antoine
PR: 215969, 216008
MFC r314708:
For now, revert r287232 from upstream llvm trunk (by Daniil Fukalov):
[SCEV] limit recursion depth of CompareSCEVComplexity
Summary:
CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled
loop) and runs almost infinite time.
Added cache of "equal" SCEV pairs to earlier cutoff of further
estimation. Recursion depth limit was also introduced as a parameter.
Reviewers: sanjoy
Subscribers: mzolotukhin, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D26389
This commit is the cause of excessive compile times on skein_block.c
(and possibly other files) during kernel builds on amd64.
We never saw the problematic behavior described in this upstream commit,
so for now it is better to revert it. An upstream bug has been filed
here: https://bugs.llvm.org/show_bug.cgi?id=32142
Reported by: mjg
MFC r314795:
Reapply r287232 from upstream llvm trunk (by Daniil Fukalov):
[SCEV] limit recursion depth of CompareSCEVComplexity
Summary:
CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled
loop) and runs almost infinite time.
Added cache of "equal" SCEV pairs to earlier cutoff of further
estimation. Recursion depth limit was also introduced as a parameter.
Reviewers: sanjoy
Subscribers: mzolotukhin, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D26389
Pull in r296992 from upstream llvm trunk (by Sanjoy Das):
[SCEV] Decrease the recursion threshold for CompareValueComplexity
Fixes PR32142.
r287232 accidentally increased the recursion threshold for
CompareValueComplexity from 2 to 32. This change reverses that
change by introducing a separate flag for CompareValueComplexity's
threshold.
The latter revision fixes the excessive compile times for skein_block.c.
MFC r314907 | mmel | 2017-03-08 12:40:27 +0100 (Wed, 08 Mar 2017) | 7 lines
Unbreak ARMv6 world.
The new compiler_rt library imported with clang 4.0.0 have several fatal
issues (non-functional __udivsi3 for example) with ARM specific instrict
functions. As temporary workaround, until upstream solve these problems,
disable all thumb[1][2] related feature.
MFC r315016:
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release.
We were already very close to the last release candidate, so this is a
pretty minor update.
Relnotes: yes
MFC r316005:
Revert r314907, and pull in r298713 from upstream compiler-rt trunk (by
Weiming Zhao):
builtins: Select correct code fragments when compiling for Thumb1/Thum2/ARM ISA.
Summary:
Value of __ARM_ARCH_ISA_THUMB isn't based on the actual compilation
mode (-mthumb, -marm), it reflect's capability of given CPU.
Due to this:
- use __tbumb__ and __thumb2__ insteand of __ARM_ARCH_ISA_THUMB
- use '.thumb' directive consistently in all affected files
- decorate all thumb functions using
DEFINE_COMPILERRT_THUMB_FUNCTION()
---------
Note: This patch doesn't fix broken Thumb1 variant of __udivsi3 !
Reviewers: weimingz, rengolin, compnerd
Subscribers: aemerson, dim
Differential Revision: https://reviews.llvm.org/D30938
Discussed with: mmel
Diffstat (limited to 'contrib/llvm/tools/clang/utils')
6 files changed, 607 insertions, 110 deletions
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangASTNodesEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangASTNodesEmitter.cpp index b17a4a3..b132dcb 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/ClangASTNodesEmitter.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/ClangASTNodesEmitter.cpp @@ -47,7 +47,7 @@ class ClangASTNodesEmitter { if (&R == &Root && !BaseSuffix.empty()) return BaseSuffix; - return R.getName() + BaseSuffix; + return R.getName().str() + BaseSuffix; } std::pair<Record *, Record *> EmitNode (const ChildMap &Tree, raw_ostream& OS, diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp index 50102af..27ab34c 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" @@ -120,12 +121,8 @@ static std::string WritePCHRecord(StringRef type, StringRef name) { // underscores. For example, __foo, foo__, __foo__ would // become foo. static StringRef NormalizeAttrName(StringRef AttrName) { - if (AttrName.startswith("__")) - AttrName = AttrName.substr(2, AttrName.size()); - - if (AttrName.endswith("__")) - AttrName = AttrName.substr(0, AttrName.size() - 2); - + AttrName.consume_front("__"); + AttrName.consume_back("__"); return AttrName; } @@ -136,10 +133,9 @@ static StringRef NormalizeNameForSpellingComparison(StringRef Name) { return Name.trim("_"); } -// Normalize attribute spelling only if the spelling has both leading -// and trailing underscores. For example, __ms_struct__ will be -// normalized to "ms_struct"; __cdecl will remain intact. -static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) { +// Normalize the spelling of a GNU attribute (i.e. "x" in "__attribute__((x))"), +// removing "__" if it appears at the beginning and end of the attribute's name. +static StringRef NormalizeGNUAttrSpelling(StringRef AttrSpelling) { if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) { AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4); } @@ -299,7 +295,13 @@ namespace { OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \""; } else if (type == "IdentifierInfo *") { - OS << "\" << get" << getUpperName() << "()->getName() << \""; + OS << "\";\n"; + if (isOptional()) + OS << " if (get" << getUpperName() << "()) "; + else + OS << " "; + OS << "OS << get" << getUpperName() << "()->getName();\n"; + OS << " OS << \""; } else if (type == "TypeSourceInfo *") { OS << "\" << get" << getUpperName() << "().getAsString() << \""; } else { @@ -717,13 +719,10 @@ namespace { std::vector<std::string> uniqueEnumsInOrder(const std::vector<std::string> &enums) { std::vector<std::string> uniques; - std::set<std::string> unique_set(enums.begin(), enums.end()); + SmallDenseSet<StringRef, 8> unique_set; for (const auto &i : enums) { - auto set_i = unique_set.find(i); - if (set_i != unique_set.end()) { + if (unique_set.insert(i).second) uniques.push_back(i); - unique_set.erase(set_i); - } } return uniques; } @@ -835,7 +834,7 @@ namespace { OS << " static const char *Convert" << type << "ToStr(" << type << " Val) {\n" << " switch(Val) {\n"; - std::set<std::string> Uniques; + SmallDenseSet<StringRef, 8> Uniques; for (size_t I = 0; I < enums.size(); ++I) { if (Uniques.insert(enums[I]).second) OS << " case " << getAttrName() << "Attr::" << enums[I] @@ -943,7 +942,7 @@ namespace { OS << " static const char *Convert" << type << "ToStr(" << type << " Val) {\n" << " switch(Val) {\n"; - std::set<std::string> Uniques; + SmallDenseSet<StringRef, 8> Uniques; for (size_t I = 0; I < enums.size(); ++I) { if (Uniques.insert(enums[I]).second) OS << " case " << getAttrName() << "Attr::" << enums[I] @@ -1312,6 +1311,9 @@ writePrettyPrintFunction(Record &R, } else if (Variety == "Declspec") { Prefix = " __declspec("; Suffix = ")"; + } else if (Variety == "Microsoft") { + Prefix = "["; + Suffix = "]"; } else if (Variety == "Keyword") { Prefix = " "; Suffix = ""; @@ -1344,11 +1346,8 @@ writePrettyPrintFunction(Record &R, // 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; - } + bool hasNonFakeArgs = llvm::any_of( + Args, [](const std::unique_ptr<Argument> &A) { return !A->isFake(); }); // FIXME: always printing the parenthesis isn't the correct behavior for // attributes which have optional arguments that were not provided. For @@ -1408,18 +1407,20 @@ getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList, static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) { std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors"); + if (Accessors.empty()) + return; + + const std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R); + assert(!SpellingList.empty() && + "Attribute with empty spelling list can't have accessors!"); for (const auto *Accessor : Accessors) { std::string Name = Accessor->getValueAsString("Name"); - std::vector<FlattenedSpelling> Spellings = - GetFlattenedSpellings(*Accessor); - std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R); - assert(!SpellingList.empty() && - "Attribute with empty spelling list can't have accessors!"); + std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Accessor); OS << " bool " << Name << "() const { return SpellingListIndex == "; for (unsigned Index = 0; Index < Spellings.size(); ++Index) { OS << getSpellingListIndex(SpellingList, Spellings[Index]); - if (Index != Spellings.size() -1) + if (Index != Spellings.size() - 1) OS << " ||\n SpellingListIndex == "; else OS << "; }\n"; @@ -1521,6 +1522,16 @@ static void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n"; } +template <typename Fn> +static void forEachUniqueSpelling(const Record &Attr, Fn &&F) { + std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); + SmallDenseSet<StringRef, 8> Seen; + for (const FlattenedSpelling &S : Spellings) { + if (Seen.insert(S.name()).second) + F(S); + } +} + /// \brief Emits the first-argument-is-type property for attributes. static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n"; @@ -1536,12 +1547,9 @@ static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { continue; // All these spellings take a single type argument. - std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); - std::set<std::string> Emitted; - for (const auto &S : Spellings) { - if (Emitted.insert(S.name()).second) - OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; - } + forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) { + OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; + }); } OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n"; } @@ -1558,12 +1566,9 @@ static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) continue; // All these spellings take are parsed unevaluated. - std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); - std::set<std::string> Emitted; - for (const auto &S : Spellings) { - if (Emitted.insert(S.name()).second) - OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; - } + forEachUniqueSpelling(Attr, [&](const FlattenedSpelling &S) { + OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; + }); } OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n"; } @@ -1589,12 +1594,9 @@ static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &O continue; // All these spellings take an identifier argument. - std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); - std::set<std::string> Emitted; - for (const auto &S : Spellings) { - if (Emitted.insert(S.name()).second) - OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; - } + forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) { + OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; + }); } OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n"; } @@ -1882,8 +1884,7 @@ static void emitAttrList(raw_ostream &OS, StringRef Class, // Determines if an attribute has a Pragma spelling. static bool AttrHasPragmaSpelling(const Record *R) { std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R); - return std::find_if(Spellings.begin(), Spellings.end(), - [](const FlattenedSpelling &S) { + return llvm::find_if(Spellings, [](const FlattenedSpelling &S) { return S.variety() == "Pragma"; }) != Spellings.end(); } @@ -2295,7 +2296,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { // Separate all of the attributes out into four group: generic, C++11, GNU, // and declspecs. Then generate a big switch statement for each of them. std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); - std::vector<Record *> Declspec, GNU, Pragma; + std::vector<Record *> Declspec, Microsoft, GNU, Pragma; std::map<std::string, std::vector<Record *>> CXX; // Walk over the list of all attributes, and split them out based on the @@ -2308,6 +2309,8 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { GNU.push_back(R); else if (Variety == "Declspec") Declspec.push_back(R); + else if (Variety == "Microsoft") + Microsoft.push_back(R); else if (Variety == "CXX11") CXX[SI.nameSpace()].push_back(R); else if (Variety == "Pragma") @@ -2323,6 +2326,9 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << "case AttrSyntax::Declspec:\n"; OS << " return llvm::StringSwitch<int>(Name)\n"; GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec"); + OS << "case AttrSyntax::Microsoft:\n"; + OS << " return llvm::StringSwitch<int>(Name)\n"; + GenerateHasAttrSpellingStringSwitch(Microsoft, OS, "Microsoft"); OS << "case AttrSyntax::Pragma:\n"; OS << " return llvm::StringSwitch<int>(Name)\n"; GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma"); @@ -2361,8 +2367,9 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { .Case("GNU", 0) .Case("CXX11", 1) .Case("Declspec", 2) - .Case("Keyword", 3) - .Case("Pragma", 4) + .Case("Microsoft", 3) + .Case("Keyword", 4) + .Case("Pragma", 5) .Default(0) << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n" << " return " << I << ";\n"; @@ -2532,6 +2539,10 @@ static void emitArgInfo(const Record &R, std::stringstream &OS) { unsigned ArgCount = 0, OptCount = 0; bool HasVariadic = false; for (const auto *Arg : Args) { + // If the arg is fake, it's the user's job to supply it: general parsing + // logic shouldn't need to know anything about it. + if (Arg->getValueAsBit("Fake")) + continue; Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount; if (!HasVariadic && isArgVariadic(*Arg, R.getName())) HasVariadic = true; @@ -2675,7 +2686,7 @@ static std::string CalculateDiagnostic(const Record &S) { } static std::string GetSubjectWithSuffix(const Record *R) { - std::string B = R->getName(); + const std::string &B = R->getName(); if (B == "DeclBase") return "Decl"; return B + "Decl"; @@ -2683,7 +2694,7 @@ static std::string GetSubjectWithSuffix(const Record *R) { static std::string GenerateCustomAppertainsTo(const Record &Subject, raw_ostream &OS) { - std::string FnName = "is" + Subject.getName(); + std::string FnName = "is" + Subject.getName().str(); // If this code has already been generated, simply return the previous // instance of it. @@ -2732,7 +2743,7 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) { // Otherwise, generate an appertainsTo check specific to this attribute which // checks all of the given subjects against the Decl passed in. Return the // name of that check to the caller. - std::string FnName = "check" + Attr.getName() + "AppertainsTo"; + std::string FnName = "check" + Attr.getName().str() + "AppertainsTo"; std::stringstream SS; SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, "; SS << "const Decl *D) {\n"; @@ -2790,8 +2801,10 @@ static std::string GenerateLangOptRequirements(const Record &R, std::string FnName = "check", Test; for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) { std::string Part = (*I)->getValueAsString("Name"); - if ((*I)->getValueAsBit("Negated")) + if ((*I)->getValueAsBit("Negated")) { + FnName += "Not"; Test += "!"; + } Test += "S.LangOpts." + Part; if (I + 1 != E) Test += " || "; @@ -2853,7 +2866,7 @@ static std::string GenerateTargetRequirements(const Record &Attr, if (I.first == APK) { std::vector<std::string> DA = I.second->getValueAsDef("Target") ->getValueAsListOfStrings("Arches"); - std::copy(DA.begin(), DA.end(), std::back_inserter(Arches)); + std::move(DA.begin(), DA.end(), std::back_inserter(Arches)); } } } @@ -2901,7 +2914,7 @@ static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr, // Generate the enumeration we will use for the mapping. SemanticSpellingMap SemanticToSyntacticMap; std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap); - std::string Name = Attr.getName() + "AttrSpellingMap"; + std::string Name = Attr.getName().str() + "AttrSpellingMap"; OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n"; OS << Enum; @@ -2915,12 +2928,9 @@ static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr, static bool IsKnownToGCC(const Record &Attr) { // Look at the spellings for this subject; if there are any spellings which // claim to be known to GCC, the attribute is known to GCC. - std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); - for (const auto &I : Spellings) { - if (I.knownToGCC()) - return true; - } - return false; + return llvm::any_of( + GetFlattenedSpellings(Attr), + [](const FlattenedSpelling &S) { return S.knownToGCC(); }); } /// Emits the parsed attribute helpers @@ -2982,7 +2992,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("Attribute name matcher", OS); std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); - std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords, Pragma; + std::vector<StringMatcher::StringPair> GNU, Declspec, Microsoft, CXX11, + Keywords, Pragma; std::set<std::string> Seen; for (const auto *A : Attrs) { const Record &Attr = *A; @@ -3024,6 +3035,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { Matches = &GNU; else if (Variety == "Declspec") Matches = &Declspec; + else if (Variety == "Microsoft") + Matches = &Microsoft; else if (Variety == "Keyword") Matches = &Keywords; else if (Variety == "Pragma") @@ -3031,7 +3044,11 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { assert(Matches && "Unsupported spelling variety found"); - Spelling += NormalizeAttrSpelling(RawSpelling); + if (Variety == "GNU") + Spelling += NormalizeGNUAttrSpelling(RawSpelling); + else + Spelling += RawSpelling; + if (SemaHandler) Matches->push_back(StringMatcher::StringPair(Spelling, "return AttributeList::AT_" + AttrName + ";")); @@ -3048,6 +3065,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { StringMatcher("Name", GNU, OS).Emit(); OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n"; StringMatcher("Name", Declspec, OS).Emit(); + OS << " } else if (AttributeList::AS_Microsoft == Syntax) {\n"; + StringMatcher("Name", Microsoft, OS).Emit(); OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n"; StringMatcher("Name", CXX11, OS).Emit(); OS << " } else if (AttributeList::AS_Keyword == Syntax || "; @@ -3131,8 +3150,9 @@ enum SpellingKind { GNU = 1 << 0, CXX11 = 1 << 1, Declspec = 1 << 2, - Keyword = 1 << 3, - Pragma = 1 << 4 + Microsoft = 1 << 3, + Keyword = 1 << 4, + Pragma = 1 << 5 }; static void WriteDocumentation(const DocumentationData &Doc, @@ -3180,6 +3200,7 @@ static void WriteDocumentation(const DocumentationData &Doc, .Case("GNU", GNU) .Case("CXX11", CXX11) .Case("Declspec", Declspec) + .Case("Microsoft", Microsoft) .Case("Keyword", Keyword) .Case("Pragma", Pragma); diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp index bbc2bdb..cad08af 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -14,14 +14,12 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/StringToOffsetTable.h" @@ -145,6 +143,11 @@ static bool beforeThanCompare(const Record *LHS, const Record *RHS) { LHS->getLoc().front().getPointer() < RHS->getLoc().front().getPointer(); } +static bool diagGroupBeforeByName(const Record *LHS, const Record *RHS) { + return LHS->getValueAsString("GroupName") < + RHS->getValueAsString("GroupName"); +} + static bool beforeThanCompareGroups(const GroupInfo *LHS, const GroupInfo *RHS){ assert(!LHS->DiagsInGroup.empty() && !RHS->DiagsInGroup.empty()); return beforeThanCompare(LHS->DiagsInGroup.front(), @@ -896,4 +899,444 @@ void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) { OS << "DIAG_NAME_INDEX(" << R.Name << ")\n"; } } + +//===----------------------------------------------------------------------===// +// Diagnostic documentation generation +//===----------------------------------------------------------------------===// + +namespace docs { +namespace { + +/// Diagnostic text, parsed into pieces. +struct DiagText { + struct Piece { + // This type and its derived classes are move-only. + Piece() {} + Piece(Piece &&O) {} + Piece &operator=(Piece &&O) { return *this; } + + virtual void print(std::vector<std::string> &RST) = 0; + virtual ~Piece() {} + }; + struct TextPiece : Piece { + StringRef Role; + std::string Text; + void print(std::vector<std::string> &RST) override; + }; + struct PlaceholderPiece : Piece { + int Index; + void print(std::vector<std::string> &RST) override; + }; + struct SelectPiece : Piece { + SelectPiece() {} + SelectPiece(SelectPiece &&O) noexcept : Options(std::move(O.Options)) {} + std::vector<DiagText> Options; + void print(std::vector<std::string> &RST) override; + }; + + std::vector<std::unique_ptr<Piece>> Pieces; + + DiagText(); + DiagText(DiagText &&O) noexcept : Pieces(std::move(O.Pieces)) {} + + DiagText(StringRef Text); + DiagText(StringRef Kind, StringRef Text); + + template<typename P> void add(P Piece) { + Pieces.push_back(llvm::make_unique<P>(std::move(Piece))); + } + void print(std::vector<std::string> &RST); +}; + +DiagText parseDiagText(StringRef &Text, bool Nested = false) { + DiagText Parsed; + + while (!Text.empty()) { + size_t End = (size_t)-2; + do + End = Nested ? Text.find_first_of("%|}", End + 2) + : Text.find_first_of('%', End + 2); + while (End < Text.size() - 1 && Text[End] == '%' && Text[End + 1] == '%'); + + if (End) { + DiagText::TextPiece Piece; + Piece.Role = "diagtext"; + Piece.Text = Text.slice(0, End); + Parsed.add(std::move(Piece)); + Text = Text.slice(End, StringRef::npos); + if (Text.empty()) break; + } + + if (Text[0] == '|' || Text[0] == '}') + break; + + // Drop the '%'. + Text = Text.drop_front(); + + // Extract the (optional) modifier. + size_t ModLength = Text.find_first_of("0123456789{"); + StringRef Modifier = Text.slice(0, ModLength); + Text = Text.slice(ModLength, StringRef::npos); + + // FIXME: Handle %ordinal here. + if (Modifier == "select" || Modifier == "plural") { + DiagText::SelectPiece Select; + do { + Text = Text.drop_front(); + if (Modifier == "plural") + while (Text[0] != ':') + Text = Text.drop_front(); + Select.Options.push_back(parseDiagText(Text, true)); + assert(!Text.empty() && "malformed %select"); + } while (Text.front() == '|'); + Parsed.add(std::move(Select)); + + // Drop the trailing '}n'. + Text = Text.drop_front(2); + continue; + } + + // For %diff, just take the second alternative (tree diagnostic). It would + // be preferable to take the first one, and replace the $ with the suitable + // placeholders. + if (Modifier == "diff") { + Text = Text.drop_front(); // '{' + parseDiagText(Text, true); + Text = Text.drop_front(); // '|' + + DiagText D = parseDiagText(Text, true); + for (auto &P : D.Pieces) + Parsed.Pieces.push_back(std::move(P)); + + Text = Text.drop_front(4); // '}n,m' + continue; + } + + if (Modifier == "s") { + Text = Text.drop_front(); + DiagText::SelectPiece Select; + Select.Options.push_back(DiagText("")); + Select.Options.push_back(DiagText("s")); + Parsed.add(std::move(Select)); + continue; + } + + assert(!Text.empty() && isdigit(Text[0]) && "malformed placeholder"); + DiagText::PlaceholderPiece Placeholder; + Placeholder.Index = Text[0] - '0'; + Parsed.add(std::move(Placeholder)); + Text = Text.drop_front(); + continue; + } + return Parsed; +} + +DiagText::DiagText() {} + +DiagText::DiagText(StringRef Text) : DiagText(parseDiagText(Text, false)) {} + +DiagText::DiagText(StringRef Kind, StringRef Text) : DiagText(parseDiagText(Text, false)) { + TextPiece Prefix; + Prefix.Role = Kind; + Prefix.Text = Kind; + Prefix.Text += ": "; + Pieces.insert(Pieces.begin(), + llvm::make_unique<TextPiece>(std::move(Prefix))); +} + +void escapeRST(StringRef Str, std::string &Out) { + for (auto K : Str) { + if (StringRef("`*|_[]\\").count(K)) + Out.push_back('\\'); + Out.push_back(K); + } +} + +template<typename It> void padToSameLength(It Begin, It End) { + size_t Width = 0; + for (It I = Begin; I != End; ++I) + Width = std::max(Width, I->size()); + for (It I = Begin; I != End; ++I) + (*I) += std::string(Width - I->size(), ' '); +} + +template<typename It> void makeTableRows(It Begin, It End) { + if (Begin == End) return; + padToSameLength(Begin, End); + for (It I = Begin; I != End; ++I) + *I = "|" + *I + "|"; +} + +void makeRowSeparator(std::string &Str) { + for (char &K : Str) + K = (K == '|' ? '+' : '-'); +} + +void DiagText::print(std::vector<std::string> &RST) { + if (Pieces.empty()) { + RST.push_back(""); + return; + } + + if (Pieces.size() == 1) + return Pieces[0]->print(RST); + + std::string EmptyLinePrefix; + size_t Start = RST.size(); + bool HasMultipleLines = true; + for (auto &P : Pieces) { + std::vector<std::string> Lines; + P->print(Lines); + if (Lines.empty()) + continue; + + // We need a vertical separator if either this or the previous piece is a + // multi-line piece, or this is the last piece. + const char *Separator = (Lines.size() > 1 || HasMultipleLines) ? "|" : ""; + HasMultipleLines = Lines.size() > 1; + + if (Start + Lines.size() > RST.size()) + RST.resize(Start + Lines.size(), EmptyLinePrefix); + + padToSameLength(Lines.begin(), Lines.end()); + for (size_t I = 0; I != Lines.size(); ++I) + RST[Start + I] += Separator + Lines[I]; + std::string Empty(Lines[0].size(), ' '); + for (size_t I = Start + Lines.size(); I != RST.size(); ++I) + RST[I] += Separator + Empty; + EmptyLinePrefix += Separator + Empty; + } + for (size_t I = Start; I != RST.size(); ++I) + RST[I] += "|"; + EmptyLinePrefix += "|"; + + makeRowSeparator(EmptyLinePrefix); + RST.insert(RST.begin() + Start, EmptyLinePrefix); + RST.insert(RST.end(), EmptyLinePrefix); +} + +void DiagText::TextPiece::print(std::vector<std::string> &RST) { + RST.push_back(""); + auto &S = RST.back(); + + StringRef T = Text; + while (!T.empty() && T.front() == ' ') { + RST.back() += " |nbsp| "; + T = T.drop_front(); + } + + std::string Suffix; + while (!T.empty() && T.back() == ' ') { + Suffix += " |nbsp| "; + T = T.drop_back(); + } + + if (!T.empty()) { + S += ':'; + S += Role; + S += ":`"; + escapeRST(T, S); + S += '`'; + } + + S += Suffix; +} + +void DiagText::PlaceholderPiece::print(std::vector<std::string> &RST) { + RST.push_back(std::string(":placeholder:`") + char('A' + Index) + "`"); +} + +void DiagText::SelectPiece::print(std::vector<std::string> &RST) { + std::vector<size_t> SeparatorIndexes; + SeparatorIndexes.push_back(RST.size()); + RST.emplace_back(); + for (auto &O : Options) { + O.print(RST); + SeparatorIndexes.push_back(RST.size()); + RST.emplace_back(); + } + + makeTableRows(RST.begin() + SeparatorIndexes.front(), + RST.begin() + SeparatorIndexes.back() + 1); + for (size_t I : SeparatorIndexes) + makeRowSeparator(RST[I]); +} + +bool isRemarkGroup(const Record *DiagGroup, + const std::map<std::string, GroupInfo> &DiagsInGroup) { + bool AnyRemarks = false, AnyNonRemarks = false; + + std::function<void(StringRef)> Visit = [&](StringRef GroupName) { + auto &GroupInfo = DiagsInGroup.find(GroupName)->second; + for (const Record *Diag : GroupInfo.DiagsInGroup) + (isRemark(*Diag) ? AnyRemarks : AnyNonRemarks) = true; + for (const auto &Name : GroupInfo.SubGroups) + Visit(Name); + }; + Visit(DiagGroup->getValueAsString("GroupName")); + + if (AnyRemarks && AnyNonRemarks) + PrintFatalError( + DiagGroup->getLoc(), + "Diagnostic group contains both remark and non-remark diagnostics"); + return AnyRemarks; +} + +std::string getDefaultSeverity(const Record *Diag) { + return Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name"); +} + +std::set<std::string> +getDefaultSeverities(const Record *DiagGroup, + const std::map<std::string, GroupInfo> &DiagsInGroup) { + std::set<std::string> States; + + std::function<void(StringRef)> Visit = [&](StringRef GroupName) { + auto &GroupInfo = DiagsInGroup.find(GroupName)->second; + for (const Record *Diag : GroupInfo.DiagsInGroup) + States.insert(getDefaultSeverity(Diag)); + for (const auto &Name : GroupInfo.SubGroups) + Visit(Name); + }; + Visit(DiagGroup->getValueAsString("GroupName")); + return States; +} + +void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') { + OS << Str << "\n" << std::string(Str.size(), Kind) << "\n"; +} + +void writeDiagnosticText(StringRef Role, StringRef Text, raw_ostream &OS) { + if (Text == "%0") + OS << "The text of this diagnostic is not controlled by Clang.\n\n"; + else { + std::vector<std::string> Out; + DiagText(Role, Text).print(Out); + for (auto &Line : Out) + OS << Line << "\n"; + OS << "\n"; + } +} + +} // namespace +} // namespace docs + +void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) { + using namespace docs; + + // Get the documentation introduction paragraph. + const Record *Documentation = Records.getDef("GlobalDocumentation"); + if (!Documentation) { + PrintFatalError("The Documentation top-level definition is missing, " + "no documentation will be generated."); + return; + } + + OS << Documentation->getValueAsString("Intro") << "\n"; + + std::vector<Record*> Diags = + Records.getAllDerivedDefinitions("Diagnostic"); + std::vector<Record*> DiagGroups = + Records.getAllDerivedDefinitions("DiagGroup"); + std::sort(DiagGroups.begin(), DiagGroups.end(), diagGroupBeforeByName); + + DiagGroupParentMap DGParentMap(Records); + + std::map<std::string, GroupInfo> DiagsInGroup; + groupDiagnostics(Diags, DiagGroups, DiagsInGroup); + + // Compute the set of diagnostics that are in -Wpedantic. + { + RecordSet DiagsInPedanticSet; + RecordSet GroupsInPedanticSet; + InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup); + inferPedantic.compute(&DiagsInPedanticSet, &GroupsInPedanticSet); + auto &PedDiags = DiagsInGroup["pedantic"]; + // Put the diagnostics into a deterministic order. + RecordVec DiagsInPedantic(DiagsInPedanticSet.begin(), + DiagsInPedanticSet.end()); + RecordVec GroupsInPedantic(GroupsInPedanticSet.begin(), + GroupsInPedanticSet.end()); + std::sort(DiagsInPedantic.begin(), DiagsInPedantic.end(), + beforeThanCompare); + std::sort(GroupsInPedantic.begin(), GroupsInPedantic.end(), + beforeThanCompare); + PedDiags.DiagsInGroup.insert(PedDiags.DiagsInGroup.end(), + DiagsInPedantic.begin(), + DiagsInPedantic.end()); + for (auto *Group : GroupsInPedantic) + PedDiags.SubGroups.push_back(Group->getValueAsString("GroupName")); + } + + // FIXME: Write diagnostic categories and link to diagnostic groups in each. + + // Write out the diagnostic groups. + for (const Record *G : DiagGroups) { + bool IsRemarkGroup = isRemarkGroup(G, DiagsInGroup); + auto &GroupInfo = DiagsInGroup[G->getValueAsString("GroupName")]; + bool IsSynonym = GroupInfo.DiagsInGroup.empty() && + GroupInfo.SubGroups.size() == 1; + + writeHeader((IsRemarkGroup ? "-R" : "-W") + + G->getValueAsString("GroupName"), + OS); + + if (!IsSynonym) { + // FIXME: Ideally, all the diagnostics in a group should have the same + // default state, but that is not currently the case. + auto DefaultSeverities = getDefaultSeverities(G, DiagsInGroup); + if (!DefaultSeverities.empty() && !DefaultSeverities.count("Ignored")) { + bool AnyNonErrors = DefaultSeverities.count("Warning") || + DefaultSeverities.count("Remark"); + if (!AnyNonErrors) + OS << "This diagnostic is an error by default, but the flag ``-Wno-" + << G->getValueAsString("GroupName") << "`` can be used to disable " + << "the error.\n\n"; + else + OS << "This diagnostic is enabled by default.\n\n"; + } else if (DefaultSeverities.size() > 1) { + OS << "Some of the diagnostics controlled by this flag are enabled " + << "by default.\n\n"; + } + } + + if (!GroupInfo.SubGroups.empty()) { + if (IsSynonym) + OS << "Synonym for "; + else if (GroupInfo.DiagsInGroup.empty()) + OS << "Controls "; + else + OS << "Also controls "; + + bool First = true; + std::sort(GroupInfo.SubGroups.begin(), GroupInfo.SubGroups.end()); + for (const auto &Name : GroupInfo.SubGroups) { + if (!First) OS << ", "; + OS << "`" << (IsRemarkGroup ? "-R" : "-W") << Name << "`_"; + First = false; + } + OS << ".\n\n"; + } + + if (!GroupInfo.DiagsInGroup.empty()) { + OS << "**Diagnostic text:**\n\n"; + for (const Record *D : GroupInfo.DiagsInGroup) { + auto Severity = getDefaultSeverity(D); + Severity[0] = tolower(Severity[0]); + if (Severity == "ignored") + Severity = IsRemarkGroup ? "remark" : "warning"; + writeDiagnosticText(Severity, D->getValueAsString("Text"), OS); + } + } + + auto Doc = G->getValueAsString("Documentation"); + if (!Doc.empty()) + OS << Doc; + else if (GroupInfo.SubGroups.empty() && GroupInfo.DiagsInGroup.empty()) + OS << "This diagnostic flag exists for GCC compatibility, and has no " + "effect in Clang.\n"; + OS << "\n"; + } +} + } // end namespace clang diff --git a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp index b5313a0..49c1edc 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp @@ -24,24 +24,32 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/SetTheory.h" -#include "llvm/TableGen/TableGenBackend.h" #include <algorithm> +#include <cassert> +#include <cctype> +#include <cstddef> +#include <cstdint> #include <deque> #include <map> +#include <set> #include <sstream> #include <string> #include <utility> #include <vector> + using namespace llvm; namespace { @@ -76,6 +84,7 @@ enum ClassKind { /// builtins. These must be kept in sync with the flags in /// include/clang/Basic/TargetBuiltins.h. namespace NeonTypeFlags { + enum { EltTypeMask = 0xf, UnsignedFlag = 0x10, QuadFlag = 0x20 }; enum EltType { @@ -91,12 +100,10 @@ enum EltType { Float32, Float64 }; -} -class Intrinsic; +} // end namespace NeonTypeFlags + class NeonEmitter; -class Type; -class Variable; //===----------------------------------------------------------------------===// // TypeSpec @@ -192,6 +199,7 @@ public: // void makeUnsigned() { Signed = false; } void makeSigned() { Signed = true; } + void makeInteger(unsigned ElemWidth, bool Sign) { Float = false; Poly = false; @@ -199,6 +207,7 @@ public: Immediate = false; ElementBitwidth = ElemWidth; } + void makeImmediate(unsigned ElemWidth) { Float = false; Poly = false; @@ -206,18 +215,22 @@ public: Immediate = true; ElementBitwidth = ElemWidth; } + void makeScalar() { Bitwidth = ElementBitwidth; NumVectors = 0; } + void makeOneVector() { assert(isVector()); NumVectors = 1; } + void doubleLanes() { assert_with_loc(Bitwidth != 128, "Can't get bigger than 128!"); Bitwidth = 128; } + void halveLanes() { assert_with_loc(Bitwidth != 64, "Can't get smaller than 64!"); Bitwidth = 64; @@ -369,6 +382,7 @@ public: bool hasImmediate() const { return Proto.find('i') != std::string::npos; } + /// Return the parameter index of the immediate operand. unsigned getImmediateIdx() const { assert(hasImmediate()); @@ -379,6 +393,7 @@ public: /// Return true if the intrinsic takes an splat operand. bool hasSplat() const { return Proto.find('a') != std::string::npos; } + /// Return the parameter index of the splat operand. unsigned getSplatIdx() const { assert(hasSplat()); @@ -414,7 +429,7 @@ public: return Idx; } - bool hasBody() const { return Body && Body->getValues().size() > 0; } + bool hasBody() const { return Body && !Body->getValues().empty(); } void setNeededEarly() { NeededEarly = true; } @@ -487,7 +502,6 @@ private: std::pair<Type, std::string> emitDagOp(DagInit *DI); std::pair<Type, std::string> emitDag(DagInit *DI); }; - }; //===----------------------------------------------------------------------===// @@ -1071,7 +1085,7 @@ std::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) const { Name == "vcvt_f32_f64" || Name == "vcvt_f64_f32") return Name; - if (typeCode.size() > 0) { + if (!typeCode.empty()) { // If the name ends with _xN (N = 2,3,4), insert the typeCode before _xN. if (Name.size() >= 3 && isdigit(Name.back()) && Name[Name.length() - 2] == 'x' && Name[Name.length() - 3] == '_') @@ -1246,7 +1260,6 @@ void Intrinsic::emitReturnReversal() { emitReverseVariable(RetVar, RetVar); } - void Intrinsic::emitShadowedArgs() { // Macro arguments are not type-checked like inline function arguments, // so assign them to local temporaries to get the right type checking. @@ -1397,7 +1410,7 @@ void Intrinsic::emitBody(StringRef CallPrefix) { emitNewLine(); } - if (!Body || Body->getValues().size() == 0) { + if (!Body || Body->getValues().empty()) { // Nothing specific to output - must output a builtin. emitBodyAsBuiltinCall(); return; @@ -1465,14 +1478,14 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagOp(DagInit *DI) { if (DI->getNumArgs() == 2) { // Unary op. std::pair<Type, std::string> R = - emitDagArg(DI->getArg(1), DI->getArgName(1)); + emitDagArg(DI->getArg(1), DI->getArgNameStr(1)); return std::make_pair(R.first, Op + R.second); } else { assert(DI->getNumArgs() == 3 && "Can only handle unary and binary ops!"); std::pair<Type, std::string> R1 = - emitDagArg(DI->getArg(1), DI->getArgName(1)); + emitDagArg(DI->getArg(1), DI->getArgNameStr(1)); std::pair<Type, std::string> R2 = - emitDagArg(DI->getArg(2), DI->getArgName(2)); + emitDagArg(DI->getArg(2), DI->getArgNameStr(2)); assert_with_loc(R1.first == R2.first, "Argument type mismatch!"); return std::make_pair(R1.first, R1.second + " " + Op + " " + R2.second); } @@ -1483,7 +1496,7 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) { std::vector<std::string> Values; for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) { std::pair<Type, std::string> R = - emitDagArg(DI->getArg(I + 1), DI->getArgName(I + 1)); + emitDagArg(DI->getArg(I + 1), DI->getArgNameStr(I + 1)); Types.push_back(R.first); Values.push_back(R.second); } @@ -1516,7 +1529,8 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI, bool IsBitCast){ // (cast MOD* VAL) -> cast VAL to type given by MOD. std::pair<Type, std::string> R = emitDagArg( - DI->getArg(DI->getNumArgs() - 1), DI->getArgName(DI->getNumArgs() - 1)); + DI->getArg(DI->getNumArgs() - 1), + DI->getArgNameStr(DI->getNumArgs() - 1)); Type castToType = R.first; for (unsigned ArgIdx = 0; ArgIdx < DI->getNumArgs() - 1; ++ArgIdx) { @@ -1527,11 +1541,11 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI, // 4. The value "U" or "S" to switch the signedness. // 5. The value "H" or "D" to half or double the bitwidth. // 6. The value "8" to convert to 8-bit (signed) integer lanes. - if (DI->getArgName(ArgIdx).size()) { - assert_with_loc(Intr.Variables.find(DI->getArgName(ArgIdx)) != + if (!DI->getArgNameStr(ArgIdx).empty()) { + assert_with_loc(Intr.Variables.find(DI->getArgNameStr(ArgIdx)) != Intr.Variables.end(), "Variable not found"); - castToType = Intr.Variables[DI->getArgName(ArgIdx)].getType(); + castToType = Intr.Variables[DI->getArgNameStr(ArgIdx)].getType(); } else { StringInit *SI = dyn_cast<StringInit>(DI->getArg(ArgIdx)); assert_with_loc(SI, "Expected string type or $Name for cast type"); @@ -1589,6 +1603,7 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ Elts.insert(Elts2.begin(), Elts2.begin() + (Elts2.size() / 2)); } }; + class HighHalf : public SetTheory::Operator { public: void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, @@ -1598,11 +1613,13 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ Elts.insert(Elts2.begin() + (Elts2.size() / 2), Elts2.end()); } }; + class Rev : public SetTheory::Operator { unsigned ElementSize; public: Rev(unsigned ElementSize) : ElementSize(ElementSize) {} + void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, ArrayRef<SMLoc> Loc) override { SetTheory::RecSet Elts2; @@ -1621,11 +1638,13 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ Elts.insert(Revved.begin(), Revved.end()); } }; + class MaskExpander : public SetTheory::Expander { unsigned N; public: MaskExpander(unsigned N) : N(N) {} + void expand(SetTheory &ST, Record *R, SetTheory::RecSet &Elts) override { unsigned Addend = 0; if (R->getName() == "mask0") @@ -1641,9 +1660,9 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ // (shuffle arg1, arg2, sequence) std::pair<Type, std::string> Arg1 = - emitDagArg(DI->getArg(0), DI->getArgName(0)); + emitDagArg(DI->getArg(0), DI->getArgNameStr(0)); std::pair<Type, std::string> Arg2 = - emitDagArg(DI->getArg(1), DI->getArgName(1)); + emitDagArg(DI->getArg(1), DI->getArgNameStr(1)); assert_with_loc(Arg1.first == Arg2.first, "Different types in arguments to shuffle!"); @@ -1685,7 +1704,8 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) { assert_with_loc(DI->getNumArgs() == 1, "dup() expects one argument"); - std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0)); + std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), + DI->getArgNameStr(0)); assert_with_loc(A.first.isScalar(), "dup() expects a scalar argument"); Type T = Intr.getBaseType(); @@ -1703,8 +1723,10 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) { std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSplat(DagInit *DI) { assert_with_loc(DI->getNumArgs() == 2, "splat() expects two arguments"); - std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0)); - std::pair<Type, std::string> B = emitDagArg(DI->getArg(1), DI->getArgName(1)); + std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), + DI->getArgNameStr(0)); + std::pair<Type, std::string> B = emitDagArg(DI->getArg(1), + DI->getArgNameStr(1)); assert_with_loc(B.first.isScalar(), "splat() requires a scalar int as the second argument"); @@ -1720,13 +1742,15 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSplat(DagInit *DI) { std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSaveTemp(DagInit *DI) { assert_with_loc(DI->getNumArgs() == 2, "save_temp() expects two arguments"); - std::pair<Type, std::string> A = emitDagArg(DI->getArg(1), DI->getArgName(1)); + std::pair<Type, std::string> A = emitDagArg(DI->getArg(1), + DI->getArgNameStr(1)); assert_with_loc(!A.first.isVoid(), "Argument to save_temp() must have non-void type!"); - std::string N = DI->getArgName(0); - assert_with_loc(N.size(), "save_temp() expects a name as the first argument"); + std::string N = DI->getArgNameStr(0); + assert_with_loc(!N.empty(), + "save_temp() expects a name as the first argument"); assert_with_loc(Intr.Variables.find(N) == Intr.Variables.end(), "Variable already defined!"); @@ -1762,7 +1786,7 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagLiteral(DagInit *DI){ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagArg(Init *Arg, std::string ArgName) { - if (ArgName.size()) { + if (!ArgName.empty()) { assert_with_loc(!Arg->isComplete(), "Arguments must either be DAGs or names, not both!"); assert_with_loc(Intr.Variables.find(ArgName) != Intr.Variables.end(), @@ -1900,7 +1924,7 @@ Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) { GoodVec.push_back(&I); } - assert_with_loc(GoodVec.size() > 0, + assert_with_loc(!GoodVec.empty(), "No compatible intrinsic found - " + ErrMsg); assert_with_loc(GoodVec.size() == 1, "Multiple overloads found - " + ErrMsg); @@ -2157,9 +2181,9 @@ NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS, OS << "case NEON::BI__builtin_neon_" << Def->getMangledName() << ": " << "i = " << Idx << ";"; - if (LowerBound.size()) + if (!LowerBound.empty()) OS << " l = " << LowerBound << ";"; - if (UpperBound.size()) + if (!UpperBound.empty()) OS << " u = " << UpperBound << ";"; OS << " break;\n"; @@ -2350,7 +2374,7 @@ void NeonEmitter::run(raw_ostream &OS) { // Only emit a def when its requirements have been met. // FIXME: This loop could be made faster, but it's fast enough for now. bool MadeProgress = true; - std::string InGuard = ""; + std::string InGuard; while (!Defs.empty() && MadeProgress) { MadeProgress = false; @@ -2393,13 +2417,17 @@ void NeonEmitter::run(raw_ostream &OS) { } namespace clang { + void EmitNeon(RecordKeeper &Records, raw_ostream &OS) { NeonEmitter(Records).run(OS); } + void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) { NeonEmitter(Records).runHeader(OS); } + void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) { llvm_unreachable("Neon test generation no longer implemented!"); } -} // End namespace clang + +} // end namespace clang diff --git a/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp b/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp index 7ccd715..6fb5b00 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp @@ -13,7 +13,6 @@ #include "TableGenBackends.h" // Declares all backends. #include "llvm/Support/CommandLine.h" -#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/TableGen/Error.h" @@ -53,7 +52,8 @@ enum ActionType { GenArmNeon, GenArmNeonSema, GenArmNeonTest, - GenAttrDocs + GenAttrDocs, + GenDiagDocs }; namespace { @@ -134,7 +134,8 @@ cl::opt<ActionType> Action( "Generate ARM NEON tests for clang"), clEnumValN(GenAttrDocs, "gen-attr-docs", "Generate attribute documentation"), - clEnumValEnd)); + clEnumValN(GenDiagDocs, "gen-diag-docs", + "Generate attribute documentation"))); cl::opt<std::string> ClangComponent("clang-component", @@ -234,6 +235,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenAttrDocs: EmitClangAttrDocs(Records, OS); break; + case GenDiagDocs: + EmitClangDiagDocs(Records, OS); + break; } return false; diff --git a/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h b/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h index 4adf368..0305ed1 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h +++ b/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h @@ -69,6 +69,7 @@ void EmitNeonSema2(RecordKeeper &Records, raw_ostream &OS); void EmitNeonTest2(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS); +void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS); } // end namespace clang |