summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Support
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Support')
-rw-r--r--contrib/llvm/lib/Support/APFloat.cpp75
-rw-r--r--contrib/llvm/lib/Support/APInt.cpp150
-rw-r--r--contrib/llvm/lib/Support/APSInt.cpp1
-rw-r--r--contrib/llvm/lib/Support/ARMBuildAttrs.cpp1
-rw-r--r--contrib/llvm/lib/Support/Atomic.cpp59
-rw-r--r--contrib/llvm/lib/Support/BranchProbability.cpp2
-rw-r--r--contrib/llvm/lib/Support/CachePruning.cpp159
-rw-r--r--contrib/llvm/lib/Support/CommandLine.cpp545
-rw-r--r--contrib/llvm/lib/Support/ConvertUTFWrapper.cpp83
-rw-r--r--contrib/llvm/lib/Support/CrashRecoveryContext.cpp8
-rw-r--r--contrib/llvm/lib/Support/Dwarf.cpp37
-rw-r--r--contrib/llvm/lib/Support/Error.cpp113
-rw-r--r--contrib/llvm/lib/Support/ErrorHandling.cpp1
-rw-r--r--contrib/llvm/lib/Support/FileUtilities.cpp6
-rw-r--r--contrib/llvm/lib/Support/FoldingSet.cpp25
-rw-r--r--contrib/llvm/lib/Support/Host.cpp1346
-rw-r--r--contrib/llvm/lib/Support/IntEqClasses.cpp13
-rw-r--r--contrib/llvm/lib/Support/JamCRC.cpp1
-rw-r--r--contrib/llvm/lib/Support/Locale.cpp3
-rw-r--r--contrib/llvm/lib/Support/LockFileManager.cpp37
-rw-r--r--contrib/llvm/lib/Support/ManagedStatic.cpp31
-rw-r--r--contrib/llvm/lib/Support/MemoryBuffer.cpp10
-rw-r--r--contrib/llvm/lib/Support/Path.cpp46
-rw-r--r--contrib/llvm/lib/Support/PrettyStackTrace.cpp47
-rw-r--r--contrib/llvm/lib/Support/Process.cpp7
-rw-r--r--contrib/llvm/lib/Support/SHA1.cpp170
-rw-r--r--contrib/llvm/lib/Support/ScaledNumber.cpp1
-rw-r--r--contrib/llvm/lib/Support/ScopedPrinter.cpp72
-rw-r--r--contrib/llvm/lib/Support/Signals.cpp34
-rw-r--r--contrib/llvm/lib/Support/SmallPtrSet.cpp191
-rw-r--r--contrib/llvm/lib/Support/SpecialCaseList.cpp2
-rw-r--r--contrib/llvm/lib/Support/Statistic.cpp74
-rw-r--r--contrib/llvm/lib/Support/StreamingMemoryObject.cpp6
-rw-r--r--contrib/llvm/lib/Support/StringMap.cpp16
-rw-r--r--contrib/llvm/lib/Support/StringRef.cpp4
-rw-r--r--contrib/llvm/lib/Support/TargetParser.cpp232
-rw-r--r--contrib/llvm/lib/Support/TargetRegistry.cpp3
-rw-r--r--contrib/llvm/lib/Support/ThreadPool.cpp5
-rw-r--r--contrib/llvm/lib/Support/Threading.cpp6
-rw-r--r--contrib/llvm/lib/Support/Timer.cpp44
-rw-r--r--contrib/llvm/lib/Support/Triple.cpp250
-rw-r--r--contrib/llvm/lib/Support/Twine.cpp2
-rw-r--r--contrib/llvm/lib/Support/Unix/Memory.inc4
-rw-r--r--contrib/llvm/lib/Support/Unix/Path.inc137
-rw-r--r--contrib/llvm/lib/Support/Unix/Process.inc4
-rw-r--r--contrib/llvm/lib/Support/Unix/Signals.inc148
-rw-r--r--contrib/llvm/lib/Support/Windows/DynamicLibrary.inc2
-rw-r--r--contrib/llvm/lib/Support/Windows/Path.inc150
-rw-r--r--contrib/llvm/lib/Support/Windows/Process.inc38
-rw-r--r--contrib/llvm/lib/Support/Windows/Signals.inc228
-rw-r--r--contrib/llvm/lib/Support/Windows/WindowsSupport.h28
-rw-r--r--contrib/llvm/lib/Support/YAMLParser.cpp2
-rw-r--r--contrib/llvm/lib/Support/YAMLTraits.cpp23
-rw-r--r--contrib/llvm/lib/Support/raw_ostream.cpp29
54 files changed, 3508 insertions, 1203 deletions
diff --git a/contrib/llvm/lib/Support/APFloat.cpp b/contrib/llvm/lib/Support/APFloat.cpp
index 19b8221..f9370b8 100644
--- a/contrib/llvm/lib/Support/APFloat.cpp
+++ b/contrib/llvm/lib/Support/APFloat.cpp
@@ -14,6 +14,7 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h"
@@ -501,7 +502,9 @@ powerOf5(integerPart *dst, unsigned int power)
/* Now result is in p1 with partsCount parts and p2 is scratch
space. */
- tmp = p1, p1 = p2, p2 = tmp;
+ tmp = p1;
+ p1 = p2;
+ p2 = tmp;
}
pow5 += pc;
@@ -3940,22 +3943,68 @@ APFloat::makeZero(bool Negative) {
category = fcZero;
sign = Negative;
exponent = semantics->minExponent-1;
- APInt::tcSet(significandParts(), 0, partCount());
+ APInt::tcSet(significandParts(), 0, partCount());
+}
+
+void APFloat::makeQuiet() {
+ assert(isNaN());
+ APInt::tcSetBit(significandParts(), semantics->precision - 2);
}
-APFloat llvm::scalbn(APFloat X, int Exp) {
- if (X.isInfinity() || X.isZero() || X.isNaN())
- return X;
+int llvm::ilogb(const APFloat &Arg) {
+ if (Arg.isNaN())
+ return APFloat::IEK_NaN;
+ if (Arg.isZero())
+ return APFloat::IEK_Zero;
+ if (Arg.isInfinity())
+ return APFloat::IEK_Inf;
+ if (!Arg.isDenormal())
+ return Arg.exponent;
+
+ APFloat Normalized(Arg);
+ int SignificandBits = Arg.getSemantics().precision - 1;
+ Normalized.exponent += SignificandBits;
+ Normalized.normalize(APFloat::rmNearestTiesToEven, lfExactlyZero);
+ return Normalized.exponent - SignificandBits;
+}
+
+APFloat llvm::scalbn(APFloat X, int Exp, APFloat::roundingMode RoundingMode) {
auto MaxExp = X.getSemantics().maxExponent;
auto MinExp = X.getSemantics().minExponent;
- if (Exp > (MaxExp - X.exponent))
- // Overflow saturates to infinity.
- return APFloat::getInf(X.getSemantics(), X.isNegative());
- if (Exp < (MinExp - X.exponent))
- // Underflow saturates to zero.
- return APFloat::getZero(X.getSemantics(), X.isNegative());
-
- X.exponent += Exp;
+
+ // If Exp is wildly out-of-scale, simply adding it to X.exponent will
+ // overflow; clamp it to a safe range before adding, but ensure that the range
+ // is large enough that the clamp does not change the result. The range we
+ // need to support is the difference between the largest possible exponent and
+ // the normalized exponent of half the smallest denormal.
+
+ int SignificandBits = X.getSemantics().precision - 1;
+ int MaxIncrement = MaxExp - (MinExp - SignificandBits) + 1;
+
+ // Clamp to one past the range ends to let normalize handle overlflow.
+ X.exponent += std::min(std::max(Exp, -MaxIncrement - 1), MaxIncrement);
+ X.normalize(RoundingMode, lfExactlyZero);
+ if (X.isNaN())
+ X.makeQuiet();
return X;
}
+
+APFloat llvm::frexp(const APFloat &Val, int &Exp, APFloat::roundingMode RM) {
+ Exp = ilogb(Val);
+
+ // Quiet signalling nans.
+ if (Exp == APFloat::IEK_NaN) {
+ APFloat Quiet(Val);
+ Quiet.makeQuiet();
+ return Quiet;
+ }
+
+ if (Exp == APFloat::IEK_Inf)
+ return Val;
+
+ // 1 is added because frexp is defined to return a normalized fraction in
+ // +/-[0.5, 1.0), rather than the usual +/-[1.0, 2.0).
+ Exp = Exp == APFloat::IEK_Zero ? 0 : Exp + 1;
+ return scalbn(Val, -Exp, RM);
+}
diff --git a/contrib/llvm/lib/Support/APInt.cpp b/contrib/llvm/lib/Support/APInt.cpp
index 23f89bb..66eee99 100644
--- a/contrib/llvm/lib/Support/APInt.cpp
+++ b/contrib/llvm/lib/Support/APInt.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
@@ -74,7 +75,7 @@ inline static unsigned getDigit(char cdigit, uint8_t radix) {
}
-void APInt::initSlowCase(unsigned numBits, uint64_t val, bool isSigned) {
+void APInt::initSlowCase(uint64_t val, bool isSigned) {
pVal = getClearedMemory(getNumWords());
pVal[0] = val;
if (isSigned && int64_t(val) < 0)
@@ -479,6 +480,15 @@ APInt APInt::operator+(const APInt& RHS) const {
return Result;
}
+APInt APInt::operator+(uint64_t RHS) const {
+ if (isSingleWord())
+ return APInt(BitWidth, VAL + RHS);
+ APInt Result(*this);
+ add_1(Result.pVal, Result.pVal, getNumWords(), RHS);
+ Result.clearUnusedBits();
+ return Result;
+}
+
APInt APInt::operator-(const APInt& RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord())
@@ -489,24 +499,17 @@ APInt APInt::operator-(const APInt& RHS) const {
return Result;
}
-bool APInt::EqualSlowCase(const APInt& RHS) const {
- // Get some facts about the number of bits used in the two operands.
- unsigned n1 = getActiveBits();
- unsigned n2 = RHS.getActiveBits();
-
- // If the number of bits isn't the same, they aren't equal
- if (n1 != n2)
- return false;
-
- // If the number of bits fits in a word, we only need to compare the low word.
- if (n1 <= APINT_BITS_PER_WORD)
- return pVal[0] == RHS.pVal[0];
+APInt APInt::operator-(uint64_t RHS) const {
+ if (isSingleWord())
+ return APInt(BitWidth, VAL - RHS);
+ APInt Result(*this);
+ sub_1(Result.pVal, getNumWords(), RHS);
+ Result.clearUnusedBits();
+ return Result;
+}
- // Otherwise, compare everything
- for (int i = whichWord(n1 - 1); i >= 0; --i)
- if (pVal[i] != RHS.pVal[i])
- return false;
- return true;
+bool APInt::EqualSlowCase(const APInt& RHS) const {
+ return std::equal(pVal, pVal + getNumWords(), RHS.pVal);
}
bool APInt::EqualSlowCase(uint64_t Val) const {
@@ -552,37 +555,21 @@ bool APInt::ult(const APInt& RHS) const {
bool APInt::slt(const APInt& RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
if (isSingleWord()) {
- int64_t lhsSext = (int64_t(VAL) << (64-BitWidth)) >> (64-BitWidth);
- int64_t rhsSext = (int64_t(RHS.VAL) << (64-BitWidth)) >> (64-BitWidth);
+ int64_t lhsSext = SignExtend64(VAL, BitWidth);
+ int64_t rhsSext = SignExtend64(RHS.VAL, BitWidth);
return lhsSext < rhsSext;
}
- APInt lhs(*this);
- APInt rhs(RHS);
bool lhsNeg = isNegative();
- bool rhsNeg = rhs.isNegative();
- if (lhsNeg) {
- // Sign bit is set so perform two's complement to make it positive
- lhs.flipAllBits();
- ++lhs;
- }
- if (rhsNeg) {
- // Sign bit is set so perform two's complement to make it positive
- rhs.flipAllBits();
- ++rhs;
- }
-
- // Now we have unsigned values to compare so do the comparison if necessary
- // based on the negativeness of the values.
- if (lhsNeg)
- if (rhsNeg)
- return lhs.ugt(rhs);
- else
- return true;
- else if (rhsNeg)
- return false;
- else
- return lhs.ult(rhs);
+ bool rhsNeg = RHS.isNegative();
+
+ // If the sign bits don't match, then (LHS < RHS) if LHS is negative
+ if (lhsNeg != rhsNeg)
+ return lhsNeg;
+
+ // Otherwise we can just use an unsigned comparision, because even negative
+ // numbers compare correctly this way if both have the same signed-ness.
+ return ult(RHS);
}
void APInt::setBit(unsigned bitPosition) {
@@ -692,30 +679,19 @@ APInt APInt::getLoBits(unsigned numBits) const {
}
unsigned APInt::countLeadingZerosSlowCase() const {
- // Treat the most significand word differently because it might have
- // meaningless bits set beyond the precision.
- unsigned BitsInMSW = BitWidth % APINT_BITS_PER_WORD;
- integerPart MSWMask;
- if (BitsInMSW) MSWMask = (integerPart(1) << BitsInMSW) - 1;
- else {
- MSWMask = ~integerPart(0);
- BitsInMSW = APINT_BITS_PER_WORD;
- }
-
- unsigned i = getNumWords();
- integerPart MSW = pVal[i-1] & MSWMask;
- if (MSW)
- return llvm::countLeadingZeros(MSW) - (APINT_BITS_PER_WORD - BitsInMSW);
-
- unsigned Count = BitsInMSW;
- for (--i; i > 0u; --i) {
- if (pVal[i-1] == 0)
+ unsigned Count = 0;
+ for (int i = getNumWords()-1; i >= 0; --i) {
+ integerPart V = pVal[i];
+ if (V == 0)
Count += APINT_BITS_PER_WORD;
else {
- Count += llvm::countLeadingZeros(pVal[i-1]);
+ Count += llvm::countLeadingZeros(V);
break;
}
}
+ // Adjust for unused bits in the most significant word (they are zero).
+ unsigned Mod = BitWidth % APINT_BITS_PER_WORD;
+ Count -= Mod > 0 ? APINT_BITS_PER_WORD - Mod : 0;
return Count;
}
@@ -814,6 +790,36 @@ APInt APInt::byteSwap() const {
return Result;
}
+APInt APInt::reverseBits() const {
+ switch (BitWidth) {
+ case 64:
+ return APInt(BitWidth, llvm::reverseBits<uint64_t>(VAL));
+ case 32:
+ return APInt(BitWidth, llvm::reverseBits<uint32_t>(VAL));
+ case 16:
+ return APInt(BitWidth, llvm::reverseBits<uint16_t>(VAL));
+ case 8:
+ return APInt(BitWidth, llvm::reverseBits<uint8_t>(VAL));
+ default:
+ break;
+ }
+
+ APInt Val(*this);
+ APInt Reversed(*this);
+ int S = BitWidth - 1;
+
+ const APInt One(BitWidth, 1);
+
+ for ((Val = Val.lshr(1)); Val != 0; (Val = Val.lshr(1))) {
+ Reversed <<= 1;
+ Reversed |= (Val & One);
+ --S;
+ }
+
+ Reversed <<= S;
+ return Reversed;
+}
+
APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1,
const APInt& API2) {
APInt A = API1, B = API2;
@@ -874,7 +880,7 @@ double APInt::roundToDouble(bool isSigned) const {
// It is wrong to optimize getWord(0) to VAL; there might be more than one word.
if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) {
if (isSigned) {
- int64_t sext = (int64_t(getWord(0)) << (64-BitWidth)) >> (64-BitWidth);
+ int64_t sext = SignExtend64(getWord(0), BitWidth);
return double(sext);
} else
return double(getWord(0));
@@ -1658,10 +1664,8 @@ static void KnuthDiv(unsigned *u, unsigned *v, unsigned *q, unsigned* r,
DEBUG(dbgs() << '\n');
}
-void APInt::divide(const APInt LHS, unsigned lhsWords,
- const APInt &RHS, unsigned rhsWords,
- APInt *Quotient, APInt *Remainder)
-{
+void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
+ unsigned rhsWords, APInt *Quotient, APInt *Remainder) {
assert(lhsWords >= rhsWords && "Fractional result");
// First, compose the values into an array of 32-bit words instead of
@@ -2268,7 +2272,7 @@ std::string APInt::toString(unsigned Radix = 10, bool Signed = true) const {
}
-void APInt::dump() const {
+LLVM_DUMP_METHOD void APInt::dump() const {
SmallString<40> S, U;
this->toStringUnsigned(U);
this->toStringSigned(S);
@@ -2725,8 +2729,10 @@ APInt::tcDivide(integerPart *lhs, const integerPart *rhs,
break;
shiftCount--;
tcShiftRight(srhs, parts, 1);
- if ((mask >>= 1) == 0)
- mask = (integerPart) 1 << (integerPartWidth - 1), n--;
+ if ((mask >>= 1) == 0) {
+ mask = (integerPart) 1 << (integerPartWidth - 1);
+ n--;
+ }
}
return false;
diff --git a/contrib/llvm/lib/Support/APSInt.cpp b/contrib/llvm/lib/Support/APSInt.cpp
index 975457c..46c0f70 100644
--- a/contrib/llvm/lib/Support/APSInt.cpp
+++ b/contrib/llvm/lib/Support/APSInt.cpp
@@ -14,6 +14,7 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/StringRef.h"
using namespace llvm;
diff --git a/contrib/llvm/lib/Support/ARMBuildAttrs.cpp b/contrib/llvm/lib/Support/ARMBuildAttrs.cpp
index 960a0f1..6d34f76 100644
--- a/contrib/llvm/lib/Support/ARMBuildAttrs.cpp
+++ b/contrib/llvm/lib/Support/ARMBuildAttrs.cpp
@@ -54,6 +54,7 @@ const struct {
{ ARMBuildAttrs::ABI_FP_16bit_format, "Tag_ABI_FP_16bit_format" },
{ ARMBuildAttrs::MPextension_use, "Tag_MPextension_use" },
{ ARMBuildAttrs::DIV_use, "Tag_DIV_use" },
+ { ARMBuildAttrs::DSP_extension, "Tag_DSP_extension" },
{ ARMBuildAttrs::nodefaults, "Tag_nodefaults" },
{ ARMBuildAttrs::also_compatible_with, "Tag_also_compatible_with" },
{ ARMBuildAttrs::T2EE_use, "Tag_T2EE_use" },
diff --git a/contrib/llvm/lib/Support/Atomic.cpp b/contrib/llvm/lib/Support/Atomic.cpp
index ac4ff3e..80550e2 100644
--- a/contrib/llvm/lib/Support/Atomic.cpp
+++ b/contrib/llvm/lib/Support/Atomic.cpp
@@ -56,62 +56,3 @@ sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
# error No compare-and-swap implementation for your platform!
#endif
}
-
-sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) {
-#if LLVM_HAS_ATOMICS == 0
- ++(*ptr);
- return *ptr;
-#elif defined(GNU_ATOMICS)
- return __sync_add_and_fetch(ptr, 1);
-#elif defined(_MSC_VER)
- return InterlockedIncrement(ptr);
-#else
-# error No atomic increment implementation for your platform!
-#endif
-}
-
-sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) {
-#if LLVM_HAS_ATOMICS == 0
- --(*ptr);
- return *ptr;
-#elif defined(GNU_ATOMICS)
- return __sync_sub_and_fetch(ptr, 1);
-#elif defined(_MSC_VER)
- return InterlockedDecrement(ptr);
-#else
-# error No atomic decrement implementation for your platform!
-#endif
-}
-
-sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) {
-#if LLVM_HAS_ATOMICS == 0
- *ptr += val;
- return *ptr;
-#elif defined(GNU_ATOMICS)
- return __sync_add_and_fetch(ptr, val);
-#elif defined(_MSC_VER)
- return InterlockedExchangeAdd(ptr, val) + val;
-#else
-# error No atomic add implementation for your platform!
-#endif
-}
-
-sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) {
- sys::cas_flag original, result;
- do {
- original = *ptr;
- result = original * val;
- } while (sys::CompareAndSwap(ptr, result, original) != original);
-
- return result;
-}
-
-sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) {
- sys::cas_flag original, result;
- do {
- original = *ptr;
- result = original / val;
- } while (sys::CompareAndSwap(ptr, result, original) != original);
-
- return result;
-}
diff --git a/contrib/llvm/lib/Support/BranchProbability.cpp b/contrib/llvm/lib/Support/BranchProbability.cpp
index 771d02c..1c41659 100644
--- a/contrib/llvm/lib/Support/BranchProbability.cpp
+++ b/contrib/llvm/lib/Support/BranchProbability.cpp
@@ -32,7 +32,7 @@ raw_ostream &BranchProbability::print(raw_ostream &OS) const {
Percent);
}
-void BranchProbability::dump() const { print(dbgs()) << '\n'; }
+LLVM_DUMP_METHOD void BranchProbability::dump() const { print(dbgs()) << '\n'; }
BranchProbability::BranchProbability(uint32_t Numerator, uint32_t Denominator) {
assert(Denominator > 0 && "Denominator cannot be 0!");
diff --git a/contrib/llvm/lib/Support/CachePruning.cpp b/contrib/llvm/lib/Support/CachePruning.cpp
new file mode 100644
index 0000000..bd42bef
--- /dev/null
+++ b/contrib/llvm/lib/Support/CachePruning.cpp
@@ -0,0 +1,159 @@
+//===-CachePruning.cpp - LLVM Cache Directory Pruning ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the pruning of a directory based on least recently used.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/CachePruning.h"
+
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "cache-pruning"
+
+#include <set>
+
+using namespace llvm;
+
+/// Write a new timestamp file with the given path. This is used for the pruning
+/// interval option.
+static void writeTimestampFile(StringRef TimestampFile) {
+ std::error_code EC;
+ raw_fd_ostream Out(TimestampFile.str(), EC, sys::fs::F_None);
+}
+
+/// Prune the cache of files that haven't been accessed in a long time.
+bool CachePruning::prune() {
+ if (Path.empty())
+ return false;
+
+ bool isPathDir;
+ if (sys::fs::is_directory(Path, isPathDir))
+ return false;
+
+ if (!isPathDir)
+ return false;
+
+ if (Expiration == 0 && PercentageOfAvailableSpace == 0) {
+ DEBUG(dbgs() << "No pruning settings set, exit early\n");
+ // Nothing will be pruned, early exit
+ return false;
+ }
+
+ // Try to stat() the timestamp file.
+ SmallString<128> TimestampFile(Path);
+ sys::path::append(TimestampFile, "llvmcache.timestamp");
+ sys::fs::file_status FileStatus;
+ sys::TimeValue CurrentTime = sys::TimeValue::now();
+ if (auto EC = sys::fs::status(TimestampFile, FileStatus)) {
+ if (EC == errc::no_such_file_or_directory) {
+ // If the timestamp file wasn't there, create one now.
+ writeTimestampFile(TimestampFile);
+ } else {
+ // Unknown error?
+ return false;
+ }
+ } else {
+ if (Interval) {
+ // Check whether the time stamp is older than our pruning interval.
+ // If not, do nothing.
+ sys::TimeValue TimeStampModTime = FileStatus.getLastModificationTime();
+ auto TimeInterval = sys::TimeValue(sys::TimeValue::SecondsType(Interval));
+ auto TimeStampAge = CurrentTime - TimeStampModTime;
+ if (TimeStampAge <= TimeInterval) {
+ DEBUG(dbgs() << "Timestamp file too recent (" << TimeStampAge.seconds()
+ << "s old), do not prune.\n");
+ return false;
+ }
+ }
+ // Write a new timestamp file so that nobody else attempts to prune.
+ // There is a benign race condition here, if two processes happen to
+ // notice at the same time that the timestamp is out-of-date.
+ writeTimestampFile(TimestampFile);
+ }
+
+ bool ShouldComputeSize = (PercentageOfAvailableSpace > 0);
+
+ // Keep track of space
+ std::set<std::pair<uint64_t, std::string>> FileSizes;
+ uint64_t TotalSize = 0;
+ // Helper to add a path to the set of files to consider for size-based
+ // pruning, sorted by size.
+ auto AddToFileListForSizePruning =
+ [&](StringRef Path) {
+ if (!ShouldComputeSize)
+ return;
+ TotalSize += FileStatus.getSize();
+ FileSizes.insert(
+ std::make_pair(FileStatus.getSize(), std::string(Path)));
+ };
+
+ // Walk the entire directory cache, looking for unused files.
+ std::error_code EC;
+ SmallString<128> CachePathNative;
+ sys::path::native(Path, CachePathNative);
+ auto TimeExpiration = sys::TimeValue(sys::TimeValue::SecondsType(Expiration));
+ // Walk all of the files within this directory.
+ for (sys::fs::directory_iterator File(CachePathNative, EC), FileEnd;
+ File != FileEnd && !EC; File.increment(EC)) {
+ // Do not touch the timestamp.
+ if (File->path() == TimestampFile)
+ continue;
+
+ // Look at this file. If we can't stat it, there's nothing interesting
+ // there.
+ if (sys::fs::status(File->path(), FileStatus)) {
+ DEBUG(dbgs() << "Ignore " << File->path() << " (can't stat)\n");
+ continue;
+ }
+
+ // If the file hasn't been used recently enough, delete it
+ sys::TimeValue FileAccessTime = FileStatus.getLastAccessedTime();
+ auto FileAge = CurrentTime - FileAccessTime;
+ if (FileAge > TimeExpiration) {
+ DEBUG(dbgs() << "Remove " << File->path() << " (" << FileAge.seconds()
+ << "s old)\n");
+ sys::fs::remove(File->path());
+ continue;
+ }
+
+ // Leave it here for now, but add it to the list of size-based pruning.
+ AddToFileListForSizePruning(File->path());
+ }
+
+ // Prune for size now if needed
+ if (ShouldComputeSize) {
+ auto ErrOrSpaceInfo = sys::fs::disk_space(Path);
+ if (!ErrOrSpaceInfo) {
+ report_fatal_error("Can't get available size");
+ }
+ sys::fs::space_info SpaceInfo = ErrOrSpaceInfo.get();
+ auto AvailableSpace = TotalSize + SpaceInfo.free;
+ auto FileAndSize = FileSizes.rbegin();
+ DEBUG(dbgs() << "Occupancy: " << ((100 * TotalSize) / AvailableSpace)
+ << "% target is: " << PercentageOfAvailableSpace << "\n");
+ // Remove the oldest accessed files first, till we get below the threshold
+ while (((100 * TotalSize) / AvailableSpace) > PercentageOfAvailableSpace &&
+ FileAndSize != FileSizes.rend()) {
+ // Remove the file.
+ sys::fs::remove(FileAndSize->second);
+ // Update size
+ TotalSize -= FileAndSize->first;
+ DEBUG(dbgs() << " - Remove " << FileAndSize->second << " (size "
+ << FileAndSize->first << "), new occupancy is " << TotalSize
+ << "%\n");
+ ++FileAndSize;
+ }
+ }
+ return true;
+}
diff --git a/contrib/llvm/lib/Support/CommandLine.cpp b/contrib/llvm/lib/Support/CommandLine.cpp
index fdcdb03..a5d2ba2 100644
--- a/contrib/llvm/lib/Support/CommandLine.cpp
+++ b/contrib/llvm/lib/Support/CommandLine.cpp
@@ -19,6 +19,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm-c/Support.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
@@ -94,35 +95,56 @@ public:
// This collects additional help to be printed.
std::vector<const char *> MoreHelp;
- SmallVector<Option *, 4> PositionalOpts;
- SmallVector<Option *, 4> SinkOpts;
- StringMap<Option *> OptionsMap;
-
- Option *ConsumeAfterOpt; // The ConsumeAfter option if it exists.
-
// This collects the different option categories that have been registered.
SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories;
- CommandLineParser() : ProgramOverview(nullptr), ConsumeAfterOpt(nullptr) {}
+ // This collects the different subcommands that have been registered.
+ SmallPtrSet<SubCommand *, 4> RegisteredSubCommands;
- void ParseCommandLineOptions(int argc, const char *const *argv,
- const char *Overview);
+ CommandLineParser() : ProgramOverview(nullptr), ActiveSubCommand(nullptr) {
+ registerSubCommand(&*TopLevelSubCommand);
+ registerSubCommand(&*AllSubCommands);
+ }
- void addLiteralOption(Option &Opt, const char *Name) {
- if (!Opt.hasArgStr()) {
- if (!OptionsMap.insert(std::make_pair(Name, &Opt)).second) {
- errs() << ProgramName << ": CommandLine Error: Option '" << Name
- << "' registered more than once!\n";
- report_fatal_error("inconsistency in registered CommandLine options");
+ void ResetAllOptionOccurrences();
+
+ bool ParseCommandLineOptions(int argc, const char *const *argv,
+ const char *Overview, bool IgnoreErrors);
+
+ void addLiteralOption(Option &Opt, SubCommand *SC, const char *Name) {
+ if (Opt.hasArgStr())
+ return;
+ if (!SC->OptionsMap.insert(std::make_pair(Name, &Opt)).second) {
+ errs() << ProgramName << ": CommandLine Error: Option '" << Name
+ << "' registered more than once!\n";
+ report_fatal_error("inconsistency in registered CommandLine options");
+ }
+
+ // If we're adding this to all sub-commands, add it to the ones that have
+ // already been registered.
+ if (SC == &*AllSubCommands) {
+ for (const auto &Sub : RegisteredSubCommands) {
+ if (SC == Sub)
+ continue;
+ addLiteralOption(Opt, Sub, Name);
}
}
}
- void addOption(Option *O) {
+ void addLiteralOption(Option &Opt, const char *Name) {
+ if (Opt.Subs.empty())
+ addLiteralOption(Opt, &*TopLevelSubCommand, Name);
+ else {
+ for (auto SC : Opt.Subs)
+ addLiteralOption(Opt, SC, Name);
+ }
+ }
+
+ void addOption(Option *O, SubCommand *SC) {
bool HadErrors = false;
if (O->hasArgStr()) {
// Add argument to the argument map!
- if (!OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {
+ if (!SC->OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {
errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
<< "' registered more than once!\n";
HadErrors = true;
@@ -131,15 +153,15 @@ public:
// Remember information about positional options.
if (O->getFormattingFlag() == cl::Positional)
- PositionalOpts.push_back(O);
+ SC->PositionalOpts.push_back(O);
else if (O->getMiscFlags() & cl::Sink) // Remember sink options
- SinkOpts.push_back(O);
+ SC->SinkOpts.push_back(O);
else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) {
- if (ConsumeAfterOpt) {
+ if (SC->ConsumeAfterOpt) {
O->error("Cannot specify more than one option with cl::ConsumeAfter!");
HadErrors = true;
}
- ConsumeAfterOpt = O;
+ SC->ConsumeAfterOpt = O;
}
// Fail hard if there were errors. These are strictly unrecoverable and
@@ -148,64 +170,165 @@ public:
// linked LLVM distribution.
if (HadErrors)
report_fatal_error("inconsistency in registered CommandLine options");
+
+ // If we're adding this to all sub-commands, add it to the ones that have
+ // already been registered.
+ if (SC == &*AllSubCommands) {
+ for (const auto &Sub : RegisteredSubCommands) {
+ if (SC == Sub)
+ continue;
+ addOption(O, Sub);
+ }
+ }
}
- void removeOption(Option *O) {
+ void addOption(Option *O) {
+ if (O->Subs.empty()) {
+ addOption(O, &*TopLevelSubCommand);
+ } else {
+ for (auto SC : O->Subs)
+ addOption(O, SC);
+ }
+ }
+
+ void removeOption(Option *O, SubCommand *SC) {
SmallVector<StringRef, 16> OptionNames;
O->getExtraOptionNames(OptionNames);
if (O->hasArgStr())
OptionNames.push_back(O->ArgStr);
+
+ SubCommand &Sub = *SC;
for (auto Name : OptionNames)
- OptionsMap.erase(Name);
+ Sub.OptionsMap.erase(Name);
if (O->getFormattingFlag() == cl::Positional)
- for (auto Opt = PositionalOpts.begin(); Opt != PositionalOpts.end();
- ++Opt) {
+ for (auto Opt = Sub.PositionalOpts.begin();
+ Opt != Sub.PositionalOpts.end(); ++Opt) {
if (*Opt == O) {
- PositionalOpts.erase(Opt);
+ Sub.PositionalOpts.erase(Opt);
break;
}
}
else if (O->getMiscFlags() & cl::Sink)
- for (auto Opt = SinkOpts.begin(); Opt != SinkOpts.end(); ++Opt) {
+ for (auto Opt = Sub.SinkOpts.begin(); Opt != Sub.SinkOpts.end(); ++Opt) {
if (*Opt == O) {
- SinkOpts.erase(Opt);
+ Sub.SinkOpts.erase(Opt);
break;
}
}
- else if (O == ConsumeAfterOpt)
- ConsumeAfterOpt = nullptr;
+ else if (O == Sub.ConsumeAfterOpt)
+ Sub.ConsumeAfterOpt = nullptr;
}
- bool hasOptions() {
- return (!OptionsMap.empty() || !PositionalOpts.empty() ||
- nullptr != ConsumeAfterOpt);
+ void removeOption(Option *O) {
+ if (O->Subs.empty())
+ removeOption(O, &*TopLevelSubCommand);
+ else {
+ if (O->isInAllSubCommands()) {
+ for (auto SC : RegisteredSubCommands)
+ removeOption(O, SC);
+ } else {
+ for (auto SC : O->Subs)
+ removeOption(O, SC);
+ }
+ }
}
- void updateArgStr(Option *O, StringRef NewName) {
- if (!OptionsMap.insert(std::make_pair(NewName, O)).second) {
+ bool hasOptions(const SubCommand &Sub) const {
+ return (!Sub.OptionsMap.empty() || !Sub.PositionalOpts.empty() ||
+ nullptr != Sub.ConsumeAfterOpt);
+ }
+
+ bool hasOptions() const {
+ for (const auto &S : RegisteredSubCommands) {
+ if (hasOptions(*S))
+ return true;
+ }
+ return false;
+ }
+
+ SubCommand *getActiveSubCommand() { return ActiveSubCommand; }
+
+ void updateArgStr(Option *O, StringRef NewName, SubCommand *SC) {
+ SubCommand &Sub = *SC;
+ if (!Sub.OptionsMap.insert(std::make_pair(NewName, O)).second) {
errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
<< "' registered more than once!\n";
report_fatal_error("inconsistency in registered CommandLine options");
}
- OptionsMap.erase(O->ArgStr);
+ Sub.OptionsMap.erase(O->ArgStr);
+ }
+
+ void updateArgStr(Option *O, StringRef NewName) {
+ if (O->Subs.empty())
+ updateArgStr(O, NewName, &*TopLevelSubCommand);
+ else {
+ for (auto SC : O->Subs)
+ updateArgStr(O, NewName, SC);
+ }
}
void printOptionValues();
void registerCategory(OptionCategory *cat) {
- assert(std::count_if(RegisteredOptionCategories.begin(),
- RegisteredOptionCategories.end(),
- [cat](const OptionCategory *Category) {
- return cat->getName() == Category->getName();
- }) == 0 &&
+ assert(count_if(RegisteredOptionCategories,
+ [cat](const OptionCategory *Category) {
+ return cat->getName() == Category->getName();
+ }) == 0 &&
"Duplicate option categories");
RegisteredOptionCategories.insert(cat);
}
+ void registerSubCommand(SubCommand *sub) {
+ assert(count_if(RegisteredSubCommands,
+ [sub](const SubCommand *Sub) {
+ return (sub->getName() != nullptr) &&
+ (Sub->getName() == sub->getName());
+ }) == 0 &&
+ "Duplicate subcommands");
+ RegisteredSubCommands.insert(sub);
+
+ // For all options that have been registered for all subcommands, add the
+ // option to this subcommand now.
+ if (sub != &*AllSubCommands) {
+ for (auto &E : AllSubCommands->OptionsMap) {
+ Option *O = E.second;
+ if ((O->isPositional() || O->isSink() || O->isConsumeAfter()) ||
+ O->hasArgStr())
+ addOption(O, sub);
+ else
+ addLiteralOption(*O, sub, E.first().str().c_str());
+ }
+ }
+ }
+
+ void unregisterSubCommand(SubCommand *sub) {
+ RegisteredSubCommands.erase(sub);
+ }
+
+ void reset() {
+ ActiveSubCommand = nullptr;
+ ProgramName.clear();
+ ProgramOverview = nullptr;
+
+ MoreHelp.clear();
+ RegisteredOptionCategories.clear();
+
+ ResetAllOptionOccurrences();
+ RegisteredSubCommands.clear();
+
+ TopLevelSubCommand->reset();
+ AllSubCommands->reset();
+ registerSubCommand(&*TopLevelSubCommand);
+ registerSubCommand(&*AllSubCommands);
+ }
+
private:
- Option *LookupOption(StringRef &Arg, StringRef &Value);
+ SubCommand *ActiveSubCommand;
+
+ Option *LookupOption(SubCommand &Sub, StringRef &Arg, StringRef &Value);
+ SubCommand *LookupSubCommand(const char *Name);
};
} // namespace
@@ -240,6 +363,32 @@ void OptionCategory::registerCategory() {
GlobalParser->registerCategory(this);
}
+// A special subcommand representing no subcommand
+ManagedStatic<SubCommand> llvm::cl::TopLevelSubCommand;
+
+// A special subcommand that can be used to put an option into all subcommands.
+ManagedStatic<SubCommand> llvm::cl::AllSubCommands;
+
+void SubCommand::registerSubCommand() {
+ GlobalParser->registerSubCommand(this);
+}
+
+void SubCommand::unregisterSubCommand() {
+ GlobalParser->unregisterSubCommand(this);
+}
+
+void SubCommand::reset() {
+ PositionalOpts.clear();
+ SinkOpts.clear();
+ OptionsMap.clear();
+
+ ConsumeAfterOpt = nullptr;
+}
+
+SubCommand::operator bool() const {
+ return (GlobalParser->getActiveSubCommand() == this);
+}
+
//===----------------------------------------------------------------------===//
// Basic, shared command line option processing machinery.
//
@@ -247,25 +396,29 @@ void OptionCategory::registerCategory() {
/// LookupOption - Lookup the option specified by the specified option on the
/// command line. If there is a value specified (after an equal sign) return
/// that as well. This assumes that leading dashes have already been stripped.
-Option *CommandLineParser::LookupOption(StringRef &Arg, StringRef &Value) {
+Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg,
+ StringRef &Value) {
// Reject all dashes.
if (Arg.empty())
return nullptr;
+ assert(&Sub != &*AllSubCommands);
size_t EqualPos = Arg.find('=');
// If we have an equals sign, remember the value.
if (EqualPos == StringRef::npos) {
// Look up the option.
- StringMap<Option *>::const_iterator I = OptionsMap.find(Arg);
- return I != OptionsMap.end() ? I->second : nullptr;
+ auto I = Sub.OptionsMap.find(Arg);
+ if (I == Sub.OptionsMap.end())
+ return nullptr;
+
+ return I != Sub.OptionsMap.end() ? I->second : nullptr;
}
// If the argument before the = is a valid option name, we match. If not,
// return Arg unmolested.
- StringMap<Option *>::const_iterator I =
- OptionsMap.find(Arg.substr(0, EqualPos));
- if (I == OptionsMap.end())
+ auto I = Sub.OptionsMap.find(Arg.substr(0, EqualPos));
+ if (I == Sub.OptionsMap.end())
return nullptr;
Value = Arg.substr(EqualPos + 1);
@@ -273,6 +426,21 @@ Option *CommandLineParser::LookupOption(StringRef &Arg, StringRef &Value) {
return I->second;
}
+SubCommand *CommandLineParser::LookupSubCommand(const char *Name) {
+ if (Name == nullptr)
+ return &*TopLevelSubCommand;
+ for (auto S : RegisteredSubCommands) {
+ if (S == &*AllSubCommands)
+ continue;
+ if (S->getName() == nullptr)
+ continue;
+
+ if (StringRef(S->getName()) == StringRef(Name))
+ return S;
+ }
+ return &*TopLevelSubCommand;
+}
+
/// LookupNearestOption - Lookup the closest match to the option specified by
/// the specified option on the command line. If there is a value specified
/// (after an equal sign) return that as well. This assumes that leading dashes
@@ -515,8 +683,6 @@ static bool isWhitespace(char C) { return strchr(" \t\n\r\f\v", C); }
static bool isQuote(char C) { return C == '\"' || C == '\''; }
-static bool isGNUSpecial(char C) { return strchr("\\\"\' ", C); }
-
void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver,
SmallVectorImpl<const char *> &NewArgv,
bool MarkEOLs) {
@@ -534,9 +700,8 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver,
break;
}
- // Backslashes can escape backslashes, spaces, and other quotes. Otherwise
- // they are literal. This makes it much easier to read Windows file paths.
- if (I + 1 < E && Src[I] == '\\' && isGNUSpecial(Src[I + 1])) {
+ // Backslash escapes the next character.
+ if (I + 1 < E && Src[I] == '\\') {
++I; // Skip the escape.
Token.push_back(Src[I]);
continue;
@@ -546,8 +711,8 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver,
if (isQuote(Src[I])) {
char Quote = Src[I++];
while (I != E && Src[I] != Quote) {
- // Backslashes are literal, unless they escape a special character.
- if (Src[I] == '\\' && I + 1 != E && isGNUSpecial(Src[I + 1]))
+ // Backslash escapes the next character.
+ if (Src[I] == '\\' && I + 1 != E)
++I;
Token.push_back(Src[I]);
++I;
@@ -787,9 +952,28 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar,
assert(envVar && "Environment variable name missing");
// Get the environment variable they want us to parse options out of.
+#ifdef _WIN32
+ std::wstring wenvVar;
+ if (!llvm::ConvertUTF8toWide(envVar, wenvVar)) {
+ assert(false &&
+ "Unicode conversion of environment variable name failed");
+ return;
+ }
+ const wchar_t *wenvValue = _wgetenv(wenvVar.c_str());
+ if (!wenvValue)
+ return;
+ std::string envValueBuffer;
+ if (!llvm::convertWideToUTF8(wenvValue, envValueBuffer)) {
+ assert(false &&
+ "Unicode conversion of environment variable value failed");
+ return;
+ }
+ const char *envValue = envValueBuffer.c_str();
+#else
const char *envValue = getenv(envVar);
if (!envValue)
return;
+#endif
// Get program's "name", which we wouldn't know without the caller
// telling us.
@@ -805,14 +989,25 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar,
ParseCommandLineOptions(newArgc, &newArgv[0], Overview);
}
-void cl::ParseCommandLineOptions(int argc, const char *const *argv,
- const char *Overview) {
- GlobalParser->ParseCommandLineOptions(argc, argv, Overview);
+bool cl::ParseCommandLineOptions(int argc, const char *const *argv,
+ const char *Overview, bool IgnoreErrors) {
+ return GlobalParser->ParseCommandLineOptions(argc, argv, Overview,
+ IgnoreErrors);
}
-void CommandLineParser::ParseCommandLineOptions(int argc,
+void CommandLineParser::ResetAllOptionOccurrences() {
+ // So that we can parse different command lines multiple times in succession
+ // we reset all option values to look like they have never been seen before.
+ for (auto SC : RegisteredSubCommands) {
+ for (auto &O : SC->OptionsMap)
+ O.second->reset();
+ }
+}
+
+bool CommandLineParser::ParseCommandLineOptions(int argc,
const char *const *argv,
- const char *Overview) {
+ const char *Overview,
+ bool IgnoreErrors) {
assert(hasOptions() && "No options specified!");
// Expand response files.
@@ -835,6 +1030,23 @@ void CommandLineParser::ParseCommandLineOptions(int argc,
// Determine whether or not there are an unlimited number of positionals
bool HasUnlimitedPositionals = false;
+ int FirstArg = 1;
+ SubCommand *ChosenSubCommand = &*TopLevelSubCommand;
+ if (argc >= 2 && argv[FirstArg][0] != '-') {
+ // If the first argument specifies a valid subcommand, start processing
+ // options from the second argument.
+ ChosenSubCommand = LookupSubCommand(argv[FirstArg]);
+ if (ChosenSubCommand != &*TopLevelSubCommand)
+ FirstArg = 2;
+ }
+ GlobalParser->ActiveSubCommand = ChosenSubCommand;
+
+ assert(ChosenSubCommand);
+ auto &ConsumeAfterOpt = ChosenSubCommand->ConsumeAfterOpt;
+ auto &PositionalOpts = ChosenSubCommand->PositionalOpts;
+ auto &SinkOpts = ChosenSubCommand->SinkOpts;
+ auto &OptionsMap = ChosenSubCommand->OptionsMap;
+
if (ConsumeAfterOpt) {
assert(PositionalOpts.size() > 0 &&
"Cannot specify cl::ConsumeAfter without a positional argument!");
@@ -850,23 +1062,28 @@ void CommandLineParser::ParseCommandLineOptions(int argc,
else if (ConsumeAfterOpt) {
// ConsumeAfter cannot be combined with "optional" positional options
// unless there is only one positional argument...
- if (PositionalOpts.size() > 1)
- ErrorParsing |= Opt->error(
- "error - this positional option will never be matched, "
- "because it does not Require a value, and a "
- "cl::ConsumeAfter option is active!");
+ if (PositionalOpts.size() > 1) {
+ if (!IgnoreErrors)
+ Opt->error("error - this positional option will never be matched, "
+ "because it does not Require a value, and a "
+ "cl::ConsumeAfter option is active!");
+ ErrorParsing = true;
+ }
} else if (UnboundedFound && !Opt->hasArgStr()) {
// This option does not "require" a value... Make sure this option is
// not specified after an option that eats all extra arguments, or this
// one will never get any!
//
- ErrorParsing |= Opt->error("error - option can never match, because "
- "another positional argument will match an "
- "unbounded number of values, and this option"
- " does not require a value!");
- errs() << ProgramName << ": CommandLine Error: Option '" << Opt->ArgStr
- << "' is all messed up!\n";
- errs() << PositionalOpts.size();
+ if (!IgnoreErrors) {
+ Opt->error("error - option can never match, because "
+ "another positional argument will match an "
+ "unbounded number of values, and this option"
+ " does not require a value!");
+ errs() << ProgramName << ": CommandLine Error: Option '"
+ << Opt->ArgStr << "' is all messed up!\n";
+ errs() << PositionalOpts.size();
+ }
+ ErrorParsing = true;
}
UnboundedFound |= EatsUnboundedNumberOfValues(Opt);
}
@@ -885,7 +1102,7 @@ void CommandLineParser::ParseCommandLineOptions(int argc,
// Loop over all of the arguments... processing them.
bool DashDashFound = false; // Have we read '--'?
- for (int i = 1; i < argc; ++i) {
+ for (int i = FirstArg; i < argc; ++i) {
Option *Handler = nullptr;
Option *NearestHandler = nullptr;
std::string NearestHandlerString;
@@ -932,7 +1149,7 @@ void CommandLineParser::ParseCommandLineOptions(int argc,
while (!ArgName.empty() && ArgName[0] == '-')
ArgName = ArgName.substr(1);
- Handler = LookupOption(ArgName, Value);
+ Handler = LookupOption(*ChosenSubCommand, ArgName, Value);
if (!Handler || Handler->getFormattingFlag() != cl::Positional) {
ProvidePositionalOption(ActivePositionalArg, argv[i], i);
continue; // We are done!
@@ -944,7 +1161,7 @@ void CommandLineParser::ParseCommandLineOptions(int argc,
while (!ArgName.empty() && ArgName[0] == '-')
ArgName = ArgName.substr(1);
- Handler = LookupOption(ArgName, Value);
+ Handler = LookupOption(*ChosenSubCommand, ArgName, Value);
// Check to see if this "option" is really a prefixed or grouped argument.
if (!Handler)
@@ -960,13 +1177,15 @@ void CommandLineParser::ParseCommandLineOptions(int argc,
if (!Handler) {
if (SinkOpts.empty()) {
- errs() << ProgramName << ": Unknown command line argument '" << argv[i]
- << "'. Try: '" << argv[0] << " -help'\n";
-
- if (NearestHandler) {
- // If we know a near match, report it as well.
- errs() << ProgramName << ": Did you mean '-" << NearestHandlerString
- << "'?\n";
+ if (!IgnoreErrors) {
+ errs() << ProgramName << ": Unknown command line argument '"
+ << argv[i] << "'. Try: '" << argv[0] << " -help'\n";
+
+ if (NearestHandler) {
+ // If we know a near match, report it as well.
+ errs() << ProgramName << ": Did you mean '-" << NearestHandlerString
+ << "'?\n";
+ }
}
ErrorParsing = true;
@@ -989,17 +1208,21 @@ void CommandLineParser::ParseCommandLineOptions(int argc,
// Check and handle positional arguments now...
if (NumPositionalRequired > PositionalVals.size()) {
- errs() << ProgramName
- << ": Not enough positional command line arguments specified!\n"
- << "Must specify at least " << NumPositionalRequired
- << " positional arguments: See: " << argv[0] << " -help\n";
+ if (!IgnoreErrors) {
+ errs() << ProgramName
+ << ": Not enough positional command line arguments specified!\n"
+ << "Must specify at least " << NumPositionalRequired
+ << " positional arguments: See: " << argv[0] << " -help\n";
+ }
ErrorParsing = true;
} else if (!HasUnlimitedPositionals &&
PositionalVals.size() > PositionalOpts.size()) {
- errs() << ProgramName << ": Too many positional arguments specified!\n"
- << "Can specify at most " << PositionalOpts.size()
- << " positional arguments: See: " << argv[0] << " -help\n";
+ if (!IgnoreErrors) {
+ errs() << ProgramName << ": Too many positional arguments specified!\n"
+ << "Can specify at most " << PositionalOpts.size()
+ << " positional arguments: See: " << argv[0] << " -help\n";
+ }
ErrorParsing = true;
} else if (!ConsumeAfterOpt) {
@@ -1094,8 +1317,12 @@ void CommandLineParser::ParseCommandLineOptions(int argc,
MoreHelp.clear();
// If we had an error processing our arguments, don't let the program execute
- if (ErrorParsing)
- exit(1);
+ if (ErrorParsing) {
+ if (!IgnoreErrors)
+ exit(1);
+ return false;
+ }
+ return true;
}
//===----------------------------------------------------------------------===//
@@ -1416,7 +1643,7 @@ PRINT_OPT_DIFF(float)
PRINT_OPT_DIFF(char)
void parser<std::string>::printOptionDiff(const Option &O, StringRef V,
- OptionValue<std::string> D,
+ const OptionValue<std::string> &D,
size_t GlobalWidth) const {
printOptionName(O, GlobalWidth);
outs() << "= " << V;
@@ -1445,11 +1672,16 @@ static int OptNameCompare(const std::pair<const char *, Option *> *LHS,
return strcmp(LHS->first, RHS->first);
}
+static int SubNameCompare(const std::pair<const char *, SubCommand *> *LHS,
+ const std::pair<const char *, SubCommand *> *RHS) {
+ return strcmp(LHS->first, RHS->first);
+}
+
// Copy Options into a vector so we can sort them as we like.
static void sortOpts(StringMap<Option *> &OptMap,
SmallVectorImpl<std::pair<const char *, Option *>> &Opts,
bool ShowHidden) {
- SmallPtrSet<Option *, 128> OptionSet; // Duplicate option detection.
+ SmallPtrSet<Option *, 32> OptionSet; // Duplicate option detection.
for (StringMap<Option *>::iterator I = OptMap.begin(), E = OptMap.end();
I != E; ++I) {
@@ -1473,6 +1705,17 @@ static void sortOpts(StringMap<Option *> &OptMap,
array_pod_sort(Opts.begin(), Opts.end(), OptNameCompare);
}
+static void
+sortSubCommands(const SmallPtrSetImpl<SubCommand *> &SubMap,
+ SmallVectorImpl<std::pair<const char *, SubCommand *>> &Subs) {
+ for (const auto &S : SubMap) {
+ if (S->getName() == nullptr)
+ continue;
+ Subs.push_back(std::make_pair(S->getName(), S));
+ }
+ array_pod_sort(Subs.begin(), Subs.end(), SubNameCompare);
+}
+
namespace {
class HelpPrinter {
@@ -1480,12 +1723,25 @@ protected:
const bool ShowHidden;
typedef SmallVector<std::pair<const char *, Option *>, 128>
StrOptionPairVector;
+ typedef SmallVector<std::pair<const char *, SubCommand *>, 128>
+ StrSubCommandPairVector;
// Print the options. Opts is assumed to be alphabetically sorted.
virtual void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) {
for (size_t i = 0, e = Opts.size(); i != e; ++i)
Opts[i].second->printOptionInfo(MaxArgLen);
}
+ void printSubCommands(StrSubCommandPairVector &Subs, size_t MaxSubLen) {
+ for (const auto &S : Subs) {
+ outs() << " " << S.first;
+ if (S.second->getDescription()) {
+ outs().indent(MaxSubLen - strlen(S.first));
+ outs() << " - " << S.second->getDescription();
+ }
+ outs() << "\n";
+ }
+ }
+
public:
explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) {}
virtual ~HelpPrinter() {}
@@ -1495,23 +1751,56 @@ public:
if (!Value)
return;
+ SubCommand *Sub = GlobalParser->getActiveSubCommand();
+ auto &OptionsMap = Sub->OptionsMap;
+ auto &PositionalOpts = Sub->PositionalOpts;
+ auto &ConsumeAfterOpt = Sub->ConsumeAfterOpt;
+
StrOptionPairVector Opts;
- sortOpts(GlobalParser->OptionsMap, Opts, ShowHidden);
+ sortOpts(OptionsMap, Opts, ShowHidden);
+
+ StrSubCommandPairVector Subs;
+ sortSubCommands(GlobalParser->RegisteredSubCommands, Subs);
if (GlobalParser->ProgramOverview)
outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n";
- outs() << "USAGE: " << GlobalParser->ProgramName << " [options]";
+ if (Sub == &*TopLevelSubCommand)
+ outs() << "USAGE: " << GlobalParser->ProgramName
+ << " [subcommand] [options]";
+ else {
+ if (Sub->getDescription() != nullptr) {
+ outs() << "SUBCOMMAND '" << Sub->getName()
+ << "': " << Sub->getDescription() << "\n\n";
+ }
+ outs() << "USAGE: " << GlobalParser->ProgramName << " " << Sub->getName()
+ << " [options]";
+ }
- for (auto Opt : GlobalParser->PositionalOpts) {
+ for (auto Opt : PositionalOpts) {
if (Opt->hasArgStr())
outs() << " --" << Opt->ArgStr;
outs() << " " << Opt->HelpStr;
}
// Print the consume after option info if it exists...
- if (GlobalParser->ConsumeAfterOpt)
- outs() << " " << GlobalParser->ConsumeAfterOpt->HelpStr;
+ if (ConsumeAfterOpt)
+ outs() << " " << ConsumeAfterOpt->HelpStr;
+
+ if (Sub == &*TopLevelSubCommand && Subs.size() > 2) {
+ // Compute the maximum subcommand length...
+ size_t MaxSubLen = 0;
+ for (size_t i = 0, e = Subs.size(); i != e; ++i)
+ MaxSubLen = std::max(MaxSubLen, strlen(Subs[i].first));
+
+ outs() << "\n\n";
+ outs() << "SUBCOMMANDS:\n\n";
+ printSubCommands(Subs, MaxSubLen);
+ outs() << "\n";
+ outs() << " Type \"" << GlobalParser->ProgramName
+ << " <subcommand> -help\" to get more help on a specific "
+ "subcommand";
+ }
outs() << "\n\n";
@@ -1589,7 +1878,8 @@ protected:
E = SortedCategories.end();
Category != E; ++Category) {
// Hide empty categories for -help, but show for -help-hidden.
- bool IsEmptyCategory = CategorizedOptions[*Category].size() == 0;
+ const auto &CategoryOptions = CategorizedOptions[*Category];
+ bool IsEmptyCategory = CategoryOptions.empty();
if (!ShowHidden && IsEmptyCategory)
continue;
@@ -1610,11 +1900,8 @@ protected:
continue;
}
// Loop over the options in the category and print.
- for (std::vector<Option *>::const_iterator
- Opt = CategorizedOptions[*Category].begin(),
- E = CategorizedOptions[*Category].end();
- Opt != E; ++Opt)
- (*Opt)->printOptionInfo(MaxArgLen);
+ for (const Option *Opt : CategoryOptions)
+ Opt->printOptionInfo(MaxArgLen);
}
}
};
@@ -1662,12 +1949,13 @@ static cl::opt<HelpPrinter, true, parser<bool>> HLOp(
"help-list",
cl::desc("Display list of available options (-help-list-hidden for more)"),
cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed,
- cl::cat(GenericCategory));
+ cl::cat(GenericCategory), cl::sub(*AllSubCommands));
static cl::opt<HelpPrinter, true, parser<bool>>
HLHOp("help-list-hidden", cl::desc("Display list of all available options"),
cl::location(UncategorizedHiddenPrinter), cl::Hidden,
- cl::ValueDisallowed, cl::cat(GenericCategory));
+ cl::ValueDisallowed, cl::cat(GenericCategory),
+ cl::sub(*AllSubCommands));
// Define uncategorized/categorized help printers. These printers change their
// behaviour at runtime depending on whether one or more Option categories have
@@ -1675,22 +1963,23 @@ static cl::opt<HelpPrinter, true, parser<bool>>
static cl::opt<HelpPrinterWrapper, true, parser<bool>>
HOp("help", cl::desc("Display available options (-help-hidden for more)"),
cl::location(WrappedNormalPrinter), cl::ValueDisallowed,
- cl::cat(GenericCategory));
+ cl::cat(GenericCategory), cl::sub(*AllSubCommands));
static cl::opt<HelpPrinterWrapper, true, parser<bool>>
HHOp("help-hidden", cl::desc("Display all available options"),
cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed,
- cl::cat(GenericCategory));
+ cl::cat(GenericCategory), cl::sub(*AllSubCommands));
static cl::opt<bool> PrintOptions(
"print-options",
cl::desc("Print non-default options after command line parsing"),
- cl::Hidden, cl::init(false), cl::cat(GenericCategory));
+ cl::Hidden, cl::init(false), cl::cat(GenericCategory),
+ cl::sub(*AllSubCommands));
static cl::opt<bool> PrintAllOptions(
"print-all-options",
cl::desc("Print all option values after command line parsing"), cl::Hidden,
- cl::init(false), cl::cat(GenericCategory));
+ cl::init(false), cl::cat(GenericCategory), cl::sub(*AllSubCommands));
void HelpPrinterWrapper::operator=(bool Value) {
if (!Value)
@@ -1717,7 +2006,7 @@ void CommandLineParser::printOptionValues() {
return;
SmallVector<std::pair<const char *, Option *>, 128> Opts;
- sortOpts(OptionsMap, Opts, /*ShowHidden*/ true);
+ sortOpts(ActiveSubCommand->OptionsMap, Opts, /*ShowHidden*/ true);
// Compute the maximum argument length...
size_t MaxArgLen = 0;
@@ -1737,8 +2026,12 @@ class VersionPrinter {
public:
void print() {
raw_ostream &OS = outs();
- OS << "LLVM (http://llvm.org/):\n"
- << " " << PACKAGE_NAME << " version " << PACKAGE_VERSION;
+#ifdef PACKAGE_VENDOR
+ OS << PACKAGE_VENDOR << " ";
+#else
+ OS << "LLVM (http://llvm.org/):\n ";
+#endif
+ OS << PACKAGE_NAME << " version " << PACKAGE_VERSION;
#ifdef LLVM_VERSION_INFO
OS << " " << LLVM_VERSION_INFO;
#endif
@@ -1755,9 +2048,6 @@ public:
if (CPU == "generic")
CPU = "(unknown)";
OS << ".\n"
-#if (ENABLE_TIMESTAMPS == 1)
- << " Built " << __DATE__ << " (" << __TIME__ << ").\n"
-#endif
<< " Default target: " << sys::getDefaultTargetTriple() << '\n'
<< " Host CPU: " << CPU << '\n';
}
@@ -1825,22 +2115,26 @@ void cl::AddExtraVersionPrinter(void (*func)()) {
ExtraVersionPrinters->push_back(func);
}
-StringMap<Option *> &cl::getRegisteredOptions() {
- return GlobalParser->OptionsMap;
+StringMap<Option *> &cl::getRegisteredOptions(SubCommand &Sub) {
+ auto &Subs = GlobalParser->RegisteredSubCommands;
+ (void)Subs;
+ assert(std::find(Subs.begin(), Subs.end(), &Sub) != Subs.end());
+ return Sub.OptionsMap;
}
-void cl::HideUnrelatedOptions(cl::OptionCategory &Category) {
- for (auto &I : GlobalParser->OptionsMap) {
+void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {
+ for (auto &I : Sub.OptionsMap) {
if (I.second->Category != &Category &&
I.second->Category != &GenericCategory)
I.second->setHiddenFlag(cl::ReallyHidden);
}
}
-void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories) {
+void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
+ SubCommand &Sub) {
auto CategoriesBegin = Categories.begin();
auto CategoriesEnd = Categories.end();
- for (auto &I : GlobalParser->OptionsMap) {
+ for (auto &I : Sub.OptionsMap) {
if (std::find(CategoriesBegin, CategoriesEnd, I.second->Category) ==
CategoriesEnd &&
I.second->Category != &GenericCategory)
@@ -1848,7 +2142,12 @@ void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories) {
}
}
+void cl::ResetCommandLineParser() { GlobalParser->reset(); }
+void cl::ResetAllOptionOccurrences() {
+ GlobalParser->ResetAllOptionOccurrences();
+}
+
void LLVMParseCommandLineOptions(int argc, const char *const *argv,
const char *Overview) {
- llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
+ llvm::cl::ParseCommandLineOptions(argc, argv, Overview, true);
}
diff --git a/contrib/llvm/lib/Support/ConvertUTFWrapper.cpp b/contrib/llvm/lib/Support/ConvertUTFWrapper.cpp
index 1bbef23..217cedb 100644
--- a/contrib/llvm/lib/Support/ConvertUTFWrapper.cpp
+++ b/contrib/llvm/lib/Support/ConvertUTFWrapper.cpp
@@ -8,6 +8,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SwapByteOrder.h"
#include <string>
#include <vector>
@@ -36,7 +39,7 @@ bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source,
ConversionFlags flags = strictConversion;
result = ConvertUTF8toUTF16(
&sourceStart, sourceStart + Source.size(),
- &targetStart, targetStart + 2*Source.size(), flags);
+ &targetStart, targetStart + Source.size(), flags);
if (result == conversionOK)
ResultPtr = reinterpret_cast<char*>(targetStart);
else
@@ -49,7 +52,7 @@ bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source,
ConversionFlags flags = strictConversion;
result = ConvertUTF8toUTF32(
&sourceStart, sourceStart + Source.size(),
- &targetStart, targetStart + 4*Source.size(), flags);
+ &targetStart, targetStart + Source.size(), flags);
if (result == conversionOK)
ResultPtr = reinterpret_cast<char*>(targetStart);
else
@@ -130,6 +133,13 @@ bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) {
return true;
}
+bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out)
+{
+ return convertUTF16ToUTF8String(
+ llvm::ArrayRef<char>(reinterpret_cast<const char *>(Src.data()),
+ Src.size() * sizeof(UTF16)), Out);
+}
+
bool convertUTF8ToUTF16String(StringRef SrcUTF8,
SmallVectorImpl<UTF16> &DstUTF16) {
assert(DstUTF16.empty());
@@ -168,5 +178,74 @@ bool convertUTF8ToUTF16String(StringRef SrcUTF8,
return true;
}
+static_assert(sizeof(wchar_t) == 1 || sizeof(wchar_t) == 2 ||
+ sizeof(wchar_t) == 4,
+ "Expected wchar_t to be 1, 2, or 4 bytes");
+
+template <typename TResult>
+static inline bool ConvertUTF8toWideInternal(llvm::StringRef Source,
+ TResult &Result) {
+ // Even in the case of UTF-16, the number of bytes in a UTF-8 string is
+ // at least as large as the number of elements in the resulting wide
+ // string, because surrogate pairs take at least 4 bytes in UTF-8.
+ Result.resize(Source.size() + 1);
+ char *ResultPtr = reinterpret_cast<char *>(&Result[0]);
+ const UTF8 *ErrorPtr;
+ if (!ConvertUTF8toWide(sizeof(wchar_t), Source, ResultPtr, ErrorPtr)) {
+ Result.clear();
+ return false;
+ }
+ Result.resize(reinterpret_cast<wchar_t *>(ResultPtr) - &Result[0]);
+ return true;
+}
+
+bool ConvertUTF8toWide(llvm::StringRef Source, std::wstring &Result) {
+ return ConvertUTF8toWideInternal(Source, Result);
+}
+
+bool ConvertUTF8toWide(const char *Source, std::wstring &Result) {
+ if (!Source) {
+ Result.clear();
+ return true;
+ }
+ return ConvertUTF8toWide(llvm::StringRef(Source), Result);
+}
+
+bool convertWideToUTF8(const std::wstring &Source, std::string &Result) {
+ if (sizeof(wchar_t) == 1) {
+ const UTF8 *Start = reinterpret_cast<const UTF8 *>(Source.data());
+ const UTF8 *End =
+ reinterpret_cast<const UTF8 *>(Source.data() + Source.size());
+ if (!isLegalUTF8String(&Start, End))
+ return false;
+ Result.resize(Source.size());
+ memcpy(&Result[0], Source.data(), Source.size());
+ return true;
+ } else if (sizeof(wchar_t) == 2) {
+ return convertUTF16ToUTF8String(
+ llvm::ArrayRef<UTF16>(reinterpret_cast<const UTF16 *>(Source.data()),
+ Source.size()),
+ Result);
+ } else if (sizeof(wchar_t) == 4) {
+ const UTF32 *Start = reinterpret_cast<const UTF32 *>(Source.data());
+ const UTF32 *End =
+ reinterpret_cast<const UTF32 *>(Source.data() + Source.size());
+ Result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * Source.size());
+ UTF8 *ResultPtr = reinterpret_cast<UTF8 *>(&Result[0]);
+ UTF8 *ResultEnd = reinterpret_cast<UTF8 *>(&Result[0] + Result.size());
+ if (ConvertUTF32toUTF8(&Start, End, &ResultPtr, ResultEnd,
+ strictConversion) == conversionOK) {
+ Result.resize(reinterpret_cast<char *>(ResultPtr) - &Result[0]);
+ return true;
+ } else {
+ Result.clear();
+ return false;
+ }
+ } else {
+ llvm_unreachable(
+ "Control should never reach this point; see static_assert further up");
+ }
+}
+
} // end namespace llvm
diff --git a/contrib/llvm/lib/Support/CrashRecoveryContext.cpp b/contrib/llvm/lib/Support/CrashRecoveryContext.cpp
index 3f4ef9d..98865f5 100644
--- a/contrib/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/contrib/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -31,7 +31,6 @@ struct CrashRecoveryContextImpl {
const CrashRecoveryContextImpl *Next;
CrashRecoveryContext *CRC;
- std::string Backtrace;
::jmp_buf JumpBuffer;
volatile unsigned Failed : 1;
unsigned SwitchedThread : 1;
@@ -335,13 +334,6 @@ void CrashRecoveryContext::HandleCrash() {
CRCI->HandleCrash();
}
-const std::string &CrashRecoveryContext::getBacktrace() const {
- CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *) Impl;
- assert(CRC && "Crash recovery context never initialized!");
- assert(CRC->Failed && "No crash was detected!");
- return CRC->Backtrace;
-}
-
// FIXME: Portability.
static void setThreadBackgroundPriority() {
#ifdef __APPLE__
diff --git a/contrib/llvm/lib/Support/Dwarf.cpp b/contrib/llvm/lib/Support/Dwarf.cpp
index 7d72256..7aea05d 100644
--- a/contrib/llvm/lib/Support/Dwarf.cpp
+++ b/contrib/llvm/lib/Support/Dwarf.cpp
@@ -384,23 +384,22 @@ const char *llvm::dwarf::CaseString(unsigned Case) {
return nullptr;
}
-const char *llvm::dwarf::ConventionString(unsigned Convention) {
- switch (Convention) {
- case DW_CC_normal: return "DW_CC_normal";
- case DW_CC_program: return "DW_CC_program";
- case DW_CC_nocall: return "DW_CC_nocall";
- case DW_CC_lo_user: return "DW_CC_lo_user";
- case DW_CC_hi_user: return "DW_CC_hi_user";
- case DW_CC_GNU_borland_fastcall_i386: return "DW_CC_GNU_borland_fastcall_i386";
- case DW_CC_BORLAND_safecall: return "DW_CC_BORLAND_safecall";
- case DW_CC_BORLAND_stdcall: return "DW_CC_BORLAND_stdcall";
- case DW_CC_BORLAND_pascal: return "DW_CC_BORLAND_pascal";
- case DW_CC_BORLAND_msfastcall: return "DW_CC_BORLAND_msfastcall";
- case DW_CC_BORLAND_msreturn: return "DW_CC_BORLAND_msreturn";
- case DW_CC_BORLAND_thiscall: return "DW_CC_BORLAND_thiscall";
- case DW_CC_BORLAND_fastcall: return "DW_CC_BORLAND_fastcall";
+const char *llvm::dwarf::ConventionString(unsigned CC) {
+ switch (CC) {
+ default:
+ return nullptr;
+#define HANDLE_DW_CC(ID, NAME) \
+ case DW_CC_##NAME: \
+ return "DW_CC_" #NAME;
+#include "llvm/Support/Dwarf.def"
}
- return nullptr;
+}
+
+unsigned llvm::dwarf::getCallingConvention(StringRef CCString) {
+ return StringSwitch<unsigned>(CCString)
+#define HANDLE_DW_CC(ID, NAME) .Case("DW_CC_" #NAME, DW_CC_##NAME)
+#include "llvm/Support/Dwarf.def"
+ .Default(0);
}
const char *llvm::dwarf::InlineCodeString(unsigned Code) {
@@ -546,6 +545,12 @@ const char *llvm::dwarf::ApplePropertyString(unsigned Prop) {
return "DW_APPLE_PROPERTY_strong";
case DW_APPLE_PROPERTY_unsafe_unretained:
return "DW_APPLE_PROPERTY_unsafe_unretained";
+ case DW_APPLE_PROPERTY_nullability:
+ return "DW_APPLE_PROPERTY_nullability";
+ case DW_APPLE_PROPERTY_null_resettable:
+ return "DW_APPLE_PROPERTY_null_resettable";
+ case DW_APPLE_PROPERTY_class:
+ return "DW_APPLE_PROPERTY_class";
}
return nullptr;
}
diff --git a/contrib/llvm/lib/Support/Error.cpp b/contrib/llvm/lib/Support/Error.cpp
new file mode 100644
index 0000000..6b22691
--- /dev/null
+++ b/contrib/llvm/lib/Support/Error.cpp
@@ -0,0 +1,113 @@
+//===----- lib/Support/Error.cpp - Error and associated utilities ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Error.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+
+
+using namespace llvm;
+
+namespace {
+
+ enum class ErrorErrorCode : int {
+ MultipleErrors = 1,
+ InconvertibleError
+ };
+
+ // FIXME: This class is only here to support the transition to llvm::Error. It
+ // will be removed once this transition is complete. Clients should prefer to
+ // deal with the Error value directly, rather than converting to error_code.
+ class ErrorErrorCategory : public std::error_category {
+ public:
+ const char *name() const LLVM_NOEXCEPT override { return "Error"; }
+
+ std::string message(int condition) const override {
+ switch (static_cast<ErrorErrorCode>(condition)) {
+ case ErrorErrorCode::MultipleErrors:
+ return "Multiple errors";
+ case ErrorErrorCode::InconvertibleError:
+ return "Inconvertible error value. An error has occurred that could "
+ "not be converted to a known std::error_code. Please file a "
+ "bug.";
+ }
+ llvm_unreachable("Unhandled error code");
+ }
+ };
+
+}
+
+static ManagedStatic<ErrorErrorCategory> ErrorErrorCat;
+
+namespace llvm {
+
+void ErrorInfoBase::anchor() {}
+char ErrorInfoBase::ID = 0;
+char ErrorList::ID = 0;
+char ECError::ID = 0;
+char StringError::ID = 0;
+
+void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) {
+ if (!E)
+ return;
+ OS << ErrorBanner;
+ handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
+ EI.log(OS);
+ OS << "\n";
+ });
+}
+
+
+std::error_code ErrorList::convertToErrorCode() const {
+ return std::error_code(static_cast<int>(ErrorErrorCode::MultipleErrors),
+ *ErrorErrorCat);
+}
+
+std::error_code inconvertibleErrorCode() {
+ return std::error_code(static_cast<int>(ErrorErrorCode::InconvertibleError),
+ *ErrorErrorCat);
+}
+
+Error errorCodeToError(std::error_code EC) {
+ if (!EC)
+ return Error::success();
+ return Error(llvm::make_unique<ECError>(ECError(EC)));
+}
+
+std::error_code errorToErrorCode(Error Err) {
+ std::error_code EC;
+ handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
+ EC = EI.convertToErrorCode();
+ });
+ if (EC == inconvertibleErrorCode())
+ report_fatal_error(EC.message());
+ return EC;
+}
+
+StringError::StringError(const Twine &S, std::error_code EC)
+ : Msg(S.str()), EC(EC) {}
+
+void StringError::log(raw_ostream &OS) const { OS << Msg; }
+
+std::error_code StringError::convertToErrorCode() const {
+ return EC;
+}
+
+void report_fatal_error(Error Err, bool GenCrashDiag) {
+ assert(Err && "report_fatal_error called with success value");
+ std::string ErrMsg;
+ {
+ raw_string_ostream ErrStream(ErrMsg);
+ logAllUnhandledErrors(std::move(Err), ErrStream, "");
+ }
+ report_fatal_error(ErrMsg);
+}
+
+}
diff --git a/contrib/llvm/lib/Support/ErrorHandling.cpp b/contrib/llvm/lib/Support/ErrorHandling.cpp
index 2808bd3..a7d3a18 100644
--- a/contrib/llvm/lib/Support/ErrorHandling.cpp
+++ b/contrib/llvm/lib/Support/ErrorHandling.cpp
@@ -19,6 +19,7 @@
#include "llvm/Config/config.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
diff --git a/contrib/llvm/lib/Support/FileUtilities.cpp b/contrib/llvm/lib/Support/FileUtilities.cpp
index 5316f04..c6a58cc 100644
--- a/contrib/llvm/lib/Support/FileUtilities.cpp
+++ b/contrib/llvm/lib/Support/FileUtilities.cpp
@@ -217,8 +217,10 @@ int llvm::DiffFilesWithTolerance(StringRef NameA,
bool CompareFailed = false;
while (1) {
// Scan for the end of file or next difference.
- while (F1P < File1End && F2P < File2End && *F1P == *F2P)
- ++F1P, ++F2P;
+ while (F1P < File1End && F2P < File2End && *F1P == *F2P) {
+ ++F1P;
+ ++F2P;
+ }
if (F1P >= File1End || F2P >= File2End) break;
diff --git a/contrib/llvm/lib/Support/FoldingSet.cpp b/contrib/llvm/lib/Support/FoldingSet.cpp
index bb0ec2d..52baf86 100644
--- a/contrib/llvm/lib/Support/FoldingSet.cpp
+++ b/contrib/llvm/lib/Support/FoldingSet.cpp
@@ -266,12 +266,12 @@ void FoldingSetImpl::clear() {
NumNodes = 0;
}
-/// GrowHashTable - Double the size of the hash table and rehash everything.
-///
-void FoldingSetImpl::GrowHashTable() {
+void FoldingSetImpl::GrowBucketCount(unsigned NewBucketCount) {
+ assert((NewBucketCount > NumBuckets) && "Can't shrink a folding set with GrowBucketCount");
+ assert(isPowerOf2_32(NewBucketCount) && "Bad bucket count!");
void **OldBuckets = Buckets;
unsigned OldNumBuckets = NumBuckets;
- NumBuckets <<= 1;
+ NumBuckets = NewBucketCount;
// Clear out new buckets.
Buckets = AllocateBuckets(NumBuckets);
@@ -298,6 +298,21 @@ void FoldingSetImpl::GrowHashTable() {
free(OldBuckets);
}
+/// GrowHashTable - Double the size of the hash table and rehash everything.
+///
+void FoldingSetImpl::GrowHashTable() {
+ GrowBucketCount(NumBuckets * 2);
+}
+
+void FoldingSetImpl::reserve(unsigned EltCount) {
+ // This will give us somewhere between EltCount / 2 and
+ // EltCount buckets. This puts us in the load factor
+ // range of 1.0 - 2.0.
+ if(EltCount < capacity())
+ return;
+ GrowBucketCount(PowerOf2Floor(EltCount));
+}
+
/// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
/// return it. If not, return the insertion token that will make insertion
/// faster.
@@ -330,7 +345,7 @@ FoldingSetImpl::Node
void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) {
assert(!N->getNextInBucket());
// Do we need to grow the hashtable?
- if (NumNodes+1 > NumBuckets*2) {
+ if (NumNodes+1 > capacity()) {
GrowHashTable();
FoldingSetNodeID TempID;
InsertPos = GetBucketFor(ComputeNodeHash(N, TempID), Buckets, NumBuckets);
diff --git a/contrib/llvm/lib/Support/Host.cpp b/contrib/llvm/lib/Support/Host.cpp
index c0f9e07..12ac19d 100644
--- a/contrib/llvm/lib/Support/Host.cpp
+++ b/contrib/llvm/lib/Support/Host.cpp
@@ -33,9 +33,9 @@
#include <intrin.h>
#endif
#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
+#include <mach/host_info.h>
#include <mach/mach.h>
#include <mach/mach_host.h>
-#include <mach/host_info.h>
#include <mach/machine.h>
#endif
@@ -69,40 +69,131 @@ static ssize_t LLVM_ATTRIBUTE_UNUSED readCpuInfo(void *Buf, size_t Size) {
}
#endif
-#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\
- || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
-
-/// GetX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
-/// specified arguments. If we can't run cpuid on the host, return true.
-static bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
+#if defined(i386) || defined(__i386__) || defined(__x86__) || \
+ defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64) || \
+ defined(_M_X64)
+
+enum VendorSignatures {
+ SIG_INTEL = 0x756e6547 /* Genu */,
+ SIG_AMD = 0x68747541 /* Auth */
+};
+
+enum ProcessorVendors {
+ VENDOR_INTEL = 1,
+ VENDOR_AMD,
+ VENDOR_OTHER,
+ VENDOR_MAX
+};
+
+enum ProcessorTypes {
+ INTEL_ATOM = 1,
+ INTEL_CORE2,
+ INTEL_COREI7,
+ AMDFAM10H,
+ AMDFAM15H,
+ INTEL_i386,
+ INTEL_i486,
+ INTEL_PENTIUM,
+ INTEL_PENTIUM_PRO,
+ INTEL_PENTIUM_II,
+ INTEL_PENTIUM_III,
+ INTEL_PENTIUM_IV,
+ INTEL_PENTIUM_M,
+ INTEL_CORE_DUO,
+ INTEL_XEONPHI,
+ INTEL_X86_64,
+ INTEL_NOCONA,
+ INTEL_PRESCOTT,
+ AMD_i486,
+ AMDPENTIUM,
+ AMDATHLON,
+ AMDFAM14H,
+ AMDFAM16H,
+ CPU_TYPE_MAX
+};
+
+enum ProcessorSubtypes {
+ INTEL_COREI7_NEHALEM = 1,
+ INTEL_COREI7_WESTMERE,
+ INTEL_COREI7_SANDYBRIDGE,
+ AMDFAM10H_BARCELONA,
+ AMDFAM10H_SHANGHAI,
+ AMDFAM10H_ISTANBUL,
+ AMDFAM15H_BDVER1,
+ AMDFAM15H_BDVER2,
+ INTEL_PENTIUM_MMX,
+ INTEL_CORE2_65,
+ INTEL_CORE2_45,
+ INTEL_COREI7_IVYBRIDGE,
+ INTEL_COREI7_HASWELL,
+ INTEL_COREI7_BROADWELL,
+ INTEL_COREI7_SKYLAKE,
+ INTEL_COREI7_SKYLAKE_AVX512,
+ INTEL_ATOM_BONNELL,
+ INTEL_ATOM_SILVERMONT,
+ INTEL_KNIGHTS_LANDING,
+ AMDPENTIUM_K6,
+ AMDPENTIUM_K62,
+ AMDPENTIUM_K63,
+ AMDPENTIUM_GEODE,
+ AMDATHLON_TBIRD,
+ AMDATHLON_MP,
+ AMDATHLON_XP,
+ AMDATHLON_K8SSE3,
+ AMDATHLON_OPTERON,
+ AMDATHLON_FX,
+ AMDATHLON_64,
+ AMD_BTVER1,
+ AMD_BTVER2,
+ AMDFAM15H_BDVER3,
+ AMDFAM15H_BDVER4,
+ CPU_SUBTYPE_MAX
+};
+
+enum ProcessorFeatures {
+ FEATURE_CMOV = 0,
+ FEATURE_MMX,
+ FEATURE_POPCNT,
+ FEATURE_SSE,
+ FEATURE_SSE2,
+ FEATURE_SSE3,
+ FEATURE_SSSE3,
+ FEATURE_SSE4_1,
+ FEATURE_SSE4_2,
+ FEATURE_AVX,
+ FEATURE_AVX2,
+ FEATURE_AVX512,
+ FEATURE_AVX512SAVE,
+ FEATURE_MOVBE,
+ FEATURE_ADX,
+ FEATURE_EM64T
+};
+
+/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
+/// the specified arguments. If we can't run cpuid on the host, return true.
+static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
unsigned *rECX, unsigned *rEDX) {
#if defined(__GNUC__) || defined(__clang__)
- #if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
- // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
- asm ("movq\t%%rbx, %%rsi\n\t"
- "cpuid\n\t"
- "xchgq\t%%rbx, %%rsi\n\t"
- : "=a" (*rEAX),
- "=S" (*rEBX),
- "=c" (*rECX),
- "=d" (*rEDX)
- : "a" (value));
- return false;
- #elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
- asm ("movl\t%%ebx, %%esi\n\t"
- "cpuid\n\t"
- "xchgl\t%%ebx, %%esi\n\t"
- : "=a" (*rEAX),
- "=S" (*rEBX),
- "=c" (*rECX),
- "=d" (*rEDX)
- : "a" (value));
- return false;
+#if defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
+ // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
+ asm("movq\t%%rbx, %%rsi\n\t"
+ "cpuid\n\t"
+ "xchgq\t%%rbx, %%rsi\n\t"
+ : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
+ : "a"(value));
+ return false;
+#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
+ asm("movl\t%%ebx, %%esi\n\t"
+ "cpuid\n\t"
+ "xchgl\t%%ebx, %%esi\n\t"
+ : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
+ : "a"(value));
+ return false;
// pedantic #else returns to appease -Wunreachable-code (so we don't generate
// postprocessed code that looks like "return true; return false;")
- #else
- return true;
- #endif
+#else
+ return true;
+#endif
#elif defined(_MSC_VER)
// The MSVC intrinsic is portable across x86 and x64.
int registers[4];
@@ -117,50 +208,42 @@ static bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
#endif
}
-/// GetX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return the
-/// 4 values in the specified arguments. If we can't run cpuid on the host,
+/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
+/// the 4 values in the specified arguments. If we can't run cpuid on the host,
/// return true.
-static bool GetX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
+static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
unsigned *rEDX) {
-#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
- #if defined(__GNUC__)
- // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
- asm ("movq\t%%rbx, %%rsi\n\t"
- "cpuid\n\t"
- "xchgq\t%%rbx, %%rsi\n\t"
- : "=a" (*rEAX),
- "=S" (*rEBX),
- "=c" (*rECX),
- "=d" (*rEDX)
- : "a" (value),
- "c" (subleaf));
- return false;
- #elif defined(_MSC_VER)
- int registers[4];
- __cpuidex(registers, value, subleaf);
- *rEAX = registers[0];
- *rEBX = registers[1];
- *rECX = registers[2];
- *rEDX = registers[3];
- return false;
- #else
- return true;
- #endif
+#if defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
+#if defined(__GNUC__)
+ // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
+ asm("movq\t%%rbx, %%rsi\n\t"
+ "cpuid\n\t"
+ "xchgq\t%%rbx, %%rsi\n\t"
+ : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
+ : "a"(value), "c"(subleaf));
+ return false;
+#elif defined(_MSC_VER)
+ int registers[4];
+ __cpuidex(registers, value, subleaf);
+ *rEAX = registers[0];
+ *rEBX = registers[1];
+ *rECX = registers[2];
+ *rEDX = registers[3];
+ return false;
+#else
+ return true;
+#endif
#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
- #if defined(__GNUC__)
- asm ("movl\t%%ebx, %%esi\n\t"
- "cpuid\n\t"
- "xchgl\t%%ebx, %%esi\n\t"
- : "=a" (*rEAX),
- "=S" (*rEBX),
- "=c" (*rECX),
- "=d" (*rEDX)
- : "a" (value),
- "c" (subleaf));
- return false;
- #elif defined(_MSC_VER)
- __asm {
+#if defined(__GNUC__)
+ asm("movl\t%%ebx, %%esi\n\t"
+ "cpuid\n\t"
+ "xchgl\t%%ebx, %%esi\n\t"
+ : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
+ : "a"(value), "c"(subleaf));
+ return false;
+#elif defined(_MSC_VER)
+ __asm {
mov eax,value
mov ecx,subleaf
cpuid
@@ -172,22 +255,22 @@ static bool GetX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
mov dword ptr [esi],ecx
mov esi,rEDX
mov dword ptr [esi],edx
- }
- return false;
- #else
- return true;
- #endif
+ }
+ return false;
+#else
+ return true;
+#endif
#else
return true;
#endif
}
-static bool GetX86XCR0(unsigned *rEAX, unsigned *rEDX) {
+static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
#if defined(__GNUC__)
// Check xgetbv; this uses a .byte sequence instead of the instruction
// directly because older assemblers do not include support for xgetbv and
// there is no easy way to conditionally compile based on the assembler used.
- __asm__ (".byte 0x0f, 0x01, 0xd0" : "=a" (*rEAX), "=d" (*rEDX) : "c" (0));
+ __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
return false;
#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
@@ -199,342 +282,669 @@ static bool GetX86XCR0(unsigned *rEAX, unsigned *rEDX) {
#endif
}
-static void DetectX86FamilyModel(unsigned EAX, unsigned &Family,
- unsigned &Model) {
- Family = (EAX >> 8) & 0xf; // Bits 8 - 11
- Model = (EAX >> 4) & 0xf; // Bits 4 - 7
- if (Family == 6 || Family == 0xf) {
- if (Family == 0xf)
+static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
+ unsigned *Model) {
+ *Family = (EAX >> 8) & 0xf; // Bits 8 - 11
+ *Model = (EAX >> 4) & 0xf; // Bits 4 - 7
+ if (*Family == 6 || *Family == 0xf) {
+ if (*Family == 0xf)
// Examine extended family ID if family ID is F.
- Family += (EAX >> 20) & 0xff; // Bits 20 - 27
+ *Family += (EAX >> 20) & 0xff; // Bits 20 - 27
// Examine extended model ID if family ID is 6 or F.
- Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
+ *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
}
}
-StringRef sys::getHostCPUName() {
- unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
- if (GetX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
- return "generic";
- unsigned Family = 0;
- unsigned Model = 0;
- DetectX86FamilyModel(EAX, Family, Model);
-
- union {
- unsigned u[3];
- char c[12];
- } text;
-
- unsigned MaxLeaf;
- GetX86CpuIDAndInfo(0, &MaxLeaf, text.u+0, text.u+2, text.u+1);
-
- bool HasMMX = (EDX >> 23) & 1;
- bool HasSSE = (EDX >> 25) & 1;
- bool HasSSE2 = (EDX >> 26) & 1;
- bool HasSSE3 = (ECX >> 0) & 1;
- bool HasSSSE3 = (ECX >> 9) & 1;
- bool HasSSE41 = (ECX >> 19) & 1;
- bool HasSSE42 = (ECX >> 20) & 1;
- bool HasMOVBE = (ECX >> 22) & 1;
- // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
- // indicates that the AVX registers will be saved and restored on context
- // switch, then we have full AVX support.
- const unsigned AVXBits = (1 << 27) | (1 << 28);
- bool HasAVX = ((ECX & AVXBits) == AVXBits) && !GetX86XCR0(&EAX, &EDX) &&
- ((EAX & 0x6) == 0x6);
- bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
- bool HasLeaf7 = MaxLeaf >= 0x7 &&
- !GetX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
- bool HasADX = HasLeaf7 && ((EBX >> 19) & 1);
- bool HasAVX2 = HasAVX && HasLeaf7 && (EBX & 0x20);
- bool HasAVX512 = HasLeaf7 && HasAVX512Save && ((EBX >> 16) & 1);
-
- GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
- bool Em64T = (EDX >> 29) & 0x1;
- bool HasTBM = (ECX >> 21) & 0x1;
-
- if (memcmp(text.c, "GenuineIntel", 12) == 0) {
- switch (Family) {
- case 3:
- return "i386";
- case 4:
- switch (Model) {
- case 0: // Intel486 DX processors
- case 1: // Intel486 DX processors
- case 2: // Intel486 SX processors
- case 3: // Intel487 processors, IntelDX2 OverDrive processors,
- // IntelDX2 processors
- case 4: // Intel486 SL processor
- case 5: // IntelSX2 processors
- case 7: // Write-Back Enhanced IntelDX2 processors
- case 8: // IntelDX4 OverDrive processors, IntelDX4 processors
- default: return "i486";
- }
- case 5:
- switch (Model) {
- case 1: // Pentium OverDrive processor for Pentium processor (60, 66),
- // Pentium processors (60, 66)
- case 2: // Pentium OverDrive processor for Pentium processor (75, 90,
- // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133,
- // 150, 166, 200)
- case 3: // Pentium OverDrive processors for Intel486 processor-based
- // systems
- return "pentium";
-
- case 4: // Pentium OverDrive processor with MMX technology for Pentium
- // processor (75, 90, 100, 120, 133), Pentium processor with
- // MMX technology (166, 200)
- return "pentium-mmx";
-
- default: return "pentium";
- }
- case 6:
- switch (Model) {
- case 1: // Pentium Pro processor
- return "pentiumpro";
-
- case 3: // Intel Pentium II OverDrive processor, Pentium II processor,
+static void
+getIntelProcessorTypeAndSubtype(unsigned int Family, unsigned int Model,
+ unsigned int Brand_id, unsigned int Features,
+ unsigned *Type, unsigned *Subtype) {
+ if (Brand_id != 0)
+ return;
+ switch (Family) {
+ case 3:
+ *Type = INTEL_i386;
+ break;
+ case 4:
+ switch (Model) {
+ case 0: // Intel486 DX processors
+ case 1: // Intel486 DX processors
+ case 2: // Intel486 SX processors
+ case 3: // Intel487 processors, IntelDX2 OverDrive processors,
+ // IntelDX2 processors
+ case 4: // Intel486 SL processor
+ case 5: // IntelSX2 processors
+ case 7: // Write-Back Enhanced IntelDX2 processors
+ case 8: // IntelDX4 OverDrive processors, IntelDX4 processors
+ default:
+ *Type = INTEL_i486;
+ break;
+ }
+ break;
+ case 5:
+ switch (Model) {
+ case 1: // Pentium OverDrive processor for Pentium processor (60, 66),
+ // Pentium processors (60, 66)
+ case 2: // Pentium OverDrive processor for Pentium processor (75, 90,
+ // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133,
+ // 150, 166, 200)
+ case 3: // Pentium OverDrive processors for Intel486 processor-based
+ // systems
+ *Type = INTEL_PENTIUM;
+ break;
+ case 4: // Pentium OverDrive processor with MMX technology for Pentium
+ // processor (75, 90, 100, 120, 133), Pentium processor with
+ // MMX technology (166, 200)
+ *Type = INTEL_PENTIUM;
+ *Subtype = INTEL_PENTIUM_MMX;
+ break;
+ default:
+ *Type = INTEL_PENTIUM;
+ break;
+ }
+ break;
+ case 6:
+ switch (Model) {
+ case 0x01: // Pentium Pro processor
+ *Type = INTEL_PENTIUM_PRO;
+ break;
+ case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor,
// model 03
- case 5: // Pentium II processor, model 05, Pentium II Xeon processor,
+ case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor,
// model 05, and Intel Celeron processor, model 05
- case 6: // Celeron processor, model 06
- return "pentium2";
-
- case 7: // Pentium III processor, model 07, and Pentium III Xeon
+ case 0x06: // Celeron processor, model 06
+ *Type = INTEL_PENTIUM_II;
+ break;
+ case 0x07: // Pentium III processor, model 07, and Pentium III Xeon
// processor, model 07
- case 8: // Pentium III processor, model 08, Pentium III Xeon processor,
+ case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor,
// model 08, and Celeron processor, model 08
- case 10: // Pentium III Xeon processor, model 0Ah
- case 11: // Pentium III processor, model 0Bh
- return "pentium3";
-
- case 9: // Intel Pentium M processor, Intel Celeron M processor model 09.
- case 13: // Intel Pentium M processor, Intel Celeron M processor, model
+ case 0x0a: // Pentium III Xeon processor, model 0Ah
+ case 0x0b: // Pentium III processor, model 0Bh
+ *Type = INTEL_PENTIUM_III;
+ break;
+ case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09.
+ case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model
// 0Dh. All processors are manufactured using the 90 nm process.
- case 21: // Intel EP80579 Integrated Processor and Intel EP80579
+ case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579
// Integrated Processor with Intel QuickAssist Technology
- return "pentium-m";
-
- case 14: // Intel Core Duo processor, Intel Core Solo processor, model
+ *Type = INTEL_PENTIUM_M;
+ break;
+ case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model
// 0Eh. All processors are manufactured using the 65 nm process.
- return "yonah";
-
- case 15: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
+ *Type = INTEL_CORE_DUO;
+ break; // yonah
+ case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
// processor, Intel Core 2 Quad processor, Intel Core 2 Quad
// mobile processor, Intel Core 2 Extreme processor, Intel
// Pentium Dual-Core processor, Intel Xeon processor, model
// 0Fh. All processors are manufactured using the 65 nm process.
- case 22: // Intel Celeron processor model 16h. All processors are
+ case 0x16: // Intel Celeron processor model 16h. All processors are
// manufactured using the 65 nm process
- return "core2";
-
- case 23: // Intel Core 2 Extreme processor, Intel Xeon processor, model
+ *Type = INTEL_CORE2; // "core2"
+ *Subtype = INTEL_CORE2_65;
+ break;
+ case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model
// 17h. All processors are manufactured using the 45 nm process.
//
// 45nm: Penryn , Wolfdale, Yorkfield (XE)
- case 29: // Intel Xeon processor MP. All processors are manufactured using
+ case 0x1d: // Intel Xeon processor MP. All processors are manufactured using
// the 45 nm process.
- return "penryn";
-
- case 26: // Intel Core i7 processor and Intel Xeon processor. All
+ *Type = INTEL_CORE2; // "penryn"
+ *Subtype = INTEL_CORE2_45;
+ break;
+ case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
// processors are manufactured using the 45 nm process.
- case 30: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz.
+ case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz.
// As found in a Summer 2010 model iMac.
- case 46: // Nehalem EX
- return "nehalem";
- case 37: // Intel Core i7, laptop version.
- case 44: // Intel Core i7 processor and Intel Xeon processor. All
+ case 0x1f:
+ case 0x2e: // Nehalem EX
+ *Type = INTEL_COREI7; // "nehalem"
+ *Subtype = INTEL_COREI7_NEHALEM;
+ break;
+ case 0x25: // Intel Core i7, laptop version.
+ case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
// processors are manufactured using the 32 nm process.
- case 47: // Westmere EX
- return "westmere";
-
- // SandyBridge:
- case 42: // Intel Core i7 processor. All processors are manufactured
+ case 0x2f: // Westmere EX
+ *Type = INTEL_COREI7; // "westmere"
+ *Subtype = INTEL_COREI7_WESTMERE;
+ break;
+ case 0x2a: // Intel Core i7 processor. All processors are manufactured
// using the 32 nm process.
- case 45:
- return "sandybridge";
+ case 0x2d:
+ *Type = INTEL_COREI7; //"sandybridge"
+ *Subtype = INTEL_COREI7_SANDYBRIDGE;
+ break;
+ case 0x3a:
+ case 0x3e: // Ivy Bridge EP
+ *Type = INTEL_COREI7; // "ivybridge"
+ *Subtype = INTEL_COREI7_IVYBRIDGE;
+ break;
- // Ivy Bridge:
- case 58:
- case 62: // Ivy Bridge EP
- return "ivybridge";
+ // Haswell:
+ case 0x3c:
+ case 0x3f:
+ case 0x45:
+ case 0x46:
+ *Type = INTEL_COREI7; // "haswell"
+ *Subtype = INTEL_COREI7_HASWELL;
+ break;
- // Haswell:
- case 60:
- case 63:
- case 69:
- case 70:
- return "haswell";
+ // Broadwell:
+ case 0x3d:
+ case 0x47:
+ case 0x4f:
+ case 0x56:
+ *Type = INTEL_COREI7; // "broadwell"
+ *Subtype = INTEL_COREI7_BROADWELL;
+ break;
- // Broadwell:
- case 61:
- case 71:
- return "broadwell";
+ // Skylake:
+ case 0x4e:
+ *Type = INTEL_COREI7; // "skylake-avx512"
+ *Subtype = INTEL_COREI7_SKYLAKE_AVX512;
+ break;
+ case 0x5e:
+ *Type = INTEL_COREI7; // "skylake"
+ *Subtype = INTEL_COREI7_SKYLAKE;
+ break;
- // Skylake:
- case 78:
- case 94:
- return "skylake";
+ case 0x1c: // Most 45 nm Intel Atom processors
+ case 0x26: // 45 nm Atom Lincroft
+ case 0x27: // 32 nm Atom Medfield
+ case 0x35: // 32 nm Atom Midview
+ case 0x36: // 32 nm Atom Midview
+ *Type = INTEL_ATOM;
+ *Subtype = INTEL_ATOM_BONNELL;
+ break; // "bonnell"
+
+ // Atom Silvermont codes from the Intel software optimization guide.
+ case 0x37:
+ case 0x4a:
+ case 0x4d:
+ case 0x5a:
+ case 0x5d:
+ case 0x4c: // really airmont
+ *Type = INTEL_ATOM;
+ *Subtype = INTEL_ATOM_SILVERMONT;
+ break; // "silvermont"
+
+ case 0x57:
+ *Type = INTEL_XEONPHI; // knl
+ *Subtype = INTEL_KNIGHTS_LANDING;
+ break;
- case 28: // Most 45 nm Intel Atom processors
- case 38: // 45 nm Atom Lincroft
- case 39: // 32 nm Atom Medfield
- case 53: // 32 nm Atom Midview
- case 54: // 32 nm Atom Midview
- return "bonnell";
+ default: // Unknown family 6 CPU, try to guess.
+ if (Features & (1 << FEATURE_AVX512)) {
+ *Type = INTEL_XEONPHI; // knl
+ *Subtype = INTEL_KNIGHTS_LANDING;
+ break;
+ }
+ if (Features & (1 << FEATURE_ADX)) {
+ *Type = INTEL_COREI7;
+ *Subtype = INTEL_COREI7_BROADWELL;
+ break;
+ }
+ if (Features & (1 << FEATURE_AVX2)) {
+ *Type = INTEL_COREI7;
+ *Subtype = INTEL_COREI7_HASWELL;
+ break;
+ }
+ if (Features & (1 << FEATURE_AVX)) {
+ *Type = INTEL_COREI7;
+ *Subtype = INTEL_COREI7_SANDYBRIDGE;
+ break;
+ }
+ if (Features & (1 << FEATURE_SSE4_2)) {
+ if (Features & (1 << FEATURE_MOVBE)) {
+ *Type = INTEL_ATOM;
+ *Subtype = INTEL_ATOM_SILVERMONT;
+ } else {
+ *Type = INTEL_COREI7;
+ *Subtype = INTEL_COREI7_NEHALEM;
+ }
+ break;
+ }
+ if (Features & (1 << FEATURE_SSE4_1)) {
+ *Type = INTEL_CORE2; // "penryn"
+ *Subtype = INTEL_CORE2_45;
+ break;
+ }
+ if (Features & (1 << FEATURE_SSSE3)) {
+ if (Features & (1 << FEATURE_MOVBE)) {
+ *Type = INTEL_ATOM;
+ *Subtype = INTEL_ATOM_BONNELL; // "bonnell"
+ } else {
+ *Type = INTEL_CORE2; // "core2"
+ *Subtype = INTEL_CORE2_65;
+ }
+ break;
+ }
+ if (Features & (1 << FEATURE_EM64T)) {
+ *Type = INTEL_X86_64;
+ break; // x86-64
+ }
+ if (Features & (1 << FEATURE_SSE2)) {
+ *Type = INTEL_PENTIUM_M;
+ break;
+ }
+ if (Features & (1 << FEATURE_SSE)) {
+ *Type = INTEL_PENTIUM_III;
+ break;
+ }
+ if (Features & (1 << FEATURE_MMX)) {
+ *Type = INTEL_PENTIUM_II;
+ break;
+ }
+ *Type = INTEL_PENTIUM_PRO;
+ break;
+ }
+ break;
+ case 15: {
+ switch (Model) {
+ case 0: // Pentium 4 processor, Intel Xeon processor. All processors are
+ // model 00h and manufactured using the 0.18 micron process.
+ case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon
+ // processor MP, and Intel Celeron processor. All processors are
+ // model 01h and manufactured using the 0.18 micron process.
+ case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M,
+ // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron
+ // processor, and Mobile Intel Celeron processor. All processors
+ // are model 02h and manufactured using the 0.13 micron process.
+ *Type =
+ ((Features & (1 << FEATURE_EM64T)) ? INTEL_X86_64 : INTEL_PENTIUM_IV);
+ break;
- // Atom Silvermont codes from the Intel software optimization guide.
- case 55:
- case 74:
- case 77:
- case 90:
- case 93:
- return "silvermont";
+ case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D
+ // processor. All processors are model 03h and manufactured using
+ // the 90 nm process.
+ case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition,
+ // Pentium D processor, Intel Xeon processor, Intel Xeon
+ // processor MP, Intel Celeron D processor. All processors are
+ // model 04h and manufactured using the 90 nm process.
+ case 6: // Pentium 4 processor, Pentium D processor, Pentium processor
+ // Extreme Edition, Intel Xeon processor, Intel Xeon processor
+ // MP, Intel Celeron D processor. All processors are model 06h
+ // and manufactured using the 65 nm process.
+ *Type =
+ ((Features & (1 << FEATURE_EM64T)) ? INTEL_NOCONA : INTEL_PRESCOTT);
+ break;
- default: // Unknown family 6 CPU, try to guess.
- if (HasAVX512)
- return "knl";
- if (HasADX)
- return "broadwell";
- if (HasAVX2)
- return "haswell";
- if (HasAVX)
- return "sandybridge";
- if (HasSSE42)
- return HasMOVBE ? "silvermont" : "nehalem";
- if (HasSSE41)
- return "penryn";
- if (HasSSSE3)
- return HasMOVBE ? "bonnell" : "core2";
- if (Em64T)
- return "x86-64";
- if (HasSSE2)
- return "pentium-m";
- if (HasSSE)
- return "pentium3";
- if (HasMMX)
- return "pentium2";
- return "pentiumpro";
- }
- case 15: {
- switch (Model) {
- case 0: // Pentium 4 processor, Intel Xeon processor. All processors are
- // model 00h and manufactured using the 0.18 micron process.
- case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon
- // processor MP, and Intel Celeron processor. All processors are
- // model 01h and manufactured using the 0.18 micron process.
- case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M,
- // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron
- // processor, and Mobile Intel Celeron processor. All processors
- // are model 02h and manufactured using the 0.13 micron process.
- return (Em64T) ? "x86-64" : "pentium4";
-
- case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D
- // processor. All processors are model 03h and manufactured using
- // the 90 nm process.
- case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition,
- // Pentium D processor, Intel Xeon processor, Intel Xeon
- // processor MP, Intel Celeron D processor. All processors are
- // model 04h and manufactured using the 90 nm process.
- case 6: // Pentium 4 processor, Pentium D processor, Pentium processor
- // Extreme Edition, Intel Xeon processor, Intel Xeon processor
- // MP, Intel Celeron D processor. All processors are model 06h
- // and manufactured using the 65 nm process.
- return (Em64T) ? "nocona" : "prescott";
+ default:
+ *Type =
+ ((Features & (1 << FEATURE_EM64T)) ? INTEL_X86_64 : INTEL_PENTIUM_IV);
+ break;
+ }
+ break;
+ }
+ default:
+ break; /*"generic"*/
+ }
+}
- default:
- return (Em64T) ? "x86-64" : "pentium4";
- }
+static void getAMDProcessorTypeAndSubtype(unsigned int Family,
+ unsigned int Model,
+ unsigned int Features,
+ unsigned *Type,
+ unsigned *Subtype) {
+ // FIXME: this poorly matches the generated SubtargetFeatureKV table. There
+ // appears to be no way to generate the wide variety of AMD-specific targets
+ // from the information returned from CPUID.
+ switch (Family) {
+ case 4:
+ *Type = AMD_i486;
+ break;
+ case 5:
+ *Type = AMDPENTIUM;
+ switch (Model) {
+ case 6:
+ case 7:
+ *Subtype = AMDPENTIUM_K6;
+ break; // "k6"
+ case 8:
+ *Subtype = AMDPENTIUM_K62;
+ break; // "k6-2"
+ case 9:
+ case 13:
+ *Subtype = AMDPENTIUM_K63;
+ break; // "k6-3"
+ case 10:
+ *Subtype = AMDPENTIUM_GEODE;
+ break; // "geode"
+ }
+ break;
+ case 6:
+ *Type = AMDATHLON;
+ switch (Model) {
+ case 4:
+ *Subtype = AMDATHLON_TBIRD;
+ break; // "athlon-tbird"
+ case 6:
+ case 7:
+ case 8:
+ *Subtype = AMDATHLON_MP;
+ break; // "athlon-mp"
+ case 10:
+ *Subtype = AMDATHLON_XP;
+ break; // "athlon-xp"
}
+ break;
+ case 15:
+ *Type = AMDATHLON;
+ if (Features & (1 << FEATURE_SSE3)) {
+ *Subtype = AMDATHLON_K8SSE3;
+ break; // "k8-sse3"
+ }
+ switch (Model) {
+ case 1:
+ *Subtype = AMDATHLON_OPTERON;
+ break; // "opteron"
+ case 5:
+ *Subtype = AMDATHLON_FX;
+ break; // "athlon-fx"; also opteron
+ default:
+ *Subtype = AMDATHLON_64;
+ break; // "athlon64"
+ }
+ break;
+ case 16:
+ *Type = AMDFAM10H; // "amdfam10"
+ switch (Model) {
+ case 2:
+ *Subtype = AMDFAM10H_BARCELONA;
+ break;
+ case 4:
+ *Subtype = AMDFAM10H_SHANGHAI;
+ break;
+ case 8:
+ *Subtype = AMDFAM10H_ISTANBUL;
+ break;
+ }
+ break;
+ case 20:
+ *Type = AMDFAM14H;
+ *Subtype = AMD_BTVER1;
+ break; // "btver1";
+ case 21:
+ *Type = AMDFAM15H;
+ if (!(Features &
+ (1 << FEATURE_AVX))) { // If no AVX support, provide a sane fallback.
+ *Subtype = AMD_BTVER1;
+ break; // "btver1"
+ }
+ if (Model >= 0x50 && Model <= 0x6f) {
+ *Subtype = AMDFAM15H_BDVER4;
+ break; // "bdver4"; 50h-6Fh: Excavator
+ }
+ if (Model >= 0x30 && Model <= 0x3f) {
+ *Subtype = AMDFAM15H_BDVER3;
+ break; // "bdver3"; 30h-3Fh: Steamroller
+ }
+ if (Model >= 0x10 && Model <= 0x1f) {
+ *Subtype = AMDFAM15H_BDVER2;
+ break; // "bdver2"; 10h-1Fh: Piledriver
+ }
+ if (Model <= 0x0f) {
+ *Subtype = AMDFAM15H_BDVER1;
+ break; // "bdver1"; 00h-0Fh: Bulldozer
+ }
+ break;
+ case 22:
+ *Type = AMDFAM16H;
+ if (!(Features &
+ (1 << FEATURE_AVX))) { // If no AVX support provide a sane fallback.
+ *Subtype = AMD_BTVER1;
+ break; // "btver1";
+ }
+ *Subtype = AMD_BTVER2;
+ break; // "btver2"
+ default:
+ break; // "generic"
+ }
+}
+
+static unsigned getAvailableFeatures(unsigned int ECX, unsigned int EDX,
+ unsigned MaxLeaf) {
+ unsigned Features = 0;
+ unsigned int EAX, EBX;
+ Features |= (((EDX >> 23) & 1) << FEATURE_MMX);
+ Features |= (((EDX >> 25) & 1) << FEATURE_SSE);
+ Features |= (((EDX >> 26) & 1) << FEATURE_SSE2);
+ Features |= (((ECX >> 0) & 1) << FEATURE_SSE3);
+ Features |= (((ECX >> 9) & 1) << FEATURE_SSSE3);
+ Features |= (((ECX >> 19) & 1) << FEATURE_SSE4_1);
+ Features |= (((ECX >> 20) & 1) << FEATURE_SSE4_2);
+ Features |= (((ECX >> 22) & 1) << FEATURE_MOVBE);
+
+ // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
+ // indicates that the AVX registers will be saved and restored on context
+ // switch, then we have full AVX support.
+ const unsigned AVXBits = (1 << 27) | (1 << 28);
+ bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
+ ((EAX & 0x6) == 0x6);
+ bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
+ bool HasLeaf7 =
+ MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
+ bool HasADX = HasLeaf7 && ((EBX >> 19) & 1);
+ bool HasAVX2 = HasAVX && HasLeaf7 && (EBX & 0x20);
+ bool HasAVX512 = HasLeaf7 && HasAVX512Save && ((EBX >> 16) & 1);
+ Features |= (HasAVX << FEATURE_AVX);
+ Features |= (HasAVX2 << FEATURE_AVX2);
+ Features |= (HasAVX512 << FEATURE_AVX512);
+ Features |= (HasAVX512Save << FEATURE_AVX512SAVE);
+ Features |= (HasADX << FEATURE_ADX);
+
+ getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
+ Features |= (((EDX >> 29) & 0x1) << FEATURE_EM64T);
+ return Features;
+}
+StringRef sys::getHostCPUName() {
+ unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
+ unsigned MaxLeaf, Vendor;
+
+ if (getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX))
+ return "generic";
+ if (getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
+ return "generic";
+
+ unsigned Brand_id = EBX & 0xff;
+ unsigned Family = 0, Model = 0;
+ unsigned Features = 0;
+ detectX86FamilyModel(EAX, &Family, &Model);
+ Features = getAvailableFeatures(ECX, EDX, MaxLeaf);
+
+ unsigned Type;
+ unsigned Subtype;
+
+ if (Vendor == SIG_INTEL) {
+ getIntelProcessorTypeAndSubtype(Family, Model, Brand_id, Features, &Type,
+ &Subtype);
+ switch (Type) {
+ case INTEL_i386:
+ return "i386";
+ case INTEL_i486:
+ return "i486";
+ case INTEL_PENTIUM:
+ if (Subtype == INTEL_PENTIUM_MMX)
+ return "pentium-mmx";
+ return "pentium";
+ case INTEL_PENTIUM_PRO:
+ return "pentiumpro";
+ case INTEL_PENTIUM_II:
+ return "pentium2";
+ case INTEL_PENTIUM_III:
+ return "pentium3";
+ case INTEL_PENTIUM_IV:
+ return "pentium4";
+ case INTEL_PENTIUM_M:
+ return "pentium-m";
+ case INTEL_CORE_DUO:
+ return "yonah";
+ case INTEL_CORE2:
+ switch (Subtype) {
+ case INTEL_CORE2_65:
+ return "core2";
+ case INTEL_CORE2_45:
+ return "penryn";
+ default:
+ return "core2";
+ }
+ case INTEL_COREI7:
+ switch (Subtype) {
+ case INTEL_COREI7_NEHALEM:
+ return "nehalem";
+ case INTEL_COREI7_WESTMERE:
+ return "westmere";
+ case INTEL_COREI7_SANDYBRIDGE:
+ return "sandybridge";
+ case INTEL_COREI7_IVYBRIDGE:
+ return "ivybridge";
+ case INTEL_COREI7_HASWELL:
+ return "haswell";
+ case INTEL_COREI7_BROADWELL:
+ return "broadwell";
+ case INTEL_COREI7_SKYLAKE:
+ return "skylake";
+ case INTEL_COREI7_SKYLAKE_AVX512:
+ return "skylake-avx512";
+ default:
+ return "corei7";
+ }
+ case INTEL_ATOM:
+ switch (Subtype) {
+ case INTEL_ATOM_BONNELL:
+ return "bonnell";
+ case INTEL_ATOM_SILVERMONT:
+ return "silvermont";
+ default:
+ return "atom";
+ }
+ case INTEL_XEONPHI:
+ return "knl"; /*update for more variants added*/
+ case INTEL_X86_64:
+ return "x86-64";
+ case INTEL_NOCONA:
+ return "nocona";
+ case INTEL_PRESCOTT:
+ return "prescott";
default:
return "generic";
}
- } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
- // FIXME: this poorly matches the generated SubtargetFeatureKV table. There
- // appears to be no way to generate the wide variety of AMD-specific targets
- // from the information returned from CPUID.
- switch (Family) {
- case 4:
- return "i486";
- case 5:
- switch (Model) {
- case 6:
- case 7: return "k6";
- case 8: return "k6-2";
- case 9:
- case 13: return "k6-3";
- case 10: return "geode";
- default: return "pentium";
- }
- case 6:
- switch (Model) {
- case 4: return "athlon-tbird";
- case 6:
- case 7:
- case 8: return "athlon-mp";
- case 10: return "athlon-xp";
- default: return "athlon";
- }
- case 15:
- if (HasSSE3)
- return "k8-sse3";
- switch (Model) {
- case 1: return "opteron";
- case 5: return "athlon-fx"; // also opteron
- default: return "athlon64";
- }
- case 16:
- return "amdfam10";
- case 20:
+ } else if (Vendor == SIG_AMD) {
+ getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype);
+ switch (Type) {
+ case AMD_i486:
+ return "i486";
+ case AMDPENTIUM:
+ switch (Subtype) {
+ case AMDPENTIUM_K6:
+ return "k6";
+ case AMDPENTIUM_K62:
+ return "k6-2";
+ case AMDPENTIUM_K63:
+ return "k6-3";
+ case AMDPENTIUM_GEODE:
+ return "geode";
+ default:
+ return "pentium";
+ }
+ case AMDATHLON:
+ switch (Subtype) {
+ case AMDATHLON_TBIRD:
+ return "athlon-tbird";
+ case AMDATHLON_MP:
+ return "athlon-mp";
+ case AMDATHLON_XP:
+ return "athlon-xp";
+ case AMDATHLON_K8SSE3:
+ return "k8-sse3";
+ case AMDATHLON_OPTERON:
+ return "opteron";
+ case AMDATHLON_FX:
+ return "athlon-fx";
+ case AMDATHLON_64:
+ return "athlon64";
+ default:
+ return "athlon";
+ }
+ case AMDFAM10H:
+ if(Subtype == AMDFAM10H_BARCELONA)
+ return "barcelona";
+ return "amdfam10";
+ case AMDFAM14H:
+ return "btver1";
+ case AMDFAM15H:
+ switch (Subtype) {
+ case AMDFAM15H_BDVER1:
+ return "bdver1";
+ case AMDFAM15H_BDVER2:
+ return "bdver2";
+ case AMDFAM15H_BDVER3:
+ return "bdver3";
+ case AMDFAM15H_BDVER4:
+ return "bdver4";
+ case AMD_BTVER1:
return "btver1";
- case 21:
- if (!HasAVX) // If the OS doesn't support AVX provide a sane fallback.
- return "btver1";
- if (Model >= 0x50)
- return "bdver4"; // 50h-6Fh: Excavator
- if (Model >= 0x30)
- return "bdver3"; // 30h-3Fh: Steamroller
- if (Model >= 0x10 || HasTBM)
- return "bdver2"; // 10h-1Fh: Piledriver
- return "bdver1"; // 00h-0Fh: Bulldozer
- case 22:
- if (!HasAVX) // If the OS doesn't support AVX provide a sane fallback.
- return "btver1";
+ default:
+ return "amdfam15";
+ }
+ case AMDFAM16H:
+ switch (Subtype) {
+ case AMD_BTVER1:
+ return "btver1";
+ case AMD_BTVER2:
return "btver2";
+ default:
+ return "amdfam16";
+ }
default:
return "generic";
}
}
return "generic";
}
+
#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
StringRef sys::getHostCPUName() {
host_basic_info_data_t hostInfo;
mach_msg_type_number_t infoCount;
infoCount = HOST_BASIC_INFO_COUNT;
- host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo,
+ host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo,
&infoCount);
-
- if (hostInfo.cpu_type != CPU_TYPE_POWERPC) return "generic";
-
- switch(hostInfo.cpu_subtype) {
- case CPU_SUBTYPE_POWERPC_601: return "601";
- case CPU_SUBTYPE_POWERPC_602: return "602";
- case CPU_SUBTYPE_POWERPC_603: return "603";
- case CPU_SUBTYPE_POWERPC_603e: return "603e";
- case CPU_SUBTYPE_POWERPC_603ev: return "603ev";
- case CPU_SUBTYPE_POWERPC_604: return "604";
- case CPU_SUBTYPE_POWERPC_604e: return "604e";
- case CPU_SUBTYPE_POWERPC_620: return "620";
- case CPU_SUBTYPE_POWERPC_750: return "750";
- case CPU_SUBTYPE_POWERPC_7400: return "7400";
- case CPU_SUBTYPE_POWERPC_7450: return "7450";
- case CPU_SUBTYPE_POWERPC_970: return "970";
- default: ;
+
+ if (hostInfo.cpu_type != CPU_TYPE_POWERPC)
+ return "generic";
+
+ switch (hostInfo.cpu_subtype) {
+ case CPU_SUBTYPE_POWERPC_601:
+ return "601";
+ case CPU_SUBTYPE_POWERPC_602:
+ return "602";
+ case CPU_SUBTYPE_POWERPC_603:
+ return "603";
+ case CPU_SUBTYPE_POWERPC_603e:
+ return "603e";
+ case CPU_SUBTYPE_POWERPC_603ev:
+ return "603ev";
+ case CPU_SUBTYPE_POWERPC_604:
+ return "604";
+ case CPU_SUBTYPE_POWERPC_604e:
+ return "604e";
+ case CPU_SUBTYPE_POWERPC_620:
+ return "620";
+ case CPU_SUBTYPE_POWERPC_750:
+ return "750";
+ case CPU_SUBTYPE_POWERPC_7400:
+ return "7400";
+ case CPU_SUBTYPE_POWERPC_7450:
+ return "7450";
+ case CPU_SUBTYPE_POWERPC_970:
+ return "970";
+ default:;
}
-
+
return "generic";
}
#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__))
@@ -573,12 +983,12 @@ StringRef sys::getHostCPUName() {
++CIP;
while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
++CIP;
-
+
if (CIP < CPUInfoEnd && *CIP == ':') {
++CIP;
while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
++CIP;
-
+
if (CIP < CPUInfoEnd) {
CPUStart = CIP;
while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
@@ -600,24 +1010,25 @@ StringRef sys::getHostCPUName() {
return generic;
return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
- .Case("604e", "604e")
- .Case("604", "604")
- .Case("7400", "7400")
- .Case("7410", "7400")
- .Case("7447", "7400")
- .Case("7455", "7450")
- .Case("G4", "g4")
- .Case("POWER4", "970")
- .Case("PPC970FX", "970")
- .Case("PPC970MP", "970")
- .Case("G5", "g5")
- .Case("POWER5", "g5")
- .Case("A2", "a2")
- .Case("POWER6", "pwr6")
- .Case("POWER7", "pwr7")
- .Case("POWER8", "pwr8")
- .Case("POWER8E", "pwr8")
- .Default(generic);
+ .Case("604e", "604e")
+ .Case("604", "604")
+ .Case("7400", "7400")
+ .Case("7410", "7400")
+ .Case("7447", "7400")
+ .Case("7455", "7450")
+ .Case("G4", "g4")
+ .Case("POWER4", "970")
+ .Case("PPC970FX", "970")
+ .Case("PPC970MP", "970")
+ .Case("G5", "g5")
+ .Case("POWER5", "g5")
+ .Case("A2", "a2")
+ .Case("POWER6", "pwr6")
+ .Case("POWER7", "pwr7")
+ .Case("POWER8", "pwr8")
+ .Case("POWER8E", "pwr8")
+ .Case("POWER9", "pwr9")
+ .Default(generic);
}
#elif defined(__linux__) && defined(__arm__)
StringRef sys::getHostCPUName() {
@@ -650,18 +1061,18 @@ StringRef sys::getHostCPUName() {
// values correspond to the "Part number" in the CP15/c0 register. The
// contents are specified in the various processor manuals.
return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
- .Case("0x926", "arm926ej-s")
- .Case("0xb02", "mpcore")
- .Case("0xb36", "arm1136j-s")
- .Case("0xb56", "arm1156t2-s")
- .Case("0xb76", "arm1176jz-s")
- .Case("0xc08", "cortex-a8")
- .Case("0xc09", "cortex-a9")
- .Case("0xc0f", "cortex-a15")
- .Case("0xc20", "cortex-m0")
- .Case("0xc23", "cortex-m3")
- .Case("0xc24", "cortex-m4")
- .Default("generic");
+ .Case("0x926", "arm926ej-s")
+ .Case("0xb02", "mpcore")
+ .Case("0xb36", "arm1136j-s")
+ .Case("0xb56", "arm1156t2-s")
+ .Case("0xb76", "arm1176jz-s")
+ .Case("0xc08", "cortex-a8")
+ .Case("0xc09", "cortex-a9")
+ .Case("0xc0f", "cortex-a15")
+ .Case("0xc20", "cortex-m0")
+ .Case("0xc23", "cortex-m3")
+ .Case("0xc24", "cortex-m4")
+ .Default("generic");
if (Implementer == "0x51") // Qualcomm Technologies, Inc.
// Look for the CPU part line.
@@ -671,8 +1082,8 @@ StringRef sys::getHostCPUName() {
// values correspond to the "Part number" in the CP15/c0 register. The
// contents are specified in the various processor manuals.
return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
- .Case("0x06f", "krait") // APQ8064
- .Default("generic");
+ .Case("0x06f", "krait") // APQ8064
+ .Default("generic");
return "generic";
}
@@ -730,107 +1141,117 @@ StringRef sys::getHostCPUName() {
break;
}
}
-
+
return "generic";
}
#else
-StringRef sys::getHostCPUName() {
- return "generic";
-}
+StringRef sys::getHostCPUName() { return "generic"; }
#endif
-#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\
- || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
+#if defined(i386) || defined(__i386__) || defined(__x86__) || \
+ defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64) || \
+ defined(_M_X64)
bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
unsigned MaxLevel;
union {
unsigned u[3];
- char c[12];
+ char c[12];
} text;
- if (GetX86CpuIDAndInfo(0, &MaxLevel, text.u+0, text.u+2, text.u+1) ||
+ if (getX86CpuIDAndInfo(0, &MaxLevel, text.u + 0, text.u + 2, text.u + 1) ||
MaxLevel < 1)
return false;
- GetX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
+ getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
- Features["cmov"] = (EDX >> 15) & 1;
- Features["mmx"] = (EDX >> 23) & 1;
- Features["sse"] = (EDX >> 25) & 1;
- Features["sse2"] = (EDX >> 26) & 1;
- Features["sse3"] = (ECX >> 0) & 1;
- Features["ssse3"] = (ECX >> 9) & 1;
+ Features["cmov"] = (EDX >> 15) & 1;
+ Features["mmx"] = (EDX >> 23) & 1;
+ Features["sse"] = (EDX >> 25) & 1;
+ Features["sse2"] = (EDX >> 26) & 1;
+ Features["sse3"] = (ECX >> 0) & 1;
+ Features["ssse3"] = (ECX >> 9) & 1;
Features["sse4.1"] = (ECX >> 19) & 1;
Features["sse4.2"] = (ECX >> 20) & 1;
- Features["pclmul"] = (ECX >> 1) & 1;
- Features["cx16"] = (ECX >> 13) & 1;
- Features["movbe"] = (ECX >> 22) & 1;
+ Features["pclmul"] = (ECX >> 1) & 1;
+ Features["cx16"] = (ECX >> 13) & 1;
+ Features["movbe"] = (ECX >> 22) & 1;
Features["popcnt"] = (ECX >> 23) & 1;
- Features["aes"] = (ECX >> 25) & 1;
- Features["rdrnd"] = (ECX >> 30) & 1;
+ Features["aes"] = (ECX >> 25) & 1;
+ Features["rdrnd"] = (ECX >> 30) & 1;
// If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
// indicates that the AVX registers will be saved and restored on context
// switch, then we have full AVX support.
bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) &&
- !GetX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6);
- Features["avx"] = HasAVXSave;
- Features["fma"] = HasAVXSave && (ECX >> 12) & 1;
- Features["f16c"] = HasAVXSave && (ECX >> 29) & 1;
+ !getX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6);
+ Features["avx"] = HasAVXSave;
+ Features["fma"] = HasAVXSave && (ECX >> 12) & 1;
+ Features["f16c"] = HasAVXSave && (ECX >> 29) & 1;
// Only enable XSAVE if OS has enabled support for saving YMM state.
- Features["xsave"] = HasAVXSave && (ECX >> 26) & 1;
+ Features["xsave"] = HasAVXSave && (ECX >> 26) & 1;
// AVX512 requires additional context to be saved by the OS.
bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
unsigned MaxExtLevel;
- GetX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
+ getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
- !GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
- Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1);
- Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1);
- Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1);
- Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
- Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
- Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1);
-
- bool HasLeaf7 = MaxLevel >= 7 &&
- !GetX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
+ !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
+ Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1);
+ Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1);
+ Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1);
+ Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
+ Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
+ Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1);
+ Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);
+
+ bool HasLeaf7 =
+ MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
// AVX2 is only supported if we have the OS save support from AVX.
- Features["avx2"] = HasAVXSave && HasLeaf7 && ((EBX >> 5) & 1);
-
- Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1);
- Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1);
- Features["hle"] = HasLeaf7 && ((EBX >> 4) & 1);
- Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1);
- Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1);
- Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1);
- Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1);
- Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1);
- // Enable protection keys
- Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1);
+ Features["avx2"] = HasAVXSave && HasLeaf7 && ((EBX >> 5) & 1);
+
+ Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1);
+ Features["sgx"] = HasLeaf7 && ((EBX >> 2) & 1);
+ Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1);
+ Features["hle"] = HasLeaf7 && ((EBX >> 4) & 1);
+ Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1);
+ Features["invpcid"] = HasLeaf7 && ((EBX >> 10) & 1);
+ Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1);
+ Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1);
+ Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1);
+ Features["smap"] = HasLeaf7 && ((EBX >> 20) & 1);
+ Features["pcommit"] = HasLeaf7 && ((EBX >> 22) & 1);
+ Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);
+ Features["clwb"] = HasLeaf7 && ((EBX >> 24) & 1);
+ Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1);
// AVX512 is only supported if the OS supports the context save for it.
- Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
+ Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
+ Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;
Features["avx512pf"] = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save;
Features["avx512er"] = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save;
Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
+ Features["prefetchwt1"] = HasLeaf7 && (ECX & 1);
+ Features["avx512vbmi"] = HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save;
+ // Enable protection keys
+ Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1);
+
bool HasLeafD = MaxLevel >= 0xd &&
- !GetX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
+ !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
// Only enable XSAVE if OS has enabled support for saving YMM state.
Features["xsaveopt"] = HasAVXSave && HasLeafD && ((EAX >> 0) & 1);
- Features["xsavec"] = HasAVXSave && HasLeafD && ((EAX >> 1) & 1);
- Features["xsaves"] = HasAVXSave && HasLeafD && ((EAX >> 3) & 1);
+ Features["xsavec"] = HasAVXSave && HasLeafD && ((EAX >> 1) & 1);
+ Features["xsaves"] = HasAVXSave && HasLeafD && ((EAX >> 3) & 1);
return true;
}
@@ -859,31 +1280,26 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
#if defined(__aarch64__)
// Keep track of which crypto features we have seen
- enum {
- CAP_AES = 0x1,
- CAP_PMULL = 0x2,
- CAP_SHA1 = 0x4,
- CAP_SHA2 = 0x8
- };
+ enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };
uint32_t crypto = 0;
#endif
for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
#if defined(__aarch64__)
- .Case("asimd", "neon")
- .Case("fp", "fp-armv8")
- .Case("crc32", "crc")
+ .Case("asimd", "neon")
+ .Case("fp", "fp-armv8")
+ .Case("crc32", "crc")
#else
- .Case("half", "fp16")
- .Case("neon", "neon")
- .Case("vfpv3", "vfp3")
- .Case("vfpv3d16", "d16")
- .Case("vfpv4", "vfp4")
- .Case("idiva", "hwdiv-arm")
- .Case("idivt", "hwdiv")
+ .Case("half", "fp16")
+ .Case("neon", "neon")
+ .Case("vfpv3", "vfp3")
+ .Case("vfpv3d16", "d16")
+ .Case("vfpv4", "vfp4")
+ .Case("idiva", "hwdiv-arm")
+ .Case("idivt", "hwdiv")
#endif
- .Default("");
+ .Default("");
#if defined(__aarch64__)
// We need to check crypto separately since we need all of the crypto
@@ -911,9 +1327,7 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
return true;
}
#else
-bool sys::getHostCPUFeatures(StringMap<bool> &Features){
- return false;
-}
+bool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; }
#endif
std::string sys::getProcessTriple() {
diff --git a/contrib/llvm/lib/Support/IntEqClasses.cpp b/contrib/llvm/lib/Support/IntEqClasses.cpp
index ff21357..cb6e3a1 100644
--- a/contrib/llvm/lib/Support/IntEqClasses.cpp
+++ b/contrib/llvm/lib/Support/IntEqClasses.cpp
@@ -37,10 +37,15 @@ unsigned IntEqClasses::join(unsigned a, unsigned b) {
// incrementally. The larger leader will eventually be updated, joining the
// classes.
while (eca != ecb)
- if (eca < ecb)
- EC[b] = eca, b = ecb, ecb = EC[b];
- else
- EC[a] = ecb, a = eca, eca = EC[a];
+ if (eca < ecb) {
+ EC[b] = eca;
+ b = ecb;
+ ecb = EC[b];
+ } else {
+ EC[a] = ecb;
+ a = eca;
+ eca = EC[a];
+ }
return eca;
}
diff --git a/contrib/llvm/lib/Support/JamCRC.cpp b/contrib/llvm/lib/Support/JamCRC.cpp
index bc21c91..17c55f5 100644
--- a/contrib/llvm/lib/Support/JamCRC.cpp
+++ b/contrib/llvm/lib/Support/JamCRC.cpp
@@ -18,6 +18,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/JamCRC.h"
+#include "llvm/ADT/ArrayRef.h"
using namespace llvm;
diff --git a/contrib/llvm/lib/Support/Locale.cpp b/contrib/llvm/lib/Support/Locale.cpp
index 53bc0e3..e24a28b 100644
--- a/contrib/llvm/lib/Support/Locale.cpp
+++ b/contrib/llvm/lib/Support/Locale.cpp
@@ -1,5 +1,6 @@
-#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Locale.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Unicode.h"
namespace llvm {
diff --git a/contrib/llvm/lib/Support/LockFileManager.cpp b/contrib/llvm/lib/Support/LockFileManager.cpp
index fb81d60..611f94a 100644
--- a/contrib/llvm/lib/Support/LockFileManager.cpp
+++ b/contrib/llvm/lib/Support/LockFileManager.cpp
@@ -144,7 +144,9 @@ LockFileManager::LockFileManager(StringRef FileName)
{
this->FileName = FileName;
if (std::error_code EC = sys::fs::make_absolute(this->FileName)) {
- Error = EC;
+ std::string S("failed to obtain absolute path for ");
+ S.append(this->FileName.str());
+ setError(EC, S);
return;
}
LockFileName = this->FileName;
@@ -161,7 +163,9 @@ LockFileManager::LockFileManager(StringRef FileName)
int UniqueLockFileID;
if (std::error_code EC = sys::fs::createUniqueFile(
UniqueLockFileName, UniqueLockFileID, UniqueLockFileName)) {
- Error = EC;
+ std::string S("failed to create unique file ");
+ S.append(UniqueLockFileName.str());
+ setError(EC, S);
return;
}
@@ -169,7 +173,7 @@ LockFileManager::LockFileManager(StringRef FileName)
{
SmallString<256> HostID;
if (auto EC = getHostID(HostID)) {
- Error = EC;
+ setError(EC, "failed to get host id");
return;
}
@@ -185,7 +189,10 @@ LockFileManager::LockFileManager(StringRef FileName)
if (Out.has_error()) {
// We failed to write out PID, so make up an excuse, remove the
// unique lock file, and fail.
- Error = make_error_code(errc::no_space_on_device);
+ auto EC = make_error_code(errc::no_space_on_device);
+ std::string S("failed to write to ");
+ S.append(UniqueLockFileName.str());
+ setError(EC, S);
sys::fs::remove(UniqueLockFileName);
return;
}
@@ -205,7 +212,10 @@ LockFileManager::LockFileManager(StringRef FileName)
}
if (EC != errc::file_exists) {
- Error = EC;
+ std::string S("failed to create link ");
+ raw_string_ostream OSS(S);
+ OSS << LockFileName.str() << " to " << UniqueLockFileName.str();
+ setError(EC, OSS.str());
return;
}
@@ -226,7 +236,9 @@ LockFileManager::LockFileManager(StringRef FileName)
// There is a lock file that nobody owns; try to clean it up and get
// ownership.
if ((EC = sys::fs::remove(LockFileName))) {
- Error = EC;
+ std::string S("failed to remove lockfile ");
+ S.append(UniqueLockFileName.str());
+ setError(EC, S);
return;
}
}
@@ -242,6 +254,19 @@ LockFileManager::LockFileState LockFileManager::getState() const {
return LFS_Owned;
}
+std::string LockFileManager::getErrorMessage() const {
+ if (Error) {
+ std::string Str(ErrorDiagMsg);
+ std::string ErrCodeMsg = Error->message();
+ raw_string_ostream OSS(Str);
+ if (!ErrCodeMsg.empty())
+ OSS << ": " << Error->message();
+ OSS.flush();
+ return Str;
+ }
+ return "";
+}
+
LockFileManager::~LockFileManager() {
if (getState() != LFS_Owned)
return;
diff --git a/contrib/llvm/lib/Support/ManagedStatic.cpp b/contrib/llvm/lib/Support/ManagedStatic.cpp
index 9868207..7dd3131 100644
--- a/contrib/llvm/lib/Support/ManagedStatic.cpp
+++ b/contrib/llvm/lib/Support/ManagedStatic.cpp
@@ -13,20 +13,25 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Config/config.h"
-#include "llvm/Support/Atomic.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
+#include "llvm/Support/Threading.h"
#include <cassert>
using namespace llvm;
static const ManagedStaticBase *StaticList = nullptr;
+static sys::Mutex *ManagedStaticMutex = nullptr;
+LLVM_DEFINE_ONCE_FLAG(mutex_init_flag);
-static sys::Mutex& getManagedStaticMutex() {
+static void initializeMutex() {
+ ManagedStaticMutex = new sys::Mutex();
+}
+
+static sys::Mutex* getManagedStaticMutex() {
// We need to use a function local static here, since this can get called
// during a static constructor and we need to guarantee that it's initialized
// correctly.
- static sys::Mutex ManagedStaticMutex;
+ llvm::call_once(mutex_init_flag, initializeMutex);
return ManagedStaticMutex;
}
@@ -34,20 +39,12 @@ void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
void (*Deleter)(void*)) const {
assert(Creator);
if (llvm_is_multithreaded()) {
- MutexGuard Lock(getManagedStaticMutex());
-
- if (!Ptr) {
- void* tmp = Creator();
+ MutexGuard Lock(*getManagedStaticMutex());
- TsanHappensBefore(this);
- sys::MemoryFence();
+ if (!Ptr.load(std::memory_order_relaxed)) {
+ void *Tmp = Creator();
- // This write is racy against the first read in the ManagedStatic
- // accessors. The race is benign because it does a second read after a
- // memory fence, at which point it isn't possible to get a partial value.
- TsanIgnoreWritesBegin();
- Ptr = tmp;
- TsanIgnoreWritesEnd();
+ Ptr.store(Tmp, std::memory_order_release);
DeleterFn = Deleter;
// Add to list of managed statics.
@@ -84,7 +81,7 @@ void ManagedStaticBase::destroy() const {
/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
void llvm::llvm_shutdown() {
- MutexGuard Lock(getManagedStaticMutex());
+ MutexGuard Lock(*getManagedStaticMutex());
while (StaticList)
StaticList->destroy();
diff --git a/contrib/llvm/lib/Support/MemoryBuffer.cpp b/contrib/llvm/lib/Support/MemoryBuffer.cpp
index faee10b..b935cbf 100644
--- a/contrib/llvm/lib/Support/MemoryBuffer.cpp
+++ b/contrib/llvm/lib/Support/MemoryBuffer.cpp
@@ -86,6 +86,10 @@ public:
init(InputData.begin(), InputData.end(), RequiresNullTerminator);
}
+ /// Disable sized deallocation for MemoryBufferMem, because it has
+ /// tail-allocated data.
+ void operator delete(void *p) { ::operator delete(p); }
+
const char *getBufferIdentifier() const override {
// The name is stored after the class itself.
return reinterpret_cast<const char*>(this + 1);
@@ -135,7 +139,7 @@ MemoryBuffer::getNewUninitMemBuffer(size_t Size, const Twine &BufferName) {
SmallString<256> NameBuf;
StringRef NameRef = BufferName.toStringRef(NameBuf);
size_t AlignedStringLen =
- RoundUpToAlignment(sizeof(MemoryBufferMem) + NameRef.size() + 1, 16);
+ alignTo(sizeof(MemoryBufferMem) + NameRef.size() + 1, 16);
size_t RealLen = AlignedStringLen + Size + 1;
char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
if (!Mem)
@@ -213,6 +217,10 @@ public:
}
}
+ /// Disable sized deallocation for MemoryBufferMMapFile, because it has
+ /// tail-allocated data.
+ void operator delete(void *p) { ::operator delete(p); }
+
const char *getBufferIdentifier() const override {
// The name is stored after the class itself.
return reinterpret_cast<const char *>(this + 1);
diff --git a/contrib/llvm/lib/Support/Path.cpp b/contrib/llvm/lib/Support/Path.cpp
index 4952f59..f6355d1 100644
--- a/contrib/llvm/lib/Support/Path.cpp
+++ b/contrib/llvm/lib/Support/Path.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/COFF.h"
+#include "llvm/Support/MachO.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
@@ -352,6 +353,10 @@ bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
Position == RHS.Position;
}
+ptrdiff_t reverse_iterator::operator-(const reverse_iterator &RHS) const {
+ return Position - RHS.Position;
+}
+
StringRef root_path(StringRef path) {
const_iterator b = begin(path),
pos = b,
@@ -517,6 +522,29 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension) {
path.append(ext.begin(), ext.end());
}
+void replace_path_prefix(SmallVectorImpl<char> &Path,
+ const StringRef &OldPrefix,
+ const StringRef &NewPrefix) {
+ if (OldPrefix.empty() && NewPrefix.empty())
+ return;
+
+ StringRef OrigPath(Path.begin(), Path.size());
+ if (!OrigPath.startswith(OldPrefix))
+ return;
+
+ // If prefixes have the same size we can simply copy the new one over.
+ if (OldPrefix.size() == NewPrefix.size()) {
+ std::copy(NewPrefix.begin(), NewPrefix.end(), Path.begin());
+ return;
+ }
+
+ StringRef RelPath = OrigPath.substr(OldPrefix.size());
+ SmallString<256> NewPath;
+ path::append(NewPath, NewPrefix);
+ path::append(NewPath, RelPath);
+ Path.swap(NewPath);
+}
+
void native(const Twine &path, SmallVectorImpl<char> &result) {
assert((!path.isSingleStringRef() ||
path.getSingleStringRef().data() != result.data()) &&
@@ -1021,7 +1049,7 @@ file_magic identify_magic(StringRef Magic) {
case 0xCA:
if (Magic[1] == char(0xFE) && Magic[2] == char(0xBA) &&
- Magic[3] == char(0xBE)) {
+ (Magic[3] == char(0xBE) || Magic[3] == char(0xBF))) {
// This is complicated by an overlap with Java class files.
// See the Mach-O section in /usr/share/file/magic for details.
if (Magic.size() >= 8 && Magic[7] < 43)
@@ -1040,12 +1068,24 @@ file_magic identify_magic(StringRef Magic) {
Magic[2] == char(0xFA) &&
(Magic[3] == char(0xCE) || Magic[3] == char(0xCF))) {
/* Native endian */
- if (Magic.size() >= 16) type = Magic[14] << 8 | Magic[15];
+ size_t MinSize;
+ if (Magic[3] == char(0xCE))
+ MinSize = sizeof(MachO::mach_header);
+ else
+ MinSize = sizeof(MachO::mach_header_64);
+ if (Magic.size() >= MinSize)
+ type = Magic[12] << 24 | Magic[13] << 12 | Magic[14] << 8 | Magic[15];
} else if ((Magic[0] == char(0xCE) || Magic[0] == char(0xCF)) &&
Magic[1] == char(0xFA) && Magic[2] == char(0xED) &&
Magic[3] == char(0xFE)) {
/* Reverse endian */
- if (Magic.size() >= 14) type = Magic[13] << 8 | Magic[12];
+ size_t MinSize;
+ if (Magic[0] == char(0xCE))
+ MinSize = sizeof(MachO::mach_header);
+ else
+ MinSize = sizeof(MachO::mach_header_64);
+ if (Magic.size() >= MinSize)
+ type = Magic[15] << 24 | Magic[14] << 12 |Magic[13] << 8 | Magic[12];
}
switch (type) {
default: break;
diff --git a/contrib/llvm/lib/Support/PrettyStackTrace.cpp b/contrib/llvm/lib/Support/PrettyStackTrace.cpp
index 05b3e31..ebad67b 100644
--- a/contrib/llvm/lib/Support/PrettyStackTrace.cpp
+++ b/contrib/llvm/lib/Support/PrettyStackTrace.cpp
@@ -21,6 +21,8 @@
#include "llvm/Support/Watchdog.h"
#include "llvm/Support/raw_ostream.h"
+#include <tuple>
+
#ifdef HAVE_CRASHREPORTERCLIENT_H
#include <CrashReporterClient.h>
#endif
@@ -36,20 +38,32 @@ using namespace llvm;
// objects, but we *really* cannot tolerate destructors running and do not want
// to pay any overhead of synchronizing. As a consequence, we use a raw
// thread-local variable.
-static LLVM_THREAD_LOCAL const PrettyStackTraceEntry *PrettyStackTraceHead =
- nullptr;
-
-static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){
- unsigned NextID = 0;
- if (Entry->getNextEntry())
- NextID = PrintStack(Entry->getNextEntry(), OS);
- OS << NextID << ".\t";
- {
+static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr;
+
+namespace llvm {
+PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) {
+ PrettyStackTraceEntry *Prev = nullptr;
+ while (Head)
+ std::tie(Prev, Head, Head->NextEntry) =
+ std::make_tuple(Head, Head->NextEntry, Prev);
+ return Prev;
+}
+}
+
+static void PrintStack(raw_ostream &OS) {
+ // Print out the stack in reverse order. To avoid recursion (which is likely
+ // to fail if we crashed due to stack overflow), we do an up-front pass to
+ // reverse the stack, then print it, then reverse it again.
+ unsigned ID = 0;
+ PrettyStackTraceEntry *ReversedStack =
+ llvm::ReverseStackTrace(PrettyStackTraceHead);
+ for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry;
+ Entry = Entry->getNextEntry()) {
+ OS << ID++ << ".\t";
sys::Watchdog W(5);
Entry->print(OS);
}
-
- return NextID+1;
+ llvm::ReverseStackTrace(ReversedStack);
}
/// PrintCurStackTrace - Print the current stack trace to the specified stream.
@@ -60,7 +74,7 @@ static void PrintCurStackTrace(raw_ostream &OS) {
// If there are pretty stack frames registered, walk and emit them.
OS << "Stack dump:\n";
- PrintStack(PrettyStackTraceHead, OS);
+ PrintStack(OS);
OS.flush();
}
@@ -123,7 +137,7 @@ PrettyStackTraceEntry::~PrettyStackTraceEntry() {
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
assert(PrettyStackTraceHead == this &&
"Pretty stack trace entry destruction is out of order");
- PrettyStackTraceHead = getNextEntry();
+ PrettyStackTraceHead = NextEntry;
#endif
}
@@ -154,7 +168,7 @@ void llvm::EnablePrettyStackTrace() {
#endif
}
-const void* llvm::SavePrettyStackState() {
+const void *llvm::SavePrettyStackState() {
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
return PrettyStackTraceHead;
#else
@@ -162,9 +176,10 @@ const void* llvm::SavePrettyStackState() {
#endif
}
-void llvm::RestorePrettyStackState(const void* Top) {
+void llvm::RestorePrettyStackState(const void *Top) {
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
- PrettyStackTraceHead = (const PrettyStackTraceEntry*)Top;
+ PrettyStackTraceHead =
+ static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top));
#endif
}
diff --git a/contrib/llvm/lib/Support/Process.cpp b/contrib/llvm/lib/Support/Process.cpp
index 6dcbb47..290c30f 100644
--- a/contrib/llvm/lib/Support/Process.cpp
+++ b/contrib/llvm/lib/Support/Process.cpp
@@ -73,6 +73,13 @@ static const char colorcodes[2][2][8][10] = {
{ ALLCOLORS("4",""), ALLCOLORS("4","1;") }
};
+// This is set to true when Process::PreventCoreFiles() is called.
+static bool coreFilesPrevented = false;
+
+bool Process::AreCoreFilesPrevented() {
+ return coreFilesPrevented;
+}
+
// Include the platform-specific parts of this class.
#ifdef LLVM_ON_UNIX
#include "Unix/Process.inc"
diff --git a/contrib/llvm/lib/Support/SHA1.cpp b/contrib/llvm/lib/Support/SHA1.cpp
new file mode 100644
index 0000000..a461d1e
--- /dev/null
+++ b/contrib/llvm/lib/Support/SHA1.cpp
@@ -0,0 +1,170 @@
+//======- SHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ======//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This code is taken from public domain
+// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c)
+// and modified by wrapping it in a C++ interface for LLVM,
+// and removing unnecessary code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Host.h"
+#include "llvm/Support/SHA1.h"
+#include "llvm/ADT/ArrayRef.h"
+using namespace llvm;
+
+#include <stdint.h>
+#include <string.h>
+
+#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
+#define SHA_BIG_ENDIAN
+#endif
+
+/* code */
+#define SHA1_K0 0x5a827999
+#define SHA1_K20 0x6ed9eba1
+#define SHA1_K40 0x8f1bbcdc
+#define SHA1_K60 0xca62c1d6
+
+#define SEED_0 0x67452301
+#define SEED_1 0xefcdab89
+#define SEED_2 0x98badcfe
+#define SEED_3 0x10325476
+#define SEED_4 0xc3d2e1f0
+
+void SHA1::init() {
+ InternalState.State[0] = SEED_0;
+ InternalState.State[1] = SEED_1;
+ InternalState.State[2] = SEED_2;
+ InternalState.State[3] = SEED_3;
+ InternalState.State[4] = SEED_4;
+ InternalState.ByteCount = 0;
+ InternalState.BufferOffset = 0;
+}
+
+static uint32_t rol32(uint32_t number, uint8_t bits) {
+ return ((number << bits) | (number >> (32 - bits)));
+}
+
+void SHA1::hashBlock() {
+ uint8_t i;
+ uint32_t a, b, c, d, e, t;
+
+ a = InternalState.State[0];
+ b = InternalState.State[1];
+ c = InternalState.State[2];
+ d = InternalState.State[3];
+ e = InternalState.State[4];
+ for (i = 0; i < 80; i++) {
+ if (i >= 16) {
+ t = InternalState.Buffer[(i + 13) & 15] ^
+ InternalState.Buffer[(i + 8) & 15] ^
+ InternalState.Buffer[(i + 2) & 15] ^ InternalState.Buffer[i & 15];
+ InternalState.Buffer[i & 15] = rol32(t, 1);
+ }
+ if (i < 20) {
+ t = (d ^ (b & (c ^ d))) + SHA1_K0;
+ } else if (i < 40) {
+ t = (b ^ c ^ d) + SHA1_K20;
+ } else if (i < 60) {
+ t = ((b & c) | (d & (b | c))) + SHA1_K40;
+ } else {
+ t = (b ^ c ^ d) + SHA1_K60;
+ }
+ t += rol32(a, 5) + e + InternalState.Buffer[i & 15];
+ e = d;
+ d = c;
+ c = rol32(b, 30);
+ b = a;
+ a = t;
+ }
+ InternalState.State[0] += a;
+ InternalState.State[1] += b;
+ InternalState.State[2] += c;
+ InternalState.State[3] += d;
+ InternalState.State[4] += e;
+}
+
+void SHA1::addUncounted(uint8_t data) {
+ uint8_t *const b = (uint8_t *)InternalState.Buffer;
+#ifdef SHA_BIG_ENDIAN
+ b[InternalState.BufferOffset] = data;
+#else
+ b[InternalState.BufferOffset ^ 3] = data;
+#endif
+ InternalState.BufferOffset++;
+ if (InternalState.BufferOffset == BLOCK_LENGTH) {
+ hashBlock();
+ InternalState.BufferOffset = 0;
+ }
+}
+
+void SHA1::writebyte(uint8_t data) {
+ ++InternalState.ByteCount;
+ addUncounted(data);
+}
+
+void SHA1::update(ArrayRef<uint8_t> Data) {
+ for (auto &C : Data)
+ writebyte(C);
+}
+
+void SHA1::pad() {
+ // Implement SHA-1 padding (fips180-2 5.1.1)
+
+ // Pad with 0x80 followed by 0x00 until the end of the block
+ addUncounted(0x80);
+ while (InternalState.BufferOffset != 56)
+ addUncounted(0x00);
+
+ // Append length in the last 8 bytes
+ addUncounted(0); // We're only using 32 bit lengths
+ addUncounted(0); // But SHA-1 supports 64 bit lengths
+ addUncounted(0); // So zero pad the top bits
+ addUncounted(InternalState.ByteCount >> 29); // Shifting to multiply by 8
+ addUncounted(InternalState.ByteCount >>
+ 21); // as SHA-1 supports bitstreams as well as
+ addUncounted(InternalState.ByteCount >> 13); // byte.
+ addUncounted(InternalState.ByteCount >> 5);
+ addUncounted(InternalState.ByteCount << 3);
+}
+
+StringRef SHA1::final() {
+ // Pad to complete the last block
+ pad();
+
+#ifdef SHA_BIG_ENDIAN
+ // Just copy the current state
+ for (int i = 0; i < 5; i++) {
+ HashResult[i] = InternalState.State[i];
+ }
+#else
+ // Swap byte order back
+ for (int i = 0; i < 5; i++) {
+ HashResult[i] = (((InternalState.State[i]) << 24) & 0xff000000) |
+ (((InternalState.State[i]) << 8) & 0x00ff0000) |
+ (((InternalState.State[i]) >> 8) & 0x0000ff00) |
+ (((InternalState.State[i]) >> 24) & 0x000000ff);
+ }
+#endif
+
+ // Return pointer to hash (20 characters)
+ return StringRef((char *)HashResult, HASH_LENGTH);
+}
+
+StringRef SHA1::result() {
+ auto StateToRestore = InternalState;
+
+ auto Hash = final();
+
+ // Restore the state
+ InternalState = StateToRestore;
+
+ // Return pointer to hash (20 characters)
+ return Hash;
+}
diff --git a/contrib/llvm/lib/Support/ScaledNumber.cpp b/contrib/llvm/lib/Support/ScaledNumber.cpp
index 987c2d8..b9432d4 100644
--- a/contrib/llvm/lib/Support/ScaledNumber.cpp
+++ b/contrib/llvm/lib/Support/ScaledNumber.cpp
@@ -13,6 +13,7 @@
#include "llvm/Support/ScaledNumber.h"
#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/contrib/llvm/lib/Support/ScopedPrinter.cpp b/contrib/llvm/lib/Support/ScopedPrinter.cpp
new file mode 100644
index 0000000..0225f01
--- /dev/null
+++ b/contrib/llvm/lib/Support/ScopedPrinter.cpp
@@ -0,0 +1,72 @@
+#include "llvm/Support/ScopedPrinter.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Format.h"
+#include <cctype>
+
+using namespace llvm::support;
+
+namespace llvm {
+
+raw_ostream &operator<<(raw_ostream &OS, const HexNumber &Value) {
+ OS << "0x" << to_hexString(Value.Value);
+ return OS;
+}
+
+const std::string to_hexString(uint64_t Value, bool UpperCase) {
+ std::string number;
+ llvm::raw_string_ostream stream(number);
+ stream << format_hex_no_prefix(Value, 1, UpperCase);
+ return stream.str();
+}
+
+void ScopedPrinter::printBinaryImpl(StringRef Label, StringRef Str,
+ ArrayRef<uint8_t> Data, bool Block) {
+ if (Data.size() > 16)
+ Block = true;
+
+ if (Block) {
+ startLine() << Label;
+ if (Str.size() > 0)
+ OS << ": " << Str;
+ OS << " (\n";
+ for (size_t addr = 0, end = Data.size(); addr < end; addr += 16) {
+ startLine() << format(" %04" PRIX64 ": ", uint64_t(addr));
+ // Dump line of hex.
+ for (size_t i = 0; i < 16; ++i) {
+ if (i != 0 && i % 4 == 0)
+ OS << ' ';
+ if (addr + i < end)
+ OS << hexdigit((Data[addr + i] >> 4) & 0xF, false)
+ << hexdigit(Data[addr + i] & 0xF, false);
+ else
+ OS << " ";
+ }
+ // Print ascii.
+ OS << " |";
+ for (std::size_t i = 0; i < 16 && addr + i < end; ++i) {
+ if (std::isprint(Data[addr + i] & 0xFF))
+ OS << Data[addr + i];
+ else
+ OS << ".";
+ }
+ OS << "|\n";
+ }
+
+ startLine() << ")\n";
+ } else {
+ startLine() << Label << ":";
+ if (Str.size() > 0)
+ OS << " " << Str;
+ OS << " (";
+ for (size_t i = 0; i < Data.size(); ++i) {
+ if (i > 0)
+ OS << " ";
+
+ OS << format("%02X", static_cast<int>(Data[i]));
+ }
+ OS << ")\n";
+ }
+}
+
+} // namespace llvm
diff --git a/contrib/llvm/lib/Support/Signals.cpp b/contrib/llvm/lib/Support/Signals.cpp
index 3dc6b7c..e5e38f5 100644
--- a/contrib/llvm/lib/Support/Signals.cpp
+++ b/contrib/llvm/lib/Support/Signals.cpp
@@ -62,28 +62,40 @@ static FormattedNumber format_ptr(void *PC) {
return format_hex((uint64_t)PC, PtrWidth);
}
-static bool printSymbolizedStackTrace(void **StackTrace, int Depth,
+static bool printSymbolizedStackTrace(StringRef Argv0,
+ void **StackTrace, int Depth,
llvm::raw_ostream &OS)
LLVM_ATTRIBUTE_USED;
/// Helper that launches llvm-symbolizer and symbolizes a backtrace.
-static bool printSymbolizedStackTrace(void **StackTrace, int Depth,
+static bool printSymbolizedStackTrace(StringRef Argv0,
+ void **StackTrace, int Depth,
llvm::raw_ostream &OS) {
+ // Don't recursively invoke the llvm-symbolizer binary.
+ if (Argv0.find("llvm-symbolizer") != std::string::npos)
+ return false;
+
// FIXME: Subtract necessary number from StackTrace entries to turn return addresses
// into actual instruction addresses.
- // Use llvm-symbolizer tool to symbolize the stack traces.
- ErrorOr<std::string> LLVMSymbolizerPathOrErr =
- sys::findProgramByName("llvm-symbolizer");
+ // Use llvm-symbolizer tool to symbolize the stack traces. First look for it
+ // alongside our binary, then in $PATH.
+ ErrorOr<std::string> LLVMSymbolizerPathOrErr = std::error_code();
+ if (!Argv0.empty()) {
+ StringRef Parent = llvm::sys::path::parent_path(Argv0);
+ if (!Parent.empty())
+ LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer", Parent);
+ }
+ if (!LLVMSymbolizerPathOrErr)
+ LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer");
if (!LLVMSymbolizerPathOrErr)
return false;
const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr;
- // We don't know argv0 or the address of main() at this point, but try
- // to guess it anyway (it's possible on some platforms).
- std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr);
- if (MainExecutableName.empty() ||
- MainExecutableName.find("llvm-symbolizer") != std::string::npos)
- return false;
+ // If we don't know argv0 or the address of main() at this point, try
+ // to guess it anyway (it's possible on some platforms).
+ std::string MainExecutableName =
+ Argv0.empty() ? sys::fs::getMainExecutable(nullptr, nullptr)
+ : (std::string)Argv0;
BumpPtrAllocator Allocator;
StringSaver StrPool(Allocator);
std::vector<const char *> Modules(Depth, nullptr);
diff --git a/contrib/llvm/lib/Support/SmallPtrSet.cpp b/contrib/llvm/lib/Support/SmallPtrSet.cpp
index 358c8e8..539b4eb 100644
--- a/contrib/llvm/lib/Support/SmallPtrSet.cpp
+++ b/contrib/llvm/lib/Support/SmallPtrSet.cpp
@@ -25,8 +25,9 @@ void SmallPtrSetImplBase::shrink_and_clear() {
free(CurArray);
// Reduce the number of buckets.
- CurArraySize = NumElements > 16 ? 1 << (Log2_32_Ceil(NumElements) + 1) : 32;
- NumElements = NumTombstones = 0;
+ unsigned Size = size();
+ CurArraySize = Size > 16 ? 1 << (Log2_32_Ceil(Size) + 1) : 32;
+ NumNonEmpty = NumTombstones = 0;
// Install the new array. Clear all the buckets to empty.
CurArray = (const void**)malloc(sizeof(void*) * CurArraySize);
@@ -35,32 +36,16 @@ void SmallPtrSetImplBase::shrink_and_clear() {
}
std::pair<const void *const *, bool>
-SmallPtrSetImplBase::insert_imp(const void *Ptr) {
- if (isSmall()) {
- // Check to see if it is already in the set.
- for (const void **APtr = SmallArray, **E = SmallArray+NumElements;
- APtr != E; ++APtr)
- if (*APtr == Ptr)
- return std::make_pair(APtr, false);
-
- // Nope, there isn't. If we stay small, just 'pushback' now.
- if (NumElements < CurArraySize) {
- SmallArray[NumElements++] = Ptr;
- return std::make_pair(SmallArray + (NumElements - 1), true);
- }
- // Otherwise, hit the big set case, which will call grow.
- }
-
- if (LLVM_UNLIKELY(NumElements * 4 >= CurArraySize * 3)) {
+SmallPtrSetImplBase::insert_imp_big(const void *Ptr) {
+ if (LLVM_UNLIKELY(size() * 4 >= CurArraySize * 3)) {
// If more than 3/4 of the array is full, grow.
- Grow(CurArraySize < 64 ? 128 : CurArraySize*2);
- } else if (LLVM_UNLIKELY(CurArraySize - (NumElements + NumTombstones) <
- CurArraySize / 8)) {
+ Grow(CurArraySize < 64 ? 128 : CurArraySize * 2);
+ } else if (LLVM_UNLIKELY(CurArraySize - NumNonEmpty < CurArraySize / 8)) {
// If fewer of 1/8 of the array is empty (meaning that many are filled with
// tombstones), rehash.
Grow(CurArraySize);
}
-
+
// Okay, we know we have space. Find a hash bucket.
const void **Bucket = const_cast<const void**>(FindBucketFor(Ptr));
if (*Bucket == Ptr)
@@ -69,34 +54,33 @@ SmallPtrSetImplBase::insert_imp(const void *Ptr) {
// Otherwise, insert it!
if (*Bucket == getTombstoneMarker())
--NumTombstones;
+ else
+ ++NumNonEmpty; // Track density.
*Bucket = Ptr;
- ++NumElements; // Track density.
return std::make_pair(Bucket, true);
}
bool SmallPtrSetImplBase::erase_imp(const void * Ptr) {
if (isSmall()) {
// Check to see if it is in the set.
- for (const void **APtr = SmallArray, **E = SmallArray+NumElements;
- APtr != E; ++APtr)
+ for (const void **APtr = CurArray, **E = CurArray + NumNonEmpty; APtr != E;
+ ++APtr)
if (*APtr == Ptr) {
// If it is in the set, replace this element.
- *APtr = E[-1];
- E[-1] = getEmptyMarker();
- --NumElements;
+ *APtr = getTombstoneMarker();
+ ++NumTombstones;
return true;
}
-
+
return false;
}
-
+
// Okay, we know we have space. Find a hash bucket.
void **Bucket = const_cast<void**>(FindBucketFor(Ptr));
if (*Bucket != Ptr) return false; // Not in the set?
// Set this as a tombstone.
*Bucket = getTombstoneMarker();
- --NumElements;
++NumTombstones;
return true;
}
@@ -122,7 +106,7 @@ const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const {
// prefer to return it than something that would require more probing.
if (Array[Bucket] == getTombstoneMarker() && !Tombstone)
Tombstone = Array+Bucket; // Remember the first tombstone found.
-
+
// It's a hash collision or a tombstone. Reprobe.
Bucket = (Bucket + ProbeAmt++) & (ArraySize-1);
}
@@ -131,43 +115,32 @@ const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const {
/// Grow - Allocate a larger backing store for the buckets and move it over.
///
void SmallPtrSetImplBase::Grow(unsigned NewSize) {
- // Allocate at twice as many buckets, but at least 128.
- unsigned OldSize = CurArraySize;
-
const void **OldBuckets = CurArray;
+ const void **OldEnd = EndPointer();
bool WasSmall = isSmall();
-
+
// Install the new array. Clear all the buckets to empty.
CurArray = (const void**)malloc(sizeof(void*) * NewSize);
assert(CurArray && "Failed to allocate memory?");
CurArraySize = NewSize;
memset(CurArray, -1, NewSize*sizeof(void*));
-
- // Copy over all the elements.
- if (WasSmall) {
- // Small sets store their elements in order.
- for (const void **BucketPtr = OldBuckets, **E = OldBuckets+NumElements;
- BucketPtr != E; ++BucketPtr) {
- const void *Elt = *BucketPtr;
+
+ // Copy over all valid entries.
+ for (const void **BucketPtr = OldBuckets; BucketPtr != OldEnd; ++BucketPtr) {
+ // Copy over the element if it is valid.
+ const void *Elt = *BucketPtr;
+ if (Elt != getTombstoneMarker() && Elt != getEmptyMarker())
*const_cast<void**>(FindBucketFor(Elt)) = const_cast<void*>(Elt);
- }
- } else {
- // Copy over all valid entries.
- for (const void **BucketPtr = OldBuckets, **E = OldBuckets+OldSize;
- BucketPtr != E; ++BucketPtr) {
- // Copy over the element if it is valid.
- const void *Elt = *BucketPtr;
- if (Elt != getTombstoneMarker() && Elt != getEmptyMarker())
- *const_cast<void**>(FindBucketFor(Elt)) = const_cast<void*>(Elt);
- }
-
- free(OldBuckets);
- NumTombstones = 0;
}
+
+ if (!WasSmall)
+ free(OldBuckets);
+ NumNonEmpty -= NumTombstones;
+ NumTombstones = 0;
}
SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
- const SmallPtrSetImplBase& that) {
+ const SmallPtrSetImplBase &that) {
SmallArray = SmallStorage;
// If we're becoming small, prepare to insert into our stack space
@@ -178,46 +151,18 @@ SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
CurArray = (const void**)malloc(sizeof(void*) * that.CurArraySize);
assert(CurArray && "Failed to allocate memory?");
}
-
- // Copy over the new array size
- CurArraySize = that.CurArraySize;
- // Copy over the contents from the other set
- memcpy(CurArray, that.CurArray, sizeof(void*)*CurArraySize);
-
- NumElements = that.NumElements;
- NumTombstones = that.NumTombstones;
+ // Copy over the that array.
+ CopyHelper(that);
}
SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
unsigned SmallSize,
SmallPtrSetImplBase &&that) {
SmallArray = SmallStorage;
-
- // Copy over the basic members.
- CurArraySize = that.CurArraySize;
- NumElements = that.NumElements;
- NumTombstones = that.NumTombstones;
-
- // When small, just copy into our small buffer.
- if (that.isSmall()) {
- CurArray = SmallArray;
- memcpy(CurArray, that.CurArray, sizeof(void *) * CurArraySize);
- } else {
- // Otherwise, we steal the large memory allocation and no copy is needed.
- CurArray = that.CurArray;
- that.CurArray = that.SmallArray;
- }
-
- // Make the "that" object small and empty.
- that.CurArraySize = SmallSize;
- assert(that.CurArray == that.SmallArray);
- that.NumElements = 0;
- that.NumTombstones = 0;
+ MoveHelper(SmallSize, std::move(that));
}
-/// CopyFrom - implement operator= from a smallptrset that has the same pointer
-/// type, but may have a different small size.
void SmallPtrSetImplBase::CopyFrom(const SmallPtrSetImplBase &RHS) {
assert(&RHS != this && "Self-copy should be handled by the caller.");
@@ -243,28 +188,36 @@ void SmallPtrSetImplBase::CopyFrom(const SmallPtrSetImplBase &RHS) {
}
assert(CurArray && "Failed to allocate memory?");
}
-
+
+ CopyHelper(RHS);
+}
+
+void SmallPtrSetImplBase::CopyHelper(const SmallPtrSetImplBase &RHS) {
// Copy over the new array size
CurArraySize = RHS.CurArraySize;
// Copy over the contents from the other set
- memcpy(CurArray, RHS.CurArray, sizeof(void*)*CurArraySize);
-
- NumElements = RHS.NumElements;
+ std::copy(RHS.CurArray, RHS.EndPointer(), CurArray);
+
+ NumNonEmpty = RHS.NumNonEmpty;
NumTombstones = RHS.NumTombstones;
}
void SmallPtrSetImplBase::MoveFrom(unsigned SmallSize,
SmallPtrSetImplBase &&RHS) {
- assert(&RHS != this && "Self-move should be handled by the caller.");
-
if (!isSmall())
free(CurArray);
+ MoveHelper(SmallSize, std::move(RHS));
+}
+
+void SmallPtrSetImplBase::MoveHelper(unsigned SmallSize,
+ SmallPtrSetImplBase &&RHS) {
+ assert(&RHS != this && "Self-move should be handled by the caller.");
if (RHS.isSmall()) {
// Copy a small RHS rather than moving.
CurArray = SmallArray;
- memcpy(CurArray, RHS.CurArray, sizeof(void*)*RHS.CurArraySize);
+ std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, CurArray);
} else {
CurArray = RHS.CurArray;
RHS.CurArray = RHS.SmallArray;
@@ -272,13 +225,13 @@ void SmallPtrSetImplBase::MoveFrom(unsigned SmallSize,
// Copy the rest of the trivial members.
CurArraySize = RHS.CurArraySize;
- NumElements = RHS.NumElements;
+ NumNonEmpty = RHS.NumNonEmpty;
NumTombstones = RHS.NumTombstones;
// Make the RHS small and empty.
RHS.CurArraySize = SmallSize;
assert(RHS.CurArray == RHS.SmallArray);
- RHS.NumElements = 0;
+ RHS.NumNonEmpty = 0;
RHS.NumTombstones = 0;
}
@@ -289,7 +242,7 @@ void SmallPtrSetImplBase::swap(SmallPtrSetImplBase &RHS) {
if (!this->isSmall() && !RHS.isSmall()) {
std::swap(this->CurArray, RHS.CurArray);
std::swap(this->CurArraySize, RHS.CurArraySize);
- std::swap(this->NumElements, RHS.NumElements);
+ std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
std::swap(this->NumTombstones, RHS.NumTombstones);
return;
}
@@ -299,40 +252,44 @@ void SmallPtrSetImplBase::swap(SmallPtrSetImplBase &RHS) {
// If only RHS is small, copy the small elements into LHS and move the pointer
// from LHS to RHS.
if (!this->isSmall() && RHS.isSmall()) {
- std::copy(RHS.SmallArray, RHS.SmallArray+RHS.CurArraySize,
- this->SmallArray);
- std::swap(this->NumElements, RHS.NumElements);
- std::swap(this->CurArraySize, RHS.CurArraySize);
+ assert(RHS.CurArray == RHS.SmallArray);
+ std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, this->SmallArray);
+ std::swap(RHS.CurArraySize, this->CurArraySize);
+ std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
+ std::swap(this->NumTombstones, RHS.NumTombstones);
RHS.CurArray = this->CurArray;
- RHS.NumTombstones = this->NumTombstones;
this->CurArray = this->SmallArray;
- this->NumTombstones = 0;
return;
}
// If only LHS is small, copy the small elements into RHS and move the pointer
// from RHS to LHS.
if (this->isSmall() && !RHS.isSmall()) {
- std::copy(this->SmallArray, this->SmallArray+this->CurArraySize,
+ assert(this->CurArray == this->SmallArray);
+ std::copy(this->CurArray, this->CurArray + this->NumNonEmpty,
RHS.SmallArray);
- std::swap(RHS.NumElements, this->NumElements);
std::swap(RHS.CurArraySize, this->CurArraySize);
+ std::swap(RHS.NumNonEmpty, this->NumNonEmpty);
+ std::swap(RHS.NumTombstones, this->NumTombstones);
this->CurArray = RHS.CurArray;
- this->NumTombstones = RHS.NumTombstones;
RHS.CurArray = RHS.SmallArray;
- RHS.NumTombstones = 0;
return;
}
// Both a small, just swap the small elements.
assert(this->isSmall() && RHS.isSmall());
- assert(this->CurArraySize == RHS.CurArraySize);
- std::swap_ranges(this->SmallArray, this->SmallArray+this->CurArraySize,
+ unsigned MinNonEmpty = std::min(this->NumNonEmpty, RHS.NumNonEmpty);
+ std::swap_ranges(this->SmallArray, this->SmallArray + MinNonEmpty,
RHS.SmallArray);
- std::swap(this->NumElements, RHS.NumElements);
-}
-
-SmallPtrSetImplBase::~SmallPtrSetImplBase() {
- if (!isSmall())
- free(CurArray);
+ if (this->NumNonEmpty > MinNonEmpty) {
+ std::copy(this->SmallArray + MinNonEmpty,
+ this->SmallArray + this->NumNonEmpty,
+ RHS.SmallArray + MinNonEmpty);
+ } else {
+ std::copy(RHS.SmallArray + MinNonEmpty, RHS.SmallArray + RHS.NumNonEmpty,
+ this->SmallArray + MinNonEmpty);
+ }
+ assert(this->CurArraySize == RHS.CurArraySize);
+ std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
+ std::swap(this->NumTombstones, RHS.NumTombstones);
}
diff --git a/contrib/llvm/lib/Support/SpecialCaseList.cpp b/contrib/llvm/lib/Support/SpecialCaseList.cpp
index ea417c4..0ffe444 100644
--- a/contrib/llvm/lib/Support/SpecialCaseList.cpp
+++ b/contrib/llvm/lib/Support/SpecialCaseList.cpp
@@ -50,7 +50,7 @@ std::unique_ptr<SpecialCaseList>
SpecialCaseList::create(const std::vector<std::string> &Paths,
std::string &Error) {
std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
- for (auto Path : Paths) {
+ for (const auto &Path : Paths) {
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
MemoryBuffer::getFile(Path);
if (std::error_code EC = FileOrErr.getError()) {
diff --git a/contrib/llvm/lib/Support/Statistic.cpp b/contrib/llvm/lib/Support/Statistic.cpp
index e49d1cb..cdd3679 100644
--- a/contrib/llvm/lib/Support/Statistic.cpp
+++ b/contrib/llvm/lib/Support/Statistic.cpp
@@ -43,6 +43,9 @@ Enabled(
cl::desc("Enable statistics output from program (available with Asserts)"));
+static cl::opt<bool> StatsAsJSON("stats-json",
+ cl::desc("Display statistics as json data"));
+
namespace {
/// StatisticInfo - This class is used in a ManagedStatic so that it is created
/// on demand (when the first statistic is bumped) and destroyed only when
@@ -51,6 +54,10 @@ class StatisticInfo {
std::vector<const Statistic*> Stats;
friend void llvm::PrintStatistics();
friend void llvm::PrintStatistics(raw_ostream &OS);
+ friend void llvm::PrintStatisticsJSON(raw_ostream &OS);
+
+ /// Sort statistics by debugtype,name,description.
+ void sort();
public:
~StatisticInfo();
@@ -95,27 +102,32 @@ bool llvm::AreStatisticsEnabled() {
return Enabled;
}
+void StatisticInfo::sort() {
+ std::stable_sort(Stats.begin(), Stats.end(),
+ [](const Statistic *LHS, const Statistic *RHS) {
+ if (int Cmp = std::strcmp(LHS->getDebugType(), RHS->getDebugType()))
+ return Cmp < 0;
+
+ if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
+ return Cmp < 0;
+
+ return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
+ });
+}
+
void llvm::PrintStatistics(raw_ostream &OS) {
StatisticInfo &Stats = *StatInfo;
// Figure out how long the biggest Value and Name fields are.
- unsigned MaxNameLen = 0, MaxValLen = 0;
+ unsigned MaxDebugTypeLen = 0, MaxValLen = 0;
for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) {
MaxValLen = std::max(MaxValLen,
(unsigned)utostr(Stats.Stats[i]->getValue()).size());
- MaxNameLen = std::max(MaxNameLen,
- (unsigned)std::strlen(Stats.Stats[i]->getName()));
+ MaxDebugTypeLen = std::max(MaxDebugTypeLen,
+ (unsigned)std::strlen(Stats.Stats[i]->getDebugType()));
}
- // Sort the fields by name.
- std::stable_sort(Stats.Stats.begin(), Stats.Stats.end(),
- [](const Statistic *LHS, const Statistic *RHS) {
- if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
- return Cmp < 0;
-
- // Secondary key is the description.
- return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
- });
+ Stats.sort();
// Print out the statistics header...
OS << "===" << std::string(73, '-') << "===\n"
@@ -126,12 +138,43 @@ void llvm::PrintStatistics(raw_ostream &OS) {
for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i)
OS << format("%*u %-*s - %s\n",
MaxValLen, Stats.Stats[i]->getValue(),
- MaxNameLen, Stats.Stats[i]->getName(),
+ MaxDebugTypeLen, Stats.Stats[i]->getDebugType(),
Stats.Stats[i]->getDesc());
OS << '\n'; // Flush the output stream.
OS.flush();
+}
+
+static void write_json_string_escaped(raw_ostream &OS, const char *string) {
+ // Out current usage should not need any escaping. Keep it simple and just
+ // check that the input is pure ASCII without special characers.
+#ifndef NDEBUG
+ for (const unsigned char *c = (const unsigned char*)string; *c != '\0'; ++c) {
+ assert(*c != '\\' && *c != '\"' && *c >= 0x20 && *c < 0x80);
+ }
+#endif
+ OS << string;
+}
+
+void llvm::PrintStatisticsJSON(raw_ostream &OS) {
+ StatisticInfo &Stats = *StatInfo;
+
+ Stats.sort();
+ // Print all of the statistics.
+ OS << "{\n";
+ const char *delim = "";
+ for (const Statistic *Stat : Stats.Stats) {
+ OS << delim;
+ OS << "\t\"";
+ write_json_string_escaped(OS, Stat->getDebugType());
+ OS << '.';
+ write_json_string_escaped(OS, Stat->getName());
+ OS << "\": " << Stat->getValue();
+ delim = ",\n";
+ }
+ OS << "\n}\n";
+ OS.flush();
}
void llvm::PrintStatistics() {
@@ -143,7 +186,10 @@ void llvm::PrintStatistics() {
// Get the stream to write to.
std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
- PrintStatistics(*OutStream);
+ if (StatsAsJSON)
+ PrintStatisticsJSON(*OutStream);
+ else
+ PrintStatistics(*OutStream);
#else
// Check if the -stats option is set instead of checking
diff --git a/contrib/llvm/lib/Support/StreamingMemoryObject.cpp b/contrib/llvm/lib/Support/StreamingMemoryObject.cpp
index 5a44e62..fb56617 100644
--- a/contrib/llvm/lib/Support/StreamingMemoryObject.cpp
+++ b/contrib/llvm/lib/Support/StreamingMemoryObject.cpp
@@ -104,6 +104,12 @@ uint64_t StreamingMemoryObject::readBytes(uint8_t *Buf, uint64_t Size,
return Size;
}
+const uint8_t *StreamingMemoryObject::getPointer(uint64_t Address,
+ uint64_t Size) const {
+ fetchToPos(Address + Size - 1);
+ return &Bytes[Address + BytesSkipped];
+}
+
bool StreamingMemoryObject::dropLeadingBytes(size_t s) {
if (BytesRead < s) return true;
BytesSkipped = s;
diff --git a/contrib/llvm/lib/Support/StringMap.cpp b/contrib/llvm/lib/Support/StringMap.cpp
index 7be9466..7da9ccb 100644
--- a/contrib/llvm/lib/Support/StringMap.cpp
+++ b/contrib/llvm/lib/Support/StringMap.cpp
@@ -17,12 +17,26 @@
#include <cassert>
using namespace llvm;
+/// Returns the number of buckets to allocate to ensure that the DenseMap can
+/// accommodate \p NumEntries without need to grow().
+static unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
+ // Ensure that "NumEntries * 4 < NumBuckets * 3"
+ if (NumEntries == 0)
+ return 0;
+ // +1 is required because of the strict equality.
+ // For example if NumEntries is 48, we need to return 401.
+ return NextPowerOf2(NumEntries * 4 / 3 + 1);
+}
+
StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) {
ItemSize = itemSize;
// If a size is specified, initialize the table with that many buckets.
if (InitSize) {
- init(InitSize);
+ // The table will grow when the number of entries reach 3/4 of the number of
+ // buckets. To guarantee that "InitSize" number of entries can be inserted
+ // in the table without growing, we allocate just what is needed here.
+ init(getMinBucketToReserveForEntries(InitSize));
return;
}
diff --git a/contrib/llvm/lib/Support/StringRef.cpp b/contrib/llvm/lib/Support/StringRef.cpp
index 7ecff29..8a9da5e 100644
--- a/contrib/llvm/lib/Support/StringRef.cpp
+++ b/contrib/llvm/lib/Support/StringRef.cpp
@@ -351,12 +351,12 @@ size_t StringRef::count(StringRef Str) const {
}
static unsigned GetAutoSenseRadix(StringRef &Str) {
- if (Str.startswith("0x")) {
+ if (Str.startswith("0x") || Str.startswith("0X")) {
Str = Str.substr(2);
return 16;
}
- if (Str.startswith("0b")) {
+ if (Str.startswith("0b") || Str.startswith("0B")) {
Str = Str.substr(2);
return 2;
}
diff --git a/contrib/llvm/lib/Support/TargetParser.cpp b/contrib/llvm/lib/Support/TargetParser.cpp
index 337532e..c3f8613 100644
--- a/contrib/llvm/lib/Support/TargetParser.cpp
+++ b/contrib/llvm/lib/Support/TargetParser.cpp
@@ -21,6 +21,7 @@
using namespace llvm;
using namespace ARM;
+using namespace AArch64;
namespace {
@@ -75,6 +76,11 @@ static const struct {
{NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \
sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR},
#include "llvm/Support/ARMTargetParser.def"
+},AArch64ARCHNames[] = {
+#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \
+ {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \
+ sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR},
+#include "llvm/Support/AArch64TargetParser.def"
};
// List of Arch Extension names.
@@ -91,6 +97,10 @@ static const struct {
#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
{ NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
#include "llvm/Support/ARMTargetParser.def"
+},AArch64ARCHExtNames[] = {
+#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
+ { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
+#include "llvm/Support/AArch64TargetParser.def"
};
// List of HWDiv names (use getHWDivSynonym) and which architectural
@@ -124,6 +134,10 @@ static const struct {
#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
{ NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
#include "llvm/Support/ARMTargetParser.def"
+},AArch64CPUNames[] = {
+#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
+ { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
+#include "llvm/Support/AArch64TargetParser.def"
};
} // namespace
@@ -305,13 +319,13 @@ StringRef llvm::ARM::getArchName(unsigned ArchKind) {
}
StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) {
- if (ArchKind >= ARM::AK_LAST)
+ if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
return StringRef();
return ARCHNames[ArchKind].getCPUAttr();
}
StringRef llvm::ARM::getSubArch(unsigned ArchKind) {
- if (ArchKind >= ARM::AK_LAST)
+ if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
return StringRef();
return ARCHNames[ArchKind].getSubArch();
}
@@ -369,6 +383,156 @@ StringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
return "generic";
}
+StringRef llvm::AArch64::getFPUName(unsigned FPUKind) {
+ return ARM::getFPUName(FPUKind);
+}
+
+unsigned llvm::AArch64::getFPUVersion(unsigned FPUKind) {
+ return ARM::getFPUVersion(FPUKind);
+}
+
+unsigned llvm::AArch64::getFPUNeonSupportLevel(unsigned FPUKind) {
+ return ARM::getFPUNeonSupportLevel( FPUKind);
+}
+
+unsigned llvm::AArch64::getFPURestriction(unsigned FPUKind) {
+ return ARM::getFPURestriction(FPUKind);
+}
+
+unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
+ if (CPU == "generic")
+ return AArch64ARCHNames[ArchKind].DefaultFPU;
+
+ return StringSwitch<unsigned>(CPU)
+#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
+ .Case(NAME, DEFAULT_FPU)
+#include "llvm/Support/AArch64TargetParser.def"
+ .Default(ARM::FK_INVALID);
+}
+
+unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
+ if (CPU == "generic")
+ return AArch64ARCHNames[ArchKind].ArchBaseExtensions;
+
+ return StringSwitch<unsigned>(CPU)
+#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
+ .Case(NAME, AArch64ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT)
+#include "llvm/Support/AArch64TargetParser.def"
+ .Default(AArch64::AEK_INVALID);
+}
+
+bool llvm::AArch64::getExtensionFeatures(unsigned Extensions,
+ std::vector<const char *> &Features) {
+
+ if (Extensions == AArch64::AEK_INVALID)
+ return false;
+
+ if (Extensions & AArch64::AEK_FP)
+ Features.push_back("+fp-armv8");
+ if (Extensions & AArch64::AEK_SIMD)
+ Features.push_back("+neon");
+ if (Extensions & AArch64::AEK_CRC)
+ Features.push_back("+crc");
+ if (Extensions & AArch64::AEK_CRYPTO)
+ Features.push_back("+crypto");
+ if (Extensions & AArch64::AEK_FP16)
+ Features.push_back("+fullfp16");
+ if (Extensions & AArch64::AEK_PROFILE)
+ Features.push_back("+spe");
+ if (Extensions & AArch64::AEK_RAS)
+ Features.push_back("+ras");
+
+ return true;
+}
+
+bool llvm::AArch64::getFPUFeatures(unsigned FPUKind,
+ std::vector<const char *> &Features) {
+ return ARM::getFPUFeatures(FPUKind, Features);
+}
+
+bool llvm::AArch64::getArchFeatures(unsigned ArchKind,
+ std::vector<const char *> &Features) {
+ if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
+ return false;
+
+ if (ArchKind == ARM::AK_ARMV8_1A)
+ Features.push_back("+v8.1a");
+ if (ArchKind == ARM::AK_ARMV8_2A)
+ Features.push_back("+v8.2a");
+
+ return true;
+}
+
+StringRef llvm::AArch64::getArchName(unsigned ArchKind) {
+ for (const auto &AI : AArch64ARCHNames)
+ if (AI.ID == ArchKind)
+ return AI.getName();
+ return StringRef();
+}
+
+StringRef llvm::AArch64::getCPUAttr(unsigned ArchKind) {
+ for (const auto &AI : AArch64ARCHNames)
+ if (AI.ID == ArchKind)
+ return AI.getCPUAttr();
+ return StringRef();
+}
+
+StringRef llvm::AArch64::getSubArch(unsigned ArchKind) {
+ for (const auto &AI : AArch64ARCHNames)
+ if (AI.ID == ArchKind)
+ return AI.getSubArch();
+ return StringRef();
+}
+
+unsigned llvm::AArch64::getArchAttr(unsigned ArchKind) {
+ for (const auto &AI : AArch64ARCHNames)
+ if (AI.ID == ArchKind)
+ return AI.ArchAttr;
+ return ARMBuildAttrs::CPUArch::v8_A;
+}
+
+StringRef llvm::AArch64::getArchExtName(unsigned AArchExtKind) {
+ for (const auto &AE : AArch64ARCHExtNames)
+ if (AArchExtKind == AE.ID)
+ return AE.getName();
+ return StringRef();
+}
+
+const char *llvm::AArch64::getArchExtFeature(StringRef ArchExt) {
+ if (ArchExt.startswith("no")) {
+ StringRef ArchExtBase(ArchExt.substr(2));
+ for (const auto &AE : AArch64ARCHExtNames) {
+ if (AE.NegFeature && ArchExtBase == AE.getName())
+ return AE.NegFeature;
+ }
+ }
+
+ for (const auto &AE : AArch64ARCHExtNames)
+ if (AE.Feature && ArchExt == AE.getName())
+ return AE.Feature;
+ return nullptr;
+}
+
+StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) {
+ unsigned AK = parseArch(Arch);
+ if (AK == ARM::AK_INVALID)
+ return StringRef();
+
+ // Look for multiple AKs to find the default for pair AK+Name.
+ for (const auto &CPU : AArch64CPUNames)
+ if (CPU.ArchID == AK && CPU.Default)
+ return CPU.getName();
+
+ // If we can't find a default then target the architecture instead
+ return "generic";
+}
+
+unsigned llvm::AArch64::checkArchVersion(StringRef Arch) {
+ if (Arch[0] == 'v' && std::isdigit(Arch[1]))
+ return (Arch[1] - 48);
+ return 0;
+}
+
// ======================================================= //
// Parsers
// ======================================================= //
@@ -411,6 +575,8 @@ static StringRef getArchSynonym(StringRef Arch) {
.Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
.Case("v8.1a", "v8.1-a")
.Case("v8.2a", "v8.2-a")
+ .Case("v8m.base", "v8-m.base")
+ .Case("v8m.main", "v8-m.main")
.Default(Arch);
}
@@ -548,6 +714,8 @@ unsigned llvm::ARM::parseArchProfile(StringRef Arch) {
case ARM::AK_ARMV6M:
case ARM::AK_ARMV7M:
case ARM::AK_ARMV7EM:
+ case ARM::AK_ARMV8MMainline:
+ case ARM::AK_ARMV8MBaseline:
return ARM::PK_M;
case ARM::AK_ARMV7R:
return ARM::PK_R;
@@ -597,7 +765,67 @@ unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
case ARM::AK_ARMV8A:
case ARM::AK_ARMV8_1A:
case ARM::AK_ARMV8_2A:
+ case ARM::AK_ARMV8MBaseline:
+ case ARM::AK_ARMV8MMainline:
return 8;
}
return 0;
}
+
+StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) {
+ return ARM::getCanonicalArchName(Arch);
+}
+
+unsigned llvm::AArch64::parseFPU(StringRef FPU) {
+ return ARM::parseFPU(FPU);
+}
+
+// Allows partial match, ex. "v8a" matches "armv8a".
+unsigned llvm::AArch64::parseArch(StringRef Arch) {
+ Arch = getCanonicalArchName(Arch);
+ if (checkArchVersion(Arch) < 8)
+ return ARM::AK_INVALID;
+
+ StringRef Syn = getArchSynonym(Arch);
+ for (const auto A : AArch64ARCHNames) {
+ if (A.getName().endswith(Syn))
+ return A.ID;
+ }
+ return ARM::AK_INVALID;
+}
+
+unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) {
+ for (const auto A : AArch64ARCHExtNames) {
+ if (ArchExt == A.getName())
+ return A.ID;
+ }
+ return AArch64::AEK_INVALID;
+}
+
+unsigned llvm::AArch64::parseCPUArch(StringRef CPU) {
+ for (const auto C : AArch64CPUNames) {
+ if (CPU == C.getName())
+ return C.ArchID;
+ }
+ return ARM::AK_INVALID;
+}
+
+// ARM, Thumb, AArch64
+unsigned llvm::AArch64::parseArchISA(StringRef Arch) {
+ return ARM::parseArchISA(Arch);
+}
+
+// Little/Big endian
+unsigned llvm::AArch64::parseArchEndian(StringRef Arch) {
+ return ARM::parseArchEndian(Arch);
+}
+
+// Profile A/R/M
+unsigned llvm::AArch64::parseArchProfile(StringRef Arch) {
+ return ARM::parseArchProfile(Arch);
+}
+
+// Version number (ex. v8 = 8).
+unsigned llvm::AArch64::parseArchVersion(StringRef Arch) {
+ return ARM::parseArchVersion(Arch);
+}
diff --git a/contrib/llvm/lib/Support/TargetRegistry.cpp b/contrib/llvm/lib/Support/TargetRegistry.cpp
index eefef8a..02a6d33 100644
--- a/contrib/llvm/lib/Support/TargetRegistry.cpp
+++ b/contrib/llvm/lib/Support/TargetRegistry.cpp
@@ -73,8 +73,7 @@ const Target *TargetRegistry::lookupTarget(const std::string &TT,
auto I = std::find_if(targets().begin(), targets().end(), ArchMatch);
if (I == targets().end()) {
- Error = "No available targets are compatible with this triple, "
- "see -version for the available targets.";
+ Error = "No available targets are compatible with this triple.";
return nullptr;
}
diff --git a/contrib/llvm/lib/Support/ThreadPool.cpp b/contrib/llvm/lib/Support/ThreadPool.cpp
index d4dcb2e..db03a4d 100644
--- a/contrib/llvm/lib/Support/ThreadPool.cpp
+++ b/contrib/llvm/lib/Support/ThreadPool.cpp
@@ -75,8 +75,11 @@ ThreadPool::ThreadPool(unsigned ThreadCount)
void ThreadPool::wait() {
// Wait for all threads to complete and the queue to be empty
std::unique_lock<std::mutex> LockGuard(CompletionLock);
+ // The order of the checks for ActiveThreads and Tasks.empty() matters because
+ // any active threads might be modifying the Tasks queue, and this would be a
+ // race.
CompletionCondition.wait(LockGuard,
- [&] { return Tasks.empty() && !ActiveThreads; });
+ [&] { return !ActiveThreads && Tasks.empty(); });
}
std::shared_future<ThreadPool::VoidTy> ThreadPool::asyncImpl(TaskTy Task) {
diff --git a/contrib/llvm/lib/Support/Threading.cpp b/contrib/llvm/lib/Support/Threading.cpp
index ca7f3f6..e8f5622 100644
--- a/contrib/llvm/lib/Support/Threading.cpp
+++ b/contrib/llvm/lib/Support/Threading.cpp
@@ -16,6 +16,7 @@
#include "llvm/Config/config.h"
#include "llvm/Support/Atomic.h"
#include "llvm/Support/Mutex.h"
+#include "llvm/Support/thread.h"
#include <cassert>
using namespace llvm;
@@ -71,6 +72,11 @@ void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
#include "Windows/WindowsSupport.h"
#include <process.h>
+// Windows will at times define MemoryFence.
+#ifdef MemoryFence
+#undef MemoryFence
+#endif
+
struct ThreadInfo {
void (*func)(void*);
void *param;
diff --git a/contrib/llvm/lib/Support/Timer.cpp b/contrib/llvm/lib/Support/Timer.cpp
index 414f559..49bd39e 100644
--- a/contrib/llvm/lib/Support/Timer.cpp
+++ b/contrib/llvm/lib/Support/Timer.cpp
@@ -79,7 +79,7 @@ static TimerGroup *getDefaultTimerGroup() {
TimerGroup *tmp = DefaultTimerGroup;
sys::MemoryFence();
if (tmp) return tmp;
-
+
sys::SmartScopedLock<true> Lock(*TimerLock);
tmp = DefaultTimerGroup;
if (!tmp) {
@@ -120,7 +120,7 @@ static inline size_t getMemUsage() {
TimeRecord TimeRecord::getCurrentTime(bool Start) {
TimeRecord Result;
sys::TimeValue now(0,0), user(0,0), sys(0,0);
-
+
if (Start) {
Result.MemUsed = getMemUsage();
sys::Process::GetTimeUsage(now, user, sys);
@@ -168,9 +168,9 @@ void TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const {
if (Total.getProcessTime())
printVal(getProcessTime(), Total.getProcessTime(), OS);
printVal(getWallTime(), Total.getWallTime(), OS);
-
+
OS << " ";
-
+
if (Total.getMemUsed())
OS << format("%9" PRId64 " ", (int64_t)getMemUsed());
}
@@ -192,15 +192,15 @@ public:
I = Map.begin(), E = Map.end(); I != E; ++I)
delete I->second.first;
}
-
+
Timer &get(StringRef Name, StringRef GroupName) {
sys::SmartScopedLock<true> L(*TimerLock);
-
+
std::pair<TimerGroup*, Name2TimerMap> &GroupEntry = Map[GroupName];
-
+
if (!GroupEntry.first)
GroupEntry.first = new TimerGroup(GroupName);
-
+
Timer &T = GroupEntry.second[Name];
if (!T.isInitialized())
T.init(Name, *GroupEntry.first);
@@ -215,7 +215,7 @@ static ManagedStatic<Name2PairMap> NamedGroupedTimers;
static Timer &getNamedRegionTimer(StringRef Name) {
sys::SmartScopedLock<true> L(*TimerLock);
-
+
Timer &T = (*NamedTimers)[Name];
if (!T.isInitialized())
T.init(Name);
@@ -240,7 +240,7 @@ static TimerGroup *TimerGroupList = nullptr;
TimerGroup::TimerGroup(StringRef name)
: Name(name.begin(), name.end()), FirstTimer(nullptr) {
-
+
// Add the group to TimerGroupList.
sys::SmartScopedLock<true> L(*TimerLock);
if (TimerGroupList)
@@ -255,7 +255,7 @@ TimerGroup::~TimerGroup() {
// print the timing data.
while (FirstTimer)
removeTimer(*FirstTimer);
-
+
// Remove the group from the TimerGroupList.
sys::SmartScopedLock<true> L(*TimerLock);
*Prev = Next;
@@ -266,18 +266,18 @@ TimerGroup::~TimerGroup() {
void TimerGroup::removeTimer(Timer &T) {
sys::SmartScopedLock<true> L(*TimerLock);
-
+
// If the timer was started, move its data to TimersToPrint.
if (T.hasTriggered())
TimersToPrint.emplace_back(T.Time, T.Name);
T.TG = nullptr;
-
+
// Unlink the timer from our list.
*T.Prev = T.Next;
if (T.Next)
T.Next->Prev = T.Prev;
-
+
// Print the report when all timers in this group are destroyed if some of
// them were started.
if (FirstTimer || TimersToPrint.empty())
@@ -289,7 +289,7 @@ void TimerGroup::removeTimer(Timer &T) {
void TimerGroup::addTimer(Timer &T) {
sys::SmartScopedLock<true> L(*TimerLock);
-
+
// Add the timer to our list.
if (FirstTimer)
FirstTimer->Prev = &T.Next;
@@ -301,11 +301,11 @@ void TimerGroup::addTimer(Timer &T) {
void TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
// Sort the timers in descending order by amount of time taken.
std::sort(TimersToPrint.begin(), TimersToPrint.end());
-
+
TimeRecord Total;
for (auto &RecordNamePair : TimersToPrint)
Total += RecordNamePair.first;
-
+
// Print out timing header.
OS << "===" << std::string(73, '-') << "===\n";
// Figure out how many spaces to indent TimerGroup name.
@@ -313,7 +313,7 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
if (Padding > 80) Padding = 0; // Don't allow "negative" numbers
OS.indent(Padding) << Name << '\n';
OS << "===" << std::string(73, '-') << "===\n";
-
+
// If this is not an collection of ungrouped times, print the total time.
// Ungrouped timers don't really make sense to add up. We still print the
// TOTAL line to make the percentages make sense.
@@ -321,7 +321,7 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
OS << format(" Total Execution Time: %5.4f seconds (%5.4f wall clock)\n",
Total.getProcessTime(), Total.getWallTime());
OS << '\n';
-
+
if (Total.getUserTime())
OS << " ---User Time---";
if (Total.getSystemTime())
@@ -332,18 +332,18 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
if (Total.getMemUsed())
OS << " ---Mem---";
OS << " --- Name ---\n";
-
+
// Loop through all of the timing data, printing it out.
for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) {
const std::pair<TimeRecord, std::string> &Entry = TimersToPrint[e-i-1];
Entry.first.print(Total, OS);
OS << Entry.second << '\n';
}
-
+
Total.print(Total, OS);
OS << "Total\n\n";
OS.flush();
-
+
TimersToPrint.clear();
}
diff --git a/contrib/llvm/lib/Support/Triple.cpp b/contrib/llvm/lib/Support/Triple.cpp
index 11afcf7..2bac2a3 100644
--- a/contrib/llvm/lib/Support/Triple.cpp
+++ b/contrib/llvm/lib/Support/Triple.cpp
@@ -19,50 +19,53 @@ using namespace llvm;
const char *Triple::getArchTypeName(ArchType Kind) {
switch (Kind) {
- case UnknownArch: return "unknown";
-
- case aarch64: return "aarch64";
- case aarch64_be: return "aarch64_be";
- case arm: return "arm";
- case armeb: return "armeb";
- case avr: return "avr";
- case bpfel: return "bpfel";
- case bpfeb: return "bpfeb";
- case hexagon: return "hexagon";
- case mips: return "mips";
- case mipsel: return "mipsel";
- case mips64: return "mips64";
- case mips64el: return "mips64el";
- case msp430: return "msp430";
- case ppc64: return "powerpc64";
- case ppc64le: return "powerpc64le";
- case ppc: return "powerpc";
- case r600: return "r600";
- case amdgcn: return "amdgcn";
- case sparc: return "sparc";
- case sparcv9: return "sparcv9";
- case sparcel: return "sparcel";
- case systemz: return "s390x";
- case tce: return "tce";
- case thumb: return "thumb";
- case thumbeb: return "thumbeb";
- case x86: return "i386";
- case x86_64: return "x86_64";
- case xcore: return "xcore";
- case nvptx: return "nvptx";
- case nvptx64: return "nvptx64";
- case le32: return "le32";
- case le64: return "le64";
- case amdil: return "amdil";
- case amdil64: return "amdil64";
- case hsail: return "hsail";
- case hsail64: return "hsail64";
- case spir: return "spir";
- case spir64: return "spir64";
- case kalimba: return "kalimba";
- case shave: return "shave";
- case wasm32: return "wasm32";
- case wasm64: return "wasm64";
+ case UnknownArch: return "unknown";
+
+ case aarch64: return "aarch64";
+ case aarch64_be: return "aarch64_be";
+ case arm: return "arm";
+ case armeb: return "armeb";
+ case avr: return "avr";
+ case bpfel: return "bpfel";
+ case bpfeb: return "bpfeb";
+ case hexagon: return "hexagon";
+ case mips: return "mips";
+ case mipsel: return "mipsel";
+ case mips64: return "mips64";
+ case mips64el: return "mips64el";
+ case msp430: return "msp430";
+ case ppc64: return "powerpc64";
+ case ppc64le: return "powerpc64le";
+ case ppc: return "powerpc";
+ case r600: return "r600";
+ case amdgcn: return "amdgcn";
+ case sparc: return "sparc";
+ case sparcv9: return "sparcv9";
+ case sparcel: return "sparcel";
+ case systemz: return "s390x";
+ case tce: return "tce";
+ case thumb: return "thumb";
+ case thumbeb: return "thumbeb";
+ case x86: return "i386";
+ case x86_64: return "x86_64";
+ case xcore: return "xcore";
+ case nvptx: return "nvptx";
+ case nvptx64: return "nvptx64";
+ case le32: return "le32";
+ case le64: return "le64";
+ case amdil: return "amdil";
+ case amdil64: return "amdil64";
+ case hsail: return "hsail";
+ case hsail64: return "hsail64";
+ case spir: return "spir";
+ case spir64: return "spir64";
+ case kalimba: return "kalimba";
+ case lanai: return "lanai";
+ case shave: return "shave";
+ case wasm32: return "wasm32";
+ case wasm64: return "wasm64";
+ case renderscript32: return "renderscript32";
+ case renderscript64: return "renderscript64";
}
llvm_unreachable("Invalid ArchType!");
@@ -94,8 +97,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {
case hexagon: return "hexagon";
- case amdgcn:
- case r600: return "amdgpu";
+ case amdgcn: return "amdgcn";
+ case r600: return "r600";
case bpfel:
case bpfeb: return "bpf";
@@ -111,8 +114,9 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {
case xcore: return "xcore";
- case nvptx: return "nvptx";
- case nvptx64: return "nvptx";
+ // NVPTX intrinsics are namespaced under nvvm.
+ case nvptx: return "nvvm";
+ case nvptx64: return "nvvm";
case le32: return "le32";
case le64: return "le64";
@@ -126,6 +130,7 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {
case spir:
case spir64: return "spir";
case kalimba: return "kalimba";
+ case lanai: return "lanai";
case shave: return "shave";
case wasm32:
case wasm64: return "wasm";
@@ -148,6 +153,8 @@ const char *Triple::getVendorTypeName(VendorType Kind) {
case NVIDIA: return "nvidia";
case CSR: return "csr";
case Myriad: return "myriad";
+ case AMD: return "amd";
+ case Mesa: return "mesa";
}
llvm_unreachable("Invalid VendorType!");
@@ -184,6 +191,7 @@ const char *Triple::getOSTypeName(OSType Kind) {
case ELFIAMCU: return "elfiamcu";
case TvOS: return "tvos";
case WatchOS: return "watchos";
+ case Mesa3D: return "mesa3d";
}
llvm_unreachable("Invalid OSType");
@@ -193,6 +201,7 @@ const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) {
switch (Kind) {
case UnknownEnvironment: return "unknown";
case GNU: return "gnu";
+ case GNUABI64: return "gnuabi64";
case GNUEABIHF: return "gnueabihf";
case GNUEABI: return "gnueabi";
case GNUX32: return "gnux32";
@@ -200,6 +209,9 @@ const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) {
case EABI: return "eabi";
case EABIHF: return "eabihf";
case Android: return "android";
+ case Musl: return "musl";
+ case MuslEABI: return "musleabi";
+ case MuslEABIHF: return "musleabihf";
case MSVC: return "msvc";
case Itanium: return "itanium";
case Cygnus: return "cygnus";
@@ -268,9 +280,12 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("spir", spir)
.Case("spir64", spir64)
.Case("kalimba", kalimba)
+ .Case("lanai", lanai)
.Case("shave", shave)
.Case("wasm32", wasm32)
.Case("wasm64", wasm64)
+ .Case("renderscript32", renderscript32)
+ .Case("renderscript64", renderscript64)
.Default(UnknownArch);
}
@@ -376,9 +391,12 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("spir", Triple::spir)
.Case("spir64", Triple::spir64)
.StartsWith("kalimba", Triple::kalimba)
+ .Case("lanai", Triple::lanai)
.Case("shave", Triple::shave)
.Case("wasm32", Triple::wasm32)
.Case("wasm64", Triple::wasm64)
+ .Case("renderscript32", Triple::renderscript32)
+ .Case("renderscript64", Triple::renderscript64)
.Default(Triple::UnknownArch);
// Some architectures require special parsing logic just to compute the
@@ -408,6 +426,8 @@ static Triple::VendorType parseVendor(StringRef VendorName) {
.Case("nvidia", Triple::NVIDIA)
.Case("csr", Triple::CSR)
.Case("myriad", Triple::Myriad)
+ .Case("amd", Triple::AMD)
+ .Case("mesa", Triple::Mesa)
.Default(Triple::UnknownVendor);
}
@@ -441,6 +461,7 @@ static Triple::OSType parseOS(StringRef OSName) {
.StartsWith("elfiamcu", Triple::ELFIAMCU)
.StartsWith("tvos", Triple::TvOS)
.StartsWith("watchos", Triple::WatchOS)
+ .StartsWith("mesa3d", Triple::Mesa3D)
.Default(Triple::UnknownOS);
}
@@ -448,12 +469,16 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) {
return StringSwitch<Triple::EnvironmentType>(EnvironmentName)
.StartsWith("eabihf", Triple::EABIHF)
.StartsWith("eabi", Triple::EABI)
+ .StartsWith("gnuabi64", Triple::GNUABI64)
.StartsWith("gnueabihf", Triple::GNUEABIHF)
.StartsWith("gnueabi", Triple::GNUEABI)
.StartsWith("gnux32", Triple::GNUX32)
.StartsWith("code16", Triple::CODE16)
.StartsWith("gnu", Triple::GNU)
.StartsWith("android", Triple::Android)
+ .StartsWith("musleabihf", Triple::MuslEABIHF)
+ .StartsWith("musleabi", Triple::MuslEABI)
+ .StartsWith("musl", Triple::Musl)
.StartsWith("msvc", Triple::MSVC)
.StartsWith("itanium", Triple::Itanium)
.StartsWith("cygnus", Triple::Cygnus)
@@ -521,6 +546,10 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) {
return Triple::ARMSubArch_v8_1a;
case ARM::AK_ARMV8_2A:
return Triple::ARMSubArch_v8_2a;
+ case ARM::AK_ARMV8MBaseline:
+ return Triple::ARMSubArch_v8m_baseline;
+ case ARM::AK_ARMV8MMainline:
+ return Triple::ARMSubArch_v8m_mainline;
default:
return Triple::NoSubArch;
}
@@ -559,6 +588,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
case Triple::bpfeb:
case Triple::bpfel:
case Triple::hexagon:
+ case Triple::lanai:
case Triple::hsail:
case Triple::hsail64:
case Triple::kalimba:
@@ -573,6 +603,8 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
case Triple::nvptx64:
case Triple::ppc64le:
case Triple::r600:
+ case Triple::renderscript32:
+ case Triple::renderscript64:
case Triple::shave:
case Triple::sparc:
case Triple::sparcel:
@@ -1111,8 +1143,10 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::hsail:
case llvm::Triple::spir:
case llvm::Triple::kalimba:
+ case llvm::Triple::lanai:
case llvm::Triple::shave:
case llvm::Triple::wasm32:
+ case llvm::Triple::renderscript32:
return 32;
case llvm::Triple::aarch64:
@@ -1133,6 +1167,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::hsail64:
case llvm::Triple::spir64:
case llvm::Triple::wasm64:
+ case llvm::Triple::renderscript64:
return 64;
}
llvm_unreachable("Invalid architecture value");
@@ -1184,24 +1219,27 @@ Triple Triple::get32BitArchVariant() const {
case Triple::thumbeb:
case Triple::x86:
case Triple::xcore:
+ case Triple::lanai:
case Triple::shave:
case Triple::wasm32:
+ case Triple::renderscript32:
// Already 32-bit.
break;
- case Triple::aarch64: T.setArch(Triple::arm); break;
- case Triple::aarch64_be: T.setArch(Triple::armeb); break;
- case Triple::le64: T.setArch(Triple::le32); break;
- case Triple::mips64: T.setArch(Triple::mips); break;
- case Triple::mips64el: T.setArch(Triple::mipsel); break;
- case Triple::nvptx64: T.setArch(Triple::nvptx); break;
- case Triple::ppc64: T.setArch(Triple::ppc); break;
- case Triple::sparcv9: T.setArch(Triple::sparc); break;
- case Triple::x86_64: T.setArch(Triple::x86); break;
- case Triple::amdil64: T.setArch(Triple::amdil); break;
- case Triple::hsail64: T.setArch(Triple::hsail); break;
- case Triple::spir64: T.setArch(Triple::spir); break;
- case Triple::wasm64: T.setArch(Triple::wasm32); break;
+ case Triple::aarch64: T.setArch(Triple::arm); break;
+ case Triple::aarch64_be: T.setArch(Triple::armeb); break;
+ case Triple::le64: T.setArch(Triple::le32); break;
+ case Triple::mips64: T.setArch(Triple::mips); break;
+ case Triple::mips64el: T.setArch(Triple::mipsel); break;
+ case Triple::nvptx64: T.setArch(Triple::nvptx); break;
+ case Triple::ppc64: T.setArch(Triple::ppc); break;
+ case Triple::sparcv9: T.setArch(Triple::sparc); break;
+ case Triple::x86_64: T.setArch(Triple::x86); break;
+ case Triple::amdil64: T.setArch(Triple::amdil); break;
+ case Triple::hsail64: T.setArch(Triple::hsail); break;
+ case Triple::spir64: T.setArch(Triple::spir); break;
+ case Triple::wasm64: T.setArch(Triple::wasm32); break;
+ case Triple::renderscript64: T.setArch(Triple::renderscript32); break;
}
return T;
}
@@ -1213,6 +1251,7 @@ Triple Triple::get64BitArchVariant() const {
case Triple::avr:
case Triple::hexagon:
case Triple::kalimba:
+ case Triple::lanai:
case Triple::msp430:
case Triple::r600:
case Triple::tce:
@@ -1240,30 +1279,35 @@ Triple Triple::get64BitArchVariant() const {
case Triple::systemz:
case Triple::x86_64:
case Triple::wasm64:
+ case Triple::renderscript64:
// Already 64-bit.
break;
- case Triple::arm: T.setArch(Triple::aarch64); break;
- case Triple::armeb: T.setArch(Triple::aarch64_be); break;
- case Triple::le32: T.setArch(Triple::le64); break;
- case Triple::mips: T.setArch(Triple::mips64); break;
- case Triple::mipsel: T.setArch(Triple::mips64el); break;
- case Triple::nvptx: T.setArch(Triple::nvptx64); break;
- case Triple::ppc: T.setArch(Triple::ppc64); break;
- case Triple::sparc: T.setArch(Triple::sparcv9); break;
- case Triple::x86: T.setArch(Triple::x86_64); break;
- case Triple::amdil: T.setArch(Triple::amdil64); break;
- case Triple::hsail: T.setArch(Triple::hsail64); break;
- case Triple::spir: T.setArch(Triple::spir64); break;
- case Triple::thumb: T.setArch(Triple::aarch64); break;
- case Triple::thumbeb: T.setArch(Triple::aarch64_be); break;
- case Triple::wasm32: T.setArch(Triple::wasm64); break;
+ case Triple::arm: T.setArch(Triple::aarch64); break;
+ case Triple::armeb: T.setArch(Triple::aarch64_be); break;
+ case Triple::le32: T.setArch(Triple::le64); break;
+ case Triple::mips: T.setArch(Triple::mips64); break;
+ case Triple::mipsel: T.setArch(Triple::mips64el); break;
+ case Triple::nvptx: T.setArch(Triple::nvptx64); break;
+ case Triple::ppc: T.setArch(Triple::ppc64); break;
+ case Triple::sparc: T.setArch(Triple::sparcv9); break;
+ case Triple::x86: T.setArch(Triple::x86_64); break;
+ case Triple::amdil: T.setArch(Triple::amdil64); break;
+ case Triple::hsail: T.setArch(Triple::hsail64); break;
+ case Triple::spir: T.setArch(Triple::spir64); break;
+ case Triple::thumb: T.setArch(Triple::aarch64); break;
+ case Triple::thumbeb: T.setArch(Triple::aarch64_be); break;
+ case Triple::wasm32: T.setArch(Triple::wasm64); break;
+ case Triple::renderscript32: T.setArch(Triple::renderscript64); break;
}
return T;
}
Triple Triple::getBigEndianArchVariant() const {
Triple T(*this);
+ // Already big endian.
+ if (!isLittleEndian())
+ return T;
switch (getArch()) {
case Triple::UnknownArch:
case Triple::amdgcn:
@@ -1288,6 +1332,8 @@ Triple Triple::getBigEndianArchVariant() const {
case Triple::x86:
case Triple::x86_64:
case Triple::xcore:
+ case Triple::renderscript32:
+ case Triple::renderscript64:
// ARM is intentionally unsupported here, changing the architecture would
// drop any arch suffixes.
@@ -1296,35 +1342,26 @@ Triple Triple::getBigEndianArchVariant() const {
T.setArch(UnknownArch);
break;
- case Triple::aarch64_be:
- case Triple::armeb:
- case Triple::bpfeb:
- case Triple::mips64:
- case Triple::mips:
- case Triple::ppc64:
- case Triple::ppc:
- case Triple::sparc:
- case Triple::sparcv9:
- case Triple::systemz:
- case Triple::tce:
- case Triple::thumbeb:
- // Already big endian.
- break;
-
case Triple::aarch64: T.setArch(Triple::aarch64_be); break;
case Triple::bpfel: T.setArch(Triple::bpfeb); break;
case Triple::mips64el:T.setArch(Triple::mips64); break;
case Triple::mipsel: T.setArch(Triple::mips); break;
case Triple::ppc64le: T.setArch(Triple::ppc64); break;
case Triple::sparcel: T.setArch(Triple::sparc); break;
+ default:
+ llvm_unreachable("getBigEndianArchVariant: unknown triple.");
}
return T;
}
Triple Triple::getLittleEndianArchVariant() const {
Triple T(*this);
+ if (isLittleEndian())
+ return T;
+
switch (getArch()) {
case Triple::UnknownArch:
+ case Triple::lanai:
case Triple::ppc:
case Triple::sparcv9:
case Triple::systemz:
@@ -1337,6 +1374,20 @@ Triple Triple::getLittleEndianArchVariant() const {
T.setArch(UnknownArch);
break;
+ case Triple::aarch64_be: T.setArch(Triple::aarch64); break;
+ case Triple::bpfeb: T.setArch(Triple::bpfel); break;
+ case Triple::mips64: T.setArch(Triple::mips64el); break;
+ case Triple::mips: T.setArch(Triple::mipsel); break;
+ case Triple::ppc64: T.setArch(Triple::ppc64le); break;
+ case Triple::sparc: T.setArch(Triple::sparcel); break;
+ default:
+ llvm_unreachable("getLittleEndianArchVariant: unknown triple.");
+ }
+ return T;
+}
+
+bool Triple::isLittleEndian() const {
+ switch (getArch()) {
case Triple::aarch64:
case Triple::amdgcn:
case Triple::amdil64:
@@ -1367,17 +1418,12 @@ Triple Triple::getLittleEndianArchVariant() const {
case Triple::x86:
case Triple::x86_64:
case Triple::xcore:
- // Already little endian.
- break;
-
- case Triple::aarch64_be: T.setArch(Triple::aarch64); break;
- case Triple::bpfeb: T.setArch(Triple::bpfel); break;
- case Triple::mips64: T.setArch(Triple::mips64el); break;
- case Triple::mips: T.setArch(Triple::mipsel); break;
- case Triple::ppc64: T.setArch(Triple::ppc64le); break;
- case Triple::sparc: T.setArch(Triple::sparcel); break;
+ case Triple::renderscript32:
+ case Triple::renderscript64:
+ return true;
+ default:
+ return false;
}
- return T;
}
StringRef Triple::getARMCPUForArch(StringRef MArch) const {
@@ -1398,6 +1444,7 @@ StringRef Triple::getARMCPUForArch(StringRef MArch) const {
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
case llvm::Triple::WatchOS:
+ case llvm::Triple::TvOS:
if (MArch == "v7k")
return "cortex-a7";
break;
@@ -1431,6 +1478,7 @@ StringRef Triple::getARMCPUForArch(StringRef MArch) const {
switch (getEnvironment()) {
case llvm::Triple::EABIHF:
case llvm::Triple::GNUEABIHF:
+ case llvm::Triple::MuslEABIHF:
return "arm1176jzf-s";
default:
return "arm7tdmi";
diff --git a/contrib/llvm/lib/Support/Twine.cpp b/contrib/llvm/lib/Support/Twine.cpp
index 020dd95..5e989fb 100644
--- a/contrib/llvm/lib/Support/Twine.cpp
+++ b/contrib/llvm/lib/Support/Twine.cpp
@@ -161,7 +161,7 @@ void Twine::printRepr(raw_ostream &OS) const {
OS << ")";
}
-void Twine::dump() const {
+LLVM_DUMP_METHOD void Twine::dump() const {
print(dbgs());
}
diff --git a/contrib/llvm/lib/Support/Unix/Memory.inc b/contrib/llvm/lib/Support/Unix/Memory.inc
index d703191..f3463e5 100644
--- a/contrib/llvm/lib/Support/Unix/Memory.inc
+++ b/contrib/llvm/lib/Support/Unix/Memory.inc
@@ -73,7 +73,7 @@ int getPosixProtectionFlags(unsigned Flags) {
return PROT_NONE;
}
-} // namespace
+} // anonymous namespace
namespace llvm {
namespace sys {
@@ -265,7 +265,7 @@ bool Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) {
}
bool Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) {
- if (M.Address == 0 || M.Size == 0) return false;
+ if (M.Address == nullptr || M.Size == 0) return false;
Memory::InvalidateInstructionCache(M.Address, M.Size);
#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address,
diff --git a/contrib/llvm/lib/Support/Unix/Path.inc b/contrib/llvm/lib/Support/Unix/Path.inc
index d85c37a..84aafcb 100644
--- a/contrib/llvm/lib/Support/Unix/Path.inc
+++ b/contrib/llvm/lib/Support/Unix/Path.inc
@@ -25,6 +25,9 @@
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
@@ -47,6 +50,7 @@
#ifdef __APPLE__
#include <mach-o/dyld.h>
+#include <sys/attr.h>
#endif
// Both stdio.h and cstdio are included via different pathes and
@@ -60,6 +64,25 @@
# define PATH_MAX 4096
#endif
+#include <sys/types.h>
+#if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__)
+#include <sys/statvfs.h>
+#define STATVFS statvfs
+#define STATVFS_F_FRSIZE(vfs) vfs.f_frsize
+#else
+#ifdef __OpenBSD__
+#include <sys/param.h>
+#include <sys/mount.h>
+#elif defined(__ANDROID__)
+#include <sys/vfs.h>
+#else
+#include <sys/mount.h>
+#endif
+#define STATVFS statfs
+#define STATVFS_F_FRSIZE(vfs) static_cast<uint64_t>(vfs.f_bsize)
+#endif
+
+
using namespace llvm;
namespace llvm {
@@ -70,7 +93,7 @@ namespace fs {
defined(__linux__) || defined(__CYGWIN__) || defined(__DragonFly__)
static int
test_dir(char ret[PATH_MAX], const char *dir, const char *bin)
-{
+{
struct stat sb;
char fullpath[PATH_MAX];
@@ -174,6 +197,12 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) {
return "";
}
+TimeValue file_status::getLastAccessedTime() const {
+ TimeValue Ret;
+ Ret.fromEpochTime(fs_st_atime);
+ return Ret;
+}
+
TimeValue file_status::getLastModificationTime() const {
TimeValue Ret;
Ret.fromEpochTime(fs_st_mtime);
@@ -184,6 +213,18 @@ UniqueID file_status::getUniqueID() const {
return UniqueID(fs_st_dev, fs_st_ino);
}
+ErrorOr<space_info> disk_space(const Twine &Path) {
+ struct STATVFS Vfs;
+ if (::STATVFS(Path.str().c_str(), &Vfs))
+ return std::error_code(errno, std::generic_category());
+ auto FrSize = STATVFS_F_FRSIZE(Vfs);
+ space_info SpaceInfo;
+ SpaceInfo.capacity = static_cast<uint64_t>(Vfs.f_blocks) * FrSize;
+ SpaceInfo.free = static_cast<uint64_t>(Vfs.f_bfree) * FrSize;
+ SpaceInfo.available = static_cast<uint64_t>(Vfs.f_bavail) * FrSize;
+ return SpaceInfo;
+}
+
std::error_code current_path(SmallVectorImpl<char> &result) {
result.clear();
@@ -373,8 +414,9 @@ static std::error_code fillStatus(int StatRet, const struct stat &Status,
perms Perms = static_cast<perms>(Status.st_mode);
Result =
- file_status(Type, Perms, Status.st_dev, Status.st_ino, Status.st_mtime,
- Status.st_uid, Status.st_gid, Status.st_size);
+ file_status(Type, Perms, Status.st_dev, Status.st_ino, Status.st_atime,
+ Status.st_mtime, Status.st_uid, Status.st_gid,
+ Status.st_size);
return std::error_code();
}
@@ -506,13 +548,47 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &it) {
return std::error_code();
}
-std::error_code openFileForRead(const Twine &Name, int &ResultFD) {
+#if !defined(F_GETPATH)
+static bool hasProcSelfFD() {
+ // If we have a /proc filesystem mounted, we can quickly establish the
+ // real name of the file with readlink
+ static const bool Result = (::access("/proc/self/fd", R_OK) == 0);
+ return Result;
+}
+#endif
+
+std::error_code openFileForRead(const Twine &Name, int &ResultFD,
+ SmallVectorImpl<char> *RealPath) {
SmallString<128> Storage;
StringRef P = Name.toNullTerminatedStringRef(Storage);
while ((ResultFD = open(P.begin(), O_RDONLY)) < 0) {
if (errno != EINTR)
return std::error_code(errno, std::generic_category());
}
+ // Attempt to get the real name of the file, if the user asked
+ if(!RealPath)
+ return std::error_code();
+ RealPath->clear();
+#if defined(F_GETPATH)
+ // When F_GETPATH is availble, it is the quickest way to get
+ // the real path name.
+ char Buffer[MAXPATHLEN];
+ if (::fcntl(ResultFD, F_GETPATH, Buffer) != -1)
+ RealPath->append(Buffer, Buffer + strlen(Buffer));
+#else
+ char Buffer[PATH_MAX];
+ if (hasProcSelfFD()) {
+ char ProcPath[64];
+ snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", ResultFD);
+ ssize_t CharCount = ::readlink(ProcPath, Buffer, sizeof(Buffer));
+ if (CharCount > 0)
+ RealPath->append(Buffer, Buffer + CharCount);
+ } else {
+ // Use ::realpath to get the real path name
+ if (::realpath(P.begin(), Buffer) != nullptr)
+ RealPath->append(Buffer, Buffer + strlen(Buffer));
+ }
+#endif
return std::error_code();
}
@@ -546,6 +622,53 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
return std::error_code();
}
+std::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath) {
+ if (FD < 0)
+ return make_error_code(errc::bad_file_descriptor);
+
+#if defined(F_GETPATH)
+ // When F_GETPATH is availble, it is the quickest way to get
+ // the path from a file descriptor.
+ ResultPath.reserve(MAXPATHLEN);
+ if (::fcntl(FD, F_GETPATH, ResultPath.begin()) == -1)
+ return std::error_code(errno, std::generic_category());
+
+ ResultPath.set_size(strlen(ResultPath.begin()));
+#else
+ // If we have a /proc filesystem mounted, we can quickly establish the
+ // real name of the file with readlink. Otherwise, we don't know how to
+ // get the filename from a file descriptor. Give up.
+ if (!fs::hasProcSelfFD())
+ return make_error_code(errc::function_not_supported);
+
+ ResultPath.reserve(PATH_MAX);
+ char ProcPath[64];
+ snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", FD);
+ ssize_t CharCount = ::readlink(ProcPath, ResultPath.begin(), ResultPath.capacity());
+ if (CharCount < 0)
+ return std::error_code(errno, std::generic_category());
+
+ // Was the filename truncated?
+ if (static_cast<size_t>(CharCount) == ResultPath.capacity()) {
+ // Use lstat to get the size of the filename
+ struct stat sb;
+ if (::lstat(ProcPath, &sb) < 0)
+ return std::error_code(errno, std::generic_category());
+
+ ResultPath.reserve(sb.st_size + 1);
+ CharCount = ::readlink(ProcPath, ResultPath.begin(), ResultPath.capacity());
+ if (CharCount < 0)
+ return std::error_code(errno, std::generic_category());
+
+ // Test for race condition: did the link size change?
+ if (CharCount > sb.st_size)
+ return std::error_code(ENAMETOOLONG, std::generic_category());
+ }
+ ResultPath.set_size(static_cast<size_t>(CharCount));
+#endif
+ return std::error_code();
+}
+
} // end namespace fs
namespace path {
@@ -586,12 +709,12 @@ static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) {
}
static bool getUserCacheDir(SmallVectorImpl<char> &Result) {
- // First try using XDS_CACHE_HOME env variable,
+ // First try using XDG_CACHE_HOME env variable,
// as specified in XDG Base Directory Specification at
// http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
- if (const char *XdsCacheDir = std::getenv("XDS_CACHE_HOME")) {
+ if (const char *XdgCacheDir = std::getenv("XDG_CACHE_HOME")) {
Result.clear();
- Result.append(XdsCacheDir, XdsCacheDir + strlen(XdsCacheDir));
+ Result.append(XdgCacheDir, XdgCacheDir + strlen(XdgCacheDir));
return true;
}
diff --git a/contrib/llvm/lib/Support/Unix/Process.inc b/contrib/llvm/lib/Support/Unix/Process.inc
index 27083ee..d81836b 100644
--- a/contrib/llvm/lib/Support/Unix/Process.inc
+++ b/contrib/llvm/lib/Support/Unix/Process.inc
@@ -169,6 +169,8 @@ void Process::PreventCoreFiles() {
signal(SIGSEGV, _exit);
signal(SIGBUS, _exit);
#endif
+
+ coreFilesPrevented = true;
}
Optional<std::string> Process::GetEnv(StringRef Name) {
@@ -456,7 +458,7 @@ unsigned llvm::sys::Process::GetRandomNumber() {
#if defined(HAVE_DECL_ARC4RANDOM) && HAVE_DECL_ARC4RANDOM
return arc4random();
#else
- static int x = (::srand(GetRandomNumberSeed()), 0);
+ static int x = (static_cast<void>(::srand(GetRandomNumberSeed())), 0);
(void)x;
return ::rand();
#endif
diff --git a/contrib/llvm/lib/Support/Unix/Signals.inc b/contrib/llvm/lib/Support/Unix/Signals.inc
index 061cdb3..55fd76d 100644
--- a/contrib/llvm/lib/Support/Unix/Signals.inc
+++ b/contrib/llvm/lib/Support/Unix/Signals.inc
@@ -45,6 +45,17 @@
#if HAVE_LINK_H
#include <link.h>
#endif
+#if HAVE_UNWIND_BACKTRACE
+// FIXME: We should be able to use <unwind.h> for any target that has an
+// _Unwind_Backtrace function, but on FreeBSD the configure test passes
+// despite the function not existing, and on Android, <unwind.h> conflicts
+// with <link.h>.
+#ifdef __GLIBC__
+#include <unwind.h>
+#else
+#undef HAVE_UNWIND_BACKTRACE
+#endif
+#endif
using namespace llvm;
@@ -57,6 +68,8 @@ static void (*InterruptFunction)() = nullptr;
static ManagedStatic<std::vector<std::string>> FilesToRemove;
+static StringRef Argv0;
+
// IntSigs - Signals that represent requested termination. There's no bug
// or failure, or if there is, it's not our direct responsibility. For whatever
// reason, our continued execution is no longer desirable.
@@ -96,7 +109,7 @@ static void RegisterHandler(int Signal) {
struct sigaction NewHandler;
NewHandler.sa_handler = SignalHandler;
- NewHandler.sa_flags = SA_NODEFER|SA_RESETHAND;
+ NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK;
sigemptyset(&NewHandler.sa_mask);
// Install the new handler, save the old one in RegisteredSignalInfo.
@@ -106,6 +119,35 @@ static void RegisterHandler(int Signal) {
++NumRegisteredSignals;
}
+#if defined(HAVE_SIGALTSTACK)
+// Hold onto the old alternate signal stack so that it's not reported as a leak.
+// We don't make any attempt to remove our alt signal stack if we remove our
+// signal handlers; that can't be done reliably if someone else is also trying
+// to do the same thing.
+static stack_t OldAltStack;
+
+static void CreateSigAltStack() {
+ const size_t AltStackSize = MINSIGSTKSZ + 8192;
+
+ // If we're executing on the alternate stack, or we already have an alternate
+ // signal stack that we're happy with, there's nothing for us to do. Don't
+ // reduce the size, some other part of the process might need a larger stack
+ // than we do.
+ if (sigaltstack(nullptr, &OldAltStack) != 0 ||
+ OldAltStack.ss_flags & SS_ONSTACK ||
+ (OldAltStack.ss_sp && OldAltStack.ss_size >= AltStackSize))
+ return;
+
+ stack_t AltStack = {};
+ AltStack.ss_sp = reinterpret_cast<char *>(malloc(AltStackSize));
+ AltStack.ss_size = AltStackSize;
+ if (sigaltstack(&AltStack, &OldAltStack) != 0)
+ free(AltStack.ss_sp);
+}
+#else
+static void CreateSigAltStack() {}
+#endif
+
static void RegisterHandlers() {
// We need to dereference the signals mutex during handler registration so
// that we force its construction. This is to prevent the first use being
@@ -116,6 +158,10 @@ static void RegisterHandlers() {
// If the handlers are already registered, we're done.
if (NumRegisteredSignals != 0) return;
+ // Create an alternate stack for signal handling. This is necessary for us to
+ // be able to reliably handle signals due to stack overflow.
+ CreateSigAltStack();
+
for (auto S : IntSigs) RegisterHandler(S);
for (auto S : KillSigs) RegisterHandler(S);
}
@@ -309,20 +355,64 @@ static bool findModulesAndOffsets(void **StackTrace, int Depth,
}
#endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) && ...
+#if defined(ENABLE_BACKTRACES) && defined(HAVE_UNWIND_BACKTRACE)
+static int unwindBacktrace(void **StackTrace, int MaxEntries) {
+ if (MaxEntries < 0)
+ return 0;
+
+ // Skip the first frame ('unwindBacktrace' itself).
+ int Entries = -1;
+
+ auto HandleFrame = [&](_Unwind_Context *Context) -> _Unwind_Reason_Code {
+ // Apparently we need to detect reaching the end of the stack ourselves.
+ void *IP = (void *)_Unwind_GetIP(Context);
+ if (!IP)
+ return _URC_END_OF_STACK;
+
+ assert(Entries < MaxEntries && "recursively called after END_OF_STACK?");
+ if (Entries >= 0)
+ StackTrace[Entries] = IP;
+
+ if (++Entries == MaxEntries)
+ return _URC_END_OF_STACK;
+ return _URC_NO_REASON;
+ };
+
+ _Unwind_Backtrace(
+ [](_Unwind_Context *Context, void *Handler) {
+ return (*static_cast<decltype(HandleFrame) *>(Handler))(Context);
+ },
+ static_cast<void *>(&HandleFrame));
+ return std::max(Entries, 0);
+}
+#endif
+
// PrintStackTrace - In the case of a program crash or fault, print out a stack
// trace so that the user has an indication of why and where we died.
//
// On glibc systems we have the 'backtrace' function, which works nicely, but
// doesn't demangle symbols.
void llvm::sys::PrintStackTrace(raw_ostream &OS) {
-#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
- static void* StackTrace[256];
+#if defined(ENABLE_BACKTRACES)
+ static void *StackTrace[256];
+ int depth = 0;
+#if defined(HAVE_BACKTRACE)
// Use backtrace() to output a backtrace on Linux systems with glibc.
- int depth = backtrace(StackTrace,
+ if (!depth)
+ depth = backtrace(StackTrace, static_cast<int>(array_lengthof(StackTrace)));
+#endif
+#if defined(HAVE_UNWIND_BACKTRACE)
+ // Try _Unwind_Backtrace() if backtrace() failed.
+ if (!depth)
+ depth = unwindBacktrace(StackTrace,
static_cast<int>(array_lengthof(StackTrace)));
- if (printSymbolizedStackTrace(StackTrace, depth, OS))
+#endif
+ if (!depth)
+ return;
+
+ if (printSymbolizedStackTrace(Argv0, StackTrace, depth, OS))
return;
-#if HAVE_DLFCN_H && __GNUG__
+#if HAVE_DLFCN_H && __GNUG__ && !defined(__CYGWIN__)
int width = 0;
for (int i = 0; i < depth; ++i) {
Dl_info dlinfo;
@@ -369,7 +459,7 @@ void llvm::sys::PrintStackTrace(raw_ostream &OS) {
}
OS << '\n';
}
-#else
+#elif defined(HAVE_BACKTRACE)
backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
#endif
#endif
@@ -383,7 +473,10 @@ void llvm::sys::DisableSystemDialogsOnCrash() {}
/// PrintStackTraceOnErrorSignal - When an error signal (such as SIGABRT or
/// SIGSEGV) is delivered to the process, print a stack trace and then exit.
-void llvm::sys::PrintStackTraceOnErrorSignal(bool DisableCrashReporting) {
+void llvm::sys::PrintStackTraceOnErrorSignal(StringRef Argv0,
+ bool DisableCrashReporting) {
+ ::Argv0 = Argv0;
+
AddSignalHandler(PrintStackTraceSignalHandler, nullptr);
#if defined(__APPLE__) && defined(ENABLE_CRASH_OVERRIDES)
@@ -402,42 +495,3 @@ void llvm::sys::PrintStackTraceOnErrorSignal(bool DisableCrashReporting) {
}
#endif
}
-
-
-/***/
-
-// On Darwin, raise sends a signal to the main thread instead of the current
-// thread. This has the unfortunate effect that assert() and abort() will end up
-// bypassing our crash recovery attempts. We work around this for anything in
-// the same linkage unit by just defining our own versions of the assert handler
-// and abort.
-
-#if defined(__APPLE__) && defined(ENABLE_CRASH_OVERRIDES)
-
-#include <signal.h>
-#include <pthread.h>
-
-int raise(int sig) {
- return pthread_kill(pthread_self(), sig);
-}
-
-void __assert_rtn(const char *func,
- const char *file,
- int line,
- const char *expr) {
- if (func)
- fprintf(stderr, "Assertion failed: (%s), function %s, file %s, line %d.\n",
- expr, func, file, line);
- else
- fprintf(stderr, "Assertion failed: (%s), file %s, line %d.\n",
- expr, file, line);
- abort();
-}
-
-void abort() {
- raise(SIGABRT);
- usleep(1000);
- __builtin_trap();
-}
-
-#endif
diff --git a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc
index 17418b0..0506894 100644
--- a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc
+++ b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc
@@ -45,7 +45,7 @@ static bool loadDebugHelp(void) {
}
static BOOL CALLBACK
-ELM_Callback(WIN32_ELMCB_PCSTR ModuleName, DWORD64 ModuleBase,
+ELM_Callback(PCSTR ModuleName, DWORD64 ModuleBase,
ULONG ModuleSize, PVOID UserContext) {
OpenedHandles->insert((HMODULE)ModuleBase);
return TRUE;
diff --git a/contrib/llvm/lib/Support/Windows/Path.inc b/contrib/llvm/lib/Support/Windows/Path.inc
index 5ef77b1..fab6aec 100644
--- a/contrib/llvm/lib/Support/Windows/Path.inc
+++ b/contrib/llvm/lib/Support/Windows/Path.inc
@@ -151,6 +151,29 @@ UniqueID file_status::getUniqueID() const {
return UniqueID(VolumeSerialNumber, FileID);
}
+ErrorOr<space_info> disk_space(const Twine &Path) {
+ ULARGE_INTEGER Avail, Total, Free;
+ if (!::GetDiskFreeSpaceExA(Path.str().c_str(), &Avail, &Total, &Free))
+ return mapWindowsError(::GetLastError());
+ space_info SpaceInfo;
+ SpaceInfo.capacity =
+ (static_cast<uint64_t>(Total.HighPart) << 32) + Total.LowPart;
+ SpaceInfo.free = (static_cast<uint64_t>(Free.HighPart) << 32) + Free.LowPart;
+ SpaceInfo.available =
+ (static_cast<uint64_t>(Avail.HighPart) << 32) + Avail.LowPart;
+ return SpaceInfo;
+}
+
+TimeValue file_status::getLastAccessedTime() const {
+ ULARGE_INTEGER UI;
+ UI.LowPart = LastAccessedTimeLow;
+ UI.HighPart = LastAccessedTimeHigh;
+
+ TimeValue Ret;
+ Ret.fromWin32Time(UI.QuadPart);
+ return Ret;
+}
+
TimeValue file_status::getLastModificationTime() const {
ULARGE_INTEGER UI;
UI.LowPart = LastWriteTimeLow;
@@ -255,24 +278,43 @@ std::error_code rename(const Twine &from, const Twine &to) {
std::error_code ec = std::error_code();
- // Retry while we see ERROR_ACCESS_DENIED.
+ // Retry while we see recoverable errors.
// System scanners (eg. indexer) might open the source file when it is written
// and closed.
- for (int i = 0; i < 2000; i++) {
- // Try ReplaceFile first, as it is able to associate a new data stream with
- // the destination even if the destination file is currently open.
- if (::ReplaceFileW(wide_to.begin(), wide_from.begin(), NULL, 0, NULL, NULL))
- return std::error_code();
+ bool TryReplace = true;
- // We get ERROR_FILE_NOT_FOUND if the destination file is missing.
- // MoveFileEx can handle this case.
- DWORD ReplaceError = ::GetLastError();
- ec = mapWindowsError(ReplaceError);
- if (ReplaceError != ERROR_ACCESS_DENIED &&
- ReplaceError != ERROR_FILE_NOT_FOUND &&
- ReplaceError != ERROR_SHARING_VIOLATION)
- break;
+ for (int i = 0; i < 2000; i++) {
+ if (i > 0)
+ ::Sleep(1);
+
+ if (TryReplace) {
+ // Try ReplaceFile first, as it is able to associate a new data stream
+ // with the destination even if the destination file is currently open.
+ if (::ReplaceFileW(wide_to.data(), wide_from.data(), NULL, 0, NULL, NULL))
+ return std::error_code();
+
+ DWORD ReplaceError = ::GetLastError();
+ ec = mapWindowsError(ReplaceError);
+
+ // If ReplaceFileW returned ERROR_UNABLE_TO_MOVE_REPLACEMENT or
+ // ERROR_UNABLE_TO_MOVE_REPLACEMENT_2, retry but only use MoveFileExW().
+ if (ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT ||
+ ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT_2) {
+ TryReplace = false;
+ continue;
+ }
+ // If ReplaceFileW returned ERROR_UNABLE_TO_REMOVE_REPLACED, retry
+ // using ReplaceFileW().
+ if (ReplaceError == ERROR_UNABLE_TO_REMOVE_REPLACED)
+ continue;
+ // We get ERROR_FILE_NOT_FOUND if the destination file is missing.
+ // MoveFileEx can handle this case.
+ if (ReplaceError != ERROR_ACCESS_DENIED &&
+ ReplaceError != ERROR_FILE_NOT_FOUND &&
+ ReplaceError != ERROR_SHARING_VIOLATION)
+ break;
+ }
if (::MoveFileExW(wide_from.begin(), wide_to.begin(),
MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
@@ -281,8 +323,6 @@ std::error_code rename(const Twine &from, const Twine &to) {
DWORD MoveError = ::GetLastError();
ec = mapWindowsError(MoveError);
if (MoveError != ERROR_ACCESS_DENIED) break;
-
- ::Sleep(1);
}
return ec;
@@ -327,13 +367,15 @@ bool can_execute(const Twine &Path) {
bool equivalent(file_status A, file_status B) {
assert(status_known(A) && status_known(B));
- return A.FileIndexHigh == B.FileIndexHigh &&
- A.FileIndexLow == B.FileIndexLow &&
- A.FileSizeHigh == B.FileSizeHigh &&
- A.FileSizeLow == B.FileSizeLow &&
- A.LastWriteTimeHigh == B.LastWriteTimeHigh &&
- A.LastWriteTimeLow == B.LastWriteTimeLow &&
- A.VolumeSerialNumber == B.VolumeSerialNumber;
+ return A.FileIndexHigh == B.FileIndexHigh &&
+ A.FileIndexLow == B.FileIndexLow &&
+ A.FileSizeHigh == B.FileSizeHigh &&
+ A.FileSizeLow == B.FileSizeLow &&
+ A.LastAccessedTimeHigh == B.LastAccessedTimeHigh &&
+ A.LastAccessedTimeLow == B.LastAccessedTimeLow &&
+ A.LastWriteTimeHigh == B.LastWriteTimeHigh &&
+ A.LastWriteTimeLow == B.LastWriteTimeLow &&
+ A.VolumeSerialNumber == B.VolumeSerialNumber;
}
std::error_code equivalent(const Twine &A, const Twine &B, bool &result) {
@@ -361,7 +403,7 @@ static bool isReservedName(StringRef path) {
if (path.startswith("\\\\.\\"))
return true;
- // Then compare against the list of ancient reserved names
+ // Then compare against the list of ancient reserved names.
for (size_t i = 0; i < array_lengthof(sReservedNames); ++i) {
if (path.equals_lower(sReservedNames[i]))
return true;
@@ -404,7 +446,9 @@ static std::error_code getStatus(HANDLE FileHandle, file_status &Result) {
? file_type::directory_file
: file_type::regular_file;
Result =
- file_status(Type, Info.ftLastWriteTime.dwHighDateTime,
+ file_status(Type, Info.ftLastAccessTime.dwHighDateTime,
+ Info.ftLastAccessTime.dwLowDateTime,
+ Info.ftLastWriteTime.dwHighDateTime,
Info.ftLastWriteTime.dwLowDateTime,
Info.dwVolumeSerialNumber, Info.nFileSizeHigh,
Info.nFileSizeLow, Info.nFileIndexHigh, Info.nFileIndexLow);
@@ -663,7 +707,8 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &it) {
return std::error_code();
}
-std::error_code openFileForRead(const Twine &Name, int &ResultFD) {
+std::error_code openFileForRead(const Twine &Name, int &ResultFD,
+ SmallVectorImpl<char> *RealPath) {
SmallVector<wchar_t, 128> PathUTF16;
if (std::error_code EC = widenPath(Name, PathUTF16))
@@ -692,6 +737,22 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD) {
return mapWindowsError(ERROR_INVALID_HANDLE);
}
+ // Fetch the real name of the file, if the user asked
+ if (RealPath) {
+ RealPath->clear();
+ wchar_t RealPathUTF16[MAX_PATH];
+ DWORD CountChars =
+ ::GetFinalPathNameByHandleW(H, RealPathUTF16, MAX_PATH,
+ FILE_NAME_NORMALIZED);
+ if (CountChars > 0 && CountChars < MAX_PATH) {
+ // Convert the result from UTF-16 to UTF-8.
+ SmallString<MAX_PATH> RealPathUTF8;
+ if (!UTF16ToUTF8(RealPathUTF16, CountChars, RealPathUTF8))
+ RealPath->append(RealPathUTF8.data(),
+ RealPathUTF8.data() + strlen(RealPathUTF8.data()));
+ }
+ }
+
ResultFD = FD;
return std::error_code();
}
@@ -752,6 +813,42 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
ResultFD = FD;
return std::error_code();
}
+
+std::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath) {
+ HANDLE FileHandle = reinterpret_cast<HANDLE>(::_get_osfhandle(FD));
+ if (FileHandle == INVALID_HANDLE_VALUE)
+ return make_error_code(errc::bad_file_descriptor);
+
+ DWORD CharCount;
+ SmallVector<wchar_t, 1024> TempPath;
+ do {
+ CharCount = ::GetFinalPathNameByHandleW(FileHandle, TempPath.begin(),
+ TempPath.capacity(),
+ FILE_NAME_NORMALIZED);
+ if (CharCount < TempPath.capacity())
+ break;
+
+ // Reserve sufficient space for the path as well as the null character. Even
+ // though the API does not document that it is required, if we reserve just
+ // CharCount space, the function call will not store the resulting path and
+ // still report success.
+ TempPath.reserve(CharCount + 1);
+ } while (true);
+
+ if (CharCount == 0)
+ return mapWindowsError(::GetLastError());
+
+ TempPath.set_size(CharCount);
+
+ // On earlier Windows releases, the character count includes the terminating
+ // null.
+ if (TempPath.back() == L'\0') {
+ --CharCount;
+ TempPath.pop_back();
+ }
+
+ return windows::UTF16ToUTF8(TempPath.data(), CharCount, ResultPath);
+}
} // end namespace fs
namespace path {
@@ -886,6 +983,7 @@ std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
llvm::SmallVectorImpl<char> &utf8) {
return UTF16ToCodePage(CP_ACP, utf16, utf16_len, utf8);
}
+
} // end namespace windows
} // end namespace sys
} // end namespace llvm
diff --git a/contrib/llvm/lib/Support/Windows/Process.inc b/contrib/llvm/lib/Support/Windows/Process.inc
index dae35a8..b012991 100644
--- a/contrib/llvm/lib/Support/Windows/Process.inc
+++ b/contrib/llvm/lib/Support/Windows/Process.inc
@@ -123,6 +123,8 @@ void Process::PreventCoreFiles() {
SetErrorMode(SEM_FAILCRITICALERRORS |
SEM_NOGPFAULTERRORBOX |
SEM_NOOPENFILEERRORBOX);
+
+ coreFilesPrevented = true;
}
/// Returns the environment variable \arg Name's value as a string encoded in
@@ -199,6 +201,9 @@ WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
const int DirSize = Dir.size();
// Search for matching files.
+ // FIXME: This assumes the wildcard is only in the file name and not in the
+ // directory portion of the file path. For example, it doesn't handle
+ // "*\foo.c" nor "s?c\bar.cpp".
WIN32_FIND_DATAW FileData;
HANDLE FindHandle = FindFirstFileW(Arg, &FileData);
if (FindHandle == INVALID_HANDLE_VALUE) {
@@ -213,7 +218,7 @@ WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
if (ec)
break;
- // Push the filename onto Dir, and remove it afterwards.
+ // Append FileName to Dir, and remove it afterwards.
llvm::sys::path::append(Dir, StringRef(FileName.data(), FileName.size()));
AllocateAndPush(Dir, Args, Allocator);
Dir.resize(DirSize);
@@ -223,6 +228,23 @@ WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
return ec;
}
+static std::error_code
+ExpandShortFileName(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
+ SpecificBumpPtrAllocator<char> &Allocator) {
+ SmallVector<wchar_t, MAX_PATH> LongPath;
+ DWORD Length = GetLongPathNameW(Arg, LongPath.data(), LongPath.capacity());
+ if (Length == 0)
+ return mapWindowsError(GetLastError());
+ if (Length > LongPath.capacity()) {
+ // We're not going to try to deal with paths longer than MAX_PATH, so we'll
+ // treat this as an error. GetLastError() returns ERROR_SUCCESS, which
+ // isn't useful, so we'll hardcode an appropriate error value.
+ return mapWindowsError(ERROR_INSUFFICIENT_BUFFER);
+ }
+ LongPath.set_size(Length);
+ return ConvertAndPushArg(LongPath.data(), Args, Allocator);
+}
+
std::error_code
Process::GetArgumentVector(SmallVectorImpl<const char *> &Args,
ArrayRef<const char *>,
@@ -236,7 +258,19 @@ Process::GetArgumentVector(SmallVectorImpl<const char *> &Args,
Args.reserve(ArgCount);
std::error_code ec;
- for (int i = 0; i < ArgCount; ++i) {
+ // The first argument may contain just the name of the executable (e.g.,
+ // "clang") rather than the full path, so swap it with the full path.
+ wchar_t ModuleName[MAX_PATH];
+ int Length = ::GetModuleFileNameW(NULL, ModuleName, MAX_PATH);
+ if (0 < Length && Length < MAX_PATH)
+ UnicodeCommandLine[0] = ModuleName;
+
+ // If the first argument is a shortened (8.3) name (which is possible even
+ // if we got the module name), the driver will have trouble distinguishing it
+ // (e.g., clang.exe v. clang++.exe), so expand it now.
+ ec = ExpandShortFileName(UnicodeCommandLine[0], Args, ArgAllocator);
+
+ for (int i = 1; i < ArgCount && !ec; ++i) {
ec = WildcardExpand(UnicodeCommandLine[i], Args, ArgAllocator);
if (ec)
break;
diff --git a/contrib/llvm/lib/Support/Windows/Signals.inc b/contrib/llvm/lib/Support/Windows/Signals.inc
index f40ca72..1e2fa42 100644
--- a/contrib/llvm/lib/Support/Windows/Signals.inc
+++ b/contrib/llvm/lib/Support/Windows/Signals.inc
@@ -11,7 +11,11 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/WindowsError.h"
#include <algorithm>
+#include <io.h>
#include <signal.h>
#include <stdio.h>
@@ -117,6 +121,12 @@ typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,
typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,
HANDLE hThread, LPADDRESS64 lpaddr);
+typedef BOOL(WINAPI *fpMiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
+ PMINIDUMP_EXCEPTION_INFORMATION,
+ PMINIDUMP_USER_STREAM_INFORMATION,
+ PMINIDUMP_CALLBACK_INFORMATION);
+static fpMiniDumpWriteDump fMiniDumpWriteDump;
+
typedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64,
PVOID, PREAD_PROCESS_MEMORY_ROUTINE64,
PFUNCTION_TABLE_ACCESS_ROUTINE64,
@@ -154,6 +164,8 @@ static fpEnumerateLoadedModules fEnumerateLoadedModules;
static bool load64BitDebugHelp(void) {
HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
if (hLib) {
+ fMiniDumpWriteDump = (fpMiniDumpWriteDump)
+ ::GetProcAddress(hLib, "MiniDumpWriteDump");
fStackWalk64 = (fpStackWalk64)
::GetProcAddress(hLib, "StackWalk64");
fSymGetModuleBase64 = (fpSymGetModuleBase64)
@@ -171,7 +183,7 @@ static bool load64BitDebugHelp(void) {
fEnumerateLoadedModules = (fpEnumerateLoadedModules)
::GetProcAddress(hLib, "EnumerateLoadedModules64");
}
- return fStackWalk64 && fSymInitialize && fSymSetOptions;
+ return fStackWalk64 && fSymInitialize && fSymSetOptions && fMiniDumpWriteDump;
}
using namespace llvm;
@@ -194,6 +206,8 @@ static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;
static CRITICAL_SECTION CriticalSection;
static bool CriticalSectionInitialized = false;
+static StringRef Argv0;
+
enum {
#if defined(_M_X64)
NativeMachineType = IMAGE_FILE_MACHINE_AMD64
@@ -228,7 +242,7 @@ static bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS,
break;
}
- return printSymbolizedStackTrace(&StackTrace[0], Depth, OS);
+ return printSymbolizedStackTrace(Argv0, &StackTrace[0], Depth, OS);
}
namespace {
@@ -241,7 +255,7 @@ struct FindModuleData {
};
}
-static BOOL CALLBACK findModuleCallback(WIN32_ELMCB_PCSTR ModuleName,
+static BOOL CALLBACK findModuleCallback(PCSTR ModuleName,
DWORD64 ModuleBase, ULONG ModuleSize,
void *VoidData) {
FindModuleData *Data = (FindModuleData*)VoidData;
@@ -484,7 +498,13 @@ void sys::DisableSystemDialogsOnCrash() {
/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or
/// SIGSEGV) is delivered to the process, print a stack trace and then exit.
-void sys::PrintStackTraceOnErrorSignal(bool DisableCrashReporting) {
+void sys::PrintStackTraceOnErrorSignal(StringRef Argv0,
+ bool DisableCrashReporting) {
+ ::Argv0 = Argv0;
+
+ if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT"))
+ Process::PreventCoreFiles();
+
DisableSystemDialogsOnCrash();
RegisterHandler();
LeaveCriticalSection(&CriticalSection);
@@ -563,9 +583,209 @@ void llvm::sys::RunInterruptHandlers() {
Cleanup();
}
+/// \brief Find the Windows Registry Key for a given location.
+///
+/// \returns a valid HKEY if the location exists, else NULL.
+static HKEY FindWERKey(const llvm::Twine &RegistryLocation) {
+ HKEY Key;
+ if (ERROR_SUCCESS != ::RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+ RegistryLocation.str().c_str(), 0,
+ KEY_QUERY_VALUE | KEY_READ, &Key))
+ return NULL;
+
+ return Key;
+}
+
+/// \brief Populate ResultDirectory with the value for "DumpFolder" for a given
+/// Windows Registry key.
+///
+/// \returns true if a valid value for DumpFolder exists, false otherwise.
+static bool GetDumpFolder(HKEY Key,
+ llvm::SmallVectorImpl<char> &ResultDirectory) {
+ using llvm::sys::windows::UTF16ToUTF8;
+
+ if (!Key)
+ return false;
+
+ DWORD BufferLengthBytes = 0;
+
+ if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ,
+ NULL, NULL, &BufferLengthBytes))
+ return false;
+
+ SmallVector<wchar_t, MAX_PATH> Buffer(BufferLengthBytes);
+
+ if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ,
+ NULL, Buffer.data(), &BufferLengthBytes))
+ return false;
+
+ DWORD ExpandBufferSize = ::ExpandEnvironmentStringsW(Buffer.data(), NULL, 0);
+
+ if (!ExpandBufferSize)
+ return false;
+
+ SmallVector<wchar_t, MAX_PATH> ExpandBuffer(ExpandBufferSize);
+
+ if (ExpandBufferSize != ::ExpandEnvironmentStringsW(Buffer.data(),
+ ExpandBuffer.data(),
+ ExpandBufferSize))
+ return false;
+
+ if (UTF16ToUTF8(ExpandBuffer.data(), ExpandBufferSize - 1, ResultDirectory))
+ return false;
+
+ return true;
+}
+
+/// \brief Populate ResultType with a valid MINIDUMP_TYPE based on the value of
+/// "DumpType" for a given Windows Registry key.
+///
+/// According to
+/// https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181(v=vs.85).aspx
+/// valid values for DumpType are:
+/// * 0: Custom dump
+/// * 1: Mini dump
+/// * 2: Full dump
+/// If "Custom dump" is specified then the "CustomDumpFlags" field is read
+/// containing a bitwise combination of MINIDUMP_TYPE values.
+///
+/// \returns true if a valid value for ResultType can be set, false otherwise.
+static bool GetDumpType(HKEY Key, MINIDUMP_TYPE &ResultType) {
+ if (!Key)
+ return false;
+
+ DWORD DumpType;
+ DWORD TypeSize = sizeof(DumpType);
+ if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"DumpType", RRF_RT_REG_DWORD,
+ NULL, &DumpType,
+ &TypeSize))
+ return false;
+
+ switch (DumpType) {
+ case 0: {
+ DWORD Flags = 0;
+ if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"CustomDumpFlags",
+ RRF_RT_REG_DWORD, NULL, &Flags,
+ &TypeSize))
+ return false;
+
+ ResultType = static_cast<MINIDUMP_TYPE>(Flags);
+ break;
+ }
+ case 1:
+ ResultType = MiniDumpNormal;
+ break;
+ case 2:
+ ResultType = MiniDumpWithFullMemory;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+/// \brief Write a Windows dump file containing process information that can be
+/// used for post-mortem debugging.
+///
+/// \returns zero error code if a mini dump created, actual error code
+/// otherwise.
+static std::error_code WINAPI
+WriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) {
+ using namespace llvm;
+ using namespace llvm::sys;
+
+ std::string MainExecutableName = fs::getMainExecutable(nullptr, nullptr);
+ StringRef ProgramName;
+
+ if (MainExecutableName.empty()) {
+ // If we can't get the executable filename,
+ // things are in worse shape than we realize
+ // and we should just bail out.
+ return mapWindowsError(::GetLastError());
+ }
+
+ ProgramName = path::filename(MainExecutableName.c_str());
+
+ // The Windows Registry location as specified at
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181%28v=vs.85%29.aspx
+ // "Collecting User-Mode Dumps" that may optionally be set to collect crash
+ // dumps in a specified location.
+ StringRef LocalDumpsRegistryLocation =
+ "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps";
+
+ // The key pointing to the Registry location that may contain global crash
+ // dump settings. This will be NULL if the location can not be found.
+ ScopedRegHandle DefaultLocalDumpsKey(FindWERKey(LocalDumpsRegistryLocation));
+
+ // The key pointing to the Registry location that may contain
+ // application-specific crash dump settings. This will be NULL if the
+ // location can not be found.
+ ScopedRegHandle AppSpecificKey(
+ FindWERKey(Twine(LocalDumpsRegistryLocation) + "\\" + ProgramName));
+
+ // Look to see if a dump type is specified in the registry; first with the
+ // app-specific key and failing that with the global key. If none are found
+ // default to a normal dump (GetDumpType will return false either if the key
+ // is NULL or if there is no valid DumpType value at its location).
+ MINIDUMP_TYPE DumpType;
+ if (!GetDumpType(AppSpecificKey, DumpType))
+ if (!GetDumpType(DefaultLocalDumpsKey, DumpType))
+ DumpType = MiniDumpNormal;
+
+ // Look to see if a dump location is specified in the registry; first with the
+ // app-specific key and failing that with the global key. If none are found
+ // we'll just create the dump file in the default temporary file location
+ // (GetDumpFolder will return false either if the key is NULL or if there is
+ // no valid DumpFolder value at its location).
+ bool ExplicitDumpDirectorySet = true;
+ SmallString<MAX_PATH> DumpDirectory;
+ if (!GetDumpFolder(AppSpecificKey, DumpDirectory))
+ if (!GetDumpFolder(DefaultLocalDumpsKey, DumpDirectory))
+ ExplicitDumpDirectorySet = false;
+
+ int FD;
+ SmallString<MAX_PATH> DumpPath;
+
+ if (ExplicitDumpDirectorySet) {
+ if (std::error_code EC = fs::create_directories(DumpDirectory))
+ return EC;
+ if (std::error_code EC = fs::createUniqueFile(
+ Twine(DumpDirectory) + "\\" + ProgramName + ".%%%%%%.dmp", FD,
+ DumpPath))
+ return EC;
+ } else if (std::error_code EC =
+ fs::createTemporaryFile(ProgramName, "dmp", FD, DumpPath))
+ return EC;
+
+ // Our support functions return a file descriptor but Windows wants a handle.
+ ScopedCommonHandle FileHandle(reinterpret_cast<HANDLE>(_get_osfhandle(FD)));
+
+ if (!fMiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(),
+ FileHandle, DumpType, ExceptionInfo, NULL, NULL))
+ return mapWindowsError(::GetLastError());
+
+ llvm::errs() << "Wrote crash dump file \"" << DumpPath << "\"\n";
+ return std::error_code();
+}
+
static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
Cleanup();
+ // We'll automatically write a Minidump file here to help diagnose
+ // the nasty sorts of crashes that aren't 100% reproducible from a set of
+ // inputs (or in the event that the user is unable or unwilling to provide a
+ // reproducible case).
+ if (!llvm::Process::AreCoreFilesPrevented()) {
+ MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo;
+ ExceptionInfo.ThreadId = ::GetCurrentThreadId();
+ ExceptionInfo.ExceptionPointers = ep;
+ ExceptionInfo.ClientPointers = FALSE;
+
+ if (std::error_code EC = WriteWindowsDumpFile(&ExceptionInfo))
+ llvm::errs() << "Could not write crash dump file: " << EC.message()
+ << "\n";
+ }
+
// Initialize the STACKFRAME structure.
STACKFRAME64 StackFrame = {};
diff --git a/contrib/llvm/lib/Support/Windows/WindowsSupport.h b/contrib/llvm/lib/Support/Windows/WindowsSupport.h
index 60490f2..18ecdf4e 100644
--- a/contrib/llvm/lib/Support/Windows/WindowsSupport.h
+++ b/contrib/llvm/lib/Support/Windows/WindowsSupport.h
@@ -45,7 +45,6 @@
#include <wincrypt.h>
#include <cassert>
#include <string>
-#include <vector>
/// Determines if the program is running on Windows 8 or newer. This
/// reimplements one of the helpers in the Windows 8.1 SDK, which are intended
@@ -69,15 +68,15 @@ inline bool RunningWindows8OrGreater() {
Mask) != FALSE;
}
-inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) {
+inline bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix) {
if (!ErrMsg)
return true;
char *buffer = NULL;
DWORD LastError = GetLastError();
- DWORD R = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_MAX_WIDTH_MASK,
- NULL, LastError, 0, (LPSTR)&buffer, 1, NULL);
+ DWORD R = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL, LastError, 0, (LPSTR)&buffer, 1, NULL);
if (R)
*ErrMsg = prefix + ": " + buffer;
else
@@ -168,6 +167,22 @@ struct CryptContextTraits : CommonHandleTraits {
}
};
+struct RegTraits : CommonHandleTraits {
+ typedef HKEY handle_type;
+
+ static handle_type GetInvalid() {
+ return NULL;
+ }
+
+ static void Close(handle_type h) {
+ ::RegCloseKey(h);
+ }
+
+ static bool IsValid(handle_type h) {
+ return h != GetInvalid();
+ }
+};
+
struct FindHandleTraits : CommonHandleTraits {
static void Close(handle_type h) {
::FindClose(h);
@@ -179,6 +194,7 @@ struct FileHandleTraits : CommonHandleTraits {};
typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle;
typedef ScopedHandle<FileHandleTraits> ScopedFileHandle;
typedef ScopedHandle<CryptContextTraits> ScopedCryptContext;
+typedef ScopedHandle<RegTraits> ScopedRegHandle;
typedef ScopedHandle<FindHandleTraits> ScopedFindHandle;
typedef ScopedHandle<JobHandleTraits> ScopedJobHandle;
diff --git a/contrib/llvm/lib/Support/YAMLParser.cpp b/contrib/llvm/lib/Support/YAMLParser.cpp
index c4384ca..620841c 100644
--- a/contrib/llvm/lib/Support/YAMLParser.cpp
+++ b/contrib/llvm/lib/Support/YAMLParser.cpp
@@ -1911,7 +1911,7 @@ StringRef ScalarNode::getValue(SmallVectorImpl<char> &Storage) const {
return UnquotedValue;
}
// Plain or block.
- return Value.rtrim(" ");
+ return Value.rtrim(' ');
}
StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue
diff --git a/contrib/llvm/lib/Support/YAMLTraits.cpp b/contrib/llvm/lib/Support/YAMLTraits.cpp
index 2aa6e9b..75fac20 100644
--- a/contrib/llvm/lib/Support/YAMLTraits.cpp
+++ b/contrib/llvm/lib/Support/YAMLTraits.cpp
@@ -423,8 +423,29 @@ void Output::beginMapping() {
bool Output::mapTag(StringRef Tag, bool Use) {
if (Use) {
- this->output(" ");
+ // If this tag is being written inside a sequence we should write the start
+ // of the sequence before writing the tag, otherwise the tag won't be
+ // attached to the element in the sequence, but rather the sequence itself.
+ bool SequenceElement =
+ StateStack.size() > 1 && (StateStack[StateStack.size() - 2] == inSeq ||
+ StateStack[StateStack.size() - 2] == inFlowSeq);
+ if (SequenceElement && StateStack.back() == inMapFirstKey) {
+ this->newLineCheck();
+ } else {
+ this->output(" ");
+ }
this->output(Tag);
+ if (SequenceElement) {
+ // If we're writing the tag during the first element of a map, the tag
+ // takes the place of the first element in the sequence.
+ if (StateStack.back() == inMapFirstKey) {
+ StateStack.pop_back();
+ StateStack.push_back(inMapOtherKey);
+ }
+ // Tags inside maps in sequences should act as keys in the map from a
+ // formatting perspective, so we always want a newline in a sequence.
+ NeedsNewLine = true;
+ }
}
return Use;
}
diff --git a/contrib/llvm/lib/Support/raw_ostream.cpp b/contrib/llvm/lib/Support/raw_ostream.cpp
index 15813fd..275fe1d 100644
--- a/contrib/llvm/lib/Support/raw_ostream.cpp
+++ b/contrib/llvm/lib/Support/raw_ostream.cpp
@@ -141,7 +141,7 @@ raw_ostream &raw_ostream::operator<<(unsigned long long N) {
return this->operator<<(static_cast<unsigned long>(N));
char NumberBuffer[20];
- char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
+ char *EndPtr = std::end(NumberBuffer);
char *CurPtr = EndPtr;
while (N) {
@@ -166,13 +166,13 @@ raw_ostream &raw_ostream::write_hex(unsigned long long N) {
if (N == 0)
return *this << '0';
- char NumberBuffer[20];
- char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
+ char NumberBuffer[16];
+ char *EndPtr = std::end(NumberBuffer);
char *CurPtr = EndPtr;
while (N) {
- uintptr_t x = N % 16;
- *--CurPtr = (x < 10 ? '0' + x : 'a' + x - 10);
+ unsigned char x = static_cast<unsigned char>(N) % 16;
+ *--CurPtr = hexdigit(x, /*LowerCase*/true);
N /= 16;
}
@@ -181,9 +181,7 @@ raw_ostream &raw_ostream::write_hex(unsigned long long N) {
raw_ostream &raw_ostream::write_escaped(StringRef Str,
bool UseHexEscapes) {
- for (unsigned i = 0, e = Str.size(); i != e; ++i) {
- unsigned char c = Str[i];
-
+ for (unsigned char c : Str) {
switch (c) {
case '\\':
*this << '\\' << '\\';
@@ -232,7 +230,7 @@ raw_ostream &raw_ostream::operator<<(double N) {
// On MSVCRT and compatible, output of %e is incompatible to Posix
// by default. Number of exponent digits should be at least 2. "%+03d"
// FIXME: Implement our formatter to here or Support/Format.h!
-#if __cplusplus >= 201103L && defined(__MINGW32__)
+#if defined(__MINGW32__)
// FIXME: It should be generic to C++11.
if (N == 0.0 && std::signbit(N))
return *this << "-0.000000e+00";
@@ -422,11 +420,10 @@ raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) {
NumberBuffer[1] = '0';
char *EndPtr = NumberBuffer+Width;
char *CurPtr = EndPtr;
- const char A = FN.Upper ? 'A' : 'a';
unsigned long long N = FN.HexValue;
while (N) {
- uintptr_t x = N % 16;
- *--CurPtr = (x < 10 ? '0' + x : A + x - 10);
+ unsigned char x = static_cast<unsigned char>(N) % 16;
+ *--CurPtr = hexdigit(x, !FN.Upper);
N /= 16;
}
@@ -626,6 +623,7 @@ void raw_fd_ostream::close() {
}
uint64_t raw_fd_ostream::seek(uint64_t off) {
+ assert(SupportsSeeking && "Stream does not support seeking!");
flush();
pos = ::lseek(FD, off, SEEK_SET);
if (pos == (uint64_t)-1)
@@ -718,9 +716,10 @@ bool raw_fd_ostream::has_colors() const {
/// outs() - This returns a reference to a raw_ostream for standard output.
/// Use it like: outs() << "foo" << "bar";
raw_ostream &llvm::outs() {
- // Set buffer settings to model stdout behavior.
- // Delete the file descriptor when the program exits, forcing error
- // detection. If you don't want this behavior, don't use outs().
+ // Set buffer settings to model stdout behavior. Delete the file descriptor
+ // when the program exits, forcing error detection. This means that if you
+ // ever call outs(), you can't open another raw_fd_ostream on stdout, as we'll
+ // close stdout twice and print an error the second time.
std::error_code EC;
static raw_fd_ostream S("-", EC, sys::fs::F_None);
assert(!EC);
OpenPOWER on IntegriCloud