diff options
author | dim <dim@FreeBSD.org> | 2014-11-24 18:11:16 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-11-24 18:11:16 +0000 |
commit | 6148c19c738a92f344008aa3f88f4e008bada0ee (patch) | |
tree | d4426858455f04d0d8c25a2f9eb9ea5582ffe1b6 /contrib/llvm/tools/clang/lib/Basic | |
parent | 2c8643c6396b0a3db33430cf9380e70bbb9efce0 (diff) | |
parent | 173a4f43a911175643bda81ee675e8d9269056ea (diff) | |
download | FreeBSD-src-6148c19c738a92f344008aa3f88f4e008bada0ee.zip FreeBSD-src-6148c19c738a92f344008aa3f88f4e008bada0ee.tar.gz |
Merge clang 3.5.0 release from ^/vendor/clang/dist, resolve conflicts,
and preserve our customizations, where necessary.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic')
17 files changed, 3785 insertions, 1629 deletions
diff --git a/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp b/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp new file mode 100644 index 0000000..a05ad05 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp @@ -0,0 +1,17 @@ +#include "clang/Basic/Attributes.h" +#include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/StringSwitch.h" +using namespace clang; + +bool clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, + const IdentifierInfo *Attr, const llvm::Triple &T, + const LangOptions &LangOpts) { + StringRef Name = Attr->getName(); + // Normalize the attribute name, __foo__ becomes foo. + if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) + Name = Name.substr(2, Name.size() - 4); + +#include "clang/Basic/AttrHasAttributeImpl.inc" + + return false; +} diff --git a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp index c84dd6d..8efcac6 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp @@ -20,7 +20,7 @@ using namespace clang; static const Builtin::Info BuiltinInfo[] = { - { "not a builtin function", 0, 0, 0, ALL_LANGUAGES }, + { "not a builtin function", nullptr, nullptr, nullptr, ALL_LANGUAGES}, #define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, #define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) { #ID, TYPE, ATTRS, 0, BUILTIN_LANG }, #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) { #ID, TYPE, ATTRS, HEADER,\ @@ -37,7 +37,7 @@ const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const { Builtin::Context::Context() { // Get the target specific builtins from the target. - TSRecords = 0; + TSRecords = nullptr; NumTSRecords = 0; } @@ -76,7 +76,7 @@ void Builtin::Context::InitializeBuiltins(IdentifierTable &Table, // Step #2: Register target-specific builtins. for (unsigned i = 0, e = NumTSRecords; i != e; ++i) - if (!LangOpts.NoBuiltin || !strchr(TSRecords[i].Attributes, 'f')) + if (BuiltinIsSupported(TSRecords[i], LangOpts)) Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin); } @@ -97,40 +97,35 @@ void Builtin::Context::ForgetBuiltin(unsigned ID, IdentifierTable &Table) { Table.get(GetRecord(ID).Name).setBuiltinID(0); } -bool -Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx, - bool &HasVAListArg) { - const char *Printf = strpbrk(GetRecord(ID).Attributes, "pP"); - if (!Printf) +bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx, + bool &HasVAListArg, const char *Fmt) const { + assert(Fmt && "Not passed a format string"); + assert(::strlen(Fmt) == 2 && + "Format string needs to be two characters long"); + assert(::toupper(Fmt[0]) == Fmt[1] && + "Format string is not in the form \"xX\""); + + const char *Like = ::strpbrk(GetRecord(ID).Attributes, Fmt); + if (!Like) return false; - HasVAListArg = (*Printf == 'P'); + HasVAListArg = (*Like == Fmt[1]); - ++Printf; - assert(*Printf == ':' && "p or P specifier must have be followed by a ':'"); - ++Printf; + ++Like; + assert(*Like == ':' && "Format specifier must be followed by a ':'"); + ++Like; - assert(strchr(Printf, ':') && "printf specifier must end with a ':'"); - FormatIdx = strtol(Printf, 0, 10); + assert(::strchr(Like, ':') && "Format specifier must end with a ':'"); + FormatIdx = ::strtol(Like, nullptr, 10); return true; } -// FIXME: Refactor with isPrintfLike. -bool -Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx, - bool &HasVAListArg) { - const char *Scanf = strpbrk(GetRecord(ID).Attributes, "sS"); - if (!Scanf) - return false; - - HasVAListArg = (*Scanf == 'S'); - - ++Scanf; - assert(*Scanf == ':' && "s or S specifier must have be followed by a ':'"); - ++Scanf; - - assert(strchr(Scanf, ':') && "printf specifier must end with a ':'"); - FormatIdx = strtol(Scanf, 0, 10); - return true; +bool Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx, + bool &HasVAListArg) { + return isLike(ID, FormatIdx, HasVAListArg, "pP"); } +bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx, + bool &HasVAListArg) { + return isLike(ID, FormatIdx, HasVAListArg, "sS"); +} diff --git a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp index 45d4b53..4567e32 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp @@ -24,15 +24,13 @@ using namespace clang; static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT, - const char *Modifier, unsigned ML, - const char *Argument, unsigned ArgLen, - const DiagnosticsEngine::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, - SmallVectorImpl<char> &Output, - void *Cookie, - ArrayRef<intptr_t> QualTypeVals) { - const char *Str = "<can't format argument>"; - Output.append(Str, Str+strlen(Str)); + StringRef Modifier, StringRef Argument, + ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs, + SmallVectorImpl<char> &Output, + void *Cookie, + ArrayRef<intptr_t> QualTypeVals) { + StringRef Str = "<can't format argument>"; + Output.append(Str.begin(), Str.end()); } @@ -41,9 +39,9 @@ DiagnosticsEngine::DiagnosticsEngine( DiagnosticOptions *DiagOpts, DiagnosticConsumer *client, bool ShouldOwnClient) : Diags(diags), DiagOpts(DiagOpts), Client(client), - OwnsDiagClient(ShouldOwnClient), SourceMgr(0) { + OwnsDiagClient(ShouldOwnClient), SourceMgr(nullptr) { ArgToStringFn = DummyArgToStringFn; - ArgToStringCookie = 0; + ArgToStringCookie = nullptr; AllExtensionsSilenced = 0; IgnoreAllWarnings = false; @@ -56,7 +54,7 @@ DiagnosticsEngine::DiagnosticsEngine( PrintTemplateTree = false; ShowColors = false; ShowOverloads = Ovl_All; - ExtBehavior = Ext_Ignore; + ExtBehavior = diag::Severity::Ignored; ErrorLimit = 0; TemplateBacktraceLimit = 0; @@ -157,17 +155,17 @@ DiagnosticsEngine::GetDiagStatePointForLoc(SourceLocation L) const { if (LastStateChangePos.isValid() && Loc.isBeforeInTranslationUnitThan(LastStateChangePos)) Pos = std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(), - DiagStatePoint(0, Loc)); + DiagStatePoint(nullptr, Loc)); --Pos; return Pos; } -void DiagnosticsEngine::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, - SourceLocation L) { +void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map, + SourceLocation L) { assert(Diag < diag::DIAG_UPPER_LIMIT && "Can only map builtin diagnostics"); assert((Diags->isBuiltinWarningOrExtension(Diag) || - (Map == diag::MAP_FATAL || Map == diag::MAP_ERROR)) && + (Map == diag::Severity::Fatal || Map == diag::Severity::Error)) && "Cannot map errors into warnings!"); assert(!DiagStatePoints.empty()); assert((L.isInvalid() || SourceMgr) && "No SourceMgr for valid location"); @@ -175,17 +173,17 @@ void DiagnosticsEngine::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, FullSourceLoc Loc = SourceMgr? FullSourceLoc(L, *SourceMgr) : FullSourceLoc(); FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc; // Don't allow a mapping to a warning override an error/fatal mapping. - if (Map == diag::MAP_WARNING) { - DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo(Diag); - if (Info.getMapping() == diag::MAP_ERROR || - Info.getMapping() == diag::MAP_FATAL) - Map = Info.getMapping(); + if (Map == diag::Severity::Warning) { + DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag); + if (Info.getSeverity() == diag::Severity::Error || + Info.getSeverity() == diag::Severity::Fatal) + Map = Info.getSeverity(); } - DiagnosticMappingInfo MappingInfo = makeMappingInfo(Map, L); + DiagnosticMapping Mapping = makeUserMapping(Map, L); // Common case; setting all the diagnostics of a group in one place. if (Loc.isInvalid() || Loc == LastStateChangePos) { - GetCurDiagState()->setMappingInfo(Diag, MappingInfo); + GetCurDiagState()->setMapping(Diag, Mapping); return; } @@ -198,7 +196,7 @@ void DiagnosticsEngine::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, // the new state became active. DiagStates.push_back(*GetCurDiagState()); PushDiagStatePoint(&DiagStates.back(), Loc); - GetCurDiagState()->setMappingInfo(Diag, MappingInfo); + GetCurDiagState()->setMapping(Diag, Mapping); return; } @@ -211,81 +209,64 @@ void DiagnosticsEngine::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, // Update all diagnostic states that are active after the given location. for (DiagStatePointsTy::iterator I = Pos+1, E = DiagStatePoints.end(); I != E; ++I) { - GetCurDiagState()->setMappingInfo(Diag, MappingInfo); + GetCurDiagState()->setMapping(Diag, Mapping); } // If the location corresponds to an existing point, just update its state. if (Pos->Loc == Loc) { - GetCurDiagState()->setMappingInfo(Diag, MappingInfo); + GetCurDiagState()->setMapping(Diag, Mapping); return; } // Create a new state/point and fit it into the vector of DiagStatePoints // so that the vector is always ordered according to location. - Pos->Loc.isBeforeInTranslationUnitThan(Loc); + assert(Pos->Loc.isBeforeInTranslationUnitThan(Loc)); DiagStates.push_back(*Pos->State); DiagState *NewState = &DiagStates.back(); - GetCurDiagState()->setMappingInfo(Diag, MappingInfo); + GetCurDiagState()->setMapping(Diag, Mapping); DiagStatePoints.insert(Pos+1, DiagStatePoint(NewState, FullSourceLoc(Loc, *SourceMgr))); } -bool DiagnosticsEngine::setDiagnosticGroupMapping( - StringRef Group, diag::Mapping Map, SourceLocation Loc) -{ +bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor, + StringRef Group, diag::Severity Map, + SourceLocation Loc) { // Get the diagnostics in this group. SmallVector<diag::kind, 8> GroupDiags; - if (Diags->getDiagnosticsInGroup(Group, GroupDiags)) + if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags)) return true; // Set the mapping. for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) - setDiagnosticMapping(GroupDiags[i], Map, Loc); + setSeverity(GroupDiags[i], Map, Loc); return false; } -void DiagnosticsEngine::setDiagnosticWarningAsError(diag::kind Diag, - bool Enabled) { - // If we are enabling this feature, just set the diagnostic mappings to map to - // errors. - if (Enabled) - setDiagnosticMapping(Diag, diag::MAP_ERROR, SourceLocation()); - - // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and - // potentially downgrade anything already mapped to be a warning. - DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo(Diag); - - if (Info.getMapping() == diag::MAP_ERROR || - Info.getMapping() == diag::MAP_FATAL) - Info.setMapping(diag::MAP_WARNING); - - Info.setNoWarningAsError(true); -} - bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled) { // If we are enabling this feature, just set the diagnostic mappings to map to // errors. if (Enabled) - return setDiagnosticGroupMapping(Group, diag::MAP_ERROR); + return setSeverityForGroup(diag::Flavor::WarningOrError, Group, + diag::Severity::Error); // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and // potentially downgrade anything already mapped to be a warning. // Get the diagnostics in this group. SmallVector<diag::kind, 8> GroupDiags; - if (Diags->getDiagnosticsInGroup(Group, GroupDiags)) + if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group, + GroupDiags)) return true; // Perform the mapping change. for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) { - DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo( - GroupDiags[i]); + DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(GroupDiags[i]); - if (Info.getMapping() == diag::MAP_ERROR || - Info.getMapping() == diag::MAP_FATAL) - Info.setMapping(diag::MAP_WARNING); + if (Info.getSeverity() == diag::Severity::Error || + Info.getSeverity() == diag::Severity::Fatal) + Info.setSeverity(diag::Severity::Warning); Info.setNoWarningAsError(true); } @@ -293,45 +274,29 @@ bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group, return false; } -void DiagnosticsEngine::setDiagnosticErrorAsFatal(diag::kind Diag, - bool Enabled) { - // If we are enabling this feature, just set the diagnostic mappings to map to - // errors. - if (Enabled) - setDiagnosticMapping(Diag, diag::MAP_FATAL, SourceLocation()); - - // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and - // potentially downgrade anything already mapped to be a warning. - DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo(Diag); - - if (Info.getMapping() == diag::MAP_FATAL) - Info.setMapping(diag::MAP_ERROR); - - Info.setNoErrorAsFatal(true); -} - bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled) { // If we are enabling this feature, just set the diagnostic mappings to map to // fatal errors. if (Enabled) - return setDiagnosticGroupMapping(Group, diag::MAP_FATAL); + return setSeverityForGroup(diag::Flavor::WarningOrError, Group, + diag::Severity::Fatal); // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and // potentially downgrade anything already mapped to be an error. // Get the diagnostics in this group. SmallVector<diag::kind, 8> GroupDiags; - if (Diags->getDiagnosticsInGroup(Group, GroupDiags)) + if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group, + GroupDiags)) return true; // Perform the mapping change. for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) { - DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo( - GroupDiags[i]); + DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(GroupDiags[i]); - if (Info.getMapping() == diag::MAP_FATAL) - Info.setMapping(diag::MAP_ERROR); + if (Info.getSeverity() == diag::Severity::Fatal) + Info.setSeverity(diag::Severity::Error); Info.setNoErrorAsFatal(true); } @@ -339,16 +304,17 @@ bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group, return false; } -void DiagnosticsEngine::setMappingToAllDiagnostics(diag::Mapping Map, - SourceLocation Loc) { +void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor, + diag::Severity Map, + SourceLocation Loc) { // Get all the diagnostics. SmallVector<diag::kind, 64> AllDiags; - Diags->getAllDiagnostics(AllDiags); + Diags->getAllDiagnostics(Flavor, AllDiags); // Set the mapping. for (unsigned i = 0, e = AllDiags.size(); i != e; ++i) if (Diags->isBuiltinWarningOrExtension(AllDiags[i])) - setDiagnosticMapping(AllDiags[i], Map, Loc); + setSeverity(AllDiags[i], Map, Loc); } void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) { @@ -358,22 +324,19 @@ void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) { CurDiagID = storedDiag.getID(); NumDiagArgs = 0; - NumDiagRanges = storedDiag.range_size(); - assert(NumDiagRanges < DiagnosticsEngine::MaxRanges && - "Too many arguments to diagnostic!"); - unsigned i = 0; + DiagRanges.clear(); + DiagRanges.reserve(storedDiag.range_size()); for (StoredDiagnostic::range_iterator RI = storedDiag.range_begin(), RE = storedDiag.range_end(); RI != RE; ++RI) - DiagRanges[i++] = *RI; + DiagRanges.push_back(*RI); - assert(NumDiagRanges < DiagnosticsEngine::MaxFixItHints && - "Too many arguments to diagnostic!"); - NumDiagFixItHints = 0; + DiagFixItHints.clear(); + DiagFixItHints.reserve(storedDiag.fixit_size()); for (StoredDiagnostic::fixit_iterator FI = storedDiag.fixit_begin(), FE = storedDiag.fixit_end(); FI != FE; ++FI) - DiagFixItHints[NumDiagFixItHints++] = *FI; + DiagFixItHints.push_back(*FI); assert(Client && "DiagnosticConsumer not set!"); Level DiagLevel = storedDiag.getLevel(); @@ -639,6 +602,17 @@ static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo, } } +/// \brief Returns the friendly description for a token kind that will appear +/// without quotes in diagnostic messages. These strings may be translatable in +/// future. +static const char *getTokenDescForDiagnostic(tok::TokenKind Kind) { + switch (Kind) { + case tok::identifier: + return "identifier"; + default: + return nullptr; + } +} /// FormatDiagnostic - Format this diagnostic into a string, substituting the /// formal arguments into the %0 slots. The result is appended onto the Str @@ -696,7 +670,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, // The digit is a number from 0-9 indicating which argument this comes from. // The modifier is a string of digits from the set [-a-z]+, arguments is a // brace enclosed string. - const char *Modifier = 0, *Argument = 0; + const char *Modifier = nullptr, *Argument = nullptr; unsigned ModifierLen = 0, ArgumentLen = 0; // Check to see if we have a modifier. If so eat it. @@ -812,6 +786,28 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, } break; } + // ---- TOKEN SPELLINGS ---- + case DiagnosticsEngine::ak_tokenkind: { + tok::TokenKind Kind = static_cast<tok::TokenKind>(getRawArg(ArgNo)); + assert(ModifierLen == 0 && "No modifiers for token kinds yet"); + + llvm::raw_svector_ostream Out(OutStr); + if (const char *S = tok::getPunctuatorSpelling(Kind)) + // Quoted token spelling for punctuators. + Out << '\'' << S << '\''; + else if (const char *S = tok::getKeywordSpelling(Kind)) + // Unquoted token spelling for keywords. + Out << S; + else if (const char *S = getTokenDescForDiagnostic(Kind)) + // Unquoted translatable token name. + Out << S; + else if (const char *S = tok::getTokenName(Kind)) + // Debug name, shouldn't appear in user-facing diagnostics. + Out << '<' << S << '>'; + else + Out << "(null)"; + break; + } // ---- NAMES and TYPES ---- case DiagnosticsEngine::ak_identifierinfo: { const IdentifierInfo *II = getArgIdentifier(ArgNo); @@ -832,10 +828,11 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, case DiagnosticsEngine::ak_nameddecl: case DiagnosticsEngine::ak_nestednamespec: case DiagnosticsEngine::ak_declcontext: + case DiagnosticsEngine::ak_attr: getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo), - Modifier, ModifierLen, - Argument, ArgumentLen, - FormattedArgs.data(), FormattedArgs.size(), + StringRef(Modifier, ModifierLen), + StringRef(Argument, ArgumentLen), + FormattedArgs, OutStr, QualTypeVals); break; case DiagnosticsEngine::ak_qualtype_pair: @@ -857,10 +854,9 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, TDT.PrintFromType = true; TDT.PrintTree = true; getDiags()->ConvertArgToString(Kind, val, - Modifier, ModifierLen, - Argument, ArgumentLen, - FormattedArgs.data(), - FormattedArgs.size(), + StringRef(Modifier, ModifierLen), + StringRef(Argument, ArgumentLen), + FormattedArgs, Tree, QualTypeVals); // If there is no tree information, fall back to regular printing. if (!Tree.empty()) { @@ -881,9 +877,9 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, TDT.PrintTree = false; TDT.PrintFromType = true; getDiags()->ConvertArgToString(Kind, val, - Modifier, ModifierLen, - Argument, ArgumentLen, - FormattedArgs.data(), FormattedArgs.size(), + StringRef(Modifier, ModifierLen), + StringRef(Argument, ArgumentLen), + FormattedArgs, OutStr, QualTypeVals); if (!TDT.TemplateDiffUsed) FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype, @@ -895,9 +891,9 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, // Append second type TDT.PrintFromType = false; getDiags()->ConvertArgToString(Kind, val, - Modifier, ModifierLen, - Argument, ArgumentLen, - FormattedArgs.data(), FormattedArgs.size(), + StringRef(Modifier, ModifierLen), + StringRef(Argument, ArgumentLen), + FormattedArgs, OutStr, QualTypeVals); if (!TDT.TemplateDiffUsed) FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype, diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp index 9d99fbe..ec244cc 100644 --- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp @@ -15,8 +15,8 @@ #include "clang/Basic/AllDiagnostics.h" #include "clang/Basic/DiagnosticCategories.h" #include "clang/Basic/SourceManager.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/ErrorHandling.h" #include <map> using namespace clang; @@ -30,14 +30,15 @@ namespace { // Diagnostic classes. enum { CLASS_NOTE = 0x01, - CLASS_WARNING = 0x02, - CLASS_EXTENSION = 0x03, - CLASS_ERROR = 0x04 + CLASS_REMARK = 0x02, + CLASS_WARNING = 0x03, + CLASS_EXTENSION = 0x04, + CLASS_ERROR = 0x05 }; struct StaticDiagInfoRec { uint16_t DiagID; - unsigned Mapping : 3; + unsigned DefaultSeverity : 3; unsigned Class : 3; unsigned SFINAE : 2; unsigned WarnNoWerror : 1; @@ -57,6 +58,11 @@ struct StaticDiagInfoRec { return StringRef(DescriptionStr, DescriptionLen); } + diag::Flavor getFlavor() const { + return Class == CLASS_REMARK ? diag::Flavor::Remark + : diag::Flavor::WarningOrError; + } + bool operator<(const StaticDiagInfoRec &RHS) const { return DiagID < RHS.DiagID; } @@ -65,12 +71,13 @@ struct StaticDiagInfoRec { } // namespace anonymous static const StaticDiagInfoRec StaticDiagInfo[] = { -#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP, \ - SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) \ - { diag::ENUM, DEFAULT_MAPPING, CLASS, \ - DiagnosticIDs::SFINAE, \ - NOWERROR, SHOWINSYSHEADER, CATEGORY, GROUP, \ - STR_SIZE(DESC, uint16_t), DESC }, +#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, CATEGORY) \ + { \ + diag::ENUM, DEFAULT_SEVERITY, CLASS, DiagnosticIDs::SFINAE, NOWERROR, \ + SHOWINSYSHEADER, CATEGORY, GROUP, STR_SIZE(DESC, uint16_t), DESC \ + } \ + , #include "clang/Basic/DiagnosticCommonKinds.inc" #include "clang/Basic/DiagnosticDriverKinds.inc" #include "clang/Basic/DiagnosticFrontendKinds.inc" @@ -108,10 +115,10 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { // Out of bounds diag. Can't be in the table. using namespace diag; if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON) - return 0; + return nullptr; // Compute the index of the requested diagnostic in the static table. - // 1. Add the number of diagnostics in each category preceeding the + // 1. Add the number of diagnostics in each category preceding the // diagnostic and of the category the diagnostic is in. This gives us // the offset of the category in the table. // 2. Subtract the number of IDs in each category from our ID. This gives us @@ -138,7 +145,7 @@ CATEGORY(ANALYSIS, SEMA) // Avoid out of bounds reads. if (ID + Offset >= StaticDiagInfoSize) - return 0; + return nullptr; assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize); @@ -147,28 +154,22 @@ CATEGORY(ANALYSIS, SEMA) // happen when this function is called with an ID that points into a hole in // the diagID space. if (Found->DiagID != DiagID) - return 0; + return nullptr; return Found; } -static DiagnosticMappingInfo GetDefaultDiagMappingInfo(unsigned DiagID) { - DiagnosticMappingInfo Info = DiagnosticMappingInfo::Make( - diag::MAP_FATAL, /*IsUser=*/false, /*IsPragma=*/false); +static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID) { + DiagnosticMapping Info = DiagnosticMapping::Make( + diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false); if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) { - Info.setMapping((diag::Mapping) StaticInfo->Mapping); + Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity); if (StaticInfo->WarnNoWerror) { - assert(Info.getMapping() == diag::MAP_WARNING && + assert(Info.getSeverity() == diag::Severity::Warning && "Unexpected mapping with no-Werror bit!"); Info.setNoWarningAsError(true); } - - if (StaticInfo->WarnShowInSystemHeader) { - assert(Info.getMapping() == diag::MAP_WARNING && - "Unexpected mapping with show-in-system-header bit!"); - Info.setShowInSystemHeader(true); - } } return Info; @@ -197,15 +198,14 @@ namespace { // Unfortunately, the split between DiagnosticIDs and Diagnostic is not // particularly clean, but for now we just implement this method here so we can // access GetDefaultDiagMapping. -DiagnosticMappingInfo &DiagnosticsEngine::DiagState::getOrAddMappingInfo( - diag::kind Diag) -{ - std::pair<iterator, bool> Result = DiagMap.insert( - std::make_pair(Diag, DiagnosticMappingInfo())); +DiagnosticMapping & +DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) { + std::pair<iterator, bool> Result = + DiagMap.insert(std::make_pair(Diag, DiagnosticMapping())); // Initialize the entry if we added it. if (Result.second) - Result.first->second = GetDefaultDiagMappingInfo(Diag); + Result.first->second = GetDefaultDiagMapping(Diag); return Result.first->second; } @@ -215,7 +215,7 @@ static const StaticDiagCategoryRec CategoryNameTable[] = { #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) }, #include "clang/Basic/DiagnosticGroups.inc" #undef GET_CATEGORY_TABLE - { 0, 0 } + { nullptr, 0 } }; /// getNumberOfCategories - Return the number of categories @@ -264,14 +264,14 @@ namespace clang { /// getDescription - Return the description of the specified custom /// diagnostic. StringRef getDescription(unsigned DiagID) const { - assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() && + assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() && "Invalid diagnostic ID"); return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second; } /// getLevel - Return the level of the specified custom diagnostic. DiagnosticIDs::Level getLevel(unsigned DiagID) const { - assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() && + assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() && "Invalid diagnostic ID"); return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first; } @@ -300,9 +300,7 @@ namespace clang { // Common Diagnostic implementation //===----------------------------------------------------------------------===// -DiagnosticIDs::DiagnosticIDs() { - CustomDiagInfo = 0; -} +DiagnosticIDs::DiagnosticIDs() { CustomDiagInfo = nullptr; } DiagnosticIDs::~DiagnosticIDs() { delete CustomDiagInfo; @@ -311,10 +309,13 @@ DiagnosticIDs::~DiagnosticIDs() { /// getCustomDiagID - Return an ID for a diagnostic with the specified message /// and level. If this is the first request for this diagnostic, it is /// registered and created, otherwise the existing ID is returned. -unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef Message) { - if (CustomDiagInfo == 0) +/// +/// \param FormatString A fixed diagnostic format string that will be hashed and +/// mapped to a unique DiagID. +unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) { + if (!CustomDiagInfo) CustomDiagInfo = new diag::CustomDiagInfo(); - return CustomDiagInfo->getOrCreateDiagID(L, Message, *this); + return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this); } @@ -344,9 +345,9 @@ bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID, if (DiagID >= diag::DIAG_UPPER_LIMIT || getBuiltinDiagClass(DiagID) != CLASS_EXTENSION) return false; - + EnabledByDefault = - GetDefaultDiagMappingInfo(DiagID).getMapping() != diag::MAP_IGNORE; + GetDefaultDiagMapping(DiagID).getSeverity() != diag::Severity::Ignored; return true; } @@ -354,7 +355,7 @@ bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) { if (DiagID >= diag::DIAG_UPPER_LIMIT) return false; - return GetDefaultDiagMappingInfo(DiagID).getMapping() == diag::MAP_ERROR; + return GetDefaultDiagMapping(DiagID).getSeverity() == diag::Severity::Error; } /// getDescription - Given a diagnostic ID, return a description of the @@ -362,9 +363,26 @@ bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) { StringRef DiagnosticIDs::getDescription(unsigned DiagID) const { if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) return Info->getDescription(); + assert(CustomDiagInfo && "Invalid CustomDiagInfo"); return CustomDiagInfo->getDescription(DiagID); } +static DiagnosticIDs::Level toLevel(diag::Severity SV) { + switch (SV) { + case diag::Severity::Ignored: + return DiagnosticIDs::Ignored; + case diag::Severity::Remark: + return DiagnosticIDs::Remark; + case diag::Severity::Warning: + return DiagnosticIDs::Warning; + case diag::Severity::Error: + return DiagnosticIDs::Error; + case diag::Severity::Fatal: + return DiagnosticIDs::Fatal; + } + llvm_unreachable("unexpected severity"); +} + /// getDiagnosticLevel - Based on the way the client configured the /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level, /// by consumable the DiagnosticClient. @@ -372,12 +390,14 @@ DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, const DiagnosticsEngine &Diag) const { // Handle custom diagnostics, which cannot be mapped. - if (DiagID >= diag::DIAG_UPPER_LIMIT) + if (DiagID >= diag::DIAG_UPPER_LIMIT) { + assert(CustomDiagInfo && "Invalid CustomDiagInfo"); return CustomDiagInfo->getLevel(DiagID); + } unsigned DiagClass = getBuiltinDiagClass(DiagID); if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note; - return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag); + return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag)); } /// \brief Based on the way the client configured the Diagnostic @@ -386,41 +406,37 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, /// /// \param Loc The source location we are interested in finding out the /// diagnostic state. Can be null in order to query the latest state. -DiagnosticIDs::Level -DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, - SourceLocation Loc, - const DiagnosticsEngine &Diag) const { +diag::Severity +DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, + const DiagnosticsEngine &Diag) const { + assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE); + // Specific non-error diagnostics may be mapped to various levels from ignored // to error. Errors can only be mapped to fatal. - DiagnosticIDs::Level Result = DiagnosticIDs::Fatal; + diag::Severity Result = diag::Severity::Fatal; DiagnosticsEngine::DiagStatePointsTy::iterator Pos = Diag.GetDiagStatePointForLoc(Loc); DiagnosticsEngine::DiagState *State = Pos->State; // Get the mapping information, or compute it lazily. - DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo( - (diag::kind)DiagID); - - switch (MappingInfo.getMapping()) { - case diag::MAP_IGNORE: - Result = DiagnosticIDs::Ignored; - break; - case diag::MAP_WARNING: - Result = DiagnosticIDs::Warning; - break; - case diag::MAP_ERROR: - Result = DiagnosticIDs::Error; - break; - case diag::MAP_FATAL: - Result = DiagnosticIDs::Fatal; - break; - } + DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID); + + // TODO: Can a null severity really get here? + if (Mapping.getSeverity() != diag::Severity()) + Result = Mapping.getSeverity(); // Upgrade ignored diagnostics if -Weverything is enabled. - if (Diag.EnableAllWarnings && Result == DiagnosticIDs::Ignored && - !MappingInfo.isUser()) - Result = DiagnosticIDs::Warning; + if (Diag.EnableAllWarnings && Result == diag::Severity::Ignored && + !Mapping.isUser()) + Result = diag::Severity::Warning; + + // Diagnostics of class REMARK are either printed as remarks or in case they + // have been added to -Werror they are printed as errors. + // FIXME: Disregarding user-requested remark mappings like this is bogus. + if (Result == diag::Severity::Warning && + getBuiltinDiagClass(DiagID) == CLASS_REMARK) + Result = diag::Severity::Remark; // Ignore -pedantic diagnostics inside __extension__ blocks. // (The diagnostics controlled by -pedantic are the extension diagnostics @@ -428,62 +444,46 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, bool EnabledByDefault = false; bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault); if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault) - return DiagnosticIDs::Ignored; + return diag::Severity::Ignored; // For extension diagnostics that haven't been explicitly mapped, check if we // should upgrade the diagnostic. - if (IsExtensionDiag && !MappingInfo.isUser()) { - switch (Diag.ExtBehavior) { - case DiagnosticsEngine::Ext_Ignore: - break; - case DiagnosticsEngine::Ext_Warn: - // Upgrade ignored diagnostics to warnings. - if (Result == DiagnosticIDs::Ignored) - Result = DiagnosticIDs::Warning; - break; - case DiagnosticsEngine::Ext_Error: - // Upgrade ignored or warning diagnostics to errors. - if (Result == DiagnosticIDs::Ignored || Result == DiagnosticIDs::Warning) - Result = DiagnosticIDs::Error; - break; - } - } + if (IsExtensionDiag && !Mapping.isUser()) + Result = std::max(Result, Diag.ExtBehavior); // At this point, ignored errors can no longer be upgraded. - if (Result == DiagnosticIDs::Ignored) + if (Result == diag::Severity::Ignored) return Result; // Honor -w, which is lower in priority than pedantic-errors, but higher than // -Werror. - if (Result == DiagnosticIDs::Warning && Diag.IgnoreAllWarnings) - return DiagnosticIDs::Ignored; + if (Result == diag::Severity::Warning && Diag.IgnoreAllWarnings) + return diag::Severity::Ignored; // If -Werror is enabled, map warnings to errors unless explicitly disabled. - if (Result == DiagnosticIDs::Warning) { - if (Diag.WarningsAsErrors && !MappingInfo.hasNoWarningAsError()) - Result = DiagnosticIDs::Error; + if (Result == diag::Severity::Warning) { + if (Diag.WarningsAsErrors && !Mapping.hasNoWarningAsError()) + Result = diag::Severity::Error; } // If -Wfatal-errors is enabled, map errors to fatal unless explicity // disabled. - if (Result == DiagnosticIDs::Error) { - if (Diag.ErrorsAsFatal && !MappingInfo.hasNoErrorAsFatal()) - Result = DiagnosticIDs::Fatal; + if (Result == diag::Severity::Error) { + if (Diag.ErrorsAsFatal && !Mapping.hasNoErrorAsFatal()) + Result = diag::Severity::Fatal; } + // Custom diagnostics always are emitted in system headers. + bool ShowInSystemHeader = + !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader; + // If we are in a system header, we ignore it. We look at the diagnostic class // because we also want to ignore extensions and warnings in -Werror and // -pedantic-errors modes, which *map* warnings/extensions to errors. - if (Result >= DiagnosticIDs::Warning && - DiagClass != CLASS_ERROR && - // Custom diagnostics always are emitted in system headers. - DiagID < diag::DIAG_UPPER_LIMIT && - !MappingInfo.hasShowInSystemHeader() && - Diag.SuppressSystemWarnings && - Loc.isValid() && + if (Diag.SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() && Diag.getSourceManager().isInSystemHeader( Diag.getSourceManager().getExpansionLoc(Loc))) - return DiagnosticIDs::Ignored; + return diag::Severity::Ignored; return Result; } @@ -527,40 +527,57 @@ StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { return StringRef(); } -static void getDiagnosticsInGroup(const WarningOption *Group, +/// Return \c true if any diagnostics were found in this group, even if they +/// were filtered out due to having the wrong flavor. +static bool getDiagnosticsInGroup(diag::Flavor Flavor, + const WarningOption *Group, SmallVectorImpl<diag::kind> &Diags) { + // An empty group is considered to be a warning group: we have empty groups + // for GCC compatibility, and GCC does not have remarks. + if (!Group->Members && !Group->SubGroups) + return Flavor == diag::Flavor::Remark ? true : false; + + bool NotFound = true; + // Add the members of the option diagnostic set. const int16_t *Member = DiagArrays + Group->Members; - for (; *Member != -1; ++Member) - Diags.push_back(*Member); + for (; *Member != -1; ++Member) { + if (GetDiagInfo(*Member)->getFlavor() == Flavor) { + NotFound = false; + Diags.push_back(*Member); + } + } // Add the members of the subgroups. const int16_t *SubGroups = DiagSubGroups + Group->SubGroups; for (; *SubGroups != (int16_t)-1; ++SubGroups) - getDiagnosticsInGroup(&OptionTable[(short)*SubGroups], Diags); + NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups], + Diags); + + return NotFound; } -bool DiagnosticIDs::getDiagnosticsInGroup( - StringRef Group, - SmallVectorImpl<diag::kind> &Diags) const { - const WarningOption *Found = - std::lower_bound(OptionTable, OptionTable + OptionTableSize, Group, - WarningOptionCompare); +bool +DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, + SmallVectorImpl<diag::kind> &Diags) const { + const WarningOption *Found = std::lower_bound( + OptionTable, OptionTable + OptionTableSize, Group, WarningOptionCompare); if (Found == OptionTable + OptionTableSize || Found->getName() != Group) return true; // Option not found. - ::getDiagnosticsInGroup(Found, Diags); - return false; + return ::getDiagnosticsInGroup(Flavor, Found, Diags); } -void DiagnosticIDs::getAllDiagnostics( - SmallVectorImpl<diag::kind> &Diags) const { +void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor, + SmallVectorImpl<diag::kind> &Diags) const { for (unsigned i = 0; i != StaticDiagInfoSize; ++i) - Diags.push_back(StaticDiagInfo[i].DiagID); + if (StaticDiagInfo[i].getFlavor() == Flavor) + Diags.push_back(StaticDiagInfo[i].DiagID); } -StringRef DiagnosticIDs::getNearestWarningOption(StringRef Group) { +StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor, + StringRef Group) { StringRef Best; unsigned BestDistance = Group.size() + 1; // Sanity threshold. for (const WarningOption *i = OptionTable, *e = OptionTable + OptionTableSize; @@ -570,6 +587,14 @@ StringRef DiagnosticIDs::getNearestWarningOption(StringRef Group) { continue; unsigned Distance = i->getName().edit_distance(Group, true, BestDistance); + if (Distance > BestDistance) + continue; + + // Don't suggest groups that are not of this kind. + llvm::SmallVector<diag::kind, 8> Diags; + if (::getDiagnosticsInGroup(Flavor, i, Diags) || Diags.empty()) + continue; + if (Distance == BestDistance) { // Two matches with the same distance, don't prefer one over the other. Best = ""; @@ -677,6 +702,7 @@ void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const { bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const { if (DiagID >= diag::DIAG_UPPER_LIMIT) { + assert(CustomDiagInfo && "Invalid CustomDiagInfo"); // Custom diagnostics. return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error; } diff --git a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp index af9b266..9421032 100644 --- a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp @@ -25,29 +25,13 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" #include <map> #include <set> #include <string> +#include <system_error> -// FIXME: This is terrible, we need this for ::close. -#if !defined(_MSC_VER) && !defined(__MINGW32__) -#include <unistd.h> -#include <sys/uio.h> -#else -#include <io.h> -#ifndef S_ISFIFO -#define S_ISFIFO(x) (0) -#endif -#endif -#if defined(LLVM_ON_UNIX) -#include <limits.h> -#endif using namespace clang; -// FIXME: Enhance libsystem to support inode and other fields. -#include <sys/stat.h> - /// NON_EXISTENT_DIR - A special value distinct from null that is used to /// represent a dir name that doesn't exist on the disk. #define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1) @@ -56,63 +40,24 @@ using namespace clang; /// represent a filename that doesn't exist on the disk. #define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) - -FileEntry::~FileEntry() { - // If this FileEntry owns an open file descriptor that never got used, close - // it. - if (FD != -1) ::close(FD); -} - -class FileManager::UniqueDirContainer { - /// UniqueDirs - Cache from ID's to existing directories/files. - std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueDirs; - -public: - /// getDirectory - Return an existing DirectoryEntry with the given - /// ID's if there is already one; otherwise create and return a - /// default-constructed DirectoryEntry. - DirectoryEntry &getDirectory(const llvm::sys::fs::UniqueID &UniqueID) { - return UniqueDirs[UniqueID]; - } - - size_t size() const { return UniqueDirs.size(); } -}; - -class FileManager::UniqueFileContainer { - /// UniqueFiles - Cache from ID's to existing directories/files. - std::set<FileEntry> UniqueFiles; - -public: - /// getFile - Return an existing FileEntry with the given ID's if - /// there is already one; otherwise create and return a - /// default-constructed FileEntry. - FileEntry &getFile(llvm::sys::fs::UniqueID UniqueID, bool IsNamedPipe, - bool InPCH) { - return const_cast<FileEntry &>( - *UniqueFiles.insert(FileEntry(UniqueID, IsNamedPipe, InPCH)).first); - } - - size_t size() const { return UniqueFiles.size(); } - - void erase(const FileEntry *Entry) { UniqueFiles.erase(*Entry); } -}; - //===----------------------------------------------------------------------===// // Common logic. //===----------------------------------------------------------------------===// -FileManager::FileManager(const FileSystemOptions &FSO) - : FileSystemOpts(FSO), - UniqueRealDirs(*new UniqueDirContainer()), - UniqueRealFiles(*new UniqueFileContainer()), +FileManager::FileManager(const FileSystemOptions &FSO, + IntrusiveRefCntPtr<vfs::FileSystem> FS) + : FS(FS), FileSystemOpts(FSO), SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) { NumDirLookups = NumFileLookups = 0; NumDirCacheMisses = NumFileCacheMisses = 0; + + // If the caller doesn't provide a virtual file system, just grab the real + // file system. + if (!FS) + this->FS = vfs::getRealFileSystem(); } FileManager::~FileManager() { - delete &UniqueRealDirs; - delete &UniqueRealFiles; for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i) delete VirtualFileEntries[i]; for (unsigned i = 0, e = VirtualDirectoryEntries.size(); i != e; ++i) @@ -122,8 +67,8 @@ FileManager::~FileManager() { void FileManager::addStatCache(FileSystemStatCache *statCache, bool AtBeginning) { assert(statCache && "No stat cache provided?"); - if (AtBeginning || StatCache.get() == 0) { - statCache->setNextStatCache(StatCache.take()); + if (AtBeginning || !StatCache.get()) { + statCache->setNextStatCache(StatCache.release()); StatCache.reset(statCache); return; } @@ -155,7 +100,7 @@ void FileManager::removeStatCache(FileSystemStatCache *statCache) { } void FileManager::clearStatCaches() { - StatCache.reset(0); + StatCache.reset(); } /// \brief Retrieve the directory that the given file name resides in. @@ -164,10 +109,10 @@ static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, StringRef Filename, bool CacheFailure) { if (Filename.empty()) - return NULL; + return nullptr; if (llvm::sys::path::is_separator(Filename[Filename.size() - 1])) - return NULL; // If Filename is a directory. + return nullptr; // If Filename is a directory. StringRef DirName = llvm::sys::path::parent_path(Filename); // Use the current directory if file has no path component. @@ -231,8 +176,8 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName, // See if there was already an entry in the map. Note that the map // contains both virtual and real directories. if (NamedDirEnt.getValue()) - return NamedDirEnt.getValue() == NON_EXISTENT_DIR - ? 0 : NamedDirEnt.getValue(); + return NamedDirEnt.getValue() == NON_EXISTENT_DIR ? nullptr + : NamedDirEnt.getValue(); ++NumDirCacheMisses; @@ -245,19 +190,18 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName, // Check to see if the directory exists. FileData Data; - if (getStatValue(InterndDirName, Data, false, 0 /*directory lookup*/)) { + if (getStatValue(InterndDirName, Data, false, nullptr /*directory lookup*/)) { // There's no real directory at the given path. if (!CacheFailure) SeenDirEntries.erase(DirName); - return 0; + return nullptr; } // It exists. See if we have already opened a directory with the // same inode (this occurs on Unix-like systems when one dir is // symlinked to another, for example) or the same path (on // Windows). - DirectoryEntry &UDE = - UniqueRealDirs.getDirectory(Data.UniqueID); + DirectoryEntry &UDE = UniqueRealDirs[Data.UniqueID]; NamedDirEnt.setValue(&UDE); if (!UDE.getName()) { @@ -280,7 +224,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, // See if there is already an entry in the map. if (NamedFileEnt.getValue()) return NamedFileEnt.getValue() == NON_EXISTENT_FILE - ? 0 : NamedFileEnt.getValue(); + ? nullptr : NamedFileEnt.getValue(); ++NumFileCacheMisses; @@ -298,56 +242,59 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, // without a 'sys' subdir will get a cached failure result. const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, CacheFailure); - if (DirInfo == 0) { // Directory doesn't exist, file can't exist. + if (DirInfo == nullptr) { // Directory doesn't exist, file can't exist. if (!CacheFailure) SeenFileEntries.erase(Filename); - - return 0; + + return nullptr; } // FIXME: Use the directory info to prune this, before doing the stat syscall. // FIXME: This will reduce the # syscalls. // Nope, there isn't. Check to see if the file exists. - int FileDescriptor = -1; + std::unique_ptr<vfs::File> F; FileData Data; - if (getStatValue(InterndFileName, Data, true, - openFile ? &FileDescriptor : 0)) { + if (getStatValue(InterndFileName, Data, true, openFile ? &F : nullptr)) { // There's no real file at the given path. if (!CacheFailure) SeenFileEntries.erase(Filename); - - return 0; - } - if (FileDescriptor != -1 && !openFile) { - close(FileDescriptor); - FileDescriptor = -1; + return nullptr; } + assert((openFile || !F) && "undesired open file"); + // It exists. See if we have already opened a file with the same inode. // This occurs when one dir is symlinked to another, for example. - FileEntry &UFE = - UniqueRealFiles.getFile(Data.UniqueID, Data.IsNamedPipe, Data.InPCH); + FileEntry &UFE = UniqueRealFiles[Data.UniqueID]; NamedFileEnt.setValue(&UFE); - if (UFE.getName()) { // Already have an entry with this inode, return it. - // If the stat process opened the file, close it to avoid a FD leak. - if (FileDescriptor != -1) - close(FileDescriptor); + if (UFE.isValid()) { // Already have an entry with this inode, return it. + + // FIXME: this hack ensures that if we look up a file by a virtual path in + // the VFS that the getDir() will have the virtual path, even if we found + // the file by a 'real' path first. This is required in order to find a + // module's structure when its headers/module map are mapped in the VFS. + // We should remove this as soon as we can properly support a file having + // multiple names. + if (DirInfo != UFE.Dir && Data.IsVFSMapped) + UFE.Dir = DirInfo; return &UFE; } - // Otherwise, we don't have this directory yet, add it. - // FIXME: Change the name to be a char* that points back to the - // 'SeenFileEntries' key. - UFE.Name = InterndFileName; + // Otherwise, we don't have this file yet, add it. + UFE.Name = Data.Name; UFE.Size = Data.Size; UFE.ModTime = Data.ModTime; UFE.Dir = DirInfo; UFE.UID = NextFileUID++; - UFE.FD = FileDescriptor; + UFE.UniqueID = Data.UniqueID; + UFE.IsNamedPipe = Data.IsNamedPipe; + UFE.InPCH = Data.InPCH; + UFE.File = std::move(F); + UFE.IsValid = true; return &UFE; } @@ -370,7 +317,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, NamedFileEnt.setValue(NON_EXISTENT_FILE); addAncestorsAsVirtualDirs(Filename); - FileEntry *UFE = 0; + FileEntry *UFE = nullptr; // Now that all ancestors of Filename are in the cache, the // following call is guaranteed to find the DirectoryEntry from the @@ -383,24 +330,26 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, // Check to see if the file exists. If so, drop the virtual file FileData Data; const char *InterndFileName = NamedFileEnt.getKeyData(); - if (getStatValue(InterndFileName, Data, true, 0) == 0) { + if (getStatValue(InterndFileName, Data, true, nullptr) == 0) { Data.Size = Size; Data.ModTime = ModificationTime; - UFE = &UniqueRealFiles.getFile(Data.UniqueID, Data.IsNamedPipe, Data.InPCH); + UFE = &UniqueRealFiles[Data.UniqueID]; NamedFileEnt.setValue(UFE); // If we had already opened this file, close it now so we don't // leak the descriptor. We're not going to use the file // descriptor anyway, since this is a virtual file. - if (UFE->FD != -1) { - close(UFE->FD); - UFE->FD = -1; - } + if (UFE->File) + UFE->closeFile(); // If we already have an entry with this inode, return it. - if (UFE->getName()) + if (UFE->isValid()) return UFE; + + UFE->UniqueID = Data.UniqueID; + UFE->IsNamedPipe = Data.IsNamedPipe; + UFE->InPCH = Data.InPCH; } if (!UFE) { @@ -414,7 +363,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, UFE->ModTime = ModificationTime; UFE->Dir = DirInfo; UFE->UID = NextFileUID++; - UFE->FD = -1; + UFE->File.reset(); return UFE; } @@ -432,9 +381,9 @@ void FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const { llvm::MemoryBuffer *FileManager:: getBufferForFile(const FileEntry *Entry, std::string *ErrorStr, - bool isVolatile) { - OwningPtr<llvm::MemoryBuffer> Result; - llvm::error_code ec; + bool isVolatile, bool ShouldCloseOpenFile) { + std::unique_ptr<llvm::MemoryBuffer> Result; + std::error_code ec; uint64_t FileSize = Entry->getSize(); // If there's a high enough chance that the file have changed since we @@ -444,50 +393,54 @@ getBufferForFile(const FileEntry *Entry, std::string *ErrorStr, const char *Filename = Entry->getName(); // If the file is already open, use the open file descriptor. - if (Entry->FD != -1) { - ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, FileSize); + if (Entry->File) { + ec = Entry->File->getBuffer(Filename, Result, FileSize, + /*RequiresNullTerminator=*/true, isVolatile); if (ErrorStr) *ErrorStr = ec.message(); - - close(Entry->FD); - Entry->FD = -1; - return Result.take(); + // FIXME: we need a set of APIs that can make guarantees about whether a + // FileEntry is open or not. + if (ShouldCloseOpenFile) + Entry->closeFile(); + return Result.release(); } // Otherwise, open the file. if (FileSystemOpts.WorkingDir.empty()) { - ec = llvm::MemoryBuffer::getFile(Filename, Result, FileSize); + ec = FS->getBufferForFile(Filename, Result, FileSize, + /*RequiresNullTerminator=*/true, isVolatile); if (ec && ErrorStr) *ErrorStr = ec.message(); - return Result.take(); + return Result.release(); } SmallString<128> FilePath(Entry->getName()); FixupRelativePath(FilePath); - ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, FileSize); + ec = FS->getBufferForFile(FilePath.str(), Result, FileSize, + /*RequiresNullTerminator=*/true, isVolatile); if (ec && ErrorStr) *ErrorStr = ec.message(); - return Result.take(); + return Result.release(); } llvm::MemoryBuffer *FileManager:: getBufferForFile(StringRef Filename, std::string *ErrorStr) { - OwningPtr<llvm::MemoryBuffer> Result; - llvm::error_code ec; + std::unique_ptr<llvm::MemoryBuffer> Result; + std::error_code ec; if (FileSystemOpts.WorkingDir.empty()) { - ec = llvm::MemoryBuffer::getFile(Filename, Result); + ec = FS->getBufferForFile(Filename, Result); if (ec && ErrorStr) *ErrorStr = ec.message(); - return Result.take(); + return Result.release(); } SmallString<128> FilePath(Filename); FixupRelativePath(FilePath); - ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result); + ec = FS->getBufferForFile(FilePath.c_str(), Result); if (ec && ErrorStr) *ErrorStr = ec.message(); - return Result.take(); + return Result.release(); } /// getStatValue - Get the 'stat' information for the specified path, @@ -496,26 +449,29 @@ getBufferForFile(StringRef Filename, std::string *ErrorStr) { /// false if it's an existent real file. If FileDescriptor is NULL, /// do directory look-up instead of file look-up. bool FileManager::getStatValue(const char *Path, FileData &Data, bool isFile, - int *FileDescriptor) { + std::unique_ptr<vfs::File> *F) { // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be // absolute! if (FileSystemOpts.WorkingDir.empty()) - return FileSystemStatCache::get(Path, Data, isFile, FileDescriptor, - StatCache.get()); + return FileSystemStatCache::get(Path, Data, isFile, F,StatCache.get(), *FS); SmallString<128> FilePath(Path); FixupRelativePath(FilePath); - return FileSystemStatCache::get(FilePath.c_str(), Data, isFile, - FileDescriptor, StatCache.get()); + return FileSystemStatCache::get(FilePath.c_str(), Data, isFile, F, + StatCache.get(), *FS); } bool FileManager::getNoncachedStatValue(StringRef Path, - llvm::sys::fs::file_status &Result) { + vfs::Status &Result) { SmallString<128> FilePath(Path); FixupRelativePath(FilePath); - return llvm::sys::fs::status(FilePath.c_str(), Result); + llvm::ErrorOr<vfs::Status> S = FS->status(FilePath.c_str()); + if (!S) + return true; + Result = *S; + return false; } void FileManager::invalidateCache(const FileEntry *Entry) { @@ -526,7 +482,7 @@ void FileManager::invalidateCache(const FileEntry *Entry) { // FileEntry invalidation should not block future optimizations in the file // caches. Possible alternatives are cache truncation (invalidate last N) or // invalidation of the whole cache. - UniqueRealFiles.erase(Entry); + UniqueRealFiles.erase(Entry->getUniqueID()); } diff --git a/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp index 7a01bff..7515cfb 100644 --- a/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/FileSystemStatCache.h" -#include "llvm/Support/FileSystem.h" +#include "clang/Basic/VirtualFileSystem.h" #include "llvm/Support/Path.h" // FIXME: This is terrible, we need this for ::close. @@ -30,14 +30,16 @@ using namespace clang; void FileSystemStatCache::anchor() { } -static void copyStatusToFileData(const llvm::sys::fs::file_status &Status, +static void copyStatusToFileData(const vfs::Status &Status, FileData &Data) { + Data.Name = Status.getName(); Data.Size = Status.getSize(); Data.ModTime = Status.getLastModificationTime().toEpochTime(); Data.UniqueID = Status.getUniqueID(); - Data.IsDirectory = is_directory(Status); - Data.IsNamedPipe = Status.type() == llvm::sys::fs::file_type::fifo_file; + Data.IsDirectory = Status.isDirectory(); + Data.IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file; Data.InPCH = false; + Data.IsVFSMapped = Status.IsVFSMapped; } /// FileSystemStatCache::get - Get the 'stat' information for the specified @@ -50,22 +52,23 @@ static void copyStatusToFileData(const llvm::sys::fs::file_status &Status, /// implementation can optionally fill in FileDescriptor with a valid /// descriptor and the client guarantees that it will close it. bool FileSystemStatCache::get(const char *Path, FileData &Data, bool isFile, - int *FileDescriptor, FileSystemStatCache *Cache) { + std::unique_ptr<vfs::File> *F, + FileSystemStatCache *Cache, vfs::FileSystem &FS) { LookupResult R; bool isForDir = !isFile; // If we have a cache, use it to resolve the stat query. if (Cache) - R = Cache->getStat(Path, Data, isFile, FileDescriptor); - else if (isForDir || !FileDescriptor) { + R = Cache->getStat(Path, Data, isFile, F, FS); + else if (isForDir || !F) { // If this is a directory or a file descriptor is not needed and we have // no cache, just go to the file system. - llvm::sys::fs::file_status Status; - if (llvm::sys::fs::status(Path, Status)) { + llvm::ErrorOr<vfs::Status> Status = FS.status(Path); + if (!Status) { R = CacheMissing; } else { R = CacheExists; - copyStatusToFileData(Status, Data); + copyStatusToFileData(*Status, Data); } } else { // Otherwise, we have to go to the filesystem. We can always just use @@ -75,7 +78,8 @@ bool FileSystemStatCache::get(const char *Path, FileData &Data, bool isFile, // // Because of this, check to see if the file exists with 'open'. If the // open succeeds, use fstat to get the stat info. - llvm::error_code EC = llvm::sys::fs::openFileForRead(Path, *FileDescriptor); + std::unique_ptr<vfs::File> OwnedFile; + std::error_code EC = FS.openFileForRead(Path, OwnedFile); if (EC) { // If the open fails, our "stat" fails. @@ -84,16 +88,16 @@ bool FileSystemStatCache::get(const char *Path, FileData &Data, bool isFile, // Otherwise, the open succeeded. Do an fstat to get the information // about the file. We'll end up returning the open file descriptor to the // client to do what they please with it. - llvm::sys::fs::file_status Status; - if (!llvm::sys::fs::status(*FileDescriptor, Status)) { + llvm::ErrorOr<vfs::Status> Status = OwnedFile->status(); + if (Status) { R = CacheExists; - copyStatusToFileData(Status, Data); + copyStatusToFileData(*Status, Data); + *F = std::move(OwnedFile); } else { // fstat rarely fails. If it does, claim the initial open didn't // succeed. R = CacheMissing; - ::close(*FileDescriptor); - *FileDescriptor = -1; + *F = nullptr; } } } @@ -105,10 +109,8 @@ bool FileSystemStatCache::get(const char *Path, FileData &Data, bool isFile, // demands. if (Data.IsDirectory != isForDir) { // If not, close the file if opened. - if (FileDescriptor && *FileDescriptor != -1) { - ::close(*FileDescriptor); - *FileDescriptor = -1; - } + if (F) + *F = nullptr; return true; } @@ -118,8 +120,8 @@ bool FileSystemStatCache::get(const char *Path, FileData &Data, bool isFile, MemorizeStatCalls::LookupResult MemorizeStatCalls::getStat(const char *Path, FileData &Data, bool isFile, - int *FileDescriptor) { - LookupResult Result = statChained(Path, Data, isFile, FileDescriptor); + std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) { + LookupResult Result = statChained(Path, Data, isFile, F, FS); // Do not cache failed stats, it is easy to construct common inconsistent // situations if we do, and they are not important for PCH performance (which diff --git a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp index 500e732..2198459 100644 --- a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp @@ -12,11 +12,13 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/CharInfo.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" -#include "clang/Basic/CharInfo.h" +#include "clang/Basic/OperatorKinds.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <cstdio> @@ -42,8 +44,8 @@ IdentifierInfo::IdentifierInfo() { RevertedTokenID = false; OutOfDate = false; IsModulesImport = false; - FETokenInfo = 0; - Entry = 0; + FETokenInfo = nullptr; + Entry = nullptr; } //===----------------------------------------------------------------------===// @@ -60,7 +62,7 @@ namespace { class EmptyLookupIterator : public IdentifierIterator { public: - virtual StringRef Next() { return StringRef(); } + StringRef Next() override { return StringRef(); } }; } @@ -105,6 +107,7 @@ namespace { KEYARC = 0x800, KEYNOMS = 0x01000, WCHARSUPPORT = 0x02000, + HALFSUPPORT = 0x04000, KEYALL = (0xffff & ~KEYNOMS) // Because KEYNOMS is used to exclude. }; } @@ -129,6 +132,7 @@ static void AddKeyword(StringRef Keyword, else if (LangOpts.MicrosoftExt && (Flags & KEYMS)) AddResult = 1; else if (LangOpts.Borland && (Flags & KEYBORLAND)) AddResult = 1; else if (LangOpts.Bool && (Flags & BOOLSUPPORT)) AddResult = 2; + else if (LangOpts.Half && (Flags & HALFSUPPORT)) AddResult = 2; else if (LangOpts.WChar && (Flags & WCHARSUPPORT)) AddResult = 2; else if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) AddResult = 2; else if (LangOpts.OpenCL && (Flags & KEYOPENCL)) AddResult = 2; @@ -139,8 +143,8 @@ static void AddKeyword(StringRef Keyword, else if (LangOpts.ObjC2 && (Flags & KEYARC)) AddResult = 2; else if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) AddResult = 3; - // Don't add this keyword under MicrosoftMode. - if (LangOpts.MicrosoftMode && (Flags & KEYNOMS)) + // Don't add this keyword under MSVCCompat. + if (LangOpts.MSVCCompat && (Flags & KEYNOMS)) return; // Don't add this keyword if disabled in this language. if (AddResult == 0) return; @@ -398,6 +402,10 @@ std::string Selector::getAsString() const { return getMultiKeywordSelector()->getName(); } +void Selector::print(llvm::raw_ostream &OS) const { + OS << getAsString(); +} + /// Interpreting the given string using the normal CamelCase /// conventions, determine whether the given string starts with the /// given "word", which is assumed to end in a lowercase letter. @@ -521,7 +529,7 @@ Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) { llvm::FoldingSetNodeID ID; MultiKeywordSelector::Profile(ID, IIV, nKeys); - void *InsertPos = 0; + void *InsertPos = nullptr; if (MultiKeywordSelector *SI = SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos)) return Selector(SI); @@ -549,7 +557,7 @@ const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) { switch (Operator) { case OO_None: case NUM_OVERLOADED_OPERATORS: - return 0; + return nullptr; #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ case OO_##Name: return Spelling; diff --git a/contrib/llvm/tools/clang/lib/Basic/Module.cpp b/contrib/llvm/tools/clang/lib/Basic/Module.cpp index d08cef1..f689c73 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Module.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Module.cpp @@ -24,20 +24,23 @@ using namespace clang; -Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, - bool IsFramework, bool IsExplicit) - : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), - Umbrella(), ASTFile(0), IsAvailable(true), IsFromModuleFile(false), - IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false), - InferSubmodules(false), InferExplicitSubmodules(false), - InferExportWildcard(false), ConfigMacrosExhaustive(false), - NameVisibility(Hidden) -{ +Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, + const FileEntry *File, bool IsFramework, bool IsExplicit) + : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), ModuleMap(File), + Umbrella(), ASTFile(nullptr), IsMissingRequirement(false), + IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework), + IsExplicit(IsExplicit), IsSystem(false), IsExternC(false), + IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false), + InferExportWildcard(false), ConfigMacrosExhaustive(false), + NameVisibility(Hidden) { if (Parent) { if (!Parent->isAvailable()) IsAvailable = false; if (Parent->IsSystem) IsSystem = true; + if (Parent->IsExternC) + IsExternC = true; + IsMissingRequirement = Parent->IsMissingRequirement; Parent->SubModuleIndex[Name] = Parent->SubModules.size(); Parent->SubModules.push_back(this); @@ -69,11 +72,15 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, - Requirement &Req) const { + Requirement &Req, HeaderDirective &MissingHeader) const { if (IsAvailable) return true; for (const Module *Current = this; Current; Current = Current->Parent) { + if (!Current->MissingHeaders.empty()) { + MissingHeader = Current->MissingHeaders.front(); + return false; + } for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) { if (hasFeature(Current->Requirements[I].first, LangOpts, Target) != Current->Requirements[I].second) { @@ -86,7 +93,7 @@ Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, llvm_unreachable("could not find a reason why module is unavailable"); } -bool Module::isSubModuleOf(Module *Other) const { +bool Module::isSubModuleOf(const Module *Other) const { const Module *This = this; do { if (This == Other) @@ -155,6 +162,10 @@ void Module::addRequirement(StringRef Feature, bool RequiredState, if (hasFeature(Feature, LangOpts, Target) == RequiredState) return; + markUnavailable(/*MissingRequirement*/true); +} + +void Module::markUnavailable(bool MissingRequirement) { if (!IsAvailable) return; @@ -168,6 +179,7 @@ void Module::addRequirement(StringRef Feature, bool RequiredState, continue; Current->IsAvailable = false; + Current->IsMissingRequirement |= MissingRequirement; for (submodule_iterator Sub = Current->submodule_begin(), SubEnd = Current->submodule_end(); Sub != SubEnd; ++Sub) { @@ -180,8 +192,8 @@ void Module::addRequirement(StringRef Feature, bool RequiredState, Module *Module::findSubmodule(StringRef Name) const { llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name); if (Pos == SubModuleIndex.end()) - return 0; - + return nullptr; + return SubModules[Pos->getValue()]; } @@ -349,7 +361,8 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end(); MI != MIEnd; ++MI) - (*MI)->print(OS, Indent + 2); + if (!(*MI)->IsInferred) + (*MI)->print(OS, Indent + 2); for (unsigned I = 0, N = Exports.size(); I != N; ++I) { OS.indent(Indent + 2); diff --git a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp index 1350934..06f010f 100644 --- a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp @@ -22,46 +22,49 @@ using namespace clang; OpenMPDirectiveKind clang::getOpenMPDirectiveKind(StringRef Str) { return llvm::StringSwitch<OpenMPDirectiveKind>(Str) -#define OPENMP_DIRECTIVE(Name) \ - .Case(#Name, OMPD_##Name) +#define OPENMP_DIRECTIVE(Name) .Case(#Name, OMPD_##Name) +#define OPENMP_DIRECTIVE_EXT(Name, Str) .Case(Str, OMPD_##Name) #include "clang/Basic/OpenMPKinds.def" - .Default(OMPD_unknown); + .Default(OMPD_unknown); } const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) { - assert(Kind < NUM_OPENMP_DIRECTIVES); + assert(Kind <= OMPD_unknown); switch (Kind) { case OMPD_unknown: return "unknown"; -#define OPENMP_DIRECTIVE(Name) \ - case OMPD_##Name : return #Name; +#define OPENMP_DIRECTIVE(Name) \ + case OMPD_##Name: \ + return #Name; +#define OPENMP_DIRECTIVE_EXT(Name, Str) \ + case OMPD_##Name: \ + return Str; #include "clang/Basic/OpenMPKinds.def" - case NUM_OPENMP_DIRECTIVES: break; } llvm_unreachable("Invalid OpenMP directive kind"); } OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) { + if (Str == "flush") + return OMPC_unknown; return llvm::StringSwitch<OpenMPClauseKind>(Str) -#define OPENMP_CLAUSE(Name, Class) \ - .Case(#Name, OMPC_##Name) +#define OPENMP_CLAUSE(Name, Class) .Case(#Name, OMPC_##Name) #include "clang/Basic/OpenMPKinds.def" - .Default(OMPC_unknown); + .Default(OMPC_unknown); } const char *clang::getOpenMPClauseName(OpenMPClauseKind Kind) { - assert(Kind < NUM_OPENMP_CLAUSES); + assert(Kind <= OMPC_unknown); switch (Kind) { case OMPC_unknown: return "unknown"; -#define OPENMP_CLAUSE(Name, Class) \ - case OMPC_##Name : return #Name; +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_##Name: \ + return #Name; #include "clang/Basic/OpenMPKinds.def" case OMPC_threadprivate: return "threadprivate or thread local"; - case NUM_OPENMP_CLAUSES: - break; } llvm_unreachable("Invalid OpenMP clause kind"); } @@ -71,16 +74,40 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, switch (Kind) { case OMPC_default: return llvm::StringSwitch<OpenMPDefaultClauseKind>(Str) -#define OPENMP_DEFAULT_KIND(Name) \ - .Case(#Name, OMPC_DEFAULT_##Name) +#define OPENMP_DEFAULT_KIND(Name) .Case(#Name, OMPC_DEFAULT_##Name) +#include "clang/Basic/OpenMPKinds.def" + .Default(OMPC_DEFAULT_unknown); + case OMPC_proc_bind: + return llvm::StringSwitch<OpenMPProcBindClauseKind>(Str) +#define OPENMP_PROC_BIND_KIND(Name) .Case(#Name, OMPC_PROC_BIND_##Name) +#include "clang/Basic/OpenMPKinds.def" + .Default(OMPC_PROC_BIND_unknown); + case OMPC_schedule: + return llvm::StringSwitch<OpenMPScheduleClauseKind>(Str) +#define OPENMP_SCHEDULE_KIND(Name) .Case(#Name, OMPC_SCHEDULE_##Name) #include "clang/Basic/OpenMPKinds.def" - .Default(OMPC_DEFAULT_unknown); + .Default(OMPC_SCHEDULE_unknown); case OMPC_unknown: case OMPC_threadprivate: + case OMPC_if: + case OMPC_final: + case OMPC_num_threads: + case OMPC_safelen: + case OMPC_collapse: case OMPC_private: case OMPC_firstprivate: + case OMPC_lastprivate: case OMPC_shared: - case NUM_OPENMP_CLAUSES: + case OMPC_reduction: + case OMPC_linear: + case OMPC_aligned: + case OMPC_copyin: + case OMPC_copyprivate: + case OMPC_ordered: + case OMPC_nowait: + case OMPC_untied: + case OMPC_mergeable: + case OMPC_flush: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); @@ -93,17 +120,53 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, switch (Type) { case OMPC_DEFAULT_unknown: return "unknown"; -#define OPENMP_DEFAULT_KIND(Name) \ - case OMPC_DEFAULT_##Name : return #Name; +#define OPENMP_DEFAULT_KIND(Name) \ + case OMPC_DEFAULT_##Name: \ + return #Name; #include "clang/Basic/OpenMPKinds.def" } llvm_unreachable("Invalid OpenMP 'default' clause type"); + case OMPC_proc_bind: + switch (Type) { + case OMPC_PROC_BIND_unknown: + return "unknown"; +#define OPENMP_PROC_BIND_KIND(Name) \ + case OMPC_PROC_BIND_##Name: \ + return #Name; +#include "clang/Basic/OpenMPKinds.def" + } + llvm_unreachable("Invalid OpenMP 'proc_bind' clause type"); + case OMPC_schedule: + switch (Type) { + case OMPC_SCHEDULE_unknown: + return "unknown"; +#define OPENMP_SCHEDULE_KIND(Name) \ + case OMPC_SCHEDULE_##Name: \ + return #Name; +#include "clang/Basic/OpenMPKinds.def" + } + llvm_unreachable("Invalid OpenMP 'schedule' clause type"); case OMPC_unknown: case OMPC_threadprivate: + case OMPC_if: + case OMPC_final: + case OMPC_num_threads: + case OMPC_safelen: + case OMPC_collapse: case OMPC_private: case OMPC_firstprivate: + case OMPC_lastprivate: case OMPC_shared: - case NUM_OPENMP_CLAUSES: + case OMPC_reduction: + case OMPC_linear: + case OMPC_aligned: + case OMPC_copyin: + case OMPC_copyprivate: + case OMPC_ordered: + case OMPC_nowait: + case OMPC_untied: + case OMPC_mergeable: + case OMPC_flush: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); @@ -111,23 +174,133 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind) { - assert(DKind < NUM_OPENMP_DIRECTIVES); - assert(CKind < NUM_OPENMP_CLAUSES); + assert(DKind <= OMPD_unknown); + assert(CKind <= OMPC_unknown); switch (DKind) { case OMPD_parallel: switch (CKind) { -#define OPENMP_PARALLEL_CLAUSE(Name) \ - case OMPC_##Name: return true; +#define OPENMP_PARALLEL_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_simd: + switch (CKind) { +#define OPENMP_SIMD_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_for: + switch (CKind) { +#define OPENMP_FOR_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_sections: + switch (CKind) { +#define OPENMP_SECTIONS_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_single: + switch (CKind) { +#define OPENMP_SINGLE_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; #include "clang/Basic/OpenMPKinds.def" default: break; } break; + case OMPD_parallel_for: + switch (CKind) { +#define OPENMP_PARALLEL_FOR_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_parallel_sections: + switch (CKind) { +#define OPENMP_PARALLEL_SECTIONS_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_task: + switch (CKind) { +#define OPENMP_TASK_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_flush: + return CKind == OMPC_flush; + break; case OMPD_unknown: case OMPD_threadprivate: - case OMPD_task: - case NUM_OPENMP_DIRECTIVES: + case OMPD_section: + case OMPD_master: + case OMPD_critical: + case OMPD_taskyield: + case OMPD_barrier: + case OMPD_taskwait: break; } return false; } + +bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) { + return DKind == OMPD_simd || DKind == OMPD_for || + DKind == OMPD_parallel_for; // TODO add next directives. +} + +bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) { + return DKind == OMPD_for || DKind == OMPD_sections || DKind == OMPD_section || + DKind == OMPD_single || DKind == OMPD_parallel_for || + DKind == OMPD_parallel_sections; // TODO add next directives. +} + +bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) { + return DKind == OMPD_parallel || DKind == OMPD_parallel_for || + DKind == OMPD_parallel_sections; // TODO add next directives. +} + +bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) { + return DKind == OMPD_simd; // TODO || DKind == OMPD_for_simd || ... +} + +bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) { + return Kind == OMPC_private || Kind == OMPC_firstprivate || + Kind == OMPC_lastprivate || Kind == OMPC_linear || + Kind == OMPC_reduction; // TODO add next clauses like 'reduction'. +} + +bool clang::isOpenMPThreadPrivate(OpenMPClauseKind Kind) { + return Kind == OMPC_threadprivate || + Kind == OMPC_copyin; // TODO add next clauses like 'copyprivate'. +} + diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp index 1822091..0c06a48c 100644 --- a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp @@ -61,14 +61,15 @@ void SourceLocation::print(raw_ostream &OS, const SourceManager &SM)const{ OS << '>'; } -std::string SourceLocation::printToString(const SourceManager &SM) const { +LLVM_DUMP_METHOD std::string +SourceLocation::printToString(const SourceManager &SM) const { std::string S; llvm::raw_string_ostream OS(S); print(OS, SM); return OS.str(); } -void SourceLocation::dump(const SourceManager &SM) const { +LLVM_DUMP_METHOD void SourceLocation::dump(const SourceManager &SM) const { print(llvm::errs(), SM); } @@ -122,7 +123,7 @@ bool FullSourceLoc::isBeforeInTranslationUnitThan(SourceLocation Loc) const { return SrcMgr->isBeforeInTranslationUnit(*this, Loc); } -void FullSourceLoc::dump() const { +LLVM_DUMP_METHOD void FullSourceLoc::dump() const { SourceLocation::dump(*SrcMgr); } diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp index 9d79551..61dfe35 100644 --- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp @@ -26,7 +26,6 @@ #include <algorithm> #include <cstring> #include <string> -#include <sys/stat.h> using namespace clang; using namespace SrcMgr; @@ -55,8 +54,8 @@ llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const { // Should be unreachable, but keep for sanity. if (!Buffer.getPointer()) return llvm::MemoryBuffer::MemoryBuffer_Malloc; - - const llvm::MemoryBuffer *buf = Buffer.getPointer(); + + llvm::MemoryBuffer *buf = Buffer.getPointer(); return buf->getBufferKind(); } @@ -69,8 +68,7 @@ unsigned ContentCache::getSize() const { : (unsigned) ContentsEntry->getSize(); } -void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, - bool DoNotFree) { +void ContentCache::replaceBuffer(llvm::MemoryBuffer *B, bool DoNotFree) { if (B && B == Buffer.getPointer()) { assert(0 && "Replacing with the same buffer"); Buffer.setInt(DoNotFree? DoNotFreeFlag : 0); @@ -83,13 +81,13 @@ void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, Buffer.setInt(DoNotFree? DoNotFreeFlag : 0); } -const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, - const SourceManager &SM, - SourceLocation Loc, - bool *Invalid) const { +llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, + const SourceManager &SM, + SourceLocation Loc, + bool *Invalid) const { // Lazily create the Buffer for ContentCaches that wrap files. If we already // computed it, just return what we have. - if (Buffer.getPointer() || ContentsEntry == 0) { + if (Buffer.getPointer() || !ContentsEntry) { if (Invalid) *Invalid = isBufferInvalid(); @@ -163,7 +161,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, .StartsWith("\x0E\xFE\xFF", "SDSU") .StartsWith("\xFB\xEE\x28", "BOCU-1") .StartsWith("\x84\x31\x95\x33", "GB-18030") - .Default(0); + .Default(nullptr); if (InvalidBOM) { Diag.Report(Loc, diag::err_unsupported_bom) @@ -272,7 +270,7 @@ const LineEntry *LineTableInfo::FindNearestLineEntry(FileID FID, // Do a binary search to find the maximal element that is still before Offset. std::vector<LineEntry>::const_iterator I = std::upper_bound(Entries.begin(), Entries.end(), Offset); - if (I == Entries.begin()) return 0; + if (I == Entries.begin()) return nullptr; return &*--I; } @@ -286,7 +284,7 @@ void LineTableInfo::AddEntry(FileID FID, /// getLineTableFilenameID - Return the uniqued ID for the specified filename. /// unsigned SourceManager::getLineTableFilenameID(StringRef Name) { - if (LineTable == 0) + if (!LineTable) LineTable = new LineTableInfo(); return LineTable->getLineTableFilenameID(Name); } @@ -309,7 +307,7 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, // Remember that this file has #line directives now if it doesn't already. const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives(); - if (LineTable == 0) + if (!LineTable) LineTable = new LineTableInfo(); LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID); } @@ -339,7 +337,7 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, // Remember that this file has #line directives now if it doesn't already. const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives(); - if (LineTable == 0) + if (!LineTable) LineTable = new LineTableInfo(); SrcMgr::CharacteristicKind FileKind; @@ -361,7 +359,7 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, } LineTableInfo &SourceManager::getLineTable() { - if (LineTable == 0) + if (!LineTable) LineTable = new LineTableInfo(); return *LineTable; } @@ -374,9 +372,9 @@ SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, bool UserFilesAreVolatile) : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true), UserFilesAreVolatile(UserFilesAreVolatile), - ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), - NumBinaryProbes(0), FakeBufferForRecovery(0), - FakeContentCacheForRecovery(0) { + ExternalSLocEntries(nullptr), LineTable(nullptr), NumLinearScans(0), + NumBinaryProbes(0), FakeBufferForRecovery(nullptr), + FakeContentCacheForRecovery(nullptr) { clearIDTables(); Diag.setSourceManager(this); } @@ -404,10 +402,7 @@ SourceManager::~SourceManager() { delete FakeBufferForRecovery; delete FakeContentCacheForRecovery; - for (llvm::DenseMap<FileID, MacroArgsMap *>::iterator - I = MacroArgsCacheMap.begin(),E = MacroArgsCacheMap.end(); I!=E; ++I) { - delete I->second; - } + llvm::DeleteContainerSeconds(MacroArgsCacheMap); } void SourceManager::clearIDTables() { @@ -416,7 +411,7 @@ void SourceManager::clearIDTables() { LoadedSLocEntryTable.clear(); SLocEntryLoaded.clear(); LastLineNoFileIDQuery = FileID(); - LastLineNoContentCache = 0; + LastLineNoContentCache = nullptr; LastFileIDLookup = FileID(); if (LineTable) @@ -439,12 +434,8 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt, ContentCache *&Entry = FileInfos[FileEnt]; if (Entry) return Entry; - // Nope, create a new Cache entry. Make sure it is at least 8-byte aligned - // so that FileInfo can use the low 3 bits of the pointer for its own - // nefarious purposes. - unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment; - EntryAlign = std::max(8U, EntryAlign); - Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign); + // Nope, create a new Cache entry. + Entry = ContentCacheAlloc.Allocate<ContentCache>(); if (OverriddenFilesInfo) { // If the file contents are overridden with contents from another file, @@ -469,14 +460,10 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt, /// createMemBufferContentCache - Create a new ContentCache for the specified /// memory buffer. This does no caching. -const ContentCache* -SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) { - // Add a new ContentCache to the MemBufferInfos list and return it. Make sure - // it is at least 8-byte aligned so that FileInfo can use the low 3 bits of - // the pointer for its own nefarious purposes. - unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment; - EntryAlign = std::max(8U, EntryAlign); - ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign); +const ContentCache * +SourceManager::createMemBufferContentCache(llvm::MemoryBuffer *Buffer) { + // Add a new ContentCache to the MemBufferInfos list and return it. + ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>(); new (Entry) ContentCache(); MemBufferInfos.push_back(Entry); Entry->setBuffer(Buffer); @@ -516,7 +503,7 @@ SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries, /// \brief As part of recovering from missing or changed content, produce a /// fake, non-empty buffer. -const llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { +llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { if (!FakeBufferForRecovery) FakeBufferForRecovery = llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>"); @@ -655,16 +642,15 @@ SourceManager::createExpansionLocImpl(const ExpansionInfo &Info, return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1)); } -const llvm::MemoryBuffer * -SourceManager::getMemoryBufferForFile(const FileEntry *File, - bool *Invalid) { +llvm::MemoryBuffer *SourceManager::getMemoryBufferForFile(const FileEntry *File, + bool *Invalid) { const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); assert(IR && "getOrCreateContentCache() cannot return NULL"); return IR->getBuffer(Diag, *this, SourceLocation(), Invalid); } void SourceManager::overrideFileContents(const FileEntry *SourceFile, - const llvm::MemoryBuffer *Buffer, + llvm::MemoryBuffer *Buffer, bool DoNotFree) { const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile); assert(IR && "getOrCreateContentCache() cannot return NULL"); @@ -691,7 +677,7 @@ void SourceManager::disableFileContentsOverride(const FileEntry *File) { return; const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); - const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(0); + const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(nullptr); const_cast<SrcMgr::ContentCache *>(IR)->ContentsEntry = IR->OrigEntry; assert(OverriddenFilesInfo); @@ -707,10 +693,9 @@ StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const { *Invalid = true; return "<<<<<INVALID SOURCE LOCATION>>>>>"; } - - const llvm::MemoryBuffer *Buf - = SLoc.getFile().getContentCache()->getBuffer(Diag, *this, SourceLocation(), - &MyInvalid); + + llvm::MemoryBuffer *Buf = SLoc.getFile().getContentCache()->getBuffer( + Diag, *this, SourceLocation(), &MyInvalid); if (Invalid) *Invalid = MyInvalid; @@ -1128,9 +1113,8 @@ const char *SourceManager::getCharacterData(SourceLocation SL, return "<<<<INVALID BUFFER>>>>"; } - const llvm::MemoryBuffer *Buffer - = Entry.getFile().getContentCache() - ->getBuffer(Diag, *this, SourceLocation(), &CharDataInvalid); + llvm::MemoryBuffer *Buffer = Entry.getFile().getContentCache()->getBuffer( + Diag, *this, SourceLocation(), &CharDataInvalid); if (Invalid) *Invalid = CharDataInvalid; return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second); @@ -1142,7 +1126,7 @@ const char *SourceManager::getCharacterData(SourceLocation SL, unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid) const { bool MyInvalid = false; - const llvm::MemoryBuffer *MemBuf = getBuffer(FID, &MyInvalid); + llvm::MemoryBuffer *MemBuf = getBuffer(FID, &MyInvalid); if (Invalid) *Invalid = MyInvalid; @@ -1159,7 +1143,7 @@ unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos, // See if we just calculated the line number for this FilePos and can use // that to lookup the start of the line instead of searching for it. if (LastLineNoFileIDQuery == FID && - LastLineNoContentCache->SourceLineCache != 0 && + LastLineNoContentCache->SourceLineCache != nullptr && LastLineNoResult < LastLineNoContentCache->NumLines) { unsigned *SourceLineCache = LastLineNoContentCache->SourceLineCache; unsigned LineStart = SourceLineCache[LastLineNoResult - 1]; @@ -1216,8 +1200,7 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, llvm::BumpPtrAllocator &Alloc, const SourceManager &SM, bool &Invalid) { // Note that calling 'getBuffer()' may lazily page in the file. - const MemoryBuffer *Buffer = FI->getBuffer(Diag, SM, SourceLocation(), - &Invalid); + MemoryBuffer *Buffer = FI->getBuffer(Diag, SM, SourceLocation(), &Invalid); if (Invalid) return; @@ -1323,7 +1306,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos, // If this is the first use of line information for this buffer, compute the /// SourceLineCache for it on demand. - if (Content->SourceLineCache == 0) { + if (!Content->SourceLineCache) { bool MyInvalid = false; ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid); if (Invalid) @@ -1381,31 +1364,6 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos, } } - // If the spread is large, do a "radix" test as our initial guess, based on - // the assumption that lines average to approximately the same length. - // NOTE: This is currently disabled, as it does not appear to be profitable in - // initial measurements. - if (0 && SourceLineCacheEnd-SourceLineCache > 20) { - unsigned FileLen = Content->SourceLineCache[Content->NumLines-1]; - - // Take a stab at guessing where it is. - unsigned ApproxPos = Content->NumLines*QueriedFilePos / FileLen; - - // Check for -10 and +10 lines. - unsigned LowerBound = std::max(int(ApproxPos-10), 0); - unsigned UpperBound = std::min(ApproxPos+10, FileLen); - - // If the computed lower bound is less than the query location, move it in. - if (SourceLineCache < SourceLineCacheStart+LowerBound && - SourceLineCacheStart[LowerBound] < QueriedFilePos) - SourceLineCache = SourceLineCacheStart+LowerBound; - - // If the computed upper bound is greater than the query location, move it. - if (SourceLineCacheEnd > SourceLineCacheStart+UpperBound && - SourceLineCacheStart[UpperBound] >= QueriedFilePos) - SourceLineCacheEnd = SourceLineCacheStart+UpperBound; - } - unsigned *Pos = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos); unsigned LineNo = Pos-SourceLineCacheStart; @@ -1583,7 +1541,7 @@ bool SourceManager::isInMainFile(SourceLocation Loc) const { return FI.getIncludeLoc().isInvalid(); } -/// \brief The size of the SLocEnty that \arg FID represents. +/// \brief The size of the SLocEntry that \p FID represents. unsigned SourceManager::getFileIDSize(FileID FID) const { bool Invalid = false; const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); @@ -1732,7 +1690,8 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const { if (SLoc.isFile()) { const ContentCache *FileContentCache = SLoc.getFile().getContentCache(); - const FileEntry *Entry =FileContentCache? FileContentCache->OrigEntry : 0; + const FileEntry *Entry = FileContentCache ? FileContentCache->OrigEntry + : nullptr; if (Entry && *SourceFileName == llvm::sys::path::filename(Entry->getName())) { if (Optional<llvm::sys::fs::UniqueID> EntryUID = @@ -1784,7 +1743,7 @@ SourceLocation SourceManager::translateLineCol(FileID FID, // If this is the first use of line information for this buffer, compute the // SourceLineCache for it on demand. - if (Content->SourceLineCache == 0) { + if (!Content->SourceLineCache) { bool MyInvalid = false; ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid); if (MyInvalid) @@ -1798,7 +1757,7 @@ SourceLocation SourceManager::translateLineCol(FileID FID, return FileLoc.getLocWithOffset(Size); } - const llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, *this); + llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, *this); unsigned FilePos = Content->SourceLineCache[Line - 1]; const char *Buf = Buffer->getBufferStart() + FilePos; unsigned BufLength = Buffer->getBufferSize() - FilePos; @@ -1893,7 +1852,7 @@ void SourceManager::associateFileChunkWithMacroArgExp( FileID SpellFID; // Current FileID in the spelling range. unsigned SpellRelativeOffs; - llvm::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc); + std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc); while (1) { const SLocEntry &Entry = getSLocEntry(SpellFID); unsigned SpellFIDBeginOffs = Entry.getOffset(); @@ -1972,7 +1931,7 @@ SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const { FileID FID; unsigned Offset; - llvm::tie(FID, Offset) = getDecomposedLoc(Loc); + std::tie(FID, Offset) = getDecomposedLoc(Loc); if (FID.isInvalid()) return Loc; @@ -2160,7 +2119,7 @@ void SourceManager::PrintStats() const { unsigned NumLineNumsComputed = 0; unsigned NumFileBytesMapped = 0; for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){ - NumLineNumsComputed += I->second->SourceLineCache != 0; + NumLineNumsComputed += I->second->SourceLineCache != nullptr; NumFileBytesMapped += I->second->getSizeBytesMapped(); } unsigned NumMacroArgsComputed = MacroArgsCacheMap.size(); diff --git a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp index e993055..aecf13b 100644 --- a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp @@ -52,7 +52,6 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { SizeType = UnsignedLong; PtrDiffType = SignedLong; IntMaxType = SignedLongLong; - UIntMaxType = UnsignedLongLong; IntPtrType = SignedLong; WCharType = SignedInt; WIntType = SignedInt; @@ -69,8 +68,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { FloatFormat = &llvm::APFloat::IEEEsingle; DoubleFormat = &llvm::APFloat::IEEEdouble; LongDoubleFormat = &llvm::APFloat::IEEEdouble; - DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-n32"; + DescriptionString = nullptr; UserLabelPrefix = "_"; MCountName = "mcount"; RegParmMax = 0; @@ -83,8 +81,10 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { // Default to not using fp2ret for __Complex long double ComplexLongDoubleUsesFP2Ret = false; - // Default to using the Itanium ABI. - TheCXXABI.set(TargetCXXABI::GenericItanium); + // Set the C++ ABI based on the triple. + TheCXXABI.set(Triple.isKnownWindowsMSVCEnvironment() + ? TargetCXXABI::Microsoft + : TargetCXXABI::GenericItanium); // Default to an empty address space map. AddrSpaceMap = &DefaultAddrSpaceMap; @@ -103,7 +103,7 @@ TargetInfo::~TargetInfo() {} const char *TargetInfo::getTypeName(IntType T) { switch (T) { default: llvm_unreachable("not an integer!"); - case SignedChar: return "char"; + case SignedChar: return "signed char"; case UnsignedChar: return "unsigned char"; case SignedShort: return "short"; case UnsignedShort: return "unsigned short"; @@ -118,7 +118,7 @@ const char *TargetInfo::getTypeName(IntType T) { /// getTypeConstantSuffix - Return the constant suffix for the specified /// integer type enum. For example, SignedLong -> "L". -const char *TargetInfo::getTypeConstantSuffix(IntType T) { +const char *TargetInfo::getTypeConstantSuffix(IntType T) const { switch (T) { default: llvm_unreachable("not an integer!"); case SignedChar: @@ -127,13 +127,36 @@ const char *TargetInfo::getTypeConstantSuffix(IntType T) { case SignedLong: return "L"; case SignedLongLong: return "LL"; case UnsignedChar: + if (getCharWidth() < getIntWidth()) + return ""; case UnsignedShort: + if (getShortWidth() < getIntWidth()) + return ""; case UnsignedInt: return "U"; case UnsignedLong: return "UL"; case UnsignedLongLong: return "ULL"; } } +/// getTypeFormatModifier - Return the printf format modifier for the +/// specified integer type enum. For example, SignedLong -> "l". + +const char *TargetInfo::getTypeFormatModifier(IntType T) { + switch (T) { + default: llvm_unreachable("not an integer!"); + case SignedChar: + case UnsignedChar: return "hh"; + case SignedShort: + case UnsignedShort: return "h"; + case SignedInt: + case UnsignedInt: return ""; + case SignedLong: + case UnsignedLong: return "l"; + case SignedLongLong: + case UnsignedLongLong: return "ll"; + } +} + /// getTypeWidth - Return the width (in bits) of the specified integer type /// enum. For example, SignedInt -> getIntWidth(). unsigned TargetInfo::getTypeWidth(IntType T) const { @@ -167,6 +190,21 @@ TargetInfo::IntType TargetInfo::getIntTypeByWidth( return NoInt; } +TargetInfo::IntType TargetInfo::getLeastIntTypeByWidth(unsigned BitWidth, + bool IsSigned) const { + if (getCharWidth() >= BitWidth) + return IsSigned ? SignedChar : UnsignedChar; + if (getShortWidth() >= BitWidth) + return IsSigned ? SignedShort : UnsignedShort; + if (getIntWidth() >= BitWidth) + return IsSigned ? SignedInt : UnsignedInt; + if (getLongWidth() >= BitWidth) + return IsSigned ? SignedLong : UnsignedLong; + if (getLongLongWidth() >= BitWidth) + return IsSigned ? SignedLongLong : UnsignedLongLong; + return NoInt; +} + TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const { if (getFloatWidth() == BitWidth) return Float; @@ -226,10 +264,10 @@ bool TargetInfo::isTypeSigned(IntType T) { }; } -/// setForcedLangOptions - Set forced language options. +/// adjust - Set forced language options. /// Apply changes to the target information with respect to certain /// language options which change the target configuration. -void TargetInfo::setForcedLangOptions(LangOptions &Opts) { +void TargetInfo::adjust(const LangOptions &Opts) { if (Opts.NoBitFieldTypeAlign) UseBitFieldTypeAlignment = false; if (Opts.ShortWChar) @@ -245,7 +283,14 @@ void TargetInfo::setForcedLangOptions(LangOptions &Opts) { LongLongWidth = LongLongAlign = 128; HalfWidth = HalfAlign = 16; FloatWidth = FloatAlign = 32; - DoubleWidth = DoubleAlign = 64; + + // Embedded 32-bit targets (OpenCL EP) might have double C type + // defined as float. Let's not override this as it might lead + // to generating illegal code that uses 64bit doubles. + if (DoubleWidth != FloatWidth) { + DoubleWidth = DoubleAlign = 64; + DoubleFormat = &llvm::APFloat::IEEEdouble; + } LongDoubleWidth = LongDoubleAlign = 128; assert(PointerWidth == 32 || PointerWidth == 64); @@ -255,12 +300,10 @@ void TargetInfo::setForcedLangOptions(LangOptions &Opts) { IntPtrType = Is32BitArch ? SignedInt : SignedLong; IntMaxType = SignedLongLong; - UIntMaxType = UnsignedLongLong; Int64Type = SignedLong; HalfFormat = &llvm::APFloat::IEEEhalf; FloatFormat = &llvm::APFloat::IEEEsingle; - DoubleFormat = &llvm::APFloat::IEEEdouble; LongDoubleFormat = &llvm::APFloat::IEEEquad; } } @@ -483,6 +526,9 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints, ConstraintInfo &Info) const { const char *Name = Info.ConstraintStr.c_str(); + if (!*Name) + return false; + while (*Name) { switch (*Name) { default: diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp index b538792..075f905 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp @@ -20,7 +20,6 @@ #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetOptions.h" #include "llvm/ADT/APFloat.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" @@ -29,6 +28,7 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/Support/ErrorHandling.h" #include <algorithm> +#include <memory> using namespace clang; //===----------------------------------------------------------------------===// @@ -74,8 +74,8 @@ protected: MacroBuilder &Builder) const=0; public: OSTargetInfo(const llvm::Triple &Triple) : TgtInfo(Triple) {} - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { TgtInfo::getTargetDefines(Opts, Builder); getOSDefines(Opts, TgtInfo::getTriple(), Builder); } @@ -90,7 +90,6 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, VersionTuple &PlatformMinVersion) { Builder.defineMacro("__APPLE_CC__", "6000"); Builder.defineMacro("__APPLE__"); - Builder.defineMacro("__MACH__"); Builder.defineMacro("OBJC_NEW_PROPERTIES"); // AddressSanitizer doesn't play well with source fortification, which is on // by default on Darwin. @@ -138,39 +137,48 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, return; } - // If there's an environment specified in the triple, that means we're dealing - // with an embedded variant of some sort and don't want the platform - // version-min defines, so only add them if there's not one. - if (Triple.getEnvironmentName().empty()) { - // Set the appropriate OS version define. - if (Triple.isiOS()) { - assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!"); - char Str[6]; - Str[0] = '0' + Maj; - Str[1] = '0' + (Min / 10); - Str[2] = '0' + (Min % 10); - Str[3] = '0' + (Rev / 10); - Str[4] = '0' + (Rev % 10); - Str[5] = '\0'; - Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", - Str); - } else { - // Note that the Driver allows versions which aren't representable in the - // define (because we only get a single digit for the minor and micro - // revision numbers). So, we limit them to the maximum representable - // version. - assert(Triple.getEnvironmentName().empty() && "Invalid environment!"); - assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!"); - char Str[5]; + // Set the appropriate OS version define. + if (Triple.isiOS()) { + assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!"); + char Str[6]; + Str[0] = '0' + Maj; + Str[1] = '0' + (Min / 10); + Str[2] = '0' + (Min % 10); + Str[3] = '0' + (Rev / 10); + Str[4] = '0' + (Rev % 10); + Str[5] = '\0'; + Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", + Str); + } else if (Triple.isMacOSX()) { + // Note that the Driver allows versions which aren't representable in the + // define (because we only get a single digit for the minor and micro + // revision numbers). So, we limit them to the maximum representable + // version. + assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!"); + char Str[7]; + if (Maj < 10 || (Maj == 10 && Min < 10)) { Str[0] = '0' + (Maj / 10); Str[1] = '0' + (Maj % 10); Str[2] = '0' + std::min(Min, 9U); Str[3] = '0' + std::min(Rev, 9U); Str[4] = '\0'; - Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str); + } else { + // Handle versions > 10.9. + Str[0] = '0' + (Maj / 10); + Str[1] = '0' + (Maj % 10); + Str[2] = '0' + (Min / 10); + Str[3] = '0' + (Min % 10); + Str[4] = '0' + (Rev / 10); + Str[5] = '0' + (Rev % 10); + Str[6] = '\0'; } + Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str); } + // Tell users about the kernel if there is one. + if (Triple.isOSDarwin()) + Builder.defineMacro("__MACH__"); + PlatformMinVersion = VersionTuple(Maj, Min, Rev); } @@ -178,8 +186,8 @@ namespace { template<typename Target> class DarwinTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { getDarwinDefines(Builder, Opts, Triple, this->PlatformName, this->PlatformMinVersion); } @@ -190,7 +198,7 @@ public: this->MCountName = "\01mcount"; } - virtual std::string isValidSectionSpecifier(StringRef SR) const { + std::string isValidSectionSpecifier(StringRef SR) const override { // Let MCSectionMachO validate this. StringRef Segment, Section; unsigned TAA, StubSize; @@ -199,7 +207,7 @@ public: TAA, HasTAA, StubSize); } - virtual const char *getStaticInitSectionSpecifier() const { + const char *getStaticInitSectionSpecifier() const override { // FIXME: We should return 0 when building kexts. return "__TEXT,__StaticInit,regular,pure_instructions"; } @@ -207,7 +215,7 @@ public: /// Darwin does not support protected visibility. Darwin's "default" /// is very similar to ELF's "protected"; Darwin requires a "weak" /// attribute on declarations that can be dynamically replaced. - virtual bool hasProtectedVisibility() const { + bool hasProtectedVisibility() const override { return false; } }; @@ -217,8 +225,8 @@ public: template<typename Target> class DragonFlyBSDTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { // DragonFly defines; list based off of gcc output Builder.defineMacro("__DragonFly__"); Builder.defineMacro("__DragonFly_cc_version", "100001"); @@ -246,8 +254,8 @@ public: template<typename Target> class FreeBSDTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { // FreeBSD defines; list based off of gcc output unsigned Release = Triple.getOSMajorVersion(); @@ -293,8 +301,8 @@ public: template<typename Target> class KFreeBSDTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { // GNU/kFreeBSD defines; list based off of gcc output DefineStd(Builder, "unix", Opts); @@ -316,8 +324,8 @@ public: template<typename Target> class MinixTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { // Minix defines Builder.defineMacro("__minix", "3"); @@ -340,8 +348,8 @@ public: template<typename Target> class LinuxTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { // Linux defines; list based off of gcc output DefineStd(Builder, "unix", Opts); DefineStd(Builder, "linux", Opts); @@ -370,7 +378,7 @@ public: } } - virtual const char *getStaticInitSectionSpecifier() const { + const char *getStaticInitSectionSpecifier() const override { return ".text.startup"; } }; @@ -379,14 +387,25 @@ public: template<typename Target> class NetBSDTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { // NetBSD defines; list based off of gcc output Builder.defineMacro("__NetBSD__"); Builder.defineMacro("__unix__"); Builder.defineMacro("__ELF__"); if (Opts.POSIXThreads) Builder.defineMacro("_POSIX_THREADS"); + + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + Builder.defineMacro("__ARM_DWARF_EH__"); + break; + } } public: NetBSDTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { @@ -398,8 +417,8 @@ public: template<typename Target> class OpenBSDTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { // OpenBSD defines; list based off of gcc output Builder.defineMacro("__OpenBSD__"); @@ -435,8 +454,8 @@ public: template<typename Target> class BitrigTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { // Bitrig defines; list based off of gcc output Builder.defineMacro("__Bitrig__"); @@ -448,7 +467,6 @@ protected: public: BitrigTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { this->UserLabelPrefix = ""; - this->TLSSupported = false; this->MCountName = "__mcount"; } }; @@ -457,8 +475,8 @@ public: template<typename Target> class PSPTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { // PSP defines; list based on the output of the pspdev gcc toolchain. Builder.defineMacro("PSP"); Builder.defineMacro("_PSP"); @@ -475,8 +493,8 @@ public: template<typename Target> class PS3PPUTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { // PS3 PPU defines. Builder.defineMacro("__PPC__"); Builder.defineMacro("__PPU__"); @@ -492,28 +510,9 @@ public: this->LongWidth = this->LongAlign = 32; this->PointerWidth = this->PointerAlign = 32; this->IntMaxType = TargetInfo::SignedLongLong; - this->UIntMaxType = TargetInfo::UnsignedLongLong; this->Int64Type = TargetInfo::SignedLongLong; this->SizeType = TargetInfo::UnsignedInt; - this->DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32"; - } -}; - -// FIXME: Need a real SPU target. -// PS3 SPU Target -template<typename Target> -class PS3SPUTargetInfo : public OSTargetInfo<Target> { -protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { - // PS3 PPU defines. - Builder.defineMacro("__SPU__"); - Builder.defineMacro("__ELF__"); - } -public: - PS3SPUTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { - this->UserLabelPrefix = ""; + this->DescriptionString = "E-m:e-p:32:32-i64:64-n32:64"; } }; @@ -521,8 +520,8 @@ public: template<typename Target> class AuroraUXTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { DefineStd(Builder, "sun", Opts); DefineStd(Builder, "unix", Opts); Builder.defineMacro("__ELF__"); @@ -542,8 +541,8 @@ public: template<typename Target> class SolarisTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { DefineStd(Builder, "sun", Opts); DefineStd(Builder, "unix", Opts); Builder.defineMacro("__ELF__"); @@ -576,14 +575,14 @@ public: template<typename Target> class WindowsTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { Builder.defineMacro("_WIN32"); } void getVisualStudioDefines(const LangOptions &Opts, MacroBuilder &Builder) const { if (Opts.CPlusPlus) { - if (Opts.RTTI) + if (Opts.RTTIData) Builder.defineMacro("_CPPRTTI"); if (Opts.Exceptions) @@ -598,8 +597,13 @@ protected: if (Opts.POSIXThreads) Builder.defineMacro("_MT"); - if (Opts.MSCVersion != 0) - Builder.defineMacro("_MSC_VER", Twine(Opts.MSCVersion)); + if (Opts.MSCompatibilityVersion) { + Builder.defineMacro("_MSC_VER", + Twine(Opts.MSCompatibilityVersion / 100000)); + Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion)); + // FIXME We cannot encode the revision information into 32-bits + Builder.defineMacro("_MSC_BUILD", Twine(1)); + } if (Opts.MicrosoftExt) { Builder.defineMacro("_MSC_EXTENSIONS"); @@ -622,8 +626,8 @@ public: template <typename Target> class NaClTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { if (Opts.POSIXThreads) Builder.defineMacro("_REENTRANT"); if (Opts.CPlusPlus) @@ -642,21 +646,32 @@ public: this->PointerAlign = 32; this->PointerWidth = 32; this->IntMaxType = TargetInfo::SignedLongLong; - this->UIntMaxType = TargetInfo::UnsignedLongLong; this->Int64Type = TargetInfo::SignedLongLong; this->DoubleAlign = 64; this->LongDoubleWidth = 64; this->LongDoubleAlign = 64; + this->LongLongWidth = 64; + this->LongLongAlign = 64; this->SizeType = TargetInfo::UnsignedInt; this->PtrDiffType = TargetInfo::SignedInt; this->IntPtrType = TargetInfo::SignedInt; // RegParmMax is inherited from the underlying architecture this->LongDoubleFormat = &llvm::APFloat::IEEEdouble; - this->DescriptionString = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-" - "f32:32:32-f64:64:64-p:32:32:32-v128:32:32"; + if (Triple.getArch() == llvm::Triple::arm) { + this->DescriptionString = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S128"; + } else if (Triple.getArch() == llvm::Triple::x86) { + this->DescriptionString = "e-m:e-p:32:32-i64:64-n8:16:32-S128"; + } else if (Triple.getArch() == llvm::Triple::x86_64) { + this->DescriptionString = "e-m:e-p:32:32-i64:64-n8:16:32:64-S128"; + } else if (Triple.getArch() == llvm::Triple::mipsel) { + // Handled on mips' setDescriptionString. + } else { + assert(Triple.getArch() == llvm::Triple::le32); + this->DescriptionString = "e-p:32:32-i64:64"; + } } - virtual typename Target::CallingConvCheckResult checkCallingConvention( - CallingConv CC) const { + typename Target::CallingConvCheckResult checkCallingConvention( + CallingConv CC) const override { return CC == CC_PnaclCall ? Target::CCCR_OK : Target::checkCallingConvention(CC); } @@ -701,15 +716,16 @@ public: ArchDefinePwr6 = 1 << 9, ArchDefinePwr6x = 1 << 10, ArchDefinePwr7 = 1 << 11, - ArchDefineA2 = 1 << 12, - ArchDefineA2q = 1 << 13 + ArchDefinePwr8 = 1 << 12, + ArchDefineA2 = 1 << 13, + ArchDefineA2q = 1 << 14 } ArchDefineTypes; // Note: GCC recognizes the following additional cpus: // 401, 403, 405, 405fp, 440fp, 464, 464fp, 476, 476fp, 505, 740, 801, // 821, 823, 8540, 8548, e300c2, e300c3, e500mc64, e6500, 860, cell, // titan, rs64. - virtual bool setCPU(const std::string &Name) { + bool setCPU(const std::string &Name) override { bool CPUKnown = llvm::StringSwitch<bool>(Name) .Case("generic", true) .Case("440", true) @@ -749,6 +765,8 @@ public: .Case("pwr6x", true) .Case("power7", true) .Case("pwr7", true) + .Case("power8", true) + .Case("pwr8", true) .Case("powerpc", true) .Case("ppc", true) .Case("powerpc64", true) @@ -763,29 +781,29 @@ public: return CPUKnown; } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { Records = BuiltinInfo; NumRecords = clang::PPC::LastTSBuiltin-Builtin::FirstTSBuiltin; } - virtual bool isCLZForZeroUndef() const { return false; } + bool isCLZForZeroUndef() const override { return false; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const; + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override; - virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const; + void getDefaultFeatures(llvm::StringMap<bool> &Features) const override; - virtual bool handleTargetFeatures(std::vector<std::string> &Features, - DiagnosticsEngine &Diags); - virtual bool hasFeature(StringRef Feature) const; - - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const; - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const; - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const { + bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) override; + bool hasFeature(StringRef Feature) const override; + + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override; + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override; + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { switch (*Name) { default: return false; case 'O': // Zero @@ -807,6 +825,7 @@ public: case 'f':// VSX vector register to hold vector float data case 's':// VSX vector register to hold scalar float data case 'a':// Any VSX register + case 'c':// An individual CR bit break; default: return false; @@ -882,10 +901,24 @@ public: } return true; } - virtual const char *getClobbers() const { + std::string convertConstraint(const char *&Constraint) const override { + std::string R; + switch (*Constraint) { + case 'e': + case 'w': + // Two-character constraint; add "^" hint for later parsing. + R = std::string("^") + std::string(Constraint, 2); + Constraint++; + break; + default: + return TargetInfo::convertConstraint(Constraint); + } + return R; + } + const char *getClobbers() const override { return ""; } - int getEHDataRegisterNumber(unsigned RegNo) const { + int getEHDataRegisterNumber(unsigned RegNo) const override { if (RegNo == 0) return 3; if (RegNo == 1) return 4; return -1; @@ -943,12 +976,11 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, // Target properties. if (getTriple().getArch() == llvm::Triple::ppc64le) { Builder.defineMacro("_LITTLE_ENDIAN"); - Builder.defineMacro("__LITTLE_ENDIAN__"); + Builder.defineMacro("_CALL_ELF","2"); } else { if (getTriple().getOS() != llvm::Triple::NetBSD && getTriple().getOS() != llvm::Triple::OpenBSD) Builder.defineMacro("_BIG_ENDIAN"); - Builder.defineMacro("__BIG_ENDIAN__"); } // Subtarget options. @@ -997,7 +1029,10 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, | ArchDefinePpcsq) .Case("pwr7", ArchDefineName | ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 - | ArchDefinePwr6 | ArchDefinePpcgr | ArchDefinePpcsq) + | ArchDefinePpcgr | ArchDefinePpcsq) + .Case("pwr8", ArchDefineName | ArchDefinePwr7 | ArchDefinePwr6x + | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 + | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) .Case("power3", ArchDefinePpcgr) .Case("power4", ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) .Case("power5", ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr @@ -1011,7 +1046,10 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, | ArchDefinePpcsq) .Case("power7", ArchDefinePwr7 | ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 - | ArchDefinePwr6 | ArchDefinePpcgr | ArchDefinePpcsq) + | ArchDefinePpcgr | ArchDefinePpcsq) + .Case("power8", ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6x + | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 + | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) .Default(ArchDefineNone); if (defs & ArchDefineName) @@ -1038,6 +1076,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("_ARCH_PWR6X"); if (defs & ArchDefinePwr7) Builder.defineMacro("_ARCH_PWR7"); + if (defs & ArchDefinePwr8) + Builder.defineMacro("_ARCH_PWR8"); if (defs & ArchDefineA2) Builder.defineMacro("_ARCH_A2"); if (defs & ArchDefineA2q) { @@ -1086,6 +1126,7 @@ void PPCTargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { .Case("g5", true) .Case("pwr6", true) .Case("pwr7", true) + .Case("pwr8", true) .Case("ppc64", true) .Case("ppc64le", true) .Default(false); @@ -1206,8 +1247,7 @@ namespace { class PPC32TargetInfo : public PPCTargetInfo { public: PPC32TargetInfo(const llvm::Triple &Triple) : PPCTargetInfo(Triple) { - DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32"; + DescriptionString = "E-m:e-p:32:32-i64:64-n32"; switch (getTriple().getOS()) { case llvm::Triple::Linux: @@ -1230,7 +1270,7 @@ public: MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { // This is the ELF definition, and is overridden by the Darwin sub-target return TargetInfo::PowerABIBuiltinVaList; } @@ -1245,24 +1285,24 @@ public: PPC64TargetInfo(const llvm::Triple &Triple) : PPCTargetInfo(Triple) { LongWidth = LongAlign = PointerWidth = PointerAlign = 64; IntMaxType = SignedLong; - UIntMaxType = UnsignedLong; Int64Type = SignedLong; if (getTriple().getOS() == llvm::Triple::FreeBSD) { LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble; - DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-" - "v128:128:128-n32:64"; - } else - DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-f128:128:128-" - "v128:128:128-n32:64"; + DescriptionString = "E-m:e-i64:64-n32:64"; + } else { + if ((Triple.getArch() == llvm::Triple::ppc64le)) { + DescriptionString = "e-m:e-i64:64-n32:64"; + } else { + DescriptionString = "E-m:e-i64:64-n32:64"; + } +} // PPC64 supports atomics up to 8 bytes. MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::CharPtrBuiltinVaList; } }; @@ -1280,10 +1320,9 @@ public: PtrDiffType = SignedInt; // for http://llvm.org/bugs/show_bug.cgi?id=15726 LongLongAlign = 32; SuitableAlign = 128; - DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:32:64-f32:32:32-f64:32:64-v128:128:128-n32"; + DescriptionString = "E-m:o-p:32:32-f64:32:64-n32"; } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::CharPtrBuiltinVaList; } }; @@ -1295,8 +1334,7 @@ public: : DarwinTargetInfo<PPC64TargetInfo>(Triple) { HasAlignMac68kSupport = true; SuitableAlign = 128; - DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64"; + DescriptionString = "E-m:o-i64:64-n32:64"; } }; } // end anonymous namespace. @@ -1324,30 +1362,30 @@ namespace { // These must be defined in sorted order! NoAsmVariants = true; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { Builder.defineMacro("__PTX__"); Builder.defineMacro("__NVPTX__"); } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { Records = BuiltinInfo; NumRecords = clang::NVPTX::LastTSBuiltin-Builtin::FirstTSBuiltin; } - virtual bool hasFeature(StringRef Feature) const { + bool hasFeature(StringRef Feature) const override { return Feature == "ptx" || Feature == "nvptx"; } - - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const; - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { + + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override; + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override { // No aliases. - Aliases = 0; + Aliases = nullptr; NumAliases = 0; } - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const { + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { switch (*Name) { default: return false; case 'c': @@ -1360,15 +1398,15 @@ namespace { return true; } } - virtual const char *getClobbers() const { + const char *getClobbers() const override { // FIXME: Is this really right? return ""; } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { // FIXME: implement return TargetInfo::CharPtrBuiltinVaList; } - virtual bool setCPU(const std::string &Name) { + bool setCPU(const std::string &Name) override { bool Valid = llvm::StringSwitch<bool>(Name) .Case("sm_20", true) .Case("sm_21", true) @@ -1401,11 +1439,9 @@ namespace { public: NVPTX32TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) { PointerWidth = PointerAlign = 32; - SizeType = PtrDiffType = IntPtrType = TargetInfo::UnsignedInt; - DescriptionString - = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-" - "f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-" - "n16:32:64"; + SizeType = PtrDiffType = TargetInfo::UnsignedInt; + IntPtrType = TargetInfo::SignedInt; + DescriptionString = "e-p:32:32-i64:64-v16:16-v32:32-n16:32:64"; } }; @@ -1413,11 +1449,9 @@ namespace { public: NVPTX64TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) { PointerWidth = PointerAlign = 64; - SizeType = PtrDiffType = IntPtrType = TargetInfo::UnsignedLongLong; - DescriptionString - = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-" - "f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-" - "n16:32:64"; + SizeType = PtrDiffType = TargetInfo::UnsignedLongLong; + IntPtrType = TargetInfo::SignedLongLong; + DescriptionString = "e-i64:64-v16:16-v32:32-n16:32:64"; } }; } @@ -1434,31 +1468,21 @@ static const unsigned R600AddrSpaceMap[] = { }; static const char *DescriptionStringR600 = - "e" - "-p:32:32:32" - "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32" - "-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128" - "-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024-v2048:2048:2048" - "-n32:64"; + "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128" + "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64"; static const char *DescriptionStringR600DoubleOps = - "e" - "-p:32:32:32" - "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64" - "-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128" - "-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024-v2048:2048:2048" - "-n32:64"; + "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128" + "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64"; static const char *DescriptionStringSI = - "e" - "-p:64:64:64" - "-p3:32:32:32" - "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64" - "-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128" - "-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024-v2048:2048:2048" - "-n32:64"; + "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-p24:64:64" + "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128" + "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64"; class R600TargetInfo : public TargetInfo { + static const Builtin::Info BuiltinInfo[]; + /// \brief The GPU profiles supported by the R600 target. enum GPUKind { GK_NONE, @@ -1482,44 +1506,43 @@ public: UseAddrSpaceMapMangling = true; } - virtual const char * getClobbers() const { + const char * getClobbers() const override { return ""; } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &numNames) const { - Names = NULL; + void getGCCRegNames(const char * const *&Names, + unsigned &numNames) const override { + Names = nullptr; numNames = 0; } - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { - Aliases = NULL; + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override { + Aliases = nullptr; NumAliases = 0; } - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const { + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override { return true; } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { - Records = NULL; - NumRecords = 0; + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { + Records = BuiltinInfo; + NumRecords = clang::R600::LastTSBuiltin - Builtin::FirstTSBuiltin; } - - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { Builder.defineMacro("__R600__"); } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::CharPtrBuiltinVaList; } - virtual bool setCPU(const std::string &Name) { + bool setCPU(const std::string &Name) override { GPU = llvm::StringSwitch<GPUKind>(Name) .Case("r600" , GK_R600) .Case("rv610", GK_R600) @@ -1554,6 +1577,7 @@ public: .Case("kabini", GK_SEA_ISLANDS) .Case("kaveri", GK_SEA_ISLANDS) .Case("hawaii", GK_SEA_ISLANDS) + .Case("mullins", GK_SEA_ISLANDS) .Default(GK_NONE); if (GPU == GK_NONE) { @@ -1585,6 +1609,12 @@ public: } }; +const Builtin::Info R600TargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) \ + { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, +#include "clang/Basic/BuiltinsR600.def" +}; + } // end anonymous namespace namespace { @@ -1784,6 +1814,7 @@ class X86TargetInfo : public TargetInfo { CK_BDVER1, CK_BDVER2, CK_BDVER3, + CK_BDVER4, //@} /// This specification is deprecated and will be removed in the future. @@ -1817,57 +1848,57 @@ public: BigEndian = false; LongDoubleFormat = &llvm::APFloat::x87DoubleExtended; } - virtual unsigned getFloatEvalMethod() const { + unsigned getFloatEvalMethod() const override { // X87 evaluates with 80 bits "long double" precision. return SSELevel == NoSSE ? 2 : 0; } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { Records = BuiltinInfo; NumRecords = clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin; } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const { + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override { Names = GCCRegNames; NumNames = llvm::array_lengthof(GCCRegNames); } - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { - Aliases = 0; + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override { + Aliases = nullptr; NumAliases = 0; } - virtual void getGCCAddlRegNames(const AddlRegName *&Names, - unsigned &NumNames) const { + void getGCCAddlRegNames(const AddlRegName *&Names, + unsigned &NumNames) const override { Names = AddlRegNames; NumNames = llvm::array_lengthof(AddlRegNames); } - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const; - virtual std::string convertConstraint(const char *&Constraint) const; - virtual const char *getClobbers() const { + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override; + std::string convertConstraint(const char *&Constraint) const override; + const char *getClobbers() const override { return "~{dirflag},~{fpsr},~{flags}"; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const; + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override; static void setSSELevel(llvm::StringMap<bool> &Features, X86SSEEnum Level, bool Enabled); static void setMMXLevel(llvm::StringMap<bool> &Features, MMX3DNowEnum Level, bool Enabled); static void setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level, bool Enabled); - virtual void setFeatureEnabled(llvm::StringMap<bool> &Features, - StringRef Name, bool Enabled) const { + void setFeatureEnabled(llvm::StringMap<bool> &Features, + StringRef Name, bool Enabled) const override { setFeatureEnabledImpl(Features, Name, Enabled); } // This exists purely to cut down on the number of virtual calls in // getDefaultFeatures which calls this repeatedly. static void setFeatureEnabledImpl(llvm::StringMap<bool> &Features, StringRef Name, bool Enabled); - virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const; - virtual bool hasFeature(StringRef Feature) const; - virtual bool handleTargetFeatures(std::vector<std::string> &Features, - DiagnosticsEngine &Diags); - virtual const char* getABI() const { + void getDefaultFeatures(llvm::StringMap<bool> &Features) const override; + bool hasFeature(StringRef Feature) const override; + bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) override; + StringRef getABI() const override { if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX) return "avx"; else if (getTriple().getArch() == llvm::Triple::x86 && @@ -1875,7 +1906,7 @@ public: return "no-mmx"; return ""; } - virtual bool setCPU(const std::string &Name) { + bool setCPU(const std::string &Name) override { CPU = llvm::StringSwitch<CPUKind>(Name) .Case("i386", CK_i386) .Case("i486", CK_i486) @@ -1927,6 +1958,7 @@ public: .Case("bdver1", CK_BDVER1) .Case("bdver2", CK_BDVER2) .Case("bdver3", CK_BDVER3) + .Case("bdver4", CK_BDVER4) .Case("x86-64", CK_x86_64) .Case("geode", CK_Geode) .Default(CK_Generic); @@ -1996,15 +2028,16 @@ public: case CK_BDVER1: case CK_BDVER2: case CK_BDVER3: + case CK_BDVER4: case CK_x86_64: return true; } llvm_unreachable("Unhandled CPU kind"); } - virtual bool setFPMath(StringRef Name); + bool setFPMath(StringRef Name) override; - virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { // We accept all non-ARM calling conventions return (CC == CC_X86ThisCall || CC == CC_X86FastCall || @@ -2014,7 +2047,7 @@ public: CC == CC_IntelOclBicc) ? CCCR_OK : CCCR_Warning; } - virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const { + CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { return MT == CCMT_Member ? CC_X86ThisCall : CC_C; } }; @@ -2198,6 +2231,10 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { setFeatureEnabledImpl(Features, "prfchw", true); setFeatureEnabledImpl(Features, "cx16", true); break; + case CK_BDVER4: + setFeatureEnabledImpl(Features, "avx2", true); + setFeatureEnabledImpl(Features, "bmi2", true); + // FALLTHROUGH case CK_BDVER2: case CK_BDVER3: setFeatureEnabledImpl(Features, "xop", true); @@ -2701,13 +2738,15 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_BDVER3: defineCPUMacros(Builder, "bdver3"); break; + case CK_BDVER4: + defineCPUMacros(Builder, "bdver4"); + break; case CK_Geode: defineCPUMacros(Builder, "geode"); break; } // Target properties. - Builder.defineMacro("__LITTLE_ENDIAN__"); Builder.defineMacro("__REGISTER_PREFIX__", ""); // Define __NO_MATH_INLINES on linux/x86 so that we don't get inline @@ -2900,6 +2939,13 @@ X86TargetInfo::validateAsmConstraint(const char *&Name, case 'm': // any MMX register, when inter-unit moves enabled. break; // falls through to setAllowsRegister. } + case 'f': // any x87 floating point stack register. + // Constraint 'f' cannot be used for output operands. + if (Info.ConstraintStr[0] == '=') + return false; + + Info.setAllowsRegister(); + return true; case 'a': // eax. case 'b': // ebx. case 'c': // ecx. @@ -2907,7 +2953,6 @@ X86TargetInfo::validateAsmConstraint(const char *&Name, case 'S': // esi. case 'D': // edi. case 'A': // edx:eax. - case 'f': // any x87 floating point stack register. case 't': // top of floating point stack. case 'u': // second from top of floating point stack. case 'q': // Any register accessible as [r]l: a, b, c, and d. @@ -2960,9 +3005,7 @@ public: LongDoubleWidth = 96; LongDoubleAlign = 32; SuitableAlign = 128; - DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-" - "a0:0:64-f80:32:32-n8:16:32-S128"; + DescriptionString = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"; SizeType = UnsignedInt; PtrDiffType = SignedInt; IntPtrType = SignedInt; @@ -2978,17 +3021,17 @@ public: // MaxAtomicInlineWidth. (cmpxchg8b is an i586 instruction.) MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::CharPtrBuiltinVaList; } - int getEHDataRegisterNumber(unsigned RegNo) const { + int getEHDataRegisterNumber(unsigned RegNo) const override { if (RegNo == 0) return 0; if (RegNo == 1) return 2; return -1; } - virtual bool validateInputSize(StringRef Constraint, - unsigned Size) const { + bool validateInputSize(StringRef Constraint, + unsigned Size) const override { switch (Constraint[0]) { default: break; case 'a': @@ -3009,7 +3052,7 @@ public: NetBSDI386TargetInfo(const llvm::Triple &Triple) : NetBSDTargetInfo<X86_32TargetInfo>(Triple) {} - virtual unsigned getFloatEvalMethod() const { + unsigned getFloatEvalMethod() const override { unsigned Major, Minor, Micro; getTriple().getOSVersion(Major, Minor, Micro); // New NetBSD uses the default rounding mode. @@ -3056,9 +3099,7 @@ public: MaxVectorAlign = 256; SizeType = UnsignedLong; IntPtrType = SignedLong; - DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-" - "a0:0:64-f80:128:128-n8:16:32-S128"; + DescriptionString = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128"; HasAlignMac68kSupport = true; } @@ -3071,32 +3112,26 @@ class WindowsX86_32TargetInfo : public WindowsTargetInfo<X86_32TargetInfo> { public: WindowsX86_32TargetInfo(const llvm::Triple &Triple) : WindowsTargetInfo<X86_32TargetInfo>(Triple) { - TLSSupported = false; WCharType = UnsignedShort; DoubleAlign = LongLongAlign = 64; - DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-" - "v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32"; + DescriptionString = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32"; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { WindowsTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder); } }; -} // end anonymous namespace - -namespace { // x86-32 Windows Visual Studio target -class VisualStudioWindowsX86_32TargetInfo : public WindowsX86_32TargetInfo { +class MicrosoftX86_32TargetInfo : public WindowsX86_32TargetInfo { public: - VisualStudioWindowsX86_32TargetInfo(const llvm::Triple &Triple) + MicrosoftX86_32TargetInfo(const llvm::Triple &Triple) : WindowsX86_32TargetInfo(Triple) { LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder); WindowsX86_32TargetInfo::getVisualStudioDefines(Opts, Builder); // The value of the following reflects processor type. @@ -3107,29 +3142,46 @@ public: }; } // end anonymous namespace +static void addMinGWDefines(const LangOptions &Opts, MacroBuilder &Builder) { + Builder.defineMacro("__MSVCRT__"); + Builder.defineMacro("__MINGW32__"); + + // Mingw defines __declspec(a) to __attribute__((a)). Clang supports + // __declspec natively under -fms-extensions, but we define a no-op __declspec + // macro anyway for pre-processor compatibility. + if (Opts.MicrosoftExt) + Builder.defineMacro("__declspec", "__declspec"); + else + Builder.defineMacro("__declspec(a)", "__attribute__((a))"); + + if (!Opts.MicrosoftExt) { + // Provide macros for all the calling convention keywords. Provide both + // single and double underscore prefixed variants. These are available on + // x64 as well as x86, even though they have no effect. + const char *CCs[] = {"cdecl", "stdcall", "fastcall", "thiscall", "pascal"}; + for (const char *CC : CCs) { + std::string GCCSpelling = "__attribute__((__"; + GCCSpelling += CC; + GCCSpelling += "__))"; + Builder.defineMacro(Twine("_") + CC, GCCSpelling); + Builder.defineMacro(Twine("__") + CC, GCCSpelling); + } + } +} + namespace { // x86-32 MinGW target class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo { public: MinGWX86_32TargetInfo(const llvm::Triple &Triple) : WindowsX86_32TargetInfo(Triple) {} - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder); DefineStd(Builder, "WIN32", Opts); DefineStd(Builder, "WINNT", Opts); Builder.defineMacro("_X86_"); - Builder.defineMacro("__MSVCRT__"); - Builder.defineMacro("__MINGW32__"); - - // mingw32-gcc provides __declspec(a) as alias of __attribute__((a)). - // In contrast, clang-cc1 provides __declspec(a) with -fms-extensions. - if (Opts.MicrosoftExt) - // Provide "as-is" __declspec. - Builder.defineMacro("__declspec", "__declspec"); - else - // Provide alias of __attribute__ like mingw32-gcc. - Builder.defineMacro("__declspec(a)", "__attribute__((a))"); + addMinGWDefines(Opts, Builder); } }; } // end anonymous namespace @@ -3143,12 +3195,10 @@ public: TLSSupported = false; WCharType = UnsignedShort; DoubleAlign = LongLongAlign = 64; - DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" - "a0:0:64-f80:32:32-n8:16:32-S32"; + DescriptionString = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32"; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { X86_32TargetInfo::getTargetDefines(Opts, Builder); Builder.defineMacro("_X86_"); Builder.defineMacro("__CYGWIN__"); @@ -3172,8 +3222,8 @@ public: this->UserLabelPrefix = ""; this->TLSSupported = false; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { X86_32TargetInfo::getTargetDefines(Opts, Builder); Builder.defineMacro("__INTEL__"); Builder.defineMacro("__HAIKU__"); @@ -3185,8 +3235,8 @@ public: template<typename Target> class RTEMSTargetInfo : public OSTargetInfo<Target> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { // RTEMS defines; list based off of gcc output Builder.defineMacro("__rtems__"); @@ -3226,8 +3276,8 @@ public: PtrDiffType = SignedLong; this->UserLabelPrefix = ""; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { X86_32TargetInfo::getTargetDefines(Opts, Builder); Builder.defineMacro("__INTEL__"); Builder.defineMacro("__rtems__"); @@ -3240,20 +3290,23 @@ namespace { class X86_64TargetInfo : public X86TargetInfo { public: X86_64TargetInfo(const llvm::Triple &Triple) : X86TargetInfo(Triple) { - LongWidth = LongAlign = PointerWidth = PointerAlign = 64; + const bool IsX32 = getTriple().getEnvironment() == llvm::Triple::GNUX32; + LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64; LongDoubleWidth = 128; LongDoubleAlign = 128; LargeArrayMinWidth = 128; LargeArrayAlign = 128; SuitableAlign = 128; - IntMaxType = SignedLong; - UIntMaxType = UnsignedLong; - Int64Type = SignedLong; + SizeType = IsX32 ? UnsignedInt : UnsignedLong; + PtrDiffType = IsX32 ? SignedInt : SignedLong; + IntPtrType = IsX32 ? SignedInt : SignedLong; + IntMaxType = IsX32 ? SignedLongLong : SignedLong; + Int64Type = IsX32 ? SignedLongLong : SignedLong; RegParmMax = 6; - DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" - "a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"; + DescriptionString = (IsX32) + ? "e-m:e-" "p:32:32-" "i64:64-f80:128-n8:16:32:64-S128" + : "e-m:e-" "i64:64-f80:128-n8:16:32:64-S128"; // Use fpret only for long double. RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble); @@ -3262,28 +3315,26 @@ public: ComplexLongDoubleUsesFP2Ret = true; // x86-64 has atomics up to 16 bytes. - // FIXME: Once the backend is fixed, increase MaxAtomicInlineWidth to 128 - // on CPUs with cmpxchg16b MaxAtomicPromoteWidth = 128; - MaxAtomicInlineWidth = 64; + MaxAtomicInlineWidth = 128; } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::X86_64ABIBuiltinVaList; } - int getEHDataRegisterNumber(unsigned RegNo) const { + int getEHDataRegisterNumber(unsigned RegNo) const override { if (RegNo == 0) return 0; if (RegNo == 1) return 1; return -1; } - virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { return (CC == CC_C || CC == CC_IntelOclBicc || CC == CC_X86_64Win64) ? CCCR_OK : CCCR_Warning; } - virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const { + CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { return CC_C; } @@ -3296,27 +3347,25 @@ class WindowsX86_64TargetInfo : public WindowsTargetInfo<X86_64TargetInfo> { public: WindowsX86_64TargetInfo(const llvm::Triple &Triple) : WindowsTargetInfo<X86_64TargetInfo>(Triple) { - TLSSupported = false; WCharType = UnsignedShort; LongWidth = LongAlign = 32; DoubleAlign = LongLongAlign = 64; IntMaxType = SignedLongLong; - UIntMaxType = UnsignedLongLong; Int64Type = SignedLongLong; SizeType = UnsignedLongLong; PtrDiffType = SignedLongLong; IntPtrType = SignedLongLong; this->UserLabelPrefix = ""; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { WindowsTargetInfo<X86_64TargetInfo>::getTargetDefines(Opts, Builder); Builder.defineMacro("_WIN64"); } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::CharPtrBuiltinVaList; } - virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { return (CC == CC_C || CC == CC_IntelOclBicc || CC == CC_X86_64SysV) ? CCCR_OK : CCCR_Warning; @@ -3326,15 +3375,15 @@ public: namespace { // x86-64 Windows Visual Studio target -class VisualStudioWindowsX86_64TargetInfo : public WindowsX86_64TargetInfo { +class MicrosoftX86_64TargetInfo : public WindowsX86_64TargetInfo { public: - VisualStudioWindowsX86_64TargetInfo(const llvm::Triple &Triple) + MicrosoftX86_64TargetInfo(const llvm::Triple &Triple) : WindowsX86_64TargetInfo(Triple) { LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder); WindowsX86_64TargetInfo::getVisualStudioDefines(Opts, Builder); Builder.defineMacro("_M_X64"); @@ -3349,22 +3398,12 @@ class MinGWX86_64TargetInfo : public WindowsX86_64TargetInfo { public: MinGWX86_64TargetInfo(const llvm::Triple &Triple) : WindowsX86_64TargetInfo(Triple) {} - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder); DefineStd(Builder, "WIN64", Opts); - Builder.defineMacro("__MSVCRT__"); - Builder.defineMacro("__MINGW32__"); Builder.defineMacro("__MINGW64__"); - - // mingw32-gcc provides __declspec(a) as alias of __attribute__((a)). - // In contrast, clang-cc1 provides __declspec(a) with -fms-extensions. - if (Opts.MicrosoftExt) - // Provide "as-is" __declspec. - Builder.defineMacro("__declspec", "__declspec"); - else - // Provide alias of __attribute__ like mingw32-gcc. - Builder.defineMacro("__declspec(a)", "__attribute__((a))"); + addMinGWDefines(Opts, Builder); } }; } // end anonymous namespace @@ -3376,6 +3415,11 @@ public: : DarwinTargetInfo<X86_64TargetInfo>(Triple) { Int64Type = SignedLongLong; MaxVectorAlign = 256; + // The 64-bit iOS simulator uses the builtin bool type for Objective-C. + llvm::Triple T = llvm::Triple(Triple); + if (T.getOS() == llvm::Triple::IOS) + UseSignedCharForObjCBool = false; + DescriptionString = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"; } }; } // end anonymous namespace @@ -3386,7 +3430,6 @@ public: OpenBSDX86_64TargetInfo(const llvm::Triple &Triple) : OpenBSDTargetInfo<X86_64TargetInfo>(Triple) { IntMaxType = SignedLongLong; - UIntMaxType = UnsignedLongLong; Int64Type = SignedLongLong; } }; @@ -3398,242 +3441,11 @@ public: BitrigX86_64TargetInfo(const llvm::Triple &Triple) : BitrigTargetInfo<X86_64TargetInfo>(Triple) { IntMaxType = SignedLongLong; - UIntMaxType = UnsignedLongLong; Int64Type = SignedLongLong; } }; } -namespace { -class AArch64TargetInfo : public TargetInfo { - static const char * const GCCRegNames[]; - static const TargetInfo::GCCRegAlias GCCRegAliases[]; - - enum FPUModeEnum { - FPUMode, - NeonMode - }; - - unsigned FPU; - unsigned Crypto; - static const Builtin::Info BuiltinInfo[]; - -public: - AArch64TargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { - BigEndian = false; - LongWidth = LongAlign = 64; - LongDoubleWidth = LongDoubleAlign = 128; - PointerWidth = PointerAlign = 64; - SuitableAlign = 128; - DescriptionString = "e-p:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-i128:128:128-f32:32:32-f64:64:64-" - "f128:128:128-n32:64-S128"; - - WCharType = UnsignedInt; - LongDoubleFormat = &llvm::APFloat::IEEEquad; - - // AArch64 backend supports 64-bit operations at the moment. In principle - // 128-bit is possible if register-pairs are used. - MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; - - TheCXXABI.set(TargetCXXABI::GenericAArch64); - } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { - // GCC defines theses currently - Builder.defineMacro("__aarch64__"); - Builder.defineMacro("__AARCH64EL__"); - - // ACLE predefines. Many can only have one possible value on v8 AArch64. - Builder.defineMacro("__ARM_ACLE", "200"); - Builder.defineMacro("__ARM_ARCH", "8"); - Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'"); - - Builder.defineMacro("__ARM_64BIT_STATE"); - Builder.defineMacro("__ARM_PCS_AAPCS64"); - Builder.defineMacro("__ARM_ARCH_ISA_A64"); - - Builder.defineMacro("__ARM_FEATURE_UNALIGNED"); - Builder.defineMacro("__ARM_FEATURE_CLZ"); - Builder.defineMacro("__ARM_FEATURE_FMA"); - Builder.defineMacro("__ARM_FEATURE_DIV"); - - Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4"); - - // 0xe implies support for half, single and double precision operations. - Builder.defineMacro("__ARM_FP", "0xe"); - - // PCS specifies this for SysV variants, which is all we support. Other ABIs - // may choose __ARM_FP16_FORMAT_ALTERNATIVE. - Builder.defineMacro("__ARM_FP16_FORMAT_IEEE"); - - if (Opts.FastMath || Opts.FiniteMathOnly) - Builder.defineMacro("__ARM_FP_FAST"); - - if ((Opts.C99 || Opts.C11) && !Opts.Freestanding) - Builder.defineMacro("__ARM_FP_FENV_ROUNDING"); - - Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", - Opts.ShortWChar ? "2" : "4"); - - Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", - Opts.ShortEnums ? "1" : "4"); - - if (BigEndian) - Builder.defineMacro("__AARCH_BIG_ENDIAN"); - - if (FPU == NeonMode) { - Builder.defineMacro("__ARM_NEON"); - // 64-bit NEON supports half, single and double precision operations. - Builder.defineMacro("__ARM_NEON_FP", "7"); - } - - if (Crypto) { - Builder.defineMacro("__ARM_FEATURE_CRYPTO"); - } - } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { - Records = BuiltinInfo; - NumRecords = clang::AArch64::LastTSBuiltin-Builtin::FirstTSBuiltin; - } - virtual bool hasFeature(StringRef Feature) const { - return Feature == "aarch64" || (Feature == "neon" && FPU == NeonMode); - } - - virtual bool setCPU(const std::string &Name) { - return llvm::StringSwitch<bool>(Name) - .Case("generic", true) - .Cases("cortex-a53", "cortex-a57", true) - .Default(false); - } - - virtual bool handleTargetFeatures(std::vector<std::string> &Features, - DiagnosticsEngine &Diags) { - FPU = FPUMode; - Crypto = 0; - for (unsigned i = 0, e = Features.size(); i != e; ++i) { - if (Features[i] == "+neon") - FPU = NeonMode; - if (Features[i] == "+crypto") - Crypto = 1; - } - return true; - } - - virtual void getGCCRegNames(const char *const *&Names, - unsigned &NumNames) const; - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const; - - virtual bool isCLZForZeroUndef() const { return false; } - - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const { - switch (*Name) { - default: return false; - case 'w': // An FP/SIMD vector register - Info.setAllowsRegister(); - return true; - case 'I': // Constant that can be used with an ADD instruction - case 'J': // Constant that can be used with a SUB instruction - case 'K': // Constant that can be used with a 32-bit logical instruction - case 'L': // Constant that can be used with a 64-bit logical instruction - case 'M': // Constant that can be used as a 32-bit MOV immediate - case 'N': // Constant that can be used as a 64-bit MOV immediate - case 'Y': // Floating point constant zero - case 'Z': // Integer constant zero - return true; - case 'Q': // A memory reference with base register and no offset - Info.setAllowsMemory(); - return true; - case 'S': // A symbolic address - Info.setAllowsRegister(); - return true; - case 'U': - // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes, whatever they may be - // Utf: A memory address suitable for ldp/stp in TF mode, whatever it may be - // Usa: An absolute symbolic address - // Ush: The high part (bits 32:12) of a pc-relative symbolic address - llvm_unreachable("FIXME: Unimplemented support for bizarre constraints"); - } - } - - virtual const char *getClobbers() const { - // There are no AArch64 clobbers shared by all asm statements. - return ""; - } - - virtual BuiltinVaListKind getBuiltinVaListKind() const { - return TargetInfo::AArch64ABIBuiltinVaList; - } -}; - -const char * const AArch64TargetInfo::GCCRegNames[] = { - "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", - "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15", - "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23", - "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp", "wzr", - - "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", - "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", - "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", - "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp", "xzr", - - "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", - "b8", "b9", "b10", "b11", "b12", "b13", "b14", "b15", - "b16", "b17", "b18", "b19", "b20", "b21", "b22", "b23", - "b24", "b25", "b26", "b27", "b28", "b29", "b30", "b31", - - "h0", "h1", "h2", "h3", "h4", "h5", "h6", "h7", - "h8", "h9", "h10", "h11", "h12", "h13", "h14", "h15", - "h16", "h17", "h18", "h19", "h20", "h21", "h22", "h23", - "h24", "h25", "h26", "h27", "h28", "h29", "h30", "h31", - - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", - "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", - "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", - "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", - - "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", - "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", - "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", - "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", - - "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", - "q16", "q17", "q18", "q19", "q20", "q21", "q22", "q23", - "q24", "q25", "q26", "q27", "q28", "q29", "q30", "q31" -}; - -void AArch64TargetInfo::getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const { - Names = GCCRegNames; - NumNames = llvm::array_lengthof(GCCRegNames); -} - -const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = { - { { "x16" }, "ip0"}, - { { "x17" }, "ip1"}, - { { "x29" }, "fp" }, - { { "x30" }, "lr" } -}; - -void AArch64TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { - Aliases = GCCRegAliases; - NumAliases = llvm::array_lengthof(GCCRegAliases); - -} - -const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\ - ALL_LANGUAGES }, -#include "clang/Basic/BuiltinsAArch64.def" -}; - -} // end anonymous namespace namespace { class ARMTargetInfo : public TargetInfo { @@ -3678,55 +3490,177 @@ class ARMTargetInfo : public TargetInfo { unsigned SoftFloatABI : 1; unsigned CRC : 1; + unsigned Crypto : 1; static const Builtin::Info BuiltinInfo[]; static bool shouldUseInlineAtomic(const llvm::Triple &T) { - // On linux, binaries targeting old cpus call functions in libgcc to - // perform atomic operations. The implementation in libgcc then calls into - // the kernel which on armv6 and newer uses ldrex and strex. The net result - // is that if we assume the kernel is at least as recent as the hardware, - // it is safe to use atomic instructions on armv6 and newer. - if (!T.isOSLinux() && - T.getOS() != llvm::Triple::FreeBSD && - T.getOS() != llvm::Triple::NetBSD && - T.getOS() != llvm::Triple::Bitrig) - return false; StringRef ArchName = T.getArchName(); - if (T.getArch() == llvm::Triple::arm) { - if (!ArchName.startswith("armv")) + if (T.getArch() == llvm::Triple::arm || + T.getArch() == llvm::Triple::armeb) { + StringRef VersionStr; + if (ArchName.startswith("armv")) + VersionStr = ArchName.substr(4, 1); + else if (ArchName.startswith("armebv")) + VersionStr = ArchName.substr(6, 1); + else return false; - StringRef VersionStr = ArchName.substr(4); unsigned Version; if (VersionStr.getAsInteger(10, Version)) return false; return Version >= 6; } - assert(T.getArch() == llvm::Triple::thumb); - if (!ArchName.startswith("thumbv")) + assert(T.getArch() == llvm::Triple::thumb || + T.getArch() == llvm::Triple::thumbeb); + StringRef VersionStr; + if (ArchName.startswith("thumbv")) + VersionStr = ArchName.substr(6, 1); + else if (ArchName.startswith("thumbebv")) + VersionStr = ArchName.substr(8, 1); + else return false; - StringRef VersionStr = ArchName.substr(6); unsigned Version; if (VersionStr.getAsInteger(10, Version)) return false; return Version >= 7; } -public: - ARMTargetInfo(const llvm::Triple &Triple) - : TargetInfo(Triple), ABI("aapcs-linux"), CPU("arm1136j-s"), - FPMath(FP_Default), IsAAPCS(true) { - BigEndian = false; - switch (getTriple().getOS()) { - case llvm::Triple::NetBSD: + void setABIAAPCS() { + IsAAPCS = true; + + DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; + const llvm::Triple &T = getTriple(); + + // size_t is unsigned long on Darwin and NetBSD. + if (T.isOSDarwin() || T.getOS() == llvm::Triple::NetBSD) SizeType = UnsignedLong; - PtrDiffType = SignedLong; + else + SizeType = UnsignedInt; + + switch (T.getOS()) { + case llvm::Triple::NetBSD: WCharType = SignedInt; break; + case llvm::Triple::Win32: + WCharType = UnsignedShort; + break; + case llvm::Triple::Linux: default: // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int. WCharType = UnsignedInt; + break; + } + + UseBitFieldTypeAlignment = true; + + ZeroLengthBitfieldBoundary = 0; + + if (IsThumb) { + // Thumb1 add sp, #imm requires the immediate value be multiple of 4, + // so set preferred for small types to 32. + if (T.isOSBinFormatMachO()) { + DescriptionString = BigEndian ? + "E-m:o-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-" + "v128:64:128-a:0:32-n32-S64" : + "e-m:o-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-" + "v128:64:128-a:0:32-n32-S64"; + } else if (T.isOSWindows()) { + // FIXME: this is invalid for WindowsCE + assert(!BigEndian && "Windows on ARM does not support big endian"); + DescriptionString = "e" + "-m:e" + "-p:32:32" + "-i1:8:32-i8:8:32-i16:16:32-i64:64" + "-v128:64:128" + "-a:0:32" + "-n32" + "-S64"; + } else { + DescriptionString = BigEndian ? + "E-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-" + "v128:64:128-a:0:32-n32-S64" : + "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-" + "v128:64:128-a:0:32-n32-S64"; + } + } else { + if (T.isOSBinFormatMachO()) + DescriptionString = BigEndian ? + "E-m:o-p:32:32-i64:64-v128:64:128-n32-S64" : + "e-m:o-p:32:32-i64:64-v128:64:128-n32-S64"; + else + DescriptionString = BigEndian ? + "E-m:e-p:32:32-i64:64-v128:64:128-n32-S64" : + "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"; + } + + // FIXME: Enumerated types are variable width in straight AAPCS. + } + + void setABIAPCS() { + const llvm::Triple &T = getTriple(); + + IsAAPCS = false; + + DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32; + + // size_t is unsigned int on FreeBSD. + if (T.getOS() == llvm::Triple::FreeBSD) SizeType = UnsignedInt; + else + SizeType = UnsignedLong; + + // Revert to using SignedInt on apcs-gnu to comply with existing behaviour. + WCharType = SignedInt; + + // Do not respect the alignment of bit-field types when laying out + // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc. + UseBitFieldTypeAlignment = false; + + /// gcc forces the alignment to 4 bytes, regardless of the type of the + /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in + /// gcc. + ZeroLengthBitfieldBoundary = 32; + + if (IsThumb) { + // Thumb1 add sp, #imm requires the immediate value be multiple of 4, + // so set preferred for small types to 32. + if (T.isOSBinFormatMachO()) + DescriptionString = BigEndian ? + "E-m:o-p:32:32-i1:8:32-i8:8:32-i16:16:32-f64:32:64" + "-v64:32:64-v128:32:128-a:0:32-n32-S32" : + "e-m:o-p:32:32-i1:8:32-i8:8:32-i16:16:32-f64:32:64" + "-v64:32:64-v128:32:128-a:0:32-n32-S32"; + else + DescriptionString = BigEndian ? + "E-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-f64:32:64" + "-v64:32:64-v128:32:128-a:0:32-n32-S32" : + "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-f64:32:64" + "-v64:32:64-v128:32:128-a:0:32-n32-S32"; + } else { + if (T.isOSBinFormatMachO()) + DescriptionString = BigEndian ? + "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" : + "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"; + else + DescriptionString = BigEndian ? + "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" : + "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"; + } + + // FIXME: Override "preferred align" for double and long long. + } + +public: + ARMTargetInfo(const llvm::Triple &Triple, bool IsBigEndian) + : TargetInfo(Triple), CPU("arm1136j-s"), FPMath(FP_Default), + IsAAPCS(true) { + BigEndian = IsBigEndian; + + switch (getTriple().getOS()) { + case llvm::Triple::NetBSD: + PtrDiffType = SignedLong; + break; + default: PtrDiffType = SignedInt; break; } @@ -3737,17 +3671,8 @@ public: // FIXME: Should we just treat this as a feature? IsThumb = getTriple().getArchName().startswith("thumb"); - if (IsThumb) { - // Thumb1 add sp, #imm requires the immediate value be multiple of 4, - // so set preferred for small types to 32. - DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-" - "v64:64:64-v128:64:128-a0:0:32-n32-S64"); - } else { - DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-" - "v64:64:64-v128:64:128-a0:0:64-n32-S64"); - } + + setABI("aapcs-linux"); // ARM targets default to using the ARM C++ ABI. TheCXXABI.set(TargetCXXABI::GenericARM); @@ -3763,8 +3688,8 @@ public: // zero length bitfield. UseZeroLengthBitfieldAlignment = true; } - virtual const char *getABI() const { return ABI.c_str(); } - virtual bool setABI(const std::string &Name) { + StringRef getABI() const override { return ABI; } + bool setABI(const std::string &Name) override { ABI = Name; // The defaults (above) are for AAPCS, check if we need to change them. @@ -3772,53 +3697,22 @@ public: // FIXME: We need support for -meabi... we could just mangle it into the // name. if (Name == "apcs-gnu") { - DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32; - // size_t is unsigned int on FreeBSD. - if (getTriple().getOS() != llvm::Triple::FreeBSD) - SizeType = UnsignedLong; - - // Revert to using SignedInt on apcs-gnu to comply with existing behaviour. - WCharType = SignedInt; - - // Do not respect the alignment of bit-field types when laying out - // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc. - UseBitFieldTypeAlignment = false; - - /// gcc forces the alignment to 4 bytes, regardless of the type of the - /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in - /// gcc. - ZeroLengthBitfieldBoundary = 32; - - IsAAPCS = false; - - if (IsThumb) { - // Thumb1 add sp, #imm requires the immediate value be multiple of 4, - // so set preferred for small types to 32. - DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-" - "i64:32:64-f32:32:32-f64:32:64-" - "v64:32:64-v128:32:128-a0:0:32-n32-S32"); - } else { - DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:32:64-f32:32:32-f64:32:64-" - "v64:32:64-v128:32:128-a0:0:32-n32-S32"); - } - - // FIXME: Override "preferred align" for double and long long. - } else if (Name == "aapcs" || Name == "aapcs-vfp") { - // size_t is unsigned long on Darwin. - if (getTriple().isOSDarwin()) - SizeType = UnsignedLong; - IsAAPCS = true; - // FIXME: Enumerated types are variable width in straight AAPCS. - } else if (Name == "aapcs-linux") { - IsAAPCS = true; - } else - return false; - - return true; + setABIAPCS(); + return true; + } + if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") { + setABIAAPCS(); + return true; + } + return false; } - void getDefaultFeatures(llvm::StringMap<bool> &Features) const { + void getDefaultFeatures(llvm::StringMap<bool> &Features) const override { + if (IsAAPCS) + Features["aapcs"] = true; + else + Features["apcs"] = true; + StringRef ArchName = getTriple().getArchName(); if (CPU == "arm1136jf-s" || CPU == "arm1176jzf-s" || CPU == "mpcore") Features["vfp2"] = true; @@ -3830,32 +3724,44 @@ public: else if (CPU == "cortex-a5") { Features["vfp4"] = true; Features["neon"] = true; - } else if (CPU == "swift" || CPU == "cortex-a7" || CPU == "cortex-a15") { + } else if (CPU == "swift" || CPU == "cortex-a7" || + CPU == "cortex-a12" || CPU == "cortex-a15" || + CPU == "krait") { Features["vfp4"] = true; Features["neon"] = true; Features["hwdiv"] = true; Features["hwdiv-arm"] = true; + } else if (CPU == "cyclone") { + Features["v8fp"] = true; + Features["neon"] = true; + Features["hwdiv"] = true; + Features["hwdiv-arm"] = true; } else if (CPU == "cortex-a53" || CPU == "cortex-a57") { Features["fp-armv8"] = true; Features["neon"] = true; Features["hwdiv"] = true; Features["hwdiv-arm"] = true; Features["crc"] = true; - } else if (CPU == "cortex-r5" || CPU == "cortex-m3" || - CPU == "cortex-m4" || + Features["crypto"] = true; + } else if (CPU == "cortex-r5" || // Enable the hwdiv extension for all v8a AArch32 cores by // default. ArchName == "armv8a" || ArchName == "armv8" || - ArchName == "thumbv8a" || ArchName == "thumbv8") { + ArchName == "armebv8a" || ArchName == "armebv8" || + ArchName == "thumbv8a" || ArchName == "thumbv8" || + ArchName == "thumbebv8a" || ArchName == "thumbebv8") { Features["hwdiv"] = true; Features["hwdiv-arm"] = true; + } else if (CPU == "cortex-m3" || CPU == "cortex-m4") { + Features["hwdiv"] = true; } } - virtual bool handleTargetFeatures(std::vector<std::string> &Features, - DiagnosticsEngine &Diags) { + bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) override { FPU = 0; CRC = 0; + Crypto = 0; SoftFloat = SoftFloatABI = false; HWDiv = 0; for (unsigned i = 0, e = Features.size(); i != e; ++i) { @@ -3879,6 +3785,8 @@ public: HWDiv |= HWDivARM; else if (Features[i] == "+crc") CRC = 1; + else if (Features[i] == "+crypto") + Crypto = 1; } if (!(FPU & NeonFPU) && FPMath == FP_Neon) { @@ -3902,7 +3810,7 @@ public: return true; } - virtual bool hasFeature(StringRef Feature) const { + bool hasFeature(StringRef Feature) const override { return llvm::StringSwitch<bool>(Feature) .Case("arm", true) .Case("softfloat", SoftFloat) @@ -3929,42 +3837,60 @@ public: .Cases("arm1176jz-s", "arm1176jzf-s", "6ZK") .Cases("arm1136jf-s", "mpcorenovfp", "mpcore", "6K") .Cases("arm1156t2-s", "arm1156t2f-s", "6T2") - .Cases("cortex-a5", "cortex-a7", "cortex-a8", "7A") - .Cases("cortex-a9", "cortex-a12", "cortex-a15", "7A") + .Cases("cortex-a5", "cortex-a7", "cortex-a8", "cortex-a9-mp", "7A") + .Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "7A") .Cases("cortex-r4", "cortex-r5", "7R") - .Case("cortex-a9-mp", "7F") .Case("swift", "7S") - .Cases("cortex-m3", "cortex-m4", "7M") + .Case("cyclone", "8A") + .Case("cortex-m3", "7M") + .Case("cortex-m4", "7EM") .Case("cortex-m0", "6M") .Cases("cortex-a53", "cortex-a57", "8A") - .Default(0); + .Default(nullptr); } static const char *getCPUProfile(StringRef Name) { return llvm::StringSwitch<const char*>(Name) .Cases("cortex-a5", "cortex-a7", "cortex-a8", "A") - .Cases("cortex-a9", "cortex-a12", "cortex-a15", "A") + .Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "A") .Cases("cortex-a53", "cortex-a57", "A") .Cases("cortex-m3", "cortex-m4", "cortex-m0", "M") .Cases("cortex-r4", "cortex-r5", "R") .Default(""); } - virtual bool setCPU(const std::string &Name) { + bool setCPU(const std::string &Name) override { if (!getCPUDefineSuffix(Name)) return false; + // Cortex M does not support 8 byte atomics, while general Thumb2 does. + StringRef Profile = getCPUProfile(Name); + if (Profile == "M" && MaxAtomicInlineWidth) { + MaxAtomicPromoteWidth = 32; + MaxAtomicInlineWidth = 32; + } + CPU = Name; return true; } - virtual bool setFPMath(StringRef Name); - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + bool setFPMath(StringRef Name) override; + bool supportsThumb(StringRef ArchName, StringRef CPUArch, + unsigned CPUArchVer) const { + return CPUArchVer >= 7 || (CPUArch.find('T') != StringRef::npos) || + (CPUArch.find('M') != StringRef::npos); + } + bool supportsThumb2(StringRef ArchName, StringRef CPUArch, + unsigned CPUArchVer) const { + // We check both CPUArchVer and ArchName because when only triple is + // specified, the default CPU is arm1136j-s. + return ArchName.endswith("v6t2") || ArchName.endswith("v7") || + ArchName.endswith("v8") || CPUArch == "6T2" || CPUArchVer >= 7; + } + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { // Target identification. Builder.defineMacro("__arm"); Builder.defineMacro("__arm__"); // Target properties. - Builder.defineMacro("__ARMEL__"); - Builder.defineMacro("__LITTLE_ENDIAN__"); Builder.defineMacro("__REGISTER_PREFIX__", ""); StringRef CPUArch = getCPUDefineSuffix(CPU); @@ -3973,21 +3899,53 @@ public: llvm_unreachable("Invalid char for architecture version number"); } Builder.defineMacro("__ARM_ARCH_" + CPUArch + "__"); - Builder.defineMacro("__ARM_ARCH", CPUArch.substr(0, 1)); + + // ACLE 6.4.1 ARM/Thumb instruction set architecture StringRef CPUProfile = getCPUProfile(CPU); + StringRef ArchName = getTriple().getArchName(); + + // __ARM_ARCH is defined as an integer value indicating the current ARM ISA + Builder.defineMacro("__ARM_ARCH", CPUArch.substr(0, 1)); + + // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It + // is not defined for the M-profile. + // NOTE that the deffault profile is assumed to be 'A' + if (CPUProfile.empty() || CPUProfile != "M") + Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1"); + + // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supporst the original + // Thumb ISA (including v6-M). It is set to 2 if the core supports the + // Thumb-2 ISA as found in the v6T2 architecture and all v7 architecture. + if (supportsThumb2(ArchName, CPUArch, CPUArchVer)) + Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2"); + else if (supportsThumb(ArchName, CPUArch, CPUArchVer)) + Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1"); + + // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit + // instruction set such as ARM or Thumb. + Builder.defineMacro("__ARM_32BIT_STATE", "1"); + + // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex) + + // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset. if (!CPUProfile.empty()) - Builder.defineMacro("__ARM_ARCH_PROFILE", CPUProfile); - + Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'"); + + // ACLE predefines. + Builder.defineMacro("__ARM_ACLE", "200"); + // Subtarget options. // FIXME: It's more complicated than this and we don't really support // interworking. - if (5 <= CPUArchVer && CPUArchVer <= 7) + // Windows on ARM does not "support" interworking + if (5 <= CPUArchVer && CPUArchVer <= 8 && !getTriple().isOSWindows()) Builder.defineMacro("__THUMB_INTERWORK__"); if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") { // Embedded targets on Darwin follow AAPCS, but not EABI. - if (!getTriple().isOSDarwin()) + // Windows on ARM follows AAPCS VFP, but does not conform to EABI. + if (!getTriple().isOSDarwin() && !getTriple().isOSWindows()) Builder.defineMacro("__ARM_EABI__"); Builder.defineMacro("__ARM_PCS", "1"); @@ -4004,7 +3962,7 @@ public: if (IsThumb) { Builder.defineMacro("__THUMBEL__"); Builder.defineMacro("__thumb__"); - if (CPUArch == "6T2" || CPUArchVer == 7) + if (supportsThumb2(ArchName, CPUArch, CPUArchVer)) Builder.defineMacro("__thumb2__"); } if (((HWDiv & HWDivThumb) && IsThumb) || ((HWDiv & HWDivARM) && !IsThumb)) @@ -4022,17 +3980,28 @@ public: if (FPU & VFP4FPU) Builder.defineMacro("__ARM_VFPV4__"); } - + // This only gets set when Neon instructions are actually available, unlike // the VFP define, hence the soft float and arch check. This is subtly // different from gcc, we follow the intent which was that it should be set // when Neon instructions are actually available. - if ((FPU & NeonFPU) && !SoftFloat && CPUArchVer >= 7) + if ((FPU & NeonFPU) && !SoftFloat && CPUArchVer >= 7) { + Builder.defineMacro("__ARM_NEON"); Builder.defineMacro("__ARM_NEON__"); + } + + Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", + Opts.ShortWChar ? "2" : "4"); + + Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", + Opts.ShortEnums ? "1" : "4"); if (CRC) Builder.defineMacro("__ARM_FEATURE_CRC32"); + if (Crypto) + Builder.defineMacro("__ARM_FEATURE_CRYPTO"); + if (CPUArchVer >= 6 && CPUArch != "6M") { Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); @@ -4040,21 +4009,21 @@ public: Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); } } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { Records = BuiltinInfo; NumRecords = clang::ARM::LastTSBuiltin-Builtin::FirstTSBuiltin; } - virtual bool isCLZForZeroUndef() const { return false; } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + bool isCLZForZeroUndef() const override { return false; } + BuiltinVaListKind getBuiltinVaListKind() const override { return IsAAPCS ? AAPCSABIBuiltinVaList : TargetInfo::VoidPtrBuiltinVaList; } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const; - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const; - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const { + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override; + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override; + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { switch (*Name) { default: break; case 'l': // r0-r7 @@ -4084,7 +4053,7 @@ public: } return false; } - virtual std::string convertConstraint(const char *&Constraint) const { + std::string convertConstraint(const char *&Constraint) const override { std::string R; switch (*Constraint) { case 'U': // Two-character constraint; add "^" hint for later parsing. @@ -4099,9 +4068,8 @@ public: } return R; } - virtual bool validateConstraintModifier(StringRef Constraint, - const char Modifier, - unsigned Size) const { + bool validateConstraintModifier(StringRef Constraint, const char Modifier, + unsigned Size) const override { bool isOutput = (Constraint[0] == '='); bool isInOut = (Constraint[0] == '+'); @@ -4126,16 +4094,16 @@ public: return true; } - virtual const char *getClobbers() const { + const char *getClobbers() const override { // FIXME: Is this really right? return ""; } - virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { return (CC == CC_AAPCS || CC == CC_AAPCS_VFP) ? CCCR_OK : CCCR_Warning; } - virtual int getEHDataRegisterNumber(unsigned RegNo) const { + int getEHDataRegisterNumber(unsigned RegNo) const override { if (RegNo == 0) return 0; if (RegNo == 1) return 1; return -1; @@ -4213,25 +4181,123 @@ const Builtin::Info ARMTargetInfo::BuiltinInfo[] = { #define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\ ALL_LANGUAGES }, +#include "clang/Basic/BuiltinsNEON.def" + +#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, +#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) { #ID, TYPE, ATTRS, 0, LANG }, +#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\ + ALL_LANGUAGES }, #include "clang/Basic/BuiltinsARM.def" }; + +class ARMleTargetInfo : public ARMTargetInfo { +public: + ARMleTargetInfo(const llvm::Triple &Triple) + : ARMTargetInfo(Triple, false) { } + virtual void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + Builder.defineMacro("__ARMEL__"); + ARMTargetInfo::getTargetDefines(Opts, Builder); + } +}; + +class ARMbeTargetInfo : public ARMTargetInfo { +public: + ARMbeTargetInfo(const llvm::Triple &Triple) + : ARMTargetInfo(Triple, true) { } + virtual void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + Builder.defineMacro("__ARMEB__"); + Builder.defineMacro("__ARM_BIG_ENDIAN"); + ARMTargetInfo::getTargetDefines(Opts, Builder); + } +}; } // end anonymous namespace. namespace { +class WindowsARMTargetInfo : public WindowsTargetInfo<ARMleTargetInfo> { + const llvm::Triple Triple; +public: + WindowsARMTargetInfo(const llvm::Triple &Triple) + : WindowsTargetInfo<ARMleTargetInfo>(Triple), Triple(Triple) { + TLSSupported = false; + WCharType = UnsignedShort; + SizeType = UnsignedInt; + UserLabelPrefix = ""; + } + void getVisualStudioDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder); + + // FIXME: this is invalid for WindowsCE + Builder.defineMacro("_M_ARM_NT", "1"); + Builder.defineMacro("_M_ARMT", "_M_ARM"); + Builder.defineMacro("_M_THUMB", "_M_ARM"); + + assert((Triple.getArch() == llvm::Triple::arm || + Triple.getArch() == llvm::Triple::thumb) && + "invalid architecture for Windows ARM target info"); + unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6; + Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset)); + + // TODO map the complete set of values + // 31: VFPv3 40: VFPv4 + Builder.defineMacro("_M_ARM_FP", "31"); + } + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::CharPtrBuiltinVaList; + } +}; + +// Windows ARM + Itanium C++ ABI Target +class ItaniumWindowsARMleTargetInfo : public WindowsARMTargetInfo { +public: + ItaniumWindowsARMleTargetInfo(const llvm::Triple &Triple) + : WindowsARMTargetInfo(Triple) { + TheCXXABI.set(TargetCXXABI::GenericARM); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + WindowsARMTargetInfo::getTargetDefines(Opts, Builder); + + if (Opts.MSVCCompat) + WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); + } +}; + +// Windows ARM, MS (C++) ABI +class MicrosoftARMleTargetInfo : public WindowsARMTargetInfo { +public: + MicrosoftARMleTargetInfo(const llvm::Triple &Triple) + : WindowsARMTargetInfo(Triple) { + TheCXXABI.set(TargetCXXABI::Microsoft); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + WindowsARMTargetInfo::getTargetDefines(Opts, Builder); + WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); + } +}; +} + + +namespace { class DarwinARMTargetInfo : - public DarwinTargetInfo<ARMTargetInfo> { + public DarwinTargetInfo<ARMleTargetInfo> { protected: - virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); } public: DarwinARMTargetInfo(const llvm::Triple &Triple) - : DarwinTargetInfo<ARMTargetInfo>(Triple) { + : DarwinTargetInfo<ARMleTargetInfo>(Triple) { HasAlignMac68kSupport = true; // iOS always has 64-bit atomic instructions. - // FIXME: This should be based off of the target features in ARMTargetInfo. + // FIXME: This should be based off of the target features in ARMleTargetInfo. MaxAtomicInlineWidth = 64; // Darwin on iOS uses a variant of the ARM C++ ABI. @@ -4242,6 +4308,357 @@ public: namespace { +class AArch64TargetInfo : public TargetInfo { + virtual void setDescriptionString() = 0; + static const TargetInfo::GCCRegAlias GCCRegAliases[]; + static const char *const GCCRegNames[]; + + enum FPUModeEnum { + FPUMode, + NeonMode + }; + + unsigned FPU; + unsigned CRC; + unsigned Crypto; + + static const Builtin::Info BuiltinInfo[]; + + std::string ABI; + +public: + AArch64TargetInfo(const llvm::Triple &Triple) + : TargetInfo(Triple), ABI("aapcs") { + + if (getTriple().getOS() == llvm::Triple::NetBSD) { + WCharType = SignedInt; + + // NetBSD apparently prefers consistency across ARM targets to consistency + // across 64-bit targets. + Int64Type = SignedLongLong; + IntMaxType = SignedLongLong; + } else { + WCharType = UnsignedInt; + Int64Type = SignedLong; + IntMaxType = SignedLong; + } + + LongWidth = LongAlign = PointerWidth = PointerAlign = 64; + MaxVectorAlign = 128; + RegParmMax = 8; + MaxAtomicInlineWidth = 128; + MaxAtomicPromoteWidth = 128; + + LongDoubleWidth = LongDoubleAlign = 128; + LongDoubleFormat = &llvm::APFloat::IEEEquad; + + // {} in inline assembly are neon specifiers, not assembly variant + // specifiers. + NoAsmVariants = true; + + // AArch64 targets default to using the ARM C++ ABI. + TheCXXABI.set(TargetCXXABI::GenericAArch64); + } + + StringRef getABI() const override { return ABI; } + virtual bool setABI(const std::string &Name) { + if (Name != "aapcs" && Name != "darwinpcs") + return false; + + ABI = Name; + return true; + } + + virtual bool setCPU(const std::string &Name) { + bool CPUKnown = llvm::StringSwitch<bool>(Name) + .Case("generic", true) + .Cases("cortex-a53", "cortex-a57", true) + .Case("cyclone", true) + .Default(false); + return CPUKnown; + } + + virtual void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + // Target identification. + Builder.defineMacro("__aarch64__"); + + // Target properties. + Builder.defineMacro("_LP64"); + Builder.defineMacro("__LP64__"); + + // ACLE predefines. Many can only have one possible value on v8 AArch64. + Builder.defineMacro("__ARM_ACLE", "200"); + Builder.defineMacro("__ARM_ARCH", "8"); + Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'"); + + Builder.defineMacro("__ARM_64BIT_STATE"); + Builder.defineMacro("__ARM_PCS_AAPCS64"); + Builder.defineMacro("__ARM_ARCH_ISA_A64"); + + Builder.defineMacro("__ARM_FEATURE_UNALIGNED"); + Builder.defineMacro("__ARM_FEATURE_CLZ"); + Builder.defineMacro("__ARM_FEATURE_FMA"); + Builder.defineMacro("__ARM_FEATURE_DIV"); + + Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4"); + + // 0xe implies support for half, single and double precision operations. + Builder.defineMacro("__ARM_FP", "0xe"); + + // PCS specifies this for SysV variants, which is all we support. Other ABIs + // may choose __ARM_FP16_FORMAT_ALTERNATIVE. + Builder.defineMacro("__ARM_FP16_FORMAT_IEEE"); + + if (Opts.FastMath || Opts.FiniteMathOnly) + Builder.defineMacro("__ARM_FP_FAST"); + + if ((Opts.C99 || Opts.C11) && !Opts.Freestanding) + Builder.defineMacro("__ARM_FP_FENV_ROUNDING"); + + Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4"); + + Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", + Opts.ShortEnums ? "1" : "4"); + + if (FPU == NeonMode) { + Builder.defineMacro("__ARM_NEON"); + // 64-bit NEON supports half, single and double precision operations. + Builder.defineMacro("__ARM_NEON_FP", "0xe"); + } + + if (CRC) + Builder.defineMacro("__ARM_FEATURE_CRC32"); + + if (Crypto) + Builder.defineMacro("__ARM_FEATURE_CRYPTO"); + } + + virtual void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const { + Records = BuiltinInfo; + NumRecords = clang::AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin; + } + + virtual bool hasFeature(StringRef Feature) const { + return Feature == "aarch64" || + Feature == "arm64" || + (Feature == "neon" && FPU == NeonMode); + } + + bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) override { + FPU = FPUMode; + CRC = 0; + Crypto = 0; + for (unsigned i = 0, e = Features.size(); i != e; ++i) { + if (Features[i] == "+neon") + FPU = NeonMode; + if (Features[i] == "+crc") + CRC = 1; + if (Features[i] == "+crypto") + Crypto = 1; + } + + setDescriptionString(); + + return true; + } + + virtual bool isCLZForZeroUndef() const { return false; } + + virtual BuiltinVaListKind getBuiltinVaListKind() const { + return TargetInfo::AArch64ABIBuiltinVaList; + } + + virtual void getGCCRegNames(const char *const *&Names, + unsigned &NumNames) const; + virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const; + + virtual bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const { + switch (*Name) { + default: + return false; + case 'w': // Floating point and SIMD registers (V0-V31) + Info.setAllowsRegister(); + return true; + case 'I': // Constant that can be used with an ADD instruction + case 'J': // Constant that can be used with a SUB instruction + case 'K': // Constant that can be used with a 32-bit logical instruction + case 'L': // Constant that can be used with a 64-bit logical instruction + case 'M': // Constant that can be used as a 32-bit MOV immediate + case 'N': // Constant that can be used as a 64-bit MOV immediate + case 'Y': // Floating point constant zero + case 'Z': // Integer constant zero + return true; + case 'Q': // A memory reference with base register and no offset + Info.setAllowsMemory(); + return true; + case 'S': // A symbolic address + Info.setAllowsRegister(); + return true; + case 'U': + // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes, whatever they may be + // Utf: A memory address suitable for ldp/stp in TF mode, whatever it may be + // Usa: An absolute symbolic address + // Ush: The high part (bits 32:12) of a pc-relative symbolic address + llvm_unreachable("FIXME: Unimplemented support for bizarre constraints"); + case 'z': // Zero register, wzr or xzr + Info.setAllowsRegister(); + return true; + case 'x': // Floating point and SIMD registers (V0-V15) + Info.setAllowsRegister(); + return true; + } + return false; + } + + virtual const char *getClobbers() const { return ""; } + + int getEHDataRegisterNumber(unsigned RegNo) const { + if (RegNo == 0) + return 0; + if (RegNo == 1) + return 1; + return -1; + } +}; + +const char *const AArch64TargetInfo::GCCRegNames[] = { + // 32-bit Integer registers + "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", + "w11", "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", + "w22", "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp", + + // 64-bit Integer registers + "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", + "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", + "x22", "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp", + + // 32-bit floating point regsisters + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", + "s11", "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", + "s22", "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", + + // 64-bit floating point regsisters + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", + "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", + "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", + + // Vector registers + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", + "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", + "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31" +}; + +void AArch64TargetInfo::getGCCRegNames(const char *const *&Names, + unsigned &NumNames) const { + Names = GCCRegNames; + NumNames = llvm::array_lengthof(GCCRegNames); +} + +const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = { + { { "w31" }, "wsp" }, + { { "x29" }, "fp" }, + { { "x30" }, "lr" }, + { { "x31" }, "sp" }, + // The S/D/Q and W/X registers overlap, but aren't really aliases; we + // don't want to substitute one of these for a different-sized one. +}; + +void AArch64TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const { + Aliases = GCCRegAliases; + NumAliases = llvm::array_lengthof(GCCRegAliases); +} + +const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) \ + { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, +#include "clang/Basic/BuiltinsNEON.def" + +#define BUILTIN(ID, TYPE, ATTRS) \ + { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, +#include "clang/Basic/BuiltinsAArch64.def" +}; + +class AArch64leTargetInfo : public AArch64TargetInfo { + void setDescriptionString() override { + if (getTriple().isOSBinFormatMachO()) + DescriptionString = "e-m:o-i64:64-i128:128-n32:64-S128"; + else + DescriptionString = "e-m:e-i64:64-i128:128-n32:64-S128"; + } + +public: + AArch64leTargetInfo(const llvm::Triple &Triple) + : AArch64TargetInfo(Triple) { + BigEndian = false; + } + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + Builder.defineMacro("__AARCH64EL__"); + AArch64TargetInfo::getTargetDefines(Opts, Builder); + } +}; + +class AArch64beTargetInfo : public AArch64TargetInfo { + void setDescriptionString() override { + assert(!getTriple().isOSBinFormatMachO()); + DescriptionString = "E-m:e-i64:64-i128:128-n32:64-S128"; + } + +public: + AArch64beTargetInfo(const llvm::Triple &Triple) + : AArch64TargetInfo(Triple) { } + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + Builder.defineMacro("__AARCH64EB__"); + Builder.defineMacro("__AARCH_BIG_ENDIAN"); + Builder.defineMacro("__ARM_BIG_ENDIAN"); + AArch64TargetInfo::getTargetDefines(Opts, Builder); + } +}; +} // end anonymous namespace. + +namespace { +class DarwinAArch64TargetInfo : public DarwinTargetInfo<AArch64leTargetInfo> { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + Builder.defineMacro("__AARCH64_SIMD__"); + Builder.defineMacro("__ARM64_ARCH_8__"); + Builder.defineMacro("__ARM_NEON__"); + Builder.defineMacro("__LITTLE_ENDIAN__"); + Builder.defineMacro("__REGISTER_PREFIX__", ""); + Builder.defineMacro("__arm64", "1"); + Builder.defineMacro("__arm64__", "1"); + + getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); + } + +public: + DarwinAArch64TargetInfo(const llvm::Triple &Triple) + : DarwinTargetInfo<AArch64leTargetInfo>(Triple) { + Int64Type = SignedLongLong; + WCharType = SignedInt; + UseSignedCharForObjCBool = false; + + LongDoubleWidth = LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble; + + TheCXXABI.set(TargetCXXABI::iOS64); + } + + virtual BuiltinVaListKind getBuiltinVaListKind() const { + return TargetInfo::CharPtrBuiltinVaList; + } +}; +} // end anonymous namespace + +namespace { // Hexagon abstract base class class HexagonTargetInfo : public TargetInfo { static const Builtin::Info BuiltinInfo[]; @@ -4251,41 +4668,39 @@ class HexagonTargetInfo : public TargetInfo { public: HexagonTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { BigEndian = false; - DescriptionString = ("e-p:32:32:32-" - "i64:64:64-i32:32:32-i16:16:16-i1:32:32-" - "f64:64:64-f32:32:32-a0:0-n32"); + DescriptionString = "e-m:e-p:32:32-i1:32-i64:64-a:0-n32"; // {} in inline assembly are packet specifiers, not assembly variant // specifiers. NoAsmVariants = true; } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { Records = BuiltinInfo; NumRecords = clang::Hexagon::LastTSBuiltin-Builtin::FirstTSBuiltin; } - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const { + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { return true; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const; + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override; - virtual bool hasFeature(StringRef Feature) const { + bool hasFeature(StringRef Feature) const override { return Feature == "hexagon"; } - - virtual BuiltinVaListKind getBuiltinVaListKind() const { + + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::CharPtrBuiltinVaList; } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const; - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const; - virtual const char *getClobbers() const { + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override; + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override; + const char *getClobbers() const override { return ""; } @@ -4293,10 +4708,10 @@ public: return llvm::StringSwitch<const char*>(Name) .Case("hexagonv4", "4") .Case("hexagonv5", "5") - .Default(0); + .Default(nullptr); } - virtual bool setCPU(const std::string &Name) { + bool setCPU(const std::string &Name) override { if (!getHexagonCPUSuffix(Name)) return false; @@ -4404,47 +4819,47 @@ class SparcTargetInfo : public TargetInfo { public: SparcTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {} - virtual bool handleTargetFeatures(std::vector<std::string> &Features, - DiagnosticsEngine &Diags) { + bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) override { SoftFloat = false; for (unsigned i = 0, e = Features.size(); i != e; ++i) if (Features[i] == "+soft-float") SoftFloat = true; return true; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { DefineStd(Builder, "sparc", Opts); Builder.defineMacro("__REGISTER_PREFIX__", ""); if (SoftFloat) Builder.defineMacro("SOFT_FLOAT", "1"); } - - virtual bool hasFeature(StringRef Feature) const { + + bool hasFeature(StringRef Feature) const override { return llvm::StringSwitch<bool>(Feature) .Case("softfloat", SoftFloat) .Case("sparc", true) .Default(false); } - - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { + + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { // FIXME: Implement! } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const; - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const; - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const { + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override; + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override; + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override { // FIXME: Implement! return false; } - virtual const char *getClobbers() const { + const char *getClobbers() const override { // FIXME: Implement! return ""; } @@ -4508,13 +4923,11 @@ void SparcTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, class SparcV8TargetInfo : public SparcTargetInfo { public: SparcV8TargetInfo(const llvm::Triple &Triple) : SparcTargetInfo(Triple) { - // FIXME: Support Sparc quad-precision long double? - DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64"; + DescriptionString = "E-m:e-p:32:32-i64:64-f128:64-n32-S64"; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { SparcTargetInfo::getTargetDefines(Opts, Builder); Builder.defineMacro("__sparcv8"); } @@ -4525,19 +4938,15 @@ class SparcV9TargetInfo : public SparcTargetInfo { public: SparcV9TargetInfo(const llvm::Triple &Triple) : SparcTargetInfo(Triple) { // FIXME: Support Sparc quad-precision long double? - DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32:64-S128"; + DescriptionString = "E-m:e-i64:64-n32:64-S128"; // This is an LP64 platform. LongWidth = LongAlign = PointerWidth = PointerAlign = 64; // OpenBSD uses long long for int64_t and intmax_t. - if (getTriple().getOS() == llvm::Triple::OpenBSD) { + if (getTriple().getOS() == llvm::Triple::OpenBSD) IntMaxType = SignedLongLong; - UIntMaxType = UnsignedLongLong; - } else { + else IntMaxType = SignedLong; - UIntMaxType = UnsignedLong; - } Int64Type = IntMaxType; // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit @@ -4548,8 +4957,8 @@ public: MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { SparcTargetInfo::getTargetDefines(Opts, Builder); Builder.defineMacro("__sparcv9"); Builder.defineMacro("__arch64__"); @@ -4563,7 +4972,7 @@ public: } } - virtual bool setCPU(const std::string &Name) { + bool setCPU(const std::string &Name) override { bool CPUKnown = llvm::StringSwitch<bool>(Name) .Case("v9", true) .Case("ultrasparc", true) @@ -4602,109 +5011,108 @@ public: } // end anonymous namespace. namespace { - class SystemZTargetInfo : public TargetInfo { - static const char *const GCCRegNames[]; +class SystemZTargetInfo : public TargetInfo { + static const char *const GCCRegNames[]; - public: - SystemZTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { - TLSSupported = true; - IntWidth = IntAlign = 32; - LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64; - PointerWidth = PointerAlign = 64; - LongDoubleWidth = 128; - LongDoubleAlign = 64; - LongDoubleFormat = &llvm::APFloat::IEEEquad; - MinGlobalAlign = 16; - DescriptionString = "E-p:64:64:64-i1:8:16-i8:8:16-i16:16-i32:32-i64:64" - "-f32:32-f64:64-f128:64-a0:8:16-n32:64"; - MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; - } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { - Builder.defineMacro("__s390__"); - Builder.defineMacro("__s390x__"); - Builder.defineMacro("__zarch__"); - Builder.defineMacro("__LONG_DOUBLE_128__"); - } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { - // FIXME: Implement. - Records = 0; - NumRecords = 0; - } +public: + SystemZTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { + TLSSupported = true; + IntWidth = IntAlign = 32; + LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64; + PointerWidth = PointerAlign = 64; + LongDoubleWidth = 128; + LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEquad; + MinGlobalAlign = 16; + DescriptionString = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64"; + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; + } + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + Builder.defineMacro("__s390__"); + Builder.defineMacro("__s390x__"); + Builder.defineMacro("__zarch__"); + Builder.defineMacro("__LONG_DOUBLE_128__"); + } + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { + // FIXME: Implement. + Records = nullptr; + NumRecords = 0; + } - virtual void getGCCRegNames(const char *const *&Names, - unsigned &NumNames) const; - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { - // No aliases. - Aliases = 0; - NumAliases = 0; - } - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const; - virtual const char *getClobbers() const { - // FIXME: Is this really right? - return ""; - } - virtual BuiltinVaListKind getBuiltinVaListKind() const { - return TargetInfo::SystemZBuiltinVaList; - } - virtual bool setCPU(const std::string &Name) { - bool CPUKnown = llvm::StringSwitch<bool>(Name) - .Case("z10", true) - .Case("z196", true) - .Case("zEC12", true) - .Default(false); + void getGCCRegNames(const char *const *&Names, + unsigned &NumNames) const override; + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override { + // No aliases. + Aliases = nullptr; + NumAliases = 0; + } + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override; + const char *getClobbers() const override { + // FIXME: Is this really right? + return ""; + } + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::SystemZBuiltinVaList; + } + bool setCPU(const std::string &Name) override { + bool CPUKnown = llvm::StringSwitch<bool>(Name) + .Case("z10", true) + .Case("z196", true) + .Case("zEC12", true) + .Default(false); - // No need to store the CPU yet. There aren't any CPU-specific - // macros to define. - return CPUKnown; - } - }; + // No need to store the CPU yet. There aren't any CPU-specific + // macros to define. + return CPUKnown; + } +}; - const char *const SystemZTargetInfo::GCCRegNames[] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "f0", "f2", "f4", "f6", "f1", "f3", "f5", "f7", - "f8", "f10", "f12", "f14", "f9", "f11", "f13", "f15" - }; +const char *const SystemZTargetInfo::GCCRegNames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "f0", "f2", "f4", "f6", "f1", "f3", "f5", "f7", + "f8", "f10", "f12", "f14", "f9", "f11", "f13", "f15" +}; - void SystemZTargetInfo::getGCCRegNames(const char *const *&Names, - unsigned &NumNames) const { - Names = GCCRegNames; - NumNames = llvm::array_lengthof(GCCRegNames); - } +void SystemZTargetInfo::getGCCRegNames(const char *const *&Names, + unsigned &NumNames) const { + Names = GCCRegNames; + NumNames = llvm::array_lengthof(GCCRegNames); +} - bool SystemZTargetInfo:: - validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const { - switch (*Name) { - default: - return false; +bool SystemZTargetInfo:: +validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const { + switch (*Name) { + default: + return false; - case 'a': // Address register - case 'd': // Data register (equivalent to 'r') - case 'f': // Floating-point register - Info.setAllowsRegister(); - return true; + case 'a': // Address register + case 'd': // Data register (equivalent to 'r') + case 'f': // Floating-point register + Info.setAllowsRegister(); + return true; - case 'I': // Unsigned 8-bit constant - case 'J': // Unsigned 12-bit constant - case 'K': // Signed 16-bit constant - case 'L': // Signed 20-bit displacement (on all targets we support) - case 'M': // 0x7fffffff - return true; + case 'I': // Unsigned 8-bit constant + case 'J': // Unsigned 12-bit constant + case 'K': // Signed 16-bit constant + case 'L': // Signed 20-bit displacement (on all targets we support) + case 'M': // 0x7fffffff + return true; - case 'Q': // Memory with base and unsigned 12-bit displacement - case 'R': // Likewise, plus an index - case 'S': // Memory with base and signed 20-bit displacement - case 'T': // Likewise, plus an index - Info.setAllowsMemory(); - return true; - } + case 'Q': // Memory with base and unsigned 12-bit displacement + case 'R': // Likewise, plus an index + case 'S': // Memory with base and signed 20-bit displacement + case 'T': // Likewise, plus an index + Info.setAllowsMemory(); + return true; } } +} namespace { class MSP430TargetInfo : public TargetInfo { @@ -4720,45 +5128,44 @@ namespace { SuitableAlign = 16; SizeType = UnsignedInt; IntMaxType = SignedLongLong; - UIntMaxType = UnsignedLongLong; IntPtrType = SignedInt; PtrDiffType = SignedInt; SigAtomicType = SignedLong; - DescriptionString = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"; - } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + DescriptionString = "e-m:e-p:16:16-i32:16:32-n8:16"; + } + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { Builder.defineMacro("MSP430"); Builder.defineMacro("__MSP430__"); // FIXME: defines for different 'flavours' of MCU } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { - // FIXME: Implement. - Records = 0; + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { + // FIXME: Implement. + Records = nullptr; NumRecords = 0; } - virtual bool hasFeature(StringRef Feature) const { + bool hasFeature(StringRef Feature) const override { return Feature == "msp430"; } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const; - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override; + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override { // No aliases. - Aliases = 0; + Aliases = nullptr; NumAliases = 0; } - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const { + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override { // No target constraints for now. return false; } - virtual const char *getClobbers() const { + const char *getClobbers() const override { // FIXME: Is this really right? return ""; } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { // FIXME: implement return TargetInfo::CharPtrBuiltinVaList; } @@ -4808,7 +5215,6 @@ namespace { SuitableAlign = 32; SizeType = UnsignedInt; IntMaxType = SignedLong; - UIntMaxType = UnsignedLong; IntPtrType = SignedInt; PtrDiffType = SignedInt; FloatWidth = 32; @@ -4820,40 +5226,38 @@ namespace { FloatFormat = &llvm::APFloat::IEEEsingle; DoubleFormat = &llvm::APFloat::IEEEsingle; LongDoubleFormat = &llvm::APFloat::IEEEsingle; - DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-" - "i16:16:32-i32:32:32-i64:32:32-" - "f32:32:32-f64:32:32-v64:32:32-" - "v128:32:32-a0:0:32-n32"; + DescriptionString = "E-p:32:32-i8:8:32-i16:16:32-i64:32" + "-f64:32-v64:32-v128:32-a:0:32-n32"; AddrSpaceMap = &TCEOpenCLAddrSpaceMap; UseAddrSpaceMapMangling = true; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { DefineStd(Builder, "tce", Opts); Builder.defineMacro("__TCE__"); Builder.defineMacro("__TCE_V1__"); } - virtual bool hasFeature(StringRef Feature) const { + bool hasFeature(StringRef Feature) const override { return Feature == "tce"; } - - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const {} - virtual const char *getClobbers() const { + + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override {} + const char *getClobbers() const override { return ""; } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const {} - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const { + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override {} + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override{ return true; } - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const {} + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override {} }; } @@ -4886,21 +5290,57 @@ public: IsNan2008(false), IsSingleFloat(false), FloatABI(HardFloat), DspRev(NoDSP), HasMSA(false), HasFP64(false), ABI(ABIStr) {} - virtual const char *getABI() const { return ABI.c_str(); } - virtual bool setABI(const std::string &Name) = 0; - virtual bool setCPU(const std::string &Name) { + bool isNaN2008Default() const { + return CPU == "mips32r6" || CPU == "mips64r6"; + } + + bool isFP64Default() const { + return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64"; + } + + StringRef getABI() const override { return ABI; } + bool setCPU(const std::string &Name) override { + bool IsMips32 = getTriple().getArch() == llvm::Triple::mips || + getTriple().getArch() == llvm::Triple::mipsel; CPU = Name; - return true; + return llvm::StringSwitch<bool>(Name) + .Case("mips1", IsMips32) + .Case("mips2", IsMips32) + .Case("mips3", true) + .Case("mips4", true) + .Case("mips5", true) + .Case("mips32", IsMips32) + .Case("mips32r2", IsMips32) + .Case("mips32r6", IsMips32) + .Case("mips64", true) + .Case("mips64r2", true) + .Case("mips64r6", true) + .Case("octeon", true) + .Default(false); } - void getDefaultFeatures(llvm::StringMap<bool> &Features) const { + const std::string& getCPU() const { return CPU; } + void getDefaultFeatures(llvm::StringMap<bool> &Features) const override { + // The backend enables certain ABI's by default according to the + // architecture. + // Disable both possible defaults so that we don't end up with multiple + // ABI's selected and trigger an assertion. + Features["o32"] = false; + Features["n64"] = false; + Features[ABI] = true; - Features[CPU] = true; + if (CPU == "octeon") + Features["mips64r2"] = Features["cnmips"] = true; + else + Features[CPU] = true; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { - DefineStd(Builder, "mips", Opts); + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + Builder.defineMacro("__mips__"); Builder.defineMacro("_mips"); + if (Opts.GNUMode) + Builder.defineMacro("mips"); + Builder.defineMacro("__REGISTER_PREFIX__", ""); switch (FloatABI) { @@ -4953,22 +5393,22 @@ public: Builder.defineMacro("_MIPS_ARCH_" + StringRef(CPU).upper()); } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { Records = BuiltinInfo; NumRecords = clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin; } - virtual bool hasFeature(StringRef Feature) const { + bool hasFeature(StringRef Feature) const override { return llvm::StringSwitch<bool>(Feature) .Case("mips", true) .Case("fp64", HasFP64) .Default(false); } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const { + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override { static const char *const GCCRegNames[] = { // CPU register names // Must match second column of GCCRegAliases @@ -4996,17 +5436,17 @@ public: Names = GCCRegNames; NumNames = llvm::array_lengthof(GCCRegNames); } - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const = 0; - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const { + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override = 0; + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { switch (*Name) { default: return false; case 'r': // CPU registers. case 'd': // Equivalent to "r" unless generating MIPS16 code. - case 'y': // Equivalent to "r", backwards compatibility only. + case 'y': // Equivalent to "r", backward compatibility only. case 'f': // floating-point registers. case 'c': // $25 for indirect jumps case 'l': // lo register @@ -5019,20 +5459,20 @@ public: } } - virtual const char *getClobbers() const { + const char *getClobbers() const override { // FIXME: Implement! return ""; } - virtual bool handleTargetFeatures(std::vector<std::string> &Features, - DiagnosticsEngine &Diags) { + bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) override { IsMips16 = false; IsMicromips = false; - IsNan2008 = false; + IsNan2008 = isNaN2008Default(); IsSingleFloat = false; FloatABI = HardFloat; DspRev = NoDSP; - HasFP64 = ABI == "n32" || ABI == "n64" || ABI == "64"; + HasFP64 = isFP64Default(); for (std::vector<std::string>::iterator it = Features.begin(), ie = Features.end(); it != ie; ++it) { @@ -5056,6 +5496,8 @@ public: HasFP64 = false; else if (*it == "+nan2008") IsNan2008 = true; + else if (*it == "-nan2008") + IsNan2008 = false; } // Remove front-end specific options. @@ -5063,20 +5505,19 @@ public: std::find(Features.begin(), Features.end(), "+soft-float"); if (it != Features.end()) Features.erase(it); - it = std::find(Features.begin(), Features.end(), "+nan2008"); - if (it != Features.end()) - Features.erase(it); setDescriptionString(); return true; } - virtual int getEHDataRegisterNumber(unsigned RegNo) const { + int getEHDataRegisterNumber(unsigned RegNo) const override { if (RegNo == 0) return 4; if (RegNo == 1) return 5; return -1; } + + bool isCLZForZeroUndef() const override { return false; } }; const Builtin::Info MipsTargetInfoBase::BuiltinInfo[] = { @@ -5089,25 +5530,31 @@ const Builtin::Info MipsTargetInfoBase::BuiltinInfo[] = { class Mips32TargetInfoBase : public MipsTargetInfoBase { public: Mips32TargetInfoBase(const llvm::Triple &Triple) - : MipsTargetInfoBase(Triple, "o32", "mips32") { + : MipsTargetInfoBase(Triple, "o32", "mips32r2") { SizeType = UnsignedInt; PtrDiffType = SignedInt; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; } - virtual bool setABI(const std::string &Name) { - if ((Name == "o32") || (Name == "eabi")) { + bool setABI(const std::string &Name) override { + if (Name == "o32" || Name == "eabi") { ABI = Name; return true; - } else if (Name == "32") { - ABI = "o32"; - return true; - } else - return false; + } + return false; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { MipsTargetInfoBase::getTargetDefines(Opts, Builder); + Builder.defineMacro("__mips", "32"); + Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS32"); + + const std::string& CPUStr = getCPU(); + if (CPUStr == "mips32") + Builder.defineMacro("__mips_isa_rev", "1"); + else if (CPUStr == "mips32r2") + Builder.defineMacro("__mips_isa_rev", "2"); + if (ABI == "o32") { Builder.defineMacro("__mips_o32"); Builder.defineMacro("_ABIO32", "1"); @@ -5118,8 +5565,8 @@ public: else llvm_unreachable("Invalid ABI for Mips32."); } - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override { static const TargetInfo::GCCRegAlias GCCRegAliases[] = { { { "at" }, "$1" }, { { "v0" }, "$2" }, @@ -5159,17 +5606,16 @@ public: }; class Mips32EBTargetInfo : public Mips32TargetInfoBase { - virtual void setDescriptionString() { - DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64"; + void setDescriptionString() override { + DescriptionString = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"; } public: Mips32EBTargetInfo(const llvm::Triple &Triple) : Mips32TargetInfoBase(Triple) { } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { DefineStd(Builder, "MIPSEB", Opts); Builder.defineMacro("_MIPSEB"); Mips32TargetInfoBase::getTargetDefines(Opts, Builder); @@ -5177,9 +5623,8 @@ public: }; class Mips32ELTargetInfo : public Mips32TargetInfoBase { - virtual void setDescriptionString() { - DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64"; + void setDescriptionString() override { + DescriptionString = "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"; } public: @@ -5187,8 +5632,8 @@ public: : Mips32TargetInfoBase(Triple) { BigEndian = false; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { DefineStd(Builder, "MIPSEL", Opts); Builder.defineMacro("_MIPSEL"); Mips32TargetInfoBase::getTargetDefines(Opts, Builder); @@ -5198,39 +5643,60 @@ public: class Mips64TargetInfoBase : public MipsTargetInfoBase { public: Mips64TargetInfoBase(const llvm::Triple &Triple) - : MipsTargetInfoBase(Triple, "n64", "mips64") { - LongWidth = LongAlign = 64; - PointerWidth = PointerAlign = 64; + : MipsTargetInfoBase(Triple, "n64", "mips64r2") { LongDoubleWidth = LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::IEEEquad; if (getTriple().getOS() == llvm::Triple::FreeBSD) { LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble; } + setN64ABITypes(); SuitableAlign = 128; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; } - virtual bool setABI(const std::string &Name) { + + void setN64ABITypes() { + LongWidth = LongAlign = 64; + PointerWidth = PointerAlign = 64; + SizeType = UnsignedLong; + PtrDiffType = SignedLong; + } + + void setN32ABITypes() { + LongWidth = LongAlign = 32; + PointerWidth = PointerAlign = 32; + SizeType = UnsignedInt; + PtrDiffType = SignedInt; + } + + bool setABI(const std::string &Name) override { if (Name == "n32") { - LongWidth = LongAlign = 32; - PointerWidth = PointerAlign = 32; + setN32ABITypes(); ABI = Name; return true; - } else if (Name == "n64") { + } + if (Name == "n64") { + setN64ABITypes(); ABI = Name; return true; - } else if (Name == "64") { - ABI = "n64"; - return true; - } else - return false; + } + return false; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { MipsTargetInfoBase::getTargetDefines(Opts, Builder); + Builder.defineMacro("__mips", "64"); Builder.defineMacro("__mips64"); Builder.defineMacro("__mips64__"); + Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS64"); + + const std::string& CPUStr = getCPU(); + if (CPUStr == "mips64") + Builder.defineMacro("__mips_isa_rev", "1"); + else if (CPUStr == "mips64r2") + Builder.defineMacro("__mips_isa_rev", "2"); if (ABI == "n32") { Builder.defineMacro("__mips_n32"); @@ -5245,8 +5711,8 @@ public: else llvm_unreachable("Invalid ABI for Mips64."); } - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override { static const TargetInfo::GCCRegAlias GCCRegAliases[] = { { { "at" }, "$1" }, { { "v0" }, "$2" }, @@ -5283,26 +5749,24 @@ public: Aliases = GCCRegAliases; NumAliases = llvm::array_lengthof(GCCRegAliases); } + + bool hasInt128Type() const override { return true; } }; class Mips64EBTargetInfo : public Mips64TargetInfoBase { - virtual void setDescriptionString() { + void setDescriptionString() override { if (ABI == "n32") - DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-f128:128:128-" - "v64:64:64-n32:64-S128"; + DescriptionString = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128"; else - DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-f128:128:128-" - "v64:64:64-n32:64-S128"; + DescriptionString = "E-m:m-i8:8:32-i16:16:32-i64:64-n32:64-S128"; } public: Mips64EBTargetInfo(const llvm::Triple &Triple) : Mips64TargetInfoBase(Triple) {} - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { DefineStd(Builder, "MIPSEB", Opts); Builder.defineMacro("_MIPSEB"); Mips64TargetInfoBase::getTargetDefines(Opts, Builder); @@ -5310,15 +5774,11 @@ public: }; class Mips64ELTargetInfo : public Mips64TargetInfoBase { - virtual void setDescriptionString() { + void setDescriptionString() override { if (ABI == "n32") - DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-f128:128:128" - "-v64:64:64-n32:64-S128"; + DescriptionString = "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128"; else - DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-f128:128:128-" - "v64:64:64-n32:64-S128"; + DescriptionString = "e-m:m-i8:8:32-i16:16:32-i64:64-n32:64-S128"; } public: Mips64ELTargetInfo(const llvm::Triple &Triple) @@ -5326,8 +5786,8 @@ public: // Default ABI is n64. BigEndian = false; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { DefineStd(Builder, "MIPSEL", Opts); Builder.defineMacro("_MIPSEL"); Mips64TargetInfoBase::getTargetDefines(Opts, Builder); @@ -5346,7 +5806,6 @@ public: this->PointerAlign = 32; this->PointerWidth = 32; this->IntMaxType = TargetInfo::SignedLongLong; - this->UIntMaxType = TargetInfo::UnsignedLongLong; this->Int64Type = TargetInfo::SignedLongLong; this->DoubleAlign = 64; this->LongDoubleWidth = 64; @@ -5355,54 +5814,50 @@ public: this->PtrDiffType = TargetInfo::SignedInt; this->IntPtrType = TargetInfo::SignedInt; this->RegParmMax = 0; // Disallow regparm - DescriptionString = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-" - "f32:32:32-f64:64:64-p:32:32:32-v128:32:32"; } - void getDefaultFeatures(llvm::StringMap<bool> &Features) const { + void getDefaultFeatures(llvm::StringMap<bool> &Features) const override { } - virtual void getArchDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getArchDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__le32__"); Builder.defineMacro("__pnacl__"); } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { - Builder.defineMacro("__LITTLE_ENDIAN__"); + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { getArchDefines(Opts, Builder); } - virtual bool hasFeature(StringRef Feature) const { + bool hasFeature(StringRef Feature) const override { return Feature == "pnacl"; } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::PNaClABIBuiltinVaList; } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const; - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const; - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const { + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override; + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override; + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { return false; } - virtual const char *getClobbers() const { + const char *getClobbers() const override { return ""; } }; void PNaClTargetInfo::getGCCRegNames(const char * const *&Names, unsigned &NumNames) const { - Names = NULL; + Names = nullptr; NumNames = 0; } void PNaClTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, unsigned &NumAliases) const { - Aliases = NULL; + Aliases = nullptr; NumAliases = 0; } } // end anonymous namespace. @@ -5432,28 +5887,28 @@ namespace { // These must be defined in sorted order! NoAsmVariants = true; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { DefineStd(Builder, "SPIR", Opts); } - virtual bool hasFeature(StringRef Feature) const { + bool hasFeature(StringRef Feature) const override { return Feature == "spir"; } - - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const {} - virtual const char *getClobbers() const { + + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override {} + const char *getClobbers() const override { return ""; } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const {} - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const { + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override {} + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override { return true; } - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const {} - virtual BuiltinVaListKind getBuiltinVaListKind() const { + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override {} + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; } }; @@ -5466,13 +5921,11 @@ namespace { SizeType = TargetInfo::UnsignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt; DescriptionString - = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-" - "f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-" - "v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-" - "v512:512:512-v1024:1024:1024"; + = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-" + "v96:128-v192:256-v256:256-v512:512-v1024:1024"; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { DefineStd(Builder, "SPIR32", Opts); } }; @@ -5483,14 +5936,11 @@ namespace { PointerWidth = PointerAlign = 64; SizeType = TargetInfo::UnsignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong; - DescriptionString - = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-" - "f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-" - "v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-" - "v512:512:512-v1024:1024:1024"; + DescriptionString = "e-i64:64-v16:16-v24:32-v32:32-v48:64-" + "v96:128-v192:256-v256:256-v512:512-v1024:1024"; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { DefineStd(Builder, "SPIR64", Opts); } }; @@ -5512,27 +5962,26 @@ public: WCharType = UnsignedChar; WIntType = UnsignedInt; UseZeroLengthBitfieldAlignment = true; - DescriptionString = "e-p:32:32:32-a0:0:32-n32" - "-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32" - "-f16:16:32-f32:32:32-f64:32:32"; + DescriptionString = "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32" + "-f64:32-a:0:32-n32"; } - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { Builder.defineMacro("__XS1B__"); } - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { Records = BuiltinInfo; NumRecords = clang::XCore::LastTSBuiltin-Builtin::FirstTSBuiltin; } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; } - virtual const char *getClobbers() const { + const char *getClobbers() const override { return ""; } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const { + void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const override { static const char * const GCCRegNames[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "cp", "dp", "sp", "lr" @@ -5540,15 +5989,19 @@ public: Names = GCCRegNames; NumNames = llvm::array_lengthof(GCCRegNames); } - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { - Aliases = NULL; + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override { + Aliases = nullptr; NumAliases = 0; } - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const { + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { return false; } + int getEHDataRegisterNumber(unsigned RegNo) const override { + // R0=ExceptionPointerRegister R1=ExceptionSelectorRegister + return (RegNo < 2)? RegNo : -1; + } }; const Builtin::Info XCoreTargetInfo::BuiltinInfo[] = { @@ -5569,7 +6022,7 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { switch (Triple.getArch()) { default: - return NULL; + return nullptr; case llvm::Triple::xcore: return new XCoreTargetInfo(Triple); @@ -5578,35 +6031,85 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { return new HexagonTargetInfo(Triple); case llvm::Triple::aarch64: + case llvm::Triple::arm64: + if (Triple.isOSDarwin()) + return new DarwinAArch64TargetInfo(Triple); + switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<AArch64TargetInfo>(Triple); + return new LinuxTargetInfo<AArch64leTargetInfo>(Triple); + case llvm::Triple::NetBSD: + return new NetBSDTargetInfo<AArch64leTargetInfo>(Triple); default: - return new AArch64TargetInfo(Triple); + return new AArch64leTargetInfo(Triple); + } + + case llvm::Triple::aarch64_be: + case llvm::Triple::arm64_be: + switch (os) { + case llvm::Triple::Linux: + return new LinuxTargetInfo<AArch64beTargetInfo>(Triple); + case llvm::Triple::NetBSD: + return new NetBSDTargetInfo<AArch64beTargetInfo>(Triple); + default: + return new AArch64beTargetInfo(Triple); } case llvm::Triple::arm: case llvm::Triple::thumb: + if (Triple.isOSBinFormatMachO()) + return new DarwinARMTargetInfo(Triple); + + switch (os) { + case llvm::Triple::Linux: + return new LinuxTargetInfo<ARMleTargetInfo>(Triple); + case llvm::Triple::FreeBSD: + return new FreeBSDTargetInfo<ARMleTargetInfo>(Triple); + case llvm::Triple::NetBSD: + return new NetBSDTargetInfo<ARMleTargetInfo>(Triple); + case llvm::Triple::OpenBSD: + return new OpenBSDTargetInfo<ARMleTargetInfo>(Triple); + case llvm::Triple::Bitrig: + return new BitrigTargetInfo<ARMleTargetInfo>(Triple); + case llvm::Triple::RTEMS: + return new RTEMSTargetInfo<ARMleTargetInfo>(Triple); + case llvm::Triple::NaCl: + return new NaClTargetInfo<ARMleTargetInfo>(Triple); + case llvm::Triple::Win32: + switch (Triple.getEnvironment()) { + default: + return new ARMleTargetInfo(Triple); + case llvm::Triple::Itanium: + return new ItaniumWindowsARMleTargetInfo(Triple); + case llvm::Triple::MSVC: + return new MicrosoftARMleTargetInfo(Triple); + } + default: + return new ARMleTargetInfo(Triple); + } + + case llvm::Triple::armeb: + case llvm::Triple::thumbeb: if (Triple.isOSDarwin()) return new DarwinARMTargetInfo(Triple); switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<ARMTargetInfo>(Triple); + return new LinuxTargetInfo<ARMbeTargetInfo>(Triple); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<ARMTargetInfo>(Triple); + return new FreeBSDTargetInfo<ARMbeTargetInfo>(Triple); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<ARMTargetInfo>(Triple); + return new NetBSDTargetInfo<ARMbeTargetInfo>(Triple); case llvm::Triple::OpenBSD: - return new OpenBSDTargetInfo<ARMTargetInfo>(Triple); + return new OpenBSDTargetInfo<ARMbeTargetInfo>(Triple); case llvm::Triple::Bitrig: - return new BitrigTargetInfo<ARMTargetInfo>(Triple); + return new BitrigTargetInfo<ARMbeTargetInfo>(Triple); case llvm::Triple::RTEMS: - return new RTEMSTargetInfo<ARMTargetInfo>(Triple); + return new RTEMSTargetInfo<ARMbeTargetInfo>(Triple); case llvm::Triple::NaCl: - return new NaClTargetInfo<ARMTargetInfo>(Triple); + return new NaClTargetInfo<ARMbeTargetInfo>(Triple); default: - return new ARMTargetInfo(Triple); + return new ARMbeTargetInfo(Triple); } case llvm::Triple::msp430: @@ -5679,7 +6182,7 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { case llvm::Triple::NaCl: return new NaClTargetInfo<PNaClTargetInfo>(Triple); default: - return NULL; + return nullptr; } case llvm::Triple::ppc: @@ -5804,12 +6307,19 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { return new MinixTargetInfo<X86_32TargetInfo>(Triple); case llvm::Triple::Solaris: return new SolarisTargetInfo<X86_32TargetInfo>(Triple); - case llvm::Triple::Cygwin: - return new CygwinX86_32TargetInfo(Triple); - case llvm::Triple::MinGW32: - return new MinGWX86_32TargetInfo(Triple); - case llvm::Triple::Win32: - return new VisualStudioWindowsX86_32TargetInfo(Triple); + case llvm::Triple::Win32: { + switch (Triple.getEnvironment()) { + default: + return new X86_32TargetInfo(Triple); + case llvm::Triple::Cygnus: + return new CygwinX86_32TargetInfo(Triple); + case llvm::Triple::GNU: + return new MinGWX86_32TargetInfo(Triple); + case llvm::Triple::Itanium: + case llvm::Triple::MSVC: + return new MicrosoftX86_32TargetInfo(Triple); + } + } case llvm::Triple::Haiku: return new HaikuX86_32TargetInfo(Triple); case llvm::Triple::RTEMS: @@ -5821,7 +6331,7 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { } case llvm::Triple::x86_64: - if (Triple.isOSDarwin() || Triple.getEnvironment() == llvm::Triple::MachO) + if (Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) return new DarwinX86_64TargetInfo(Triple); switch (os) { @@ -5843,10 +6353,16 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { return new KFreeBSDTargetInfo<X86_64TargetInfo>(Triple); case llvm::Triple::Solaris: return new SolarisTargetInfo<X86_64TargetInfo>(Triple); - case llvm::Triple::MinGW32: - return new MinGWX86_64TargetInfo(Triple); - case llvm::Triple::Win32: // This is what Triple.h supports now. - return new VisualStudioWindowsX86_64TargetInfo(Triple); + case llvm::Triple::Win32: { + switch (Triple.getEnvironment()) { + default: + return new X86_64TargetInfo(Triple); + case llvm::Triple::GNU: + return new MinGWX86_64TargetInfo(Triple); + case llvm::Triple::MSVC: + return new MicrosoftX86_64TargetInfo(Triple); + } + } case llvm::Triple::NaCl: return new NaClTargetInfo<X86_64TargetInfo>(Triple); default: @@ -5856,13 +6372,13 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { case llvm::Triple::spir: { if (Triple.getOS() != llvm::Triple::UnknownOS || Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) - return NULL; + return nullptr; return new SPIR32TargetInfo(Triple); } case llvm::Triple::spir64: { if (Triple.getOS() != llvm::Triple::UnknownOS || Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) - return NULL; + return nullptr; return new SPIR64TargetInfo(Triple); } } @@ -5870,40 +6386,35 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { /// CreateTargetInfo - Return the target info object for the specified target /// triple. -TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, - TargetOptions *Opts) { +TargetInfo * +TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, + const std::shared_ptr<TargetOptions> &Opts) { llvm::Triple Triple(Opts->Triple); // Construct the target - OwningPtr<TargetInfo> Target(AllocateTarget(Triple)); + std::unique_ptr<TargetInfo> Target(AllocateTarget(Triple)); if (!Target) { Diags.Report(diag::err_target_unknown_triple) << Triple.str(); - return 0; + return nullptr; } - Target->setTargetOpts(Opts); + Target->TargetOpts = Opts; // Set the target CPU if specified. if (!Opts->CPU.empty() && !Target->setCPU(Opts->CPU)) { Diags.Report(diag::err_target_unknown_cpu) << Opts->CPU; - return 0; + return nullptr; } // Set the target ABI if specified. if (!Opts->ABI.empty() && !Target->setABI(Opts->ABI)) { Diags.Report(diag::err_target_unknown_abi) << Opts->ABI; - return 0; - } - - // Set the target C++ ABI. - if (!Opts->CXXABI.empty() && !Target->setCXXABI(Opts->CXXABI)) { - Diags.Report(diag::err_target_unknown_cxxabi) << Opts->CXXABI; - return 0; + return nullptr; } // Set the fp math unit. if (!Opts->FPMath.empty() && !Target->setFPMath(Opts->FPMath)) { Diags.Report(diag::err_target_unknown_fpmath) << Opts->FPMath; - return 0; + return nullptr; } // Compute the default target features, we need the target to handle this @@ -5929,7 +6440,7 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, ie = Features.end(); it != ie; ++it) Opts->Features.push_back((it->second ? "+" : "-") + it->first().str()); if (!Target->handleTargetFeatures(Opts->Features, Diags)) - return 0; + return nullptr; - return Target.take(); + return Target.release(); } diff --git a/contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp b/contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp index 6ce076e..3b1f8fe 100644 --- a/contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp @@ -12,27 +12,37 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/TokenKinds.h" -#include <cassert> +#include "llvm/Support/ErrorHandling.h" using namespace clang; static const char * const TokNames[] = { #define TOK(X) #X, #define KEYWORD(X,Y) #X, #include "clang/Basic/TokenKinds.def" - 0 + nullptr }; -const char *tok::getTokenName(enum TokenKind Kind) { - assert(Kind < tok::NUM_TOKENS); - return TokNames[Kind]; +const char *tok::getTokenName(TokenKind Kind) { + if (Kind < tok::NUM_TOKENS) + return TokNames[Kind]; + llvm_unreachable("unknown TokenKind"); + return nullptr; } -const char *tok::getTokenSimpleSpelling(enum TokenKind Kind) { +const char *tok::getPunctuatorSpelling(TokenKind Kind) { switch (Kind) { #define PUNCTUATOR(X,Y) case X: return Y; #include "clang/Basic/TokenKinds.def" default: break; } + return nullptr; +} - return 0; +const char *tok::getKeywordSpelling(TokenKind Kind) { + switch (Kind) { +#define KEYWORD(X,Y) case kw_ ## X: return #X; +#include "clang/Basic/TokenKinds.def" + default: break; + } + return nullptr; } diff --git a/contrib/llvm/tools/clang/lib/Basic/Version.cpp b/contrib/llvm/tools/clang/lib/Basic/Version.cpp index bc09880..2b577d6 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Version.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Version.cpp @@ -13,7 +13,7 @@ #include "clang/Basic/Version.h" #include "clang/Basic/LLVM.h" -#include "llvm/Config/config.h" +#include "clang/Config/config.h" #include "llvm/Support/raw_ostream.h" #include <cstdlib> #include <cstring> @@ -36,7 +36,7 @@ std::string getClangRepositoryPath() { // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us // pick up a tag in an SVN export, for example. - StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_34/dot1-final/lib/Basic/Version.cpp $"); + StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_350/final/lib/Basic/Version.cpp $"); if (URL.empty()) { URL = SVNRepository.slice(SVNRepository.find(':'), SVNRepository.find("/lib/Basic")); @@ -102,11 +102,11 @@ std::string getClangFullRepositoryVersion() { OS << Revision; } OS << ')'; - } + } // Support LLVM in a separate repository. std::string LLVMRev = getLLVMRevision(); if (!LLVMRev.empty() && LLVMRev != Revision) { - OS << " ("; + OS << " ("; std::string LLVMRepo = getLLVMRepositoryPath(); if (!LLVMRepo.empty()) OS << LLVMRepo << ' '; @@ -116,19 +116,23 @@ std::string getClangFullRepositoryVersion() { } std::string getClangFullVersion() { + return getClangToolFullVersion("clang"); +} + +std::string getClangToolFullVersion(StringRef ToolName) { std::string buf; llvm::raw_string_ostream OS(buf); #ifdef CLANG_VENDOR OS << CLANG_VENDOR; #endif - OS << "clang version " CLANG_VERSION_STRING " " + OS << ToolName << " version " CLANG_VERSION_STRING " " << getClangFullRepositoryVersion(); #ifdef CLANG_VENDOR_SUFFIX OS << CLANG_VENDOR_SUFFIX; #elif defined(CLANG_VENDOR) // If vendor supplied, include the base LLVM version as well. - OS << " (based on LLVM " << PACKAGE_VERSION << ")"; + OS << " (based on " << BACKEND_PACKAGE_STRING << ")"; #endif return OS.str(); diff --git a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp new file mode 100644 index 0000000..a5c83b8 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp @@ -0,0 +1,1209 @@ +//===- VirtualFileSystem.cpp - Virtual File System Layer --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This file implements the VirtualFileSystem interface. +//===----------------------------------------------------------------------===// + +#include "clang/Basic/VirtualFileSystem.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/YAMLParser.h" +#include <atomic> +#include <memory> + +using namespace clang; +using namespace clang::vfs; +using namespace llvm; +using llvm::sys::fs::file_status; +using llvm::sys::fs::file_type; +using llvm::sys::fs::perms; +using llvm::sys::fs::UniqueID; + +Status::Status(const file_status &Status) + : UID(Status.getUniqueID()), MTime(Status.getLastModificationTime()), + User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()), + Type(Status.type()), Perms(Status.permissions()), IsVFSMapped(false) {} + +Status::Status(StringRef Name, StringRef ExternalName, UniqueID UID, + sys::TimeValue MTime, uint32_t User, uint32_t Group, + uint64_t Size, file_type Type, perms Perms) + : Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size), + Type(Type), Perms(Perms), IsVFSMapped(false) {} + +bool Status::equivalent(const Status &Other) const { + return getUniqueID() == Other.getUniqueID(); +} +bool Status::isDirectory() const { + return Type == file_type::directory_file; +} +bool Status::isRegularFile() const { + return Type == file_type::regular_file; +} +bool Status::isOther() const { + return exists() && !isRegularFile() && !isDirectory() && !isSymlink(); +} +bool Status::isSymlink() const { + return Type == file_type::symlink_file; +} +bool Status::isStatusKnown() const { + return Type != file_type::status_error; +} +bool Status::exists() const { + return isStatusKnown() && Type != file_type::file_not_found; +} + +File::~File() {} + +FileSystem::~FileSystem() {} + +std::error_code FileSystem::getBufferForFile( + const llvm::Twine &Name, std::unique_ptr<MemoryBuffer> &Result, + int64_t FileSize, bool RequiresNullTerminator, bool IsVolatile) { + std::unique_ptr<File> F; + if (std::error_code EC = openFileForRead(Name, F)) + return EC; + + std::error_code EC = + F->getBuffer(Name, Result, FileSize, RequiresNullTerminator, IsVolatile); + return EC; +} + +//===-----------------------------------------------------------------------===/ +// RealFileSystem implementation +//===-----------------------------------------------------------------------===/ + +namespace { +/// \brief Wrapper around a raw file descriptor. +class RealFile : public File { + int FD; + Status S; + friend class RealFileSystem; + RealFile(int FD) : FD(FD) { + assert(FD >= 0 && "Invalid or inactive file descriptor"); + } + +public: + ~RealFile(); + ErrorOr<Status> status() override; + std::error_code getBuffer(const Twine &Name, + std::unique_ptr<MemoryBuffer> &Result, + int64_t FileSize = -1, + bool RequiresNullTerminator = true, + bool IsVolatile = false) override; + std::error_code close() override; + void setName(StringRef Name) override; +}; +} // end anonymous namespace +RealFile::~RealFile() { close(); } + +ErrorOr<Status> RealFile::status() { + assert(FD != -1 && "cannot stat closed file"); + if (!S.isStatusKnown()) { + file_status RealStatus; + if (std::error_code EC = sys::fs::status(FD, RealStatus)) + return EC; + Status NewS(RealStatus); + NewS.setName(S.getName()); + S = std::move(NewS); + } + return S; +} + +std::error_code RealFile::getBuffer(const Twine &Name, + std::unique_ptr<MemoryBuffer> &Result, + int64_t FileSize, + bool RequiresNullTerminator, + bool IsVolatile) { + assert(FD != -1 && "cannot get buffer for closed file"); + ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = + MemoryBuffer::getOpenFile(FD, Name.str().c_str(), FileSize, + RequiresNullTerminator, IsVolatile); + if (std::error_code EC = BufferOrErr.getError()) + return EC; + Result = std::move(BufferOrErr.get()); + return std::error_code(); +} + +// FIXME: This is terrible, we need this for ::close. +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include <unistd.h> +#include <sys/uio.h> +#else +#include <io.h> +#ifndef S_ISFIFO +#define S_ISFIFO(x) (0) +#endif +#endif +std::error_code RealFile::close() { + if (::close(FD)) + return std::error_code(errno, std::generic_category()); + FD = -1; + return std::error_code(); +} + +void RealFile::setName(StringRef Name) { + S.setName(Name); +} + +namespace { +/// \brief The file system according to your operating system. +class RealFileSystem : public FileSystem { +public: + ErrorOr<Status> status(const Twine &Path) override; + std::error_code openFileForRead(const Twine &Path, + std::unique_ptr<File> &Result) override; + directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; +}; +} // end anonymous namespace + +ErrorOr<Status> RealFileSystem::status(const Twine &Path) { + sys::fs::file_status RealStatus; + if (std::error_code EC = sys::fs::status(Path, RealStatus)) + return EC; + Status Result(RealStatus); + Result.setName(Path.str()); + return Result; +} + +std::error_code RealFileSystem::openFileForRead(const Twine &Name, + std::unique_ptr<File> &Result) { + int FD; + if (std::error_code EC = sys::fs::openFileForRead(Name, FD)) + return EC; + Result.reset(new RealFile(FD)); + Result->setName(Name.str()); + return std::error_code(); +} + +IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() { + static IntrusiveRefCntPtr<FileSystem> FS = new RealFileSystem(); + return FS; +} + +namespace { +class RealFSDirIter : public clang::vfs::detail::DirIterImpl { + std::string Path; + llvm::sys::fs::directory_iterator Iter; +public: + RealFSDirIter(const Twine &_Path, std::error_code &EC) + : Path(_Path.str()), Iter(Path, EC) { + if (!EC && Iter != llvm::sys::fs::directory_iterator()) { + llvm::sys::fs::file_status S; + EC = Iter->status(S); + if (!EC) { + CurrentEntry = Status(S); + CurrentEntry.setName(Iter->path()); + } + } + } + + std::error_code increment() override { + std::error_code EC; + Iter.increment(EC); + if (EC) { + return EC; + } else if (Iter == llvm::sys::fs::directory_iterator()) { + CurrentEntry = Status(); + } else { + llvm::sys::fs::file_status S; + EC = Iter->status(S); + CurrentEntry = Status(S); + CurrentEntry.setName(Iter->path()); + } + return EC; + } +}; +} + +directory_iterator RealFileSystem::dir_begin(const Twine &Dir, + std::error_code &EC) { + return directory_iterator(std::make_shared<RealFSDirIter>(Dir, EC)); +} + +//===-----------------------------------------------------------------------===/ +// OverlayFileSystem implementation +//===-----------------------------------------------------------------------===/ +OverlayFileSystem::OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> BaseFS) { + pushOverlay(BaseFS); +} + +void OverlayFileSystem::pushOverlay(IntrusiveRefCntPtr<FileSystem> FS) { + FSList.push_back(FS); +} + +ErrorOr<Status> OverlayFileSystem::status(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { + ErrorOr<Status> Status = (*I)->status(Path); + if (Status || Status.getError() != llvm::errc::no_such_file_or_directory) + return Status; + } + return make_error_code(llvm::errc::no_such_file_or_directory); +} + +std::error_code +OverlayFileSystem::openFileForRead(const llvm::Twine &Path, + std::unique_ptr<File> &Result) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { + std::error_code EC = (*I)->openFileForRead(Path, Result); + if (!EC || EC != llvm::errc::no_such_file_or_directory) + return EC; + } + return make_error_code(llvm::errc::no_such_file_or_directory); +} + +clang::vfs::detail::DirIterImpl::~DirIterImpl() { } + +namespace { +class OverlayFSDirIterImpl : public clang::vfs::detail::DirIterImpl { + OverlayFileSystem &Overlays; + std::string Path; + OverlayFileSystem::iterator CurrentFS; + directory_iterator CurrentDirIter; + llvm::StringSet<> SeenNames; + + std::error_code incrementFS() { + assert(CurrentFS != Overlays.overlays_end() && "incrementing past end"); + ++CurrentFS; + for (auto E = Overlays.overlays_end(); CurrentFS != E; ++CurrentFS) { + std::error_code EC; + CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC); + if (EC && EC != errc::no_such_file_or_directory) + return EC; + if (CurrentDirIter != directory_iterator()) + break; // found + } + return std::error_code(); + } + + std::error_code incrementDirIter(bool IsFirstTime) { + assert((IsFirstTime || CurrentDirIter != directory_iterator()) && + "incrementing past end"); + std::error_code EC; + if (!IsFirstTime) + CurrentDirIter.increment(EC); + if (!EC && CurrentDirIter == directory_iterator()) + EC = incrementFS(); + return EC; + } + + std::error_code incrementImpl(bool IsFirstTime) { + while (true) { + std::error_code EC = incrementDirIter(IsFirstTime); + if (EC || CurrentDirIter == directory_iterator()) { + CurrentEntry = Status(); + return EC; + } + CurrentEntry = *CurrentDirIter; + StringRef Name = llvm::sys::path::filename(CurrentEntry.getName()); + if (SeenNames.insert(Name)) + return EC; // name not seen before + } + llvm_unreachable("returned above"); + } + +public: + OverlayFSDirIterImpl(const Twine &Path, OverlayFileSystem &FS, + std::error_code &EC) + : Overlays(FS), Path(Path.str()), CurrentFS(Overlays.overlays_begin()) { + CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC); + EC = incrementImpl(true); + } + + std::error_code increment() override { return incrementImpl(false); } +}; +} // end anonymous namespace + +directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir, + std::error_code &EC) { + return directory_iterator( + std::make_shared<OverlayFSDirIterImpl>(Dir, *this, EC)); +} + +//===-----------------------------------------------------------------------===/ +// VFSFromYAML implementation +//===-----------------------------------------------------------------------===/ + +// Allow DenseMap<StringRef, ...>. This is useful below because we know all the +// strings are literals and will outlive the map, and there is no reason to +// store them. +namespace llvm { + template<> + struct DenseMapInfo<StringRef> { + // This assumes that "" will never be a valid key. + static inline StringRef getEmptyKey() { return StringRef(""); } + static inline StringRef getTombstoneKey() { return StringRef(); } + static unsigned getHashValue(StringRef Val) { return HashString(Val); } + static bool isEqual(StringRef LHS, StringRef RHS) { return LHS == RHS; } + }; +} + +namespace { + +enum EntryKind { + EK_Directory, + EK_File +}; + +/// \brief A single file or directory in the VFS. +class Entry { + EntryKind Kind; + std::string Name; + +public: + virtual ~Entry(); + Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {} + StringRef getName() const { return Name; } + EntryKind getKind() const { return Kind; } +}; + +class DirectoryEntry : public Entry { + std::vector<Entry *> Contents; + Status S; + +public: + virtual ~DirectoryEntry(); + DirectoryEntry(StringRef Name, std::vector<Entry *> Contents, Status S) + : Entry(EK_Directory, Name), Contents(std::move(Contents)), + S(std::move(S)) {} + Status getStatus() { return S; } + typedef std::vector<Entry *>::iterator iterator; + iterator contents_begin() { return Contents.begin(); } + iterator contents_end() { return Contents.end(); } + static bool classof(const Entry *E) { return E->getKind() == EK_Directory; } +}; + +class FileEntry : public Entry { +public: + enum NameKind { + NK_NotSet, + NK_External, + NK_Virtual + }; +private: + std::string ExternalContentsPath; + NameKind UseName; +public: + FileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName) + : Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath), + UseName(UseName) {} + StringRef getExternalContentsPath() const { return ExternalContentsPath; } + /// \brief whether to use the external path as the name for this file. + bool useExternalName(bool GlobalUseExternalName) const { + return UseName == NK_NotSet ? GlobalUseExternalName + : (UseName == NK_External); + } + static bool classof(const Entry *E) { return E->getKind() == EK_File; } +}; + +class VFSFromYAML; + +class VFSFromYamlDirIterImpl : public clang::vfs::detail::DirIterImpl { + std::string Dir; + VFSFromYAML &FS; + DirectoryEntry::iterator Current, End; +public: + VFSFromYamlDirIterImpl(const Twine &Path, VFSFromYAML &FS, + DirectoryEntry::iterator Begin, + DirectoryEntry::iterator End, std::error_code &EC); + std::error_code increment() override; +}; + +/// \brief A virtual file system parsed from a YAML file. +/// +/// Currently, this class allows creating virtual directories and mapping +/// virtual file paths to existing external files, available in \c ExternalFS. +/// +/// The basic structure of the parsed file is: +/// \verbatim +/// { +/// 'version': <version number>, +/// <optional configuration> +/// 'roots': [ +/// <directory entries> +/// ] +/// } +/// \endverbatim +/// +/// All configuration options are optional. +/// 'case-sensitive': <boolean, default=true> +/// 'use-external-names': <boolean, default=true> +/// +/// Virtual directories are represented as +/// \verbatim +/// { +/// 'type': 'directory', +/// 'name': <string>, +/// 'contents': [ <file or directory entries> ] +/// } +/// \endverbatim +/// +/// The default attributes for virtual directories are: +/// \verbatim +/// MTime = now() when created +/// Perms = 0777 +/// User = Group = 0 +/// Size = 0 +/// UniqueID = unspecified unique value +/// \endverbatim +/// +/// Re-mapped files are represented as +/// \verbatim +/// { +/// 'type': 'file', +/// 'name': <string>, +/// 'use-external-name': <boolean> # Optional +/// 'external-contents': <path to external file>) +/// } +/// \endverbatim +/// +/// and inherit their attributes from the external contents. +/// +/// In both cases, the 'name' field may contain multiple path components (e.g. +/// /path/to/file). However, any directory that contains more than one child +/// must be uniquely represented by a directory entry. +class VFSFromYAML : public vfs::FileSystem { + std::vector<Entry *> Roots; ///< The root(s) of the virtual file system. + /// \brief The file system to use for external references. + IntrusiveRefCntPtr<FileSystem> ExternalFS; + + /// @name Configuration + /// @{ + + /// \brief Whether to perform case-sensitive comparisons. + /// + /// Currently, case-insensitive matching only works correctly with ASCII. + bool CaseSensitive; + + /// \brief Whether to use to use the value of 'external-contents' for the + /// names of files. This global value is overridable on a per-file basis. + bool UseExternalNames; + /// @} + + friend class VFSFromYAMLParser; + +private: + VFSFromYAML(IntrusiveRefCntPtr<FileSystem> ExternalFS) + : ExternalFS(ExternalFS), CaseSensitive(true), UseExternalNames(true) {} + + /// \brief Looks up \p Path in \c Roots. + ErrorOr<Entry *> lookupPath(const Twine &Path); + + /// \brief Looks up the path <tt>[Start, End)</tt> in \p From, possibly + /// recursing into the contents of \p From if it is a directory. + ErrorOr<Entry *> lookupPath(sys::path::const_iterator Start, + sys::path::const_iterator End, Entry *From); + + /// \brief Get the status of a given an \c Entry. + ErrorOr<Status> status(const Twine &Path, Entry *E); + +public: + ~VFSFromYAML(); + + /// \brief Parses \p Buffer, which is expected to be in YAML format and + /// returns a virtual file system representing its contents. + /// + /// Takes ownership of \p Buffer. + static VFSFromYAML *create(MemoryBuffer *Buffer, + SourceMgr::DiagHandlerTy DiagHandler, + void *DiagContext, + IntrusiveRefCntPtr<FileSystem> ExternalFS); + + ErrorOr<Status> status(const Twine &Path) override; + std::error_code openFileForRead(const Twine &Path, + std::unique_ptr<File> &Result) override; + + directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override{ + ErrorOr<Entry *> E = lookupPath(Dir); + if (!E) { + EC = E.getError(); + return directory_iterator(); + } + ErrorOr<Status> S = status(Dir, *E); + if (!S) { + EC = S.getError(); + return directory_iterator(); + } + if (!S->isDirectory()) { + EC = std::error_code(static_cast<int>(errc::not_a_directory), + std::system_category()); + return directory_iterator(); + } + + DirectoryEntry *D = cast<DirectoryEntry>(*E); + return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(Dir, + *this, D->contents_begin(), D->contents_end(), EC)); + } +}; + +/// \brief A helper class to hold the common YAML parsing state. +class VFSFromYAMLParser { + yaml::Stream &Stream; + + void error(yaml::Node *N, const Twine &Msg) { + Stream.printError(N, Msg); + } + + // false on error + bool parseScalarString(yaml::Node *N, StringRef &Result, + SmallVectorImpl<char> &Storage) { + yaml::ScalarNode *S = dyn_cast<yaml::ScalarNode>(N); + if (!S) { + error(N, "expected string"); + return false; + } + Result = S->getValue(Storage); + return true; + } + + // false on error + bool parseScalarBool(yaml::Node *N, bool &Result) { + SmallString<5> Storage; + StringRef Value; + if (!parseScalarString(N, Value, Storage)) + return false; + + if (Value.equals_lower("true") || Value.equals_lower("on") || + Value.equals_lower("yes") || Value == "1") { + Result = true; + return true; + } else if (Value.equals_lower("false") || Value.equals_lower("off") || + Value.equals_lower("no") || Value == "0") { + Result = false; + return true; + } + + error(N, "expected boolean value"); + return false; + } + + struct KeyStatus { + KeyStatus(bool Required=false) : Required(Required), Seen(false) {} + bool Required; + bool Seen; + }; + typedef std::pair<StringRef, KeyStatus> KeyStatusPair; + + // false on error + bool checkDuplicateOrUnknownKey(yaml::Node *KeyNode, StringRef Key, + DenseMap<StringRef, KeyStatus> &Keys) { + if (!Keys.count(Key)) { + error(KeyNode, "unknown key"); + return false; + } + KeyStatus &S = Keys[Key]; + if (S.Seen) { + error(KeyNode, Twine("duplicate key '") + Key + "'"); + return false; + } + S.Seen = true; + return true; + } + + // false on error + bool checkMissingKeys(yaml::Node *Obj, DenseMap<StringRef, KeyStatus> &Keys) { + for (DenseMap<StringRef, KeyStatus>::iterator I = Keys.begin(), + E = Keys.end(); + I != E; ++I) { + if (I->second.Required && !I->second.Seen) { + error(Obj, Twine("missing key '") + I->first + "'"); + return false; + } + } + return true; + } + + Entry *parseEntry(yaml::Node *N) { + yaml::MappingNode *M = dyn_cast<yaml::MappingNode>(N); + if (!M) { + error(N, "expected mapping node for file or directory entry"); + return nullptr; + } + + KeyStatusPair Fields[] = { + KeyStatusPair("name", true), + KeyStatusPair("type", true), + KeyStatusPair("contents", false), + KeyStatusPair("external-contents", false), + KeyStatusPair("use-external-name", false), + }; + + DenseMap<StringRef, KeyStatus> Keys( + &Fields[0], Fields + sizeof(Fields)/sizeof(Fields[0])); + + bool HasContents = false; // external or otherwise + std::vector<Entry *> EntryArrayContents; + std::string ExternalContentsPath; + std::string Name; + FileEntry::NameKind UseExternalName = FileEntry::NK_NotSet; + EntryKind Kind; + + for (yaml::MappingNode::iterator I = M->begin(), E = M->end(); I != E; + ++I) { + StringRef Key; + // Reuse the buffer for key and value, since we don't look at key after + // parsing value. + SmallString<256> Buffer; + if (!parseScalarString(I->getKey(), Key, Buffer)) + return nullptr; + + if (!checkDuplicateOrUnknownKey(I->getKey(), Key, Keys)) + return nullptr; + + StringRef Value; + if (Key == "name") { + if (!parseScalarString(I->getValue(), Value, Buffer)) + return nullptr; + Name = Value; + } else if (Key == "type") { + if (!parseScalarString(I->getValue(), Value, Buffer)) + return nullptr; + if (Value == "file") + Kind = EK_File; + else if (Value == "directory") + Kind = EK_Directory; + else { + error(I->getValue(), "unknown value for 'type'"); + return nullptr; + } + } else if (Key == "contents") { + if (HasContents) { + error(I->getKey(), + "entry already has 'contents' or 'external-contents'"); + return nullptr; + } + HasContents = true; + yaml::SequenceNode *Contents = + dyn_cast<yaml::SequenceNode>(I->getValue()); + if (!Contents) { + // FIXME: this is only for directories, what about files? + error(I->getValue(), "expected array"); + return nullptr; + } + + for (yaml::SequenceNode::iterator I = Contents->begin(), + E = Contents->end(); + I != E; ++I) { + if (Entry *E = parseEntry(&*I)) + EntryArrayContents.push_back(E); + else + return nullptr; + } + } else if (Key == "external-contents") { + if (HasContents) { + error(I->getKey(), + "entry already has 'contents' or 'external-contents'"); + return nullptr; + } + HasContents = true; + if (!parseScalarString(I->getValue(), Value, Buffer)) + return nullptr; + ExternalContentsPath = Value; + } else if (Key == "use-external-name") { + bool Val; + if (!parseScalarBool(I->getValue(), Val)) + return nullptr; + UseExternalName = Val ? FileEntry::NK_External : FileEntry::NK_Virtual; + } else { + llvm_unreachable("key missing from Keys"); + } + } + + if (Stream.failed()) + return nullptr; + + // check for missing keys + if (!HasContents) { + error(N, "missing key 'contents' or 'external-contents'"); + return nullptr; + } + if (!checkMissingKeys(N, Keys)) + return nullptr; + + // check invalid configuration + if (Kind == EK_Directory && UseExternalName != FileEntry::NK_NotSet) { + error(N, "'use-external-name' is not supported for directories"); + return nullptr; + } + + // Remove trailing slash(es), being careful not to remove the root path + StringRef Trimmed(Name); + size_t RootPathLen = sys::path::root_path(Trimmed).size(); + while (Trimmed.size() > RootPathLen && + sys::path::is_separator(Trimmed.back())) + Trimmed = Trimmed.slice(0, Trimmed.size()-1); + // Get the last component + StringRef LastComponent = sys::path::filename(Trimmed); + + Entry *Result = nullptr; + switch (Kind) { + case EK_File: + Result = new FileEntry(LastComponent, std::move(ExternalContentsPath), + UseExternalName); + break; + case EK_Directory: + Result = new DirectoryEntry(LastComponent, std::move(EntryArrayContents), + Status("", "", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0, + 0, file_type::directory_file, sys::fs::all_all)); + break; + } + + StringRef Parent = sys::path::parent_path(Trimmed); + if (Parent.empty()) + return Result; + + // if 'name' contains multiple components, create implicit directory entries + for (sys::path::reverse_iterator I = sys::path::rbegin(Parent), + E = sys::path::rend(Parent); + I != E; ++I) { + Result = new DirectoryEntry(*I, llvm::makeArrayRef(Result), + Status("", "", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0, + 0, file_type::directory_file, sys::fs::all_all)); + } + return Result; + } + +public: + VFSFromYAMLParser(yaml::Stream &S) : Stream(S) {} + + // false on error + bool parse(yaml::Node *Root, VFSFromYAML *FS) { + yaml::MappingNode *Top = dyn_cast<yaml::MappingNode>(Root); + if (!Top) { + error(Root, "expected mapping node"); + return false; + } + + KeyStatusPair Fields[] = { + KeyStatusPair("version", true), + KeyStatusPair("case-sensitive", false), + KeyStatusPair("use-external-names", false), + KeyStatusPair("roots", true), + }; + + DenseMap<StringRef, KeyStatus> Keys( + &Fields[0], Fields + sizeof(Fields)/sizeof(Fields[0])); + + // Parse configuration and 'roots' + for (yaml::MappingNode::iterator I = Top->begin(), E = Top->end(); I != E; + ++I) { + SmallString<10> KeyBuffer; + StringRef Key; + if (!parseScalarString(I->getKey(), Key, KeyBuffer)) + return false; + + if (!checkDuplicateOrUnknownKey(I->getKey(), Key, Keys)) + return false; + + if (Key == "roots") { + yaml::SequenceNode *Roots = dyn_cast<yaml::SequenceNode>(I->getValue()); + if (!Roots) { + error(I->getValue(), "expected array"); + return false; + } + + for (yaml::SequenceNode::iterator I = Roots->begin(), E = Roots->end(); + I != E; ++I) { + if (Entry *E = parseEntry(&*I)) + FS->Roots.push_back(E); + else + return false; + } + } else if (Key == "version") { + StringRef VersionString; + SmallString<4> Storage; + if (!parseScalarString(I->getValue(), VersionString, Storage)) + return false; + int Version; + if (VersionString.getAsInteger<int>(10, Version)) { + error(I->getValue(), "expected integer"); + return false; + } + if (Version < 0) { + error(I->getValue(), "invalid version number"); + return false; + } + if (Version != 0) { + error(I->getValue(), "version mismatch, expected 0"); + return false; + } + } else if (Key == "case-sensitive") { + if (!parseScalarBool(I->getValue(), FS->CaseSensitive)) + return false; + } else if (Key == "use-external-names") { + if (!parseScalarBool(I->getValue(), FS->UseExternalNames)) + return false; + } else { + llvm_unreachable("key missing from Keys"); + } + } + + if (Stream.failed()) + return false; + + if (!checkMissingKeys(Top, Keys)) + return false; + return true; + } +}; +} // end of anonymous namespace + +Entry::~Entry() {} +DirectoryEntry::~DirectoryEntry() { llvm::DeleteContainerPointers(Contents); } + +VFSFromYAML::~VFSFromYAML() { llvm::DeleteContainerPointers(Roots); } + +VFSFromYAML *VFSFromYAML::create(MemoryBuffer *Buffer, + SourceMgr::DiagHandlerTy DiagHandler, + void *DiagContext, + IntrusiveRefCntPtr<FileSystem> ExternalFS) { + + SourceMgr SM; + yaml::Stream Stream(Buffer, SM); + + SM.setDiagHandler(DiagHandler, DiagContext); + yaml::document_iterator DI = Stream.begin(); + yaml::Node *Root = DI->getRoot(); + if (DI == Stream.end() || !Root) { + SM.PrintMessage(SMLoc(), SourceMgr::DK_Error, "expected root node"); + return nullptr; + } + + VFSFromYAMLParser P(Stream); + + std::unique_ptr<VFSFromYAML> FS(new VFSFromYAML(ExternalFS)); + if (!P.parse(Root, FS.get())) + return nullptr; + + return FS.release(); +} + +ErrorOr<Entry *> VFSFromYAML::lookupPath(const Twine &Path_) { + SmallString<256> Path; + Path_.toVector(Path); + + // Handle relative paths + if (std::error_code EC = sys::fs::make_absolute(Path)) + return EC; + + if (Path.empty()) + return make_error_code(llvm::errc::invalid_argument); + + sys::path::const_iterator Start = sys::path::begin(Path); + sys::path::const_iterator End = sys::path::end(Path); + for (std::vector<Entry *>::iterator I = Roots.begin(), E = Roots.end(); + I != E; ++I) { + ErrorOr<Entry *> Result = lookupPath(Start, End, *I); + if (Result || Result.getError() != llvm::errc::no_such_file_or_directory) + return Result; + } + return make_error_code(llvm::errc::no_such_file_or_directory); +} + +ErrorOr<Entry *> VFSFromYAML::lookupPath(sys::path::const_iterator Start, + sys::path::const_iterator End, + Entry *From) { + if (Start->equals(".")) + ++Start; + + // FIXME: handle .. + if (CaseSensitive ? !Start->equals(From->getName()) + : !Start->equals_lower(From->getName())) + // failure to match + return make_error_code(llvm::errc::no_such_file_or_directory); + + ++Start; + + if (Start == End) { + // Match! + return From; + } + + DirectoryEntry *DE = dyn_cast<DirectoryEntry>(From); + if (!DE) + return make_error_code(llvm::errc::not_a_directory); + + for (DirectoryEntry::iterator I = DE->contents_begin(), + E = DE->contents_end(); + I != E; ++I) { + ErrorOr<Entry *> Result = lookupPath(Start, End, *I); + if (Result || Result.getError() != llvm::errc::no_such_file_or_directory) + return Result; + } + return make_error_code(llvm::errc::no_such_file_or_directory); +} + +ErrorOr<Status> VFSFromYAML::status(const Twine &Path, Entry *E) { + assert(E != nullptr); + std::string PathStr(Path.str()); + if (FileEntry *F = dyn_cast<FileEntry>(E)) { + ErrorOr<Status> S = ExternalFS->status(F->getExternalContentsPath()); + assert(!S || S->getName() == F->getExternalContentsPath()); + if (S && !F->useExternalName(UseExternalNames)) + S->setName(PathStr); + if (S) + S->IsVFSMapped = true; + return S; + } else { // directory + DirectoryEntry *DE = cast<DirectoryEntry>(E); + Status S = DE->getStatus(); + S.setName(PathStr); + return S; + } +} + +ErrorOr<Status> VFSFromYAML::status(const Twine &Path) { + ErrorOr<Entry *> Result = lookupPath(Path); + if (!Result) + return Result.getError(); + return status(Path, *Result); +} + +std::error_code +VFSFromYAML::openFileForRead(const Twine &Path, + std::unique_ptr<vfs::File> &Result) { + ErrorOr<Entry *> E = lookupPath(Path); + if (!E) + return E.getError(); + + FileEntry *F = dyn_cast<FileEntry>(*E); + if (!F) // FIXME: errc::not_a_file? + return make_error_code(llvm::errc::invalid_argument); + + if (std::error_code EC = + ExternalFS->openFileForRead(F->getExternalContentsPath(), Result)) + return EC; + + if (!F->useExternalName(UseExternalNames)) + Result->setName(Path.str()); + + return std::error_code(); +} + +IntrusiveRefCntPtr<FileSystem> +vfs::getVFSFromYAML(MemoryBuffer *Buffer, SourceMgr::DiagHandlerTy DiagHandler, + void *DiagContext, + IntrusiveRefCntPtr<FileSystem> ExternalFS) { + return VFSFromYAML::create(Buffer, DiagHandler, DiagContext, ExternalFS); +} + +UniqueID vfs::getNextVirtualUniqueID() { + static std::atomic<unsigned> UID; + unsigned ID = ++UID; + // The following assumes that uint64_t max will never collide with a real + // dev_t value from the OS. + return UniqueID(std::numeric_limits<uint64_t>::max(), ID); +} + +#ifndef NDEBUG +static bool pathHasTraversal(StringRef Path) { + using namespace llvm::sys; + for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path))) + if (Comp == "." || Comp == "..") + return true; + return false; +} +#endif + +void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) { + assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute"); + assert(sys::path::is_absolute(RealPath) && "real path not absolute"); + assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported"); + Mappings.emplace_back(VirtualPath, RealPath); +} + +namespace { +class JSONWriter { + llvm::raw_ostream &OS; + SmallVector<StringRef, 16> DirStack; + inline unsigned getDirIndent() { return 4 * DirStack.size(); } + inline unsigned getFileIndent() { return 4 * (DirStack.size() + 1); } + bool containedIn(StringRef Parent, StringRef Path); + StringRef containedPart(StringRef Parent, StringRef Path); + void startDirectory(StringRef Path); + void endDirectory(); + void writeEntry(StringRef VPath, StringRef RPath); + +public: + JSONWriter(llvm::raw_ostream &OS) : OS(OS) {} + void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> IsCaseSensitive); +}; +} + +bool JSONWriter::containedIn(StringRef Parent, StringRef Path) { + using namespace llvm::sys; + // Compare each path component. + auto IParent = path::begin(Parent), EParent = path::end(Parent); + for (auto IChild = path::begin(Path), EChild = path::end(Path); + IParent != EParent && IChild != EChild; ++IParent, ++IChild) { + if (*IParent != *IChild) + return false; + } + // Have we exhausted the parent path? + return IParent == EParent; +} + +StringRef JSONWriter::containedPart(StringRef Parent, StringRef Path) { + assert(!Parent.empty()); + assert(containedIn(Parent, Path)); + return Path.slice(Parent.size() + 1, StringRef::npos); +} + +void JSONWriter::startDirectory(StringRef Path) { + StringRef Name = + DirStack.empty() ? Path : containedPart(DirStack.back(), Path); + DirStack.push_back(Path); + unsigned Indent = getDirIndent(); + OS.indent(Indent) << "{\n"; + OS.indent(Indent + 2) << "'type': 'directory',\n"; + OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(Name) << "\",\n"; + OS.indent(Indent + 2) << "'contents': [\n"; +} + +void JSONWriter::endDirectory() { + unsigned Indent = getDirIndent(); + OS.indent(Indent + 2) << "]\n"; + OS.indent(Indent) << "}"; + + DirStack.pop_back(); +} + +void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) { + unsigned Indent = getFileIndent(); + OS.indent(Indent) << "{\n"; + OS.indent(Indent + 2) << "'type': 'file',\n"; + OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(VPath) << "\",\n"; + OS.indent(Indent + 2) << "'external-contents': \"" + << llvm::yaml::escape(RPath) << "\"\n"; + OS.indent(Indent) << "}"; +} + +void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries, + Optional<bool> IsCaseSensitive) { + using namespace llvm::sys; + + OS << "{\n" + " 'version': 0,\n"; + if (IsCaseSensitive.hasValue()) + OS << " 'case-sensitive': '" + << (IsCaseSensitive.getValue() ? "true" : "false") << "',\n"; + OS << " 'roots': [\n"; + + if (!Entries.empty()) { + const YAMLVFSEntry &Entry = Entries.front(); + startDirectory(path::parent_path(Entry.VPath)); + writeEntry(path::filename(Entry.VPath), Entry.RPath); + + for (const auto &Entry : Entries.slice(1)) { + StringRef Dir = path::parent_path(Entry.VPath); + if (Dir == DirStack.back()) + OS << ",\n"; + else { + while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) { + OS << "\n"; + endDirectory(); + } + OS << ",\n"; + startDirectory(Dir); + } + writeEntry(path::filename(Entry.VPath), Entry.RPath); + } + + while (!DirStack.empty()) { + OS << "\n"; + endDirectory(); + } + OS << "\n"; + } + + OS << " ]\n" + << "}\n"; +} + +void YAMLVFSWriter::write(llvm::raw_ostream &OS) { + std::sort(Mappings.begin(), Mappings.end(), + [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) { + return LHS.VPath < RHS.VPath; + }); + + JSONWriter(OS).write(Mappings, IsCaseSensitive); +} + +VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(const Twine &_Path, + VFSFromYAML &FS, + DirectoryEntry::iterator Begin, + DirectoryEntry::iterator End, + std::error_code &EC) + : Dir(_Path.str()), FS(FS), Current(Begin), End(End) { + if (Current != End) { + SmallString<128> PathStr(Dir); + llvm::sys::path::append(PathStr, (*Current)->getName()); + llvm::ErrorOr<vfs::Status> S = FS.status(PathStr.str()); + if (S) + CurrentEntry = *S; + else + EC = S.getError(); + } +} + +std::error_code VFSFromYamlDirIterImpl::increment() { + assert(Current != End && "cannot iterate past end"); + if (++Current != End) { + SmallString<128> PathStr(Dir); + llvm::sys::path::append(PathStr, (*Current)->getName()); + llvm::ErrorOr<vfs::Status> S = FS.status(PathStr.str()); + if (!S) + return S.getError(); + CurrentEntry = *S; + } else { + CurrentEntry = Status(); + } + return std::error_code(); +} + +vfs::recursive_directory_iterator::recursive_directory_iterator(FileSystem &FS_, + const Twine &Path, + std::error_code &EC) + : FS(&FS_) { + directory_iterator I = FS->dir_begin(Path, EC); + if (!EC && I != directory_iterator()) { + State = std::make_shared<IterState>(); + State->push(I); + } +} + +vfs::recursive_directory_iterator & +recursive_directory_iterator::increment(std::error_code &EC) { + assert(FS && State && !State->empty() && "incrementing past end"); + assert(State->top()->isStatusKnown() && "non-canonical end iterator"); + vfs::directory_iterator End; + if (State->top()->isDirectory()) { + vfs::directory_iterator I = FS->dir_begin(State->top()->getName(), EC); + if (EC) + return *this; + if (I != End) { + State->push(I); + return *this; + } + } + + while (!State->empty() && State->top().increment(EC) == End) + State->pop(); + + if (State->empty()) + State.reset(); // end iterator + + return *this; +} diff --git a/contrib/llvm/tools/clang/lib/Basic/Warnings.cpp b/contrib/llvm/tools/clang/lib/Basic/Warnings.cpp new file mode 100644 index 0000000..6306cea --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Basic/Warnings.cpp @@ -0,0 +1,230 @@ +//===--- Warnings.cpp - C-Language Front-end ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Command line warning options handler. +// +//===----------------------------------------------------------------------===// +// +// This file is responsible for handling all warning options. This includes +// a number of -Wfoo options and their variants, which are driven by TableGen- +// generated data, and the special cases -pedantic, -pedantic-errors, -w, +// -Werror and -Wfatal-errors. +// +// Each warning option controls any number of actual warnings. +// Given a warning option 'foo', the following are valid: +// -Wfoo, -Wno-foo, -Werror=foo, -Wfatal-errors=foo +// +// Remark options are also handled here, analogously, except that they are much +// simpler because a remark can't be promoted to an error. +#include "clang/Basic/AllDiagnostics.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" +#include <algorithm> +#include <cstring> +#include <utility> +using namespace clang; + +// EmitUnknownDiagWarning - Emit a warning and typo hint for unknown warning +// opts +static void EmitUnknownDiagWarning(DiagnosticsEngine &Diags, + diag::Flavor Flavor, StringRef Prefix, + StringRef Opt) { + StringRef Suggestion = DiagnosticIDs::getNearestOption(Flavor, Opt); + Diags.Report(diag::warn_unknown_diag_option) + << (Flavor == diag::Flavor::WarningOrError ? 0 : 1) << (Prefix.str() += Opt) + << !Suggestion.empty() << (Prefix.str() += Suggestion); +} + +void clang::ProcessWarningOptions(DiagnosticsEngine &Diags, + const DiagnosticOptions &Opts, + bool ReportDiags) { + Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers + Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings); + Diags.setShowOverloads(Opts.getShowOverloads()); + + Diags.setElideType(Opts.ElideType); + Diags.setPrintTemplateTree(Opts.ShowTemplateTree); + Diags.setShowColors(Opts.ShowColors); + + // Handle -ferror-limit + if (Opts.ErrorLimit) + Diags.setErrorLimit(Opts.ErrorLimit); + if (Opts.TemplateBacktraceLimit) + Diags.setTemplateBacktraceLimit(Opts.TemplateBacktraceLimit); + if (Opts.ConstexprBacktraceLimit) + Diags.setConstexprBacktraceLimit(Opts.ConstexprBacktraceLimit); + + // If -pedantic or -pedantic-errors was specified, then we want to map all + // extension diagnostics onto WARNING or ERROR unless the user has futz'd + // around with them explicitly. + if (Opts.PedanticErrors) + Diags.setExtensionHandlingBehavior(diag::Severity::Error); + else if (Opts.Pedantic) + Diags.setExtensionHandlingBehavior(diag::Severity::Warning); + else + Diags.setExtensionHandlingBehavior(diag::Severity::Ignored); + + SmallVector<diag::kind, 10> _Diags; + const IntrusiveRefCntPtr< DiagnosticIDs > DiagIDs = + Diags.getDiagnosticIDs(); + // We parse the warning options twice. The first pass sets diagnostic state, + // while the second pass reports warnings/errors. This has the effect that + // we follow the more canonical "last option wins" paradigm when there are + // conflicting options. + for (unsigned Report = 0, ReportEnd = 2; Report != ReportEnd; ++Report) { + bool SetDiagnostic = (Report == 0); + + // If we've set the diagnostic state and are not reporting diagnostics then + // we're done. + if (!SetDiagnostic && !ReportDiags) + break; + + for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) { + const auto Flavor = diag::Flavor::WarningOrError; + StringRef Opt = Opts.Warnings[i]; + StringRef OrigOpt = Opts.Warnings[i]; + + // Treat -Wformat=0 as an alias for -Wno-format. + if (Opt == "format=0") + Opt = "no-format"; + + // Check to see if this warning starts with "no-", if so, this is a + // negative form of the option. + bool isPositive = true; + if (Opt.startswith("no-")) { + isPositive = false; + Opt = Opt.substr(3); + } + + // Figure out how this option affects the warning. If -Wfoo, map the + // diagnostic to a warning, if -Wno-foo, map it to ignore. + diag::Severity Mapping = + isPositive ? diag::Severity::Warning : diag::Severity::Ignored; + + // -Wsystem-headers is a special case, not driven by the option table. It + // cannot be controlled with -Werror. + if (Opt == "system-headers") { + if (SetDiagnostic) + Diags.setSuppressSystemWarnings(!isPositive); + continue; + } + + // -Weverything is a special case as well. It implicitly enables all + // warnings, including ones not explicitly in a warning group. + if (Opt == "everything") { + if (SetDiagnostic) { + if (isPositive) { + Diags.setEnableAllWarnings(true); + } else { + Diags.setEnableAllWarnings(false); + Diags.setSeverityForAll(Flavor, diag::Severity::Ignored); + } + } + continue; + } + + // -Werror/-Wno-error is a special case, not controlled by the option + // table. It also has the "specifier" form of -Werror=foo and -Werror-foo. + if (Opt.startswith("error")) { + StringRef Specifier; + if (Opt.size() > 5) { // Specifier must be present. + if ((Opt[5] != '=' && Opt[5] != '-') || Opt.size() == 6) { + if (Report) + Diags.Report(diag::warn_unknown_warning_specifier) + << "-Werror" << ("-W" + OrigOpt.str()); + continue; + } + Specifier = Opt.substr(6); + } + + if (Specifier.empty()) { + if (SetDiagnostic) + Diags.setWarningsAsErrors(isPositive); + continue; + } + + if (SetDiagnostic) { + // Set the warning as error flag for this specifier. + Diags.setDiagnosticGroupWarningAsError(Specifier, isPositive); + } else if (DiagIDs->getDiagnosticsInGroup(Flavor, Specifier, _Diags)) { + EmitUnknownDiagWarning(Diags, Flavor, "-Werror=", Specifier); + } + continue; + } + + // -Wfatal-errors is yet another special case. + if (Opt.startswith("fatal-errors")) { + StringRef Specifier; + if (Opt.size() != 12) { + if ((Opt[12] != '=' && Opt[12] != '-') || Opt.size() == 13) { + if (Report) + Diags.Report(diag::warn_unknown_warning_specifier) + << "-Wfatal-errors" << ("-W" + OrigOpt.str()); + continue; + } + Specifier = Opt.substr(13); + } + + if (Specifier.empty()) { + if (SetDiagnostic) + Diags.setErrorsAsFatal(isPositive); + continue; + } + + if (SetDiagnostic) { + // Set the error as fatal flag for this specifier. + Diags.setDiagnosticGroupErrorAsFatal(Specifier, isPositive); + } else if (DiagIDs->getDiagnosticsInGroup(Flavor, Specifier, _Diags)) { + EmitUnknownDiagWarning(Diags, Flavor, "-Wfatal-errors=", Specifier); + } + continue; + } + + if (Report) { + if (DiagIDs->getDiagnosticsInGroup(Flavor, Opt, _Diags)) + EmitUnknownDiagWarning(Diags, Flavor, isPositive ? "-W" : "-Wno-", + Opt); + } else { + Diags.setSeverityForGroup(Flavor, Opt, Mapping); + } + } + + for (unsigned i = 0, e = Opts.Remarks.size(); i != e; ++i) { + StringRef Opt = Opts.Remarks[i]; + const auto Flavor = diag::Flavor::Remark; + + // Check to see if this warning starts with "no-", if so, this is a + // negative form of the option. + bool IsPositive = !Opt.startswith("no-"); + if (!IsPositive) Opt = Opt.substr(3); + + auto Severity = IsPositive ? diag::Severity::Remark + : diag::Severity::Ignored; + + // -Reverything sets the state of all remarks. Note that all remarks are + // in remark groups, so we don't need a separate 'all remarks enabled' + // flag. + if (Opt == "everything") { + if (SetDiagnostic) + Diags.setSeverityForAll(Flavor, Severity); + continue; + } + + if (Report) { + if (DiagIDs->getDiagnosticsInGroup(Flavor, Opt, _Diags)) + EmitUnknownDiagWarning(Diags, Flavor, IsPositive ? "-R" : "-Rno-", + Opt); + } else { + Diags.setSeverityForGroup(Flavor, Opt, + IsPositive ? diag::Severity::Remark + : diag::Severity::Ignored); + } + } + } +} |