aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Basic
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Basic')
-rw-r--r--clang/lib/Basic/Cuda.cpp43
-rw-r--r--clang/lib/Basic/Diagnostic.cpp35
-rw-r--r--clang/lib/Basic/DiagnosticIDs.cpp109
-rw-r--r--clang/lib/Basic/FileEntry.cpp24
-rw-r--r--clang/lib/Basic/FileManager.cpp181
-rw-r--r--clang/lib/Basic/FixedPoint.cpp394
-rw-r--r--clang/lib/Basic/IdentifierTable.cpp5
-rw-r--r--clang/lib/Basic/LangOptions.cpp2
-rw-r--r--clang/lib/Basic/Module.cpp21
-rw-r--r--clang/lib/Basic/OpenCLOptions.cpp106
-rw-r--r--clang/lib/Basic/OpenMPKinds.cpp50
-rw-r--r--clang/lib/Basic/ProfileList.cpp113
-rw-r--r--clang/lib/Basic/SourceLocation.cpp21
-rw-r--r--clang/lib/Basic/SourceManager.cpp506
-rw-r--r--clang/lib/Basic/TargetID.cpp169
-rw-r--r--clang/lib/Basic/TargetInfo.cpp1
-rw-r--r--clang/lib/Basic/Targets.cpp68
-rw-r--r--clang/lib/Basic/Targets/AArch64.cpp48
-rw-r--r--clang/lib/Basic/Targets/AArch64.h6
-rw-r--r--clang/lib/Basic/Targets/AMDGPU.cpp36
-rw-r--r--clang/lib/Basic/Targets/AMDGPU.h77
-rw-r--r--clang/lib/Basic/Targets/ARM.cpp2
-rw-r--r--clang/lib/Basic/Targets/AVR.cpp7
-rw-r--r--clang/lib/Basic/Targets/Hexagon.cpp3
-rw-r--r--clang/lib/Basic/Targets/MSP430.cpp1
-rw-r--r--clang/lib/Basic/Targets/Mips.cpp1
-rw-r--r--clang/lib/Basic/Targets/NVPTX.cpp8
-rw-r--r--clang/lib/Basic/Targets/NVPTX.h22
-rw-r--r--clang/lib/Basic/Targets/OSTargets.h81
-rw-r--r--clang/lib/Basic/Targets/PPC.cpp87
-rw-r--r--clang/lib/Basic/Targets/PPC.h34
-rw-r--r--clang/lib/Basic/Targets/RISCV.cpp160
-rw-r--r--clang/lib/Basic/Targets/RISCV.h49
-rw-r--r--clang/lib/Basic/Targets/SPIR.h6
-rw-r--r--clang/lib/Basic/Targets/Sparc.cpp28
-rw-r--r--clang/lib/Basic/Targets/Sparc.h11
-rw-r--r--clang/lib/Basic/Targets/SystemZ.h4
-rw-r--r--clang/lib/Basic/Targets/TCE.h2
-rw-r--r--clang/lib/Basic/Targets/VE.h16
-rw-r--r--clang/lib/Basic/Targets/WebAssembly.cpp60
-rw-r--r--clang/lib/Basic/Targets/WebAssembly.h6
-rw-r--r--clang/lib/Basic/Targets/X86.cpp59
-rw-r--r--clang/lib/Basic/Targets/X86.h36
-rw-r--r--clang/lib/Basic/Version.cpp2
-rw-r--r--clang/lib/Basic/Warnings.cpp7
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());