diff options
Diffstat (limited to 'clang/lib/Basic')
45 files changed, 1725 insertions, 982 deletions
diff --git a/clang/lib/Basic/Cuda.cpp b/clang/lib/Basic/Cuda.cpp index 709185707bd9..144113f2d2e7 100644 --- a/clang/lib/Basic/Cuda.cpp +++ b/clang/lib/Basic/Cuda.cpp @@ -64,6 +64,7 @@ struct CudaArchToStringMap { { CudaArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn" } CudaArchToStringMap arch_names[] = { // clang-format off + {CudaArch::UNUSED, "", ""}, SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi SM(30), SM(32), SM(35), SM(37), // Kepler SM(50), SM(52), SM(53), // Maxwell @@ -71,20 +72,34 @@ CudaArchToStringMap arch_names[] = { SM(70), SM(72), // Volta SM(75), // Turing SM(80), // Ampere - GFX(600), // tahiti - GFX(601), // pitcairn, verde, oland,hainan - GFX(700), // kaveri - GFX(701), // hawaii - GFX(702), // 290,290x,R390,R390x - GFX(703), // kabini mullins - GFX(704), // bonaire - GFX(801), // carrizo - GFX(802), // tonga,iceland - GFX(803), // fiji,polaris10 - GFX(810), // stoney - GFX(900), // vega, instinct - GFX(902), GFX(904), GFX(906), GFX(908), GFX(909), - GFX(1010), GFX(1011), GFX(1012), + GFX(600), // gfx600 + GFX(601), // gfx601 + GFX(602), // gfx602 + GFX(700), // gfx700 + GFX(701), // gfx701 + GFX(702), // gfx702 + GFX(703), // gfx703 + GFX(704), // gfx704 + GFX(705), // gfx705 + GFX(801), // gfx801 + GFX(802), // gfx802 + GFX(803), // gfx803 + GFX(805), // gfx805 + GFX(810), // gfx810 + GFX(900), // gfx900 + GFX(902), // gfx902 + GFX(904), // gfx903 + GFX(906), // gfx906 + GFX(908), // gfx908 + GFX(909), // gfx909 + GFX(90c), // gfx90c + GFX(1010), // gfx1010 + GFX(1011), // gfx1011 + GFX(1012), // gfx1012 + GFX(1030), // gfx1030 + GFX(1031), // gfx1031 + GFX(1032), // gfx1032 + GFX(1033), // gfx1033 // clang-format on }; #undef SM diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp index 661eabf9bc7c..d3b2122e9c59 100644 --- a/clang/lib/Basic/Diagnostic.cpp +++ b/clang/lib/Basic/Diagnostic.cpp @@ -40,8 +40,8 @@ using namespace clang; -const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, - DiagNullabilityKind nullability) { +const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, + DiagNullabilityKind nullability) { StringRef string; switch (nullability.first) { case NullabilityKind::NonNull: @@ -55,14 +55,20 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, case NullabilityKind::Unspecified: string = nullability.second ? "'null_unspecified'" : "'_Null_unspecified'"; break; + + case NullabilityKind::NullableResult: + assert(!nullability.second && + "_Nullable_result isn't supported as context-sensitive keyword"); + string = "_Nullable_result"; + break; } DB.AddString(string); return DB; } -const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, - llvm::Error &&E) { +const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, + llvm::Error &&E) { DB.AddString(toString(std::move(E))); return DB; } @@ -265,7 +271,8 @@ void DiagnosticsEngine::DiagStateMap::dump(SourceManager &SrcMgr, PrintedOuterHeading = true; llvm::errs() << "File " << &File << " <FileID " << ID.getHashValue() - << ">: " << SrcMgr.getBuffer(ID)->getBufferIdentifier(); + << ">: " << SrcMgr.getBufferOrFake(ID).getBufferIdentifier(); + if (F.second.Parent) { std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedIncludedLoc(ID); @@ -481,13 +488,15 @@ void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) { CurDiagLoc = storedDiag.getLocation(); CurDiagID = storedDiag.getID(); - NumDiagArgs = 0; + DiagStorage.NumDiagArgs = 0; - DiagRanges.clear(); - DiagRanges.append(storedDiag.range_begin(), storedDiag.range_end()); + DiagStorage.DiagRanges.clear(); + DiagStorage.DiagRanges.append(storedDiag.range_begin(), + storedDiag.range_end()); - DiagFixItHints.clear(); - DiagFixItHints.append(storedDiag.fixit_begin(), storedDiag.fixit_end()); + DiagStorage.FixItHints.clear(); + DiagStorage.FixItHints.append(storedDiag.fixit_begin(), + storedDiag.fixit_end()); assert(Client && "DiagnosticConsumer not set!"); Level DiagLevel = storedDiag.getLevel(); @@ -805,7 +814,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, /// QualTypeVals - Pass a vector of arrays so that QualType names can be /// compared to see if more information is needed to be printed. SmallVector<intptr_t, 2> QualTypeVals; - SmallVector<char, 64> Tree; + SmallString<64> Tree; for (unsigned i = 0, e = getNumArgs(); i < e; ++i) if (getArgKind(i) == DiagnosticsEngine::ak_qualtype) @@ -1140,13 +1149,13 @@ bool ForwardingDiagnosticConsumer::IncludeInDiagnosticCounts() const { return Target.IncludeInDiagnosticCounts(); } -PartialDiagnostic::StorageAllocator::StorageAllocator() { +PartialDiagnostic::DiagStorageAllocator::DiagStorageAllocator() { for (unsigned I = 0; I != NumCached; ++I) FreeList[I] = Cached + I; NumFreeListEntries = NumCached; } -PartialDiagnostic::StorageAllocator::~StorageAllocator() { +PartialDiagnostic::DiagStorageAllocator::~DiagStorageAllocator() { // Don't assert if we are in a CrashRecovery context, as this invariant may // be invalidated during a crash. assert((NumFreeListEntries == NumCached || diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index 8c7e63e06301..06a8e2ed5ebd 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -26,6 +26,78 @@ using namespace clang; namespace { +struct StaticDiagInfoRec; + +// Store the descriptions in a separate table to avoid pointers that need to +// be relocated, and also decrease the amount of data needed on 64-bit +// platforms. See "How To Write Shared Libraries" by Ulrich Drepper. +struct StaticDiagInfoDescriptionStringTable { +#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, DEFERRABLE, CATEGORY) \ + char ENUM##_desc[sizeof(DESC)]; + // clang-format off +#include "clang/Basic/DiagnosticCommonKinds.inc" +#include "clang/Basic/DiagnosticDriverKinds.inc" +#include "clang/Basic/DiagnosticFrontendKinds.inc" +#include "clang/Basic/DiagnosticSerializationKinds.inc" +#include "clang/Basic/DiagnosticLexKinds.inc" +#include "clang/Basic/DiagnosticParseKinds.inc" +#include "clang/Basic/DiagnosticASTKinds.inc" +#include "clang/Basic/DiagnosticCommentKinds.inc" +#include "clang/Basic/DiagnosticCrossTUKinds.inc" +#include "clang/Basic/DiagnosticSemaKinds.inc" +#include "clang/Basic/DiagnosticAnalysisKinds.inc" +#include "clang/Basic/DiagnosticRefactoringKinds.inc" + // clang-format on +#undef DIAG +}; + +const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions = { +#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, DEFERRABLE, CATEGORY) \ + DESC, +// clang-format off +#include "clang/Basic/DiagnosticCommonKinds.inc" +#include "clang/Basic/DiagnosticDriverKinds.inc" +#include "clang/Basic/DiagnosticFrontendKinds.inc" +#include "clang/Basic/DiagnosticSerializationKinds.inc" +#include "clang/Basic/DiagnosticLexKinds.inc" +#include "clang/Basic/DiagnosticParseKinds.inc" +#include "clang/Basic/DiagnosticASTKinds.inc" +#include "clang/Basic/DiagnosticCommentKinds.inc" +#include "clang/Basic/DiagnosticCrossTUKinds.inc" +#include "clang/Basic/DiagnosticSemaKinds.inc" +#include "clang/Basic/DiagnosticAnalysisKinds.inc" +#include "clang/Basic/DiagnosticRefactoringKinds.inc" + // clang-format on +#undef DIAG +}; + +extern const StaticDiagInfoRec StaticDiagInfo[]; + +// Stored separately from StaticDiagInfoRec to pack better. Otherwise, +// StaticDiagInfoRec would have extra padding on 64-bit platforms. +const uint32_t StaticDiagInfoDescriptionOffsets[] = { +#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, DEFERRABLE, CATEGORY) \ + offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc), +// clang-format off +#include "clang/Basic/DiagnosticCommonKinds.inc" +#include "clang/Basic/DiagnosticDriverKinds.inc" +#include "clang/Basic/DiagnosticFrontendKinds.inc" +#include "clang/Basic/DiagnosticSerializationKinds.inc" +#include "clang/Basic/DiagnosticLexKinds.inc" +#include "clang/Basic/DiagnosticParseKinds.inc" +#include "clang/Basic/DiagnosticASTKinds.inc" +#include "clang/Basic/DiagnosticCommentKinds.inc" +#include "clang/Basic/DiagnosticCrossTUKinds.inc" +#include "clang/Basic/DiagnosticSemaKinds.inc" +#include "clang/Basic/DiagnosticAnalysisKinds.inc" +#include "clang/Basic/DiagnosticRefactoringKinds.inc" + // clang-format on +#undef DIAG +}; + // Diagnostic classes. enum { CLASS_NOTE = 0x01, @@ -42,19 +114,22 @@ struct StaticDiagInfoRec { unsigned SFINAE : 2; unsigned WarnNoWerror : 1; unsigned WarnShowInSystemHeader : 1; + unsigned Deferrable : 1; unsigned Category : 6; uint16_t OptionGroupIndex; uint16_t DescriptionLen; - const char *DescriptionStr; unsigned getOptionGroupIndex() const { return OptionGroupIndex; } StringRef getDescription() const { - return StringRef(DescriptionStr, DescriptionLen); + size_t MyIndex = this - &StaticDiagInfo[0]; + uint32_t StringOffset = StaticDiagInfoDescriptionOffsets[MyIndex]; + const char* Table = reinterpret_cast<const char*>(&StaticDiagInfoDescriptions); + return StringRef(&Table[StringOffset], DescriptionLen); } diag::Flavor getFlavor() const { @@ -92,16 +167,21 @@ VALIDATE_DIAG_SIZE(REFACTORING) #undef VALIDATE_DIAG_SIZE #undef STRINGIFY_NAME -} // namespace anonymous - -static const StaticDiagInfoRec StaticDiagInfo[] = { +const StaticDiagInfoRec StaticDiagInfo[] = { #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ - SHOWINSYSHEADER, CATEGORY) \ + SHOWINSYSHEADER, DEFERRABLE, CATEGORY) \ { \ - diag::ENUM, DEFAULT_SEVERITY, CLASS, DiagnosticIDs::SFINAE, NOWERROR, \ - SHOWINSYSHEADER, CATEGORY, GROUP, STR_SIZE(DESC, uint16_t), DESC \ - } \ - , + diag::ENUM, \ + DEFAULT_SEVERITY, \ + CLASS, \ + DiagnosticIDs::SFINAE, \ + NOWERROR, \ + SHOWINSYSHEADER, \ + DEFERRABLE, \ + CATEGORY, \ + GROUP, \ + STR_SIZE(DESC, uint16_t)}, +// clang-format off #include "clang/Basic/DiagnosticCommonKinds.inc" #include "clang/Basic/DiagnosticDriverKinds.inc" #include "clang/Basic/DiagnosticFrontendKinds.inc" @@ -114,9 +194,12 @@ static const StaticDiagInfoRec StaticDiagInfo[] = { #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" #include "clang/Basic/DiagnosticRefactoringKinds.inc" + // clang-format on #undef DIAG }; +} // namespace + static const unsigned StaticDiagInfoSize = llvm::array_lengthof(StaticDiagInfo); /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, @@ -253,6 +336,12 @@ DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { return SFINAE_Report; } +bool DiagnosticIDs::isDeferrable(unsigned DiagID) { + if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + return Info->Deferrable; + return false; +} + /// getBuiltinDiagClass - Return the class field of the diagnostic. /// static unsigned getBuiltinDiagClass(unsigned DiagID) { diff --git a/clang/lib/Basic/FileEntry.cpp b/clang/lib/Basic/FileEntry.cpp new file mode 100644 index 000000000000..5ee9bef9523e --- /dev/null +++ b/clang/lib/Basic/FileEntry.cpp @@ -0,0 +1,24 @@ +//===- FileEntry.cpp - File references --------------------------*- C++ -*-===// +// +// 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 implementation for clang::FileEntry and clang::FileEntryRef. +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/FileEntry.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/VirtualFileSystem.h" + +using namespace clang; + +FileEntry::FileEntry() : UniqueID(0, 0) {} + +FileEntry::~FileEntry() = default; + +void FileEntry::closeFile() const { File.reset(); } diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index e92e9d5911c0..6e9d5d7fb422 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -69,21 +69,22 @@ 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 llvm::ErrorOr<const DirectoryEntry *> +static llvm::Expected<DirectoryEntryRef> getDirectoryFromFile(FileManager &FileMgr, StringRef Filename, bool CacheFailure) { if (Filename.empty()) - return std::errc::no_such_file_or_directory; + return llvm::errorCodeToError( + make_error_code(std::errc::no_such_file_or_directory)); if (llvm::sys::path::is_separator(Filename[Filename.size() - 1])) - return std::errc::is_a_directory; + return llvm::errorCodeToError(make_error_code(std::errc::is_a_directory)); StringRef DirName = llvm::sys::path::parent_path(Filename); // Use the current directory if file has no path component. if (DirName.empty()) DirName = "."; - return FileMgr.getDirectory(DirName, CacheFailure); + return FileMgr.getDirectoryRef(DirName, CacheFailure); } /// Add all ancestors of the given path (pointing to either a file or @@ -141,7 +142,7 @@ FileManager::getDirectoryRef(StringRef DirName, bool CacheFailure) { SeenDirEntries.insert({DirName, std::errc::no_such_file_or_directory}); if (!SeenDirInsertResult.second) { if (SeenDirInsertResult.first->second) - return DirectoryEntryRef(&*SeenDirInsertResult.first); + return DirectoryEntryRef(*SeenDirInsertResult.first); return llvm::errorCodeToError(SeenDirInsertResult.first->second.getError()); } @@ -180,7 +181,7 @@ FileManager::getDirectoryRef(StringRef DirName, bool CacheFailure) { UDE.Name = InterndDirName; } - return DirectoryEntryRef(&NamedDirEnt); + return DirectoryEntryRef(NamedDirEnt); } llvm::ErrorOr<const DirectoryEntry *> @@ -212,11 +213,11 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { 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); + FileEntryRef::MapValue Value = *SeenFileInsertResult.first->second; + if (LLVM_LIKELY(Value.V.is<FileEntry *>())) + return FileEntryRef(*SeenFileInsertResult.first); + return FileEntryRef(*reinterpret_cast<const FileEntryRef::MapEntry *>( + Value.V.get<const void *>())); } // We've not seen this before. Fill it in. @@ -235,14 +236,15 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { // without a 'sys' subdir will get a cached failure result. auto DirInfoOrErr = getDirectoryFromFile(*this, Filename, CacheFailure); if (!DirInfoOrErr) { // Directory doesn't exist, file can't exist. + std::error_code Err = errorToErrorCode(DirInfoOrErr.takeError()); if (CacheFailure) - NamedFileEnt->second = DirInfoOrErr.getError(); + NamedFileEnt->second = Err; else SeenFileEntries.erase(Filename); - return llvm::errorCodeToError(DirInfoOrErr.getError()); + return llvm::errorCodeToError(Err); } - const DirectoryEntry *DirInfo = *DirInfoOrErr; + DirectoryEntryRef DirInfo = *DirInfoOrErr; // FIXME: Use the directory info to prune this, before doing the stat syscall. // FIXME: This will reduce the # syscalls. @@ -268,26 +270,30 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { // This occurs when one dir is symlinked to another, for example. FileEntry &UFE = UniqueRealFiles[Status.getUniqueID()]; - NamedFileEnt->second = &UFE; - - // If the name returned by getStatValue is different than Filename, re-intern - // the name. - if (Status.getName() != Filename) { - auto &NewNamedFileEnt = - *SeenFileEntries.insert({Status.getName(), &UFE}).first; - assert((*NewNamedFileEnt.second).get<FileEntry *>() == &UFE && + if (Status.getName() == Filename) { + // The name matches. Set the FileEntry. + NamedFileEnt->second = FileEntryRef::MapValue(UFE, DirInfo); + } else { + // Name mismatch. We need a redirect. First grab the actual entry we want + // to return. + auto &Redirection = + *SeenFileEntries + .insert({Status.getName(), FileEntryRef::MapValue(UFE, DirInfo)}) + .first; + assert(Redirection.second->V.is<FileEntry *>() && + "filename redirected to a non-canonical filename?"); + assert(Redirection.second->V.get<FileEntry *>() == &UFE && "filename from getStatValue() refers to wrong file"); - 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); - auto SeenFileInsertResultIt = SeenFileEntries.find(Filename); - assert(SeenFileInsertResultIt != SeenFileEntries.end() && - "unexpected SeenFileEntries cache miss"); - SeenFileInsertResultIt->second = Redirect; - NamedFileEnt = &*SeenFileInsertResultIt; + + // Cache the redirection in the previously-inserted entry, still available + // in the tentative return value. + NamedFileEnt->second = FileEntryRef::MapValue(Redirection); + + // Fix the tentative return value. + NamedFileEnt = &Redirection; } + FileEntryRef ReturnedRef(*NamedFileEnt); 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 @@ -296,26 +302,26 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { // module's structure when its headers/module map are mapped in the VFS. // We should remove this as soon as we can properly support a file having // multiple names. - if (DirInfo != UFE.Dir && Status.IsVFSMapped) - UFE.Dir = DirInfo; + if (&DirInfo.getDirEntry() != UFE.Dir && Status.IsVFSMapped) + UFE.Dir = &DirInfo.getDirEntry(); - // 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 + // Always update LastRef to the last name by which a file was accessed. + // FIXME: Neither this nor always using the first reference 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. - // FIXME: The Name should be removed from FileEntry once all clients - // adopt FileEntryRef. - UFE.Name = InterndFileName; + // FIXME: LastRef should be removed from FileEntry once all clients adopt + // FileEntryRef. + UFE.LastRef = ReturnedRef; - return FileEntryRef(InterndFileName, UFE); + return ReturnedRef; } // Otherwise, we don't have this file yet, add it. - UFE.Name = InterndFileName; + UFE.LastRef = ReturnedRef; UFE.Size = Status.getSize(); UFE.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime()); - UFE.Dir = DirInfo; + UFE.Dir = &DirInfo.getDirEntry(); UFE.UID = NextFileUID++; UFE.UniqueID = Status.getUniqueID(); UFE.IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file; @@ -329,24 +335,46 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { // We should still fill the path even if we aren't opening the file. fillRealPathName(&UFE, InterndFileName); } - return FileEntryRef(InterndFileName, UFE); + return ReturnedRef; +} + +llvm::Expected<FileEntryRef> FileManager::getSTDIN() { + // Only read stdin once. + if (STDIN) + return *STDIN; + + std::unique_ptr<llvm::MemoryBuffer> Content; + if (auto ContentOrError = llvm::MemoryBuffer::getSTDIN()) + Content = std::move(*ContentOrError); + else + return llvm::errorCodeToError(ContentOrError.getError()); + + STDIN = getVirtualFileRef(Content->getBufferIdentifier(), + Content->getBufferSize(), 0); + FileEntry &FE = const_cast<FileEntry &>(STDIN->getFileEntry()); + FE.Content = std::move(Content); + FE.IsNamedPipe = true; + return *STDIN; } -const FileEntry * -FileManager::getVirtualFile(StringRef Filename, off_t Size, - time_t ModificationTime) { +const FileEntry *FileManager::getVirtualFile(StringRef Filename, off_t Size, + time_t ModificationTime) { + return &getVirtualFileRef(Filename, Size, ModificationTime).getFileEntry(); +} + +FileEntryRef FileManager::getVirtualFileRef(StringRef Filename, off_t Size, + time_t ModificationTime) { ++NumFileLookups; // See if there is already an entry in the map for an existing file. 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); + FileEntryRef::MapValue Value = *NamedFileEnt.second; + if (LLVM_LIKELY(Value.V.is<FileEntry *>())) + return FileEntryRef(NamedFileEnt); + return FileEntryRef(*reinterpret_cast<const FileEntryRef::MapEntry *>( + Value.V.get<const void *>())); } // We've not seen this before, or the file is cached as non-existent. @@ -357,7 +385,8 @@ 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. - auto DirInfo = getDirectoryFromFile(*this, Filename, /*CacheFailure=*/true); + auto DirInfo = expectedToOptional( + getDirectoryFromFile(*this, Filename, /*CacheFailure=*/true)); assert(DirInfo && "The directory of a virtual file should already be in the cache."); @@ -372,7 +401,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, Status.getUser(), Status.getGroup(), Size, Status.getType(), Status.getPermissions()); - NamedFileEnt.second = UFE; + NamedFileEnt.second = FileEntryRef::MapValue(*UFE, *DirInfo); // 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 @@ -381,8 +410,11 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, UFE->closeFile(); // If we already have an entry with this inode, return it. + // + // FIXME: Surely this should add a reference by the new name, and return + // it instead... if (UFE->isValid()) - return UFE; + return FileEntryRef(NamedFileEnt); UFE->UniqueID = Status.getUniqueID(); UFE->IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file; @@ -390,17 +422,17 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, } else { VirtualFileEntries.push_back(std::make_unique<FileEntry>()); UFE = VirtualFileEntries.back().get(); - NamedFileEnt.second = UFE; + NamedFileEnt.second = FileEntryRef::MapValue(*UFE, *DirInfo); } - UFE->Name = InterndFileName; + UFE->LastRef = FileEntryRef(NamedFileEnt); UFE->Size = Size; UFE->ModTime = ModificationTime; - UFE->Dir = *DirInfo; + UFE->Dir = &DirInfo->getDirEntry(); UFE->UID = NextFileUID++; UFE->IsValid = true; UFE->File.reset(); - return UFE; + return FileEntryRef(NamedFileEnt); } llvm::Optional<FileEntryRef> FileManager::getBypassFile(FileEntryRef VF) { @@ -409,17 +441,30 @@ llvm::Optional<FileEntryRef> FileManager::getBypassFile(FileEntryRef VF) { if (getStatValue(VF.getName(), Status, /*isFile=*/true, /*F=*/nullptr)) return None; - // Fill it in from the stat. + if (!SeenBypassFileEntries) + SeenBypassFileEntries = std::make_unique< + llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>>>(); + + // If we've already bypassed just use the existing one. + auto Insertion = SeenBypassFileEntries->insert( + {VF.getName(), std::errc::no_such_file_or_directory}); + if (!Insertion.second) + return FileEntryRef(*Insertion.first); + + // Fill in the new entry from the stat. BypassFileEntries.push_back(std::make_unique<FileEntry>()); const FileEntry &VFE = VF.getFileEntry(); FileEntry &BFE = *BypassFileEntries.back(); - BFE.Name = VFE.getName(); + Insertion.first->second = FileEntryRef::MapValue(BFE, VF.getDir()); + BFE.LastRef = FileEntryRef(*Insertion.first); 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); + + // Save the entry in the bypass table and return. + return FileEntryRef(*Insertion.first); } bool FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const { @@ -460,10 +505,14 @@ void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile, bool RequiresNullTerminator) { + // If the content is living on the file entry, return a reference to it. + if (Entry->Content) + return llvm::MemoryBuffer::getMemBuffer(Entry->Content->getMemBufferRef()); + 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. - if (isVolatile) + if (isVolatile || Entry->isNamedPipe()) FileSize = -1; StringRef Filename = Entry->getName(); @@ -534,13 +583,13 @@ void FileManager::GetUniqueIDMapping( UIDToFiles.resize(NextFileUID); // Map file entries - for (llvm::StringMap<llvm::ErrorOr<SeenFileEntryOrRedirect>, + for (llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>, llvm::BumpPtrAllocator>::const_iterator FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end(); FE != FEEnd; ++FE) - if (llvm::ErrorOr<SeenFileEntryOrRedirect> Entry = FE->getValue()) { - if (const auto *FE = (*Entry).dyn_cast<FileEntry *>()) + if (llvm::ErrorOr<FileEntryRef::MapValue> Entry = FE->getValue()) { + if (const auto *FE = Entry->V.dyn_cast<FileEntry *>()) UIDToFiles[FE->getUID()] = FE; } diff --git a/clang/lib/Basic/FixedPoint.cpp b/clang/lib/Basic/FixedPoint.cpp deleted file mode 100644 index ed8b92c98fdb..000000000000 --- a/clang/lib/Basic/FixedPoint.cpp +++ /dev/null @@ -1,394 +0,0 @@ -//===- FixedPoint.cpp - Fixed point constant handling -----------*- C++ -*-===// -// -// 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 the implementation for the fixed point number interface. -// -//===----------------------------------------------------------------------===// - -#include "clang/Basic/FixedPoint.h" - -namespace clang { - -APFixedPoint APFixedPoint::convert(const FixedPointSemantics &DstSema, - bool *Overflow) const { - llvm::APSInt NewVal = Val; - unsigned DstWidth = DstSema.getWidth(); - unsigned DstScale = DstSema.getScale(); - bool Upscaling = DstScale > getScale(); - if (Overflow) - *Overflow = false; - - if (Upscaling) { - NewVal = NewVal.extend(NewVal.getBitWidth() + DstScale - getScale()); - NewVal <<= (DstScale - getScale()); - } else { - NewVal >>= (getScale() - DstScale); - } - - auto Mask = llvm::APInt::getBitsSetFrom( - NewVal.getBitWidth(), - std::min(DstScale + DstSema.getIntegralBits(), NewVal.getBitWidth())); - llvm::APInt Masked(NewVal & Mask); - - // Change in the bits above the sign - if (!(Masked == Mask || Masked == 0)) { - // Found overflow in the bits above the sign - if (DstSema.isSaturated()) - NewVal = NewVal.isNegative() ? Mask : ~Mask; - else if (Overflow) - *Overflow = true; - } - - // If the dst semantics are unsigned, but our value is signed and negative, we - // clamp to zero. - if (!DstSema.isSigned() && NewVal.isSigned() && NewVal.isNegative()) { - // Found negative overflow for unsigned result - if (DstSema.isSaturated()) - NewVal = 0; - else if (Overflow) - *Overflow = true; - } - - NewVal = NewVal.extOrTrunc(DstWidth); - NewVal.setIsSigned(DstSema.isSigned()); - return APFixedPoint(NewVal, DstSema); -} - -int APFixedPoint::compare(const APFixedPoint &Other) const { - llvm::APSInt ThisVal = getValue(); - llvm::APSInt OtherVal = Other.getValue(); - bool ThisSigned = Val.isSigned(); - bool OtherSigned = OtherVal.isSigned(); - unsigned OtherScale = Other.getScale(); - unsigned OtherWidth = OtherVal.getBitWidth(); - - unsigned CommonWidth = std::max(Val.getBitWidth(), OtherWidth); - - // Prevent overflow in the event the widths are the same but the scales differ - CommonWidth += getScale() >= OtherScale ? getScale() - OtherScale - : OtherScale - getScale(); - - ThisVal = ThisVal.extOrTrunc(CommonWidth); - OtherVal = OtherVal.extOrTrunc(CommonWidth); - - unsigned CommonScale = std::max(getScale(), OtherScale); - ThisVal = ThisVal.shl(CommonScale - getScale()); - OtherVal = OtherVal.shl(CommonScale - OtherScale); - - if (ThisSigned && OtherSigned) { - if (ThisVal.sgt(OtherVal)) - return 1; - else if (ThisVal.slt(OtherVal)) - return -1; - } else if (!ThisSigned && !OtherSigned) { - if (ThisVal.ugt(OtherVal)) - return 1; - else if (ThisVal.ult(OtherVal)) - return -1; - } else if (ThisSigned && !OtherSigned) { - if (ThisVal.isSignBitSet()) - return -1; - else if (ThisVal.ugt(OtherVal)) - return 1; - else if (ThisVal.ult(OtherVal)) - return -1; - } else { - // !ThisSigned && OtherSigned - if (OtherVal.isSignBitSet()) - return 1; - else if (ThisVal.ugt(OtherVal)) - return 1; - else if (ThisVal.ult(OtherVal)) - return -1; - } - - return 0; -} - -APFixedPoint APFixedPoint::getMax(const FixedPointSemantics &Sema) { - bool IsUnsigned = !Sema.isSigned(); - auto Val = llvm::APSInt::getMaxValue(Sema.getWidth(), IsUnsigned); - if (IsUnsigned && Sema.hasUnsignedPadding()) - Val = Val.lshr(1); - return APFixedPoint(Val, Sema); -} - -APFixedPoint APFixedPoint::getMin(const FixedPointSemantics &Sema) { - auto Val = llvm::APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned()); - return APFixedPoint(Val, Sema); -} - -FixedPointSemantics FixedPointSemantics::getCommonSemantics( - const FixedPointSemantics &Other) const { - unsigned CommonScale = std::max(getScale(), Other.getScale()); - unsigned CommonWidth = - std::max(getIntegralBits(), Other.getIntegralBits()) + CommonScale; - - bool ResultIsSigned = isSigned() || Other.isSigned(); - bool ResultIsSaturated = isSaturated() || Other.isSaturated(); - bool ResultHasUnsignedPadding = false; - if (!ResultIsSigned) { - // Both are unsigned. - ResultHasUnsignedPadding = hasUnsignedPadding() && - Other.hasUnsignedPadding() && !ResultIsSaturated; - } - - // If the result is signed, add an extra bit for the sign. Otherwise, if it is - // unsigned and has unsigned padding, we only need to add the extra padding - // bit back if we are not saturating. - if (ResultIsSigned || ResultHasUnsignedPadding) - CommonWidth++; - - return FixedPointSemantics(CommonWidth, CommonScale, ResultIsSigned, - ResultIsSaturated, ResultHasUnsignedPadding); -} - -APFixedPoint APFixedPoint::add(const APFixedPoint &Other, - bool *Overflow) const { - auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics()); - APFixedPoint ConvertedThis = convert(CommonFXSema); - APFixedPoint ConvertedOther = Other.convert(CommonFXSema); - llvm::APSInt ThisVal = ConvertedThis.getValue(); - llvm::APSInt OtherVal = ConvertedOther.getValue(); - bool Overflowed = false; - - llvm::APSInt Result; - if (CommonFXSema.isSaturated()) { - Result = CommonFXSema.isSigned() ? ThisVal.sadd_sat(OtherVal) - : ThisVal.uadd_sat(OtherVal); - } else { - Result = ThisVal.isSigned() ? ThisVal.sadd_ov(OtherVal, Overflowed) - : ThisVal.uadd_ov(OtherVal, Overflowed); - } - - if (Overflow) - *Overflow = Overflowed; - - return APFixedPoint(Result, CommonFXSema); -} - -APFixedPoint APFixedPoint::sub(const APFixedPoint &Other, - bool *Overflow) const { - auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics()); - APFixedPoint ConvertedThis = convert(CommonFXSema); - APFixedPoint ConvertedOther = Other.convert(CommonFXSema); - llvm::APSInt ThisVal = ConvertedThis.getValue(); - llvm::APSInt OtherVal = ConvertedOther.getValue(); - bool Overflowed = false; - - llvm::APSInt Result; - if (CommonFXSema.isSaturated()) { - Result = CommonFXSema.isSigned() ? ThisVal.ssub_sat(OtherVal) - : ThisVal.usub_sat(OtherVal); - } else { - Result = ThisVal.isSigned() ? ThisVal.ssub_ov(OtherVal, Overflowed) - : ThisVal.usub_ov(OtherVal, Overflowed); - } - - if (Overflow) - *Overflow = Overflowed; - - return APFixedPoint(Result, CommonFXSema); -} - -APFixedPoint APFixedPoint::mul(const APFixedPoint &Other, - bool *Overflow) const { - auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics()); - APFixedPoint ConvertedThis = convert(CommonFXSema); - APFixedPoint ConvertedOther = Other.convert(CommonFXSema); - llvm::APSInt ThisVal = ConvertedThis.getValue(); - llvm::APSInt OtherVal = ConvertedOther.getValue(); - bool Overflowed = false; - - // Widen the LHS and RHS so we can perform a full multiplication. - unsigned Wide = CommonFXSema.getWidth() * 2; - if (CommonFXSema.isSigned()) { - ThisVal = ThisVal.sextOrSelf(Wide); - OtherVal = OtherVal.sextOrSelf(Wide); - } else { - ThisVal = ThisVal.zextOrSelf(Wide); - OtherVal = OtherVal.zextOrSelf(Wide); - } - - // Perform the full multiplication and downscale to get the same scale. - // - // Note that the right shifts here perform an implicit downwards rounding. - // This rounding could discard bits that would technically place the result - // outside the representable range. We interpret the spec as allowing us to - // perform the rounding step first, avoiding the overflow case that would - // arise. - llvm::APSInt Result; - if (CommonFXSema.isSigned()) - Result = ThisVal.smul_ov(OtherVal, Overflowed) - .ashr(CommonFXSema.getScale()); - else - Result = ThisVal.umul_ov(OtherVal, Overflowed) - .lshr(CommonFXSema.getScale()); - assert(!Overflowed && "Full multiplication cannot overflow!"); - Result.setIsSigned(CommonFXSema.isSigned()); - - // If our result lies outside of the representative range of the common - // semantic, we either have overflow or saturation. - llvm::APSInt Max = APFixedPoint::getMax(CommonFXSema).getValue() - .extOrTrunc(Wide); - llvm::APSInt Min = APFixedPoint::getMin(CommonFXSema).getValue() - .extOrTrunc(Wide); - if (CommonFXSema.isSaturated()) { - if (Result < Min) - Result = Min; - else if (Result > Max) - Result = Max; - } else - Overflowed = Result < Min || Result > Max; - - if (Overflow) - *Overflow = Overflowed; - - return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()), - CommonFXSema); -} - -APFixedPoint APFixedPoint::div(const APFixedPoint &Other, - bool *Overflow) const { - auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics()); - APFixedPoint ConvertedThis = convert(CommonFXSema); - APFixedPoint ConvertedOther = Other.convert(CommonFXSema); - llvm::APSInt ThisVal = ConvertedThis.getValue(); - llvm::APSInt OtherVal = ConvertedOther.getValue(); - bool Overflowed = false; - - // Widen the LHS and RHS so we can perform a full division. - unsigned Wide = CommonFXSema.getWidth() * 2; - if (CommonFXSema.isSigned()) { - ThisVal = ThisVal.sextOrSelf(Wide); - OtherVal = OtherVal.sextOrSelf(Wide); - } else { - ThisVal = ThisVal.zextOrSelf(Wide); - OtherVal = OtherVal.zextOrSelf(Wide); - } - - // Upscale to compensate for the loss of precision from division, and - // perform the full division. - ThisVal = ThisVal.shl(CommonFXSema.getScale()); - llvm::APSInt Result; - if (CommonFXSema.isSigned()) { - llvm::APInt Rem; - llvm::APInt::sdivrem(ThisVal, OtherVal, Result, Rem); - // If the quotient is negative and the remainder is nonzero, round - // towards negative infinity by subtracting epsilon from the result. - if (ThisVal.isNegative() != OtherVal.isNegative() && !Rem.isNullValue()) - Result = Result - 1; - } else - Result = ThisVal.udiv(OtherVal); - Result.setIsSigned(CommonFXSema.isSigned()); - - // If our result lies outside of the representative range of the common - // semantic, we either have overflow or saturation. - llvm::APSInt Max = APFixedPoint::getMax(CommonFXSema).getValue() - .extOrTrunc(Wide); - llvm::APSInt Min = APFixedPoint::getMin(CommonFXSema).getValue() - .extOrTrunc(Wide); - if (CommonFXSema.isSaturated()) { - if (Result < Min) - Result = Min; - else if (Result > Max) - Result = Max; - } else - Overflowed = Result < Min || Result > Max; - - if (Overflow) - *Overflow = Overflowed; - - return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()), - CommonFXSema); -} - -void APFixedPoint::toString(llvm::SmallVectorImpl<char> &Str) const { - llvm::APSInt Val = getValue(); - unsigned Scale = getScale(); - - if (Val.isSigned() && Val.isNegative() && Val != -Val) { - Val = -Val; - Str.push_back('-'); - } - - llvm::APSInt IntPart = Val >> Scale; - - // Add 4 digits to hold the value after multiplying 10 (the radix) - unsigned Width = Val.getBitWidth() + 4; - llvm::APInt FractPart = Val.zextOrTrunc(Scale).zext(Width); - llvm::APInt FractPartMask = llvm::APInt::getAllOnesValue(Scale).zext(Width); - llvm::APInt RadixInt = llvm::APInt(Width, 10); - - IntPart.toString(Str, /*Radix=*/10); - Str.push_back('.'); - do { - (FractPart * RadixInt) - .lshr(Scale) - .toString(Str, /*Radix=*/10, Val.isSigned()); - FractPart = (FractPart * RadixInt) & FractPartMask; - } while (FractPart != 0); -} - -APFixedPoint APFixedPoint::negate(bool *Overflow) const { - if (!isSaturated()) { - if (Overflow) - *Overflow = - (!isSigned() && Val != 0) || (isSigned() && Val.isMinSignedValue()); - return APFixedPoint(-Val, Sema); - } - - // We never overflow for saturation - if (Overflow) - *Overflow = false; - - if (isSigned()) - return Val.isMinSignedValue() ? getMax(Sema) : APFixedPoint(-Val, Sema); - else - return APFixedPoint(Sema); -} - -llvm::APSInt APFixedPoint::convertToInt(unsigned DstWidth, bool DstSign, - bool *Overflow) const { - llvm::APSInt Result = getIntPart(); - unsigned SrcWidth = getWidth(); - - llvm::APSInt DstMin = llvm::APSInt::getMinValue(DstWidth, !DstSign); - llvm::APSInt DstMax = llvm::APSInt::getMaxValue(DstWidth, !DstSign); - - if (SrcWidth < DstWidth) { - Result = Result.extend(DstWidth); - } else if (SrcWidth > DstWidth) { - DstMin = DstMin.extend(SrcWidth); - DstMax = DstMax.extend(SrcWidth); - } - - if (Overflow) { - if (Result.isSigned() && !DstSign) { - *Overflow = Result.isNegative() || Result.ugt(DstMax); - } else if (Result.isUnsigned() && DstSign) { - *Overflow = Result.ugt(DstMax); - } else { - *Overflow = Result < DstMin || Result > DstMax; - } - } - - Result.setIsSigned(DstSign); - return Result.extOrTrunc(DstWidth); -} - -APFixedPoint APFixedPoint::getFromIntValue(const llvm::APSInt &Value, - const FixedPointSemantics &DstFXSema, - bool *Overflow) { - FixedPointSemantics IntFXSema = FixedPointSemantics::GetIntegerSemantics( - Value.getBitWidth(), Value.isSigned()); - return APFixedPoint(Value, IntFXSema).convert(DstFXSema, Overflow); -} - -} // namespace clang diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp index 36b26d9b7c68..51c6e02e2e2e 100644 --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -714,6 +714,11 @@ StringRef clang::getNullabilitySpelling(NullabilityKind kind, case NullabilityKind::Nullable: return isContextSensitive ? "nullable" : "_Nullable"; + case NullabilityKind::NullableResult: + assert(!isContextSensitive && + "_Nullable_result isn't supported as context-sensitive keyword"); + return "_Nullable_result"; + case NullabilityKind::Unspecified: return isContextSensitive ? "null_unspecified" : "_Null_unspecified"; } diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp index c08670c87fb6..ed275ade4001 100644 --- a/clang/lib/Basic/LangOptions.cpp +++ b/clang/lib/Basic/LangOptions.cpp @@ -14,7 +14,7 @@ using namespace clang; -LangOptions::LangOptions() { +LangOptions::LangOptions() : LangStd(LangStandard::lang_unspecified) { #define LANGOPT(Name, Bits, Default, Description) Name = Default; #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default); #include "clang/Basic/LangOptions.def" diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index b3daaa3a4442..2dd53b05d442 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -44,7 +44,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, InferSubmodules(false), InferExplicitSubmodules(false), InferExportWildcard(false), ConfigMacrosExhaustive(false), NoUndeclaredIncludes(false), ModuleMapIsPrivate(false), - HasUmbrellaDir(false), NameVisibility(Hidden) { + NameVisibility(Hidden) { if (Parent) { IsAvailable = Parent->isAvailable(); IsUnimportable = Parent->isUnimportable(); @@ -75,7 +75,7 @@ static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) { return true; auto CmpPlatformEnv = [](StringRef LHS, StringRef RHS) { - auto Pos = LHS.find("-"); + auto Pos = LHS.find('-'); if (Pos == StringRef::npos) return false; SmallString<128> NewLHS = LHS.slice(0, Pos); @@ -173,14 +173,10 @@ bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, } bool Module::isSubModuleOf(const Module *Other) const { - const Module *This = this; - do { - if (This == Other) + for (auto *Parent = this; Parent; Parent = Parent->Parent) { + if (Parent == Other) return true; - - This = This->Parent; - } while (This); - + } return false; } @@ -251,7 +247,10 @@ Module::DirectoryName Module::getUmbrellaDir() const { if (Header U = getUmbrellaHeader()) return {"", U.Entry->getDir()}; - return {UmbrellaAsWritten, static_cast<const DirectoryEntry *>(Umbrella)}; + if (auto *ME = Umbrella.dyn_cast<const DirectoryEntryRef::MapEntry *>()) + return {UmbrellaAsWritten, DirectoryEntryRef(*ME)}; + + return {"", None}; } void Module::addTopHeader(const FileEntry *File) { @@ -675,7 +674,7 @@ ASTSourceDescriptor::ASTSourceDescriptor(Module &M) : Signature(M.Signature), ClangModule(&M) { if (M.Directory) Path = M.Directory->getName(); - if (auto *File = M.getASTFile()) + if (auto File = M.getASTFile()) ASTFile = File->getName(); } diff --git a/clang/lib/Basic/OpenCLOptions.cpp b/clang/lib/Basic/OpenCLOptions.cpp new file mode 100644 index 000000000000..266acc5fe477 --- /dev/null +++ b/clang/lib/Basic/OpenCLOptions.cpp @@ -0,0 +1,106 @@ +//===--- OpenCLOptions.cpp---------------------------------------*- C++ -*-===// +// +// 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/OpenCLOptions.h" + +namespace clang { + +bool OpenCLOptions::isKnown(llvm::StringRef Ext) const { + return OptMap.find(Ext) != OptMap.end(); +} + +bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const { + auto E = OptMap.find(Ext); + return E != OptMap.end() && E->second.Enabled; +} + +bool OpenCLOptions::isSupported(llvm::StringRef Ext, + const LangOptions &LO) const { + auto E = OptMap.find(Ext); + if (E == OptMap.end()) { + return false; + } + auto I = OptMap.find(Ext)->getValue(); + return I.Supported && I.isAvailableIn(LO); +} + +bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext, + const LangOptions &LO) const { + auto E = OptMap.find(Ext); + if (E == OptMap.end()) { + return false; + } + auto I = OptMap.find(Ext)->getValue(); + return I.Supported && I.isCoreIn(LO); +} + +bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext, + const LangOptions &LO) const { + auto E = OptMap.find(Ext); + if (E == OptMap.end()) { + return false; + } + auto I = OptMap.find(Ext)->getValue(); + return I.Supported && I.isOptionalCoreIn(LO); +} + +bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext, + const LangOptions &LO) const { + return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO); +} + +bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext, + const LangOptions &LO) const { + auto E = OptMap.find(Ext); + if (E == OptMap.end()) { + return false; + } + auto I = OptMap.find(Ext)->getValue(); + return I.Supported && I.isAvailableIn(LO) && + !isSupportedCoreOrOptionalCore(Ext, LO); +} + +void OpenCLOptions::enable(llvm::StringRef Ext, bool V) { + OptMap[Ext].Enabled = V; +} + +void OpenCLOptions::support(llvm::StringRef Ext, bool V) { + assert(!Ext.empty() && "Extension is empty."); + assert(Ext[0] != '+' && Ext[0] != '-'); + OptMap[Ext].Supported = V; +} + +OpenCLOptions::OpenCLOptions() { +#define OPENCL_GENERIC_EXTENSION(Ext, AvailVer, CoreVer, OptVer) \ + OptMap[#Ext].Avail = AvailVer; \ + OptMap[#Ext].Core = CoreVer; \ + OptMap[#Ext].Opt = OptVer; +#include "clang/Basic/OpenCLExtensions.def" +} + +void OpenCLOptions::addSupport(const llvm::StringMap<bool> &FeaturesMap, + const LangOptions &Opts) { + for (const auto &F : FeaturesMap) { + const auto &Name = F.getKey(); + if (F.getValue() && isKnown(Name) && OptMap[Name].isAvailableIn(Opts)) + support(Name); + } +} + +void OpenCLOptions::disableAll() { + for (auto &Opt : OptMap) + Opt.getValue().Enabled = false; +} + +void OpenCLOptions::enableSupportedCore(const LangOptions &LO) { + for (auto &Opt : OptMap) + if (isSupportedCoreOrOptionalCore(Opt.getKey(), LO)) + Opt.getValue().Enabled = true; +} + +} // end namespace clang diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index cae61ad4f2e3..5c19d60cbd6e 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -20,8 +20,8 @@ using namespace clang; using namespace llvm::omp; -unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, - StringRef Str) { +unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str, + unsigned OpenMPVersion) { switch (Kind) { case OMPC_default: return llvm::StringSwitch<unsigned>(Str) @@ -51,26 +51,29 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, #define OPENMP_LINEAR_KIND(Name) .Case(#Name, OMPC_LINEAR_##Name) #include "clang/Basic/OpenMPKinds.def" .Default(OMPC_LINEAR_unknown); - case OMPC_map: - return llvm::StringSwitch<unsigned>(Str) + case OMPC_map: { + unsigned Type = llvm::StringSwitch<unsigned>(Str) #define OPENMP_MAP_KIND(Name) \ .Case(#Name, static_cast<unsigned>(OMPC_MAP_##Name)) #define OPENMP_MAP_MODIFIER_KIND(Name) \ .Case(#Name, static_cast<unsigned>(OMPC_MAP_MODIFIER_##Name)) #include "clang/Basic/OpenMPKinds.def" .Default(OMPC_MAP_unknown); + if (OpenMPVersion < 51 && Type == OMPC_MAP_MODIFIER_present) + return OMPC_MAP_MODIFIER_unknown; + return Type; + } case OMPC_to: - return llvm::StringSwitch<unsigned>(Str) -#define OPENMP_TO_MODIFIER_KIND(Name) \ - .Case(#Name, static_cast<unsigned>(OMPC_TO_MODIFIER_##Name)) + case OMPC_from: { + unsigned Type = llvm::StringSwitch<unsigned>(Str) +#define OPENMP_MOTION_MODIFIER_KIND(Name) \ + .Case(#Name, static_cast<unsigned>(OMPC_MOTION_MODIFIER_##Name)) #include "clang/Basic/OpenMPKinds.def" - .Default(OMPC_TO_MODIFIER_unknown); - case OMPC_from: - return llvm::StringSwitch<unsigned>(Str) -#define OPENMP_FROM_MODIFIER_KIND(Name) \ - .Case(#Name, static_cast<unsigned>(OMPC_FROM_MODIFIER_##Name)) -#include "clang/Basic/OpenMPKinds.def" - .Default(OMPC_FROM_MODIFIER_unknown); + .Default(OMPC_MOTION_MODIFIER_unknown); + if (OpenMPVersion < 51 && Type == OMPC_MOTION_MODIFIER_present) + return OMPC_MOTION_MODIFIER_unknown; + return Type; + } case OMPC_dist_schedule: return llvm::StringSwitch<OpenMPDistScheduleClauseKind>(Str) #define OPENMP_DIST_SCHEDULE_KIND(Name) .Case(#Name, OMPC_DIST_SCHEDULE_##Name) @@ -254,29 +257,18 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, } llvm_unreachable("Invalid OpenMP 'map' clause type"); case OMPC_to: - switch (Type) { - case OMPC_TO_MODIFIER_unknown: - return "unknown"; -#define OPENMP_TO_MODIFIER_KIND(Name) \ - case OMPC_TO_MODIFIER_##Name: \ - return #Name; -#include "clang/Basic/OpenMPKinds.def" - default: - break; - } - llvm_unreachable("Invalid OpenMP 'to' clause type"); case OMPC_from: switch (Type) { - case OMPC_FROM_MODIFIER_unknown: + case OMPC_MOTION_MODIFIER_unknown: return "unknown"; -#define OPENMP_FROM_MODIFIER_KIND(Name) \ - case OMPC_FROM_MODIFIER_##Name: \ +#define OPENMP_MOTION_MODIFIER_KIND(Name) \ + case OMPC_MOTION_MODIFIER_##Name: \ return #Name; #include "clang/Basic/OpenMPKinds.def" default: break; } - llvm_unreachable("Invalid OpenMP 'from' clause type"); + llvm_unreachable("Invalid OpenMP 'to' or 'from' clause type"); case OMPC_dist_schedule: switch (Type) { case OMPC_DIST_SCHEDULE_unknown: diff --git a/clang/lib/Basic/ProfileList.cpp b/clang/lib/Basic/ProfileList.cpp new file mode 100644 index 000000000000..56bc37a79301 --- /dev/null +++ b/clang/lib/Basic/ProfileList.cpp @@ -0,0 +1,113 @@ +//===--- ProfileList.h - ProfileList filter ---------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// User-provided filters include/exclude profile instrumentation in certain +// functions or files. +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/ProfileList.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/Support/SpecialCaseList.h" + +#include "llvm/Support/raw_ostream.h" + +using namespace clang; + +namespace clang { + +class ProfileSpecialCaseList : public llvm::SpecialCaseList { +public: + static std::unique_ptr<ProfileSpecialCaseList> + create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &VFS, + std::string &Error); + + static std::unique_ptr<ProfileSpecialCaseList> + createOrDie(const std::vector<std::string> &Paths, + llvm::vfs::FileSystem &VFS); + + bool isEmpty() const { return Sections.empty(); } + + bool hasPrefix(StringRef Prefix) const { + for (auto &SectionIter : Sections) + if (SectionIter.Entries.count(Prefix) > 0) + return true; + return false; + } +}; + +std::unique_ptr<ProfileSpecialCaseList> +ProfileSpecialCaseList::create(const std::vector<std::string> &Paths, + llvm::vfs::FileSystem &VFS, + std::string &Error) { + auto PSCL = std::make_unique<ProfileSpecialCaseList>(); + if (PSCL->createInternal(Paths, VFS, Error)) + return PSCL; + return nullptr; +} + +std::unique_ptr<ProfileSpecialCaseList> +ProfileSpecialCaseList::createOrDie(const std::vector<std::string> &Paths, + llvm::vfs::FileSystem &VFS) { + std::string Error; + if (auto PSCL = create(Paths, VFS, Error)) + return PSCL; + llvm::report_fatal_error(Error); +} + +} + +ProfileList::ProfileList(ArrayRef<std::string> Paths, SourceManager &SM) + : SCL(ProfileSpecialCaseList::createOrDie( + Paths, SM.getFileManager().getVirtualFileSystem())), + Empty(SCL->isEmpty()), + Default(SCL->hasPrefix("fun") || SCL->hasPrefix("src")), SM(SM) {} + +ProfileList::~ProfileList() = default; + +static StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) { + switch (Kind) { + case CodeGenOptions::ProfileNone: + return ""; + case CodeGenOptions::ProfileClangInstr: + return "clang"; + case CodeGenOptions::ProfileIRInstr: + return "llvm"; + case CodeGenOptions::ProfileCSIRInstr: + return "csllvm"; + } +} + +llvm::Optional<bool> +ProfileList::isFunctionExcluded(StringRef FunctionName, + CodeGenOptions::ProfileInstrKind Kind) const { + StringRef Section = getSectionName(Kind); + if (SCL->inSection(Section, "!fun", FunctionName)) + return true; + if (SCL->inSection(Section, "fun", FunctionName)) + return false; + return None; +} + +llvm::Optional<bool> +ProfileList::isLocationExcluded(SourceLocation Loc, + CodeGenOptions::ProfileInstrKind Kind) const { + return isFileExcluded(SM.getFilename(SM.getFileLoc(Loc)), Kind); +} + +llvm::Optional<bool> +ProfileList::isFileExcluded(StringRef FileName, + CodeGenOptions::ProfileInstrKind Kind) const { + StringRef Section = getSectionName(Kind); + if (SCL->inSection(Section, "!src", FileName)) + return true; + if (SCL->inSection(Section, "src", FileName)) + return false; + return None; +} diff --git a/clang/lib/Basic/SourceLocation.cpp b/clang/lib/Basic/SourceLocation.cpp index c1fa406909fe..6f6412028d77 100644 --- a/clang/lib/Basic/SourceLocation.cpp +++ b/clang/lib/Basic/SourceLocation.cpp @@ -14,6 +14,8 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Basic/SourceManager.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" @@ -40,6 +42,23 @@ void PrettyStackTraceLoc::print(raw_ostream &OS) const { // SourceLocation //===----------------------------------------------------------------------===// +static_assert(std::is_trivially_destructible<SourceLocation>::value, + "SourceLocation must be trivially destructible because it is " + "used in unions"); + +static_assert(std::is_trivially_destructible<SourceRange>::value, + "SourceRange must be trivially destructible because it is " + "used in unions"); + +unsigned SourceLocation::getHashValue() const { + return llvm::DenseMapInfo<unsigned>::getHashValue(ID); +} + +void llvm::FoldingSetTrait<SourceLocation>::Profile( + const SourceLocation &X, llvm::FoldingSetNodeID &ID) { + ID.AddInteger(X.ID); +} + void SourceLocation::print(raw_ostream &OS, const SourceManager &SM)const{ if (!isValid()) { OS << "<invalid loc>"; @@ -245,7 +264,7 @@ const char *FullSourceLoc::getCharacterData(bool *Invalid) const { StringRef FullSourceLoc::getBufferData(bool *Invalid) const { assert(isValid()); - return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid)->getBuffer(); + return SrcMgr->getBufferData(SrcMgr->getFileID(*this), Invalid); } std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const { diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 0a76c78cd44f..c0b22837693b 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -49,28 +49,22 @@ using llvm::MemoryBuffer; // SourceManager Helper Classes //===----------------------------------------------------------------------===// -ContentCache::~ContentCache() { - if (shouldFreeBuffer()) - delete Buffer.getPointer(); -} - /// getSizeBytesMapped - Returns the number of bytes actually mapped for this /// ContentCache. This can be 0 if the MemBuffer was not actually expanded. unsigned ContentCache::getSizeBytesMapped() const { - return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0; + return Buffer ? Buffer->getBufferSize() : 0; } /// Returns the kind of memory used to back the memory buffer for /// this content cache. This is used for performance analysis. llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const { - assert(Buffer.getPointer()); + assert(Buffer); // Should be unreachable, but keep for sanity. - if (!Buffer.getPointer()) + if (!Buffer) return llvm::MemoryBuffer::MemoryBuffer_Malloc; - const llvm::MemoryBuffer *buf = Buffer.getPointer(); - return buf->getBufferKind(); + return Buffer->getBufferKind(); } /// getSize - Returns the size of the content encapsulated by this ContentCache. @@ -78,21 +72,8 @@ llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const { /// scratch buffer. If the ContentCache encapsulates a source file, that /// file is not lazily brought in from disk to satisfy this query. unsigned ContentCache::getSize() const { - return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize() - : (unsigned) ContentsEntry->getSize(); -} - -void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree) { - if (B && B == Buffer.getPointer()) { - assert(0 && "Replacing with the same buffer"); - Buffer.setInt(DoNotFree? DoNotFreeFlag : 0); - return; - } - - if (shouldFreeBuffer()) - delete Buffer.getPointer(); - Buffer.setPointer(B); - Buffer.setInt((B && DoNotFree) ? DoNotFreeFlag : 0); + return Buffer ? (unsigned)Buffer->getBufferSize() + : (unsigned)ContentsEntry->getSize(); } const char *ContentCache::getInvalidBOM(StringRef BufStr) { @@ -118,44 +99,21 @@ const char *ContentCache::getInvalidBOM(StringRef BufStr) { return InvalidBOM; } -const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, - FileManager &FM, - SourceLocation Loc, - bool *Invalid) const { +llvm::Optional<llvm::MemoryBufferRef> +ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, + SourceLocation Loc) const { // Lazily create the Buffer for ContentCaches that wrap files. If we already // computed it, just return what we have. - if (Buffer.getPointer() || !ContentsEntry) { - if (Invalid) - *Invalid = isBufferInvalid(); - - return Buffer.getPointer(); - } - - // Check that the file's size fits in an 'unsigned' (with room for a - // past-the-end value). This is deeply regrettable, but various parts of - // Clang (including elsewhere in this file!) use 'unsigned' to represent file - // offsets, line numbers, string literal lengths, and so on, and fail - // miserably on large source files. - if ((uint64_t)ContentsEntry->getSize() >= - std::numeric_limits<unsigned>::max()) { - // We can't make a memory buffer of the required size, so just make a small - // one. We should never hit a situation where we've already parsed to a - // later offset of the file, so it shouldn't matter that the buffer is - // smaller than the file. - Buffer.setPointer( - llvm::MemoryBuffer::getMemBuffer("", ContentsEntry->getName()) - .release()); - if (Diag.isDiagnosticInFlight()) - Diag.SetDelayedDiagnostic(diag::err_file_too_large, - ContentsEntry->getName()); - else - Diag.Report(Loc, diag::err_file_too_large) - << ContentsEntry->getName(); + if (IsBufferInvalid) + return None; + if (Buffer) + return Buffer->getMemBufferRef(); + if (!ContentsEntry) + return None; - Buffer.setInt(Buffer.getInt() | InvalidFlag); - if (Invalid) *Invalid = true; - return Buffer.getPointer(); - } + // Start with the assumption that the buffer is invalid to simplify early + // return paths. + IsBufferInvalid = true; auto BufferOrError = FM.getBufferForFile(ContentsEntry, IsFileVolatile); @@ -164,20 +122,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, // exists. Most likely, we were using a stat cache with an invalid entry but // the file could also have been removed during processing. Since we can't // really deal with this situation, just create an empty buffer. - // - // FIXME: This is definitely not ideal, but our immediate clients can't - // 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 (!BufferOrError) { - StringRef FillStr("<<<MISSING SOURCE FILE>>>\n"); - auto BackupBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer( - ContentsEntry->getSize(), "<invalid>"); - char *Ptr = BackupBuffer->getBufferStart(); - for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i) - Ptr[i] = FillStr[i % FillStr.size()]; - Buffer.setPointer(BackupBuffer.release()); - if (Diag.isDiagnosticInFlight()) Diag.SetDelayedDiagnostic(diag::err_cannot_open_file, ContentsEntry->getName(), @@ -186,17 +131,36 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, Diag.Report(Loc, diag::err_cannot_open_file) << ContentsEntry->getName() << BufferOrError.getError().message(); - Buffer.setInt(Buffer.getInt() | InvalidFlag); - - if (Invalid) *Invalid = true; - return Buffer.getPointer(); + return None; } - Buffer.setPointer(BufferOrError->release()); + Buffer = std::move(*BufferOrError); - // Check that the file's size is the same as in the file entry (which may + // Check that the file's size fits in an 'unsigned' (with room for a + // past-the-end value). This is deeply regrettable, but various parts of + // Clang (including elsewhere in this file!) use 'unsigned' to represent file + // offsets, line numbers, string literal lengths, and so on, and fail + // miserably on large source files. + // + // Note: ContentsEntry could be a named pipe, in which case + // ContentsEntry::getSize() could have the wrong size. Use + // MemoryBuffer::getBufferSize() instead. + if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) { + if (Diag.isDiagnosticInFlight()) + Diag.SetDelayedDiagnostic(diag::err_file_too_large, + ContentsEntry->getName()); + else + Diag.Report(Loc, diag::err_file_too_large) + << ContentsEntry->getName(); + + return None; + } + + // Unless this is a named pipe (in which case we can handle a mismatch), + // 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()) { + if (!ContentsEntry->isNamedPipe() && + Buffer->getBufferSize() != (size_t)ContentsEntry->getSize()) { if (Diag.isDiagnosticInFlight()) Diag.SetDelayedDiagnostic(diag::err_file_modified, ContentsEntry->getName()); @@ -204,27 +168,24 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, Diag.Report(Loc, diag::err_file_modified) << ContentsEntry->getName(); - Buffer.setInt(Buffer.getInt() | InvalidFlag); - if (Invalid) *Invalid = true; - return Buffer.getPointer(); + return None; } // If the buffer is valid, check to see if it has a UTF Byte Order Mark // (BOM). We only support UTF-8 with and without a BOM right now. See // http://en.wikipedia.org/wiki/Byte_order_mark for more information. - StringRef BufStr = Buffer.getPointer()->getBuffer(); + StringRef BufStr = Buffer->getBuffer(); const char *InvalidBOM = getInvalidBOM(BufStr); if (InvalidBOM) { Diag.Report(Loc, diag::err_unsupported_bom) << InvalidBOM << ContentsEntry->getName(); - Buffer.setInt(Buffer.getInt() | InvalidFlag); + return None; } - if (Invalid) - *Invalid = isBufferInvalid(); - - return Buffer.getPointer(); + // Buffer has been validated. + IsBufferInvalid = false; + return Buffer->getMemBufferRef(); } unsigned LineTableInfo::getLineTableFilenameID(StringRef Name) { @@ -389,12 +350,11 @@ void SourceManager::clearIDTables() { createExpansionLoc(SourceLocation(), SourceLocation(), SourceLocation(), 1); } -bool SourceManager::isMainFile(FileEntryRef SourceFile) { +bool SourceManager::isMainFile(const FileEntry &SourceFile) { assert(MainFileID.isValid() && "expected initialized SourceManager"); - auto FE = getFileEntryRefForID(MainFileID); - if (!FE) - return false; - return FE->getUID() == SourceFile.getUID(); + if (auto *FE = getFileEntryForID(MainFileID)) + return FE->getUID() == SourceFile.getUID(); + return false; } void SourceManager::initializeForReplay(const SourceManager &Old) { @@ -407,7 +367,7 @@ void SourceManager::initializeForReplay(const SourceManager &Old) { Clone->BufferOverridden = Cache->BufferOverridden; Clone->IsFileVolatile = Cache->IsFileVolatile; Clone->IsTransient = Cache->IsTransient; - Clone->replaceBuffer(Cache->getRawBuffer(), /*DoNotFree*/true); + Clone->setUnownedBuffer(Cache->getBufferIfLoaded()); return Clone; }; @@ -425,16 +385,12 @@ void SourceManager::initializeForReplay(const SourceManager &Old) { } } -/// getOrCreateContentCache - Create or return a cached ContentCache for the -/// specified file. -const ContentCache * -SourceManager::getOrCreateContentCache(const FileEntry *FileEnt, - bool isSystemFile) { - assert(FileEnt && "Didn't specify a file entry to use?"); - +ContentCache &SourceManager::getOrCreateContentCache(FileEntryRef FileEnt, + bool isSystemFile) { // Do we already have information about this file? ContentCache *&Entry = FileInfos[FileEnt]; - if (Entry) return Entry; + if (Entry) + return *Entry; // Nope, create a new Cache entry. Entry = ContentCacheAlloc.Allocate<ContentCache>(); @@ -456,21 +412,21 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt, Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile; Entry->IsTransient = FilesAreTransient; + Entry->BufferOverridden |= FileEnt.isNamedPipe(); - return Entry; + return *Entry; } /// Create a new ContentCache for the specified memory buffer. /// This does no caching. -const ContentCache * -SourceManager::createMemBufferContentCache(const llvm::MemoryBuffer *Buffer, - bool DoNotFree) { +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->replaceBuffer(Buffer, DoNotFree); - return Entry; + Entry->setBuffer(std::move(Buffer)); + return *Entry; } const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, @@ -482,9 +438,11 @@ 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, "")); + if (!FakeSLocEntryForRecovery) + FakeSLocEntryForRecovery = std::make_unique<SLocEntry>(SLocEntry::get( + 0, FileInfo::get(SourceLocation(), getFakeContentCacheForRecovery(), + SrcMgr::C_User, ""))); + return *FakeSLocEntryForRecovery; } } @@ -507,24 +465,22 @@ SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries, /// As part of recovering from missing or changed content, produce a /// fake, non-empty buffer. -llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { +llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery() const { if (!FakeBufferForRecovery) FakeBufferForRecovery = llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>"); - return FakeBufferForRecovery.get(); + return *FakeBufferForRecovery; } /// As part of recovering from missing or changed content, produce a /// fake content cache. -const SrcMgr::ContentCache * -SourceManager::getFakeContentCacheForRecovery() const { +SrcMgr::ContentCache &SourceManager::getFakeContentCacheForRecovery() const { if (!FakeContentCacheForRecovery) { FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>(); - FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(), - /*DoNotFree=*/true); + FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery()); } - return FakeContentCacheForRecovery.get(); + return *FakeContentCacheForRecovery; } /// Returns the previous in-order FileID or an invalid FileID if there @@ -576,23 +532,24 @@ FileID SourceManager::createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID, unsigned LoadedOffset) { - assert(SourceFile && "Null source file!"); - const SrcMgr::ContentCache *IR = - getOrCreateContentCache(SourceFile, isSystem(FileCharacter)); - assert(IR && "getOrCreateContentCache() cannot return NULL"); - return createFileID(IR, SourceFile->getName(), IncludePos, FileCharacter, - LoadedID, LoadedOffset); + return createFileID(SourceFile->getLastRef(), IncludePos, FileCharacter, + LoadedID, LoadedOffset); } FileID SourceManager::createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID, unsigned LoadedOffset) { - const SrcMgr::ContentCache *IR = getOrCreateContentCache( - &SourceFile.getFileEntry(), isSystem(FileCharacter)); - assert(IR && "getOrCreateContentCache() cannot return NULL"); - return createFileID(IR, SourceFile.getName(), IncludePos, FileCharacter, - LoadedID, LoadedOffset); + SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile, + isSystem(FileCharacter)); + + // If this is a named pipe, immediately load the buffer to ensure subsequent + // calls to ContentCache::getSize() are accurate. + if (IR.ContentsEntry->isNamedPipe()) + (void)IR.getBufferOrNone(Diag, getFileManager(), SourceLocation()); + + return createFileIDImpl(IR, SourceFile.getName(), IncludePos, FileCharacter, + LoadedID, LoadedOffset); } /// Create a new FileID that represents the specified memory buffer. @@ -604,22 +561,20 @@ FileID SourceManager::createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer, int LoadedID, unsigned LoadedOffset, SourceLocation IncludeLoc) { StringRef Name = Buffer->getBufferIdentifier(); - return createFileID( - createMemBufferContentCache(Buffer.release(), /*DoNotFree*/ false), - Name, IncludeLoc, FileCharacter, LoadedID, LoadedOffset); + return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name, + IncludeLoc, FileCharacter, LoadedID, LoadedOffset); } /// Create a new FileID that represents the specified memory buffer. /// /// This does not take ownership of the MemoryBuffer. The memory buffer must /// outlive the SourceManager. -FileID SourceManager::createFileID(UnownedTag, const llvm::MemoryBuffer *Buffer, +FileID SourceManager::createFileID(const llvm::MemoryBufferRef &Buffer, SrcMgr::CharacteristicKind FileCharacter, int LoadedID, unsigned LoadedOffset, SourceLocation IncludeLoc) { - return createFileID(createMemBufferContentCache(Buffer, /*DoNotFree*/ true), - Buffer->getBufferIdentifier(), IncludeLoc, - FileCharacter, LoadedID, LoadedOffset); + return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter, + LoadedID, LoadedOffset, IncludeLoc); } /// Get the FileID for \p SourceFile if it exists. Otherwise, create a @@ -635,10 +590,10 @@ SourceManager::getOrCreateFileID(const FileEntry *SourceFile, /// 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, StringRef Filename, - SourceLocation IncludePos, - SrcMgr::CharacteristicKind FileCharacter, - int LoadedID, unsigned LoadedOffset) { +FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename, + SourceLocation IncludePos, + SrcMgr::CharacteristicKind FileCharacter, + int LoadedID, unsigned LoadedOffset) { if (LoadedID < 0) { assert(LoadedID != -1 && "Loading sentinel FileID"); unsigned Index = unsigned(-LoadedID) - 2; @@ -649,7 +604,7 @@ FileID SourceManager::createFileID(const ContentCache *File, StringRef Filename, SLocEntryLoaded[Index] = true; return FileID::get(LoadedID); } - unsigned FileSize = File->getSize(); + unsigned FileSize = File.getSize(); if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset && NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) { Diag.Report(IncludePos, diag::err_include_too_large); @@ -723,21 +678,18 @@ SourceManager::createExpansionLocImpl(const ExpansionInfo &Info, return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1)); } -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, getFileManager(), SourceLocation(), Invalid); +llvm::Optional<llvm::MemoryBufferRef> +SourceManager::getMemoryBufferForFileOrNone(const FileEntry *File) { + SrcMgr::ContentCache &IR = getOrCreateContentCache(File->getLastRef()); + return IR.getBufferOrNone(Diag, getFileManager(), SourceLocation()); } -void SourceManager::overrideFileContents(const FileEntry *SourceFile, - llvm::MemoryBuffer *Buffer, - bool DoNotFree) { - const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile); - assert(IR && "getOrCreateContentCache() cannot return NULL"); +void SourceManager::overrideFileContents( + const FileEntry *SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) { + SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile->getLastRef()); - const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree); - const_cast<SrcMgr::ContentCache *>(IR)->BufferOverridden = true; + IR.setBuffer(std::move(Buffer)); + IR.BufferOverridden = true; getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile); } @@ -753,56 +705,51 @@ void SourceManager::overrideFileContents(const FileEntry *SourceFile, getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile; } -const FileEntry * -SourceManager::bypassFileContentsOverride(const FileEntry &File) { - assert(isFileOverridden(&File)); - llvm::Optional<FileEntryRef> BypassFile = - FileMgr.getBypassFile(FileEntryRef(File.getName(), File)); +Optional<FileEntryRef> +SourceManager::bypassFileContentsOverride(FileEntryRef File) { + assert(isFileOverridden(&File.getFileEntry())); + llvm::Optional<FileEntryRef> BypassFile = FileMgr.getBypassFile(File); // If the file can't be found in the FS, give up. if (!BypassFile) - return nullptr; + return None; - const FileEntry *FE = &BypassFile->getFileEntry(); - (void)getOrCreateContentCache(FE); - return FE; + (void)getOrCreateContentCache(*BypassFile); + return BypassFile; } void SourceManager::setFileIsTransient(const FileEntry *File) { - const SrcMgr::ContentCache *CC = getOrCreateContentCache(File); - const_cast<SrcMgr::ContentCache *>(CC)->IsTransient = true; + getOrCreateContentCache(File->getLastRef()).IsTransient = true; } -Optional<FileEntryRef> SourceManager::getFileEntryRefForID(FileID FID) const { - bool Invalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); - if (Invalid || !Entry.isFile()) - return None; - - const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache(); - if (!Content || !Content->OrigEntry) - return None; - return FileEntryRef(Entry.getFile().getName(), *Content->OrigEntry); +Optional<StringRef> +SourceManager::getNonBuiltinFilenameForID(FileID FID) const { + if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID)) + if (Entry->getFile().getContentCache().OrigEntry) + return Entry->getFile().getName(); + return None; } StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const { - bool MyInvalid = false; - const SLocEntry &SLoc = getSLocEntry(FID, &MyInvalid); - if (!SLoc.isFile() || MyInvalid) { - if (Invalid) - *Invalid = true; - return "<<<<<INVALID SOURCE LOCATION>>>>>"; - } - - const llvm::MemoryBuffer *Buf = SLoc.getFile().getContentCache()->getBuffer( - Diag, getFileManager(), SourceLocation(), &MyInvalid); + auto B = getBufferDataOrNone(FID); if (Invalid) - *Invalid = MyInvalid; + *Invalid = !B; + return B ? *B : "<<<<<INVALID SOURCE LOCATION>>>>>"; +} - if (MyInvalid) - return "<<<<<INVALID SOURCE LOCATION>>>>>"; +llvm::Optional<StringRef> +SourceManager::getBufferDataIfLoaded(FileID FID) const { + if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID)) + return Entry->getFile().getContentCache().getBufferDataIfLoaded(); + return None; +} - return Buf->getBuffer(); +llvm::Optional<StringRef> SourceManager::getBufferDataOrNone(FileID FID) const { + if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID)) + if (auto B = Entry->getFile().getContentCache().getBufferOrNone( + Diag, getFileManager(), SourceLocation())) + return B->getBuffer(); + return None; } //===----------------------------------------------------------------------===// @@ -1219,24 +1166,24 @@ const char *SourceManager::getCharacterData(SourceLocation SL, return "<<<<INVALID BUFFER>>>>"; } - const llvm::MemoryBuffer *Buffer = - Entry.getFile().getContentCache()->getBuffer( - Diag, getFileManager(), SourceLocation(), &CharDataInvalid); + llvm::Optional<llvm::MemoryBufferRef> Buffer = + Entry.getFile().getContentCache().getBufferOrNone(Diag, getFileManager(), + SourceLocation()); if (Invalid) - *Invalid = CharDataInvalid; - return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second); + *Invalid = !Buffer; + return Buffer ? Buffer->getBufferStart() + LocInfo.second + : "<<<<INVALID BUFFER>>>>"; } /// getColumnNumber - Return the column # for the specified file position. /// this is significantly cheaper to compute than the line number. unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid) const { - bool MyInvalid = false; - const llvm::MemoryBuffer *MemBuf = getBuffer(FID, &MyInvalid); + llvm::Optional<llvm::MemoryBufferRef> MemBuf = getBufferOrNone(FID); if (Invalid) - *Invalid = MyInvalid; + *Invalid = !MemBuf; - if (MyInvalid) + if (!MemBuf) return 1; // It is okay to request a position just past the end of the buffer. @@ -1249,10 +1196,10 @@ unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos, const char *Buf = MemBuf->getBufferStart(); // See if we just calculated the line number for this FilePos and can use // that to lookup the start of the line instead of searching for it. - if (LastLineNoFileIDQuery == FID && - LastLineNoContentCache->SourceLineCache != nullptr && - LastLineNoResult < LastLineNoContentCache->NumLines) { - unsigned *SourceLineCache = LastLineNoContentCache->SourceLineCache; + if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache && + LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) { + const unsigned *SourceLineCache = + LastLineNoContentCache->SourceLineCache.begin(); unsigned LineStart = SourceLineCache[LastLineNoResult - 1]; unsigned LineEnd = SourceLineCache[LastLineNoResult]; if (FilePos >= LineStart && FilePos < LineEnd) { @@ -1309,19 +1256,8 @@ unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc, #include <emmintrin.h> #endif -static LLVM_ATTRIBUTE_NOINLINE void -ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, - llvm::BumpPtrAllocator &Alloc, - const SourceManager &SM, bool &Invalid); -static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, - llvm::BumpPtrAllocator &Alloc, - const SourceManager &SM, bool &Invalid) { - // Note that calling 'getBuffer()' may lazily page in the file. - const MemoryBuffer *Buffer = - FI->getBuffer(Diag, SM.getFileManager(), SourceLocation(), &Invalid); - if (Invalid) - return; - +LineOffsetMapping LineOffsetMapping::get(llvm::MemoryBufferRef Buffer, + llvm::BumpPtrAllocator &Alloc) { // Find the file offsets of all of the *physical* source lines. This does // not look at trigraphs, escaped newlines, or anything else tricky. SmallVector<unsigned, 256> LineOffsets; @@ -1329,8 +1265,8 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, // Line #1 starts at char 0. LineOffsets.push_back(0); - const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart(); - const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd(); + const unsigned char *Buf = (const unsigned char *)Buffer.getBufferStart(); + const unsigned char *End = (const unsigned char *)Buffer.getBufferEnd(); const std::size_t BufLen = End - Buf; unsigned I = 0; while (I < BufLen) { @@ -1345,10 +1281,14 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, ++I; } - // Copy the offsets into the FileInfo structure. - FI->NumLines = LineOffsets.size(); - FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size()); - std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache); + return LineOffsetMapping(LineOffsets, Alloc); +} + +LineOffsetMapping::LineOffsetMapping(ArrayRef<unsigned> LineOffsets, + llvm::BumpPtrAllocator &Alloc) + : Storage(Alloc.Allocate<unsigned>(LineOffsets.size() + 1)) { + Storage[0] = LineOffsets.size(); + std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1); } /// getLineNumber - Given a SourceLocation, return the spelling line number @@ -1363,7 +1303,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos, return 1; } - ContentCache *Content; + const ContentCache *Content; if (LastLineNoFileIDQuery == FID) Content = LastLineNoContentCache; else { @@ -1375,26 +1315,29 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos, return 1; } - Content = const_cast<ContentCache*>(Entry.getFile().getContentCache()); + Content = &Entry.getFile().getContentCache(); } // If this is the first use of line information for this buffer, compute the /// SourceLineCache for it on demand. if (!Content->SourceLineCache) { - bool MyInvalid = false; - ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid); + llvm::Optional<llvm::MemoryBufferRef> Buffer = + Content->getBufferOrNone(Diag, getFileManager(), SourceLocation()); if (Invalid) - *Invalid = MyInvalid; - if (MyInvalid) + *Invalid = !Buffer; + if (!Buffer) return 1; + + Content->SourceLineCache = + LineOffsetMapping::get(*Buffer, ContentCacheAlloc); } else if (Invalid) *Invalid = false; // Okay, we know we have a line number table. Do a binary search to find the // line number that this character position lands on. - unsigned *SourceLineCache = Content->SourceLineCache; - unsigned *SourceLineCacheStart = SourceLineCache; - unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines; + const unsigned *SourceLineCache = Content->SourceLineCache.begin(); + const unsigned *SourceLineCacheStart = SourceLineCache; + const unsigned *SourceLineCacheEnd = Content->SourceLineCache.end(); unsigned QueriedFilePos = FilePos+1; @@ -1433,13 +1376,13 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos, } } } else { - if (LastLineNoResult < Content->NumLines) + if (LastLineNoResult < Content->SourceLineCache.size()) SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1; } } - unsigned *Pos - = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos); + const unsigned *Pos = + std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos); unsigned LineNo = Pos-SourceLineCacheStart; LastLineNoFileIDQuery = FID; @@ -1480,12 +1423,11 @@ SrcMgr::CharacteristicKind SourceManager::getFileCharacteristic(SourceLocation Loc) const { assert(Loc.isValid() && "Can't get file characteristic of invalid loc!"); std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); - bool Invalid = false; - const SLocEntry &SEntry = getSLocEntry(LocInfo.first, &Invalid); - if (Invalid || !SEntry.isFile()) + const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first); + if (!SEntry) return C_User; - const SrcMgr::FileInfo &FI = SEntry.getFile(); + const SrcMgr::FileInfo &FI = SEntry->getFile(); // If there are no #line directives in this file, just return the whole-file // state. @@ -1511,7 +1453,10 @@ StringRef SourceManager::getBufferName(SourceLocation Loc, bool *Invalid) const { if (isInvalid(Loc, Invalid)) return "<invalid loc>"; - return getBuffer(getFileID(Loc), Invalid)->getBufferIdentifier(); + auto B = getBufferOrNone(getFileID(Loc)); + if (Invalid) + *Invalid = !B; + return B ? B->getBufferIdentifier() : "<invalid buffer>"; } /// getPresumedLoc - This method returns the "presumed" location of a @@ -1534,7 +1479,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc, return PresumedLoc(); const SrcMgr::FileInfo &FI = Entry.getFile(); - const SrcMgr::ContentCache *C = FI.getContentCache(); + const SrcMgr::ContentCache *C = &FI.getContentCache(); // To get the source name, first consult the FileEntry (if one exists) // before the MemBuffer as this will avoid unnecessarily paging in the @@ -1543,8 +1488,8 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc, StringRef Filename; if (C->OrigEntry) Filename = C->OrigEntry->getName(); - else - Filename = C->getBuffer(Diag, getFileManager())->getBufferIdentifier(); + else if (auto Buffer = C->getBufferOrNone(Diag, getFileManager())) + Filename = Buffer->getBufferIdentifier(); unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid); if (Invalid) @@ -1603,12 +1548,11 @@ bool SourceManager::isInMainFile(SourceLocation Loc) const { // Presumed locations are always for expansion points. std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); - bool Invalid = false; - const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); - if (Invalid || !Entry.isFile()) + const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first); + if (!Entry) return false; - const SrcMgr::FileInfo &FI = Entry.getFile(); + const SrcMgr::FileInfo &FI = Entry->getFile(); // Check if there is a line directive for this location. if (FI.hasLineDirectives()) @@ -1673,9 +1617,7 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const { return FileID(); if (MainSLoc.isFile()) { - const ContentCache *MainContentCache = - MainSLoc.getFile().getContentCache(); - if (MainContentCache && MainContentCache->OrigEntry == SourceFile) + if (MainSLoc.getFile().getContentCache().OrigEntry == SourceFile) return MainFileID; } } @@ -1684,16 +1626,16 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const { // through all of the local source locations. for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { const SLocEntry &SLoc = getLocalSLocEntry(I); - if (SLoc.isFile() && SLoc.getFile().getContentCache() && - SLoc.getFile().getContentCache()->OrigEntry == SourceFile) + if (SLoc.isFile() && + SLoc.getFile().getContentCache().OrigEntry == SourceFile) return FileID::get(I); } // 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) + if (SLoc.isFile() && + SLoc.getFile().getContentCache().OrigEntry == SourceFile) return FileID::get(-int(I) - 2); } @@ -1725,28 +1667,25 @@ SourceLocation SourceManager::translateLineCol(FileID FID, if (Line == 1 && Col == 1) return FileLoc; - ContentCache *Content - = const_cast<ContentCache *>(Entry.getFile().getContentCache()); - if (!Content) - return SourceLocation(); + const ContentCache *Content = &Entry.getFile().getContentCache(); // If this is the first use of line information for this buffer, compute the // SourceLineCache for it on demand. - if (!Content->SourceLineCache) { - bool MyInvalid = false; - ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid); - if (MyInvalid) - return SourceLocation(); - } + llvm::Optional<llvm::MemoryBufferRef> Buffer = + Content->getBufferOrNone(Diag, getFileManager()); + if (!Buffer) + return SourceLocation(); + if (!Content->SourceLineCache) + Content->SourceLineCache = + LineOffsetMapping::get(*Buffer, ContentCacheAlloc); - if (Line > Content->NumLines) { - unsigned Size = Content->getBuffer(Diag, getFileManager())->getBufferSize(); + if (Line > Content->SourceLineCache.size()) { + unsigned Size = Buffer->getBufferSize(); if (Size > 0) --Size; return FileLoc.getLocWithOffset(Size); } - 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; @@ -1791,13 +1730,18 @@ void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache, if (Invalid) return; if (Entry.isFile()) { - SourceLocation IncludeLoc = Entry.getFile().getIncludeLoc(); + auto& File = Entry.getFile(); + if (File.getFileCharacteristic() == C_User_ModuleMap || + File.getFileCharacteristic() == C_System_ModuleMap) + continue; + + SourceLocation IncludeLoc = File.getIncludeLoc(); bool IncludedInFID = (IncludeLoc.isValid() && isInFileID(IncludeLoc, FID)) || // Predefined header doesn't have a valid include location in main // file, but any files created by it should still be skipped when // computing macro args expanded in the main file. - (FID == MainFileID && Entry.getFile().Filename == "<built-in>"); + (FID == MainFileID && Entry.getFile().getName() == "<built-in>"); if (IncludedInFID) { // Skip the files/macros of the #include'd file, we only care about // macros that lexed macro arguments from our file. @@ -1936,6 +1880,11 @@ SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const { assert(!MacroArgsCache->empty()); MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset); + // In case every element in MacroArgsCache is greater than Offset we can't + // decrement the iterator. + if (I == MacroArgsCache->begin()) + return Loc; + --I; unsigned MacroArgBeginOffs = I->first; @@ -2040,8 +1989,8 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, // If we arrived here, the location is either in a built-ins buffer or // associated with global inline asm. PR5662 and PR22576 are examples. - StringRef LB = getBuffer(LOffs.first)->getBufferIdentifier(); - StringRef RB = getBuffer(ROffs.first)->getBufferIdentifier(); + StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier(); + StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier(); bool LIsBuiltins = LB == "<built-in>"; bool RIsBuiltins = RB == "<built-in>"; // Sort built-in before non-built-in. @@ -2142,7 +2091,7 @@ void SourceManager::PrintStats() const { unsigned NumLineNumsComputed = 0; unsigned NumFileBytesMapped = 0; for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){ - NumLineNumsComputed += I->second->SourceLineCache != nullptr; + NumLineNumsComputed += bool(I->second->SourceLineCache); NumFileBytesMapped += I->second->getSizeBytesMapped(); } unsigned NumMacroArgsComputed = MacroArgsCacheMap.size(); @@ -2172,16 +2121,15 @@ LLVM_DUMP_METHOD void SourceManager::dump() const { << ">\n"; if (FI.getIncludeLoc().isValid()) out << " included from " << FI.getIncludeLoc().getOffset() << "\n"; - if (auto *CC = FI.getContentCache()) { - out << " for " << (CC->OrigEntry ? CC->OrigEntry->getName() : "<none>") + auto &CC = FI.getContentCache(); + out << " for " << (CC.OrigEntry ? CC.OrigEntry->getName() : "<none>") + << "\n"; + if (CC.BufferOverridden) + out << " contents overridden\n"; + if (CC.ContentsEntry != CC.OrigEntry) { + out << " contents from " + << (CC.ContentsEntry ? CC.ContentsEntry->getName() : "<none>") << "\n"; - if (CC->BufferOverridden) - out << " contents overridden\n"; - if (CC->ContentsEntry != CC->OrigEntry) { - out << " contents from " - << (CC->ContentsEntry ? CC->ContentsEntry->getName() : "<none>") - << "\n"; - } } } else { auto &EI = Entry.getExpansion(); diff --git a/clang/lib/Basic/TargetID.cpp b/clang/lib/Basic/TargetID.cpp new file mode 100644 index 000000000000..59d416f0e015 --- /dev/null +++ b/clang/lib/Basic/TargetID.cpp @@ -0,0 +1,169 @@ +//===--- TargetID.cpp - Utilities for parsing target ID -------------------===// +// +// 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/TargetID.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/raw_ostream.h" +#include <map> + +namespace clang { + +static const llvm::SmallVector<llvm::StringRef, 4> +getAllPossibleAMDGPUTargetIDFeatures(const llvm::Triple &T, + llvm::StringRef Proc) { + // Entries in returned vector should be in alphabetical order. + llvm::SmallVector<llvm::StringRef, 4> Ret; + auto ProcKind = T.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Proc) + : llvm::AMDGPU::parseArchR600(Proc); + if (ProcKind == llvm::AMDGPU::GK_NONE) + return Ret; + auto Features = T.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind) + : llvm::AMDGPU::getArchAttrR600(ProcKind); + if (Features & llvm::AMDGPU::FEATURE_SRAMECC) + Ret.push_back("sramecc"); + if (Features & llvm::AMDGPU::FEATURE_XNACK) + Ret.push_back("xnack"); + return Ret; +} + +const llvm::SmallVector<llvm::StringRef, 4> +getAllPossibleTargetIDFeatures(const llvm::Triple &T, + llvm::StringRef Processor) { + llvm::SmallVector<llvm::StringRef, 4> Ret; + if (T.isAMDGPU()) + return getAllPossibleAMDGPUTargetIDFeatures(T, Processor); + return Ret; +} + +/// Returns canonical processor name or empty string if \p Processor is invalid. +static llvm::StringRef getCanonicalProcessorName(const llvm::Triple &T, + llvm::StringRef Processor) { + if (T.isAMDGPU()) + return llvm::AMDGPU::getCanonicalArchName(T, Processor); + return Processor; +} + +llvm::StringRef getProcessorFromTargetID(const llvm::Triple &T, + llvm::StringRef TargetID) { + auto Split = TargetID.split(':'); + return getCanonicalProcessorName(T, Split.first); +} + +// Parse a target ID with format checking only. Do not check whether processor +// name or features are valid for the processor. +// +// A target ID is a processor name followed by a list of target features +// delimited by colon. Each target feature is a string post-fixed by a plus +// or minus sign, e.g. gfx908:sramecc+:xnack-. +static llvm::Optional<llvm::StringRef> +parseTargetIDWithFormatCheckingOnly(llvm::StringRef TargetID, + llvm::StringMap<bool> *FeatureMap) { + llvm::StringRef Processor; + + if (TargetID.empty()) + return llvm::StringRef(); + + auto Split = TargetID.split(':'); + Processor = Split.first; + if (Processor.empty()) + return llvm::None; + + auto Features = Split.second; + if (Features.empty()) + return Processor; + + llvm::StringMap<bool> LocalFeatureMap; + if (!FeatureMap) + FeatureMap = &LocalFeatureMap; + + while (!Features.empty()) { + auto Splits = Features.split(':'); + auto Sign = Splits.first.back(); + auto Feature = Splits.first.drop_back(); + if (Sign != '+' && Sign != '-') + return llvm::None; + bool IsOn = Sign == '+'; + auto Loc = FeatureMap->find(Feature); + // Each feature can only show up at most once in target ID. + if (Loc != FeatureMap->end()) + return llvm::None; + (*FeatureMap)[Feature] = IsOn; + Features = Splits.second; + } + return Processor; +} + +llvm::Optional<llvm::StringRef> +parseTargetID(const llvm::Triple &T, llvm::StringRef TargetID, + llvm::StringMap<bool> *FeatureMap) { + auto OptionalProcessor = + parseTargetIDWithFormatCheckingOnly(TargetID, FeatureMap); + + if (!OptionalProcessor) + return llvm::None; + + llvm::StringRef Processor = + getCanonicalProcessorName(T, OptionalProcessor.getValue()); + if (Processor.empty()) + return llvm::None; + + llvm::SmallSet<llvm::StringRef, 4> AllFeatures; + for (auto &&F : getAllPossibleTargetIDFeatures(T, Processor)) + AllFeatures.insert(F); + + for (auto &&F : *FeatureMap) + if (!AllFeatures.count(F.first())) + return llvm::None; + + return Processor; +} + +// A canonical target ID is a target ID containing a canonical processor name +// and features in alphabetical order. +std::string getCanonicalTargetID(llvm::StringRef Processor, + const llvm::StringMap<bool> &Features) { + std::string TargetID = Processor.str(); + std::map<const llvm::StringRef, bool> OrderedMap; + for (const auto &F : Features) + OrderedMap[F.first()] = F.second; + for (auto F : OrderedMap) + TargetID = TargetID + ':' + F.first.str() + (F.second ? "+" : "-"); + return TargetID; +} + +// For a specific processor, a feature either shows up in all target IDs, or +// does not show up in any target IDs. Otherwise the target ID combination +// is invalid. +llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>> +getConflictTargetIDCombination(const std::set<llvm::StringRef> &TargetIDs) { + struct Info { + llvm::StringRef TargetID; + llvm::StringMap<bool> Features; + }; + llvm::StringMap<Info> FeatureMap; + for (auto &&ID : TargetIDs) { + llvm::StringMap<bool> Features; + llvm::StringRef Proc = + parseTargetIDWithFormatCheckingOnly(ID, &Features).getValue(); + auto Loc = FeatureMap.find(Proc); + if (Loc == FeatureMap.end()) + FeatureMap[Proc] = Info{ID, Features}; + else { + auto &ExistingFeatures = Loc->second.Features; + if (llvm::any_of(Features, [&](auto &F) { + return ExistingFeatures.count(F.first()) == 0; + })) + return std::make_pair(Loc->second.TargetID, ID); + } + } + return llvm::None; +} + +} // namespace clang diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index eccdc21d724a..642ee753d224 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -115,6 +115,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { HasBuiltinMSVaList = false; IsRenderScriptTarget = false; HasAArch64SVETypes = false; + AllowAMDGPUUnsafeFPAtomics = false; ARMCDECoprocMask = 0; // Default to no types using fpret. diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 6bbcafa27dfe..90a67d03b7b2 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -334,6 +334,16 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, return new PPC32TargetInfo(Triple, Opts); } + case llvm::Triple::ppcle: + switch (os) { + case llvm::Triple::Linux: + return new LinuxTargetInfo<PPC32TargetInfo>(Triple, Opts); + case llvm::Triple::FreeBSD: + return new FreeBSDTargetInfo<PPC32TargetInfo>(Triple, Opts); + default: + return new PPC32TargetInfo(Triple, Opts); + } + case llvm::Triple::ppc64: if (Triple.isOSDarwin()) return new DarwinPPC64TargetInfo(Triple, Opts); @@ -346,6 +356,8 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, return new FreeBSDTargetInfo<PPC64TargetInfo>(Triple, Opts); case llvm::Triple::NetBSD: return new NetBSDTargetInfo<PPC64TargetInfo>(Triple, Opts); + case llvm::Triple::OpenBSD: + return new OpenBSDTargetInfo<PPC64TargetInfo>(Triple, Opts); case llvm::Triple::AIX: return new AIXPPC64TargetInfo(Triple, Opts); default: @@ -356,8 +368,12 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, switch (os) { case llvm::Triple::Linux: return new LinuxTargetInfo<PPC64TargetInfo>(Triple, Opts); + case llvm::Triple::FreeBSD: + return new FreeBSDTargetInfo<PPC64TargetInfo>(Triple, Opts); case llvm::Triple::NetBSD: return new NetBSDTargetInfo<PPC64TargetInfo>(Triple, Opts); + case llvm::Triple::OpenBSD: + return new OpenBSDTargetInfo<PPC64TargetInfo>(Triple, Opts); default: return new PPC64TargetInfo(Triple, Opts); } @@ -387,6 +403,8 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, switch (os) { case llvm::Triple::FreeBSD: return new FreeBSDTargetInfo<RISCV64TargetInfo>(Triple, Opts); + case llvm::Triple::OpenBSD: + return new OpenBSDTargetInfo<RISCV64TargetInfo>(Triple, Opts); case llvm::Triple::Fuchsia: return new FuchsiaTargetInfo<RISCV64TargetInfo>(Triple, Opts); case llvm::Triple::Linux: @@ -403,8 +421,6 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, return new SolarisTargetInfo<SparcV8TargetInfo>(Triple, Opts); case llvm::Triple::NetBSD: return new NetBSDTargetInfo<SparcV8TargetInfo>(Triple, Opts); - case llvm::Triple::OpenBSD: - return new OpenBSDTargetInfo<SparcV8TargetInfo>(Triple, Opts); case llvm::Triple::RTEMS: return new RTEMSTargetInfo<SparcV8TargetInfo>(Triple, Opts); default: @@ -418,8 +434,6 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, return new LinuxTargetInfo<SparcV8elTargetInfo>(Triple, Opts); case llvm::Triple::NetBSD: return new NetBSDTargetInfo<SparcV8elTargetInfo>(Triple, Opts); - case llvm::Triple::OpenBSD: - return new OpenBSDTargetInfo<SparcV8elTargetInfo>(Triple, Opts); case llvm::Triple::RTEMS: return new RTEMSTargetInfo<SparcV8elTargetInfo>(Triple, Opts); default: @@ -446,6 +460,8 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, switch (os) { case llvm::Triple::Linux: return new LinuxTargetInfo<SystemZTargetInfo>(Triple, Opts); + case llvm::Triple::ZOS: + return new ZOSTargetInfo<SystemZTargetInfo>(Triple, Opts); default: return new SystemZTargetInfo(Triple, Opts); } @@ -648,6 +664,17 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, return nullptr; } + // Check the TuneCPU name if specified. + if (!Opts->TuneCPU.empty() && + !Target->isValidTuneCPUName(Opts->TuneCPU)) { + Diags.Report(diag::err_target_unknown_cpu) << Opts->TuneCPU; + SmallVector<StringRef, 32> ValidList; + Target->fillValidTuneCPUList(ValidList); + if (!ValidList.empty()) + Diags.Report(diag::note_valid_options) << llvm::join(ValidList, ", "); + return nullptr; + } + // Set the target ABI if specified. if (!Opts->ABI.empty() && !Target->setABI(Opts->ABI)) { Diags.Report(diag::err_target_unknown_abi) << Opts->ABI; @@ -662,14 +689,13 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, // Compute the default target features, we need the target to handle this // because features may have dependencies on one another. - llvm::StringMap<bool> Features; - if (!Target->initFeatureMap(Features, Diags, Opts->CPU, + if (!Target->initFeatureMap(Opts->FeatureMap, Diags, Opts->CPU, Opts->FeaturesAsWritten)) return nullptr; // Add the features to the compile options. Opts->Features.clear(); - for (const auto &F : Features) + for (const auto &F : Opts->FeatureMap) Opts->Features.push_back((F.getValue() ? "+" : "-") + F.getKey().str()); // Sort here, so we handle the features in a predictable order. (This matters // when we're dealing with features that overlap.) @@ -679,7 +705,7 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, return nullptr; Target->setSupportedOpenCLOpts(); - Target->setOpenCLExtensionOpts(); + Target->setCommandLineOpenCLOpts(); Target->setMaxAtomicWidth(); if (!Target->validateTarget(Diags)) @@ -689,3 +715,29 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, return Target.release(); } + +/// getOpenCLFeatureDefines - Define OpenCL macros based on target settings +/// and language version +void TargetInfo::getOpenCLFeatureDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + + auto defineOpenCLExtMacro = [&](llvm::StringRef Name, unsigned AvailVer, + unsigned CoreVersions, + unsigned OptionalVersions) { + // Check if extension is supported by target and is available in this + // OpenCL version + auto It = getTargetOpts().OpenCLFeaturesMap.find(Name); + if ((It != getTargetOpts().OpenCLFeaturesMap.end()) && It->getValue() && + OpenCLOptions::OpenCLOptionInfo(AvailVer, CoreVersions, + OptionalVersions) + .isAvailableIn(Opts)) + Builder.defineMacro(Name); + }; +#define OPENCL_GENERIC_EXTENSION(Ext, Avail, Core, Opt) \ + defineOpenCLExtMacro(#Ext, Avail, Core, Opt); +#include "clang/Basic/OpenCLExtensions.def" + + // FIXME: OpenCL options which affect language semantics/syntax + // should be moved into LangOptions, thus macro definitions of + // such options is better to be done in clang::InitializePreprocessor +} diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 25c02cb888c1..f17134623b8b 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -155,8 +155,9 @@ void AArch64TargetInfo::fillValidCPUList( void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, MacroBuilder &Builder) const { - // FIXME: Armv8.1 makes __ARM_FEATURE_CRC32 mandatory. Handle it here. Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); + Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1"); + Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); } void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts, @@ -176,8 +177,6 @@ void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts, void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts, MacroBuilder &Builder) const { // Also include the Armv8.3 defines - // FIXME: Armv8.4 makes __ARM_FEATURE_ATOMICS, defined in GCC, mandatory. - // Add and handle it here. getTargetDefinesARMV83A(Opts, Builder); } @@ -197,6 +196,12 @@ void AArch64TargetInfo::getTargetDefinesARMV86A(const LangOptions &Opts, getTargetDefinesARMV85A(Opts, Builder); } +void AArch64TargetInfo::getTargetDefinesARMV87A(const LangOptions &Opts, + MacroBuilder &Builder) const { + // Also include the Armv8.6 defines + getTargetDefinesARMV86A(Opts, Builder); +} + void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { // Target identification. @@ -304,6 +309,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasMatMul) Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1"); + if (HasLSE) + Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1"); + if (HasBFloat16) { Builder.defineMacro("__ARM_FEATURE_BF16", "1"); Builder.defineMacro("__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", "1"); @@ -348,6 +356,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (Opts.BranchTargetEnforcement) Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1"); + if (HasLS64) + Builder.defineMacro("__ARM_FEATURE_LS64", "1"); + switch (ArchKind) { default: break; @@ -369,6 +380,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, case llvm::AArch64::ArchKind::ARMV8_6A: getTargetDefinesARMV86A(Opts, Builder); break; + case llvm::AArch64::ArchKind::ARMV8_7A: + getTargetDefinesARMV87A(Opts, Builder); + break; } // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work. @@ -376,6 +390,11 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); + + if (Opts.ArmSveVectorBits) { + Builder.defineMacro("__ARM_FEATURE_SVE_BITS", Twine(Opts.ArmSveVectorBits)); + Builder.defineMacro("__ARM_FEATURE_SVE_VECTOR_OPERATORS"); + } } ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const { @@ -404,6 +423,7 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasFP16FML = false; HasMTE = false; HasTME = false; + HasLS64 = false; HasMatMul = false; HasBFloat16 = false; HasSVE2 = false; @@ -413,6 +433,7 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasSVE2BitPerm = false; HasMatmulFP64 = false; HasMatmulFP32 = false; + HasLSE = false; ArchKind = llvm::AArch64::ArchKind::ARMV8A; @@ -478,6 +499,10 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, ArchKind = llvm::AArch64::ArchKind::ARMV8_5A; if (Feature == "+v8.6a") ArchKind = llvm::AArch64::ArchKind::ARMV8_6A; + if (Feature == "+v8.7a") + ArchKind = llvm::AArch64::ArchKind::ARMV8_7A; + if (Feature == "+v8r") + ArchKind = llvm::AArch64::ArchKind::ARMV8R; if (Feature == "+fullfp16") HasFullFP16 = true; if (Feature == "+dotprod") @@ -488,10 +513,18 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasMTE = true; if (Feature == "+tme") HasTME = true; + if (Feature == "+pauth") + HasPAuth = true; if (Feature == "+i8mm") HasMatMul = true; if (Feature == "+bf16") HasBFloat16 = true; + if (Feature == "+lse") + HasLSE = true; + if (Feature == "+ls64") + HasLS64 = true; + if (Feature == "+flagm") + HasFlagM = true; } setDataLayout(); @@ -754,7 +787,9 @@ WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple, } void WindowsARM64TargetInfo::setDataLayout() { - resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"); + resetDataLayout(Triple.isOSBinFormatMachO() + ? "e-m:o-i64:64-i128:128-n32:64-S128" + : "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"); } TargetInfo::BuiltinVaListKind @@ -843,7 +878,7 @@ DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple, UseZeroLengthBitfieldAlignment = true; TheCXXABI.set(TargetCXXABI::WatchOS); } else - TheCXXABI.set(TargetCXXABI::iOS64); + TheCXXABI.set(TargetCXXABI::AppleARM64); } void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts, @@ -860,6 +895,9 @@ void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts, Builder.defineMacro("__arm64", "1"); Builder.defineMacro("__arm64__", "1"); + if (Triple.isArm64e()) + Builder.defineMacro("__arm64e__", "1"); + getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); } diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index d1982897d84e..2809fbce9c88 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -36,6 +36,8 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { bool HasFP16FML; bool HasMTE; bool HasTME; + bool HasPAuth; + bool HasLS64; bool HasMatMul; bool HasSVE2; bool HasSVE2AES; @@ -44,6 +46,8 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { bool HasSVE2BitPerm; bool HasMatmulFP64; bool HasMatmulFP32; + bool HasLSE; + bool HasFlagM; llvm::AArch64::ArchKind ArchKind; @@ -80,6 +84,8 @@ public: MacroBuilder &Builder) const; void getTargetDefinesARMV86A(const LangOptions &Opts, MacroBuilder &Builder) const; + void getTargetDefinesARMV87A(const LangOptions &Opts, + MacroBuilder &Builder) const; void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp index db7db8d36d03..91c1e83f61cb 100644 --- a/clang/lib/Basic/Targets/AMDGPU.cpp +++ b/clang/lib/Basic/Targets/AMDGPU.cpp @@ -31,12 +31,12 @@ namespace targets { static const char *const DataLayoutStringR600 = "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-S32-A5"; + "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1"; static const char *const DataLayoutStringAMDGCN = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6: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-S32-A5" + "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1" "-ni:7"; const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = { @@ -46,6 +46,8 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = { Constant, // opencl_constant Private, // opencl_private Generic, // opencl_generic + Global, // opencl_global_device + Global, // opencl_global_host Global, // cuda_device Constant, // cuda_constant Local, // cuda_shared @@ -61,6 +63,8 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = { Constant, // opencl_constant Private, // opencl_private Generic, // opencl_generic + Global, // opencl_global_device + Global, // opencl_global_host Global, // cuda_device Constant, // cuda_constant Local, // cuda_shared @@ -170,6 +174,9 @@ bool AMDGPUTargetInfo::initFeatureMap( // XXX - What does the member GPU mean if device name string passed here? if (isAMDGCN(getTriple())) { switch (llvm::AMDGPU::parseArchAMDGCN(CPU)) { + case GK_GFX1033: + case GK_GFX1032: + case GK_GFX1031: case GK_GFX1030: Features["ci-insts"] = true; Features["dot1-insts"] = true; @@ -216,6 +223,7 @@ bool AMDGPUTargetInfo::initFeatureMap( Features["dot1-insts"] = true; Features["dot2-insts"] = true; LLVM_FALLTHROUGH; + case GK_GFX90C: case GK_GFX909: case GK_GFX904: case GK_GFX902: @@ -223,6 +231,7 @@ bool AMDGPUTargetInfo::initFeatureMap( Features["gfx9-insts"] = true; LLVM_FALLTHROUGH; case GK_GFX810: + case GK_GFX805: case GK_GFX803: case GK_GFX802: case GK_GFX801: @@ -231,6 +240,7 @@ bool AMDGPUTargetInfo::initFeatureMap( Features["dpp"] = true; Features["s-memrealtime"] = true; LLVM_FALLTHROUGH; + case GK_GFX705: case GK_GFX704: case GK_GFX703: case GK_GFX702: @@ -239,6 +249,7 @@ bool AMDGPUTargetInfo::initFeatureMap( Features["ci-insts"] = true; Features["flat-address-space"] = true; LLVM_FALLTHROUGH; + case GK_GFX602: case GK_GFX601: case GK_GFX600: break; @@ -311,6 +322,8 @@ AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple, HasLegalHalfType = true; HasFloat16 = true; + WavefrontSize = GPUFeatures & llvm::AMDGPU::FEATURE_WAVE32 ? 32 : 64; + AllowAMDGPUUnsafeFPAtomics = Opts.AllowAMDGPUUnsafeFPAtomics; // Set pointer width and alignment for target address space 0. PointerWidth = PointerAlign = DataLayout->getPointerSizeInBits(); @@ -352,6 +365,23 @@ void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts, StringRef CanonName = isAMDGCN(getTriple()) ? getArchNameAMDGCN(GPUKind) : getArchNameR600(GPUKind); Builder.defineMacro(Twine("__") + Twine(CanonName) + Twine("__")); + if (isAMDGCN(getTriple())) { + Builder.defineMacro("__amdgcn_processor__", + Twine("\"") + Twine(CanonName) + Twine("\"")); + Builder.defineMacro("__amdgcn_target_id__", + Twine("\"") + Twine(getTargetID().getValue()) + + Twine("\"")); + for (auto F : getAllPossibleTargetIDFeatures(getTriple(), CanonName)) { + auto Loc = OffloadArchFeatures.find(F); + if (Loc != OffloadArchFeatures.end()) { + std::string NewF = F.str(); + std::replace(NewF.begin(), NewF.end(), '-', '_'); + Builder.defineMacro(Twine("__amdgcn_feature_") + Twine(NewF) + + Twine("__"), + Loc->second ? "1" : "0"); + } + } + } } // TODO: __HAS_FMAF__, __HAS_LDEXPF__, __HAS_FP64__ are deprecated and will be @@ -366,6 +396,8 @@ void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__HAS_FP64__"); if (hasFastFMA()) Builder.defineMacro("FP_FAST_FMA"); + + Builder.defineMacro("__AMDGCN_WAVEFRONT_SIZE", Twine(WavefrontSize)); } void AMDGPUTargetInfo::setAuxTarget(const TargetInfo *Aux) { diff --git a/clang/lib/Basic/Targets/AMDGPU.h b/clang/lib/Basic/Targets/AMDGPU.h index d0394492cad6..8ee0ca30d305 100644 --- a/clang/lib/Basic/Targets/AMDGPU.h +++ b/clang/lib/Basic/Targets/AMDGPU.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H #define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H +#include "clang/Basic/TargetID.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "llvm/ADT/StringSet.h" @@ -40,6 +41,15 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo { llvm::AMDGPU::GPUKind GPUKind; unsigned GPUFeatures; + unsigned WavefrontSize; + + /// Target ID is device name followed by optional feature name postfixed + /// by plus or minus sign delimitted by colon, e.g. gfx908:xnack+:sramecc-. + /// If the target ID contains feature+, map it to true. + /// If the target ID contains feature-, map it to false. + /// If the target ID does not contain a feature (default), do not map it. + llvm::StringMap<bool> OffloadArchFeatures; + std::string TargetID; bool hasFP64() const { return getTriple().getArch() == llvm::Triple::amdgcn || @@ -274,32 +284,32 @@ public: void setSupportedOpenCLOpts() override { auto &Opts = getSupportedOpenCLOpts(); - Opts.support("cl_clang_storage_class_specifiers"); - Opts.support("cl_khr_icd"); + Opts["cl_clang_storage_class_specifiers"] = true; + Opts["__cl_clang_variadic_functions"] = true; + Opts["__cl_clang_function_pointers"] = true; bool IsAMDGCN = isAMDGCN(getTriple()); - if (hasFP64()) - Opts.support("cl_khr_fp64"); + Opts["cl_khr_fp64"] = hasFP64(); if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) { - Opts.support("cl_khr_byte_addressable_store"); - Opts.support("cl_khr_global_int32_base_atomics"); - Opts.support("cl_khr_global_int32_extended_atomics"); - Opts.support("cl_khr_local_int32_base_atomics"); - Opts.support("cl_khr_local_int32_extended_atomics"); + Opts["cl_khr_byte_addressable_store"] = true; + Opts["cl_khr_global_int32_base_atomics"] = true; + Opts["cl_khr_global_int32_extended_atomics"] = true; + Opts["cl_khr_local_int32_base_atomics"] = true; + Opts["cl_khr_local_int32_extended_atomics"] = true; } if (IsAMDGCN) { - Opts.support("cl_khr_fp16"); - Opts.support("cl_khr_int64_base_atomics"); - Opts.support("cl_khr_int64_extended_atomics"); - Opts.support("cl_khr_mipmap_image"); - Opts.support("cl_khr_mipmap_image_writes"); - Opts.support("cl_khr_subgroups"); - Opts.support("cl_khr_3d_image_writes"); - Opts.support("cl_amd_media_ops"); - Opts.support("cl_amd_media_ops2"); + Opts["cl_khr_fp16"] = true; + Opts["cl_khr_int64_base_atomics"] = true; + Opts["cl_khr_int64_extended_atomics"] = true; + Opts["cl_khr_mipmap_image"] = true; + Opts["cl_khr_mipmap_image_writes"] = true; + Opts["cl_khr_subgroups"] = true; + Opts["cl_khr_3d_image_writes"] = true; + Opts["cl_amd_media_ops"] = true; + Opts["cl_amd_media_ops2"] = true; } } @@ -389,6 +399,37 @@ public: void setAuxTarget(const TargetInfo *Aux) override; bool hasExtIntType() const override { return true; } + + // Record offload arch features since they are needed for defining the + // pre-defined macros. + bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) override { + auto TargetIDFeatures = + getAllPossibleTargetIDFeatures(getTriple(), getArchNameAMDGCN(GPUKind)); + llvm::for_each(Features, [&](const auto &F) { + assert(F.front() == '+' || F.front() == '-'); + if (F == "+wavefrontsize64") + WavefrontSize = 64; + bool IsOn = F.front() == '+'; + StringRef Name = StringRef(F).drop_front(); + if (llvm::find(TargetIDFeatures, Name) == TargetIDFeatures.end()) + return; + assert(OffloadArchFeatures.find(Name) == OffloadArchFeatures.end()); + OffloadArchFeatures[Name] = IsOn; + }); + return true; + } + + Optional<std::string> getTargetID() const override { + if (!isAMDGCN(getTriple())) + return llvm::None; + // When -target-cpu is not set, we assume generic code that it is valid + // for all GPU and use an empty string as target ID to represent that. + if (GPUKind == llvm::AMDGPU::GK_NONE) + return std::string(""); + return getCanonicalTargetID(getArchNameAMDGCN(GPUKind), + OffloadArchFeatures); + } }; } // namespace targets diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp index 21cfe0107bbb..a2c96ad12a76 100644 --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -208,6 +208,8 @@ StringRef ARMTargetInfo::getCPUAttr() const { return "8_5A"; case llvm::ARM::ArchKind::ARMV8_6A: return "8_6A"; + case llvm::ARM::ArchKind::ARMV8_7A: + return "8_7A"; case llvm::ARM::ArchKind::ARMV8MBaseline: return "8M_BASE"; case llvm::ARM::ArchKind::ARMV8MMainline: diff --git a/clang/lib/Basic/Targets/AVR.cpp b/clang/lib/Basic/Targets/AVR.cpp index bb215b4114ac..664eea0de841 100644 --- a/clang/lib/Basic/Targets/AVR.cpp +++ b/clang/lib/Basic/Targets/AVR.cpp @@ -63,8 +63,10 @@ static MCUInfo AVRMcus[] = { {"attiny85", "__AVR_ATtiny85__"}, {"attiny261", "__AVR_ATtiny261__"}, {"attiny261a", "__AVR_ATtiny261A__"}, + {"attiny441", "__AVR_ATtiny441__"}, {"attiny461", "__AVR_ATtiny461__"}, {"attiny461a", "__AVR_ATtiny461A__"}, + {"attiny841", "__AVR_ATtiny841__"}, {"attiny861", "__AVR_ATtiny861__"}, {"attiny861a", "__AVR_ATtiny861A__"}, {"attiny87", "__AVR_ATtiny87__"}, @@ -92,11 +94,13 @@ static MCUInfo AVRMcus[] = { {"atmega48", "__AVR_ATmega48__"}, {"atmega48a", "__AVR_ATmega48A__"}, {"atmega48pa", "__AVR_ATmega48PA__"}, + {"atmega48pb", "__AVR_ATmega48PB__"}, {"atmega48p", "__AVR_ATmega48P__"}, {"atmega88", "__AVR_ATmega88__"}, {"atmega88a", "__AVR_ATmega88A__"}, {"atmega88p", "__AVR_ATmega88P__"}, {"atmega88pa", "__AVR_ATmega88PA__"}, + {"atmega88pb", "__AVR_ATmega88PB__"}, {"atmega8515", "__AVR_ATmega8515__"}, {"atmega8535", "__AVR_ATmega8535__"}, {"atmega8hva", "__AVR_ATmega8HVA__"}, @@ -124,6 +128,7 @@ static MCUInfo AVRMcus[] = { {"atmega168a", "__AVR_ATmega168A__"}, {"atmega168p", "__AVR_ATmega168P__"}, {"atmega168pa", "__AVR_ATmega168PA__"}, + {"atmega168pb", "__AVR_ATmega168PB__"}, {"atmega169", "__AVR_ATmega169__"}, {"atmega169a", "__AVR_ATmega169A__"}, {"atmega169p", "__AVR_ATmega169P__"}, @@ -134,6 +139,7 @@ static MCUInfo AVRMcus[] = { {"atmega324a", "__AVR_ATmega324A__"}, {"atmega324p", "__AVR_ATmega324P__"}, {"atmega324pa", "__AVR_ATmega324PA__"}, + {"atmega324pb", "__AVR_ATmega324PB__"}, {"atmega325", "__AVR_ATmega325__"}, {"atmega325a", "__AVR_ATmega325A__"}, {"atmega325p", "__AVR_ATmega325P__"}, @@ -144,6 +150,7 @@ static MCUInfo AVRMcus[] = { {"atmega3250pa", "__AVR_ATmega3250PA__"}, {"atmega328", "__AVR_ATmega328__"}, {"atmega328p", "__AVR_ATmega328P__"}, + {"atmega328pb", "__AVR_ATmega328PB__"}, {"atmega329", "__AVR_ATmega329__"}, {"atmega329a", "__AVR_ATmega329A__"}, {"atmega329p", "__AVR_ATmega329P__"}, diff --git a/clang/lib/Basic/Targets/Hexagon.cpp b/clang/lib/Basic/Targets/Hexagon.cpp index 205601c359d0..a8b4380b6a87 100644 --- a/clang/lib/Basic/Targets/Hexagon.cpp +++ b/clang/lib/Basic/Targets/Hexagon.cpp @@ -98,7 +98,8 @@ bool HexagonTargetInfo::initFeatureMap( StringRef CPUFeature = CPU; CPUFeature.consume_front("hexagon"); CPUFeature.consume_back("t"); - Features[CPUFeature] = true; + if (!CPUFeature.empty()) + Features[CPUFeature] = true; Features["long-calls"] = false; diff --git a/clang/lib/Basic/Targets/MSP430.cpp b/clang/lib/Basic/Targets/MSP430.cpp index ef53ee352c32..90890500ae27 100644 --- a/clang/lib/Basic/Targets/MSP430.cpp +++ b/clang/lib/Basic/Targets/MSP430.cpp @@ -29,5 +29,6 @@ void MSP430TargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("MSP430"); Builder.defineMacro("__MSP430__"); + Builder.defineMacro("__ELF__"); // FIXME: defines for different 'flavours' of MCU } diff --git a/clang/lib/Basic/Targets/Mips.cpp b/clang/lib/Basic/Targets/Mips.cpp index ead5e91f7c8f..3a32fd492c6b 100644 --- a/clang/lib/Basic/Targets/Mips.cpp +++ b/clang/lib/Basic/Targets/Mips.cpp @@ -41,7 +41,6 @@ bool MipsTargetInfo::processorSupportsGPR64() const { .Case("octeon", true) .Case("octeon+", true) .Default(false); - return false; } static constexpr llvm::StringLiteral ValidCPUNames[] = { diff --git a/clang/lib/Basic/Targets/NVPTX.cpp b/clang/lib/Basic/Targets/NVPTX.cpp index 18c3c8370331..b7f0dce33d2b 100644 --- a/clang/lib/Basic/Targets/NVPTX.cpp +++ b/clang/lib/Basic/Targets/NVPTX.cpp @@ -182,14 +182,17 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts, switch (GPU) { case CudaArch::GFX600: case CudaArch::GFX601: + case CudaArch::GFX602: case CudaArch::GFX700: case CudaArch::GFX701: case CudaArch::GFX702: case CudaArch::GFX703: case CudaArch::GFX704: + case CudaArch::GFX705: case CudaArch::GFX801: case CudaArch::GFX802: case CudaArch::GFX803: + case CudaArch::GFX805: case CudaArch::GFX810: case CudaArch::GFX900: case CudaArch::GFX902: @@ -197,12 +200,17 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts, case CudaArch::GFX906: case CudaArch::GFX908: case CudaArch::GFX909: + case CudaArch::GFX90c: case CudaArch::GFX1010: case CudaArch::GFX1011: case CudaArch::GFX1012: case CudaArch::GFX1030: + case CudaArch::GFX1031: + case CudaArch::GFX1032: + case CudaArch::GFX1033: case CudaArch::LAST: break; + case CudaArch::UNUSED: case CudaArch::UNKNOWN: assert(false && "No GPU arch when compiling CUDA device code."); return ""; diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h index f57a0f18efa3..038dec4a28bd 100644 --- a/clang/lib/Basic/Targets/NVPTX.h +++ b/clang/lib/Basic/Targets/NVPTX.h @@ -30,6 +30,8 @@ static const unsigned NVPTXAddrSpaceMap[] = { 0, // opencl_private // FIXME: generic has to be added to the target 0, // opencl_generic + 1, // opencl_global_device + 1, // opencl_global_host 1, // cuda_device 4, // cuda_constant 3, // cuda_shared @@ -125,16 +127,16 @@ public: void setSupportedOpenCLOpts() override { auto &Opts = getSupportedOpenCLOpts(); - Opts.support("cl_clang_storage_class_specifiers"); - Opts.support("cl_khr_gl_sharing"); - Opts.support("cl_khr_icd"); - - Opts.support("cl_khr_fp64"); - Opts.support("cl_khr_byte_addressable_store"); - Opts.support("cl_khr_global_int32_base_atomics"); - Opts.support("cl_khr_global_int32_extended_atomics"); - Opts.support("cl_khr_local_int32_base_atomics"); - Opts.support("cl_khr_local_int32_extended_atomics"); + Opts["cl_clang_storage_class_specifiers"] = true; + Opts["__cl_clang_function_pointers"] = true; + Opts["__cl_clang_variadic_functions"] = true; + + Opts["cl_khr_fp64"] = true; + Opts["cl_khr_byte_addressable_store"] = true; + Opts["cl_khr_global_int32_base_atomics"] = true; + Opts["cl_khr_global_int32_extended_atomics"] = true; + Opts["cl_khr_local_int32_base_atomics"] = true; + Opts["cl_khr_local_int32_extended_atomics"] = true; } /// \returns If a target requires an address within a target specific address diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index cfa362bef1b1..67fa1a537fea 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -154,7 +154,8 @@ public: MinVersion = llvm::VersionTuple(5U); break; default: - llvm_unreachable("Unexpected OS"); + // Conservatively return 8 bytes if OS is unknown. + return 64; } unsigned Major, Minor, Micro; @@ -252,6 +253,7 @@ public: case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: this->MCountName = "_mcount"; @@ -382,8 +384,12 @@ protected: Triple.getEnvironmentVersion(Maj, Min, Rev); this->PlatformName = "android"; this->PlatformMinVersion = VersionTuple(Maj, Min, Rev); - if (Maj) - Builder.defineMacro("__ANDROID_API__", Twine(Maj)); + if (Maj) { + Builder.defineMacro("__ANDROID_MIN_SDK_VERSION__", Twine(Maj)); + // This historical but ambiguous name for the minSdkVersion macro. Keep + // defined for compatibility. + Builder.defineMacro("__ANDROID_API__", "__ANDROID_MIN_SDK_VERSION__"); + } } else { Builder.defineMacro("__gnu_linux__"); } @@ -408,6 +414,7 @@ public: case llvm::Triple::mips64: case llvm::Triple::mips64el: case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: this->MCountName = "_mcount"; @@ -465,6 +472,9 @@ protected: public: OpenBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : OSTargetInfo<Target>(Triple, Opts) { + this->WCharType = this->WIntType = this->SignedInt; + this->IntMaxType = TargetInfo::SignedLongLong; + this->Int64Type = TargetInfo::SignedLongLong; switch (Triple.getArch()) { case llvm::Triple::x86: case llvm::Triple::x86_64: @@ -476,6 +486,8 @@ public: case llvm::Triple::mips64: case llvm::Triple::mips64el: case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: case llvm::Triple::sparcv9: this->MCountName = "_mcount"; break; @@ -668,6 +680,9 @@ protected: Builder.defineMacro("_AIX"); + if (Opts.EnableAIXExtendedAltivecABI) + Builder.defineMacro("__EXTABI__"); + unsigned Major, Minor, Micro; Triple.getOSVersion(Major, Minor, Micro); @@ -719,6 +734,66 @@ public: // AIX sets FLT_EVAL_METHOD to be 1. unsigned getFloatEvalMethod() const override { return 1; } bool hasInt128Type() const override { return false; } + + bool defaultsToAIXPowerAlignment() const override { return true; } +}; + +// z/OS target +template <typename Target> +class LLVM_LIBRARY_VISIBILITY ZOSTargetInfo : public OSTargetInfo<Target> { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + // FIXME: _LONG_LONG should not be defined under -std=c89. + Builder.defineMacro("_LONG_LONG"); + Builder.defineMacro("_OPEN_DEFAULT"); + // _UNIX03_WITHDRAWN is required to build libcxx. + Builder.defineMacro("_UNIX03_WITHDRAWN"); + Builder.defineMacro("__370__"); + Builder.defineMacro("__BFP__"); + // FIXME: __BOOL__ should not be defined under -std=c89. + Builder.defineMacro("__BOOL__"); + Builder.defineMacro("__LONGNAME__"); + Builder.defineMacro("__MVS__"); + Builder.defineMacro("__THW_370__"); + Builder.defineMacro("__THW_BIG_ENDIAN__"); + Builder.defineMacro("__TOS_390__"); + Builder.defineMacro("__TOS_MVS__"); + Builder.defineMacro("__XPLINK__"); + + if (this->PointerWidth == 64) + Builder.defineMacro("__64BIT__"); + + if (Opts.CPlusPlus) { + Builder.defineMacro("__DLL__"); + // _XOPEN_SOURCE=600 is required to build libcxx. + Builder.defineMacro("_XOPEN_SOURCE", "600"); + } + + if (Opts.GNUMode) { + Builder.defineMacro("_MI_BUILTIN"); + Builder.defineMacro("_EXT"); + } + + if (Opts.CPlusPlus && Opts.WChar) { + // Macro __wchar_t is defined so that the wchar_t data + // type is not declared as a typedef in system headers. + Builder.defineMacro("__wchar_t"); + } + + this->PlatformName = llvm::Triple::getOSTypeName(Triple.getOS()); + } + +public: + ZOSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OSTargetInfo<Target>(Triple, Opts) { + this->WCharType = TargetInfo::UnsignedInt; + this->UseBitFieldTypeAlignment = false; + this->UseZeroLengthBitfieldAlignment = true; + this->ZeroLengthBitfieldBoundary = 32; + this->MinGlobalAlign = 0; + this->DefaultAlignForAttributeAligned = 128; + } }; void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index f0de2bf070ea..cfede6e6e756 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -46,8 +46,6 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasP8Crypto = true; } else if (Feature == "+direct-move") { HasDirectMove = true; - } else if (Feature == "+qpx") { - HasQPX = true; } else if (Feature == "+htm") { HasHTM = true; } else if (Feature == "+float128") { @@ -58,12 +56,16 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasP10Vector = true; } else if (Feature == "+pcrelative-memops") { HasPCRelativeMemops = true; - } else if (Feature == "+spe") { + } else if (Feature == "+spe" || Feature == "+efpu2") { HasSPE = true; LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); } else if (Feature == "-hard-float") { FloatABI = SoftFloat; + } else if (Feature == "+paired-vector-memops") { + PairedVectorMemops = true; + } else if (Feature == "+mma") { + HasMMA = true; } // TODO: Finish this list and add an assert that we've handled them // all. @@ -90,7 +92,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, } // Target properties. - if (getTriple().getArch() == llvm::Triple::ppc64le) { + if (getTriple().getArch() == llvm::Triple::ppc64le || + getTriple().getArch() == llvm::Triple::ppcle) { Builder.defineMacro("_LITTLE_ENDIAN"); } else { if (!getTriple().isOSNetBSD() && @@ -99,7 +102,7 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, } // ABI options. - if (ABI == "elfv1" || ABI == "elfv1-qpx") + if (ABI == "elfv1") Builder.defineMacro("_CALL_ELF", "1"); if (ABI == "elfv2") Builder.defineMacro("_CALL_ELF", "2"); @@ -120,6 +123,10 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, if (LongDoubleWidth == 128) { Builder.defineMacro("__LONG_DOUBLE_128__"); Builder.defineMacro("__LONGDOUBLE128"); + if (Opts.PPCIEEELongDouble) + Builder.defineMacro("__LONG_DOUBLE_IEEE128__"); + else + Builder.defineMacro("__LONG_DOUBLE_IBM128__"); } // Define this for elfv2 (64-bit only) or 64-bit darwin. @@ -159,22 +166,11 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("_ARCH_PWR10"); if (ArchDefs & ArchDefineA2) Builder.defineMacro("_ARCH_A2"); - if (ArchDefs & ArchDefineA2q) { - Builder.defineMacro("_ARCH_A2Q"); - Builder.defineMacro("_ARCH_QP"); - } if (ArchDefs & ArchDefineE500) Builder.defineMacro("__NO_LWSYNC__"); if (ArchDefs & ArchDefineFuture) Builder.defineMacro("_ARCH_PWR_FUTURE"); - if (getTriple().getVendor() == llvm::Triple::BGQ) { - Builder.defineMacro("__bg__"); - Builder.defineMacro("__THW_BLUEGENE__"); - Builder.defineMacro("__bgq__"); - Builder.defineMacro("__TOS_BGQ__"); - } - if (HasAltivec) { Builder.defineMacro("__VEC__", "10206"); Builder.defineMacro("__ALTIVEC__"); @@ -195,6 +191,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__FLOAT128__"); if (HasP9Vector) Builder.defineMacro("__POWER9_VECTOR__"); + if (HasMMA) + Builder.defineMacro("__MMA__"); if (HasP10Vector) Builder.defineMacro("__POWER10_VECTOR__"); @@ -231,6 +229,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, // - direct-move // - float128 // - power9-vector +// - paired-vector-memops +// - mma // - power10-vector // then go ahead and error since the customer has expressed an incompatible // set of options. @@ -253,6 +253,8 @@ static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags, Found |= FindVSXSubfeature("+direct-move", "-mdirect-move"); Found |= FindVSXSubfeature("+float128", "-mfloat128"); Found |= FindVSXSubfeature("+power9-vector", "-mpower9-vector"); + Found |= FindVSXSubfeature("+paired-vector-memops", "-mpaired-vector-memops"); + Found |= FindVSXSubfeature("+mma", "-mmma"); Found |= FindVSXSubfeature("+power10-vector", "-mpower10-vector"); // Return false if any vsx subfeatures was found. @@ -277,7 +279,6 @@ bool PPCTargetInfo::initFeatureMap( .Case("ppc64le", true) .Default(false); - Features["qpx"] = (CPU == "a2q"); Features["power9-vector"] = (CPU == "pwr9"); Features["crypto"] = llvm::StringSwitch<bool>(CPU) .Case("ppc64le", true) @@ -317,6 +318,9 @@ bool PPCTargetInfo::initFeatureMap( .Case("pwr9", true) .Case("pwr8", true) .Default(false); + Features["float128"] = llvm::StringSwitch<bool>(CPU) + .Case("pwr9", true) + .Default(false); Features["spe"] = llvm::StringSwitch<bool>(CPU) .Case("8548", true) @@ -347,6 +351,13 @@ bool PPCTargetInfo::initFeatureMap( return false; } + if (!(ArchDefs & ArchDefinePwr10) && + llvm::find(FeaturesVec, "+mma") != FeaturesVec.end()) { + // We have MMA on PPC but not power 10 and above. + Diags.Report(diag::err_opt_not_valid_with_opt) << "-mmma" << CPU; + return false; + } + return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); } @@ -354,6 +365,8 @@ bool PPCTargetInfo::initFeatureMap( void PPCTargetInfo::addP10SpecificFeatures( llvm::StringMap<bool> &Features) const { Features["htm"] = false; // HTM was removed for P10. + Features["paired-vector-memops"] = true; + Features["mma"] = true; Features["power10-vector"] = true; Features["pcrelative-memops"] = true; return; @@ -373,21 +386,24 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const { .Case("power8-vector", HasP8Vector) .Case("crypto", HasP8Crypto) .Case("direct-move", HasDirectMove) - .Case("qpx", HasQPX) .Case("htm", HasHTM) .Case("bpermd", HasBPERMD) .Case("extdiv", HasExtDiv) .Case("float128", HasFloat128) .Case("power9-vector", HasP9Vector) + .Case("paired-vector-memops", PairedVectorMemops) .Case("power10-vector", HasP10Vector) .Case("pcrelative-memops", HasPCRelativeMemops) .Case("spe", HasSPE) + .Case("mma", HasMMA) .Default(false); } void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, bool Enabled) const { if (Enabled) { + if (Name == "efpu2") + Features["spe"] = true; // If we're enabling any of the vsx based features then enable vsx and // altivec. We'll diagnose any problems later. bool FeatureHasVSX = llvm::StringSwitch<bool>(Name) @@ -395,8 +411,10 @@ void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, .Case("direct-move", true) .Case("power8-vector", true) .Case("power9-vector", true) + .Case("paired-vector-memops", true) .Case("power10-vector", true) .Case("float128", true) + .Case("mma", true) .Default(false); if (FeatureHasVSX) Features["vsx"] = Features["altivec"] = true; @@ -409,16 +427,21 @@ void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, else Features[Name] = true; } else { + if (Name == "spe") + Features["efpu2"] = false; // If we're disabling altivec or vsx go ahead and disable all of the vsx // features. if ((Name == "altivec") || (Name == "vsx")) Features["vsx"] = Features["direct-move"] = Features["power8-vector"] = Features["float128"] = Features["power9-vector"] = - Features["power10-vector"] = false; + Features["paired-vector-memops"] = Features["mma"] = + Features["power10-vector"] = false; if (Name == "power8-vector") - Features["power9-vector"] = Features["power10-vector"] = false; + Features["power9-vector"] = Features["paired-vector-memops"] = + Features["mma"] = Features["power10-vector"] = false; else if (Name == "power9-vector") - Features["power10-vector"] = false; + Features["paired-vector-memops"] = Features["mma"] = + Features["power10-vector"] = false; if (Name == "pcrel") Features["pcrelative-memops"] = false; else @@ -503,17 +526,17 @@ ArrayRef<TargetInfo::AddlRegName> PPCTargetInfo::getGCCAddlRegNames() const { } static constexpr llvm::StringLiteral ValidCPUNames[] = { - {"generic"}, {"440"}, {"450"}, {"601"}, {"602"}, - {"603"}, {"603e"}, {"603ev"}, {"604"}, {"604e"}, - {"620"}, {"630"}, {"g3"}, {"7400"}, {"g4"}, - {"7450"}, {"g4+"}, {"750"}, {"8548"}, {"970"}, - {"g5"}, {"a2"}, {"a2q"}, {"e500"}, {"e500mc"}, - {"e5500"}, {"power3"}, {"pwr3"}, {"power4"}, {"pwr4"}, - {"power5"}, {"pwr5"}, {"power5x"}, {"pwr5x"}, {"power6"}, - {"pwr6"}, {"power6x"}, {"pwr6x"}, {"power7"}, {"pwr7"}, - {"power8"}, {"pwr8"}, {"power9"}, {"pwr9"}, {"power10"}, - {"pwr10"}, {"powerpc"}, {"ppc"}, {"powerpc64"}, {"ppc64"}, - {"powerpc64le"}, {"ppc64le"}, {"future"}}; + {"generic"}, {"440"}, {"450"}, {"601"}, {"602"}, + {"603"}, {"603e"}, {"603ev"}, {"604"}, {"604e"}, + {"620"}, {"630"}, {"g3"}, {"7400"}, {"g4"}, + {"7450"}, {"g4+"}, {"750"}, {"8548"}, {"970"}, + {"g5"}, {"a2"}, {"e500"}, {"e500mc"}, {"e5500"}, + {"power3"}, {"pwr3"}, {"power4"}, {"pwr4"}, {"power5"}, + {"pwr5"}, {"power5x"}, {"pwr5x"}, {"power6"}, {"pwr6"}, + {"power6x"}, {"pwr6x"}, {"power7"}, {"pwr7"}, {"power8"}, + {"pwr8"}, {"power9"}, {"pwr9"}, {"power10"}, {"pwr10"}, + {"powerpc"}, {"ppc"}, {"powerpc64"}, {"ppc64"}, {"powerpc64le"}, + {"ppc64le"}, {"future"}}; bool PPCTargetInfo::isValidCPUName(StringRef Name) const { return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames); diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index 858059bacb86..56c8f33ef221 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -46,7 +46,6 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { ArchDefinePwr10 = 1 << 14, ArchDefineFuture = 1 << 15, ArchDefineA2 = 1 << 16, - ArchDefineA2q = 1 << 17, ArchDefineE500 = 1 << 18 } ArchDefineTypes; @@ -59,16 +58,17 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { // Target cpu features. bool HasAltivec = false; + bool HasMMA = false; bool HasVSX = false; bool HasP8Vector = false; bool HasP8Crypto = false; bool HasDirectMove = false; - bool HasQPX = false; bool HasHTM = false; bool HasBPERMD = false; bool HasExtDiv = false; bool HasP9Vector = false; bool HasSPE = false; + bool PairedVectorMemops = false; bool HasP10Vector = false; bool HasPCRelativeMemops = false; @@ -82,6 +82,7 @@ public: SimdDefaultAlign = 128; LongDoubleWidth = LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble(); + HasStrictFP = true; } // Set the language option for altivec based on our value. @@ -118,7 +119,6 @@ public: .Case("970", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) .Case("a2", ArchDefineA2) - .Case("a2q", ArchDefineName | ArchDefineA2 | ArchDefineA2q) .Cases("power3", "pwr3", ArchDefinePpcgr) .Cases("power4", "pwr4", ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) @@ -355,6 +355,8 @@ public: : PPCTargetInfo(Triple, Opts) { if (Triple.isOSAIX()) resetDataLayout("E-m:a-p:32:32-i64:64-n32"); + else if (Triple.getArch() == llvm::Triple::ppcle) + resetDataLayout("e-m:e-p:32:32-i64:64-n32"); else resetDataLayout("E-m:e-p:32:32-i64:64-n32"); @@ -370,14 +372,16 @@ public: SizeType = UnsignedLong; PtrDiffType = SignedLong; IntPtrType = SignedLong; - SuitableAlign = 64; + LongDoubleWidth = 64; + LongDoubleAlign = DoubleAlign = 32; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); break; default: break; } if (Triple.isOSFreeBSD() || Triple.isOSNetBSD() || Triple.isOSOpenBSD() || - Triple.getOS() == llvm::Triple::AIX || Triple.isMusl()) { + Triple.isMusl()) { LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); } @@ -401,25 +405,31 @@ public: LongWidth = LongAlign = PointerWidth = PointerAlign = 64; IntMaxType = SignedLong; Int64Type = SignedLong; + std::string DataLayout = ""; if (Triple.isOSAIX()) { // TODO: Set appropriate ABI for AIX platform. - resetDataLayout("E-m:a-i64:64-n32:64"); - SuitableAlign = 64; + DataLayout = "E-m:a-i64:64-n32:64"; + LongDoubleWidth = 64; + LongDoubleAlign = DoubleAlign = 32; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); } else if ((Triple.getArch() == llvm::Triple::ppc64le)) { - resetDataLayout("e-m:e-i64:64-n32:64"); + DataLayout = "e-m:e-i64:64-n32:64"; ABI = "elfv2"; } else { - resetDataLayout("E-m:e-i64:64-n32:64"); + DataLayout = "E-m:e-i64:64-n32:64"; ABI = "elfv1"; } - if (Triple.isOSFreeBSD() || Triple.getOS() == llvm::Triple::AIX || - Triple.isMusl()) { + if (Triple.isOSFreeBSD() || Triple.isOSOpenBSD() || Triple.isMusl()) { LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); } + if (Triple.isOSAIX() || Triple.isOSLinux()) + DataLayout += "-v256:256:256-v512:512:512"; + resetDataLayout(DataLayout); + // PPC64 supports atomics up to 8 bytes. MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; } @@ -430,7 +440,7 @@ public: // PPC64 Linux-specific ABI options. bool setABI(const std::string &Name) override { - if (Name == "elfv1" || Name == "elfv1-qpx" || Name == "elfv2") { + if (Name == "elfv1" || Name == "elfv2") { ABI = Name; return true; } diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 522776437cd2..0bf02e605740 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -13,6 +13,7 @@ #include "RISCV.h" #include "clang/Basic/MacroBuilder.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/TargetParser.h" using namespace clang; using namespace clang::targets; @@ -108,26 +109,92 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, if (ABIName == "ilp32e") Builder.defineMacro("__riscv_abi_rve"); + Builder.defineMacro("__riscv_arch_test"); + Builder.defineMacro("__riscv_i", "2000000"); + if (HasM) { + Builder.defineMacro("__riscv_m", "2000000"); Builder.defineMacro("__riscv_mul"); Builder.defineMacro("__riscv_div"); Builder.defineMacro("__riscv_muldiv"); } - if (HasA) + if (HasA) { + Builder.defineMacro("__riscv_a", "2000000"); Builder.defineMacro("__riscv_atomic"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); + if (Is64Bit) + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); + } if (HasF || HasD) { + Builder.defineMacro("__riscv_f", "2000000"); Builder.defineMacro("__riscv_flen", HasD ? "64" : "32"); Builder.defineMacro("__riscv_fdiv"); Builder.defineMacro("__riscv_fsqrt"); } - if (HasC) + if (HasD) + Builder.defineMacro("__riscv_d", "2000000"); + + if (HasC) { + Builder.defineMacro("__riscv_c", "2000000"); Builder.defineMacro("__riscv_compressed"); + } - if (HasB) + if (HasB) { + Builder.defineMacro("__riscv_b", "93000"); Builder.defineMacro("__riscv_bitmanip"); + } + + if (HasV) { + Builder.defineMacro("__riscv_v", "1000000"); + Builder.defineMacro("__riscv_vector"); + } + + if (HasZba) + Builder.defineMacro("__riscv_zba", "93000"); + + if (HasZbb) + Builder.defineMacro("__riscv_zbb", "93000"); + + if (HasZbc) + Builder.defineMacro("__riscv_zbc", "93000"); + + if (HasZbe) + Builder.defineMacro("__riscv_zbe", "93000"); + + if (HasZbf) + Builder.defineMacro("__riscv_zbf", "93000"); + + if (HasZbm) + Builder.defineMacro("__riscv_zbm", "93000"); + + if (HasZbp) + Builder.defineMacro("__riscv_zbp", "93000"); + + if (HasZbproposedc) + Builder.defineMacro("__riscv_zbproposedc", "93000"); + + if (HasZbr) + Builder.defineMacro("__riscv_zbr", "93000"); + + if (HasZbs) + Builder.defineMacro("__riscv_zbs", "93000"); + + if (HasZbt) + Builder.defineMacro("__riscv_zbt", "93000"); + + if (HasZfh) + Builder.defineMacro("__riscv_zfh", "1000"); + + if (HasZvamo) + Builder.defineMacro("__riscv_zvamo", "1000000"); + + if (HasZvlsseg) + Builder.defineMacro("__riscv_zvlsseg", "1000000"); } /// Return true if has this feature, need to sync with handleTargetFeatures. @@ -143,6 +210,21 @@ bool RISCVTargetInfo::hasFeature(StringRef Feature) const { .Case("d", HasD) .Case("c", HasC) .Case("experimental-b", HasB) + .Case("experimental-v", HasV) + .Case("experimental-zba", HasZba) + .Case("experimental-zbb", HasZbb) + .Case("experimental-zbc", HasZbc) + .Case("experimental-zbe", HasZbe) + .Case("experimental-zbf", HasZbf) + .Case("experimental-zbm", HasZbm) + .Case("experimental-zbp", HasZbp) + .Case("experimental-zbproposedc", HasZbproposedc) + .Case("experimental-zbr", HasZbr) + .Case("experimental-zbs", HasZbs) + .Case("experimental-zbt", HasZbt) + .Case("experimental-zfh", HasZfh) + .Case("experimental-zvamo", HasZvamo) + .Case("experimental-zvlsseg", HasZvlsseg) .Default(false); } @@ -162,7 +244,79 @@ bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasC = true; else if (Feature == "+experimental-b") HasB = true; + else if (Feature == "+experimental-v") + HasV = true; + else if (Feature == "+experimental-zba") + HasZba = true; + else if (Feature == "+experimental-zbb") + HasZbb = true; + else if (Feature == "+experimental-zbc") + HasZbc = true; + else if (Feature == "+experimental-zbe") + HasZbe = true; + else if (Feature == "+experimental-zbf") + HasZbf = true; + else if (Feature == "+experimental-zbm") + HasZbm = true; + else if (Feature == "+experimental-zbp") + HasZbp = true; + else if (Feature == "+experimental-zbproposedc") + HasZbproposedc = true; + else if (Feature == "+experimental-zbr") + HasZbr = true; + else if (Feature == "+experimental-zbs") + HasZbs = true; + else if (Feature == "+experimental-zbt") + HasZbt = true; + else if (Feature == "+experimental-zfh") + HasZfh = true; + else if (Feature == "+experimental-zvamo") + HasZvamo = true; + else if (Feature == "+experimental-zvlsseg") + HasZvlsseg = true; } return true; } + +bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const { + return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), + /*Is64Bit=*/false); +} + +void RISCV32TargetInfo::fillValidCPUList( + SmallVectorImpl<StringRef> &Values) const { + llvm::RISCV::fillValidCPUArchList(Values, false); +} + +bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const { + return llvm::RISCV::checkTuneCPUKind( + llvm::RISCV::parseTuneCPUKind(Name, false), + /*Is64Bit=*/false); +} + +void RISCV32TargetInfo::fillValidTuneCPUList( + SmallVectorImpl<StringRef> &Values) const { + llvm::RISCV::fillValidTuneCPUArchList(Values, false); +} + +bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const { + return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), + /*Is64Bit=*/true); +} + +void RISCV64TargetInfo::fillValidCPUList( + SmallVectorImpl<StringRef> &Values) const { + llvm::RISCV::fillValidCPUArchList(Values, true); +} + +bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const { + return llvm::RISCV::checkTuneCPUKind( + llvm::RISCV::parseTuneCPUKind(Name, true), + /*Is64Bit=*/true); +} + +void RISCV64TargetInfo::fillValidTuneCPUList( + SmallVectorImpl<StringRef> &Values) const { + llvm::RISCV::fillValidTuneCPUArchList(Values, true); +} diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index 73652b409e9c..f1e9215b2d17 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -24,18 +24,32 @@ namespace targets { // RISC-V Target class RISCVTargetInfo : public TargetInfo { protected: - std::string ABI; - bool HasM; - bool HasA; - bool HasF; - bool HasD; - bool HasC; - bool HasB; + std::string ABI, CPU; + bool HasM = false; + bool HasA = false; + bool HasF = false; + bool HasD = false; + bool HasC = false; + bool HasB = false; + bool HasV = false; + bool HasZba = false; + bool HasZbb = false; + bool HasZbc = false; + bool HasZbe = false; + bool HasZbf = false; + bool HasZbm = false; + bool HasZbp = false; + bool HasZbproposedc = false; + bool HasZbr = false; + bool HasZbs = false; + bool HasZbt = false; + bool HasZfh = false; + bool HasZvamo = false; + bool HasZvlsseg = false; public: RISCVTargetInfo(const llvm::Triple &Triple, const TargetOptions &) - : TargetInfo(Triple), HasM(false), HasA(false), HasF(false), - HasD(false), HasC(false), HasB(false) { + : TargetInfo(Triple) { LongDoubleWidth = 128; LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::IEEEquad(); @@ -44,6 +58,13 @@ public: WIntType = UnsignedInt; } + bool setCPU(const std::string &Name) override { + if (!isValidCPUName(Name)) + return false; + CPU = Name; + return true; + } + StringRef getABI() const override { return ABI; } void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; @@ -97,6 +118,11 @@ public: return false; } + bool isValidCPUName(StringRef Name) const override; + void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; + bool isValidTuneCPUName(StringRef Name) const override; + void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override; + void setMaxAtomicWidth() override { MaxAtomicPromoteWidth = 128; @@ -121,6 +147,11 @@ public: return false; } + bool isValidCPUName(StringRef Name) const override; + void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; + bool isValidTuneCPUName(StringRef Name) const override; + void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override; + void setMaxAtomicWidth() override { MaxAtomicPromoteWidth = 128; diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index f625d4980e29..a2e812624d37 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -28,6 +28,8 @@ static const unsigned SPIRAddrSpaceMap[] = { 2, // opencl_constant 0, // opencl_private 4, // opencl_generic + 5, // opencl_global_device + 6, // opencl_global_host 0, // cuda_device 0, // cuda_constant 0, // cuda_shared @@ -98,10 +100,12 @@ public: void setSupportedOpenCLOpts() override { // Assume all OpenCL extensions and optional core features are supported // for SPIR since it is a generic target. - getSupportedOpenCLOpts().supportAll(); + supportAllOpenCLOpts(); } bool hasExtIntType() const override { return true; } + + bool hasInt128Type() const override { return false; } }; class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo { public: diff --git a/clang/lib/Basic/Targets/Sparc.cpp b/clang/lib/Basic/Targets/Sparc.cpp index 13aa964d4716..5eeb77406c34 100644 --- a/clang/lib/Basic/Targets/Sparc.cpp +++ b/clang/lib/Basic/Targets/Sparc.cpp @@ -147,19 +147,20 @@ void SparcTargetInfo::getTargetDefines(const LangOptions &Opts, void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { SparcTargetInfo::getTargetDefines(Opts, Builder); - switch (getCPUGeneration(CPU)) { - case CG_V8: + if (getTriple().getOS() == llvm::Triple::Solaris) Builder.defineMacro("__sparcv8"); - if (getTriple().getOS() != llvm::Triple::Solaris) + else { + switch (getCPUGeneration(CPU)) { + case CG_V8: + Builder.defineMacro("__sparcv8"); Builder.defineMacro("__sparcv8__"); - break; - case CG_V9: - Builder.defineMacro("__sparcv9"); - if (getTriple().getOS() != llvm::Triple::Solaris) { + break; + case CG_V9: + Builder.defineMacro("__sparcv9"); Builder.defineMacro("__sparcv9__"); Builder.defineMacro("__sparc_v9__"); + break; } - break; } if (getTriple().getVendor() == llvm::Triple::Myriad) { std::string MyriadArchValue, Myriad2Value; @@ -227,6 +228,12 @@ void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__myriad2__", Myriad2Value); Builder.defineMacro("__myriad2", Myriad2Value); } + if (getCPUGeneration(CPU) == CG_V9) { + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); + } } void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts, @@ -240,6 +247,11 @@ void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__sparc_v9__"); Builder.defineMacro("__sparcv9__"); } + + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); } void SparcV9TargetInfo::fillValidCPUList( diff --git a/clang/lib/Basic/Targets/Sparc.h b/clang/lib/Basic/Targets/Sparc.h index d24cf15d7cd6..07844abafe11 100644 --- a/clang/lib/Basic/Targets/Sparc.h +++ b/clang/lib/Basic/Targets/Sparc.h @@ -166,10 +166,15 @@ public: PtrDiffType = SignedLong; break; } - // Up to 32 bits are lock-free atomic, but we're willing to do atomic ops - // on up to 64 bits. + // Up to 32 bits (V8) or 64 bits (V9) are lock-free atomic, but we're + // willing to do atomic ops on up to 64 bits. MaxAtomicPromoteWidth = 64; - MaxAtomicInlineWidth = 32; + if (getCPUGeneration(CPU) == CG_V9) + MaxAtomicInlineWidth = 64; + else + // FIXME: This isn't correct for plain V8 which lacks CAS, + // only for LEON 3+ and Myriad. + MaxAtomicInlineWidth = 32; } void getTargetDefines(const LangOptions &Opts, diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index d7869e3754a8..39fdcf90d0c8 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -157,6 +157,10 @@ public: const char *getLongDoubleMangling() const override { return "g"; } bool hasExtIntType() const override { return true; } + + int getEHDataRegisterNumber(unsigned RegNo) const override { + return RegNo < 4 ? 6 + RegNo : -1; + } }; } // namespace targets } // namespace clang diff --git a/clang/lib/Basic/Targets/TCE.h b/clang/lib/Basic/Targets/TCE.h index 9cbf2a3688a2..445fe4fe7293 100644 --- a/clang/lib/Basic/Targets/TCE.h +++ b/clang/lib/Basic/Targets/TCE.h @@ -35,6 +35,8 @@ static const unsigned TCEOpenCLAddrSpaceMap[] = { 4, // opencl_local 5, // opencl_constant 0, // opencl_private + 1, // opencl_global_device + 1, // opencl_global_host // FIXME: generic has to be added to the target 0, // opencl_generic 0, // cuda_device diff --git a/clang/lib/Basic/Targets/VE.h b/clang/lib/Basic/Targets/VE.h index f863a0af0acb..71d6fc08d859 100644 --- a/clang/lib/Basic/Targets/VE.h +++ b/clang/lib/Basic/Targets/VE.h @@ -45,16 +45,15 @@ public: WCharType = UnsignedInt; WIntType = UnsignedInt; UseZeroLengthBitfieldAlignment = true; - resetDataLayout("e-m:e-i64:64-n32:64-S128"); + resetDataLayout( + "e-m:e-i64:64-n32:64-S128-v64:64:64-v128:64:64-v256:64:64-v512:64:64-" + "v1024:64:64-v2048:64:64-v4096:64:64-v8192:64:64-v16384:64:64"); } void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - bool hasSjLjLowering() const override { - // TODO - return false; - } + bool hasSjLjLowering() const override { return true; } ArrayRef<Builtin::Info> getTargetBuiltins() const override; @@ -160,6 +159,13 @@ public: bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const override { + switch (*Name) { + default: + return false; + case 'v': + Info.setAllowsRegister(); + return true; + } return false; } diff --git a/clang/lib/Basic/Targets/WebAssembly.cpp b/clang/lib/Basic/Targets/WebAssembly.cpp index 6746768090f5..dcb3d8fd7790 100644 --- a/clang/lib/Basic/Targets/WebAssembly.cpp +++ b/clang/lib/Basic/Targets/WebAssembly.cpp @@ -96,19 +96,43 @@ void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts, } void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features, - SIMDEnum Level) { + SIMDEnum Level, bool Enabled) { + if (Enabled) { + switch (Level) { + case UnimplementedSIMD128: + Features["unimplemented-simd128"] = true; + LLVM_FALLTHROUGH; + case SIMD128: + Features["simd128"] = true; + LLVM_FALLTHROUGH; + case NoSIMD: + break; + } + return; + } + switch (Level) { - case UnimplementedSIMD128: - Features["unimplemented-simd128"] = true; - LLVM_FALLTHROUGH; + case NoSIMD: case SIMD128: - Features["simd128"] = true; + Features["simd128"] = false; LLVM_FALLTHROUGH; - case NoSIMD: + case UnimplementedSIMD128: + Features["unimplemented-simd128"] = false; break; } } +void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, + StringRef Name, + bool Enabled) const { + if (Name == "simd128") + setSIMDLevel(Features, SIMD128, Enabled); + else if (Name == "unimplemented-simd128") + setSIMDLevel(Features, UnimplementedSIMD128, Enabled); + else + Features[Name] = Enabled; +} + bool WebAssemblyTargetInfo::initFeatureMap( llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector<std::string> &FeaturesVec) const { @@ -119,30 +143,8 @@ bool WebAssemblyTargetInfo::initFeatureMap( Features["atomics"] = true; Features["mutable-globals"] = true; Features["tail-call"] = true; - setSIMDLevel(Features, SIMD128); + setSIMDLevel(Features, SIMD128, true); } - // Other targets do not consider user-configured features here, but while we - // are actively developing new features it is useful to let user-configured - // features control availability of builtins - setSIMDLevel(Features, SIMDLevel); - if (HasNontrappingFPToInt) - Features["nontrapping-fptoint"] = true; - if (HasSignExt) - Features["sign-ext"] = true; - if (HasExceptionHandling) - Features["exception-handling"] = true; - if (HasBulkMemory) - Features["bulk-memory"] = true; - if (HasAtomics) - Features["atomics"] = true; - if (HasMutableGlobals) - Features["mutable-globals"] = true; - if (HasMultivalue) - Features["multivalue"] = true; - if (HasTailCall) - Features["tail-call"] = true; - if (HasReferenceTypes) - Features["reference-types"] = true; return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); } diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h index 77a2fe9ae117..0068ccb5d71f 100644 --- a/clang/lib/Basic/Targets/WebAssembly.h +++ b/clang/lib/Basic/Targets/WebAssembly.h @@ -69,7 +69,8 @@ protected: MacroBuilder &Builder) const override; private: - static void setSIMDLevel(llvm::StringMap<bool> &Features, SIMDEnum Level); + static void setSIMDLevel(llvm::StringMap<bool> &Features, SIMDEnum Level, + bool Enabled); bool initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, @@ -77,6 +78,9 @@ private: const std::vector<std::string> &FeaturesVec) const override; bool hasFeature(StringRef Feature) const final; + void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, + bool Enabled) const final; + bool handleTargetFeatures(std::vector<std::string> &Features, DiagnosticsEngine &Diags) final; diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 543f232d2459..694a8095e336 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -159,11 +159,7 @@ void X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, } Features[Name] = Enabled; - - SmallVector<StringRef, 8> ImpliedFeatures; - llvm::X86::getImpliedFeatures(Name, Enabled, ImpliedFeatures); - for (const auto &F : ImpliedFeatures) - Features[F] = Enabled; + llvm::X86::updateImpliedFeatures(Name, Enabled, Features); } /// handleTargetFeatures - Perform initialization based on the user @@ -280,6 +276,10 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasCLDEMOTE = true; } else if (Feature == "+rdpid") { HasRDPID = true; + } else if (Feature == "+kl") { + HasKL = true; + } else if (Feature == "+widekl") { + HasWIDEKL = true; } else if (Feature == "+retpoline-external-thunk") { HasRetpolineExternalThunk = true; } else if (Feature == "+sahf") { @@ -298,16 +298,22 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasINVPCID = true; } else if (Feature == "+enqcmd") { HasENQCMD = true; + } else if (Feature == "+hreset") { + HasHRESET = true; } else if (Feature == "+amx-bf16") { HasAMXBF16 = true; } else if (Feature == "+amx-int8") { HasAMXINT8 = true; } else if (Feature == "+amx-tile") { HasAMXTILE = true; + } else if (Feature == "+avxvnni") { + HasAVXVNNI = true; } else if (Feature == "+serialize") { HasSERIALIZE = true; } else if (Feature == "+tsxldtrk") { HasTSXLDTRK = true; + } else if (Feature == "+uintr") { + HasUINTR = true; } X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature) @@ -463,6 +469,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_IcelakeClient: case CK_IcelakeServer: case CK_Tigerlake: + case CK_SapphireRapids: + case CK_Alderlake: // 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. @@ -505,6 +513,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_K8: case CK_K8SSE3: case CK_x86_64: + case CK_x86_64_v2: + case CK_x86_64_v3: + case CK_x86_64_v4: defineCPUMacros(Builder, "k8"); break; case CK_AMDFAM10: @@ -534,6 +545,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_ZNVER2: defineCPUMacros(Builder, "znver2"); break; + case CK_ZNVER3: + defineCPUMacros(Builder, "znver3"); + break; case CK_Geode: defineCPUMacros(Builder, "geode"); break; @@ -559,6 +573,11 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasVPCLMULQDQ) Builder.defineMacro("__VPCLMULQDQ__"); + // Note, in 32-bit mode, GCC does not define the macro if -mno-sahf. In LLVM, + // the feature flag only applies to 64-bit mode. + if (HasLAHFSAHF || getTriple().getArch() == llvm::Triple::x86) + Builder.defineMacro("__LAHF_SAHF__"); + if (HasLZCNT) Builder.defineMacro("__LZCNT__"); @@ -681,6 +700,10 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__PREFETCHWT1__"); if (HasCLZERO) Builder.defineMacro("__CLZERO__"); + if (HasKL) + Builder.defineMacro("__KL__"); + if (HasWIDEKL) + Builder.defineMacro("__WIDEKL__"); if (HasRDPID) Builder.defineMacro("__RDPID__"); if (HasCLDEMOTE) @@ -699,16 +722,22 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__INVPCID__"); if (HasENQCMD) Builder.defineMacro("__ENQCMD__"); + if (HasHRESET) + Builder.defineMacro("__HRESET__"); if (HasAMXTILE) Builder.defineMacro("__AMXTILE__"); if (HasAMXINT8) Builder.defineMacro("__AMXINT8__"); if (HasAMXBF16) Builder.defineMacro("__AMXBF16__"); + if (HasAVXVNNI) + Builder.defineMacro("__AVXVNNI__"); if (HasSERIALIZE) Builder.defineMacro("__SERIALIZE__"); if (HasTSXLDTRK) Builder.defineMacro("__TSXLDTRK__"); + if (HasUINTR) + Builder.defineMacro("__UINTR__"); // Each case falls through to the previous one here. switch (SSELevel) { @@ -821,6 +850,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const { .Case("avx512vbmi2", true) .Case("avx512ifma", true) .Case("avx512vp2intersect", true) + .Case("avxvnni", true) .Case("bmi", true) .Case("bmi2", true) .Case("cldemote", true) @@ -835,7 +865,10 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const { .Case("fsgsbase", true) .Case("fxsr", true) .Case("gfni", true) + .Case("hreset", true) .Case("invpcid", true) + .Case("kl", true) + .Case("widekl", true) .Case("lwp", true) .Case("lzcnt", true) .Case("mmx", true) @@ -869,6 +902,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const { .Case("sse4a", true) .Case("tbm", true) .Case("tsxldtrk", true) + .Case("uintr", true) .Case("vaes", true) .Case("vpclmulqdq", true) .Case("wbnoinvd", true) @@ -889,6 +923,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("amx-bf16", HasAMXBF16) .Case("amx-int8", HasAMXINT8) .Case("amx-tile", HasAMXTILE) + .Case("avxvnni", HasAVXVNNI) .Case("avx", SSELevel >= AVX) .Case("avx2", SSELevel >= AVX2) .Case("avx512f", SSELevel >= AVX512F) @@ -921,7 +956,10 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("fsgsbase", HasFSGSBASE) .Case("fxsr", HasFXSR) .Case("gfni", HasGFNI) + .Case("hreset", HasHRESET) .Case("invpcid", HasINVPCID) + .Case("kl", HasKL) + .Case("widekl", HasWIDEKL) .Case("lwp", HasLWP) .Case("lzcnt", HasLZCNT) .Case("mm3dnow", MMX3DNowLevel >= AMD3DNow) @@ -957,6 +995,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("sse4a", XOPLevel >= SSE4A) .Case("tbm", HasTBM) .Case("tsxldtrk", HasTSXLDTRK) + .Case("uintr", HasUINTR) .Case("vaes", HasVAES) .Case("vpclmulqdq", HasVPCLMULQDQ) .Case("wbnoinvd", HasWBNOINVD) @@ -1273,8 +1312,10 @@ Optional<unsigned> X86TargetInfo::getCPUCacheLineSize() const { case CK_Cooperlake: case CK_Cannonlake: case CK_Tigerlake: + case CK_SapphireRapids: case CK_IcelakeClient: case CK_IcelakeServer: + case CK_Alderlake: case CK_KNL: case CK_KNM: // K7 @@ -1295,8 +1336,12 @@ Optional<unsigned> X86TargetInfo::getCPUCacheLineSize() const { // Zen case CK_ZNVER1: case CK_ZNVER2: + case CK_ZNVER3: // Deprecated case CK_x86_64: + case CK_x86_64_v2: + case CK_x86_64_v3: + case CK_x86_64_v4: case CK_Yonah: case CK_Penryn: case CK_Core2: @@ -1440,6 +1485,10 @@ void X86TargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const { llvm::X86::fillValidCPUArchList(Values, Only64Bit); } +void X86TargetInfo::fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const { + llvm::X86::fillValidTuneCPUList(Values); +} + ArrayRef<const char *> X86TargetInfo::getGCCRegNames() const { return llvm::makeArrayRef(GCCRegNames); } diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 72a01d2514c2..91a365c7d405 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -30,6 +30,8 @@ static const unsigned X86AddrSpaceMap[] = { 0, // opencl_constant 0, // opencl_private 0, // opencl_generic + 0, // opencl_global_device + 0, // opencl_global_host 0, // cuda_device 0, // cuda_constant 0, // cuda_shared @@ -125,11 +127,16 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo { bool HasPTWRITE = false; bool HasINVPCID = false; bool HasENQCMD = false; + bool HasKL = false; // For key locker + bool HasWIDEKL = false; // For wide key locker + bool HasHRESET = false; + bool HasAVXVNNI = false; bool HasAMXTILE = false; bool HasAMXINT8 = false; bool HasAMXBF16 = false; bool HasSERIALIZE = false; bool HasTSXLDTRK = false; + bool HasUINTR = false; protected: llvm::X86::CPUKind CPU = llvm::X86::CK_None; @@ -142,6 +149,11 @@ public: LongDoubleFormat = &llvm::APFloat::x87DoubleExtended(); AddrSpaceMap = &X86AddrSpaceMap; HasStrictFP = true; + + bool IsWinCOFF = + getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF(); + if (IsWinCOFF) + MaxVectorAlign = MaxTLSAlign = 8192u * getCharWidth(); } const char *getLongDoubleMangling() const override { @@ -289,12 +301,27 @@ public: return ""; } + bool supportsTargetAttributeTune() const override { + return true; + } + bool isValidCPUName(StringRef Name) const override { bool Only64Bit = getTriple().getArch() != llvm::Triple::x86; return llvm::X86::parseArchX86(Name, Only64Bit) != llvm::X86::CK_None; } + bool isValidTuneCPUName(StringRef Name) const override { + if (Name == "generic") + return true; + + // Allow 32-bit only CPUs regardless of 64-bit mode unlike isValidCPUName. + // NOTE: gcc rejects 32-bit mtune CPUs in 64-bit mode. But being lenient + // since mtune was ignored by clang for so long. + return llvm::X86::parseTuneCPU(Name) != llvm::X86::CK_None; + } + void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; + void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override; bool setCPU(const std::string &Name) override { bool Only64Bit = getTriple().getArch() != llvm::Triple::x86; @@ -332,9 +359,7 @@ public: bool hasSjLjLowering() const override { return true; } - void setSupportedOpenCLOpts() override { - getSupportedOpenCLOpts().supportAll(); - } + void setSupportedOpenCLOpts() override { supportAllOpenCLOpts(); } uint64_t getPointerWidthV(unsigned AddrSpace) const override { if (AddrSpace == ptr32_sptr || AddrSpace == ptr32_uptr) @@ -358,7 +383,10 @@ public: LongDoubleWidth = 96; LongDoubleAlign = 32; SuitableAlign = 128; - resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-" + resetDataLayout(Triple.isOSBinFormatMachO() ? + "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-" + "f80:32-n8:16:32-S128" : + "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; diff --git a/clang/lib/Basic/Version.cpp b/clang/lib/Basic/Version.cpp index 286107cab9d7..af3118b0f6da 100644 --- a/clang/lib/Basic/Version.cpp +++ b/clang/lib/Basic/Version.cpp @@ -17,9 +17,7 @@ #include <cstdlib> #include <cstring> -#ifdef HAVE_VCS_VERSION_INC #include "VCSVersion.inc" -#endif namespace clang { diff --git a/clang/lib/Basic/Warnings.cpp b/clang/lib/Basic/Warnings.cpp index 2c909d9510d4..cc8c138233ca 100644 --- a/clang/lib/Basic/Warnings.cpp +++ b/clang/lib/Basic/Warnings.cpp @@ -130,11 +130,14 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags, } // -Werror/-Wno-error is a special case, not controlled by the option - // table. It also has the "specifier" form of -Werror=foo and -Werror-foo. + // table. It also has the "specifier" form of -Werror=foo. GCC supports + // the deprecated -Werror-implicit-function-declaration which is used by + // a few projects. if (Opt.startswith("error")) { StringRef Specifier; if (Opt.size() > 5) { // Specifier must be present. - if ((Opt[5] != '=' && Opt[5] != '-') || Opt.size() == 6) { + if (Opt[5] != '=' && + Opt.substr(5) != "-implicit-function-declaration") { if (Report) Diags.Report(diag::warn_unknown_warning_specifier) << "-Werror" << ("-W" + OrigOpt.str()); |