aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Basic
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2014-11-24 09:15:30 +0000
committerDimitry Andric <dim@FreeBSD.org>2014-11-24 09:15:30 +0000
commit9f4dbff6669c8037f3b036bcf580d14f1a4f12a5 (patch)
tree47df2c12b57214af6c31e47404b005675b8b7ffc /lib/Basic
parentf73d5f23a889b93d89ddef61ac0995df40286bb8 (diff)
downloadsrc-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.tar.gz
src-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.zip
Vendor import of clang RELEASE_350/final tag r216957 (effectively, 3.5.0 release):vendor/clang/clang-release_350-r216957
Notes
Notes: svn path=/vendor/clang/dist/; revision=274958 svn path=/vendor/clang/clang-release_350-r216957/; revision=274959; tag=vendor/clang/clang-release_350-r216957
Diffstat (limited to 'lib/Basic')
-rw-r--r--lib/Basic/Attributes.cpp17
-rw-r--r--lib/Basic/Builtins.cpp57
-rw-r--r--lib/Basic/CMakeLists.txt46
-rw-r--r--lib/Basic/Diagnostic.cpp212
-rw-r--r--lib/Basic/DiagnosticIDs.cpp268
-rw-r--r--lib/Basic/FileManager.cpp226
-rw-r--r--lib/Basic/FileSystemStatCache.cpp46
-rw-r--r--lib/Basic/IdentifierTable.cpp24
-rw-r--r--lib/Basic/Module.cpp41
-rw-r--r--lib/Basic/OpenMPKinds.cpp229
-rw-r--r--lib/Basic/SourceLocation.cpp7
-rw-r--r--lib/Basic/SourceManager.cpp135
-rw-r--r--lib/Basic/TargetInfo.cpp70
-rw-r--r--lib/Basic/Targets.cpp2624
-rw-r--r--lib/Basic/TokenKinds.cpp24
-rw-r--r--lib/Basic/Version.cpp16
-rw-r--r--lib/Basic/VirtualFileSystem.cpp1209
-rw-r--r--lib/Basic/Warnings.cpp230
18 files changed, 3821 insertions, 1660 deletions
diff --git a/lib/Basic/Attributes.cpp b/lib/Basic/Attributes.cpp
new file mode 100644
index 000000000000..a05ad053db04
--- /dev/null
+++ b/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/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp
index c84dd6dc38ff..8efcac6d7fe4 100644
--- a/lib/Basic/Builtins.cpp
+++ b/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/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index 34111691c82e..0df82b3bc906 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -1,6 +1,10 @@
-set(LLVM_LINK_COMPONENTS mc)
+set(LLVM_LINK_COMPONENTS
+ MC
+ Support
+ )
add_clang_library(clangBasic
+ Attributes.cpp
Builtins.cpp
CharInfo.cpp
Diagnostic.cpp
@@ -20,6 +24,8 @@ add_clang_library(clangBasic
TokenKinds.cpp
Version.cpp
VersionTuple.cpp
+ VirtualFileSystem.cpp
+ Warnings.cpp
)
# Determine Subversion revision.
@@ -29,17 +35,15 @@ if( NOT IS_SYMLINK "${CLANG_SOURCE_DIR}" ) # See PR 8437
find_package(Subversion)
endif()
if (Subversion_FOUND AND EXISTS "${CLANG_SOURCE_DIR}/.svn")
- # Create custom target to generate the Subversion version include.
- add_custom_target(clang_revision_tag ALL
- COMMAND ${CMAKE_COMMAND} -DFIRST_SOURCE_DIR=${LLVM_MAIN_SRC_DIR}
- -DFIRST_REPOSITORY=LLVM_REPOSITORY
- -DSECOND_SOURCE_DIR=${CLANG_SOURCE_DIR}
- -DSECOND_REPOSITORY=SVN_REPOSITORY
- -DHEADER_FILE=${CMAKE_CURRENT_BINARY_DIR}/SVNVersion.inc
- -P ${LLVM_MAIN_SRC_DIR}/cmake/modules/GetSVN.cmake)
+ set(FIRST_SOURCE_DIR ${LLVM_MAIN_SRC_DIR})
+ set(FIRST_REPOSITORY LLVM_REPOSITORY)
+ set(SECOND_SOURCE_DIR ${CLANG_SOURCE_DIR})
+ set(SECOND_REPOSITORY SVN_REPOSITORY)
+ set(HEADER_FILE ${CMAKE_CURRENT_BINARY_DIR}/SVNVersion.inc)
+ include(GetSVN)
# Mark the generated header as being generated.
-message(STATUS "Expecting header to go in ${CMAKE_CURRENT_BINARY_DIR}/SVNVersion.inc")
+ message(STATUS "Expecting header to go in ${CMAKE_CURRENT_BINARY_DIR}/SVNVersion.inc")
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/SVNVersion.inc
PROPERTIES GENERATED TRUE
HEADER_FILE_ONLY TRUE)
@@ -49,25 +53,3 @@ message(STATUS "Expecting header to go in ${CMAKE_CURRENT_BINARY_DIR}/SVNVersion
PROPERTIES COMPILE_DEFINITIONS "HAVE_SVN_VERSION_INC")
endif()
-
-add_dependencies(clangBasic
- ClangARMNeon
- ClangAttrList
- ClangDiagnosticAnalysis
- ClangDiagnosticAST
- ClangDiagnosticComment
- ClangDiagnosticCommon
- ClangDiagnosticDriver
- ClangDiagnosticFrontend
- ClangDiagnosticGroups
- ClangDiagnosticIndexName
- ClangDiagnosticLex
- ClangDiagnosticParse
- ClangDiagnosticSema
- ClangDiagnosticSerialization
- )
-
-# clangBasic depends on the version.
-if (Subversion_FOUND AND EXISTS "${CLANG_SOURCE_DIR}/.svn")
- add_dependencies(clangBasic clang_revision_tag)
-endif() \ No newline at end of file
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 45d4b539e8c2..4567e3267131 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/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/lib/Basic/DiagnosticIDs.cpp b/lib/Basic/DiagnosticIDs.cpp
index 9d99fbedd83c..ec244ccda3cb 100644
--- a/lib/Basic/DiagnosticIDs.cpp
+++ b/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/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index af9b2663cbfa..94210320bff7 100644
--- a/lib/Basic/FileManager.cpp
+++ b/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/lib/Basic/FileSystemStatCache.cpp b/lib/Basic/FileSystemStatCache.cpp
index 7a01bffcd95f..7515cfb440af 100644
--- a/lib/Basic/FileSystemStatCache.cpp
+++ b/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/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 500e732eef34..219845996323 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/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/lib/Basic/Module.cpp b/lib/Basic/Module.cpp
index d08cef1a1563..f689c733d9c0 100644
--- a/lib/Basic/Module.cpp
+++ b/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/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index 1350934d0e65..06f010f7ceb4 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/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/lib/Basic/SourceLocation.cpp b/lib/Basic/SourceLocation.cpp
index 182209117966..0c06a48c123a 100644
--- a/lib/Basic/SourceLocation.cpp
+++ b/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/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 9d79551f9118..61dfe35e2257 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/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/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index e993055cc881..aecf13b00854 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/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/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index c8bfda7e6658..075f905cc359 100644
--- a/lib/Basic/Targets.cpp
+++ b/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,24 +4938,27 @@ 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
+ // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned.
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ 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__");
@@ -4555,6 +4971,22 @@ public:
Builder.defineMacro("__sparcv9__");
}
}
+
+ bool setCPU(const std::string &Name) override {
+ bool CPUKnown = llvm::StringSwitch<bool>(Name)
+ .Case("v9", true)
+ .Case("ultrasparc", true)
+ .Case("ultrasparc3", true)
+ .Case("niagara", true)
+ .Case("niagara2", true)
+ .Case("niagara3", true)
+ .Case("niagara4", true)
+ .Default(false);
+
+ // No need to store the CPU yet. There aren't any CPU-specific
+ // macros to define.
+ return CPUKnown;
+ }
};
} // end anonymous namespace.
@@ -4579,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 {
@@ -4697,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;
}
@@ -4785,7 +5215,6 @@ namespace {
SuitableAlign = 32;
SizeType = UnsignedInt;
IntMaxType = SignedLong;
- UIntMaxType = UnsignedLong;
IntPtrType = SignedInt;
PtrDiffType = SignedInt;
FloatWidth = 32;
@@ -4797,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 {}
};
}
@@ -4863,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) {
@@ -4930,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
@@ -4973,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
@@ -4996,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) {
@@ -5033,6 +5496,8 @@ public:
HasFP64 = false;
else if (*it == "+nan2008")
IsNan2008 = true;
+ else if (*it == "-nan2008")
+ IsNan2008 = false;
}
// Remove front-end specific options.
@@ -5040,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[] = {
@@ -5066,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");
@@ -5095,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" },
@@ -5136,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);
@@ -5154,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:
@@ -5164,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);
@@ -5175,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");
@@ -5222,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" },
@@ -5260,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);
@@ -5287,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)
@@ -5303,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);
@@ -5323,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;
@@ -5332,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.
@@ -5409,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;
}
};
@@ -5443,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);
}
};
@@ -5460,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);
}
};
@@ -5489,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"
@@ -5517,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[] = {
@@ -5546,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);
@@ -5555,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<AArch64leTargetInfo>(Triple);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<AArch64leTargetInfo>(Triple);
+ default:
+ return new AArch64leTargetInfo(Triple);
+ }
+
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64_be:
switch (os) {
case llvm::Triple::Linux:
- return new LinuxTargetInfo<AArch64TargetInfo>(Triple);
+ return new LinuxTargetInfo<AArch64beTargetInfo>(Triple);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<AArch64beTargetInfo>(Triple);
default:
- return new AArch64TargetInfo(Triple);
+ 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:
@@ -5656,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:
@@ -5781,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:
@@ -5798,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) {
@@ -5820,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:
@@ -5833,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);
}
}
@@ -5847,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
@@ -5906,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/lib/Basic/TokenKinds.cpp b/lib/Basic/TokenKinds.cpp
index 6ce076e57a6c..3b1f8fe34bef 100644
--- a/lib/Basic/TokenKinds.cpp
+++ b/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/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index 2006878349a1..87ecac17649b 100644
--- a/lib/Basic/Version.cpp
+++ b/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,17 +116,21 @@ 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();
// If vendor supplied, include the base LLVM version as well.
#ifdef CLANG_VENDOR
- OS << " (based on LLVM " << PACKAGE_VERSION << ")";
+ OS << " (based on " << BACKEND_PACKAGE_STRING << ")";
#endif
return OS.str();
diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp
new file mode 100644
index 000000000000..a5c83b88af50
--- /dev/null
+++ b/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/lib/Basic/Warnings.cpp b/lib/Basic/Warnings.cpp
new file mode 100644
index 000000000000..6306ceabc638
--- /dev/null
+++ b/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);
+ }
+ }
+ }
+}