diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic')
18 files changed, 1315 insertions, 641 deletions
diff --git a/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp b/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp index a05ad05..da9ac79 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp @@ -3,7 +3,7 @@ #include "llvm/ADT/StringSwitch.h" using namespace clang; -bool clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, +int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, const IdentifierInfo *Attr, const llvm::Triple &T, const LangOptions &LangOpts) { StringRef Name = Attr->getName(); @@ -13,5 +13,5 @@ bool clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, #include "clang/Basic/AttrHasAttributeImpl.inc" - return false; + return 0; } diff --git a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp index 4567e32..83228ad 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CrashRecoveryContext.h" +#include "llvm/Support/Locale.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -33,13 +34,11 @@ static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT, Output.append(Str.begin(), Str.end()); } - DiagnosticsEngine::DiagnosticsEngine( - const IntrusiveRefCntPtr<DiagnosticIDs> &diags, - DiagnosticOptions *DiagOpts, - DiagnosticConsumer *client, bool ShouldOwnClient) - : Diags(diags), DiagOpts(DiagOpts), Client(client), - OwnsDiagClient(ShouldOwnClient), SourceMgr(nullptr) { + const IntrusiveRefCntPtr<DiagnosticIDs> &diags, DiagnosticOptions *DiagOpts, + DiagnosticConsumer *client, bool ShouldOwnClient) + : Diags(diags), DiagOpts(DiagOpts), Client(nullptr), SourceMgr(nullptr) { + setClient(client, ShouldOwnClient); ArgToStringFn = DummyArgToStringFn; ArgToStringCookie = nullptr; @@ -64,17 +63,15 @@ DiagnosticsEngine::DiagnosticsEngine( } DiagnosticsEngine::~DiagnosticsEngine() { - if (OwnsDiagClient) - delete Client; + // If we own the diagnostic client, destroy it first so that it can access the + // engine from its destructor. + setClient(nullptr); } void DiagnosticsEngine::setClient(DiagnosticConsumer *client, bool ShouldOwnClient) { - if (OwnsDiagClient && Client) - delete Client; - + Owner.reset(ShouldOwnClient ? client : nullptr); Client = client; - OwnsDiagClient = ShouldOwnClient; } void DiagnosticsEngine::pushMappings(SourceLocation Loc) { @@ -101,7 +98,6 @@ void DiagnosticsEngine::Reset() { NumWarnings = 0; NumErrors = 0; - NumErrorsSuppressed = 0; TrapNumErrorsOccurred = 0; TrapNumUnrecoverableErrorsOccurred = 0; @@ -232,13 +228,13 @@ bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor, StringRef Group, diag::Severity Map, SourceLocation Loc) { // Get the diagnostics in this group. - SmallVector<diag::kind, 8> GroupDiags; + SmallVector<diag::kind, 256> GroupDiags; if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags)) return true; // Set the mapping. - for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) - setSeverity(GroupDiags[i], Map, Loc); + for (diag::kind Diag : GroupDiags) + setSeverity(Diag, Map, Loc); return false; } @@ -634,6 +630,20 @@ void Diagnostic:: FormatDiagnostic(const char *DiagStr, const char *DiagEnd, SmallVectorImpl<char> &OutStr) const { + // When the diagnostic string is only "%0", the entire string is being given + // by an outside source. Remove unprintable characters from this string + // and skip all the other string processing. + if (DiagEnd - DiagStr == 2 && DiagStr[0] == '%' && DiagStr[1] == '0' && + getArgKind(0) == DiagnosticsEngine::ak_std_string) { + const std::string &S = getArgStdStr(0); + for (char c : S) { + if (llvm::sys::locale::isPrint(c) || c == '\t') { + OutStr.push_back(c); + } + } + return; + } + /// FormattedArgs - Keep track of all of the arguments formatted by /// ConvertArgToString and pass them into subsequent calls to /// ConvertArgToString, allowing the implementation to avoid redundancies in diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp index ec244cc..1c68375 100644 --- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp @@ -428,16 +428,9 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, // Upgrade ignored diagnostics if -Weverything is enabled. if (Diag.EnableAllWarnings && Result == diag::Severity::Ignored && - !Mapping.isUser()) + !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK) 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 // that are not enabled by default.) @@ -613,9 +606,6 @@ StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor, bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { Diagnostic Info(&Diag); - if (Diag.SuppressAllDiagnostics) - return false; - assert(Diag.getClient() && "DiagnosticClient not set!"); // Figure out the diagnostic level of this message. @@ -623,6 +613,17 @@ bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { DiagnosticIDs::Level DiagLevel = getDiagnosticLevel(DiagID, Info.getLocation(), Diag); + // Update counts for DiagnosticErrorTrap even if a fatal error occurred + // or diagnostics are suppressed. + if (DiagLevel >= DiagnosticIDs::Error) { + ++Diag.TrapNumErrorsOccurred; + if (isUnrecoverable(DiagID)) + ++Diag.TrapNumUnrecoverableErrorsOccurred; + } + + if (Diag.SuppressAllDiagnostics) + return false; + if (DiagLevel != DiagnosticIDs::Note) { // Record that a fatal error occurred only when we see a second // non-note diagnostic. This allows notes to be attached to the @@ -634,20 +635,12 @@ bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { Diag.LastDiagLevel = DiagLevel; } - // Update counts for DiagnosticErrorTrap even if a fatal error occurred. - if (DiagLevel >= DiagnosticIDs::Error) { - ++Diag.TrapNumErrorsOccurred; - if (isUnrecoverable(DiagID)) - ++Diag.TrapNumUnrecoverableErrorsOccurred; - } - // If a fatal error has already been emitted, silence all subsequent // diagnostics. if (Diag.FatalErrorOccurred) { if (DiagLevel >= DiagnosticIDs::Error && Diag.Client->IncludeInDiagnosticCounts()) { ++Diag.NumErrors; - ++Diag.NumErrorsSuppressed; } return false; diff --git a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp index 9421032..214e0f3 100644 --- a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp @@ -64,20 +64,20 @@ FileManager::~FileManager() { delete VirtualDirectoryEntries[i]; } -void FileManager::addStatCache(FileSystemStatCache *statCache, +void FileManager::addStatCache(std::unique_ptr<FileSystemStatCache> statCache, bool AtBeginning) { assert(statCache && "No stat cache provided?"); if (AtBeginning || !StatCache.get()) { - statCache->setNextStatCache(StatCache.release()); - StatCache.reset(statCache); + statCache->setNextStatCache(std::move(StatCache)); + StatCache = std::move(statCache); return; } FileSystemStatCache *LastCache = StatCache.get(); while (LastCache->getNextStatCache()) LastCache = LastCache->getNextStatCache(); - - LastCache->setNextStatCache(statCache); + + LastCache->setNextStatCache(std::move(statCache)); } void FileManager::removeStatCache(FileSystemStatCache *statCache) { @@ -86,7 +86,7 @@ void FileManager::removeStatCache(FileSystemStatCache *statCache) { if (StatCache.get() == statCache) { // This is the first stat cache. - StatCache.reset(StatCache->takeNextStatCache()); + StatCache = StatCache->takeNextStatCache(); return; } @@ -96,7 +96,7 @@ void FileManager::removeStatCache(FileSystemStatCache *statCache) { PrevCache = PrevCache->getNextStatCache(); assert(PrevCache && "Stat cache not found for removal"); - PrevCache->setNextStatCache(statCache->getNextStatCache()); + PrevCache->setNextStatCache(statCache->takeNextStatCache()); } void FileManager::clearStatCaches() { @@ -129,20 +129,20 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef Path) { if (DirName.empty()) return; - llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = - SeenDirEntries.GetOrCreateValue(DirName); + auto &NamedDirEnt = + *SeenDirEntries.insert(std::make_pair(DirName, nullptr)).first; // When caching a virtual directory, we always cache its ancestors // at the same time. Therefore, if DirName is already in the cache, // we don't need to recurse as its ancestors must also already be in // the cache. - if (NamedDirEnt.getValue()) + if (NamedDirEnt.second) return; // Add the virtual directory to the cache. DirectoryEntry *UDE = new DirectoryEntry; - UDE->Name = NamedDirEnt.getKeyData(); - NamedDirEnt.setValue(UDE); + UDE->Name = NamedDirEnt.first().data(); + NamedDirEnt.second = UDE; VirtualDirectoryEntries.push_back(UDE); // Recursively add the other ancestors. @@ -170,23 +170,23 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName, #endif ++NumDirLookups; - llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = - SeenDirEntries.GetOrCreateValue(DirName); + auto &NamedDirEnt = + *SeenDirEntries.insert(std::make_pair(DirName, nullptr)).first; // 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 ? nullptr - : NamedDirEnt.getValue(); + if (NamedDirEnt.second) + return NamedDirEnt.second == NON_EXISTENT_DIR ? nullptr + : NamedDirEnt.second; ++NumDirCacheMisses; // By default, initialize it to invalid. - NamedDirEnt.setValue(NON_EXISTENT_DIR); + NamedDirEnt.second = NON_EXISTENT_DIR; // Get the null-terminated directory name as stored as the key of the // SeenDirEntries map. - const char *InterndDirName = NamedDirEnt.getKeyData(); + const char *InterndDirName = NamedDirEnt.first().data(); // Check to see if the directory exists. FileData Data; @@ -203,7 +203,7 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName, // Windows). DirectoryEntry &UDE = UniqueRealDirs[Data.UniqueID]; - NamedDirEnt.setValue(&UDE); + NamedDirEnt.second = &UDE; if (!UDE.getName()) { // We don't have this directory yet, add it. We use the string // key from the SeenDirEntries map as the string. @@ -218,22 +218,22 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, ++NumFileLookups; // See if there is already an entry in the map. - llvm::StringMapEntry<FileEntry *> &NamedFileEnt = - SeenFileEntries.GetOrCreateValue(Filename); + auto &NamedFileEnt = + *SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first; // See if there is already an entry in the map. - if (NamedFileEnt.getValue()) - return NamedFileEnt.getValue() == NON_EXISTENT_FILE - ? nullptr : NamedFileEnt.getValue(); + if (NamedFileEnt.second) + return NamedFileEnt.second == NON_EXISTENT_FILE ? nullptr + : NamedFileEnt.second; ++NumFileCacheMisses; // By default, initialize it to invalid. - NamedFileEnt.setValue(NON_EXISTENT_FILE); + NamedFileEnt.second = NON_EXISTENT_FILE; // Get the null-terminated file name as stored as the key of the // SeenFileEntries map. - const char *InterndFileName = NamedFileEnt.getKeyData(); + const char *InterndFileName = NamedFileEnt.first().data(); // Look up the directory for the file. When looking up something like // sys/foo.h we'll discover all of the search directories that have a 'sys' @@ -269,7 +269,21 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, // This occurs when one dir is symlinked to another, for example. FileEntry &UFE = UniqueRealFiles[Data.UniqueID]; - NamedFileEnt.setValue(&UFE); + NamedFileEnt.second = &UFE; + + // If the name returned by getStatValue is different than Filename, re-intern + // the name. + if (Data.Name != Filename) { + auto &NamedFileEnt = + *SeenFileEntries.insert(std::make_pair(Data.Name, nullptr)).first; + if (!NamedFileEnt.second) + NamedFileEnt.second = &UFE; + else + assert(NamedFileEnt.second == &UFE && + "filename from getStatValue() refers to wrong file"); + InterndFileName = NamedFileEnt.first().data(); + } + 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 @@ -281,11 +295,18 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, if (DirInfo != UFE.Dir && Data.IsVFSMapped) UFE.Dir = DirInfo; + // Always update the name to use the last name by which a file was accessed. + // FIXME: Neither this nor always using the first name is correct; we want + // to switch towards a design where we return a FileName object that + // encapsulates both the name by which the file was accessed and the + // corresponding FileEntry. + UFE.Name = InterndFileName; + return &UFE; } // Otherwise, we don't have this file yet, add it. - UFE.Name = Data.Name; + UFE.Name = InterndFileName; UFE.Size = Data.Size; UFE.ModTime = Data.ModTime; UFE.Dir = DirInfo; @@ -304,17 +325,17 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, ++NumFileLookups; // See if there is already an entry in the map. - llvm::StringMapEntry<FileEntry *> &NamedFileEnt = - SeenFileEntries.GetOrCreateValue(Filename); + auto &NamedFileEnt = + *SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first; // See if there is already an entry in the map. - if (NamedFileEnt.getValue() && NamedFileEnt.getValue() != NON_EXISTENT_FILE) - return NamedFileEnt.getValue(); + if (NamedFileEnt.second && NamedFileEnt.second != NON_EXISTENT_FILE) + return NamedFileEnt.second; ++NumFileCacheMisses; // By default, initialize it to invalid. - NamedFileEnt.setValue(NON_EXISTENT_FILE); + NamedFileEnt.second = NON_EXISTENT_FILE; addAncestorsAsVirtualDirs(Filename); FileEntry *UFE = nullptr; @@ -329,13 +350,13 @@ 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(); + const char *InterndFileName = NamedFileEnt.first().data(); if (getStatValue(InterndFileName, Data, true, nullptr) == 0) { Data.Size = Size; Data.ModTime = ModificationTime; UFE = &UniqueRealFiles[Data.UniqueID]; - NamedFileEnt.setValue(UFE); + NamedFileEnt.second = 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 @@ -355,7 +376,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, if (!UFE) { UFE = new FileEntry(); VirtualFileEntries.push_back(UFE); - NamedFileEnt.setValue(UFE); + NamedFileEnt.second = UFE; } UFE->Name = InterndFileName; @@ -379,12 +400,9 @@ void FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const { path = NewPath; } -llvm::MemoryBuffer *FileManager:: -getBufferForFile(const FileEntry *Entry, std::string *ErrorStr, - bool isVolatile, bool ShouldCloseOpenFile) { - std::unique_ptr<llvm::MemoryBuffer> Result; - std::error_code ec; - +llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> +FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile, + bool ShouldCloseOpenFile) { uint64_t FileSize = Entry->getSize(); // If there's a high enough chance that the file have changed since we // got its size, force a stat before opening it. @@ -394,53 +412,36 @@ 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->File) { - ec = Entry->File->getBuffer(Filename, Result, FileSize, - /*RequiresNullTerminator=*/true, isVolatile); - if (ErrorStr) - *ErrorStr = ec.message(); + auto Result = + Entry->File->getBuffer(Filename, FileSize, + /*RequiresNullTerminator=*/true, isVolatile); // 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(); + return Result; } // Otherwise, open the file. - if (FileSystemOpts.WorkingDir.empty()) { - ec = FS->getBufferForFile(Filename, Result, FileSize, - /*RequiresNullTerminator=*/true, isVolatile); - if (ec && ErrorStr) - *ErrorStr = ec.message(); - return Result.release(); - } + if (FileSystemOpts.WorkingDir.empty()) + return FS->getBufferForFile(Filename, FileSize, + /*RequiresNullTerminator=*/true, isVolatile); SmallString<128> FilePath(Entry->getName()); FixupRelativePath(FilePath); - ec = FS->getBufferForFile(FilePath.str(), Result, FileSize, - /*RequiresNullTerminator=*/true, isVolatile); - if (ec && ErrorStr) - *ErrorStr = ec.message(); - return Result.release(); + return FS->getBufferForFile(FilePath.str(), FileSize, + /*RequiresNullTerminator=*/true, isVolatile); } -llvm::MemoryBuffer *FileManager:: -getBufferForFile(StringRef Filename, std::string *ErrorStr) { - std::unique_ptr<llvm::MemoryBuffer> Result; - std::error_code ec; - if (FileSystemOpts.WorkingDir.empty()) { - ec = FS->getBufferForFile(Filename, Result); - if (ec && ErrorStr) - *ErrorStr = ec.message(); - return Result.release(); - } +llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> +FileManager::getBufferForFile(StringRef Filename) { + if (FileSystemOpts.WorkingDir.empty()) + return FS->getBufferForFile(Filename); SmallString<128> FilePath(Filename); FixupRelativePath(FilePath); - ec = FS->getBufferForFile(FilePath.c_str(), Result); - if (ec && ErrorStr) - *ErrorStr = ec.message(); - return Result.release(); + return FS->getBufferForFile(FilePath.c_str()); } /// getStatValue - Get the 'stat' information for the specified path, @@ -512,15 +513,47 @@ void FileManager::modifyFileEntry(FileEntry *File, File->ModTime = ModificationTime; } +/// Remove '.' path components from the given absolute path. +/// \return \c true if any changes were made. +// FIXME: Move this to llvm::sys::path. +bool FileManager::removeDotPaths(SmallVectorImpl<char> &Path) { + using namespace llvm::sys; + + SmallVector<StringRef, 16> ComponentStack; + StringRef P(Path.data(), Path.size()); + + // Skip the root path, then look for traversal in the components. + StringRef Rel = path::relative_path(P); + bool AnyDots = false; + for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) { + if (C == ".") { + AnyDots = true; + continue; + } + ComponentStack.push_back(C); + } + + if (!AnyDots) + return false; + + SmallString<256> Buffer = path::root_path(P); + for (StringRef C : ComponentStack) + path::append(Buffer, C); + + Path.swap(Buffer); + return true; +} + StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) { // FIXME: use llvm::sys::fs::canonical() when it gets implemented -#ifdef LLVM_ON_UNIX llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known = CanonicalDirNames.find(Dir); if (Known != CanonicalDirNames.end()) return Known->second; StringRef CanonicalName(Dir->getName()); + +#ifdef LLVM_ON_UNIX char CanonicalNameBuf[PATH_MAX]; if (realpath(Dir->getName(), CanonicalNameBuf)) { unsigned Len = strlen(CanonicalNameBuf); @@ -528,12 +561,15 @@ StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) { memcpy(Mem, CanonicalNameBuf, Len); CanonicalName = StringRef(Mem, Len); } +#else + SmallString<256> CanonicalNameBuf(CanonicalName); + llvm::sys::fs::make_absolute(CanonicalNameBuf); + llvm::sys::path::native(CanonicalNameBuf); + removeDotPaths(CanonicalNameBuf); +#endif CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName)); return CanonicalName; -#else - return StringRef(Dir->getName()); -#endif } void FileManager::PrintStats() const { diff --git a/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp index 7515cfb..83e42bd 100644 --- a/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp @@ -78,21 +78,20 @@ 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. - std::unique_ptr<vfs::File> OwnedFile; - std::error_code EC = FS.openFileForRead(Path, OwnedFile); + auto OwnedFile = FS.openFileForRead(Path); - if (EC) { + if (!OwnedFile) { // If the open fails, our "stat" fails. R = CacheMissing; } else { // 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::ErrorOr<vfs::Status> Status = OwnedFile->status(); + llvm::ErrorOr<vfs::Status> Status = (*OwnedFile)->status(); if (Status) { R = CacheExists; copyStatusToFileData(*Status, Data); - *F = std::move(OwnedFile); + *F = std::move(*OwnedFile); } else { // fstat rarely fails. If it does, claim the initial open didn't // succeed. diff --git a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp index 2198459..613b43f 100644 --- a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp @@ -110,49 +110,59 @@ namespace { HALFSUPPORT = 0x04000, KEYALL = (0xffff & ~KEYNOMS) // Because KEYNOMS is used to exclude. }; + + /// \brief How a keyword is treated in the selected standard. + enum KeywordStatus { + KS_Disabled, // Disabled + KS_Extension, // Is an extension + KS_Enabled, // Enabled + KS_Future // Is a keyword in future standard + }; +} + +/// \brief Translates flags as specified in TokenKinds.def into keyword status +/// in the given language standard. +static KeywordStatus getKeywordStatus(const LangOptions &LangOpts, + unsigned Flags) { + if (Flags == KEYALL) return KS_Enabled; + if (LangOpts.CPlusPlus && (Flags & KEYCXX)) return KS_Enabled; + if (LangOpts.CPlusPlus11 && (Flags & KEYCXX11)) return KS_Enabled; + if (LangOpts.C99 && (Flags & KEYC99)) return KS_Enabled; + if (LangOpts.GNUKeywords && (Flags & KEYGNU)) return KS_Extension; + if (LangOpts.MicrosoftExt && (Flags & KEYMS)) return KS_Extension; + if (LangOpts.Borland && (Flags & KEYBORLAND)) return KS_Extension; + if (LangOpts.Bool && (Flags & BOOLSUPPORT)) return KS_Enabled; + if (LangOpts.Half && (Flags & HALFSUPPORT)) return KS_Enabled; + if (LangOpts.WChar && (Flags & WCHARSUPPORT)) return KS_Enabled; + if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) return KS_Enabled; + if (LangOpts.OpenCL && (Flags & KEYOPENCL)) return KS_Enabled; + if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) return KS_Enabled; + if (LangOpts.C11 && (Flags & KEYC11)) return KS_Enabled; + // We treat bridge casts as objective-C keywords so we can warn on them + // in non-arc mode. + if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled; + if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) return KS_Future; + return KS_Disabled; } /// AddKeyword - This method is used to associate a token ID with specific /// identifiers because they are language keywords. This causes the lexer to /// automatically map matching identifiers to specialized token codes. -/// -/// The C90/C99/CPP/CPP0x flags are set to 3 if the token is a keyword in a -/// future language standard, set to 2 if the token should be enabled in the -/// specified language, set to 1 if it is an extension in the specified -/// language, and set to 0 if disabled in the specified language. static void AddKeyword(StringRef Keyword, tok::TokenKind TokenCode, unsigned Flags, const LangOptions &LangOpts, IdentifierTable &Table) { - unsigned AddResult = 0; - if (Flags == KEYALL) AddResult = 2; - else if (LangOpts.CPlusPlus && (Flags & KEYCXX)) AddResult = 2; - else if (LangOpts.CPlusPlus11 && (Flags & KEYCXX11)) AddResult = 2; - else if (LangOpts.C99 && (Flags & KEYC99)) AddResult = 2; - else if (LangOpts.GNUKeywords && (Flags & KEYGNU)) AddResult = 1; - 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; - else if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) AddResult = 2; - else if (LangOpts.C11 && (Flags & KEYC11)) AddResult = 2; - // We treat bridge casts as objective-C keywords so we can warn on them - // in non-arc mode. - else if (LangOpts.ObjC2 && (Flags & KEYARC)) AddResult = 2; - else if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) AddResult = 3; + KeywordStatus AddResult = getKeywordStatus(LangOpts, Flags); // 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; + if (AddResult == KS_Disabled) return; IdentifierInfo &Info = - Table.get(Keyword, AddResult == 3 ? tok::identifier : TokenCode); - Info.setIsExtensionToken(AddResult == 1); - Info.setIsCXX11CompatKeyword(AddResult == 3); + Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode); + Info.setIsExtensionToken(AddResult == KS_Extension); + Info.setIsCXX11CompatKeyword(AddResult == KS_Future); } /// AddCXXOperatorKeyword - Register a C++ operator keyword alternative @@ -199,6 +209,31 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) { LangOpts, *this); } +/// \brief Checks if the specified token kind represents a keyword in the +/// specified language. +/// \returns Status of the keyword in the language. +static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts, + tok::TokenKind K) { + switch (K) { +#define KEYWORD(NAME, FLAGS) \ + case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS); +#include "clang/Basic/TokenKinds.def" + default: return KS_Disabled; + } +} + +/// \brief Returns true if the identifier represents a keyword in the +/// specified language. +bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) { + switch (getTokenKwStatus(LangOpts, getTokenID())) { + case KS_Enabled: + case KS_Extension: + return true; + default: + return false; + } +} + tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const { // We use a perfect hash function here involving the length of the keyword, // the first and third character. For preprocessor ID's there are no @@ -428,6 +463,7 @@ ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) { if (name == "retain") return OMF_retain; if (name == "retainCount") return OMF_retainCount; if (name == "self") return OMF_self; + if (name == "initialize") return OMF_initialize; } if (name == "performSelector") return OMF_performSelector; @@ -486,6 +522,33 @@ ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) { return OIT_None; } +ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) { + IdentifierInfo *first = sel.getIdentifierInfoForSlot(0); + if (!first) return SFF_None; + + StringRef name = first->getName(); + + switch (name.front()) { + case 'a': + if (name == "appendFormat") return SFF_NSString; + break; + + case 'i': + if (name == "initWithFormat") return SFF_NSString; + break; + + case 'l': + if (name == "localizedStringWithFormat") return SFF_NSString; + break; + + case 's': + if (name == "stringByAppendingFormat" || + name == "stringWithFormat") return SFF_NSString; + break; + } + return SFF_None; +} + namespace { struct SelectorTableImpl { llvm::FoldingSet<MultiKeywordSelector> Table; diff --git a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp index f8714b2..dcbd228 100644 --- a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp @@ -14,14 +14,10 @@ using namespace clang; -const SanitizerOptions SanitizerOptions::Disabled = {}; - LangOptions::LangOptions() { #define LANGOPT(Name, Bits, Default, Description) Name = Default; #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default); #include "clang/Basic/LangOptions.def" - - Sanitize = SanitizerOptions::Disabled; } void LangOptions::resetNonModularOptions() { @@ -33,8 +29,10 @@ void LangOptions::resetNonModularOptions() { // FIXME: This should not be reset; modules can be different with different // sanitizer options (this affects __has_feature(address_sanitizer) etc). - Sanitize = SanitizerOptions::Disabled; + Sanitize.clear(); + SanitizerBlacklistFile.clear(); CurrentModule.clear(); + ImplementationOfModule.clear(); } diff --git a/contrib/llvm/tools/clang/lib/Basic/Module.cpp b/contrib/llvm/tools/clang/lib/Basic/Module.cpp index f689c73..03f9bd3 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Module.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Module.cpp @@ -25,8 +25,8 @@ using namespace clang; Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, - const FileEntry *File, bool IsFramework, bool IsExplicit) - : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), ModuleMap(File), + bool IsFramework, bool IsExplicit) + : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), Directory(), Umbrella(), ASTFile(nullptr), IsMissingRequirement(false), IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false), IsExternC(false), @@ -70,9 +70,9 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, .Default(Target.hasFeature(Feature)); } -bool -Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, - Requirement &Req, HeaderDirective &MissingHeader) const { +bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, + Requirement &Req, + UnresolvedHeaderDirective &MissingHeader) const { if (IsAvailable) return true; @@ -293,9 +293,12 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { OS << "explicit "; OS << "module " << Name; - if (IsSystem) { + if (IsSystem || IsExternC) { OS.indent(Indent + 2); - OS << " [system]"; + if (IsSystem) + OS << " [system]"; + if (IsExternC) + OS << " [extern_c]"; } OS << " {\n"; @@ -338,30 +341,31 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { OS << "\n"; } - for (unsigned I = 0, N = NormalHeaders.size(); I != N; ++I) { - OS.indent(Indent + 2); - OS << "header \""; - OS.write_escaped(NormalHeaders[I]->getName()); - OS << "\"\n"; - } - - for (unsigned I = 0, N = ExcludedHeaders.size(); I != N; ++I) { - OS.indent(Indent + 2); - OS << "exclude header \""; - OS.write_escaped(ExcludedHeaders[I]->getName()); - OS << "\"\n"; + struct { + StringRef Prefix; + HeaderKind Kind; + } Kinds[] = {{"", HK_Normal}, + {"textual ", HK_Textual}, + {"private ", HK_Private}, + {"private textual ", HK_PrivateTextual}, + {"exclude ", HK_Excluded}}; + + for (auto &K : Kinds) { + for (auto &H : Headers[K.Kind]) { + OS.indent(Indent + 2); + OS << K.Prefix << "header \""; + OS.write_escaped(H.NameAsWritten); + OS << "\"\n"; + } } - for (unsigned I = 0, N = PrivateHeaders.size(); I != N; ++I) { - OS.indent(Indent + 2); - OS << "private header \""; - OS.write_escaped(PrivateHeaders[I]->getName()); - OS << "\"\n"; - } - for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end(); MI != MIEnd; ++MI) - if (!(*MI)->IsInferred) + // Print inferred subframework modules so that we don't need to re-infer + // them (requires expensive directory iteration + stat calls) when we build + // the module. Regular inferred submodules are OK, as we need to look at all + // those header files anyway. + if (!(*MI)->IsInferred || (*MI)->IsFramework) (*MI)->print(OS, Indent + 2); for (unsigned I = 0, N = Exports.size(); I != N; ++I) { diff --git a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp index 06f010f..6e98d48 100644 --- a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp @@ -46,6 +46,10 @@ const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) { } OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) { + // 'flush' clause cannot be specified explicitly, because this is an implicit + // clause for 'flush' directive. If the 'flush' clause is explicitly specified + // the Parser should generate a warning about extra tokens at the end of the + // directive. if (Str == "flush") return OMPC_unknown; return llvm::StringSwitch<OpenMPClauseKind>(Str) @@ -108,6 +112,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_untied: case OMPC_mergeable: case OMPC_flush: + case OMPC_read: + case OMPC_write: + case OMPC_update: + case OMPC_capture: + case OMPC_seq_cst: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); @@ -167,6 +176,11 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_untied: case OMPC_mergeable: case OMPC_flush: + case OMPC_read: + case OMPC_write: + case OMPC_update: + case OMPC_capture: + case OMPC_seq_cst: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); @@ -207,6 +221,16 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, break; } break; + case OMPD_for_simd: + switch (CKind) { +#define OPENMP_FOR_SIMD_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) \ @@ -237,6 +261,16 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, break; } break; + case OMPD_parallel_for_simd: + switch (CKind) { +#define OPENMP_PARALLEL_FOR_SIMD_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) \ @@ -260,6 +294,36 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, case OMPD_flush: return CKind == OMPC_flush; break; + case OMPD_atomic: + switch (CKind) { +#define OPENMP_ATOMIC_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_target: + switch (CKind) { +#define OPENMP_TARGET_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_teams: + switch (CKind) { +#define OPENMP_TEAMS_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; case OMPD_unknown: case OMPD_threadprivate: case OMPD_section: @@ -268,29 +332,39 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: + case OMPD_ordered: break; } return false; } bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) { - return DKind == OMPD_simd || DKind == OMPD_for || - DKind == OMPD_parallel_for; // TODO add next directives. + return DKind == OMPD_simd || DKind == OMPD_for || DKind == OMPD_for_simd || + DKind == OMPD_parallel_for || + DKind == OMPD_parallel_for_simd; // TODO add next directives. } bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) { - return DKind == OMPD_for || DKind == OMPD_sections || DKind == OMPD_section || + return DKind == OMPD_for || DKind == OMPD_for_simd || + DKind == OMPD_sections || DKind == OMPD_section || DKind == OMPD_single || DKind == OMPD_parallel_for || + DKind == OMPD_parallel_for_simd || DKind == OMPD_parallel_sections; // TODO add next directives. } bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) { return DKind == OMPD_parallel || DKind == OMPD_parallel_for || + DKind == OMPD_parallel_for_simd || DKind == OMPD_parallel_sections; // TODO add next directives. } +bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) { + return DKind == OMPD_teams; // TODO add next directives. +} + bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) { - return DKind == OMPD_simd; // TODO || DKind == OMPD_for_simd || ... + return DKind == OMPD_simd || DKind == OMPD_for_simd || + DKind == OMPD_parallel_for_simd; // TODO add next directives. } bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) { diff --git a/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp b/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp new file mode 100644 index 0000000..ea5b8d0 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp @@ -0,0 +1,46 @@ +//===--- SanitizerBlacklist.cpp - Blacklist for sanitizers ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// User-provided blacklist used to disable/alter instrumentation done in +// sanitizers. +// +//===----------------------------------------------------------------------===// +#include "clang/Basic/SanitizerBlacklist.h" + +using namespace clang; + +SanitizerBlacklist::SanitizerBlacklist(StringRef BlacklistPath, + SourceManager &SM) + : SCL(llvm::SpecialCaseList::createOrDie(BlacklistPath)), SM(SM) {} + +bool SanitizerBlacklist::isBlacklistedGlobal(StringRef GlobalName, + StringRef Category) const { + return SCL->inSection("global", GlobalName, Category); +} + +bool SanitizerBlacklist::isBlacklistedType(StringRef MangledTypeName, + StringRef Category) const { + return SCL->inSection("type", MangledTypeName, Category); +} + +bool SanitizerBlacklist::isBlacklistedFunction(StringRef FunctionName) const { + return SCL->inSection("fun", FunctionName); +} + +bool SanitizerBlacklist::isBlacklistedFile(StringRef FileName, + StringRef Category) const { + return SCL->inSection("src", FileName, Category); +} + +bool SanitizerBlacklist::isBlacklistedLocation(SourceLocation Loc, + StringRef Category) const { + return !Loc.isInvalid() && + isBlacklistedFile(SM.getFilename(SM.getFileLoc(Loc)), Category); +} + diff --git a/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp b/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp new file mode 100644 index 0000000..e9aaa36 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp @@ -0,0 +1,35 @@ +//===--- Sanitizers.cpp - C Language Family Language Options ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the classes from Sanitizers.h +// +//===----------------------------------------------------------------------===// +#include "clang/Basic/Sanitizers.h" + +using namespace clang; + +SanitizerSet::SanitizerSet() : Kinds(0) {} + +bool SanitizerSet::has(SanitizerKind K) const { + unsigned Bit = static_cast<unsigned>(K); + return Kinds & (1 << Bit); +} + +void SanitizerSet::set(SanitizerKind K, bool Value) { + unsigned Bit = static_cast<unsigned>(K); + Kinds = Value ? (Kinds | (1 << Bit)) : (Kinds & ~(1 << Bit)); +} + +void SanitizerSet::clear() { + Kinds = 0; +} + +bool SanitizerSet::empty() const { + return Kinds == 0; +} diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp index 0c06a48c..6b885a7 100644 --- a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp @@ -132,13 +132,9 @@ const char *FullSourceLoc::getCharacterData(bool *Invalid) const { return SrcMgr->getCharacterData(*this, Invalid); } -const llvm::MemoryBuffer* FullSourceLoc::getBuffer(bool *Invalid) const { - assert(isValid()); - return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid); -} - StringRef FullSourceLoc::getBufferData(bool *Invalid) const { - return getBuffer(Invalid)->getBuffer(); + assert(isValid()); + return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid)->getBuffer();; } std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const { diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp index 61dfe35..305dcd4 100644 --- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp @@ -94,11 +94,9 @@ llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, return Buffer.getPointer(); } - std::string ErrorStr; bool isVolatile = SM.userFilesAreVolatile() && !IsSystemFile; - Buffer.setPointer(SM.getFileManager().getBufferForFile(ContentsEntry, - &ErrorStr, - isVolatile)); + auto BufferOrError = + SM.getFileManager().getBufferForFile(ContentsEntry, isVolatile); // If we were unable to open the file, then we are in an inconsistent // situation where the content cache referenced a file which no longer @@ -110,27 +108,30 @@ llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, // currently handle returning a null entry here. Ideally we should detect // that we are in an inconsistent situation and error out as quickly as // possible. - if (!Buffer.getPointer()) { - const StringRef FillStr("<<<MISSING SOURCE FILE>>>\n"); - Buffer.setPointer(MemoryBuffer::getNewMemBuffer(ContentsEntry->getSize(), - "<invalid>")); + if (!BufferOrError) { + StringRef FillStr("<<<MISSING SOURCE FILE>>>\n"); + Buffer.setPointer(MemoryBuffer::getNewMemBuffer(ContentsEntry->getSize(), + "<invalid>").release()); char *Ptr = const_cast<char*>(Buffer.getPointer()->getBufferStart()); for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i) Ptr[i] = FillStr[i % FillStr.size()]; if (Diag.isDiagnosticInFlight()) - Diag.SetDelayedDiagnostic(diag::err_cannot_open_file, - ContentsEntry->getName(), ErrorStr); - else + Diag.SetDelayedDiagnostic(diag::err_cannot_open_file, + ContentsEntry->getName(), + BufferOrError.getError().message()); + else Diag.Report(Loc, diag::err_cannot_open_file) - << ContentsEntry->getName() << ErrorStr; + << ContentsEntry->getName() << BufferOrError.getError().message(); Buffer.setInt(Buffer.getInt() | InvalidFlag); if (Invalid) *Invalid = true; return Buffer.getPointer(); } - + + Buffer.setPointer(BufferOrError->release()); + // Check that the file's size is the same as in the file entry (which may // have come from a stat cache). if (getRawBuffer()->getBufferSize() != (size_t)ContentsEntry->getSize()) { @@ -176,17 +177,11 @@ llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, } unsigned LineTableInfo::getLineTableFilenameID(StringRef Name) { - // Look up the filename in the string table, returning the pre-existing value - // if it exists. - llvm::StringMapEntry<unsigned> &Entry = - FilenameIDs.GetOrCreateValue(Name, ~0U); - if (Entry.getValue() != ~0U) - return Entry.getValue(); - - // Otherwise, assign this the next available ID. - Entry.setValue(FilenamesByID.size()); - FilenamesByID.push_back(&Entry); - return FilenamesByID.size()-1; + auto IterBool = + FilenameIDs.insert(std::make_pair(Name, FilenamesByID.size())); + if (IterBool.second) + FilenamesByID.push_back(&*IterBool.first); + return IterBool.first->second; } /// AddLineNote - Add a line note to the line table that indicates that there @@ -373,8 +368,7 @@ SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true), UserFilesAreVolatile(UserFilesAreVolatile), ExternalSLocEntries(nullptr), LineTable(nullptr), NumLinearScans(0), - NumBinaryProbes(0), FakeBufferForRecovery(nullptr), - FakeContentCacheForRecovery(nullptr) { + NumBinaryProbes(0) { clearIDTables(); Diag.setSourceManager(this); } @@ -398,9 +392,6 @@ SourceManager::~SourceManager() { ContentCacheAlloc.Deallocate(I->second); } } - - delete FakeBufferForRecovery; - delete FakeContentCacheForRecovery; llvm::DeleteContainerSeconds(MacroArgsCacheMap); } @@ -460,13 +451,13 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt, /// createMemBufferContentCache - Create a new ContentCache for the specified /// memory buffer. This does no caching. -const ContentCache * -SourceManager::createMemBufferContentCache(llvm::MemoryBuffer *Buffer) { +const ContentCache *SourceManager::createMemBufferContentCache( + std::unique_ptr<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); + Entry->setBuffer(std::move(Buffer)); return Entry; } @@ -505,10 +496,10 @@ SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries, /// fake, non-empty buffer. llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { if (!FakeBufferForRecovery) - FakeBufferForRecovery - = llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>"); - - return FakeBufferForRecovery; + FakeBufferForRecovery = + llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>"); + + return FakeBufferForRecovery.get(); } /// \brief As part of recovering from missing or changed content, produce a @@ -516,11 +507,11 @@ llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { const SrcMgr::ContentCache * SourceManager::getFakeContentCacheForRecovery() const { if (!FakeContentCacheForRecovery) { - FakeContentCacheForRecovery = new ContentCache(); + FakeContentCacheForRecovery = llvm::make_unique<SrcMgr::ContentCache>(); FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(), /*DoNotFree=*/true); } - return FakeContentCacheForRecovery; + return FakeContentCacheForRecovery.get(); } /// \brief Returns the previous in-order FileID or an invalid FileID if there diff --git a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp index aecf13b..6987cd7 100644 --- a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp @@ -338,6 +338,8 @@ bool TargetInfo::isValidGCCRegisterName(StringRef Name) const { // Get rid of any register prefix. Name = removeGCCRegisterPrefix(Name); + if (Name.empty()) + return false; getGCCRegNames(Names, NumNames); @@ -457,7 +459,9 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const { // Eventually, an unknown constraint should just be treated as 'g'. return false; } + break; case '&': // early clobber. + Info.setEarlyClobber(); break; case '%': // commutative. // FIXME: Check that there is a another register after this one. @@ -482,9 +486,12 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const { if (Name[1] == '=' || Name[1] == '+') Name++; break; + case '#': // Ignore as constraint. + while (Name[1] && Name[1] != ',') + Name++; + break; case '?': // Disparage slightly code. case '!': // Disparage severely. - case '#': // Ignore as constraint. case '*': // Ignore for choosing register preferences. break; // Pass them. } @@ -492,6 +499,11 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const { Name++; } + // Early clobber with a read-write constraint which doesn't permit registers + // is invalid. + if (Info.earlyClobber() && Info.isReadWrite() && !Info.allowsRegister()) + return false; + // If a constraint allows neither memory nor register operands it contains // only modifiers. Reject it. return Info.allowsMemory() || Info.allowsRegister(); @@ -534,11 +546,17 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints, default: // Check if we have a matching constraint if (*Name >= '0' && *Name <= '9') { - unsigned i = *Name - '0'; + const char *DigitStart = Name; + while (Name[1] >= '0' && Name[1] <= '9') + Name++; + const char *DigitEnd = Name; + unsigned i; + if (StringRef(DigitStart, DigitEnd - DigitStart + 1) + .getAsInteger(10, i)) + return false; // Check if matching constraint is out of bounds. - if (i >= NumOutputs) - return false; + if (i >= NumOutputs) return false; // A number must refer to an output only operand. if (OutputConstraints[i].isReadWrite()) @@ -569,6 +587,10 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints, if (Info.hasTiedOperand() && Info.getTiedOperand() != Index) return false; + // A number must refer to an output only operand. + if (OutputConstraints[Index].isReadWrite()) + return false; + Info.setTiedOperand(Index, OutputConstraints[Index]); break; } @@ -586,6 +608,8 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints, case 'N': case 'O': case 'P': + if (!validateAsmConstraint(Name, Info)) + return false; break; case 'r': // general register. Info.setAllowsRegister(); @@ -608,9 +632,12 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints, break; case ',': // multiple alternative constraint. Ignore comma. break; + case '#': // Ignore as constraint. + while (Name[1] && Name[1] != ',') + Name++; + break; case '?': // Disparage slightly code. case '!': // Disparage severely. - case '#': // Ignore as constraint. case '*': // Ignore for choosing register preferences. break; // Pass them. } diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp index 728e9c0..4c64a02 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp @@ -21,6 +21,7 @@ #include "clang/Basic/TargetOptions.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" @@ -93,7 +94,8 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, Builder.defineMacro("OBJC_NEW_PROPERTIES"); // AddressSanitizer doesn't play well with source fortification, which is on // by default on Darwin. - if (Opts.Sanitize.Address) Builder.defineMacro("_FORTIFY_SOURCE", "0"); + if (Opts.Sanitize.has(SanitizerKind::Address)) + Builder.defineMacro("_FORTIFY_SOURCE", "0"); if (!Opts.ObjCAutoRefCount) { // __weak is always defined, for use in blocks and with objc pointers. @@ -271,6 +273,12 @@ protected: // On FreeBSD, wchar_t contains the number of the code point as // used by the character set of the locale. These character sets are // not necessarily a superset of ASCII. + // + // FIXME: This is wrong; the macro refers to the numerical values + // of wchar_t *literals*, which are not locale-dependent. However, + // FreeBSD systems apparently depend on us getting this wrong, and + // setting this to 1 is conforming even if all the basic source + // character literals have the same encoding as char and wchar_t. Builder.defineMacro("__STDC_MB_MIGHT_NEQ_WC__", "1"); } public: @@ -315,7 +323,8 @@ protected: Builder.defineMacro("_GNU_SOURCE"); } public: - KFreeBSDTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { + KFreeBSDTargetInfo(const llvm::Triple &Triple) + : OSTargetInfo<Target>(Triple) { this->UserLabelPrefix = ""; } }; @@ -516,27 +525,6 @@ public: } }; -// AuroraUX target -template<typename Target> -class AuroraUXTargetInfo : public OSTargetInfo<Target> { -protected: - void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const override { - DefineStd(Builder, "sun", Opts); - DefineStd(Builder, "unix", Opts); - Builder.defineMacro("__ELF__"); - Builder.defineMacro("__svr4__"); - Builder.defineMacro("__SVR4"); - } -public: - AuroraUXTargetInfo(const llvm::Triple &Triple) - : OSTargetInfo<Target>(Triple) { - this->UserLabelPrefix = ""; - this->WCharType = this->SignedLong; - // FIXME: WIntType should be SignedLong - } -}; - // Solaris target template<typename Target> class SolarisTargetInfo : public OSTargetInfo<Target> { @@ -551,8 +539,8 @@ protected: // Solaris headers require _XOPEN_SOURCE to be set to 600 for C99 and // newer, but to 500 for everything else. feature_test.h has a check to // ensure that you are not using C99 with an old version of X/Open or C89 - // with a new version. - if (Opts.C99 || Opts.C11) + // with a new version. + if (Opts.C99) Builder.defineMacro("_XOPEN_SOURCE", "600"); else Builder.defineMacro("_XOPEN_SOURCE", "500"); @@ -658,7 +646,8 @@ public: // RegParmMax is inherited from the underlying architecture this->LongDoubleFormat = &llvm::APFloat::IEEEdouble; if (Triple.getArch() == llvm::Triple::arm) { - this->DescriptionString = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S128"; + this->DescriptionString = + "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-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) { @@ -692,10 +681,14 @@ class PPCTargetInfo : public TargetInfo { // Target cpu features. bool HasVSX; + bool HasP8Vector; + +protected: + std::string ABI; public: PPCTargetInfo(const llvm::Triple &Triple) - : TargetInfo(Triple), HasVSX(false) { + : TargetInfo(Triple), HasVSX(false), HasP8Vector(false) { BigEndian = (Triple.getArch() != llvm::Triple::ppc64le); LongDoubleWidth = LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble; @@ -781,6 +774,9 @@ public: return CPUKnown; } + + StringRef getABI() const override { return ABI; } + void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const override { Records = BuiltinInfo; @@ -932,11 +928,10 @@ const Builtin::Info PPCTargetInfo::BuiltinInfo[] = { #include "clang/Basic/BuiltinsPPC.def" }; - /// handleTargetFeatures - Perform initialization based on the user +/// handleTargetFeatures - Perform initialization based on the user /// configured set of features. bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, DiagnosticsEngine &Diags) { - // Remember the maximum enabled sselevel. for (unsigned i = 0, e = Features.size(); i !=e; ++i) { // Ignore disabled features. if (Features[i][0] == '-') @@ -949,6 +944,11 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, continue; } + if (Feature == "power8-vector") { + HasP8Vector = true; + continue; + } + // TODO: Finish this list and add an assert that we've handled them // all. } @@ -976,13 +976,18 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, // Target properties. if (getTriple().getArch() == llvm::Triple::ppc64le) { 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"); } + // ABI options. + if (ABI == "elfv1") + Builder.defineMacro("_CALL_ELF", "1"); + if (ABI == "elfv2") + Builder.defineMacro("_CALL_ELF", "2"); + // Subtarget options. Builder.defineMacro("__NATURAL_ALIGNMENT__"); Builder.defineMacro("__REGISTER_PREFIX__", ""); @@ -1094,6 +1099,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, if (HasVSX) Builder.defineMacro("__VSX__"); + if (HasP8Vector) + Builder.defineMacro("__POWER8_VECTOR__"); // FIXME: The following are not yet generated here by Clang, but are // generated by GCC: @@ -1132,13 +1139,19 @@ void PPCTargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { .Default(false); Features["qpx"] = (CPU == "a2q"); + + if (!ABI.empty()) + Features[ABI] = true; } bool PPCTargetInfo::hasFeature(StringRef Feature) const { - return Feature == "powerpc"; + return llvm::StringSwitch<bool>(Feature) + .Case("powerpc", true) + .Case("vsx", HasVSX) + .Case("power8-vector", HasP8Vector) + .Default(false); } - const char * const PPCTargetInfo::GCCRegNames[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", @@ -1287,17 +1300,26 @@ public: IntMaxType = SignedLong; Int64Type = SignedLong; - if (getTriple().getOS() == llvm::Triple::FreeBSD) { + if ((Triple.getArch() == llvm::Triple::ppc64le)) { + DescriptionString = "e-m:e-i64:64-n32:64"; + ABI = "elfv2"; + } else { + DescriptionString = "E-m:e-i64:64-n32:64"; + ABI = "elfv1"; + } + + switch (getTriple().getOS()) { + case llvm::Triple::FreeBSD: LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble; - 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"; - } -} + break; + case llvm::Triple::NetBSD: + IntMaxType = SignedLongLong; + Int64Type = SignedLongLong; + break; + default: + break; + } // PPC64 supports atomics up to 8 bytes. MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; @@ -1305,6 +1327,14 @@ public: BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::CharPtrBuiltinVaList; } + // PPC64 Linux-specifc ABI options. + bool setABI(const std::string &Name) override { + if (Name == "elfv1" || Name == "elfv2") { + ABI = Name; + return true; + } + return false; + } }; } // end anonymous namespace. @@ -1317,7 +1347,7 @@ public: : DarwinTargetInfo<PPC32TargetInfo>(Triple) { HasAlignMac68kSupport = true; BoolWidth = BoolAlign = 32; //XXX support -mone-byte-bool? - PtrDiffType = SignedInt; // for http://llvm.org/bugs/show_bug.cgi?id=15726 + PtrDiffType = SignedInt; // for http://llvm.org/bugs/show_bug.cgi?id=15726 LongLongAlign = 32; SuitableAlign = 128; DescriptionString = "E-m:o-p:32:32-f64:32:64-n32"; @@ -1344,6 +1374,8 @@ namespace { 1, // opencl_global 3, // opencl_local 4, // opencl_constant + // FIXME: generic has to be added to the target + 0, // opencl_generic 1, // cuda_device 4, // cuda_constant 3, // cuda_shared @@ -1351,6 +1383,16 @@ namespace { class NVPTXTargetInfo : public TargetInfo { static const char * const GCCRegNames[]; static const Builtin::Info BuiltinInfo[]; + + // The GPU profiles supported by the NVPTX backend + enum GPUKind { + GK_NONE, + GK_SM20, + GK_SM21, + GK_SM30, + GK_SM35, + } GPU; + public: NVPTXTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { BigEndian = false; @@ -1361,11 +1403,34 @@ namespace { // Define available target features // These must be defined in sorted order! NoAsmVariants = true; + // Set the default GPU to sm20 + GPU = GK_SM20; } void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override { Builder.defineMacro("__PTX__"); Builder.defineMacro("__NVPTX__"); + if (Opts.CUDAIsDevice) { + // Set __CUDA_ARCH__ for the GPU specified. + std::string CUDAArchCode; + switch (GPU) { + case GK_SM20: + CUDAArchCode = "200"; + break; + case GK_SM21: + CUDAArchCode = "210"; + break; + case GK_SM30: + CUDAArchCode = "300"; + break; + case GK_SM35: + CUDAArchCode = "350"; + break; + default: + llvm_unreachable("Unhandled target CPU"); + } + Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode); + } } void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const override { @@ -1384,8 +1449,9 @@ namespace { Aliases = nullptr; NumAliases = 0; } - bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const override { + bool + validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { switch (*Name) { default: return false; case 'c': @@ -1407,14 +1473,14 @@ namespace { return TargetInfo::CharPtrBuiltinVaList; } bool setCPU(const std::string &Name) override { - bool Valid = llvm::StringSwitch<bool>(Name) - .Case("sm_20", true) - .Case("sm_21", true) - .Case("sm_30", true) - .Case("sm_35", true) - .Default(false); + GPU = llvm::StringSwitch<GPUKind>(Name) + .Case("sm_20", GK_SM20) + .Case("sm_21", GK_SM21) + .Case("sm_30", GK_SM30) + .Case("sm_35", GK_SM35) + .Default(GK_NONE); - return Valid; + return GPU != GK_NONE; } }; @@ -1462,11 +1528,15 @@ static const unsigned R600AddrSpaceMap[] = { 1, // opencl_global 3, // opencl_local 2, // opencl_constant + 4, // opencl_generic 1, // cuda_device 2, // cuda_constant 3 // cuda_shared }; +// If you edit the description strings, make sure you update +// getPointerWidthV(). + static const char *DescriptionStringR600 = "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"; @@ -1506,6 +1576,20 @@ public: UseAddrSpaceMapMangling = true; } + uint64_t getPointerWidthV(unsigned AddrSpace) const override { + if (GPU <= GK_CAYMAN) + return 32; + + switch(AddrSpace) { + default: + return 64; + case 0: + case 3: + case 5: + return 32; + } + } + const char * getClobbers() const override { return ""; } @@ -1573,6 +1657,7 @@ public: .Case("pitcairn", GK_SOUTHERN_ISLANDS) .Case("verde", GK_SOUTHERN_ISLANDS) .Case("oland", GK_SOUTHERN_ISLANDS) + .Case("hainan", GK_SOUTHERN_ISLANDS) .Case("bonaire", GK_SEA_ISLANDS) .Case("kabini", GK_SEA_ISLANDS) .Case("kaveri", GK_SEA_ISLANDS) @@ -1669,16 +1754,19 @@ class X86TargetInfo : public TargetInfo { bool HasPCLMUL; bool HasLZCNT; bool HasRDRND; + bool HasFSGSBASE; bool HasBMI; bool HasBMI2; bool HasPOPCNT; bool HasRTM; bool HasPRFCHW; bool HasRDSEED; + bool HasADX; bool HasTBM; bool HasFMA; bool HasF16C; - bool HasAVX512CD, HasAVX512ER, HasAVX512PF; + bool HasAVX512CD, HasAVX512ER, HasAVX512PF, HasAVX512DQ, HasAVX512BW, + HasAVX512VL; bool HasSHA; bool HasCX16; @@ -1753,18 +1841,37 @@ class X86TargetInfo : public TargetInfo { /// \name Atom /// Atom processors //@{ - CK_Atom, + CK_Bonnell, CK_Silvermont, //@} /// \name Nehalem /// Nehalem microarchitecture based processors. - //@{ - CK_Corei7, - CK_Corei7AVX, - CK_CoreAVXi, - CK_CoreAVX2, - //@} + CK_Nehalem, + + /// \name Westmere + /// Westmere microarchitecture based processors. + CK_Westmere, + + /// \name Sandy Bridge + /// Sandy Bridge microarchitecture based processors. + CK_SandyBridge, + + /// \name Ivy Bridge + /// Ivy Bridge microarchitecture based processors. + CK_IvyBridge, + + /// \name Haswell + /// Haswell microarchitecture based processors. + CK_Haswell, + + /// \name Broadwell + /// Broadwell microarchitecture based processors. + CK_Broadwell, + + /// \name Skylake + /// Skylake microarchitecture based processors. + CK_Skylake, /// \name Knights Landing /// Knights Landing processor. @@ -1820,6 +1927,7 @@ class X86TargetInfo : public TargetInfo { /// This specification is deprecated and will be removed in the future. /// Users should prefer \see CK_K8. // FIXME: Warn on this when the CPU is set to it. + //@{ CK_x86_64, //@} @@ -1840,11 +1948,12 @@ public: X86TargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple), SSELevel(NoSSE), MMX3DNowLevel(NoMMX3DNow), XOPLevel(NoXOP), HasAES(false), HasPCLMUL(false), HasLZCNT(false), - HasRDRND(false), HasBMI(false), HasBMI2(false), HasPOPCNT(false), - HasRTM(false), HasPRFCHW(false), HasRDSEED(false), HasTBM(false), - HasFMA(false), HasF16C(false), HasAVX512CD(false), HasAVX512ER(false), - HasAVX512PF(false), HasSHA(false), HasCX16(false), CPU(CK_Generic), - FPMath(FP_Default) { + HasRDRND(false), HasFSGSBASE(false), HasBMI(false), HasBMI2(false), + HasPOPCNT(false), HasRTM(false), HasPRFCHW(false), HasRDSEED(false), + HasADX(false), HasTBM(false), HasFMA(false), HasF16C(false), + HasAVX512CD(false), HasAVX512ER(false), HasAVX512PF(false), + HasAVX512DQ(false), HasAVX512BW(false), HasAVX512VL(false), + HasSHA(false), HasCX16(false), CPU(CK_Generic), FPMath(FP_Default) { BigEndian = false; LongDoubleFormat = &llvm::APFloat::x87DoubleExtended; } @@ -1873,7 +1982,14 @@ public: NumNames = llvm::array_lengthof(AddlRegNames); } bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const override; + TargetInfo::ConstraintInfo &info) const override; + + bool validateOutputSize(StringRef Constraint, unsigned Size) const override; + + bool validateInputSize(StringRef Constraint, unsigned Size) const override; + + virtual bool validateOperandSize(StringRef Constraint, unsigned Size) const; + std::string convertConstraint(const char *&Constraint) const override; const char *getClobbers() const override { return "~{dirflag},~{fpsr},~{flags}"; @@ -1930,12 +2046,22 @@ public: .Case("nocona", CK_Nocona) .Case("core2", CK_Core2) .Case("penryn", CK_Penryn) - .Case("atom", CK_Atom) - .Case("slm", CK_Silvermont) - .Case("corei7", CK_Corei7) - .Case("corei7-avx", CK_Corei7AVX) - .Case("core-avx-i", CK_CoreAVXi) - .Case("core-avx2", CK_CoreAVX2) + .Case("bonnell", CK_Bonnell) + .Case("atom", CK_Bonnell) // Legacy name. + .Case("silvermont", CK_Silvermont) + .Case("slm", CK_Silvermont) // Legacy name. + .Case("nehalem", CK_Nehalem) + .Case("corei7", CK_Nehalem) // Legacy name. + .Case("westmere", CK_Westmere) + .Case("sandybridge", CK_SandyBridge) + .Case("corei7-avx", CK_SandyBridge) // Legacy name. + .Case("ivybridge", CK_IvyBridge) + .Case("core-avx-i", CK_IvyBridge) // Legacy name. + .Case("haswell", CK_Haswell) + .Case("core-avx2", CK_Haswell) // Legacy name. + .Case("broadwell", CK_Broadwell) + .Case("skylake", CK_Skylake) + .Case("skx", CK_Skylake) // Legacy name. .Case("knl", CK_KNL) .Case("k6", CK_K6) .Case("k6-2", CK_K6_2) @@ -1952,6 +2078,7 @@ public: .Case("k8-sse3", CK_K8SSE3) .Case("opteron", CK_Opteron) .Case("opteron-sse3", CK_OpteronSSE3) + .Case("barcelona", CK_AMDFAM10) .Case("amdfam10", CK_AMDFAM10) .Case("btver1", CK_BTVER1) .Case("btver2", CK_BTVER2) @@ -2008,12 +2135,15 @@ public: case CK_Nocona: case CK_Core2: case CK_Penryn: - case CK_Atom: + case CK_Bonnell: case CK_Silvermont: - case CK_Corei7: - case CK_Corei7AVX: - case CK_CoreAVXi: - case CK_CoreAVX2: + case CK_Nehalem: + case CK_Westmere: + case CK_SandyBridge: + case CK_IvyBridge: + case CK_Haswell: + case CK_Broadwell: + case CK_Skylake: case CK_KNL: case CK_Athlon64: case CK_Athlon64SSE3: @@ -2041,8 +2171,9 @@ public: // We accept all non-ARM calling conventions return (CC == CC_X86ThisCall || CC == CC_X86FastCall || - CC == CC_X86StdCall || - CC == CC_C || + CC == CC_X86StdCall || + CC == CC_X86VectorCall || + CC == CC_C || CC == CC_X86Pascal || CC == CC_IntelOclBicc) ? CCCR_OK : CCCR_Warning; } @@ -2082,10 +2213,13 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { break; case CK_PentiumMMX: case CK_Pentium2: + case CK_K6: + case CK_WinChipC6: setFeatureEnabledImpl(Features, "mmx", true); break; case CK_Pentium3: case CK_Pentium3M: + case CK_C3_2: setFeatureEnabledImpl(Features, "sse", true); break; case CK_PentiumM: @@ -2101,6 +2235,7 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { setFeatureEnabledImpl(Features, "cx16", true); break; case CK_Core2: + case CK_Bonnell: setFeatureEnabledImpl(Features, "ssse3", true); setFeatureEnabledImpl(Features, "cx16", true); break; @@ -2108,44 +2243,40 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { setFeatureEnabledImpl(Features, "sse4.1", true); setFeatureEnabledImpl(Features, "cx16", true); break; - case CK_Atom: - setFeatureEnabledImpl(Features, "ssse3", true); - setFeatureEnabledImpl(Features, "cx16", true); - break; - case CK_Silvermont: - setFeatureEnabledImpl(Features, "sse4.2", true); - setFeatureEnabledImpl(Features, "aes", true); - setFeatureEnabledImpl(Features, "cx16", true); - setFeatureEnabledImpl(Features, "pclmul", true); - break; - case CK_Corei7: - setFeatureEnabledImpl(Features, "sse4.2", true); - setFeatureEnabledImpl(Features, "cx16", true); - break; - case CK_Corei7AVX: - setFeatureEnabledImpl(Features, "avx", true); - setFeatureEnabledImpl(Features, "aes", true); - setFeatureEnabledImpl(Features, "cx16", true); - setFeatureEnabledImpl(Features, "pclmul", true); - break; - case CK_CoreAVXi: - setFeatureEnabledImpl(Features, "avx", true); - setFeatureEnabledImpl(Features, "aes", true); - setFeatureEnabledImpl(Features, "pclmul", true); - setFeatureEnabledImpl(Features, "rdrnd", true); - setFeatureEnabledImpl(Features, "f16c", true); - break; - case CK_CoreAVX2: + case CK_Skylake: + setFeatureEnabledImpl(Features, "avx512f", true); + setFeatureEnabledImpl(Features, "avx512cd", true); + setFeatureEnabledImpl(Features, "avx512dq", true); + setFeatureEnabledImpl(Features, "avx512bw", true); + setFeatureEnabledImpl(Features, "avx512vl", true); + // FALLTHROUGH + case CK_Broadwell: + setFeatureEnabledImpl(Features, "rdseed", true); + setFeatureEnabledImpl(Features, "adx", true); + // FALLTHROUGH + case CK_Haswell: setFeatureEnabledImpl(Features, "avx2", true); - setFeatureEnabledImpl(Features, "aes", true); - setFeatureEnabledImpl(Features, "pclmul", true); setFeatureEnabledImpl(Features, "lzcnt", true); - setFeatureEnabledImpl(Features, "rdrnd", true); - setFeatureEnabledImpl(Features, "f16c", true); setFeatureEnabledImpl(Features, "bmi", true); setFeatureEnabledImpl(Features, "bmi2", true); setFeatureEnabledImpl(Features, "rtm", true); setFeatureEnabledImpl(Features, "fma", true); + // FALLTHROUGH + case CK_IvyBridge: + setFeatureEnabledImpl(Features, "rdrnd", true); + setFeatureEnabledImpl(Features, "f16c", true); + setFeatureEnabledImpl(Features, "fsgsbase", true); + // FALLTHROUGH + case CK_SandyBridge: + setFeatureEnabledImpl(Features, "avx", true); + // FALLTHROUGH + case CK_Westmere: + case CK_Silvermont: + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "pclmul", true); + // FALLTHROUGH + case CK_Nehalem: + setFeatureEnabledImpl(Features, "sse4.2", true); setFeatureEnabledImpl(Features, "cx16", true); break; case CK_KNL: @@ -2153,19 +2284,19 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { setFeatureEnabledImpl(Features, "avx512cd", true); setFeatureEnabledImpl(Features, "avx512er", true); setFeatureEnabledImpl(Features, "avx512pf", true); - setFeatureEnabledImpl(Features, "aes", true); - setFeatureEnabledImpl(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "rdseed", true); + setFeatureEnabledImpl(Features, "adx", true); setFeatureEnabledImpl(Features, "lzcnt", true); - setFeatureEnabledImpl(Features, "rdrnd", true); - setFeatureEnabledImpl(Features, "f16c", true); setFeatureEnabledImpl(Features, "bmi", true); setFeatureEnabledImpl(Features, "bmi2", true); setFeatureEnabledImpl(Features, "rtm", true); setFeatureEnabledImpl(Features, "fma", true); - break; - case CK_K6: - case CK_WinChipC6: - setFeatureEnabledImpl(Features, "mmx", true); + setFeatureEnabledImpl(Features, "rdrnd", true); + setFeatureEnabledImpl(Features, "f16c", true); + setFeatureEnabledImpl(Features, "fsgsbase", true); + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "cx16", true); break; case CK_K6_2: case CK_K6_3: @@ -2191,43 +2322,29 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { setFeatureEnabledImpl(Features, "sse2", true); setFeatureEnabledImpl(Features, "3dnowa", true); break; + case CK_AMDFAM10: + setFeatureEnabledImpl(Features, "sse4a", true); + setFeatureEnabledImpl(Features, "lzcnt", true); + setFeatureEnabledImpl(Features, "popcnt", true); + // FALLTHROUGH case CK_K8SSE3: case CK_OpteronSSE3: case CK_Athlon64SSE3: setFeatureEnabledImpl(Features, "sse3", true); setFeatureEnabledImpl(Features, "3dnowa", true); break; - case CK_AMDFAM10: - setFeatureEnabledImpl(Features, "sse3", true); - setFeatureEnabledImpl(Features, "sse4a", true); - setFeatureEnabledImpl(Features, "3dnowa", true); - setFeatureEnabledImpl(Features, "lzcnt", true); - setFeatureEnabledImpl(Features, "popcnt", true); - break; - case CK_BTVER1: - setFeatureEnabledImpl(Features, "ssse3", true); - setFeatureEnabledImpl(Features, "sse4a", true); - setFeatureEnabledImpl(Features, "cx16", true); - setFeatureEnabledImpl(Features, "lzcnt", true); - setFeatureEnabledImpl(Features, "popcnt", true); - setFeatureEnabledImpl(Features, "prfchw", true); - break; case CK_BTVER2: setFeatureEnabledImpl(Features, "avx", true); - setFeatureEnabledImpl(Features, "sse4a", true); - setFeatureEnabledImpl(Features, "lzcnt", true); setFeatureEnabledImpl(Features, "aes", true); setFeatureEnabledImpl(Features, "pclmul", true); - setFeatureEnabledImpl(Features, "prfchw", true); setFeatureEnabledImpl(Features, "bmi", true); setFeatureEnabledImpl(Features, "f16c", true); - setFeatureEnabledImpl(Features, "cx16", true); - break; - case CK_BDVER1: - setFeatureEnabledImpl(Features, "xop", true); + // FALLTHROUGH + case CK_BTVER1: + setFeatureEnabledImpl(Features, "ssse3", true); + setFeatureEnabledImpl(Features, "sse4a", true); setFeatureEnabledImpl(Features, "lzcnt", true); - setFeatureEnabledImpl(Features, "aes", true); - setFeatureEnabledImpl(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "popcnt", true); setFeatureEnabledImpl(Features, "prfchw", true); setFeatureEnabledImpl(Features, "cx16", true); break; @@ -2235,22 +2352,24 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { setFeatureEnabledImpl(Features, "avx2", true); setFeatureEnabledImpl(Features, "bmi2", true); // FALLTHROUGH - case CK_BDVER2: case CK_BDVER3: + setFeatureEnabledImpl(Features, "fsgsbase", true); + // FALLTHROUGH + case CK_BDVER2: + setFeatureEnabledImpl(Features, "bmi", true); + setFeatureEnabledImpl(Features, "fma", true); + setFeatureEnabledImpl(Features, "f16c", true); + setFeatureEnabledImpl(Features, "tbm", true); + // FALLTHROUGH + case CK_BDVER1: + // xop implies avx, sse4a and fma4. setFeatureEnabledImpl(Features, "xop", true); setFeatureEnabledImpl(Features, "lzcnt", true); setFeatureEnabledImpl(Features, "aes", true); setFeatureEnabledImpl(Features, "pclmul", true); setFeatureEnabledImpl(Features, "prfchw", true); - setFeatureEnabledImpl(Features, "bmi", true); - setFeatureEnabledImpl(Features, "fma", true); - setFeatureEnabledImpl(Features, "f16c", true); - setFeatureEnabledImpl(Features, "tbm", true); setFeatureEnabledImpl(Features, "cx16", true); break; - case CK_C3_2: - setFeatureEnabledImpl(Features, "sse", true); - break; } } @@ -2305,7 +2424,8 @@ void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features, Features["avx2"] = false; case AVX512F: Features["avx512f"] = Features["avx512cd"] = Features["avx512er"] = - Features["avx512pf"] = false; + Features["avx512pf"] = Features["avx512dq"] = Features["avx512bw"] = + Features["avx512vl"] = false; } } @@ -2404,7 +2524,8 @@ void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features, setSSELevel(Features, AVX2, Enabled); } else if (Name == "avx512f") { setSSELevel(Features, AVX512F, Enabled); - } else if (Name == "avx512cd" || Name == "avx512er" || Name == "avx512pf") { + } else if (Name == "avx512cd" || Name == "avx512er" || Name == "avx512pf" + || Name == "avx512dq" || Name == "avx512bw" || Name == "avx512vl") { if (Enabled) setSSELevel(Features, AVX512F, Enabled); } else if (Name == "fma") { @@ -2457,6 +2578,11 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, continue; } + if (Feature == "fsgsbase") { + HasFSGSBASE = true; + continue; + } + if (Feature == "bmi") { HasBMI = true; continue; @@ -2487,6 +2613,11 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, continue; } + if (Feature == "adx") { + HasADX = true; + continue; + } + if (Feature == "tbm") { HasTBM = true; continue; @@ -2517,6 +2648,21 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, continue; } + if (Feature == "avx512dq") { + HasAVX512DQ = true; + continue; + } + + if (Feature == "avx512bw") { + HasAVX512BW = true; + continue; + } + + if (Feature == "avx512vl") { + HasAVX512VL = true; + continue; + } + if (Feature == "sha") { HasSHA = true; continue; @@ -2606,6 +2752,10 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__amd64"); Builder.defineMacro("__x86_64"); Builder.defineMacro("__x86_64__"); + if (getTriple().getArchName() == "x86_64h") { + Builder.defineMacro("__x86_64h"); + Builder.defineMacro("__x86_64h__"); + } } else { DefineStd(Builder, "i386", Opts); } @@ -2668,18 +2818,30 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_Penryn: defineCPUMacros(Builder, "core2"); break; - case CK_Atom: + case CK_Bonnell: defineCPUMacros(Builder, "atom"); break; case CK_Silvermont: defineCPUMacros(Builder, "slm"); break; - case CK_Corei7: - case CK_Corei7AVX: - case CK_CoreAVXi: - case CK_CoreAVX2: + case CK_Nehalem: + case CK_Westmere: + case CK_SandyBridge: + case CK_IvyBridge: + case CK_Haswell: + case CK_Broadwell: + // FIXME: Historically, we defined this legacy name, it would be nice to + // remove it at some point. We've never exposed fine-grained names for + // recent primary x86 CPUs, and we should keep it that way. defineCPUMacros(Builder, "corei7"); break; + case CK_Skylake: + // FIXME: Historically, we defined this legacy name, it would be nice to + // remove it at some point. This is the only fine-grained CPU macro in the + // main intel CPU line, and it would be better to not have these and force + // people to use ISA macros. + defineCPUMacros(Builder, "skx"); + break; case CK_KNL: defineCPUMacros(Builder, "knl"); break; @@ -2766,6 +2928,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasRDRND) Builder.defineMacro("__RDRND__"); + if (HasFSGSBASE) + Builder.defineMacro("__FSGSBASE__"); + if (HasBMI) Builder.defineMacro("__BMI__"); @@ -2784,6 +2949,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasRDSEED) Builder.defineMacro("__RDSEED__"); + if (HasADX) + Builder.defineMacro("__ADX__"); + if (HasTBM) Builder.defineMacro("__TBM__"); @@ -2810,6 +2978,12 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__AVX512ER__"); if (HasAVX512PF) Builder.defineMacro("__AVX512PF__"); + if (HasAVX512DQ) + Builder.defineMacro("__AVX512DQ__"); + if (HasAVX512BW) + Builder.defineMacro("__AVX512BW__"); + if (HasAVX512VL) + Builder.defineMacro("__AVX512VL__"); if (HasSHA) Builder.defineMacro("__SHA__"); @@ -2893,23 +3067,26 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("avx512cd", HasAVX512CD) .Case("avx512er", HasAVX512ER) .Case("avx512pf", HasAVX512PF) + .Case("avx512dq", HasAVX512DQ) + .Case("avx512bw", HasAVX512BW) + .Case("avx512vl", HasAVX512VL) .Case("bmi", HasBMI) .Case("bmi2", HasBMI2) .Case("cx16", HasCX16) .Case("f16c", HasF16C) .Case("fma", HasFMA) .Case("fma4", XOPLevel >= FMA4) - .Case("tbm", HasTBM) + .Case("fsgsbase", HasFSGSBASE) .Case("lzcnt", HasLZCNT) - .Case("rdrnd", HasRDRND) .Case("mm3dnow", MMX3DNowLevel >= AMD3DNow) .Case("mm3dnowa", MMX3DNowLevel >= AMD3DNowAthlon) .Case("mmx", MMX3DNowLevel >= MMX) .Case("pclmul", HasPCLMUL) .Case("popcnt", HasPOPCNT) - .Case("rtm", HasRTM) .Case("prfchw", HasPRFCHW) + .Case("rdrnd", HasRDRND) .Case("rdseed", HasRDSEED) + .Case("rtm", HasRTM) .Case("sha", HasSHA) .Case("sse", SSELevel >= SSE1) .Case("sse2", SSELevel >= SSE2) @@ -2918,6 +3095,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("sse4.1", SSELevel >= SSE41) .Case("sse4.2", SSELevel >= SSE42) .Case("sse4a", XOPLevel >= SSE4A) + .Case("tbm", HasTBM) .Case("x86", true) .Case("x86_32", getTriple().getArch() == llvm::Triple::x86) .Case("x86_64", getTriple().getArch() == llvm::Triple::x86_64) @@ -2930,6 +3108,28 @@ X86TargetInfo::validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const { switch (*Name) { default: return false; + case 'I': + Info.setRequiresImmediate(0, 31); + return true; + case 'J': + Info.setRequiresImmediate(0, 63); + return true; + case 'K': + Info.setRequiresImmediate(-128, 127); + return true; + case 'L': + // FIXME: properly analyze this constraint: + // must be one of 0xff, 0xffff, or 0xffffffff + return true; + case 'M': + Info.setRequiresImmediate(0, 3); + return true; + case 'N': + Info.setRequiresImmediate(0, 255); + return true; + case 'O': + Info.setRequiresImmediate(0, 127); + return true; case 'Y': // first letter of a pair: switch (*(Name+1)) { default: return false; @@ -2974,6 +3174,39 @@ X86TargetInfo::validateAsmConstraint(const char *&Name, } } +bool X86TargetInfo::validateOutputSize(StringRef Constraint, + unsigned Size) const { + // Strip off constraint modifiers. + while (Constraint[0] == '=' || + Constraint[0] == '+' || + Constraint[0] == '&') + Constraint = Constraint.substr(1); + + return validateOperandSize(Constraint, Size); +} + +bool X86TargetInfo::validateInputSize(StringRef Constraint, + unsigned Size) const { + return validateOperandSize(Constraint, Size); +} + +bool X86TargetInfo::validateOperandSize(StringRef Constraint, + unsigned Size) const { + switch (Constraint[0]) { + default: break; + case 'y': + return Size <= 64; + case 'f': + case 't': + case 'u': + return Size <= 128; + case 'x': + // 256-bit ymm registers can be used if target supports AVX. + return Size <= (SSELevel >= AVX ? 256U : 128U); + } + + return true; +} std::string X86TargetInfo::convertConstraint(const char *&Constraint) const { @@ -3030,18 +3263,25 @@ public: if (RegNo == 1) return 2; return -1; } - bool validateInputSize(StringRef Constraint, - unsigned Size) const override { + bool validateOperandSize(StringRef Constraint, + unsigned Size) const override { switch (Constraint[0]) { default: break; + case 'R': + case 'q': + case 'Q': case 'a': case 'b': case 'c': case 'd': + case 'S': + case 'D': return Size <= 32; + case 'A': + return Size <= 64; } - return true; + return X86TargetInfo::validateOperandSize(Constraint, Size); } }; } // end anonymous namespace @@ -3304,9 +3544,10 @@ public: Int64Type = IsX32 ? SignedLongLong : SignedLong; RegParmMax = 6; + // Pointers are 32-bit in x32. 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"; + ? "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); @@ -3330,6 +3571,7 @@ public: CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { return (CC == CC_C || + CC == CC_X86VectorCall || CC == CC_IntelOclBicc || CC == CC_X86_64Win64) ? CCCR_OK : CCCR_Warning; } @@ -3338,6 +3580,8 @@ public: return CC_C; } + // for x32 we need it here explicitly + bool hasInt128Type() const override { return true; } }; } // end anonymous namespace @@ -3367,6 +3611,7 @@ public: } CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { return (CC == CC_C || + CC == CC_X86VectorCall || CC == CC_IntelOclBicc || CC == CC_X86_64SysV) ? CCCR_OK : CCCR_Warning; } @@ -3404,6 +3649,10 @@ public: DefineStd(Builder, "WIN64", Opts); Builder.defineMacro("__MINGW64__"); addMinGWDefines(Opts, Builder); + + // GCC defines this macro when it is using __gxx_personality_seh0. + if (!Opts.SjLjExceptions) + Builder.defineMacro("__SEH__"); } }; } // end anonymous namespace @@ -3417,7 +3666,7 @@ public: 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) + if (T.isiOS()) UseSignedCharForObjCBool = false; DescriptionString = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"; } @@ -3492,6 +3741,14 @@ class ARMTargetInfo : public TargetInfo { unsigned CRC : 1; unsigned Crypto : 1; + // ACLE 6.5.1 Hardware floating point + enum { + HW_FP_HP = (1 << 1), /// half (16-bit) + HW_FP_SP = (1 << 2), /// single (32-bit) + HW_FP_DP = (1 << 3), /// double (64-bit) + }; + uint32_t HW_FP; + static const Builtin::Info BuiltinInfo[]; static bool shouldUseInlineAtomic(const llvm::Triple &T) { @@ -3531,8 +3788,8 @@ class ARMTargetInfo : public TargetInfo { 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) + // size_t is unsigned long on MachO-derived environments and NetBSD. + if (T.isOSBinFormatMachO() || T.getOS() == llvm::Triple::NetBSD) SizeType = UnsignedLong; else SizeType = UnsignedInt; @@ -3555,42 +3812,27 @@ class ARMTargetInfo : public TargetInfo { 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"; - } + // 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-i64:64-v128:64:128-a:0:32-n32-S64" + : "e-m:o-p:32: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" + "-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"; + DescriptionString = + BigEndian ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" + : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"; } // FIXME: Enumerated types are variable width in straight AAPCS. @@ -3621,31 +3863,16 @@ class ARMTargetInfo : public TargetInfo { /// 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"; - } + 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. } @@ -3653,7 +3880,7 @@ class ARMTargetInfo : public TargetInfo { public: ARMTargetInfo(const llvm::Triple &Triple, bool IsBigEndian) : TargetInfo(Triple), CPU("arm1136j-s"), FPMath(FP_Default), - IsAAPCS(true) { + IsAAPCS(true), HW_FP(0) { BigEndian = IsBigEndian; switch (getTriple().getOS()) { @@ -3672,7 +3899,45 @@ public: // FIXME: Should we just treat this as a feature? IsThumb = getTriple().getArchName().startswith("thumb"); - setABI("aapcs-linux"); + // FIXME: This duplicates code from the driver that sets the -target-abi + // option - this code is used if -target-abi isn't passed and should + // be unified in some way. + if (Triple.isOSBinFormatMachO()) { + // The backend is hardwired to assume AAPCS for M-class processors, ensure + // the frontend matches that. + if (Triple.getEnvironment() == llvm::Triple::EABI || + Triple.getOS() == llvm::Triple::UnknownOS || + StringRef(CPU).startswith("cortex-m")) { + setABI("aapcs"); + } else { + setABI("apcs-gnu"); + } + } else if (Triple.isOSWindows()) { + // FIXME: this is invalid for WindowsCE + setABI("aapcs"); + } else { + // Select the default based on the platform. + switch (Triple.getEnvironment()) { + case llvm::Triple::Android: + case llvm::Triple::GNUEABI: + case llvm::Triple::GNUEABIHF: + setABI("aapcs-linux"); + break; + case llvm::Triple::EABIHF: + case llvm::Triple::EABI: + setABI("aapcs"); + break; + case llvm::Triple::GNU: + setABI("apcs-gnu"); + break; + default: + if (Triple.getOS() == llvm::Triple::NetBSD) + setABI("apcs-gnu"); + else + setABI("aapcs"); + break; + } + } // ARM targets default to using the ARM C++ ABI. TheCXXABI.set(TargetCXXABI::GenericARM); @@ -3683,8 +3948,8 @@ public: MaxAtomicInlineWidth = 64; // Do force alignment of members that follow zero length bitfields. If - // the alignment of the zero-length bitfield is greater than the member - // that follows it, `bar', `bar' will be aligned as the type of the + // the alignment of the zero-length bitfield is greater than the member + // that follows it, `bar', `bar' will be aligned as the type of the // zero length bitfield. UseZeroLengthBitfieldAlignment = true; } @@ -3708,16 +3973,10 @@ public: } 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; - else if (CPU == "cortex-a8" || CPU == "cortex-a9" || - CPU == "cortex-a9-mp") { + else if (CPU == "cortex-a8" || CPU == "cortex-a9") { Features["vfp3"] = true; Features["neon"] = true; } @@ -3726,7 +3985,7 @@ public: Features["neon"] = true; } else if (CPU == "swift" || CPU == "cortex-a7" || CPU == "cortex-a12" || CPU == "cortex-a15" || - CPU == "krait") { + CPU == "cortex-a17" || CPU == "krait") { Features["vfp4"] = true; Features["neon"] = true; Features["hwdiv"] = true; @@ -3752,7 +4011,7 @@ public: ArchName == "thumbebv8a" || ArchName == "thumbebv8") { Features["hwdiv"] = true; Features["hwdiv-arm"] = true; - } else if (CPU == "cortex-m3" || CPU == "cortex-m4") { + } else if (CPU == "cortex-m3" || CPU == "cortex-m4" || CPU == "cortex-m7") { Features["hwdiv"] = true; } } @@ -3764,29 +4023,38 @@ public: Crypto = 0; SoftFloat = SoftFloatABI = false; HWDiv = 0; - for (unsigned i = 0, e = Features.size(); i != e; ++i) { - if (Features[i] == "+soft-float") + + for (const auto &Feature : Features) { + if (Feature == "+soft-float") { SoftFloat = true; - else if (Features[i] == "+soft-float-abi") + } else if (Feature == "+soft-float-abi") { SoftFloatABI = true; - else if (Features[i] == "+vfp2") + } else if (Feature == "+vfp2") { FPU |= VFP2FPU; - else if (Features[i] == "+vfp3") + HW_FP = HW_FP_SP | HW_FP_DP; + } else if (Feature == "+vfp3") { FPU |= VFP3FPU; - else if (Features[i] == "+vfp4") + HW_FP = HW_FP_SP | HW_FP_DP; + } else if (Feature == "+vfp4") { FPU |= VFP4FPU; - else if (Features[i] == "+fp-armv8") + HW_FP = HW_FP_SP | HW_FP_DP | HW_FP_HP; + } else if (Feature == "+fp-armv8") { FPU |= FPARMV8; - else if (Features[i] == "+neon") + HW_FP = HW_FP_SP | HW_FP_DP | HW_FP_HP; + } else if (Feature == "+neon") { FPU |= NeonFPU; - else if (Features[i] == "+hwdiv") + HW_FP = HW_FP_SP | HW_FP_DP; + } else if (Feature == "+hwdiv") { HWDiv |= HWDivThumb; - else if (Features[i] == "+hwdiv-arm") + } else if (Feature == "+hwdiv-arm") { HWDiv |= HWDivARM; - else if (Features[i] == "+crc") + } else if (Feature == "+crc") { CRC = 1; - else if (Features[i] == "+crypto") + } else if (Feature == "+crypto") { Crypto = 1; + } else if (Feature == "+fp-only-sp") { + HW_FP &= ~HW_FP_DP; + } } if (!(FPU & NeonFPU) && FPMath == FP_Neon) { @@ -3800,13 +4068,13 @@ public: Features.push_back("-neonfp"); // Remove front-end specific options which the backend handles differently. - std::vector<std::string>::iterator it; - it = std::find(Features.begin(), Features.end(), "+soft-float"); - if (it != Features.end()) - Features.erase(it); - it = std::find(Features.begin(), Features.end(), "+soft-float-abi"); - if (it != Features.end()) - Features.erase(it); + const StringRef FrontEndFeatures[] = { "+soft-float", "+soft-float-abi" }; + for (const auto &FEFeature : FrontEndFeatures) { + auto Feature = std::find(Features.begin(), Features.end(), FEFeature); + if (Feature != Features.end()) + Features.erase(Feature); + } + return true; } @@ -3822,40 +4090,43 @@ public: } // FIXME: Should we actually have some table instead of these switches? static const char *getCPUDefineSuffix(StringRef Name) { - return llvm::StringSwitch<const char*>(Name) - .Cases("arm8", "arm810", "4") - .Cases("strongarm", "strongarm110", "strongarm1100", "strongarm1110", "4") - .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "arm720t", "arm9", "4T") - .Cases("arm9tdmi", "arm920", "arm920t", "arm922t", "arm940t", "4T") - .Case("ep9312", "4T") - .Cases("arm10tdmi", "arm1020t", "5T") - .Cases("arm9e", "arm946e-s", "arm966e-s", "arm968e-s", "5TE") - .Case("arm926ej-s", "5TEJ") - .Cases("arm10e", "arm1020e", "arm1022e", "5TE") - .Cases("xscale", "iwmmxt", "5TE") - .Case("arm1136j-s", "6J") - .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", "cortex-a9-mp", "7A") - .Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "7A") - .Cases("cortex-r4", "cortex-r5", "7R") - .Case("swift", "7S") - .Case("cyclone", "8A") - .Case("cortex-m3", "7M") - .Case("cortex-m4", "7EM") - .Case("cortex-m0", "6M") - .Cases("cortex-a53", "cortex-a57", "8A") - .Default(nullptr); + return llvm::StringSwitch<const char *>(Name) + .Cases("arm8", "arm810", "4") + .Cases("strongarm", "strongarm110", "strongarm1100", "strongarm1110", + "4") + .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "arm720t", "arm9", "4T") + .Cases("arm9tdmi", "arm920", "arm920t", "arm922t", "arm940t", "4T") + .Case("ep9312", "4T") + .Cases("arm10tdmi", "arm1020t", "5T") + .Cases("arm9e", "arm946e-s", "arm966e-s", "arm968e-s", "5TE") + .Case("arm926ej-s", "5TEJ") + .Cases("arm10e", "arm1020e", "arm1022e", "5TE") + .Cases("xscale", "iwmmxt", "5TE") + .Case("arm1136j-s", "6J") + .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", "cortex-a17", "krait", + "7A") + .Cases("cortex-r4", "cortex-r5", "7R") + .Case("swift", "7S") + .Case("cyclone", "8A") + .Case("cortex-m3", "7M") + .Cases("cortex-m4", "cortex-m7", "7EM") + .Case("cortex-m0", "6M") + .Cases("cortex-a53", "cortex-a57", "8A") + .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", "krait", "A") - .Cases("cortex-a53", "cortex-a57", "A") - .Cases("cortex-m3", "cortex-m4", "cortex-m0", "M") - .Cases("cortex-r4", "cortex-r5", "R") - .Default(""); + return llvm::StringSwitch<const char *>(Name) + .Cases("cortex-a5", "cortex-a7", "cortex-a8", "A") + .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", + "A") + .Cases("cortex-a53", "cortex-a57", "A") + .Cases("cortex-m3", "cortex-m4", "cortex-m0", "cortex-m7", "M") + .Cases("cortex-r4", "cortex-r5", "R") + .Default(""); } bool setCPU(const std::string &Name) override { if (!getCPUDefineSuffix(Name)) @@ -3895,9 +4166,8 @@ public: StringRef CPUArch = getCPUDefineSuffix(CPU); unsigned int CPUArchVer; - if(CPUArch.substr(0, 1).getAsInteger<unsigned int>(10, CPUArchVer)) { + if (CPUArch.substr(0, 1).getAsInteger<unsigned int>(10, CPUArchVer)) llvm_unreachable("Invalid char for architecture version number"); - } Builder.defineMacro("__ARM_ARCH_" + CPUArch + "__"); // ACLE 6.4.1 ARM/Thumb instruction set architecture @@ -3906,6 +4176,10 @@ public: // __ARM_ARCH is defined as an integer value indicating the current ARM ISA Builder.defineMacro("__ARM_ARCH", CPUArch.substr(0, 1)); + if (CPUArch[0] >= '8') { + Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN"); + Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING"); + } // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It // is not defined for the M-profile. @@ -3931,6 +4205,10 @@ public: if (!CPUProfile.empty()) Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'"); + // ACLE 6.5.1 Hardware Floating Point + if (HW_FP) + Builder.defineMacro("__ARM_FP", "0x" + llvm::utohexstr(HW_FP)); + // ACLE predefines. Builder.defineMacro("__ARM_ACLE", "200"); @@ -4008,6 +4286,13 @@ public: Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); } + + bool is5EOrAbove = (CPUArchVer >= 6 || + (CPUArchVer == 5 && + CPUArch.find('E') != StringRef::npos)); + bool is32Bit = (!IsThumb || supportsThumb2(ArchName, CPUArch, CPUArchVer)); + if (is5EOrAbove && is32Bit && (CPUProfile != "M" || CPUArch == "7EM")) + Builder.defineMacro("__ARM_FEATURE_DSP"); } void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const override { @@ -4032,6 +4317,13 @@ public: case 'P': // VFP Floating point register double precision Info.setAllowsRegister(); return true; + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + // FIXME + return true; case 'Q': // A memory address that is a single base register. Info.setAllowsMemory(); return true; @@ -4068,8 +4360,9 @@ public: } return R; } - bool validateConstraintModifier(StringRef Constraint, const char Modifier, - unsigned Size) const override { + bool + validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size, + std::string &SuggestedModifier) const override { bool isOutput = (Constraint[0] == '='); bool isInOut = (Constraint[0] == '+'); @@ -4297,7 +4590,8 @@ public: : DarwinTargetInfo<ARMleTargetInfo>(Triple) { HasAlignMac68kSupport = true; // iOS always has 64-bit atomic instructions. - // FIXME: This should be based off of the target features in ARMleTargetInfo. + // 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. @@ -4361,7 +4655,7 @@ public: } StringRef getABI() const override { return ABI; } - virtual bool setABI(const std::string &Name) { + bool setABI(const std::string &Name) override { if (Name != "aapcs" && Name != "darwinpcs") return false; @@ -4369,7 +4663,7 @@ public: return true; } - virtual bool setCPU(const std::string &Name) { + bool setCPU(const std::string &Name) override { bool CPUKnown = llvm::StringSwitch<bool>(Name) .Case("generic", true) .Cases("cortex-a53", "cortex-a57", true) @@ -4379,7 +4673,7 @@ public: } virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + MacroBuilder &Builder) const override { // Target identification. Builder.defineMacro("__aarch64__"); @@ -4400,6 +4694,10 @@ public: Builder.defineMacro("__ARM_FEATURE_CLZ"); Builder.defineMacro("__ARM_FEATURE_FMA"); Builder.defineMacro("__ARM_FEATURE_DIV"); + Builder.defineMacro("__ARM_FEATURE_IDIV"); // As specified in ACLE + Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility + Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN"); + Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING"); Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4"); @@ -4413,7 +4711,7 @@ public: if (Opts.FastMath || Opts.FiniteMathOnly) Builder.defineMacro("__ARM_FP_FAST"); - if ((Opts.C99 || Opts.C11) && !Opts.Freestanding) + if (Opts.C99 && !Opts.Freestanding) Builder.defineMacro("__ARM_FP_FENV_ROUNDING"); Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4"); @@ -4435,12 +4733,12 @@ public: } virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { + unsigned &NumRecords) const override { Records = BuiltinInfo; NumRecords = clang::AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin; } - virtual bool hasFeature(StringRef Feature) const { + bool hasFeature(StringRef Feature) const override { return Feature == "aarch64" || Feature == "arm64" || (Feature == "neon" && FPU == NeonMode); @@ -4465,19 +4763,20 @@ public: return true; } - virtual bool isCLZForZeroUndef() const { return false; } + bool isCLZForZeroUndef() const override { return false; } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::AArch64ABIBuiltinVaList; } virtual void getGCCRegNames(const char *const *&Names, - unsigned &NumNames) const; + unsigned &NumNames) const override; virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const; + unsigned &NumAliases) const override; - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const { + virtual bool + validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { switch (*Name) { default: return false; @@ -4500,11 +4799,11 @@ public: 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"); + // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes. + // Utf: A memory address suitable for ldp/stp in TF mode. + // Usa: An absolute symbolic address. + // Ush: The high part (bits 32:12) of a pc-relative symbolic address. + llvm_unreachable("FIXME: Unimplemented support for U* constraints."); case 'z': // Zero register, wzr or xzr Info.setAllowsRegister(); return true; @@ -4515,9 +4814,40 @@ public: return false; } - virtual const char *getClobbers() const { return ""; } + bool + validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size, + std::string &SuggestedModifier) const override { + // Strip off constraint modifiers. + while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') + Constraint = Constraint.substr(1); + + switch (Constraint[0]) { + default: + return true; + case 'z': + case 'r': { + switch (Modifier) { + case 'x': + case 'w': + // For now assume that the person knows what they're + // doing with the modifier. + return true; + default: + // By default an 'r' constraint will be in the 'x' + // registers. + if (Size == 64) + return true; + + SuggestedModifier = "w"; + return false; + } + } + } + } + + const char *getClobbers() const override { return ""; } - int getEHDataRegisterNumber(unsigned RegNo) const { + int getEHDataRegisterNumber(unsigned RegNo) const override { if (RegNo == 0) return 0; if (RegNo == 1) @@ -4652,7 +4982,7 @@ public: TheCXXABI.set(TargetCXXABI::iOS64); } - virtual BuiltinVaListKind getBuiltinVaListKind() const { + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::CharPtrBuiltinVaList; } }; @@ -4857,6 +5187,16 @@ public: bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &info) const override { // FIXME: Implement! + switch (*Name) { + case 'I': // Signed 13-bit constant + case 'J': // Zero + case 'K': // 32-bit constant with the low 12 bits clear + case 'L': // A constant in the range supported by movcc (11-bit signed imm) + case 'M': // A constant in the range supported by movrcc (19-bit signed imm) + case 'N': // Same as 'K' but zext (required for SIMode) + case 'O': // The constant 4096 + return true; + } return false; } const char *getClobbers() const override { @@ -4962,10 +5302,8 @@ public: SparcTargetInfo::getTargetDefines(Opts, Builder); Builder.defineMacro("__sparcv9"); Builder.defineMacro("__arch64__"); - // Solaris and its derivative AuroraUX don't need these variants, but the - // BSDs do. - if (getTriple().getOS() != llvm::Triple::Solaris && - getTriple().getOS() != llvm::Triple::AuroraUX) { + // Solaris doesn't need these variants, but the BSDs do. + if (getTriple().getOS() != llvm::Triple::Solaris) { Builder.defineMacro("__sparc64__"); Builder.defineMacro("__sparc_v9__"); Builder.defineMacro("__sparcv9__"); @@ -4992,14 +5330,6 @@ public: } // end anonymous namespace. namespace { -class AuroraUXSparcV8TargetInfo : public AuroraUXTargetInfo<SparcV8TargetInfo> { -public: - AuroraUXSparcV8TargetInfo(const llvm::Triple &Triple) - : AuroraUXTargetInfo<SparcV8TargetInfo>(Triple) { - SizeType = UnsignedInt; - PtrDiffType = SignedInt; - } -}; class SolarisSparcV8TargetInfo : public SolarisTargetInfo<SparcV8TargetInfo> { public: SolarisSparcV8TargetInfo(const llvm::Triple &Triple) @@ -5131,7 +5461,7 @@ namespace { IntPtrType = SignedInt; PtrDiffType = SignedInt; SigAtomicType = SignedLong; - DescriptionString = "e-m:e-p:16:16-i32:16:32-n8:16"; + DescriptionString = "e-m:e-p:16:16-i32:16:32-a:16-n8:16"; } void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override { @@ -5156,8 +5486,16 @@ namespace { Aliases = nullptr; NumAliases = 0; } - bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const override { + bool + validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override { + // FIXME: implement + switch (*Name) { + case 'K': // the constant 1 + case 'L': // constant -1^20 .. 1^19 + case 'M': // constant 1-4: + return true; + } // No target constraints for now. return false; } @@ -5197,6 +5535,8 @@ namespace { 3, // opencl_global 4, // opencl_local 5, // opencl_constant + // FIXME: generic has to be added to the target + 0, // opencl_generic 0, // cuda_device 0, // cuda_constant 0 // cuda_shared @@ -5443,7 +5783,6 @@ public: switch (*Name) { default: return false; - case 'r': // CPU registers. case 'd': // Equivalent to "r" unless generating MIPS16 code. case 'y': // Equivalent to "r", backward compatibility only. @@ -5453,6 +5792,15 @@ public: case 'x': // hilo register pair Info.setAllowsRegister(); return true; + case 'I': // Signed 16-bit constant + case 'J': // Integer 0 + case 'K': // Unsigned 16-bit constant + case 'L': // Signed 32-bit constant, lower 16-bit zeros (for lui) + case 'M': // Constants not loadable via lui, addiu, or ori + case 'N': // Constant -1 to -65535 + case 'O': // A signed 15-bit constant + case 'P': // A constant between 1 go 65535 + return true; case 'R': // An address that can be used in a non-macro load or store Info.setAllowsMemory(); return true; @@ -5460,8 +5808,28 @@ public: } const char *getClobbers() const override { - // FIXME: Implement! - return ""; + // In GCC, $1 is not widely used in generated code (it's used only in a few + // specific situations), so there is no real need for users to add it to + // the clobbers list if they want to use it in their inline assembly code. + // + // In LLVM, $1 is treated as a normal GPR and is always allocatable during + // code generation, so using it in inline assembly without adding it to the + // clobbers list can cause conflicts between the inline assembly code and + // the surrounding generated code. + // + // Another problem is that LLVM is allowed to choose $1 for inline assembly + // operands, which will conflict with the ".set at" assembler option (which + // we use only for inline assembly, in order to maintain compatibility with + // GCC) and will also conflict with the user's usage of $1. + // + // The easiest way to avoid these conflicts and keep $1 as an allocatable + // register for generated code is to automatically clobber $1 for all inline + // assembly code. + // + // FIXME: We should automatically clobber $1 only for inline assembly code + // which actually uses it. This would allow LLVM to use $1 for inline + // assembly operands if the user's assembly code doesn't use it. + return "~{$1}"; } bool handleTargetFeatures(std::vector<std::string> &Features, @@ -5863,10 +6231,65 @@ void PNaClTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, } // end anonymous namespace. namespace { +class Le64TargetInfo : public TargetInfo { + static const Builtin::Info BuiltinInfo[]; + +public: + Le64TargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { + BigEndian = false; + NoAsmVariants = true; + LongWidth = LongAlign = PointerWidth = PointerAlign = 64; + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; + DescriptionString = + "e-m:e-v128:32-v16:16-v32:32-v96:32-n8:16:32:64-S128"; + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + DefineStd(Builder, "unix", Opts); + defineCPUMacros(Builder, "le64", /*Tuning=*/false); + Builder.defineMacro("__ELF__"); + } + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override { + Records = BuiltinInfo; + NumRecords = clang::Le64::LastTSBuiltin - Builtin::FirstTSBuiltin; + } + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::PNaClABIBuiltinVaList; + } + const char *getClobbers() const override { return ""; } + void getGCCRegNames(const char *const *&Names, + unsigned &NumNames) const override { + Names = nullptr; + NumNames = 0; + } + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override { + Aliases = nullptr; + NumAliases = 0; + } + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { + return false; + } + + bool hasProtectedVisibility() const override { return false; } +}; +} // end anonymous namespace. + +const Builtin::Info Le64TargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) \ + { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, +#include "clang/Basic/BuiltinsLe64.def" +}; + +namespace { static const unsigned SPIRAddrSpaceMap[] = { 1, // opencl_global 3, // opencl_local 2, // opencl_constant + 4, // opencl_generic 0, // cuda_device 0, // cuda_constant 0 // cuda_shared @@ -5902,8 +6325,9 @@ namespace { } void getGCCRegNames(const char * const *&Names, unsigned &NumNames) const override {} - bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const override { + bool + validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override { return true; } void getGCCRegAliases(const GCCRegAlias *&Aliases, @@ -6031,7 +6455,6 @@ 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); @@ -6047,7 +6470,6 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { } case llvm::Triple::aarch64_be: - case llvm::Triple::arm64_be: switch (os) { case llvm::Triple::FreeBSD: return new FreeBSDTargetInfo<AArch64beTargetInfo>(Triple); @@ -6189,6 +6611,9 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { return nullptr; } + case llvm::Triple::le64: + return new Le64TargetInfo(Triple); + case llvm::Triple::ppc: if (Triple.isOSDarwin()) return new DarwinPPC32TargetInfo(Triple); @@ -6236,6 +6661,7 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { case llvm::Triple::nvptx64: return new NVPTX64TargetInfo(Triple); + case llvm::Triple::amdgcn: case llvm::Triple::r600: return new R600TargetInfo(Triple); @@ -6243,8 +6669,6 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { switch (os) { case llvm::Triple::Linux: return new LinuxTargetInfo<SparcV8TargetInfo>(Triple); - case llvm::Triple::AuroraUX: - return new AuroraUXSparcV8TargetInfo(Triple); case llvm::Triple::Solaris: return new SolarisSparcV8TargetInfo(Triple); case llvm::Triple::NetBSD: @@ -6261,8 +6685,6 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { switch (os) { case llvm::Triple::Linux: return new LinuxTargetInfo<SparcV9TargetInfo>(Triple); - case llvm::Triple::AuroraUX: - return new AuroraUXTargetInfo<SparcV9TargetInfo>(Triple); case llvm::Triple::Solaris: return new SolarisTargetInfo<SparcV9TargetInfo>(Triple); case llvm::Triple::NetBSD: @@ -6291,8 +6713,6 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { return new DarwinI386TargetInfo(Triple); switch (os) { - case llvm::Triple::AuroraUX: - return new AuroraUXTargetInfo<X86_32TargetInfo>(Triple); case llvm::Triple::Linux: return new LinuxTargetInfo<X86_32TargetInfo>(Triple); case llvm::Triple::DragonFly: @@ -6339,8 +6759,6 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { return new DarwinX86_64TargetInfo(Triple); switch (os) { - case llvm::Triple::AuroraUX: - return new AuroraUXTargetInfo<X86_64TargetInfo>(Triple); case llvm::Triple::Linux: return new LinuxTargetInfo<X86_64TargetInfo>(Triple); case llvm::Triple::DragonFly: diff --git a/contrib/llvm/tools/clang/lib/Basic/Version.cpp b/contrib/llvm/tools/clang/lib/Basic/Version.cpp index 2d3875d..3ba51d4 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Version.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Version.cpp @@ -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_351/final/lib/Basic/Version.cpp $"); + StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_360/rc1/lib/Basic/Version.cpp $"); if (URL.empty()) { URL = SVNRepository.slice(SVNRepository.find(':'), SVNRepository.find("/lib/Basic")); diff --git a/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp b/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp index 8b781ab..aa43ae2 100644 --- a/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp @@ -29,9 +29,9 @@ raw_ostream& clang::operator<<(raw_ostream &Out, const VersionTuple &V) { Out << V.getMajor(); if (Optional<unsigned> Minor = V.getMinor()) - Out << '.' << *Minor; + Out << (V.usesUnderscores() ? '_' : '.') << *Minor; if (Optional<unsigned> Subminor = V.getSubminor()) - Out << '.' << *Subminor; + Out << (V.usesUnderscores() ? '_' : '.') << *Subminor; return Out; } diff --git a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp index a5c83b8..c89195e 100644 --- a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp @@ -11,10 +11,10 @@ #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/ADT/iterator_range.h" #include "llvm/Support/Errc.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -67,16 +67,14 @@ 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; +ErrorOr<std::unique_ptr<MemoryBuffer>> +FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize, + bool RequiresNullTerminator, bool IsVolatile) { + auto F = openFileForRead(Name); + if (!F) + return F.getError(); - std::error_code EC = - F->getBuffer(Name, Result, FileSize, RequiresNullTerminator, IsVolatile); - return EC; + return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile); } //===-----------------------------------------------------------------------===/ @@ -96,11 +94,10 @@ class RealFile : public File { 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; + ErrorOr<std::unique_ptr<MemoryBuffer>> + getBuffer(const Twine &Name, int64_t FileSize = -1, + bool RequiresNullTerminator = true, + bool IsVolatile = false) override; std::error_code close() override; void setName(StringRef Name) override; }; @@ -120,19 +117,12 @@ ErrorOr<Status> RealFile::status() { return S; } -std::error_code RealFile::getBuffer(const Twine &Name, - std::unique_ptr<MemoryBuffer> &Result, - int64_t FileSize, - bool RequiresNullTerminator, - bool IsVolatile) { +ErrorOr<std::unique_ptr<MemoryBuffer>> +RealFile::getBuffer(const Twine &Name, 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(); + return MemoryBuffer::getOpenFile(FD, Name, FileSize, RequiresNullTerminator, + IsVolatile); } // FIXME: This is terrible, we need this for ::close. @@ -161,8 +151,7 @@ namespace { 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; + ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; }; } // end anonymous namespace @@ -176,14 +165,14 @@ ErrorOr<Status> RealFileSystem::status(const Twine &Path) { return Result; } -std::error_code RealFileSystem::openFileForRead(const Twine &Name, - std::unique_ptr<File> &Result) { +ErrorOr<std::unique_ptr<File>> +RealFileSystem::openFileForRead(const Twine &Name) { int FD; if (std::error_code EC = sys::fs::openFileForRead(Name, FD)) return EC; - Result.reset(new RealFile(FD)); + std::unique_ptr<File> Result(new RealFile(FD)); Result->setName(Name.str()); - return std::error_code(); + return std::move(Result); } IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() { @@ -252,14 +241,13 @@ ErrorOr<Status> OverlayFileSystem::status(const Twine &Path) { 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) { +ErrorOr<std::unique_ptr<File>> +OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // 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; + auto Result = (*I)->openFileForRead(Path); + if (Result || Result.getError() != llvm::errc::no_such_file_or_directory) + return Result; } return make_error_code(llvm::errc::no_such_file_or_directory); } @@ -308,7 +296,7 @@ class OverlayFSDirIterImpl : public clang::vfs::detail::DirIterImpl { } CurrentEntry = *CurrentDirIter; StringRef Name = llvm::sys::path::filename(CurrentEntry.getName()); - if (SeenNames.insert(Name)) + if (SeenNames.insert(Name).second) return EC; // name not seen before } llvm_unreachable("returned above"); @@ -514,16 +502,13 @@ public: /// \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, + static VFSFromYAML *create(std::unique_ptr<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; + ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override{ ErrorOr<Entry *> E = lookupPath(Dir); @@ -865,13 +850,13 @@ DirectoryEntry::~DirectoryEntry() { llvm::DeleteContainerPointers(Contents); } VFSFromYAML::~VFSFromYAML() { llvm::DeleteContainerPointers(Roots); } -VFSFromYAML *VFSFromYAML::create(MemoryBuffer *Buffer, +VFSFromYAML *VFSFromYAML::create(std::unique_ptr<MemoryBuffer> Buffer, SourceMgr::DiagHandlerTy DiagHandler, void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS) { SourceMgr SM; - yaml::Stream Stream(Buffer, SM); + yaml::Stream Stream(Buffer->getMemBufferRef(), SM); SM.setDiagHandler(DiagHandler, DiagContext); yaml::document_iterator DI = Stream.begin(); @@ -971,9 +956,7 @@ ErrorOr<Status> VFSFromYAML::status(const Twine &Path) { return status(Path, *Result); } -std::error_code -VFSFromYAML::openFileForRead(const Twine &Path, - std::unique_ptr<vfs::File> &Result) { +ErrorOr<std::unique_ptr<File>> VFSFromYAML::openFileForRead(const Twine &Path) { ErrorOr<Entry *> E = lookupPath(Path); if (!E) return E.getError(); @@ -982,21 +965,22 @@ VFSFromYAML::openFileForRead(const Twine &Path, 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; + auto Result = ExternalFS->openFileForRead(F->getExternalContentsPath()); + if (!Result) + return Result; if (!F->useExternalName(UseExternalNames)) - Result->setName(Path.str()); + (*Result)->setName(Path.str()); - return std::error_code(); + return Result; } IntrusiveRefCntPtr<FileSystem> -vfs::getVFSFromYAML(MemoryBuffer *Buffer, SourceMgr::DiagHandlerTy DiagHandler, - void *DiagContext, +vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer, + SourceMgr::DiagHandlerTy DiagHandler, void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS) { - return VFSFromYAML::create(Buffer, DiagHandler, DiagContext, ExternalFS); + return VFSFromYAML::create(std::move(Buffer), DiagHandler, DiagContext, + ExternalFS); } UniqueID vfs::getNextVirtualUniqueID() { |