diff options
Diffstat (limited to 'lib/Basic')
27 files changed, 814 insertions, 327 deletions
diff --git a/lib/Basic/Attributes.cpp b/lib/Basic/Attributes.cpp index 9a8eb3d932cc6..74cc3d1d03dac 100644 --- a/lib/Basic/Attributes.cpp +++ b/lib/Basic/Attributes.cpp @@ -1,5 +1,6 @@ #include "clang/Basic/Attributes.h" #include "clang/Basic/AttrSubjectMatchRules.h" +#include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/StringSwitch.h" using namespace clang; @@ -21,7 +22,7 @@ int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, #include "clang/Basic/AttrHasAttributeImpl.inc" - return 0;
+ return 0; } const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) { @@ -33,3 +34,75 @@ const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) { } llvm_unreachable("Invalid subject match rule"); } + +static StringRef +normalizeAttrScopeName(StringRef ScopeName, + AttributeCommonInfo::Syntax SyntaxUsed) { + // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name + // to be "clang". + if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 || + SyntaxUsed == AttributeCommonInfo::AS_C2x) { + if (ScopeName == "__gnu__") + ScopeName = "gnu"; + else if (ScopeName == "_Clang") + ScopeName = "clang"; + } + return ScopeName; +} + +static StringRef normalizeAttrName(StringRef AttrName, + StringRef NormalizedScopeName, + AttributeCommonInfo::Syntax SyntaxUsed) { + // Normalize the attribute name, __foo__ becomes foo. This is only allowable + // for GNU attributes, and attributes using the double square bracket syntax. + bool ShouldNormalize = + SyntaxUsed == AttributeCommonInfo::AS_GNU || + ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 || + SyntaxUsed == AttributeCommonInfo::AS_C2x) && + (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" || + NormalizedScopeName == "clang")); + if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") && + AttrName.endswith("__")) + AttrName = AttrName.slice(2, AttrName.size() - 2); + + return AttrName; +} + +bool AttributeCommonInfo::isGNUScope() const { + return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__")); +} + +#include "clang/Sema/AttrParsedAttrKinds.inc" + +AttributeCommonInfo::Kind +AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name, + const IdentifierInfo *ScopeName, + Syntax SyntaxUsed) { + StringRef AttrName = Name->getName(); + + SmallString<64> FullName; + if (ScopeName) + FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed); + + AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed); + + // Ensure that in the case of C++11 attributes, we look for '::foo' if it is + // unscoped. + if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x) + FullName += "::"; + FullName += AttrName; + + return ::getAttrKind(FullName, SyntaxUsed); +} + +unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const { + // Both variables will be used in tablegen generated + // attribute spell list index matching code. + auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax()); + StringRef Scope = + getScopeName() ? normalizeAttrScopeName(getScopeName()->getName(), Syntax) + : ""; + StringRef Name = normalizeAttrName(getAttrName()->getName(), Scope, Syntax); + +#include "clang/Sema/AttrSpellingListIndex.inc" +} diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index b6a7fde09f357..88a7a12508375 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -18,9 +18,10 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemStatCache.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Config/llvm-config.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -35,6 +36,14 @@ using namespace clang; +#define DEBUG_TYPE "file-search" + +ALWAYS_ENABLED_STATISTIC(NumDirLookups, "Number of directory lookups."); +ALWAYS_ENABLED_STATISTIC(NumFileLookups, "Number of file lookups."); +ALWAYS_ENABLED_STATISTIC(NumDirCacheMisses, + "Number of directory cache misses."); +ALWAYS_ENABLED_STATISTIC(NumFileCacheMisses, "Number of file cache misses."); + //===----------------------------------------------------------------------===// // Common logic. //===----------------------------------------------------------------------===// @@ -43,9 +52,6 @@ FileManager::FileManager(const FileSystemOptions &FSO, IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) : FS(std::move(FS)), FileSystemOpts(FSO), SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) { - NumDirLookups = NumFileLookups = 0; - NumDirCacheMisses = NumFileCacheMisses = 0; - // If the caller doesn't provide a virtual file system, just grab the real // file system. if (!this->FS) @@ -63,14 +69,14 @@ void FileManager::clearStatCache() { StatCache.reset(); } /// Retrieve the directory that the given file name resides in. /// Filename can point to either a real file or a virtual file. -static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, - StringRef Filename, - bool CacheFailure) { +static llvm::ErrorOr<const DirectoryEntry *> +getDirectoryFromFile(FileManager &FileMgr, StringRef Filename, + bool CacheFailure) { if (Filename.empty()) - return nullptr; + return std::errc::no_such_file_or_directory; if (llvm::sys::path::is_separator(Filename[Filename.size() - 1])) - return nullptr; // If Filename is a directory. + return std::errc::is_a_directory; StringRef DirName = llvm::sys::path::parent_path(Filename); // Use the current directory if file has no path component. @@ -87,7 +93,8 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef Path) { if (DirName.empty()) DirName = "."; - auto &NamedDirEnt = *SeenDirEntries.insert({DirName, nullptr}).first; + auto &NamedDirEnt = *SeenDirEntries.insert( + {DirName, std::errc::no_such_file_or_directory}).first; // When caching a virtual directory, we always cache its ancestors // at the same time. Therefore, if DirName is already in the cache, @@ -97,17 +104,17 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef Path) { return; // Add the virtual directory to the cache. - auto UDE = llvm::make_unique<DirectoryEntry>(); + auto UDE = std::make_unique<DirectoryEntry>(); UDE->Name = NamedDirEnt.first(); - NamedDirEnt.second = UDE.get(); + NamedDirEnt.second = *UDE.get(); VirtualDirectoryEntries.push_back(std::move(UDE)); // Recursively add the other ancestors. addAncestorsAsVirtualDirs(DirName); } -const DirectoryEntry *FileManager::getDirectory(StringRef DirName, - bool CacheFailure) { +llvm::Expected<DirectoryEntryRef> +FileManager::getDirectoryRef(StringRef DirName, bool CacheFailure) { // stat doesn't like trailing separators except for root directory. // At least, on Win32 MSVCRT, stat() cannot strip trailing '/'. // (though it can strip '\\') @@ -130,9 +137,13 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName, // See if there was already an entry in the map. Note that the map // contains both virtual and real directories. - auto SeenDirInsertResult = SeenDirEntries.insert({DirName, nullptr}); - if (!SeenDirInsertResult.second) - return SeenDirInsertResult.first->second; + auto SeenDirInsertResult = + SeenDirEntries.insert({DirName, std::errc::no_such_file_or_directory}); + if (!SeenDirInsertResult.second) { + if (SeenDirInsertResult.first->second) + return DirectoryEntryRef(&*SeenDirInsertResult.first); + return llvm::errorCodeToError(SeenDirInsertResult.first->second.getError()); + } // We've not seen this before. Fill it in. ++NumDirCacheMisses; @@ -145,11 +156,15 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName, // Check to see if the directory exists. llvm::vfs::Status Status; - if (getStatValue(InterndDirName, Status, false, nullptr /*directory lookup*/)) { + auto statError = getStatValue(InterndDirName, Status, false, + nullptr /*directory lookup*/); + if (statError) { // There's no real directory at the given path. - if (!CacheFailure) + if (CacheFailure) + NamedDirEnt.second = statError; + else SeenDirEntries.erase(DirName); - return nullptr; + return llvm::errorCodeToError(statError); } // It exists. See if we have already opened a directory with the @@ -158,24 +173,51 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName, // Windows). DirectoryEntry &UDE = UniqueRealDirs[Status.getUniqueID()]; - NamedDirEnt.second = &UDE; + NamedDirEnt.second = UDE; if (UDE.getName().empty()) { // We don't have this directory yet, add it. We use the string // key from the SeenDirEntries map as the string. UDE.Name = InterndDirName; } - return &UDE; + return DirectoryEntryRef(&NamedDirEnt); +} + +llvm::ErrorOr<const DirectoryEntry *> +FileManager::getDirectory(StringRef DirName, bool CacheFailure) { + auto Result = getDirectoryRef(DirName, CacheFailure); + if (Result) + return &Result->getDirEntry(); + return llvm::errorToErrorCode(Result.takeError()); } -const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, - bool CacheFailure) { +llvm::ErrorOr<const FileEntry *> +FileManager::getFile(StringRef Filename, bool openFile, bool CacheFailure) { + auto Result = getFileRef(Filename, openFile, CacheFailure); + if (Result) + return &Result->getFileEntry(); + return llvm::errorToErrorCode(Result.takeError()); +} + +llvm::Expected<FileEntryRef> +FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { ++NumFileLookups; // See if there is already an entry in the map. - auto SeenFileInsertResult = SeenFileEntries.insert({Filename, nullptr}); - if (!SeenFileInsertResult.second) - return SeenFileInsertResult.first->second; + auto SeenFileInsertResult = + SeenFileEntries.insert({Filename, std::errc::no_such_file_or_directory}); + if (!SeenFileInsertResult.second) { + if (!SeenFileInsertResult.first->second) + return llvm::errorCodeToError( + SeenFileInsertResult.first->second.getError()); + // Construct and return and FileEntryRef, unless it's a redirect to another + // filename. + SeenFileEntryOrRedirect Value = *SeenFileInsertResult.first->second; + FileEntry *FE; + if (LLVM_LIKELY(FE = Value.dyn_cast<FileEntry *>())) + return FileEntryRef(SeenFileInsertResult.first->first(), *FE); + return getFileRef(*Value.get<const StringRef *>(), openFile, CacheFailure); + } // We've not seen this before. Fill it in. ++NumFileCacheMisses; @@ -191,14 +233,16 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, // subdirectory. This will let us avoid having to waste time on known-to-fail // searches when we go to find sys/bar.h, because all the search directories // without a 'sys' subdir will get a cached failure result. - const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, - CacheFailure); - if (DirInfo == nullptr) { // Directory doesn't exist, file can't exist. - if (!CacheFailure) + auto DirInfoOrErr = getDirectoryFromFile(*this, Filename, CacheFailure); + if (!DirInfoOrErr) { // Directory doesn't exist, file can't exist. + if (CacheFailure) + NamedFileEnt.second = DirInfoOrErr.getError(); + else SeenFileEntries.erase(Filename); - return nullptr; + return llvm::errorCodeToError(DirInfoOrErr.getError()); } + const DirectoryEntry *DirInfo = *DirInfoOrErr; // FIXME: Use the directory info to prune this, before doing the stat syscall. // FIXME: This will reduce the # syscalls. @@ -206,12 +250,16 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, // Check to see if the file exists. std::unique_ptr<llvm::vfs::File> F; llvm::vfs::Status Status; - if (getStatValue(InterndFileName, Status, true, openFile ? &F : nullptr)) { + auto statError = getStatValue(InterndFileName, Status, true, + openFile ? &F : nullptr); + if (statError) { // There's no real file at the given path. - if (!CacheFailure) + if (CacheFailure) + NamedFileEnt.second = statError; + else SeenFileEntries.erase(Filename); - return nullptr; + return llvm::errorCodeToError(statError); } assert((openFile || !F) && "undesired open file"); @@ -225,11 +273,15 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, // If the name returned by getStatValue is different than Filename, re-intern // the name. if (Status.getName() != Filename) { - auto &NamedFileEnt = - *SeenFileEntries.insert({Status.getName(), &UFE}).first; - assert(NamedFileEnt.second == &UFE && + auto &NewNamedFileEnt = + *SeenFileEntries.insert({Status.getName(), &UFE}).first; + assert((*NewNamedFileEnt.second).get<FileEntry *>() == &UFE && "filename from getStatValue() refers to wrong file"); - InterndFileName = NamedFileEnt.first().data(); + InterndFileName = NewNamedFileEnt.first().data(); + // In addition to re-interning the name, construct a redirecting seen file + // entry, that will point to the name the filesystem actually wants to use. + StringRef *Redirect = new (CanonicalNameStorage) StringRef(InterndFileName); + NamedFileEnt.second = Redirect; } if (UFE.isValid()) { // Already have an entry with this inode, return it. @@ -248,9 +300,11 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, // 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. + // FIXME: The Name should be removed from FileEntry once all clients + // adopt FileEntryRef. UFE.Name = InterndFileName; - return &UFE; + return FileEntryRef(InterndFileName, UFE); } // Otherwise, we don't have this file yet, add it. @@ -271,7 +325,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, // We should still fill the path even if we aren't opening the file. fillRealPathName(&UFE, InterndFileName); } - return &UFE; + return FileEntryRef(InterndFileName, UFE); } const FileEntry * @@ -280,9 +334,16 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, ++NumFileLookups; // See if there is already an entry in the map for an existing file. - auto &NamedFileEnt = *SeenFileEntries.insert({Filename, nullptr}).first; - if (NamedFileEnt.second) - return NamedFileEnt.second; + auto &NamedFileEnt = *SeenFileEntries.insert( + {Filename, std::errc::no_such_file_or_directory}).first; + if (NamedFileEnt.second) { + SeenFileEntryOrRedirect Value = *NamedFileEnt.second; + FileEntry *FE; + if (LLVM_LIKELY(FE = Value.dyn_cast<FileEntry *>())) + return FE; + return getVirtualFile(*Value.get<const StringRef *>(), Size, + ModificationTime); + } // We've not seen this before, or the file is cached as non-existent. ++NumFileCacheMisses; @@ -292,15 +353,14 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, // Now that all ancestors of Filename are in the cache, the // following call is guaranteed to find the DirectoryEntry from the // cache. - const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, - /*CacheFailure=*/true); + auto DirInfo = getDirectoryFromFile(*this, Filename, /*CacheFailure=*/true); assert(DirInfo && "The directory of a virtual file should already be in the cache."); // Check to see if the file exists. If so, drop the virtual file llvm::vfs::Status Status; const char *InterndFileName = NamedFileEnt.first().data(); - if (getStatValue(InterndFileName, Status, true, nullptr) == 0) { + if (!getStatValue(InterndFileName, Status, true, nullptr)) { UFE = &UniqueRealFiles[Status.getUniqueID()]; Status = llvm::vfs::Status( Status.getName(), Status.getUniqueID(), @@ -324,7 +384,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, UFE->IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file; fillRealPathName(UFE, Status.getName()); } else { - VirtualFileEntries.push_back(llvm::make_unique<FileEntry>()); + VirtualFileEntries.push_back(std::make_unique<FileEntry>()); UFE = VirtualFileEntries.back().get(); NamedFileEnt.second = UFE; } @@ -332,13 +392,32 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, UFE->Name = InterndFileName; UFE->Size = Size; UFE->ModTime = ModificationTime; - UFE->Dir = DirInfo; + UFE->Dir = *DirInfo; UFE->UID = NextFileUID++; UFE->IsValid = true; UFE->File.reset(); return UFE; } +llvm::Optional<FileEntryRef> FileManager::getBypassFile(FileEntryRef VF) { + // Stat of the file and return nullptr if it doesn't exist. + llvm::vfs::Status Status; + if (getStatValue(VF.getName(), Status, /*isFile=*/true, /*F=*/nullptr)) + return None; + + // Fill it in from the stat. + BypassFileEntries.push_back(std::make_unique<FileEntry>()); + const FileEntry &VFE = VF.getFileEntry(); + FileEntry &BFE = *BypassFileEntries.back(); + BFE.Name = VFE.getName(); + BFE.Size = Status.getSize(); + BFE.Dir = VFE.Dir; + BFE.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime()); + BFE.UID = NextFileUID++; + BFE.IsValid = true; + return FileEntryRef(VF.getName(), BFE); +} + bool FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const { StringRef pathRef(path.data(), path.size()); @@ -375,8 +454,7 @@ void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) { } llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> -FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile, - bool ShouldCloseOpenFile) { +FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile) { 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. @@ -389,80 +467,59 @@ FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile, 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(); + Entry->closeFile(); return Result; } // Otherwise, open the file. + return getBufferForFileImpl(Filename, FileSize, isVolatile); +} +llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> +FileManager::getBufferForFileImpl(StringRef Filename, int64_t FileSize, + bool isVolatile) { if (FileSystemOpts.WorkingDir.empty()) return FS->getBufferForFile(Filename, FileSize, /*RequiresNullTerminator=*/true, isVolatile); - SmallString<128> FilePath(Entry->getName()); + SmallString<128> FilePath(Filename); FixupRelativePath(FilePath); return FS->getBufferForFile(FilePath, FileSize, /*RequiresNullTerminator=*/true, isVolatile); } -llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> -FileManager::getBufferForFile(StringRef Filename, bool isVolatile) { - if (FileSystemOpts.WorkingDir.empty()) - return FS->getBufferForFile(Filename, -1, true, isVolatile); - - SmallString<128> FilePath(Filename); - FixupRelativePath(FilePath); - return FS->getBufferForFile(FilePath.c_str(), -1, true, isVolatile); -} - /// getStatValue - Get the 'stat' information for the specified path, /// using the cache to accelerate it if possible. This returns true /// if the path points to a virtual file or does not exist, or returns /// false if it's an existent real file. If FileDescriptor is NULL, /// do directory look-up instead of file look-up. -bool FileManager::getStatValue(StringRef Path, llvm::vfs::Status &Status, - bool isFile, - std::unique_ptr<llvm::vfs::File> *F) { +std::error_code +FileManager::getStatValue(StringRef Path, llvm::vfs::Status &Status, + bool isFile, std::unique_ptr<llvm::vfs::File> *F) { // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be // absolute! if (FileSystemOpts.WorkingDir.empty()) - return bool(FileSystemStatCache::get(Path, Status, isFile, F, - StatCache.get(), *FS)); + return FileSystemStatCache::get(Path, Status, isFile, F, + StatCache.get(), *FS); SmallString<128> FilePath(Path); FixupRelativePath(FilePath); - return bool(FileSystemStatCache::get(FilePath.c_str(), Status, isFile, F, - StatCache.get(), *FS)); + return FileSystemStatCache::get(FilePath.c_str(), Status, isFile, F, + StatCache.get(), *FS); } -bool FileManager::getNoncachedStatValue(StringRef Path, - llvm::vfs::Status &Result) { +std::error_code +FileManager::getNoncachedStatValue(StringRef Path, + llvm::vfs::Status &Result) { SmallString<128> FilePath(Path); FixupRelativePath(FilePath); llvm::ErrorOr<llvm::vfs::Status> S = FS->status(FilePath.c_str()); if (!S) - return true; + return S.getError(); Result = *S; - return false; -} - -void FileManager::invalidateCache(const FileEntry *Entry) { - assert(Entry && "Cannot invalidate a NULL FileEntry"); - - SeenFileEntries.erase(Entry->getName()); - - // FileEntry invalidation should not block future optimizations in the file - // caches. Possible alternatives are cache truncation (invalidate last N) or - // invalidation of the whole cache. - // - // FIXME: This is broken. We sometimes have the same FileEntry* shared - // betweeen multiple SeenFileEntries, so this can leave dangling pointers. - UniqueRealFiles.erase(Entry->getUniqueID()); + return std::error_code(); } void FileManager::GetUniqueIDMapping( @@ -471,23 +528,21 @@ void FileManager::GetUniqueIDMapping( UIDToFiles.resize(NextFileUID); // Map file entries - for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator - FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end(); + for (llvm::StringMap<llvm::ErrorOr<SeenFileEntryOrRedirect>, + llvm::BumpPtrAllocator>::const_iterator + FE = SeenFileEntries.begin(), + FEEnd = SeenFileEntries.end(); FE != FEEnd; ++FE) - if (FE->getValue()) - UIDToFiles[FE->getValue()->getUID()] = FE->getValue(); + if (llvm::ErrorOr<SeenFileEntryOrRedirect> Entry = FE->getValue()) { + if (const auto *FE = (*Entry).dyn_cast<FileEntry *>()) + UIDToFiles[FE->getUID()] = FE; + } // Map virtual file entries for (const auto &VFE : VirtualFileEntries) UIDToFiles[VFE->getUID()] = VFE.get(); } -void FileManager::modifyFileEntry(FileEntry *File, - off_t Size, time_t ModificationTime) { - File->Size = Size; - File->ModTime = ModificationTime; -} - StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) { // FIXME: use llvm::sys::fs::canonical() when it gets implemented llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index ca9c71287ab7e..4aebea19924f7 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -412,6 +412,21 @@ public: } // namespace clang. +bool Selector::isKeywordSelector(ArrayRef<StringRef> Names) const { + assert(!Names.empty() && "must have >= 1 selector slots"); + if (getNumArgs() != Names.size()) + return false; + for (unsigned I = 0, E = Names.size(); I != E; ++I) { + if (getNameForSlot(I) != Names[I]) + return false; + } + return true; +} + +bool Selector::isUnarySelector(StringRef Name) const { + return isUnarySelector() && getNameForSlot(0) == Name; +} + unsigned Selector::getNumArgs() const { unsigned IIF = getIdentifierInfoFlag(); if (IIF <= ZeroArg) diff --git a/lib/Basic/LangStandards.cpp b/lib/Basic/LangStandards.cpp new file mode 100644 index 0000000000000..ee27bfd12113c --- /dev/null +++ b/lib/Basic/LangStandards.cpp @@ -0,0 +1,45 @@ +//===--- LangStandards.cpp - Language Standard Definitions ----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/LangStandard.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/ErrorHandling.h" +using namespace clang; + +#define LANGSTANDARD(id, name, lang, desc, features) \ + static const LangStandard Lang_##id = {name, desc, features, Language::lang}; +#include "clang/Basic/LangStandards.def" + +const LangStandard &LangStandard::getLangStandardForKind(Kind K) { + switch (K) { + case lang_unspecified: + llvm::report_fatal_error("getLangStandardForKind() on unspecified kind"); +#define LANGSTANDARD(id, name, lang, desc, features) \ + case lang_##id: return Lang_##id; +#include "clang/Basic/LangStandards.def" + } + llvm_unreachable("Invalid language kind!"); +} + +LangStandard::Kind LangStandard::getLangKind(StringRef Name) { + return llvm::StringSwitch<Kind>(Name) +#define LANGSTANDARD(id, name, lang, desc, features) .Case(name, lang_##id) +#define LANGSTANDARD_ALIAS(id, alias) .Case(alias, lang_##id) +#include "clang/Basic/LangStandards.def" + .Default(lang_unspecified); +} + +const LangStandard *LangStandard::getLangStandardForName(StringRef Name) { + Kind K = getLangKind(Name); + if (K == lang_unspecified) + return nullptr; + + return &getLangStandardForKind(K); +} + + diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index f394f26e550cb..541431dbbe7d9 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -246,8 +246,8 @@ ArrayRef<const FileEntry *> Module::getTopHeaders(FileManager &FileMgr) { if (!TopHeaderNames.empty()) { for (std::vector<std::string>::iterator I = TopHeaderNames.begin(), E = TopHeaderNames.end(); I != E; ++I) { - if (const FileEntry *FE = FileMgr.getFile(*I)) - TopHeaders.insert(FE); + if (auto FE = FileMgr.getFile(*I)) + TopHeaders.insert(*FE); } TopHeaderNames.clear(); } diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp index 82e193efef326..a52ed8caa1217 100644 --- a/lib/Basic/OpenMPKinds.cpp +++ b/lib/Basic/OpenMPKinds.cpp @@ -55,6 +55,8 @@ OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) { #define OPENMP_CLAUSE(Name, Class) .Case(#Name, OMPC_##Name) #include "clang/Basic/OpenMPKinds.def" .Case("uniform", OMPC_uniform) + .Case("device_type", OMPC_device_type) + .Case("match", OMPC_match) .Default(OMPC_unknown); } @@ -71,6 +73,10 @@ const char *clang::getOpenMPClauseName(OpenMPClauseKind Kind) { return "uniform"; case OMPC_threadprivate: return "threadprivate or thread local"; + case OMPC_device_type: + return "device_type"; + case OMPC_match: + return "match"; } llvm_unreachable("Invalid OpenMP clause kind"); } @@ -145,6 +151,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, .Case(#Name, OMPC_ATOMIC_DEFAULT_MEM_ORDER_##Name) #include "clang/Basic/OpenMPKinds.def" .Default(OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown); + case OMPC_device_type: + return llvm::StringSwitch<OpenMPDeviceType>(Str) +#define OPENMP_DEVICE_TYPE_KIND(Name) .Case(#Name, OMPC_DEVICE_TYPE_##Name) +#include "clang/Basic/OpenMPKinds.def" + .Default(OMPC_DEVICE_TYPE_unknown); case OMPC_unknown: case OMPC_threadprivate: case OMPC_if: @@ -192,6 +203,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_unified_shared_memory: case OMPC_reverse_offload: case OMPC_dynamic_allocators: + case OMPC_match: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); @@ -328,6 +340,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, #include "clang/Basic/OpenMPKinds.def" } llvm_unreachable("Invalid OpenMP 'atomic_default_mem_order' clause type"); + case OMPC_device_type: + switch (Type) { + case OMPC_DEVICE_TYPE_unknown: + return "unknown"; +#define OPENMP_DEVICE_TYPE_KIND(Name) \ + case OMPC_DEVICE_TYPE_##Name: \ + return #Name; +#include "clang/Basic/OpenMPKinds.def" + } + llvm_unreachable("Invalid OpenMP 'device_type' clause type"); case OMPC_unknown: case OMPC_threadprivate: case OMPC_if: @@ -375,6 +397,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_unified_shared_memory: case OMPC_reverse_offload: case OMPC_dynamic_allocators: + case OMPC_match: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); @@ -588,8 +611,6 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, break; } break; - case OMPD_declare_simd: - break; case OMPD_cancel: switch (CKind) { #define OPENMP_CANCEL_CLAUSE(Name) \ @@ -630,6 +651,36 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, break; } break; + case OMPD_master_taskloop: + switch (CKind) { +#define OPENMP_MASTER_TASKLOOP_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_master_taskloop_simd: + switch (CKind) { +#define OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_parallel_master_taskloop: + switch (CKind) { +#define OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; case OMPD_critical: switch (CKind) { #define OPENMP_CRITICAL_CLAUSE(Name) \ @@ -820,6 +871,16 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, break; } break; + case OMPD_declare_variant: + switch (CKind) { +#define OPENMP_DECLARE_VARIANT_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; case OMPD_declare_target: case OMPD_end_declare_target: case OMPD_unknown: @@ -831,6 +892,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, case OMPD_taskwait: case OMPD_cancellation_point: case OMPD_declare_reduction: + case OMPD_declare_simd: break; } return false; @@ -840,7 +902,9 @@ bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) { return DKind == OMPD_simd || DKind == OMPD_for || DKind == OMPD_for_simd || DKind == OMPD_parallel_for || DKind == OMPD_parallel_for_simd || DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd || - DKind == OMPD_distribute || DKind == OMPD_target_parallel_for || + DKind == OMPD_master_taskloop || DKind == OMPD_master_taskloop_simd || + DKind == OMPD_parallel_master_taskloop || DKind == OMPD_distribute || + DKind == OMPD_target_parallel_for || DKind == OMPD_distribute_parallel_for || DKind == OMPD_distribute_parallel_for_simd || DKind == OMPD_distribute_simd || @@ -871,7 +935,9 @@ bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) { } bool clang::isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind) { - return DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd; + return DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd || + DKind == OMPD_master_taskloop || DKind == OMPD_master_taskloop_simd || + DKind == OMPD_parallel_master_taskloop; } bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) { @@ -884,7 +950,8 @@ bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) { DKind == OMPD_teams_distribute_parallel_for || DKind == OMPD_teams_distribute_parallel_for_simd || DKind == OMPD_target_teams_distribute_parallel_for || - DKind == OMPD_target_teams_distribute_parallel_for_simd; + DKind == OMPD_target_teams_distribute_parallel_for_simd || + DKind == OMPD_parallel_master_taskloop; } bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) { @@ -920,6 +987,7 @@ bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) { bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) { return DKind == OMPD_simd || DKind == OMPD_for_simd || DKind == OMPD_parallel_for_simd || DKind == OMPD_taskloop_simd || + DKind == OMPD_master_taskloop_simd || DKind == OMPD_distribute_parallel_for_simd || DKind == OMPD_distribute_simd || DKind == OMPD_target_simd || DKind == OMPD_teams_distribute_simd || @@ -1021,6 +1089,12 @@ void clang::getOpenMPCaptureRegions( break; case OMPD_taskloop: case OMPD_taskloop_simd: + case OMPD_master_taskloop: + case OMPD_master_taskloop_simd: + CaptureRegions.push_back(OMPD_taskloop); + break; + case OMPD_parallel_master_taskloop: + CaptureRegions.push_back(OMPD_parallel); CaptureRegions.push_back(OMPD_taskloop); break; case OMPD_target_teams_distribute_parallel_for: @@ -1060,6 +1134,7 @@ void clang::getOpenMPCaptureRegions( case OMPD_declare_target: case OMPD_end_declare_target: case OMPD_requires: + case OMPD_declare_variant: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index 12b0305e707c9..58b95289eaf2d 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -96,7 +96,7 @@ void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree) { } const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, - const SourceManager &SM, + FileManager &FM, SourceLocation Loc, bool *Invalid) const { // Lazily create the Buffer for ContentCaches that wrap files. If we already @@ -134,9 +134,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, return Buffer.getPointer(); } - bool isVolatile = SM.userFilesAreVolatile() && !IsSystemFile; - auto BufferOrError = - SM.getFileManager().getBufferForFile(ContentsEntry, isVolatile); + auto BufferOrError = FM.getBufferForFile(ContentsEntry, IsFileVolatile); // 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 @@ -389,7 +387,7 @@ void SourceManager::initializeForReplay(const SourceManager &Old) { Clone->OrigEntry = Cache->OrigEntry; Clone->ContentsEntry = Cache->ContentsEntry; Clone->BufferOverridden = Cache->BufferOverridden; - Clone->IsSystemFile = Cache->IsSystemFile; + Clone->IsFileVolatile = Cache->IsFileVolatile; Clone->IsTransient = Cache->IsTransient; Clone->replaceBuffer(Cache->getRawBuffer(), /*DoNotFree*/true); return Clone; @@ -438,7 +436,7 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt, new (Entry) ContentCache(FileEnt); } - Entry->IsSystemFile = isSystemFile; + Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile; Entry->IsTransient = FilesAreTransient; return Entry; @@ -466,10 +464,9 @@ const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, // If the file of the SLocEntry changed we could still have loaded it. if (!SLocEntryLoaded[Index]) { // Try to recover; create a SLocEntry so the rest of clang can handle it. - LoadedSLocEntryTable[Index] = SLocEntry::get(0, - FileInfo::get(SourceLocation(), - getFakeContentCacheForRecovery(), - SrcMgr::C_User)); + LoadedSLocEntryTable[Index] = SLocEntry::get( + 0, FileInfo::get(SourceLocation(), getFakeContentCacheForRecovery(), + SrcMgr::C_User, "")); } } @@ -505,7 +502,7 @@ llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { const SrcMgr::ContentCache * SourceManager::getFakeContentCacheForRecovery() const { if (!FakeContentCacheForRecovery) { - FakeContentCacheForRecovery = llvm::make_unique<SrcMgr::ContentCache>(); + FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>(); FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(), /*DoNotFree=*/true); } @@ -556,7 +553,7 @@ FileID SourceManager::getNextFileID(FileID FID) const { /// createFileID - Create a new FileID for the specified ContentCache and /// include position. This works regardless of whether the ContentCache /// corresponds to a file or some other input source. -FileID SourceManager::createFileID(const ContentCache *File, +FileID SourceManager::createFileID(const ContentCache *File, StringRef Filename, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID, unsigned LoadedOffset) { @@ -565,14 +562,14 @@ FileID SourceManager::createFileID(const ContentCache *File, unsigned Index = unsigned(-LoadedID) - 2; assert(Index < LoadedSLocEntryTable.size() && "FileID out of range"); assert(!SLocEntryLoaded[Index] && "FileID already loaded"); - LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, - FileInfo::get(IncludePos, File, FileCharacter)); + LoadedSLocEntryTable[Index] = SLocEntry::get( + LoadedOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename)); SLocEntryLoaded[Index] = true; return FileID::get(LoadedID); } - LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, - FileInfo::get(IncludePos, File, - FileCharacter))); + LocalSLocEntryTable.push_back( + SLocEntry::get(NextLocalOffset, + FileInfo::get(IncludePos, File, FileCharacter, Filename))); unsigned FileSize = File->getSize(); assert(NextLocalOffset + FileSize + 1 > NextLocalOffset && NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset && @@ -646,7 +643,7 @@ const llvm::MemoryBuffer * SourceManager::getMemoryBufferForFile(const FileEntry *File, bool *Invalid) { const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); assert(IR && "getOrCreateContentCache() cannot return NULL"); - return IR->getBuffer(Diag, *this, SourceLocation(), Invalid); + return IR->getBuffer(Diag, getFileManager(), SourceLocation(), Invalid); } void SourceManager::overrideFileContents(const FileEntry *SourceFile, @@ -672,17 +669,19 @@ void SourceManager::overrideFileContents(const FileEntry *SourceFile, getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile; } -void SourceManager::disableFileContentsOverride(const FileEntry *File) { - if (!isFileOverridden(File)) - return; +const FileEntry * +SourceManager::bypassFileContentsOverride(const FileEntry &File) { + assert(isFileOverridden(&File)); + llvm::Optional<FileEntryRef> BypassFile = + FileMgr.getBypassFile(FileEntryRef(File.getName(), File)); - const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); - const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(nullptr); - const_cast<SrcMgr::ContentCache *>(IR)->ContentsEntry = IR->OrigEntry; + // If the file can't be found in the FS, give up. + if (!BypassFile) + return nullptr; - assert(OverriddenFilesInfo); - OverriddenFilesInfo->OverriddenFiles.erase(File); - OverriddenFilesInfo->OverriddenFilesWithBuffer.erase(File); + const FileEntry *FE = &BypassFile->getFileEntry(); + (void)getOrCreateContentCache(FE); + return FE; } void SourceManager::setFileIsTransient(const FileEntry *File) { @@ -700,7 +699,7 @@ StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const { } const llvm::MemoryBuffer *Buf = SLoc.getFile().getContentCache()->getBuffer( - Diag, *this, SourceLocation(), &MyInvalid); + Diag, getFileManager(), SourceLocation(), &MyInvalid); if (Invalid) *Invalid = MyInvalid; @@ -1131,7 +1130,7 @@ const char *SourceManager::getCharacterData(SourceLocation SL, } const llvm::MemoryBuffer *Buffer = Entry.getFile().getContentCache()->getBuffer( - Diag, *this, SourceLocation(), &CharDataInvalid); + Diag, getFileManager(), SourceLocation(), &CharDataInvalid); if (Invalid) *Invalid = CharDataInvalid; return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second); @@ -1228,7 +1227,7 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, const SourceManager &SM, bool &Invalid) { // Note that calling 'getBuffer()' may lazily page in the file. const MemoryBuffer *Buffer = - FI->getBuffer(Diag, SM, SourceLocation(), &Invalid); + FI->getBuffer(Diag, SM.getFileManager(), SourceLocation(), &Invalid); if (Invalid) return; @@ -1459,7 +1458,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc, if (C->OrigEntry) Filename = C->OrigEntry->getName(); else - Filename = C->getBuffer(Diag, *this)->getBufferIdentifier(); + Filename = C->getBuffer(Diag, getFileManager())->getBufferIdentifier(); unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid); if (Invalid) @@ -1558,22 +1557,6 @@ unsigned SourceManager::getFileIDSize(FileID FID) const { // Other miscellaneous methods. //===----------------------------------------------------------------------===// -/// Retrieve the inode for the given file entry, if possible. -/// -/// This routine involves a system call, and therefore should only be used -/// in non-performance-critical code. -static Optional<llvm::sys::fs::UniqueID> -getActualFileUID(const FileEntry *File) { - if (!File) - return None; - - llvm::sys::fs::UniqueID ID; - if (llvm::sys::fs::getUniqueID(File->getName(), ID)) - return None; - - return ID; -} - /// Get the source location for the given file:line:col triplet. /// /// If the source file is included multiple times, the source location will @@ -1595,13 +1578,8 @@ SourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile, FileID SourceManager::translateFile(const FileEntry *SourceFile) const { assert(SourceFile && "Null source file!"); - // Find the first file ID that corresponds to the given file. - FileID FirstFID; - // First, check the main file ID, since it is common to look for a // location in the main file. - Optional<llvm::sys::fs::UniqueID> SourceFileUID; - Optional<StringRef> SourceFileName; if (MainFileID.isValid()) { bool Invalid = false; const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid); @@ -1609,100 +1587,35 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const { return FileID(); if (MainSLoc.isFile()) { - const ContentCache *MainContentCache - = MainSLoc.getFile().getContentCache(); - if (!MainContentCache || !MainContentCache->OrigEntry) { - // Can't do anything - } else if (MainContentCache->OrigEntry == SourceFile) { - FirstFID = MainFileID; - } else { - // Fall back: check whether we have the same base name and inode - // as the main file. - const FileEntry *MainFile = MainContentCache->OrigEntry; - SourceFileName = llvm::sys::path::filename(SourceFile->getName()); - if (*SourceFileName == llvm::sys::path::filename(MainFile->getName())) { - SourceFileUID = getActualFileUID(SourceFile); - if (SourceFileUID) { - if (Optional<llvm::sys::fs::UniqueID> MainFileUID = - getActualFileUID(MainFile)) { - if (*SourceFileUID == *MainFileUID) { - FirstFID = MainFileID; - SourceFile = MainFile; - } - } - } - } - } + const ContentCache *MainContentCache = + MainSLoc.getFile().getContentCache(); + if (MainContentCache && MainContentCache->OrigEntry == SourceFile) + return MainFileID; } } - if (FirstFID.isInvalid()) { - // The location we're looking for isn't in the main file; look - // through all of the local source locations. - for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { - bool Invalid = false; - const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid); - if (Invalid) - return FileID(); + // The location we're looking for isn't in the main file; look + // through all of the local source locations. + for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { + bool Invalid = false; + const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid); + if (Invalid) + return FileID(); - if (SLoc.isFile() && - SLoc.getFile().getContentCache() && - SLoc.getFile().getContentCache()->OrigEntry == SourceFile) { - FirstFID = FileID::get(I); - break; - } - } - // If that still didn't help, try the modules. - if (FirstFID.isInvalid()) { - for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) { - const SLocEntry &SLoc = getLoadedSLocEntry(I); - if (SLoc.isFile() && - SLoc.getFile().getContentCache() && - SLoc.getFile().getContentCache()->OrigEntry == SourceFile) { - FirstFID = FileID::get(-int(I) - 2); - break; - } - } - } + if (SLoc.isFile() && SLoc.getFile().getContentCache() && + SLoc.getFile().getContentCache()->OrigEntry == SourceFile) + return FileID::get(I); } - // If we haven't found what we want yet, try again, but this time stat() - // each of the files in case the files have changed since we originally - // parsed the file. - if (FirstFID.isInvalid() && - (SourceFileName || - (SourceFileName = llvm::sys::path::filename(SourceFile->getName()))) && - (SourceFileUID || (SourceFileUID = getActualFileUID(SourceFile)))) { - bool Invalid = false; - for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { - FileID IFileID; - IFileID.ID = I; - const SLocEntry &SLoc = getSLocEntry(IFileID, &Invalid); - if (Invalid) - return FileID(); - - if (SLoc.isFile()) { - const ContentCache *FileContentCache - = SLoc.getFile().getContentCache(); - const FileEntry *Entry = FileContentCache ? FileContentCache->OrigEntry - : nullptr; - if (Entry && - *SourceFileName == llvm::sys::path::filename(Entry->getName())) { - if (Optional<llvm::sys::fs::UniqueID> EntryUID = - getActualFileUID(Entry)) { - if (*SourceFileUID == *EntryUID) { - FirstFID = FileID::get(I); - SourceFile = Entry; - break; - } - } - } - } - } + // If that still didn't help, try the modules. + for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) { + const SLocEntry &SLoc = getLoadedSLocEntry(I); + if (SLoc.isFile() && SLoc.getFile().getContentCache() && + SLoc.getFile().getContentCache()->OrigEntry == SourceFile) + return FileID::get(-int(I) - 2); } - (void) SourceFile; - return FirstFID; + return FileID(); } /// Get the source location in \arg FID for the given line:col. @@ -1745,13 +1658,13 @@ SourceLocation SourceManager::translateLineCol(FileID FID, } if (Line > Content->NumLines) { - unsigned Size = Content->getBuffer(Diag, *this)->getBufferSize(); + unsigned Size = Content->getBuffer(Diag, getFileManager())->getBufferSize(); if (Size > 0) --Size; return FileLoc.getLocWithOffset(Size); } - const llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, *this); + const llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, getFileManager()); unsigned FilePos = Content->SourceLineCache[Line - 1]; const char *Buf = Buffer->getBufferStart() + FilePos; unsigned BufLength = Buffer->getBufferSize() - FilePos; @@ -1927,7 +1840,7 @@ SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const { std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID]; if (!MacroArgsCache) { - MacroArgsCache = llvm::make_unique<MacroArgsMap>(); + MacroArgsCache = std::make_unique<MacroArgsMap>(); computeMacroArgsCache(*MacroArgsCache, FID); } @@ -2256,14 +2169,14 @@ SourceManagerForFile::SourceManagerForFile(StringRef FileName, // This is passed to `SM` as reference, so the pointer has to be referenced // in `Environment` so that `FileMgr` can out-live this function scope. FileMgr = - llvm::make_unique<FileManager>(FileSystemOptions(), InMemoryFileSystem); + std::make_unique<FileManager>(FileSystemOptions(), InMemoryFileSystem); // This is passed to `SM` as reference, so the pointer has to be referenced // by `Environment` due to the same reason above. - Diagnostics = llvm::make_unique<DiagnosticsEngine>( + Diagnostics = std::make_unique<DiagnosticsEngine>( IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), new DiagnosticOptions); - SourceMgr = llvm::make_unique<SourceManager>(*Diagnostics, *FileMgr); - FileID ID = SourceMgr->createFileID(FileMgr->getFile(FileName), + SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr); + FileID ID = SourceMgr->createFileID(*FileMgr->getFile(FileName), SourceLocation(), clang::SrcMgr::C_User); assert(ID.isValid()); SourceMgr->setMainFileID(ID); diff --git a/lib/Basic/Stack.cpp b/lib/Basic/Stack.cpp new file mode 100644 index 0000000000000..5e47509315002 --- /dev/null +++ b/lib/Basic/Stack.cpp @@ -0,0 +1,75 @@ +//===--- Stack.cpp - Utilities for dealing with stack space ---------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Defines utilities for dealing with stack allocation and stack space. +/// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/Stack.h" +#include "llvm/ADT/Optional.h" +#include "llvm/Support/CrashRecoveryContext.h" + +#ifdef _MSC_VER +#include <intrin.h> // for _AddressOfReturnAddress +#endif + +static LLVM_THREAD_LOCAL void *BottomOfStack = nullptr; + +static void *getStackPointer() { +#if __GNUC__ || __has_builtin(__builtin_frame_address) + return __builtin_frame_address(0); +#elif defined(_MSC_VER) + return _AddressOfReturnAddress(); +#else + char CharOnStack = 0; + // The volatile store here is intended to escape the local variable, to + // prevent the compiler from optimizing CharOnStack into anything other + // than a char on the stack. + // + // Tested on: MSVC 2015 - 2019, GCC 4.9 - 9, Clang 3.2 - 9, ICC 13 - 19. + char *volatile Ptr = &CharOnStack; + return Ptr; +#endif +} + +void clang::noteBottomOfStack() { + if (!BottomOfStack) + BottomOfStack = getStackPointer(); +} + +bool clang::isStackNearlyExhausted() { + // We consider 256 KiB to be sufficient for any code that runs between checks + // for stack size. + constexpr size_t SufficientStack = 256 << 10; + + // If we don't know where the bottom of the stack is, hope for the best. + if (!BottomOfStack) + return false; + + intptr_t StackDiff = (intptr_t)getStackPointer() - (intptr_t)BottomOfStack; + size_t StackUsage = (size_t)std::abs(StackDiff); + + // If the stack pointer has a surprising value, we do not understand this + // stack usage scheme. (Perhaps the target allocates new stack regions on + // demand for us.) Don't try to guess what's going on. + if (StackUsage > DesiredStackSize) + return false; + + return StackUsage >= DesiredStackSize - SufficientStack; +} + +void clang::runWithSufficientStackSpaceSlow(llvm::function_ref<void()> Diag, + llvm::function_ref<void()> Fn) { + llvm::CrashRecoveryContext CRC; + CRC.RunSafelyOnThread([&] { + noteBottomOfStack(); + Diag(); + Fn(); + }, DesiredStackSize); +} diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index a9dfe69b90c5e..3a21a19e1f19a 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -17,6 +17,7 @@ #include "clang/Basic/LangOptions.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/IR/DataLayout.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetParser.h" #include <cstdlib> @@ -111,6 +112,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { HasAlignMac68kSupport = false; HasBuiltinMSVaList = false; IsRenderScriptTarget = false; + HasAArch64SVETypes = false; // Default to no types using fpret. RealTypeUsesObjCFPRet = 0; @@ -135,6 +137,10 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { // Out of line virtual dtor for TargetInfo. TargetInfo::~TargetInfo() {} +void TargetInfo::resetDataLayout(StringRef DL) { + DataLayout.reset(new llvm::DataLayout(DL)); +} + bool TargetInfo::checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const { Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=branch"; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index a08e399e72700..63a64ed2931a8 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -363,15 +363,26 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, return new AMDGPUTargetInfo(Triple, Opts); case llvm::Triple::riscv32: - // TODO: add cases for FreeBSD, NetBSD, RTEMS once tested. - if (os == llvm::Triple::Linux) + // TODO: add cases for NetBSD, RTEMS once tested. + switch (os) { + case llvm::Triple::FreeBSD: + return new FreeBSDTargetInfo<RISCV32TargetInfo>(Triple, Opts); + case llvm::Triple::Linux: return new LinuxTargetInfo<RISCV32TargetInfo>(Triple, Opts); - return new RISCV32TargetInfo(Triple, Opts); + default: + return new RISCV32TargetInfo(Triple, Opts); + } + case llvm::Triple::riscv64: - // TODO: add cases for FreeBSD, NetBSD, RTEMS once tested. - if (os == llvm::Triple::Linux) + // TODO: add cases for NetBSD, RTEMS once tested. + switch (os) { + case llvm::Triple::FreeBSD: + return new FreeBSDTargetInfo<RISCV64TargetInfo>(Triple, Opts); + case llvm::Triple::Linux: return new LinuxTargetInfo<RISCV64TargetInfo>(Triple, Opts); - return new RISCV64TargetInfo(Triple, Opts); + default: + return new RISCV64TargetInfo(Triple, Opts); + } case llvm::Triple::sparc: switch (os) { diff --git a/lib/Basic/Targets/AArch64.cpp b/lib/Basic/Targets/AArch64.cpp index 74ac69ab8946a..c86cc63e3d84c 100644 --- a/lib/Basic/Targets/AArch64.cpp +++ b/lib/Basic/Targets/AArch64.cpp @@ -62,6 +62,16 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, // Make __builtin_ms_va_list available. HasBuiltinMSVaList = true; + // Make the SVE types available. Note that this deliberately doesn't + // depend on SveMode, since in principle it should be possible to turn + // SVE on and off within a translation unit. It should also be possible + // to compile the global declaration: + // + // __SVInt8_t *ptr; + // + // even without SVE. + HasAArch64SVETypes = true; + // {} in inline assembly are neon specifiers, not assembly variant // specifiers. NoAsmVariants = true; @@ -196,9 +206,6 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__ARM_NEON_FP", "0xE"); } - if (FPU & SveMode) - Builder.defineMacro("__ARM_FEATURE_SVE", "1"); - if (HasCRC) Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); @@ -219,6 +226,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasMTE) Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1"); + if (HasTME) + Builder.defineMacro("__ARM_FEATURE_TME", "1"); + if ((FPU & NeonMode) && HasFP16FML) Builder.defineMacro("__ARM_FEATURE_FP16FML", "1"); @@ -270,6 +280,7 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasDotProd = false; HasFP16FML = false; HasMTE = false; + HasTME = false; ArchKind = llvm::AArch64::ArchKind::ARMV8A; for (const auto &Feature : Features) { @@ -301,6 +312,8 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasFP16FML = true; if (Feature == "+mte") HasMTE = true; + if (Feature == "+tme") + HasTME = true; } setDataLayout(); @@ -351,10 +364,19 @@ const char *const AArch64TargetInfo::GCCRegNames[] = { "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", - // Vector registers + // Neon vector registers "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", - "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31" + "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", + + // SVE vector registers + "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10", + "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21", + "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31", + + // SVE predicate registers + "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10", + "p11", "p12", "p13", "p14", "p15" }; ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const { diff --git a/lib/Basic/Targets/AArch64.h b/lib/Basic/Targets/AArch64.h index 5833c146003b0..b6aa07780edda 100644 --- a/lib/Basic/Targets/AArch64.h +++ b/lib/Basic/Targets/AArch64.h @@ -35,6 +35,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { bool HasDotProd; bool HasFP16FML; bool HasMTE; + bool HasTME; llvm::AArch64::ArchKind ArchKind; diff --git a/lib/Basic/Targets/AMDGPU.cpp b/lib/Basic/Targets/AMDGPU.cpp index b5c82e2885707..481630c0fa455 100644 --- a/lib/Basic/Targets/AMDGPU.cpp +++ b/lib/Basic/Targets/AMDGPU.cpp @@ -17,6 +17,7 @@ #include "clang/Basic/MacroBuilder.h" #include "clang/Basic/TargetBuiltins.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/IR/DataLayout.h" using namespace clang; using namespace clang::targets; @@ -131,9 +132,6 @@ bool AMDGPUTargetInfo::initFeatureMap( // XXX - What does the member GPU mean if device name string passed here? if (isAMDGCN(getTriple())) { - if (CPU.empty()) - CPU = "gfx600"; - switch (llvm::AMDGPU::parseArchAMDGCN(CPU)) { case GK_GFX1012: case GK_GFX1011: @@ -145,6 +143,7 @@ bool AMDGPUTargetInfo::initFeatureMap( case GK_GFX1010: Features["dl-insts"] = true; Features["ci-insts"] = true; + Features["flat-address-space"] = true; Features["16-bit-insts"] = true; Features["dpp"] = true; Features["gfx8-insts"] = true; @@ -184,12 +183,13 @@ bool AMDGPUTargetInfo::initFeatureMap( case GK_GFX701: case GK_GFX700: Features["ci-insts"] = true; + Features["flat-address-space"] = true; LLVM_FALLTHROUGH; case GK_GFX601: case GK_GFX600: break; case GK_NONE: - return false; + break; default: llvm_unreachable("Unhandled GPU!"); } diff --git a/lib/Basic/Targets/ARM.cpp b/lib/Basic/Targets/ARM.cpp index c6834b9fac15b..437a77afdc998 100644 --- a/lib/Basic/Targets/ARM.cpp +++ b/lib/Basic/Targets/ARM.cpp @@ -309,8 +309,9 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple, setAtomic(); // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS) + // as well the default alignment if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android)) - MaxVectorAlign = 64; + DefaultAlignForAttributeAligned = MaxVectorAlign = 64; // Do force alignment of members that follow zero length bitfields. If // the alignment of the zero-length bitfield is greater than the member @@ -321,7 +322,7 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple, if (Triple.getOS() == llvm::Triple::Linux || Triple.getOS() == llvm::Triple::UnknownOS) this->MCountName = Opts.EABIVersion == llvm::EABI::GNU - ? "\01__gnu_mcount_nc" + ? "llvm.arm.gnu.eabi.mcount" : "\01mcount"; SoftFloatABI = llvm::is_contained(Opts.FeaturesAsWritten, "+soft-float-abi"); @@ -427,11 +428,10 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, for (const auto &Feature : Features) { if (Feature == "+soft-float") { SoftFloat = true; - } else if (Feature == "+vfp2sp" || Feature == "+vfp2d16sp" || - Feature == "+vfp2" || Feature == "+vfp2d16") { + } else if (Feature == "+vfp2sp" || Feature == "+vfp2") { FPU |= VFP2FPU; HW_FP |= HW_FP_SP; - if (Feature == "+vfp2" || Feature == "+vfp2d16") + if (Feature == "+vfp2") HW_FP |= HW_FP_DP; } else if (Feature == "+vfp3sp" || Feature == "+vfp3d16sp" || Feature == "+vfp3" || Feature == "+vfp3d16") { @@ -884,19 +884,102 @@ bool ARMTargetInfo::validateAsmConstraint( switch (*Name) { default: break; - case 'l': // r0-r7 - case 'h': // r8-r15 - case 't': // VFP Floating point register single precision - case 'w': // VFP Floating point register double precision + case 'l': // r0-r7 if thumb, r0-r15 if ARM Info.setAllowsRegister(); return true; + case 'h': // r8-r15, thumb only + if (isThumb()) { + Info.setAllowsRegister(); + return true; + } + break; + case 's': // An integer constant, but allowing only relocatable values. + return true; + case 't': // s0-s31, d0-d31, or q0-q15 + case 'w': // s0-s15, d0-d7, or q0-q3 + case 'x': // s0-s31, d0-d15, or q0-q7 + Info.setAllowsRegister(); + return true; + case 'j': // An immediate integer between 0 and 65535 (valid for MOVW) + // only available in ARMv6T2 and above + if (CPUAttr.equals("6T2") || ArchVersion >= 7) { + Info.setRequiresImmediate(0, 65535); + return true; + } + break; case 'I': + if (isThumb()) { + if (!supportsThumb2()) + Info.setRequiresImmediate(0, 255); + else + // FIXME: should check if immediate value would be valid for a Thumb2 + // data-processing instruction + Info.setRequiresImmediate(); + } else + // FIXME: should check if immediate value would be valid for an ARM + // data-processing instruction + Info.setRequiresImmediate(); + return true; case 'J': + if (isThumb() && !supportsThumb2()) + Info.setRequiresImmediate(-255, -1); + else + Info.setRequiresImmediate(-4095, 4095); + return true; case 'K': + if (isThumb()) { + if (!supportsThumb2()) + // FIXME: should check if immediate value can be obtained from shifting + // a value between 0 and 255 left by any amount + Info.setRequiresImmediate(); + else + // FIXME: should check if immediate value would be valid for a Thumb2 + // data-processing instruction when inverted + Info.setRequiresImmediate(); + } else + // FIXME: should check if immediate value would be valid for an ARM + // data-processing instruction when inverted + Info.setRequiresImmediate(); + return true; case 'L': + if (isThumb()) { + if (!supportsThumb2()) + Info.setRequiresImmediate(-7, 7); + else + // FIXME: should check if immediate value would be valid for a Thumb2 + // data-processing instruction when negated + Info.setRequiresImmediate(); + } else + // FIXME: should check if immediate value would be valid for an ARM + // data-processing instruction when negated + Info.setRequiresImmediate(); + return true; case 'M': - // FIXME + if (isThumb() && !supportsThumb2()) + // FIXME: should check if immediate value is a multiple of 4 between 0 and + // 1020 + Info.setRequiresImmediate(); + else + // FIXME: should check if immediate value is a power of two or a integer + // between 0 and 32 + Info.setRequiresImmediate(); return true; + case 'N': + // Thumb1 only + if (isThumb() && !supportsThumb2()) { + Info.setRequiresImmediate(0, 31); + return true; + } + break; + case 'O': + // Thumb1 only + if (isThumb() && !supportsThumb2()) { + // FIXME: should check if immediate value is a multiple of 4 between -508 + // and 508 + Info.setRequiresImmediate(); + return true; + } + break; case 'Q': // A memory address that is a single base register. Info.setAllowsMemory(); return true; diff --git a/lib/Basic/Targets/BPF.cpp b/lib/Basic/Targets/BPF.cpp index 0cf55a58a9512..2fe2450b9a654 100644 --- a/lib/Basic/Targets/BPF.cpp +++ b/lib/Basic/Targets/BPF.cpp @@ -13,11 +13,18 @@ #include "BPF.h" #include "Targets.h" #include "clang/Basic/MacroBuilder.h" +#include "clang/Basic/TargetBuiltins.h" #include "llvm/ADT/StringRef.h" using namespace clang; using namespace clang::targets; +const Builtin::Info BPFTargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) \ + {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, +#include "clang/Basic/BuiltinsBPF.def" +}; + void BPFTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__bpf__"); @@ -34,3 +41,8 @@ bool BPFTargetInfo::isValidCPUName(StringRef Name) const { void BPFTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const { Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames)); } + +ArrayRef<Builtin::Info> BPFTargetInfo::getTargetBuiltins() const { + return llvm::makeArrayRef(BuiltinInfo, clang::BPF::LastTSBuiltin - + Builtin::FirstTSBuiltin); +} diff --git a/lib/Basic/Targets/BPF.h b/lib/Basic/Targets/BPF.h index 79abd8828a2c9..117f81430bf40 100644 --- a/lib/Basic/Targets/BPF.h +++ b/lib/Basic/Targets/BPF.h @@ -22,6 +22,8 @@ namespace clang { namespace targets { class LLVM_LIBRARY_VISIBILITY BPFTargetInfo : public TargetInfo { + static const Builtin::Info BuiltinInfo[]; + public: BPFTargetInfo(const llvm::Triple &Triple, const TargetOptions &) : TargetInfo(Triple) { @@ -54,7 +56,7 @@ public: Features[Name] = Enabled; } - ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; } + ArrayRef<Builtin::Info> getTargetBuiltins() const override; const char *getClobbers() const override { return ""; } diff --git a/lib/Basic/Targets/OSTargets.h b/lib/Basic/Targets/OSTargets.h index 8542311ffa41d..cc72a0a39f30f 100644 --- a/lib/Basic/Targets/OSTargets.h +++ b/lib/Basic/Targets/OSTargets.h @@ -561,6 +561,10 @@ public: break; } } + TargetInfo::CallingConvCheckResult + checkCallingConvention(CallingConv CC) const override { + return (CC == CC_C) ? TargetInfo::CCCR_OK : TargetInfo::CCCR_Error; + } }; // RTEMS Target @@ -618,8 +622,11 @@ protected: Builder.defineMacro("_XOPEN_SOURCE", "600"); else Builder.defineMacro("_XOPEN_SOURCE", "500"); - if (Opts.CPlusPlus) + if (Opts.CPlusPlus) { Builder.defineMacro("__C99FEATURES__"); + Builder.defineMacro("_FILE_OFFSET_BITS", "64"); + } + // GCC restricts the next two to C++. Builder.defineMacro("_LARGEFILE_SOURCE"); Builder.defineMacro("_LARGEFILE64_SOURCE"); Builder.defineMacro("__EXTENSIONS__"); @@ -768,9 +775,11 @@ public: if (Triple.getArch() == llvm::Triple::arm) { // Handled in ARM's setABI(). } else if (Triple.getArch() == llvm::Triple::x86) { - this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32-S128"); + this->resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-" + "i64:64-n8:16:32-S128"); } else if (Triple.getArch() == llvm::Triple::x86_64) { - this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32:64-S128"); + this->resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-" + "i64:64-n8:16:32:64-S128"); } else if (Triple.getArch() == llvm::Triple::mipsel) { // Handled on mips' setDataLayout. } else { diff --git a/lib/Basic/Targets/PPC.cpp b/lib/Basic/Targets/PPC.cpp index 2a773d9992869..a40991048873e 100644 --- a/lib/Basic/Targets/PPC.cpp +++ b/lib/Basic/Targets/PPC.cpp @@ -54,6 +54,10 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasFloat128 = true; } else if (Feature == "+power9-vector") { HasP9Vector = true; + } else if (Feature == "+spe") { + HasSPE = true; + LongDoubleWidth = LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); } else if (Feature == "-hard-float") { FloatABI = SoftFloat; } @@ -165,6 +169,10 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__VEC__", "10206"); Builder.defineMacro("__ALTIVEC__"); } + if (HasSPE) { + Builder.defineMacro("__SPE__"); + Builder.defineMacro("__NO_FPRS__"); + } if (HasVSX) Builder.defineMacro("__VSX__"); if (HasP8Vector) @@ -203,7 +211,6 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, // __CMODEL_LARGE__ // _CALL_SYSV // _CALL_DARWIN - // __NO_FPRS__ } // Handle explicit options being passed to the compiler here: if we've @@ -332,6 +339,7 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const { .Case("extdiv", HasExtDiv) .Case("float128", HasFloat128) .Case("power9-vector", HasP9Vector) + .Case("spe", HasSPE) .Default(false); } diff --git a/lib/Basic/Targets/PPC.h b/lib/Basic/Targets/PPC.h index 6e5df097921b1..6c6421c28e232 100644 --- a/lib/Basic/Targets/PPC.h +++ b/lib/Basic/Targets/PPC.h @@ -66,6 +66,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { bool HasBPERMD = false; bool HasExtDiv = false; bool HasP9Vector = false; + bool HasSPE = false; protected: std::string ABI; diff --git a/lib/Basic/Targets/RISCV.cpp b/lib/Basic/Targets/RISCV.cpp index f800bb0b25dac..ab8272c034fd3 100644 --- a/lib/Basic/Targets/RISCV.cpp +++ b/lib/Basic/Targets/RISCV.cpp @@ -19,23 +19,38 @@ using namespace clang::targets; ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const { static const char *const GCCRegNames[] = { + // Integer registers "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", - "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31"}; + "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", + + // Floating point registers + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"}; return llvm::makeArrayRef(GCCRegNames); } ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const { static const TargetInfo::GCCRegAlias GCCRegAliases[] = { - {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"}, - {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"}, - {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"}, - {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"}, - {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"}, - {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"}, - {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"}, - {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"}}; + {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"}, + {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"}, + {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"}, + {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"}, + {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"}, + {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"}, + {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"}, + {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"}, + {{"ft0"}, "f0"}, {{"ft1"}, "f1"}, {{"ft2"}, "f2"}, {{"ft3"}, "f3"}, + {{"ft4"}, "f4"}, {{"ft5"}, "f5"}, {{"ft6"}, "f6"}, {{"ft7"}, "f7"}, + {{"fs0"}, "f8"}, {{"fs1"}, "f9"}, {{"fa0"}, "f10"}, {{"fa1"}, "f11"}, + {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"}, {{"fa5"}, "f15"}, + {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"}, {{"fs3"}, "f19"}, + {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"}, {{"fs7"}, "f23"}, + {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"}, + {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}}; return llvm::makeArrayRef(GCCRegAliases); } @@ -56,6 +71,14 @@ bool RISCVTargetInfo::validateAsmConstraint( // A 5-bit unsigned immediate for CSR access instructions. Info.setRequiresImmediate(0, 31); return true; + case 'f': + // A floating-point register. + Info.setAllowsRegister(); + return true; + case 'A': + // An address that is held in a general-purpose register. + Info.setAllowsMemory(); + return true; } } @@ -65,9 +88,25 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__riscv"); bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); - // TODO: modify when more code models and ABIs are supported. - Builder.defineMacro("__riscv_cmodel_medlow"); - Builder.defineMacro("__riscv_float_abi_soft"); + StringRef CodeModel = getTargetOpts().CodeModel; + if (CodeModel == "default") + CodeModel = "small"; + + if (CodeModel == "small") + Builder.defineMacro("__riscv_cmodel_medlow"); + else if (CodeModel == "medium") + Builder.defineMacro("__riscv_cmodel_medany"); + + StringRef ABIName = getABI(); + if (ABIName == "ilp32f" || ABIName == "lp64f") + Builder.defineMacro("__riscv_float_abi_single"); + else if (ABIName == "ilp32d" || ABIName == "lp64d") + Builder.defineMacro("__riscv_float_abi_double"); + else + Builder.defineMacro("__riscv_float_abi_soft"); + + if (ABIName == "ilp32e") + Builder.defineMacro("__riscv_abi_rve"); if (HasM) { Builder.defineMacro("__riscv_mul"); diff --git a/lib/Basic/Targets/RISCV.h b/lib/Basic/Targets/RISCV.h index bc814b79ce516..9118494a87ab4 100644 --- a/lib/Basic/Targets/RISCV.h +++ b/lib/Basic/Targets/RISCV.h @@ -87,13 +87,19 @@ public: } bool setABI(const std::string &Name) override { - // TODO: support ilp32f and ilp32d ABIs. - if (Name == "ilp32") { + if (Name == "ilp32" || Name == "ilp32f" || Name == "ilp32d") { ABI = Name; return true; } return false; } + + void setMaxAtomicWidth() override { + MaxAtomicPromoteWidth = 128; + + if (HasA) + MaxAtomicInlineWidth = 32; + } }; class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo { public: @@ -105,13 +111,19 @@ public: } bool setABI(const std::string &Name) override { - // TODO: support lp64f and lp64d ABIs. - if (Name == "lp64") { + if (Name == "lp64" || Name == "lp64f" || Name == "lp64d") { ABI = Name; return true; } return false; } + + void setMaxAtomicWidth() override { + MaxAtomicPromoteWidth = 128; + + if (HasA) + MaxAtomicInlineWidth = 64; + } }; } // namespace targets } // namespace clang diff --git a/lib/Basic/Targets/SPIR.h b/lib/Basic/Targets/SPIR.h index 6023c868dbdc8..802ccf8b671e2 100644 --- a/lib/Basic/Targets/SPIR.h +++ b/lib/Basic/Targets/SPIR.h @@ -88,7 +88,7 @@ public: : CCCR_Warning; } - CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { + CallingConv getDefaultCallingConv() const override { return CC_SpirFunction; } diff --git a/lib/Basic/Targets/Sparc.h b/lib/Basic/Targets/Sparc.h index 963192a4634fc..1f799565e99b5 100644 --- a/lib/Basic/Targets/Sparc.h +++ b/lib/Basic/Targets/Sparc.h @@ -208,6 +208,7 @@ public: // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned. LongDoubleWidth = 128; LongDoubleAlign = 128; + SuitableAlign = 128; LongDoubleFormat = &llvm::APFloat::IEEEquad(); MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; } diff --git a/lib/Basic/Targets/SystemZ.cpp b/lib/Basic/Targets/SystemZ.cpp index d86928a6333b0..ad3915e4d5dd0 100644 --- a/lib/Basic/Targets/SystemZ.cpp +++ b/lib/Basic/Targets/SystemZ.cpp @@ -92,7 +92,7 @@ static constexpr ISANameRevision ISARevisions[] = { {{"arch10"}, 10}, {{"zEC12"}, 10}, {{"arch11"}, 11}, {{"z13"}, 11}, {{"arch12"}, 12}, {{"z14"}, 12}, - {{"arch13"}, 13}, + {{"arch13"}, 13}, {{"z15"}, 13} }; int SystemZTargetInfo::getISARevision(StringRef Name) const { diff --git a/lib/Basic/Targets/X86.cpp b/lib/Basic/Targets/X86.cpp index d618c90b05c02..311ae6e170287 100644 --- a/lib/Basic/Targets/X86.cpp +++ b/lib/Basic/Targets/X86.cpp @@ -157,11 +157,20 @@ bool X86TargetInfo::initFeatureMap( // SkylakeServer cores inherits all SKL features, except SGX goto SkylakeCommon; + case CK_Tigerlake: + setFeatureEnabledImpl(Features, "avx512vp2intersect", true); + setFeatureEnabledImpl(Features, "movdiri", true); + setFeatureEnabledImpl(Features, "movdir64b", true); + setFeatureEnabledImpl(Features, "shstk", true); + // Tigerlake cores inherits IcelakeClient, except pconfig and wbnoinvd + goto IcelakeCommon; + case CK_IcelakeServer: setFeatureEnabledImpl(Features, "pconfig", true); setFeatureEnabledImpl(Features, "wbnoinvd", true); LLVM_FALLTHROUGH; case CK_IcelakeClient: +IcelakeCommon: setFeatureEnabledImpl(Features, "vaes", true); setFeatureEnabledImpl(Features, "gfni", true); setFeatureEnabledImpl(Features, "vpclmulqdq", true); @@ -189,7 +198,6 @@ bool X86TargetInfo::initFeatureMap( SkylakeCommon: setFeatureEnabledImpl(Features, "xsavec", true); setFeatureEnabledImpl(Features, "xsaves", true); - setFeatureEnabledImpl(Features, "mpx", true); setFeatureEnabledImpl(Features, "clflushopt", true); setFeatureEnabledImpl(Features, "aes", true); LLVM_FALLTHROUGH; @@ -268,7 +276,6 @@ SkylakeCommon: setFeatureEnabledImpl(Features, "xsavec", true); setFeatureEnabledImpl(Features, "xsaves", true); setFeatureEnabledImpl(Features, "clflushopt", true); - setFeatureEnabledImpl(Features, "mpx", true); setFeatureEnabledImpl(Features, "fsgsbase", true); setFeatureEnabledImpl(Features, "aes", true); LLVM_FALLTHROUGH; @@ -789,8 +796,6 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasAVX512VP2INTERSECT = true; } else if (Feature == "+sha") { HasSHA = true; - } else if (Feature == "+mpx") { - HasMPX = true; } else if (Feature == "+shstk") { HasSHSTK = true; } else if (Feature == "+movbe") { @@ -895,7 +900,7 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, /// definitions for this particular subtarget. void X86TargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { - // Inline assembly supports X86 flag outputs. + // Inline assembly supports X86 flag outputs. Builder.defineMacro("__GCC_ASM_FLAG_OUTPUTS__"); std::string CodeModel = getTargetOpts().CodeModel; @@ -1000,6 +1005,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_Cannonlake: case CK_IcelakeClient: case CK_IcelakeServer: + case CK_Tigerlake: // 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. @@ -1210,8 +1216,6 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__CLWB__"); if (HasWBNOINVD) Builder.defineMacro("__WBNOINVD__"); - if (HasMPX) - Builder.defineMacro("__MPX__"); if (HasSHSTK) Builder.defineMacro("__SHSTK__"); if (HasSGX) @@ -1368,7 +1372,6 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const { .Case("movbe", true) .Case("movdiri", true) .Case("movdir64b", true) - .Case("mpx", true) .Case("mwaitx", true) .Case("pclmul", true) .Case("pconfig", true) @@ -1452,7 +1455,6 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("movbe", HasMOVBE) .Case("movdiri", HasMOVDIRI) .Case("movdir64b", HasMOVDIR64B) - .Case("mpx", HasMPX) .Case("mwaitx", HasMWAITX) .Case("pclmul", HasPCLMUL) .Case("pconfig", HasPCONFIG) diff --git a/lib/Basic/Targets/X86.h b/lib/Basic/Targets/X86.h index 588b6d3da1d68..cad869f712302 100644 --- a/lib/Basic/Targets/X86.h +++ b/lib/Basic/Targets/X86.h @@ -80,7 +80,6 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo { bool HasAVX512IFMA = false; bool HasAVX512VP2INTERSECT = false; bool HasSHA = false; - bool HasMPX = false; bool HasSHSTK = false; bool HasSGX = false; bool HasCX8 = false; @@ -320,8 +319,8 @@ public: } } - CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { - return MT == CCMT_Member ? CC_X86ThisCall : CC_C; + CallingConv getDefaultCallingConv() const override { + return CC_C; } bool hasSjLjLowering() const override { return true; } @@ -340,7 +339,8 @@ public: LongDoubleWidth = 96; LongDoubleAlign = 32; SuitableAlign = 128; - resetDataLayout("e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"); + resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-" + "f80:32-n8:16:32-S128"); SizeType = UnsignedInt; PtrDiffType = SignedInt; IntPtrType = SignedInt; @@ -440,7 +440,8 @@ public: UseSignedCharForObjCBool = false; SizeType = UnsignedLong; IntPtrType = SignedLong; - resetDataLayout("e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128"); + resetDataLayout("e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-" + "f80:128-n8:16:32-S128"); HasAlignMac68kSupport = true; } @@ -465,9 +466,10 @@ public: DoubleAlign = LongLongAlign = 64; bool IsWinCOFF = getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF(); - resetDataLayout(IsWinCOFF - ? "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" - : "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"); + resetDataLayout(IsWinCOFF ? "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:" + "64-i64:64-f80:32-n8:16:32-a:0:32-S32" + : "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:" + "64-i64:64-f80:32-n8:16:32-a:0:32-S32"); } }; @@ -515,7 +517,8 @@ public: : X86_32TargetInfo(Triple, Opts) { this->WCharType = TargetInfo::UnsignedShort; DoubleAlign = LongLongAlign = 64; - resetDataLayout("e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"); + resetDataLayout("e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:" + "32-n8:16:32-a:0:32-S32"); } void getTargetDefines(const LangOptions &Opts, @@ -552,7 +555,8 @@ public: : X86_32TargetInfo(Triple, Opts) { LongDoubleWidth = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); - resetDataLayout("e-m:e-p:32:32-i64:32-f64:32-f128:32-n8:16:32-a:0:32-S32"); + resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:32-f64:" + "32-f128:32-n8:16:32-a:0:32-S32"); WIntType = UnsignedInt; } @@ -611,10 +615,12 @@ public: RegParmMax = 6; // Pointers are 32-bit in x32. - resetDataLayout(IsX32 - ? "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128" - : IsWinCOFF ? "e-m:w-i64:64-f80:128-n8:16:32:64-S128" - : "e-m:e-i64:64-f80:128-n8:16:32:64-S128"); + resetDataLayout(IsX32 ? "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-" + "i64:64-f80:128-n8:16:32:64-S128" + : IsWinCOFF ? "e-m:w-p270:32:32-p271:32:32-p272:64:" + "64-i64:64-f80:128-n8:16:32:64-S128" + : "e-m:e-p270:32:32-p271:32:32-p272:64:" + "64-i64:64-f80:128-n8:16:32:64-S128"); // Use fpret only for long double. RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble); @@ -659,7 +665,7 @@ public: } } - CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { + CallingConv getDefaultCallingConv() const override { return CC_C; } @@ -804,7 +810,8 @@ public: llvm::Triple T = llvm::Triple(Triple); if (T.isiOS()) UseSignedCharForObjCBool = false; - resetDataLayout("e-m:o-i64:64-f80:128-n8:16:32:64-S128"); + resetDataLayout("e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:" + "16:32:64-S128"); } bool handleTargetFeatures(std::vector<std::string> &Features, diff --git a/lib/Basic/TokenKinds.cpp b/lib/Basic/TokenKinds.cpp index a71cd72517dee..d55e176c72c4c 100644 --- a/lib/Basic/TokenKinds.cpp +++ b/lib/Basic/TokenKinds.cpp @@ -45,3 +45,23 @@ const char *tok::getKeywordSpelling(TokenKind Kind) { } return nullptr; } + +bool tok::isAnnotation(TokenKind Kind) { + switch (Kind) { +#define ANNOTATION(X) case annot_ ## X: return true; +#include "clang/Basic/TokenKinds.def" + default: + break; + } + return false; +} + +bool tok::isPragmaAnnotation(TokenKind Kind) { + switch (Kind) { +#define PRAGMA_ANNOTATION(X) case annot_ ## X: return true; +#include "clang/Basic/TokenKinds.def" + default: + break; + } + return false; +} |