aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Support')
-rw-r--r--llvm/lib/Support/AArch64TargetParser.cpp48
-rw-r--r--llvm/lib/Support/AMDGPUMetadata.cpp1
-rw-r--r--llvm/lib/Support/APFloat.cpp184
-rw-r--r--llvm/lib/Support/APInt.cpp79
-rw-r--r--llvm/lib/Support/ARMAttributeParser.cpp18
-rw-r--r--llvm/lib/Support/ARMTargetParser.cpp2
-rw-r--r--llvm/lib/Support/BinaryStreamReader.cpp8
-rw-r--r--llvm/lib/Support/CRC.cpp2
-rw-r--r--llvm/lib/Support/CommandLine.cpp209
-rw-r--r--llvm/lib/Support/Compression.cpp4
-rw-r--r--llvm/lib/Support/CrashRecoveryContext.cpp73
-rw-r--r--llvm/lib/Support/DebugCounter.cpp1
-rw-r--r--llvm/lib/Support/Error.cpp5
-rw-r--r--llvm/lib/Support/FileCheck.cpp272
-rw-r--r--llvm/lib/Support/FileCheckImpl.h175
-rw-r--r--llvm/lib/Support/FileOutputBuffer.cpp5
-rw-r--r--llvm/lib/Support/Host.cpp63
-rw-r--r--llvm/lib/Support/InitLLVM.cpp6
-rw-r--r--llvm/lib/Support/ItaniumManglingCanonicalizer.cpp39
-rw-r--r--llvm/lib/Support/KnownBits.cpp4
-rw-r--r--llvm/lib/Support/LockFileManager.cpp6
-rw-r--r--llvm/lib/Support/Options.cpp32
-rw-r--r--llvm/lib/Support/Parallel.cpp82
-rw-r--r--llvm/lib/Support/Path.cpp41
-rw-r--r--llvm/lib/Support/SHA1.cpp54
-rw-r--r--llvm/lib/Support/Signals.cpp4
-rw-r--r--llvm/lib/Support/SpecialCaseList.cpp14
-rw-r--r--llvm/lib/Support/Statistic.cpp14
-rw-r--r--llvm/lib/Support/StringRef.cpp19
-rw-r--r--llvm/lib/Support/TargetParser.cpp8
-rw-r--r--llvm/lib/Support/Threading.cpp51
-rw-r--r--llvm/lib/Support/TimeProfiler.cpp34
-rw-r--r--llvm/lib/Support/Timer.cpp11
-rw-r--r--llvm/lib/Support/Triple.cpp274
-rw-r--r--llvm/lib/Support/Unix/Memory.inc6
-rw-r--r--llvm/lib/Support/Unix/Path.inc47
-rw-r--r--llvm/lib/Support/Unix/Signals.inc50
-rw-r--r--llvm/lib/Support/Unix/Threading.inc63
-rw-r--r--llvm/lib/Support/Unix/Unix.h9
-rw-r--r--llvm/lib/Support/VirtualFileSystem.cpp52
-rw-r--r--llvm/lib/Support/Windows/Memory.inc8
-rw-r--r--llvm/lib/Support/Windows/Process.inc7
-rw-r--r--llvm/lib/Support/Windows/Program.inc2
-rw-r--r--llvm/lib/Support/Windows/Signals.inc63
-rw-r--r--llvm/lib/Support/Windows/Threading.inc50
-rw-r--r--llvm/lib/Support/Windows/WindowsSupport.h8
-rw-r--r--llvm/lib/Support/YAMLParser.cpp64
-rw-r--r--llvm/lib/Support/YAMLTraits.cpp3
-rw-r--r--llvm/lib/Support/raw_ostream.cpp12
49 files changed, 1422 insertions, 864 deletions
diff --git a/llvm/lib/Support/AArch64TargetParser.cpp b/llvm/lib/Support/AArch64TargetParser.cpp
index 6f1d6d50eee2..b5cd4af0eb3d 100644
--- a/llvm/lib/Support/AArch64TargetParser.cpp
+++ b/llvm/lib/Support/AArch64TargetParser.cpp
@@ -213,3 +213,51 @@ AArch64::ArchKind AArch64::parseCPUArch(StringRef CPU) {
}
return ArchKind::INVALID;
}
+
+// Parse a branch protection specification, which has the form
+// standard | none | [bti,pac-ret[+b-key,+leaf]*]
+// Returns true on success, with individual elements of the specification
+// returned in `PBP`. Returns false in error, with `Err` containing
+// an erroneous part of the spec.
+bool AArch64::parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP,
+ StringRef &Err) {
+ PBP = {"none", "a_key", false};
+ if (Spec == "none")
+ return true; // defaults are ok
+
+ if (Spec == "standard") {
+ PBP.Scope = "non-leaf";
+ PBP.BranchTargetEnforcement = true;
+ return true;
+ }
+
+ SmallVector<StringRef, 4> Opts;
+ Spec.split(Opts, "+");
+ for (int I = 0, E = Opts.size(); I != E; ++I) {
+ StringRef Opt = Opts[I].trim();
+ if (Opt == "bti") {
+ PBP.BranchTargetEnforcement = true;
+ continue;
+ }
+ if (Opt == "pac-ret") {
+ PBP.Scope = "non-leaf";
+ for (; I + 1 != E; ++I) {
+ StringRef PACOpt = Opts[I + 1].trim();
+ if (PACOpt == "leaf")
+ PBP.Scope = "all";
+ else if (PACOpt == "b-key")
+ PBP.Key = "b_key";
+ else
+ break;
+ }
+ continue;
+ }
+ if (Opt == "")
+ Err = "<empty>";
+ else
+ Err = Opt;
+ return false;
+ }
+
+ return true;
+}
diff --git a/llvm/lib/Support/AMDGPUMetadata.cpp b/llvm/lib/Support/AMDGPUMetadata.cpp
index 5f8102299f47..4ea197a97389 100644
--- a/llvm/lib/Support/AMDGPUMetadata.cpp
+++ b/llvm/lib/Support/AMDGPUMetadata.cpp
@@ -62,6 +62,7 @@ struct ScalarEnumerationTraits<ValueKind> {
YIO.enumCase(EN, "HiddenGlobalOffsetZ", ValueKind::HiddenGlobalOffsetZ);
YIO.enumCase(EN, "HiddenNone", ValueKind::HiddenNone);
YIO.enumCase(EN, "HiddenPrintfBuffer", ValueKind::HiddenPrintfBuffer);
+ YIO.enumCase(EN, "HiddenHostcallBuffer", ValueKind::HiddenHostcallBuffer);
YIO.enumCase(EN, "HiddenDefaultQueue", ValueKind::HiddenDefaultQueue);
YIO.enumCase(EN, "HiddenCompletionAction",
ValueKind::HiddenCompletionAction);
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index b79baf1834a7..050c37baefb8 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -20,7 +20,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>
@@ -208,6 +208,10 @@ namespace llvm {
/* A bunch of private, handy routines. */
+static inline Error createError(const Twine &Err) {
+ return make_error<StringError>(Err, inconvertibleErrorCode());
+}
+
static inline unsigned int
partCountForBits(unsigned int bits)
{
@@ -226,9 +230,8 @@ decDigitValue(unsigned int c)
If the exponent overflows, returns a large exponent with the
appropriate sign. */
-static int
-readExponent(StringRef::iterator begin, StringRef::iterator end)
-{
+static Expected<int> readExponent(StringRef::iterator begin,
+ StringRef::iterator end) {
bool isNegative;
unsigned int absExponent;
const unsigned int overlargeExponent = 24000; /* FIXME. */
@@ -242,29 +245,28 @@ readExponent(StringRef::iterator begin, StringRef::iterator end)
isNegative = (*p == '-');
if (*p == '-' || *p == '+') {
p++;
- assert(p != end && "Exponent has no digits");
+ if (p == end)
+ return createError("Exponent has no digits");
}
absExponent = decDigitValue(*p++);
- assert(absExponent < 10U && "Invalid character in exponent");
+ if (absExponent >= 10U)
+ return createError("Invalid character in exponent");
for (; p != end; ++p) {
unsigned int value;
value = decDigitValue(*p);
- assert(value < 10U && "Invalid character in exponent");
+ if (value >= 10U)
+ return createError("Invalid character in exponent");
- value += absExponent * 10;
+ absExponent = absExponent * 10U + value;
if (absExponent >= overlargeExponent) {
absExponent = overlargeExponent;
- p = end; /* outwit assert below */
break;
}
- absExponent = value;
}
- assert(p == end && "Invalid exponent in exponent");
-
if (isNegative)
return -(int) absExponent;
else
@@ -273,20 +275,21 @@ readExponent(StringRef::iterator begin, StringRef::iterator end)
/* This is ugly and needs cleaning up, but I don't immediately see
how whilst remaining safe. */
-static int
-totalExponent(StringRef::iterator p, StringRef::iterator end,
- int exponentAdjustment)
-{
+static Expected<int> totalExponent(StringRef::iterator p,
+ StringRef::iterator end,
+ int exponentAdjustment) {
int unsignedExponent;
bool negative, overflow;
int exponent = 0;
- assert(p != end && "Exponent has no digits");
+ if (p == end)
+ return createError("Exponent has no digits");
negative = *p == '-';
if (*p == '-' || *p == '+') {
p++;
- assert(p != end && "Exponent has no digits");
+ if (p == end)
+ return createError("Exponent has no digits");
}
unsignedExponent = 0;
@@ -295,7 +298,8 @@ totalExponent(StringRef::iterator p, StringRef::iterator end,
unsigned int value;
value = decDigitValue(*p);
- assert(value < 10U && "Invalid character in exponent");
+ if (value >= 10U)
+ return createError("Invalid character in exponent");
unsignedExponent = unsignedExponent * 10 + value;
if (unsignedExponent > 32767) {
@@ -322,10 +326,9 @@ totalExponent(StringRef::iterator p, StringRef::iterator end,
return exponent;
}
-static StringRef::iterator
+static Expected<StringRef::iterator>
skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end,
- StringRef::iterator *dot)
-{
+ StringRef::iterator *dot) {
StringRef::iterator p = begin;
*dot = end;
while (p != end && *p == '0')
@@ -334,7 +337,8 @@ skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end,
if (p != end && *p == '.') {
*dot = p++;
- assert(end - begin != 1 && "Significand has no digits");
+ if (end - begin == 1)
+ return createError("Significand has no digits");
while (p != end && *p == '0')
p++;
@@ -363,12 +367,14 @@ struct decimalInfo {
int normalizedExponent;
};
-static void
-interpretDecimal(StringRef::iterator begin, StringRef::iterator end,
- decimalInfo *D)
-{
+static Error interpretDecimal(StringRef::iterator begin,
+ StringRef::iterator end, decimalInfo *D) {
StringRef::iterator dot = end;
- StringRef::iterator p = skipLeadingZeroesAndAnyDot (begin, end, &dot);
+
+ auto PtrOrErr = skipLeadingZeroesAndAnyDot(begin, end, &dot);
+ if (!PtrOrErr)
+ return PtrOrErr.takeError();
+ StringRef::iterator p = *PtrOrErr;
D->firstSigDigit = p;
D->exponent = 0;
@@ -376,7 +382,8 @@ interpretDecimal(StringRef::iterator begin, StringRef::iterator end,
for (; p != end; ++p) {
if (*p == '.') {
- assert(dot == end && "String contains multiple dots");
+ if (dot != end)
+ return createError("String contains multiple dots");
dot = p++;
if (p == end)
break;
@@ -386,12 +393,18 @@ interpretDecimal(StringRef::iterator begin, StringRef::iterator end,
}
if (p != end) {
- assert((*p == 'e' || *p == 'E') && "Invalid character in significand");
- assert(p != begin && "Significand has no digits");
- assert((dot == end || p - begin != 1) && "Significand has no digits");
+ if (*p != 'e' && *p != 'E')
+ return createError("Invalid character in significand");
+ if (p == begin)
+ return createError("Significand has no digits");
+ if (dot != end && p - begin == 1)
+ return createError("Significand has no digits");
/* p points to the first non-digit in the string */
- D->exponent = readExponent(p + 1, end);
+ auto ExpOrErr = readExponent(p + 1, end);
+ if (!ExpOrErr)
+ return ExpOrErr.takeError();
+ D->exponent = *ExpOrErr;
/* Implied decimal point? */
if (dot == end)
@@ -417,15 +430,15 @@ interpretDecimal(StringRef::iterator begin, StringRef::iterator end,
}
D->lastSigDigit = p;
+ return Error::success();
}
/* Return the trailing fraction of a hexadecimal number.
DIGITVALUE is the first hex digit of the fraction, P points to
the next digit. */
-static lostFraction
+static Expected<lostFraction>
trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end,
- unsigned int digitValue)
-{
+ unsigned int digitValue) {
unsigned int hexDigit;
/* If the first trailing digit isn't 0 or 8 we can work out the
@@ -439,7 +452,8 @@ trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end,
while (p != end && (*p == '0' || *p == '.'))
p++;
- assert(p != end && "Invalid trailing hexadecimal fraction!");
+ if (p == end)
+ return createError("Invalid trailing hexadecimal fraction!");
hexDigit = hexDigitValue(*p);
@@ -978,7 +992,7 @@ IEEEFloat::integerPart IEEEFloat::subtractSignificand(const IEEEFloat &rhs,
on to the full-precision result of the multiplication. Returns the
lost fraction. */
lostFraction IEEEFloat::multiplySignificand(const IEEEFloat &rhs,
- const IEEEFloat *addend) {
+ IEEEFloat addend) {
unsigned int omsb; // One, not zero, based MSB.
unsigned int partsCount, newPartsCount, precision;
integerPart *lhsSignificand;
@@ -1022,7 +1036,7 @@ lostFraction IEEEFloat::multiplySignificand(const IEEEFloat &rhs,
// toward left by two bits, and adjust exponent accordingly.
exponent += 2;
- if (addend && addend->isNonZero()) {
+ if (addend.isNonZero()) {
// The intermediate result of the multiplication has "2 * precision"
// signicant bit; adjust the addend to be consistent with mul result.
//
@@ -1051,7 +1065,10 @@ lostFraction IEEEFloat::multiplySignificand(const IEEEFloat &rhs,
significand.parts = fullSignificand;
semantics = &extendedSemantics;
- IEEEFloat extendedAddend(*addend);
+ // Make a copy so we can convert it to the extended semantics.
+ // Note that we cannot convert the addend directly, as the extendedSemantics
+ // is a local variable (which we take a reference to).
+ IEEEFloat extendedAddend(addend);
status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored);
assert(status == opOK);
(void)status;
@@ -1106,6 +1123,10 @@ lostFraction IEEEFloat::multiplySignificand(const IEEEFloat &rhs,
return lost_fraction;
}
+lostFraction IEEEFloat::multiplySignificand(const IEEEFloat &rhs) {
+ return multiplySignificand(rhs, IEEEFloat(*semantics));
+}
+
/* Multiply the significands of LHS and RHS to DST. */
lostFraction IEEEFloat::divideSignificand(const IEEEFloat &rhs) {
unsigned int bit, i, partsCount;
@@ -1484,22 +1505,19 @@ lostFraction IEEEFloat::addOrSubtractSignificand(const IEEEFloat &rhs,
/* Subtraction is more subtle than one might naively expect. */
if (subtract) {
IEEEFloat temp_rhs(rhs);
- bool reverse;
- if (bits == 0) {
- reverse = compareAbsoluteValue(temp_rhs) == cmpLessThan;
+ if (bits == 0)
lost_fraction = lfExactlyZero;
- } else if (bits > 0) {
+ else if (bits > 0) {
lost_fraction = temp_rhs.shiftSignificandRight(bits - 1);
shiftSignificandLeft(1);
- reverse = false;
} else {
lost_fraction = shiftSignificandRight(-bits - 1);
temp_rhs.shiftSignificandLeft(1);
- reverse = true;
}
- if (reverse) {
+ // Should we reverse the subtraction.
+ if (compareAbsoluteValue(temp_rhs) == cmpLessThan) {
carry = temp_rhs.subtractSignificand
(*this, lost_fraction != lfExactlyZero);
copySignificand(temp_rhs);
@@ -1714,7 +1732,7 @@ IEEEFloat::opStatus IEEEFloat::multiply(const IEEEFloat &rhs,
fs = multiplySpecials(rhs);
if (isFiniteNonZero()) {
- lostFraction lost_fraction = multiplySignificand(rhs, nullptr);
+ lostFraction lost_fraction = multiplySignificand(rhs);
fs = normalize(rounding_mode, lost_fraction);
if (lost_fraction != lfExactlyZero)
fs = (opStatus) (fs | opInexact);
@@ -1815,7 +1833,7 @@ IEEEFloat::opStatus IEEEFloat::fusedMultiplyAdd(const IEEEFloat &multiplicand,
addend.isFinite()) {
lostFraction lost_fraction;
- lost_fraction = multiplySignificand(multiplicand, &addend);
+ lost_fraction = multiplySignificand(multiplicand, addend);
fs = normalize(rounding_mode, lost_fraction);
if (lost_fraction != lfExactlyZero)
fs = (opStatus) (fs | opInexact);
@@ -2302,7 +2320,7 @@ IEEEFloat::convertFromZeroExtendedInteger(const integerPart *parts,
return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode);
}
-IEEEFloat::opStatus
+Expected<IEEEFloat::opStatus>
IEEEFloat::convertFromHexadecimalString(StringRef s,
roundingMode rounding_mode) {
lostFraction lost_fraction = lfExactlyZero;
@@ -2320,14 +2338,18 @@ IEEEFloat::convertFromHexadecimalString(StringRef s,
StringRef::iterator begin = s.begin();
StringRef::iterator end = s.end();
StringRef::iterator dot;
- StringRef::iterator p = skipLeadingZeroesAndAnyDot(begin, end, &dot);
+ auto PtrOrErr = skipLeadingZeroesAndAnyDot(begin, end, &dot);
+ if (!PtrOrErr)
+ return PtrOrErr.takeError();
+ StringRef::iterator p = *PtrOrErr;
StringRef::iterator firstSignificantDigit = p;
while (p != end) {
integerPart hex_value;
if (*p == '.') {
- assert(dot == end && "String contains multiple dots");
+ if (dot != end)
+ return createError("String contains multiple dots");
dot = p++;
continue;
}
@@ -2344,16 +2366,23 @@ IEEEFloat::convertFromHexadecimalString(StringRef s,
hex_value <<= bitPos % integerPartWidth;
significand[bitPos / integerPartWidth] |= hex_value;
} else if (!computedTrailingFraction) {
- lost_fraction = trailingHexadecimalFraction(p, end, hex_value);
+ auto FractOrErr = trailingHexadecimalFraction(p, end, hex_value);
+ if (!FractOrErr)
+ return FractOrErr.takeError();
+ lost_fraction = *FractOrErr;
computedTrailingFraction = true;
}
}
/* Hex floats require an exponent but not a hexadecimal point. */
- assert(p != end && "Hex strings require an exponent");
- assert((*p == 'p' || *p == 'P') && "Invalid character in significand");
- assert(p != begin && "Significand has no digits");
- assert((dot == end || p - begin != 1) && "Significand has no digits");
+ if (p == end)
+ return createError("Hex strings require an exponent");
+ if (*p != 'p' && *p != 'P')
+ return createError("Invalid character in significand");
+ if (p == begin)
+ return createError("Significand has no digits");
+ if (dot != end && p - begin == 1)
+ return createError("Significand has no digits");
/* Ignore the exponent if we are zero. */
if (p != firstSignificantDigit) {
@@ -2376,7 +2405,10 @@ IEEEFloat::convertFromHexadecimalString(StringRef s,
expAdjustment -= partsCount * integerPartWidth;
/* Adjust for the given exponent. */
- exponent = totalExponent(p + 1, end, expAdjustment);
+ auto ExpOrErr = totalExponent(p + 1, end, expAdjustment);
+ if (!ExpOrErr)
+ return ExpOrErr.takeError();
+ exponent = *ExpOrErr;
}
return normalize(rounding_mode, lost_fraction);
@@ -2424,7 +2456,7 @@ IEEEFloat::roundSignificandWithExponent(const integerPart *decSigParts,
if (exp >= 0) {
/* multiplySignificand leaves the precision-th bit set to 1. */
- calcLostFraction = decSig.multiplySignificand(pow5, nullptr);
+ calcLostFraction = decSig.multiplySignificand(pow5);
powHUerr = powStatus != opOK;
} else {
calcLostFraction = decSig.divideSignificand(pow5);
@@ -2467,14 +2499,15 @@ IEEEFloat::roundSignificandWithExponent(const integerPart *decSigParts,
}
}
-IEEEFloat::opStatus
+Expected<IEEEFloat::opStatus>
IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) {
decimalInfo D;
opStatus fs;
/* Scan the text. */
StringRef::iterator p = str.begin();
- interpretDecimal(p, str.end(), &D);
+ if (Error Err = interpretDecimal(p, str.end(), &D))
+ return std::move(Err);
/* Handle the quick cases. First the case of no significant digits,
i.e. zero, and then exponents that are obviously too large or too
@@ -2557,7 +2590,10 @@ IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) {
}
}
decValue = decDigitValue(*p++);
- assert(decValue < 10U && "Invalid character in significand");
+ if (decValue >= 10U) {
+ delete[] decSignificand;
+ return createError("Invalid character in significand");
+ }
multiplier *= 10;
val = val * 10 + decValue;
/* The maximum number that can be multiplied by ten with any
@@ -2608,9 +2644,10 @@ bool IEEEFloat::convertFromStringSpecials(StringRef str) {
return false;
}
-IEEEFloat::opStatus IEEEFloat::convertFromString(StringRef str,
- roundingMode rounding_mode) {
- assert(!str.empty() && "Invalid string length");
+Expected<IEEEFloat::opStatus>
+IEEEFloat::convertFromString(StringRef str, roundingMode rounding_mode) {
+ if (str.empty())
+ return createError("Invalid string length");
// Handle special cases.
if (convertFromStringSpecials(str))
@@ -2623,11 +2660,13 @@ IEEEFloat::opStatus IEEEFloat::convertFromString(StringRef str,
if (*p == '-' || *p == '+') {
p++;
slen--;
- assert(slen && "String has no digits");
+ if (!slen)
+ return createError("String has no digits");
}
if (slen >= 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
- assert(slen - 2 && "Invalid string");
+ if (slen == 2)
+ return createError("Invalid string");
return convertFromHexadecimalString(StringRef(p + 2, slen - 2),
rounding_mode);
}
@@ -4315,8 +4354,8 @@ APInt DoubleAPFloat::bitcastToAPInt() const {
return APInt(128, 2, Data);
}
-APFloat::opStatus DoubleAPFloat::convertFromString(StringRef S,
- roundingMode RM) {
+Expected<APFloat::opStatus> DoubleAPFloat::convertFromString(StringRef S,
+ roundingMode RM) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy);
auto Ret = Tmp.convertFromString(S, RM);
@@ -4463,7 +4502,8 @@ APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) {
llvm_unreachable("Unexpected semantics");
}
-APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) {
+Expected<APFloat::opStatus> APFloat::convertFromString(StringRef Str,
+ roundingMode RM) {
APFLOAT_DISPATCH_ON_SEMANTICS(convertFromString(Str, RM));
}
@@ -4477,7 +4517,9 @@ hash_code hash_value(const APFloat &Arg) {
APFloat::APFloat(const fltSemantics &Semantics, StringRef S)
: APFloat(Semantics) {
- convertFromString(S, rmNearestTiesToEven);
+ auto StatusOrErr = convertFromString(S, rmNearestTiesToEven);
+ assert(StatusOrErr && "Invalid floating point representation");
+ consumeError(StatusOrErr.takeError());
}
APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics,
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 758fe8b4f866..9b9cd70078b3 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -187,7 +187,7 @@ APInt& APInt::operator--() {
return clearUnusedBits();
}
-/// Adds the RHS APint to this APInt.
+/// Adds the RHS APInt to this APInt.
/// @returns this, after addition of RHS.
/// Addition assignment operator.
APInt& APInt::operator+=(const APInt& RHS) {
@@ -884,6 +884,31 @@ APInt APInt::trunc(unsigned width) const {
return Result;
}
+// Truncate to new width with unsigned saturation.
+APInt APInt::truncUSat(unsigned width) const {
+ assert(width < BitWidth && "Invalid APInt Truncate request");
+ assert(width && "Can't truncate to 0 bits");
+
+ // Can we just losslessly truncate it?
+ if (isIntN(width))
+ return trunc(width);
+ // If not, then just return the new limit.
+ return APInt::getMaxValue(width);
+}
+
+// Truncate to new width with signed saturation.
+APInt APInt::truncSSat(unsigned width) const {
+ assert(width < BitWidth && "Invalid APInt Truncate request");
+ assert(width && "Can't truncate to 0 bits");
+
+ // Can we just losslessly truncate it?
+ if (isSignedIntN(width))
+ return trunc(width);
+ // If not, then just return the new limits.
+ return isNegative() ? APInt::getSignedMinValue(width)
+ : APInt::getSignedMaxValue(width);
+}
+
// Sign extend to a new width.
APInt APInt::sext(unsigned Width) const {
assert(Width > BitWidth && "Invalid APInt SignExtend request");
@@ -2048,6 +2073,46 @@ APInt APInt::usub_sat(const APInt &RHS) const {
return APInt(BitWidth, 0);
}
+APInt APInt::smul_sat(const APInt &RHS) const {
+ bool Overflow;
+ APInt Res = smul_ov(RHS, Overflow);
+ if (!Overflow)
+ return Res;
+
+ // The result is negative if one and only one of inputs is negative.
+ bool ResIsNegative = isNegative() ^ RHS.isNegative();
+
+ return ResIsNegative ? APInt::getSignedMinValue(BitWidth)
+ : APInt::getSignedMaxValue(BitWidth);
+}
+
+APInt APInt::umul_sat(const APInt &RHS) const {
+ bool Overflow;
+ APInt Res = umul_ov(RHS, Overflow);
+ if (!Overflow)
+ return Res;
+
+ return APInt::getMaxValue(BitWidth);
+}
+
+APInt APInt::sshl_sat(const APInt &RHS) const {
+ bool Overflow;
+ APInt Res = sshl_ov(RHS, Overflow);
+ if (!Overflow)
+ return Res;
+
+ return isNegative() ? APInt::getSignedMinValue(BitWidth)
+ : APInt::getSignedMaxValue(BitWidth);
+}
+
+APInt APInt::ushl_sat(const APInt &RHS) const {
+ bool Overflow;
+ APInt Res = ushl_ov(RHS, Overflow);
+ if (!Overflow)
+ return Res;
+
+ return APInt::getMaxValue(BitWidth);
+}
void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) {
// Check our assumptions here
@@ -2790,7 +2855,7 @@ APInt llvm::APIntOps::RoundingSDiv(const APInt &A, const APInt &B,
return Quo;
return Quo + 1;
}
- // Currently sdiv rounds twards zero.
+ // Currently sdiv rounds towards zero.
case APInt::Rounding::TOWARD_ZERO:
return A.sdiv(B);
}
@@ -2933,7 +2998,7 @@ llvm::APIntOps::SolveQuadraticEquationWrap(APInt A, APInt B, APInt C,
APInt Q = SQ * SQ;
bool InexactSQ = Q != D;
// The calculated SQ may actually be greater than the exact (non-integer)
- // value. If that's the case, decremement SQ to get a value that is lower.
+ // value. If that's the case, decrement SQ to get a value that is lower.
if (Q.sgt(D))
SQ -= 1;
@@ -2987,6 +3052,14 @@ llvm::APIntOps::SolveQuadraticEquationWrap(APInt A, APInt B, APInt C,
return X;
}
+Optional<unsigned>
+llvm::APIntOps::GetMostSignificantDifferentBit(const APInt &A, const APInt &B) {
+ assert(A.getBitWidth() == B.getBitWidth() && "Must have the same bitwidth");
+ if (A == B)
+ return llvm::None;
+ return A.getBitWidth() - ((A ^ B).countLeadingZeros() + 1);
+}
+
/// StoreIntToMemory - Fills the StoreBytes bytes of memory starting from Dst
/// with the integer held in IntVal.
void llvm::StoreIntToMemory(const APInt &IntVal, uint8_t *Dst,
diff --git a/llvm/lib/Support/ARMAttributeParser.cpp b/llvm/lib/Support/ARMAttributeParser.cpp
index df50fff720cd..8a89f4c45fb9 100644
--- a/llvm/lib/Support/ARMAttributeParser.cpp
+++ b/llvm/lib/Support/ARMAttributeParser.cpp
@@ -73,9 +73,9 @@ ARMAttributeParser::DisplayRoutines[] = {
uint64_t ARMAttributeParser::ParseInteger(const uint8_t *Data,
uint32_t &Offset) {
- unsigned Length;
- uint64_t Value = decodeULEB128(Data + Offset, &Length);
- Offset = Offset + Length;
+ unsigned DecodeLength;
+ uint64_t Value = decodeULEB128(Data + Offset, &DecodeLength);
+ Offset += DecodeLength;
return Value;
}
@@ -587,9 +587,9 @@ void ARMAttributeParser::nodefaults(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ParseIndexList(const uint8_t *Data, uint32_t &Offset,
SmallVectorImpl<uint8_t> &IndexList) {
for (;;) {
- unsigned Length;
- uint64_t Value = decodeULEB128(Data + Offset, &Length);
- Offset = Offset + Length;
+ unsigned DecodeLength;
+ uint64_t Value = decodeULEB128(Data + Offset, &DecodeLength);
+ Offset += DecodeLength;
if (Value == 0)
break;
IndexList.push_back(Value);
@@ -599,9 +599,9 @@ void ARMAttributeParser::ParseIndexList(const uint8_t *Data, uint32_t &Offset,
void ARMAttributeParser::ParseAttributeList(const uint8_t *Data,
uint32_t &Offset, uint32_t Length) {
while (Offset < Length) {
- unsigned Length;
- uint64_t Tag = decodeULEB128(Data + Offset, &Length);
- Offset += Length;
+ unsigned DecodeLength;
+ uint64_t Tag = decodeULEB128(Data + Offset, &DecodeLength);
+ Offset += DecodeLength;
bool Handled = false;
for (unsigned AHI = 0, AHE = array_lengthof(DisplayRoutines);
diff --git a/llvm/lib/Support/ARMTargetParser.cpp b/llvm/lib/Support/ARMTargetParser.cpp
index ce5daa7fe58c..f2c22fd93c8b 100644
--- a/llvm/lib/Support/ARMTargetParser.cpp
+++ b/llvm/lib/Support/ARMTargetParser.cpp
@@ -174,8 +174,6 @@ bool ARM::getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features) {
// under FPURestriction::None, which is the only FPURestriction in
// which they would be valid (since FPURestriction::SP doesn't
// exist).
-
- {"+fpregs", "-fpregs", FPUVersion::VFPV2, FPURestriction::SP_D16},
{"+vfp2", "-vfp2", FPUVersion::VFPV2, FPURestriction::D16},
{"+vfp2sp", "-vfp2sp", FPUVersion::VFPV2, FPURestriction::SP_D16},
{"+vfp3", "-vfp3", FPUVersion::VFPV3, FPURestriction::None},
diff --git a/llvm/lib/Support/BinaryStreamReader.cpp b/llvm/lib/Support/BinaryStreamReader.cpp
index b17786593bde..a0434bdc6115 100644
--- a/llvm/lib/Support/BinaryStreamReader.cpp
+++ b/llvm/lib/Support/BinaryStreamReader.cpp
@@ -139,10 +139,10 @@ Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
return Error::success();
}
-Error BinaryStreamReader::readSubstream(BinarySubstreamRef &Stream,
- uint32_t Size) {
- Stream.Offset = getOffset();
- return readStreamRef(Stream.StreamData, Size);
+Error BinaryStreamReader::readSubstream(BinarySubstreamRef &Ref,
+ uint32_t Length) {
+ Ref.Offset = getOffset();
+ return readStreamRef(Ref.StreamData, Length);
}
Error BinaryStreamReader::skip(uint32_t Amount) {
diff --git a/llvm/lib/Support/CRC.cpp b/llvm/lib/Support/CRC.cpp
index 7c008d3b599d..a3dba1a3aa10 100644
--- a/llvm/lib/Support/CRC.cpp
+++ b/llvm/lib/Support/CRC.cpp
@@ -25,7 +25,7 @@
using namespace llvm;
-#if LLVM_ENABLE_ZLIB == 0 || !HAVE_ZLIB_H
+#if !LLVM_ENABLE_ZLIB
static const uint32_t CRCTable[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp
index 620f7ffd4c9f..cb73380ba383 100644
--- a/llvm/lib/Support/CommandLine.cpp
+++ b/llvm/lib/Support/CommandLine.cpp
@@ -24,11 +24,13 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@@ -37,9 +39,11 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <map>
+#include <string>
using namespace llvm;
using namespace cl;
@@ -53,6 +57,8 @@ namespace cl {
template class basic_parser<bool>;
template class basic_parser<boolOrDefault>;
template class basic_parser<int>;
+template class basic_parser<long>;
+template class basic_parser<long long>;
template class basic_parser<unsigned>;
template class basic_parser<unsigned long>;
template class basic_parser<unsigned long long>;
@@ -78,6 +84,8 @@ void basic_parser_impl::anchor() {}
void parser<bool>::anchor() {}
void parser<boolOrDefault>::anchor() {}
void parser<int>::anchor() {}
+void parser<long>::anchor() {}
+void parser<long long>::anchor() {}
void parser<unsigned>::anchor() {}
void parser<unsigned long>::anchor() {}
void parser<unsigned long long>::anchor() {}
@@ -88,21 +96,26 @@ void parser<char>::anchor() {}
//===----------------------------------------------------------------------===//
-static StringRef ArgPrefix = " -";
-static StringRef ArgPrefixLong = " --";
+const static size_t DefaultPad = 2;
+
+static StringRef ArgPrefix = "-";
+static StringRef ArgPrefixLong = "--";
static StringRef ArgHelpPrefix = " - ";
-static size_t argPlusPrefixesSize(StringRef ArgName) {
+static size_t argPlusPrefixesSize(StringRef ArgName, size_t Pad = DefaultPad) {
size_t Len = ArgName.size();
if (Len == 1)
- return Len + ArgPrefix.size() + ArgHelpPrefix.size();
- return Len + ArgPrefixLong.size() + ArgHelpPrefix.size();
+ return Len + Pad + ArgPrefix.size() + ArgHelpPrefix.size();
+ return Len + Pad + ArgPrefixLong.size() + ArgHelpPrefix.size();
}
-static StringRef argPrefix(StringRef ArgName) {
- if (ArgName.size() == 1)
- return ArgPrefix;
- return ArgPrefixLong;
+static SmallString<8> argPrefix(StringRef ArgName, size_t Pad = DefaultPad) {
+ SmallString<8> Prefix;
+ for (size_t I = 0; I < Pad; ++I) {
+ Prefix.push_back(' ');
+ }
+ Prefix.append(ArgName.size() > 1 ? ArgPrefixLong : ArgPrefix);
+ return Prefix;
}
// Option predicates...
@@ -119,13 +132,14 @@ namespace {
class PrintArg {
StringRef ArgName;
+ size_t Pad;
public:
- PrintArg(StringRef ArgName) : ArgName(ArgName) {}
- friend raw_ostream &operator<<(raw_ostream &OS, const PrintArg&);
+ PrintArg(StringRef ArgName, size_t Pad = DefaultPad) : ArgName(ArgName), Pad(Pad) {}
+ friend raw_ostream &operator<<(raw_ostream &OS, const PrintArg &);
};
raw_ostream &operator<<(raw_ostream &OS, const PrintArg& Arg) {
- OS << argPrefix(Arg.ArgName) << Arg.ArgName;
+ OS << argPrefix(Arg.ArgName, Arg.Pad) << Arg.ArgName;
return OS;
}
@@ -173,7 +187,7 @@ public:
// 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) {
+ for (auto *Sub : RegisteredSubCommands) {
if (SC == Sub)
continue;
addLiteralOption(Opt, Sub, Name);
@@ -229,7 +243,7 @@ public:
// 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) {
+ for (auto *Sub : RegisteredSubCommands) {
if (SC == Sub)
continue;
addOption(O, Sub);
@@ -304,7 +318,7 @@ public:
}
bool hasOptions() const {
- for (const auto &S : RegisteredSubCommands) {
+ for (const auto *S : RegisteredSubCommands) {
if (hasOptions(*S))
return true;
}
@@ -1037,14 +1051,16 @@ static bool hasUTF8ByteOrderMark(ArrayRef<char> S) {
return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf');
}
-static bool ExpandResponseFile(StringRef FName, StringSaver &Saver,
- TokenizerCallback Tokenizer,
- SmallVectorImpl<const char *> &NewArgv,
- bool MarkEOLs, bool RelativeNames) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
- MemoryBuffer::getFile(FName);
+// FName must be an absolute path.
+static llvm::Error ExpandResponseFile(
+ StringRef FName, StringSaver &Saver, TokenizerCallback Tokenizer,
+ SmallVectorImpl<const char *> &NewArgv, bool MarkEOLs, bool RelativeNames,
+ llvm::vfs::FileSystem &FS) {
+ assert(sys::path::is_absolute(FName));
+ llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
+ FS.getBufferForFile(FName);
if (!MemBufOrErr)
- return false;
+ return llvm::errorCodeToError(MemBufOrErr.getError());
MemoryBuffer &MemBuf = *MemBufOrErr.get();
StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize());
@@ -1053,7 +1069,8 @@ static bool ExpandResponseFile(StringRef FName, StringSaver &Saver,
std::string UTF8Buf;
if (hasUTF16ByteOrderMark(BufRef)) {
if (!convertUTF16ToUTF8String(BufRef, UTF8Buf))
- return false;
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "Could not convert UTF16 to UTF8");
Str = StringRef(UTF8Buf);
}
// If we see UTF-8 BOM sequence at the beginning of a file, we shall remove
@@ -1065,41 +1082,40 @@ static bool ExpandResponseFile(StringRef FName, StringSaver &Saver,
// Tokenize the contents into NewArgv.
Tokenizer(Str, Saver, NewArgv, MarkEOLs);
+ if (!RelativeNames)
+ return Error::success();
+ llvm::StringRef BasePath = llvm::sys::path::parent_path(FName);
// If names of nested response files should be resolved relative to including
// file, replace the included response file names with their full paths
// obtained by required resolution.
- if (RelativeNames)
- for (unsigned I = 0; I < NewArgv.size(); ++I)
- if (NewArgv[I]) {
- StringRef Arg = NewArgv[I];
- if (Arg.front() == '@') {
- StringRef FileName = Arg.drop_front();
- if (llvm::sys::path::is_relative(FileName)) {
- SmallString<128> ResponseFile;
- ResponseFile.append(1, '@');
- if (llvm::sys::path::is_relative(FName)) {
- SmallString<128> curr_dir;
- llvm::sys::fs::current_path(curr_dir);
- ResponseFile.append(curr_dir.str());
- }
- llvm::sys::path::append(
- ResponseFile, llvm::sys::path::parent_path(FName), FileName);
- NewArgv[I] = Saver.save(ResponseFile.c_str()).data();
- }
- }
- }
+ for (auto &Arg : NewArgv) {
+ // Skip non-rsp file arguments.
+ if (!Arg || Arg[0] != '@')
+ continue;
- return true;
+ StringRef FileName(Arg + 1);
+ // Skip if non-relative.
+ if (!llvm::sys::path::is_relative(FileName))
+ continue;
+
+ SmallString<128> ResponseFile;
+ ResponseFile.push_back('@');
+ ResponseFile.append(BasePath);
+ llvm::sys::path::append(ResponseFile, FileName);
+ Arg = Saver.save(ResponseFile.c_str()).data();
+ }
+ return Error::success();
}
/// Expand response files on a command line recursively using the given
/// StringSaver and tokenization strategy.
bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
- SmallVectorImpl<const char *> &Argv,
- bool MarkEOLs, bool RelativeNames) {
+ SmallVectorImpl<const char *> &Argv, bool MarkEOLs,
+ bool RelativeNames, llvm::vfs::FileSystem &FS,
+ llvm::Optional<llvm::StringRef> CurrentDir) {
bool AllExpanded = true;
struct ResponseFileRecord {
- const char *File;
+ std::string File;
size_t End;
};
@@ -1133,8 +1149,31 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
}
const char *FName = Arg + 1;
- auto IsEquivalent = [FName](const ResponseFileRecord &RFile) {
- return sys::fs::equivalent(RFile.File, FName);
+ // Note that CurrentDir is only used for top-level rsp files, the rest will
+ // always have an absolute path deduced from the containing file.
+ SmallString<128> CurrDir;
+ if (llvm::sys::path::is_relative(FName)) {
+ if (!CurrentDir)
+ llvm::sys::fs::current_path(CurrDir);
+ else
+ CurrDir = *CurrentDir;
+ llvm::sys::path::append(CurrDir, FName);
+ FName = CurrDir.c_str();
+ }
+ auto IsEquivalent = [FName, &FS](const ResponseFileRecord &RFile) {
+ llvm::ErrorOr<llvm::vfs::Status> LHS = FS.status(FName);
+ if (!LHS) {
+ // TODO: The error should be propagated up the stack.
+ llvm::consumeError(llvm::errorCodeToError(LHS.getError()));
+ return false;
+ }
+ llvm::ErrorOr<llvm::vfs::Status> RHS = FS.status(RFile.File);
+ if (!RHS) {
+ // TODO: The error should be propagated up the stack.
+ llvm::consumeError(llvm::errorCodeToError(RHS.getError()));
+ return false;
+ }
+ return LHS->equivalent(*RHS);
};
// Check for recursive response files.
@@ -1149,10 +1188,13 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
// Replace this response file argument with the tokenization of its
// contents. Nested response files are expanded in subsequent iterations.
SmallVector<const char *, 0> ExpandedArgv;
- if (!ExpandResponseFile(FName, Saver, Tokenizer, ExpandedArgv, MarkEOLs,
- RelativeNames)) {
+ if (llvm::Error Err =
+ ExpandResponseFile(FName, Saver, Tokenizer, ExpandedArgv, MarkEOLs,
+ RelativeNames, FS)) {
// We couldn't read this file, so we leave it in the argument stream and
// move on.
+ // TODO: The error should be propagated up the stack.
+ llvm::consumeError(std::move(Err));
AllExpanded = false;
++I;
continue;
@@ -1180,9 +1222,20 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
bool cl::readConfigFile(StringRef CfgFile, StringSaver &Saver,
SmallVectorImpl<const char *> &Argv) {
- if (!ExpandResponseFile(CfgFile, Saver, cl::tokenizeConfigFile, Argv,
- /*MarkEOLs*/ false, /*RelativeNames*/ true))
+ SmallString<128> AbsPath;
+ if (sys::path::is_relative(CfgFile)) {
+ llvm::sys::fs::current_path(AbsPath);
+ llvm::sys::path::append(AbsPath, CfgFile);
+ CfgFile = AbsPath.str();
+ }
+ if (llvm::Error Err =
+ ExpandResponseFile(CfgFile, Saver, cl::tokenizeConfigFile, Argv,
+ /*MarkEOLs*/ false, /*RelativeNames*/ true,
+ *llvm::vfs::getRealFileSystem())) {
+ // TODO: The error should be propagated up the stack.
+ llvm::consumeError(std::move(Err));
return false;
+ }
return ExpandResponseFiles(Saver, cl::tokenizeConfigFile, Argv,
/*MarkEOLs*/ false, /*RelativeNames*/ true);
}
@@ -1447,7 +1500,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
if (NearestHandler) {
// If we know a near match, report it as well.
*Errs << ProgramName << ": Did you mean '"
- << PrintArg(NearestHandlerString) << "'?\n";
+ << PrintArg(NearestHandlerString, 0) << "'?\n";
}
ErrorParsing = true;
@@ -1601,7 +1654,7 @@ bool Option::error(const Twine &Message, StringRef ArgName, raw_ostream &Errs) {
if (ArgName.empty())
Errs << HelpStr; // Be nice for positional arguments
else
- Errs << GlobalParser->ProgramName << ": for the " << PrintArg(ArgName);
+ Errs << GlobalParser->ProgramName << ": for the " << PrintArg(ArgName, 0);
Errs << " option: " << Message << "\n";
return true;
@@ -1757,6 +1810,24 @@ bool parser<int>::parse(Option &O, StringRef ArgName, StringRef Arg,
return false;
}
+// parser<long> implementation
+//
+bool parser<long>::parse(Option &O, StringRef ArgName, StringRef Arg,
+ long &Value) {
+ if (Arg.getAsInteger(0, Value))
+ return O.error("'" + Arg + "' value invalid for long argument!");
+ return false;
+}
+
+// parser<long long> implementation
+//
+bool parser<long long>::parse(Option &O, StringRef ArgName, StringRef Arg,
+ long long &Value) {
+ if (Arg.getAsInteger(0, Value))
+ return O.error("'" + Arg + "' value invalid for llong argument!");
+ return false;
+}
+
// parser<unsigned> implementation
//
bool parser<unsigned>::parse(Option &O, StringRef ArgName, StringRef Arg,
@@ -1966,6 +2037,8 @@ void generic_parser_base::printGenericOptionDiff(
PRINT_OPT_DIFF(bool)
PRINT_OPT_DIFF(boolOrDefault)
PRINT_OPT_DIFF(int)
+PRINT_OPT_DIFF(long)
+PRINT_OPT_DIFF(long long)
PRINT_OPT_DIFF(unsigned)
PRINT_OPT_DIFF(unsigned long)
PRINT_OPT_DIFF(unsigned long long)
@@ -2039,7 +2112,7 @@ static void sortOpts(StringMap<Option *> &OptMap,
static void
sortSubCommands(const SmallPtrSetImpl<SubCommand *> &SubMap,
SmallVectorImpl<std::pair<const char *, SubCommand *>> &Subs) {
- for (const auto &S : SubMap) {
+ for (auto *S : SubMap) {
if (S->getName().empty())
continue;
Subs.push_back(std::make_pair(S->getName().data(), S));
@@ -2363,6 +2436,28 @@ static VersionPrinterTy OverrideVersionPrinter = nullptr;
static std::vector<VersionPrinterTy> *ExtraVersionPrinters = nullptr;
+#if defined(__GNUC__)
+// GCC and GCC-compatible compilers define __OPTIMIZE__ when optimizations are
+// enabled.
+# if defined(__OPTIMIZE__)
+# define LLVM_IS_DEBUG_BUILD 0
+# else
+# define LLVM_IS_DEBUG_BUILD 1
+# endif
+#elif defined(_MSC_VER)
+// MSVC doesn't have a predefined macro indicating if optimizations are enabled.
+// Use _DEBUG instead. This macro actually corresponds to the choice between
+// debug and release CRTs, but it is a reasonable proxy.
+# if defined(_DEBUG)
+# define LLVM_IS_DEBUG_BUILD 1
+# else
+# define LLVM_IS_DEBUG_BUILD 0
+# endif
+#else
+// Otherwise, for an unknown compiler, assume this is an optimized build.
+# define LLVM_IS_DEBUG_BUILD 0
+#endif
+
namespace {
class VersionPrinter {
public:
@@ -2378,7 +2473,7 @@ public:
OS << " " << LLVM_VERSION_INFO;
#endif
OS << "\n ";
-#ifndef __OPTIMIZE__
+#if LLVM_IS_DEBUG_BUILD
OS << "DEBUG build";
#else
OS << "Optimized build";
diff --git a/llvm/lib/Support/Compression.cpp b/llvm/lib/Support/Compression.cpp
index 97d5ffaadf82..4165a2740cd0 100644
--- a/llvm/lib/Support/Compression.cpp
+++ b/llvm/lib/Support/Compression.cpp
@@ -17,13 +17,13 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
-#if LLVM_ENABLE_ZLIB == 1 && HAVE_ZLIB_H
+#if LLVM_ENABLE_ZLIB
#include <zlib.h>
#endif
using namespace llvm;
-#if LLVM_ENABLE_ZLIB == 1 && HAVE_LIBZ
+#if LLVM_ENABLE_ZLIB
static Error createError(StringRef Err) {
return make_error<StringError>(Err, inconvertibleErrorCode());
}
diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp
index 9d13fce9cc52..b9031f52375c 100644
--- a/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -10,9 +10,17 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Signals.h"
#include "llvm/Support/ThreadLocal.h"
#include <mutex>
#include <setjmp.h>
+#ifdef _WIN32
+#include <excpt.h> // for GetExceptionInformation
+#endif
+#if LLVM_ON_UNIX
+#include <sysexits.h> // EX_IOERR
+#endif
+
using namespace llvm;
namespace {
@@ -54,7 +62,11 @@ public:
#endif
}
- void HandleCrash() {
+ // If the function ran by the CrashRecoveryContext crashes or fails, then
+ // 'RetCode' represents the returned error code, as if it was returned by a
+ // process. 'Context' represents the signal type on Unix; on Windows, it is
+ // the ExceptionContext.
+ void HandleCrash(int RetCode, uintptr_t Context) {
// Eliminate the current context entry, to avoid re-entering in case the
// cleanup code crashes.
CurrentContext->set(Next);
@@ -62,7 +74,10 @@ public:
assert(!Failed && "Crash recovery context already failed!");
Failed = true;
- // FIXME: Stash the backtrace.
+ if (CRC->DumpStackAndCleanupOnFailure)
+ sys::CleanupOnSignal(Context);
+
+ CRC->RetCode = RetCode;
// Jump back to the RunSafely we were called under.
longjmp(JumpBuffer, 1);
@@ -171,19 +186,32 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
static void installExceptionOrSignalHandlers() {}
static void uninstallExceptionOrSignalHandlers() {}
-bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
- if (!gCrashRecoveryEnabled) {
+// We need this function because the call to GetExceptionInformation() can only
+// occur inside the __except evaluation block
+static int ExceptionFilter(bool DumpStackAndCleanup,
+ _EXCEPTION_POINTERS *Except) {
+ if (DumpStackAndCleanup)
+ sys::CleanupOnSignal((uintptr_t)Except);
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+static bool InvokeFunctionCall(function_ref<void()> Fn,
+ bool DumpStackAndCleanup, int &RetCode) {
+ __try {
Fn();
- return true;
+ } __except (ExceptionFilter(DumpStackAndCleanup, GetExceptionInformation())) {
+ RetCode = GetExceptionCode();
+ return false;
}
+ return true;
+}
- bool Result = true;
- __try {
+bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
+ if (!gCrashRecoveryEnabled) {
Fn();
- } __except (1) { // Catch any exception.
- Result = false;
+ return true;
}
- return Result;
+ return InvokeFunctionCall(Fn, DumpStackAndCleanupOnFailure, RetCode);
}
#else // !_MSC_VER
@@ -237,7 +265,9 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
// implementation if we so choose.
// Handle the crash
- const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash();
+ const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(
+ (int)ExceptionInfo->ExceptionRecord->ExceptionCode,
+ reinterpret_cast<uintptr_t>(ExceptionInfo));
// Note that we don't actually get here because HandleCrash calls
// longjmp, which means the HandleCrash function never returns.
@@ -280,7 +310,7 @@ static void uninstallExceptionOrSignalHandlers() {
// crash recovery context, and install signal handlers to invoke HandleCrash on
// the active object.
//
-// This implementation does not to attempt to chain signal handlers in any
+// This implementation does not attempt to chain signal handlers in any
// reliable fashion -- if we get a signal outside of a crash recovery context we
// simply disable crash recovery and raise the signal again.
@@ -319,8 +349,16 @@ static void CrashRecoverySignalHandler(int Signal) {
sigaddset(&SigMask, Signal);
sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
+ // As per convention, -2 indicates a crash or timeout as opposed to failure to
+ // execute (see llvm/include/llvm/Support/Program.h)
+ int RetCode = -2;
+
+ // Don't consider a broken pipe as a crash (see clang/lib/Driver/Driver.cpp)
+ if (Signal == SIGPIPE)
+ RetCode = EX_IOERR;
+
if (CRCI)
- const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash();
+ const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(RetCode, Signal);
}
static void installExceptionOrSignalHandlers() {
@@ -364,7 +402,9 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
void CrashRecoveryContext::HandleCrash() {
CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
assert(CRCI && "Crash recovery context never initialized!");
- CRCI->HandleCrash();
+ // As per convention, -2 indicates a crash or timeout as opposed to failure to
+ // execute (see llvm/include/llvm/Support/Program.h)
+ CRCI->HandleCrash(-2, 0);
}
// FIXME: Portability.
@@ -404,7 +444,10 @@ bool CrashRecoveryContext::RunSafelyOnThread(function_ref<void()> Fn,
unsigned RequestedStackSize) {
bool UseBackgroundPriority = hasThreadBackgroundPriority();
RunSafelyOnThreadInfo Info = { Fn, this, UseBackgroundPriority, false };
- llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info, RequestedStackSize);
+ llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info,
+ RequestedStackSize == 0
+ ? llvm::None
+ : llvm::Optional<unsigned>(RequestedStackSize));
if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl)
CRC->setSwitchedThread();
return Info.Result;
diff --git a/llvm/lib/Support/DebugCounter.cpp b/llvm/lib/Support/DebugCounter.cpp
index 6598103658da..1e3ec300964c 100644
--- a/llvm/lib/Support/DebugCounter.cpp
+++ b/llvm/lib/Support/DebugCounter.cpp
@@ -2,7 +2,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Options.h"
using namespace llvm;
diff --git a/llvm/lib/Support/Error.cpp b/llvm/lib/Support/Error.cpp
index 9ea08c37478e..315a11e967d1 100644
--- a/llvm/lib/Support/Error.cpp
+++ b/llvm/lib/Support/Error.cpp
@@ -103,9 +103,10 @@ std::error_code errorToErrorCode(Error Err) {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
void Error::fatalUncheckedError() const {
dbgs() << "Program aborted due to an unhandled Error:\n";
- if (getPtr())
+ if (getPtr()) {
getPtr()->log(dbgs());
- else
+ dbgs() << "\n";
+ }else
dbgs() << "Error value was Success. (Note: Success values must still be "
"checked prior to being destroyed).\n";
abort();
diff --git a/llvm/lib/Support/FileCheck.cpp b/llvm/lib/Support/FileCheck.cpp
index 841e406a7b69..2261ecc236c2 100644
--- a/llvm/lib/Support/FileCheck.cpp
+++ b/llvm/lib/Support/FileCheck.cpp
@@ -25,15 +25,15 @@
using namespace llvm;
-Expected<uint64_t> FileCheckNumericVariableUse::eval() const {
- Optional<uint64_t> Value = NumericVariable->getValue();
+Expected<uint64_t> NumericVariableUse::eval() const {
+ Optional<uint64_t> Value = Variable->getValue();
if (Value)
return *Value;
- return make_error<FileCheckUndefVarError>(Name);
+ return make_error<UndefVarError>(Name);
}
-Expected<uint64_t> FileCheckASTBinop::eval() const {
+Expected<uint64_t> BinaryOperation::eval() const {
Expected<uint64_t> LeftOp = LeftOperand->eval();
Expected<uint64_t> RightOp = RightOperand->eval();
@@ -51,14 +51,14 @@ Expected<uint64_t> FileCheckASTBinop::eval() const {
return EvalBinop(*LeftOp, *RightOp);
}
-Expected<std::string> FileCheckNumericSubstitution::getResult() const {
- Expected<uint64_t> EvaluatedValue = ExpressionAST->eval();
+Expected<std::string> NumericSubstitution::getResult() const {
+ Expected<uint64_t> EvaluatedValue = ExpressionASTPointer->eval();
if (!EvaluatedValue)
return EvaluatedValue.takeError();
return utostr(*EvaluatedValue);
}
-Expected<std::string> FileCheckStringSubstitution::getResult() const {
+Expected<std::string> StringSubstitution::getResult() const {
// Look up the value and escape it so that we can put it into the regex.
Expected<StringRef> VarVal = Context->getPatternVarValue(FromStr);
if (!VarVal)
@@ -66,14 +66,12 @@ Expected<std::string> FileCheckStringSubstitution::getResult() const {
return Regex::escape(*VarVal);
}
-bool FileCheckPattern::isValidVarNameStart(char C) {
- return C == '_' || isalpha(C);
-}
+bool Pattern::isValidVarNameStart(char C) { return C == '_' || isalpha(C); }
-Expected<FileCheckPattern::VariableProperties>
-FileCheckPattern::parseVariable(StringRef &Str, const SourceMgr &SM) {
+Expected<Pattern::VariableProperties>
+Pattern::parseVariable(StringRef &Str, const SourceMgr &SM) {
if (Str.empty())
- return FileCheckErrorDiagnostic::get(SM, Str, "empty variable name");
+ return ErrorDiagnostic::get(SM, Str, "empty variable name");
bool ParsedOneChar = false;
unsigned I = 0;
@@ -85,7 +83,7 @@ FileCheckPattern::parseVariable(StringRef &Str, const SourceMgr &SM) {
for (unsigned E = Str.size(); I != E; ++I) {
if (!ParsedOneChar && !isValidVarNameStart(Str[I]))
- return FileCheckErrorDiagnostic::get(SM, Str, "invalid variable name");
+ return ErrorDiagnostic::get(SM, Str, "invalid variable name");
// Variable names are composed of alphanumeric characters and underscores.
if (Str[I] != '_' && !isalnum(Str[I]))
@@ -109,12 +107,11 @@ static char popFront(StringRef &S) {
return C;
}
-char FileCheckUndefVarError::ID = 0;
-char FileCheckErrorDiagnostic::ID = 0;
-char FileCheckNotFoundError::ID = 0;
+char UndefVarError::ID = 0;
+char ErrorDiagnostic::ID = 0;
+char NotFoundError::ID = 0;
-Expected<FileCheckNumericVariable *>
-FileCheckPattern::parseNumericVariableDefinition(
+Expected<NumericVariable *> Pattern::parseNumericVariableDefinition(
StringRef &Expr, FileCheckPatternContext *Context,
Optional<size_t> LineNumber, const SourceMgr &SM) {
Expected<VariableProperties> ParseVarResult = parseVariable(Expr, SM);
@@ -123,22 +120,22 @@ FileCheckPattern::parseNumericVariableDefinition(
StringRef Name = ParseVarResult->Name;
if (ParseVarResult->IsPseudo)
- return FileCheckErrorDiagnostic::get(
+ return ErrorDiagnostic::get(
SM, Name, "definition of pseudo numeric variable unsupported");
// Detect collisions between string and numeric variables when the latter
// is created later than the former.
if (Context->DefinedVariableTable.find(Name) !=
Context->DefinedVariableTable.end())
- return FileCheckErrorDiagnostic::get(
+ return ErrorDiagnostic::get(
SM, Name, "string variable with name '" + Name + "' already exists");
Expr = Expr.ltrim(SpaceChars);
if (!Expr.empty())
- return FileCheckErrorDiagnostic::get(
+ return ErrorDiagnostic::get(
SM, Expr, "unexpected characters after numeric variable name");
- FileCheckNumericVariable *DefinedNumericVariable;
+ NumericVariable *DefinedNumericVariable;
auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
if (VarTableIter != Context->GlobalNumericVariableTable.end())
DefinedNumericVariable = VarTableIter->second;
@@ -148,13 +145,11 @@ FileCheckPattern::parseNumericVariableDefinition(
return DefinedNumericVariable;
}
-Expected<std::unique_ptr<FileCheckNumericVariableUse>>
-FileCheckPattern::parseNumericVariableUse(StringRef Name, bool IsPseudo,
- Optional<size_t> LineNumber,
- FileCheckPatternContext *Context,
- const SourceMgr &SM) {
+Expected<std::unique_ptr<NumericVariableUse>> Pattern::parseNumericVariableUse(
+ StringRef Name, bool IsPseudo, Optional<size_t> LineNumber,
+ FileCheckPatternContext *Context, const SourceMgr &SM) {
if (IsPseudo && !Name.equals("@LINE"))
- return FileCheckErrorDiagnostic::get(
+ return ErrorDiagnostic::get(
SM, Name, "invalid pseudo numeric variable '" + Name + "'");
// Numeric variable definitions and uses are parsed in the order in which
@@ -166,7 +161,7 @@ FileCheckPattern::parseNumericVariableUse(StringRef Name, bool IsPseudo,
// uses of undefined variables, whether string or numeric, are then diagnosed
// in printSubstitutions() after failing to match.
auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
- FileCheckNumericVariable *NumericVariable;
+ NumericVariable *NumericVariable;
if (VarTableIter != Context->GlobalNumericVariableTable.end())
NumericVariable = VarTableIter->second;
else {
@@ -176,22 +171,20 @@ FileCheckPattern::parseNumericVariableUse(StringRef Name, bool IsPseudo,
Optional<size_t> DefLineNumber = NumericVariable->getDefLineNumber();
if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
- return FileCheckErrorDiagnostic::get(
+ return ErrorDiagnostic::get(
SM, Name,
"numeric variable '" + Name +
"' defined earlier in the same CHECK directive");
- return std::make_unique<FileCheckNumericVariableUse>(Name, NumericVariable);
+ return std::make_unique<NumericVariableUse>(Name, NumericVariable);
}
-Expected<std::unique_ptr<FileCheckExpressionAST>>
-FileCheckPattern::parseNumericOperand(StringRef &Expr, AllowedOperand AO,
- Optional<size_t> LineNumber,
- FileCheckPatternContext *Context,
- const SourceMgr &SM) {
+Expected<std::unique_ptr<ExpressionAST>> Pattern::parseNumericOperand(
+ StringRef &Expr, AllowedOperand AO, Optional<size_t> LineNumber,
+ FileCheckPatternContext *Context, const SourceMgr &SM) {
if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
// Try to parse as a numeric variable use.
- Expected<FileCheckPattern::VariableProperties> ParseVarResult =
+ Expected<Pattern::VariableProperties> ParseVarResult =
parseVariable(Expr, SM);
if (ParseVarResult)
return parseNumericVariableUse(ParseVarResult->Name,
@@ -206,10 +199,10 @@ FileCheckPattern::parseNumericOperand(StringRef &Expr, AllowedOperand AO,
// Otherwise, parse it as a literal.
uint64_t LiteralValue;
if (!Expr.consumeInteger(/*Radix=*/10, LiteralValue))
- return std::make_unique<FileCheckExpressionLiteral>(LiteralValue);
+ return std::make_unique<ExpressionLiteral>(LiteralValue);
- return FileCheckErrorDiagnostic::get(SM, Expr,
- "invalid operand format '" + Expr + "'");
+ return ErrorDiagnostic::get(SM, Expr,
+ "invalid operand format '" + Expr + "'");
}
static uint64_t add(uint64_t LeftOp, uint64_t RightOp) {
@@ -220,10 +213,10 @@ static uint64_t sub(uint64_t LeftOp, uint64_t RightOp) {
return LeftOp - RightOp;
}
-Expected<std::unique_ptr<FileCheckExpressionAST>> FileCheckPattern::parseBinop(
- StringRef &Expr, std::unique_ptr<FileCheckExpressionAST> LeftOp,
- bool IsLegacyLineExpr, Optional<size_t> LineNumber,
- FileCheckPatternContext *Context, const SourceMgr &SM) {
+Expected<std::unique_ptr<ExpressionAST>>
+Pattern::parseBinop(StringRef &Expr, std::unique_ptr<ExpressionAST> LeftOp,
+ bool IsLegacyLineExpr, Optional<size_t> LineNumber,
+ FileCheckPatternContext *Context, const SourceMgr &SM) {
Expr = Expr.ltrim(SpaceChars);
if (Expr.empty())
return std::move(LeftOp);
@@ -241,35 +234,32 @@ Expected<std::unique_ptr<FileCheckExpressionAST>> FileCheckPattern::parseBinop(
EvalBinop = sub;
break;
default:
- return FileCheckErrorDiagnostic::get(
+ return ErrorDiagnostic::get(
SM, OpLoc, Twine("unsupported operation '") + Twine(Operator) + "'");
}
// Parse right operand.
Expr = Expr.ltrim(SpaceChars);
if (Expr.empty())
- return FileCheckErrorDiagnostic::get(SM, Expr,
- "missing operand in expression");
+ return ErrorDiagnostic::get(SM, Expr, "missing operand in expression");
// The second operand in a legacy @LINE expression is always a literal.
AllowedOperand AO =
IsLegacyLineExpr ? AllowedOperand::Literal : AllowedOperand::Any;
- Expected<std::unique_ptr<FileCheckExpressionAST>> RightOpResult =
+ Expected<std::unique_ptr<ExpressionAST>> RightOpResult =
parseNumericOperand(Expr, AO, LineNumber, Context, SM);
if (!RightOpResult)
return RightOpResult;
Expr = Expr.ltrim(SpaceChars);
- return std::make_unique<FileCheckASTBinop>(EvalBinop, std::move(LeftOp),
- std::move(*RightOpResult));
+ return std::make_unique<BinaryOperation>(EvalBinop, std::move(LeftOp),
+ std::move(*RightOpResult));
}
-Expected<std::unique_ptr<FileCheckExpressionAST>>
-FileCheckPattern::parseNumericSubstitutionBlock(
- StringRef Expr,
- Optional<FileCheckNumericVariable *> &DefinedNumericVariable,
+Expected<std::unique_ptr<ExpressionAST>> Pattern::parseNumericSubstitutionBlock(
+ StringRef Expr, Optional<NumericVariable *> &DefinedNumericVariable,
bool IsLegacyLineExpr, Optional<size_t> LineNumber,
FileCheckPatternContext *Context, const SourceMgr &SM) {
- std::unique_ptr<FileCheckExpressionAST> ExpressionAST = nullptr;
+ std::unique_ptr<ExpressionAST> ExpressionASTPointer = nullptr;
StringRef DefExpr = StringRef();
DefinedNumericVariable = None;
// Save variable definition expression if any.
@@ -286,26 +276,26 @@ FileCheckPattern::parseNumericSubstitutionBlock(
// pseudo variable.
AllowedOperand AO =
IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
- Expected<std::unique_ptr<FileCheckExpressionAST>> ParseResult =
+ Expected<std::unique_ptr<ExpressionAST>> ParseResult =
parseNumericOperand(Expr, AO, LineNumber, Context, SM);
while (ParseResult && !Expr.empty()) {
ParseResult = parseBinop(Expr, std::move(*ParseResult), IsLegacyLineExpr,
LineNumber, Context, SM);
// Legacy @LINE expressions only allow 2 operands.
if (ParseResult && IsLegacyLineExpr && !Expr.empty())
- return FileCheckErrorDiagnostic::get(
+ return ErrorDiagnostic::get(
SM, Expr,
"unexpected characters at end of expression '" + Expr + "'");
}
if (!ParseResult)
return ParseResult;
- ExpressionAST = std::move(*ParseResult);
+ ExpressionASTPointer = std::move(*ParseResult);
}
// Parse the numeric variable definition.
if (DefEnd != StringRef::npos) {
DefExpr = DefExpr.ltrim(SpaceChars);
- Expected<FileCheckNumericVariable *> ParseResult =
+ Expected<NumericVariable *> ParseResult =
parseNumericVariableDefinition(DefExpr, Context, LineNumber, SM);
if (!ParseResult)
@@ -313,12 +303,11 @@ FileCheckPattern::parseNumericSubstitutionBlock(
DefinedNumericVariable = *ParseResult;
}
- return std::move(ExpressionAST);
+ return std::move(ExpressionASTPointer);
}
-bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
- SourceMgr &SM,
- const FileCheckRequest &Req) {
+bool Pattern::parsePattern(StringRef PatternStr, StringRef Prefix,
+ SourceMgr &SM, const FileCheckRequest &Req) {
bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot;
IgnoreCase = Req.IgnoreCase;
@@ -447,7 +436,7 @@ bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
// Get the name (e.g. "foo") and verify it is well formed.
StringRef OrigMatchStr = MatchStr;
- Expected<FileCheckPattern::VariableProperties> ParseVarResult =
+ Expected<Pattern::VariableProperties> ParseVarResult =
parseVariable(MatchStr, SM);
if (!ParseVarResult) {
logAllUnhandledErrors(ParseVarResult.takeError(), errs());
@@ -487,10 +476,10 @@ bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
}
// Parse numeric substitution block.
- std::unique_ptr<FileCheckExpressionAST> ExpressionAST;
- Optional<FileCheckNumericVariable *> DefinedNumericVariable;
+ std::unique_ptr<ExpressionAST> ExpressionASTPointer;
+ Optional<NumericVariable *> DefinedNumericVariable;
if (IsNumBlock) {
- Expected<std::unique_ptr<FileCheckExpressionAST>> ParseResult =
+ Expected<std::unique_ptr<ExpressionAST>> ParseResult =
parseNumericSubstitutionBlock(MatchStr, DefinedNumericVariable,
IsLegacyLineExpr, LineNumber, Context,
SM);
@@ -498,8 +487,8 @@ bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
logAllUnhandledErrors(ParseResult.takeError(), errs());
return true;
}
- ExpressionAST = std::move(*ParseResult);
- SubstNeeded = ExpressionAST != nullptr;
+ ExpressionASTPointer = std::move(*ParseResult);
+ SubstNeeded = ExpressionASTPointer != nullptr;
if (DefinedNumericVariable) {
IsDefinition = true;
DefName = (*DefinedNumericVariable)->getName();
@@ -516,7 +505,7 @@ bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
++SubstInsertIdx;
if (IsNumBlock) {
- FileCheckNumericVariableMatch NumericVariableDefinition = {
+ NumericVariableMatch NumericVariableDefinition = {
*DefinedNumericVariable, CurParen};
NumericVariableDefs[DefName] = NumericVariableDefinition;
// This store is done here rather than in match() to allow
@@ -562,10 +551,11 @@ bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
} else {
// Handle substitution of string variables ([[<var>]]) defined in
// previous CHECK patterns, and substitution of expressions.
- FileCheckSubstitution *Substitution =
+ Substitution *Substitution =
IsNumBlock
? Context->makeNumericSubstitution(
- SubstStr, std::move(ExpressionAST), SubstInsertIdx)
+ SubstStr, std::move(ExpressionASTPointer),
+ SubstInsertIdx)
: Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
Substitutions.push_back(Substitution);
}
@@ -589,7 +579,7 @@ bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
return false;
}
-bool FileCheckPattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {
+bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {
Regex R(RS);
std::string Error;
if (!R.isValid(Error)) {
@@ -603,14 +593,14 @@ bool FileCheckPattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceM
return false;
}
-void FileCheckPattern::AddBackrefToRegEx(unsigned BackrefNum) {
+void Pattern::AddBackrefToRegEx(unsigned BackrefNum) {
assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum);
RegExStr += Backref;
}
-Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,
- const SourceMgr &SM) const {
+Expected<size_t> Pattern::match(StringRef Buffer, size_t &MatchLen,
+ const SourceMgr &SM) const {
// If this is the EOF pattern, match it immediately.
if (CheckTy == Check::CheckEOF) {
MatchLen = 0;
@@ -620,10 +610,10 @@ Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,
// If this is a fixed string pattern, just match it now.
if (!FixedStr.empty()) {
MatchLen = FixedStr.size();
- size_t Pos = IgnoreCase ? Buffer.find_lower(FixedStr)
- : Buffer.find(FixedStr);
+ size_t Pos =
+ IgnoreCase ? Buffer.find_lower(FixedStr) : Buffer.find(FixedStr);
if (Pos == StringRef::npos)
- return make_error<FileCheckNotFoundError>();
+ return make_error<NotFoundError>();
return Pos;
}
@@ -663,7 +653,7 @@ Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,
if (IgnoreCase)
Flags |= Regex::IgnoreCase;
if (!Regex(RegExToMatch, Flags).match(Buffer, &MatchInfo))
- return make_error<FileCheckNotFoundError>();
+ return make_error<NotFoundError>();
// Successful regex match.
assert(!MatchInfo.empty() && "Didn't get any match");
@@ -678,18 +668,18 @@ Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,
// If this defines any numeric variables, remember their values.
for (const auto &NumericVariableDef : NumericVariableDefs) {
- const FileCheckNumericVariableMatch &NumericVariableMatch =
+ const NumericVariableMatch &NumericVariableMatch =
NumericVariableDef.getValue();
unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
assert(CaptureParenGroup < MatchInfo.size() && "Internal paren error");
- FileCheckNumericVariable *DefinedNumericVariable =
+ NumericVariable *DefinedNumericVariable =
NumericVariableMatch.DefinedNumericVariable;
StringRef MatchedValue = MatchInfo[CaptureParenGroup];
uint64_t Val;
if (MatchedValue.getAsInteger(10, Val))
- return FileCheckErrorDiagnostic::get(SM, MatchedValue,
- "Unable to represent numeric value");
+ return ErrorDiagnostic::get(SM, MatchedValue,
+ "Unable to represent numeric value");
DefinedNumericVariable->setValue(Val);
}
@@ -701,7 +691,7 @@ Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,
return FullMatch.data() - Buffer.data() + MatchStartSkip;
}
-unsigned FileCheckPattern::computeMatchDistance(StringRef Buffer) const {
+unsigned Pattern::computeMatchDistance(StringRef Buffer) const {
// Just compute the number of matching characters. For regular expressions, we
// just compare against the regex itself and hope for the best.
//
@@ -718,8 +708,8 @@ unsigned FileCheckPattern::computeMatchDistance(StringRef Buffer) const {
return BufferPrefix.edit_distance(ExampleString);
}
-void FileCheckPattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
- SMRange MatchRange) const {
+void Pattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
+ SMRange MatchRange) const {
// Print what we know about substitutions.
if (!Substitutions.empty()) {
for (const auto &Substitution : Substitutions) {
@@ -731,11 +721,10 @@ void FileCheckPattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
// variables it uses.
if (!MatchedValue) {
bool UndefSeen = false;
- handleAllErrors(MatchedValue.takeError(),
- [](const FileCheckNotFoundError &E) {},
+ handleAllErrors(MatchedValue.takeError(), [](const NotFoundError &E) {},
// Handled in PrintNoMatch().
- [](const FileCheckErrorDiagnostic &E) {},
- [&](const FileCheckUndefVarError &E) {
+ [](const ErrorDiagnostic &E) {},
+ [&](const UndefVarError &E) {
if (!UndefSeen) {
OS << "uses undefined variable(s):";
UndefSeen = true;
@@ -778,9 +767,8 @@ static SMRange ProcessMatchResult(FileCheckDiag::MatchType MatchTy,
return Range;
}
-void FileCheckPattern::printFuzzyMatch(
- const SourceMgr &SM, StringRef Buffer,
- std::vector<FileCheckDiag> *Diags) const {
+void Pattern::printFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
+ std::vector<FileCheckDiag> *Diags) const {
// Attempt to find the closest/best fuzzy match. Usually an error happens
// because some string in the output didn't exactly match. In these cases, we
// would like to show the user a best guess at what "should have" matched, to
@@ -829,36 +817,34 @@ Expected<StringRef>
FileCheckPatternContext::getPatternVarValue(StringRef VarName) {
auto VarIter = GlobalVariableTable.find(VarName);
if (VarIter == GlobalVariableTable.end())
- return make_error<FileCheckUndefVarError>(VarName);
+ return make_error<UndefVarError>(VarName);
return VarIter->second;
}
template <class... Types>
-FileCheckNumericVariable *
-FileCheckPatternContext::makeNumericVariable(Types... args) {
- NumericVariables.push_back(
- std::make_unique<FileCheckNumericVariable>(args...));
+NumericVariable *FileCheckPatternContext::makeNumericVariable(Types... args) {
+ NumericVariables.push_back(std::make_unique<NumericVariable>(args...));
return NumericVariables.back().get();
}
-FileCheckSubstitution *
+Substitution *
FileCheckPatternContext::makeStringSubstitution(StringRef VarName,
size_t InsertIdx) {
Substitutions.push_back(
- std::make_unique<FileCheckStringSubstitution>(this, VarName, InsertIdx));
+ std::make_unique<StringSubstitution>(this, VarName, InsertIdx));
return Substitutions.back().get();
}
-FileCheckSubstitution *FileCheckPatternContext::makeNumericSubstitution(
+Substitution *FileCheckPatternContext::makeNumericSubstitution(
StringRef ExpressionStr,
- std::unique_ptr<FileCheckExpressionAST> ExpressionAST, size_t InsertIdx) {
- Substitutions.push_back(std::make_unique<FileCheckNumericSubstitution>(
- this, ExpressionStr, std::move(ExpressionAST), InsertIdx));
+ std::unique_ptr<ExpressionAST> ExpressionASTPointer, size_t InsertIdx) {
+ Substitutions.push_back(std::make_unique<NumericSubstitution>(
+ this, ExpressionStr, std::move(ExpressionASTPointer), InsertIdx));
return Substitutions.back().get();
}
-size_t FileCheckPattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
+size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
// Offset keeps track of the current offset within the input Str
size_t Offset = 0;
// [...] Nesting depth
@@ -1139,7 +1125,7 @@ bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer,
PatternContext->createLineVariable();
- std::vector<FileCheckPattern> ImplicitNegativeChecks;
+ std::vector<Pattern> ImplicitNegativeChecks;
for (const auto &PatternString : Req.ImplicitCheckNot) {
// Create a buffer with fake command line content in order to display the
// command line option responsible for the specific implicit CHECK-NOT.
@@ -1153,12 +1139,12 @@ bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer,
SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
ImplicitNegativeChecks.push_back(
- FileCheckPattern(Check::CheckNot, PatternContext.get()));
+ Pattern(Check::CheckNot, PatternContext.get()));
ImplicitNegativeChecks.back().parsePattern(PatternInBuffer,
"IMPLICIT-CHECK", SM, Req);
}
- std::vector<FileCheckPattern> DagNotMatches = ImplicitNegativeChecks;
+ std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks;
// LineNumber keeps track of the line on which CheckPrefix instances are
// found.
@@ -1216,7 +1202,7 @@ bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer,
SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
// Parse the pattern.
- FileCheckPattern P(CheckTy, PatternContext.get(), LineNumber);
+ Pattern P(CheckTy, PatternContext.get(), LineNumber);
if (P.parsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, Req))
return true;
@@ -1261,7 +1247,7 @@ bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer,
// prefix as a filler for the error message.
if (!DagNotMatches.empty()) {
CheckStrings->emplace_back(
- FileCheckPattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1),
+ Pattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1),
*Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data()));
std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
}
@@ -1286,7 +1272,7 @@ bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer,
}
static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
- StringRef Prefix, SMLoc Loc, const FileCheckPattern &Pat,
+ StringRef Prefix, SMLoc Loc, const Pattern &Pat,
int MatchedCount, StringRef Buffer, size_t MatchPos,
size_t MatchLen, const FileCheckRequest &Req,
std::vector<FileCheckDiag> *Diags) {
@@ -1332,10 +1318,10 @@ static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
}
static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
- StringRef Prefix, SMLoc Loc,
- const FileCheckPattern &Pat, int MatchedCount,
- StringRef Buffer, bool VerboseVerbose,
- std::vector<FileCheckDiag> *Diags, Error MatchErrors) {
+ StringRef Prefix, SMLoc Loc, const Pattern &Pat,
+ int MatchedCount, StringRef Buffer,
+ bool VerboseVerbose, std::vector<FileCheckDiag> *Diags,
+ Error MatchErrors) {
assert(MatchErrors && "Called on successful match");
bool PrintDiag = true;
if (!ExpectedMatch) {
@@ -1361,9 +1347,8 @@ static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
return;
}
- MatchErrors =
- handleErrors(std::move(MatchErrors),
- [](const FileCheckErrorDiagnostic &E) { E.log(errs()); });
+ MatchErrors = handleErrors(std::move(MatchErrors),
+ [](const ErrorDiagnostic &E) { E.log(errs()); });
// No problem matching the string per se.
if (!MatchErrors)
@@ -1427,7 +1412,7 @@ size_t FileCheckString::Check(const SourceMgr &SM, StringRef Buffer,
FileCheckRequest &Req,
std::vector<FileCheckDiag> *Diags) const {
size_t LastPos = 0;
- std::vector<const FileCheckPattern *> NotStrings;
+ std::vector<const Pattern *> NotStrings;
// IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
// bounds; we have not processed variable definitions within the bounded block
@@ -1565,11 +1550,11 @@ bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
return false;
}
-bool FileCheckString::CheckNot(
- const SourceMgr &SM, StringRef Buffer,
- const std::vector<const FileCheckPattern *> &NotStrings,
- const FileCheckRequest &Req, std::vector<FileCheckDiag> *Diags) const {
- for (const FileCheckPattern *Pat : NotStrings) {
+bool FileCheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
+ const std::vector<const Pattern *> &NotStrings,
+ const FileCheckRequest &Req,
+ std::vector<FileCheckDiag> *Diags) const {
+ for (const Pattern *Pat : NotStrings) {
assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
size_t MatchLen = 0;
@@ -1591,11 +1576,10 @@ bool FileCheckString::CheckNot(
return false;
}
-size_t
-FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
- std::vector<const FileCheckPattern *> &NotStrings,
- const FileCheckRequest &Req,
- std::vector<FileCheckDiag> *Diags) const {
+size_t FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
+ std::vector<const Pattern *> &NotStrings,
+ const FileCheckRequest &Req,
+ std::vector<FileCheckDiag> *Diags) const {
if (DagNotStrings.empty())
return 0;
@@ -1615,7 +1599,7 @@ FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
// group, so we don't use a range-based for loop here.
for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end();
PatItr != PatEnd; ++PatItr) {
- const FileCheckPattern &Pat = *PatItr;
+ const Pattern &Pat = *PatItr;
assert((Pat.getCheckTy() == Check::CheckDAG ||
Pat.getCheckTy() == Check::CheckNot) &&
"Invalid CHECK-DAG or CHECK-NOT!");
@@ -1820,8 +1804,8 @@ Error FileCheckPatternContext::defineCmdlineVariables(
if (CmdlineDef.empty()) {
Errs = joinErrors(
std::move(Errs),
- FileCheckErrorDiagnostic::get(
- SM, CmdlineDef, "missing equal sign in global definition"));
+ ErrorDiagnostic::get(SM, CmdlineDef,
+ "missing equal sign in global definition"));
continue;
}
@@ -1830,21 +1814,21 @@ Error FileCheckPatternContext::defineCmdlineVariables(
// Now parse the definition both to check that the syntax is correct and
// to create the necessary class instance.
StringRef CmdlineDefExpr = CmdlineDef.substr(1);
- Optional<FileCheckNumericVariable *> DefinedNumericVariable;
- Expected<std::unique_ptr<FileCheckExpressionAST>> ExpressionASTResult =
- FileCheckPattern::parseNumericSubstitutionBlock(
+ Optional<NumericVariable *> DefinedNumericVariable;
+ Expected<std::unique_ptr<ExpressionAST>> ExpressionASTResult =
+ Pattern::parseNumericSubstitutionBlock(
CmdlineDefExpr, DefinedNumericVariable, false, None, this, SM);
if (!ExpressionASTResult) {
Errs = joinErrors(std::move(Errs), ExpressionASTResult.takeError());
continue;
}
- std::unique_ptr<FileCheckExpressionAST> ExpressionAST =
+ std::unique_ptr<ExpressionAST> ExpressionASTPointer =
std::move(*ExpressionASTResult);
// Now evaluate the expression whose value this variable should be set
// to, since the expression of a command-line variable definition should
// only use variables defined earlier on the command-line. If not, this
// is an error and we report it.
- Expected<uint64_t> Value = ExpressionAST->eval();
+ Expected<uint64_t> Value = ExpressionASTPointer->eval();
if (!Value) {
Errs = joinErrors(std::move(Errs), Value.takeError());
continue;
@@ -1861,8 +1845,8 @@ Error FileCheckPatternContext::defineCmdlineVariables(
std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('=');
StringRef CmdlineName = CmdlineNameVal.first;
StringRef OrigCmdlineName = CmdlineName;
- Expected<FileCheckPattern::VariableProperties> ParseVarResult =
- FileCheckPattern::parseVariable(CmdlineName, SM);
+ Expected<Pattern::VariableProperties> ParseVarResult =
+ Pattern::parseVariable(CmdlineName, SM);
if (!ParseVarResult) {
Errs = joinErrors(std::move(Errs), ParseVarResult.takeError());
continue;
@@ -1872,7 +1856,7 @@ Error FileCheckPatternContext::defineCmdlineVariables(
// "FOO+2" in a "FOO+2=10" definition.
if (ParseVarResult->IsPseudo || !CmdlineName.empty()) {
Errs = joinErrors(std::move(Errs),
- FileCheckErrorDiagnostic::get(
+ ErrorDiagnostic::get(
SM, OrigCmdlineName,
"invalid name in string variable definition '" +
OrigCmdlineName + "'"));
@@ -1884,8 +1868,8 @@ Error FileCheckPatternContext::defineCmdlineVariables(
// is created later than the latter.
if (GlobalNumericVariableTable.find(Name) !=
GlobalNumericVariableTable.end()) {
- Errs = joinErrors(std::move(Errs), FileCheckErrorDiagnostic::get(
- SM, Name,
+ Errs = joinErrors(std::move(Errs),
+ ErrorDiagnostic::get(SM, Name,
"numeric variable with name '" +
Name + "' already exists"));
continue;
diff --git a/llvm/lib/Support/FileCheckImpl.h b/llvm/lib/Support/FileCheckImpl.h
index 06ce8301cec4..dc07d22aefd8 100644
--- a/llvm/lib/Support/FileCheckImpl.h
+++ b/llvm/lib/Support/FileCheckImpl.h
@@ -31,9 +31,9 @@ namespace llvm {
//===----------------------------------------------------------------------===//
/// Base class representing the AST of a given expression.
-class FileCheckExpressionAST {
+class ExpressionAST {
public:
- virtual ~FileCheckExpressionAST() = default;
+ virtual ~ExpressionAST() = default;
/// Evaluates and \returns the value of the expression represented by this
/// AST or an error if evaluation fails.
@@ -41,29 +41,29 @@ public:
};
/// Class representing an unsigned literal in the AST of an expression.
-class FileCheckExpressionLiteral : public FileCheckExpressionAST {
+class ExpressionLiteral : public ExpressionAST {
private:
/// Actual value of the literal.
uint64_t Value;
public:
/// Constructs a literal with the specified value.
- FileCheckExpressionLiteral(uint64_t Val) : Value(Val) {}
+ ExpressionLiteral(uint64_t Val) : Value(Val) {}
/// \returns the literal's value.
- Expected<uint64_t> eval() const { return Value; }
+ Expected<uint64_t> eval() const override { return Value; }
};
/// Class to represent an undefined variable error, which quotes that
/// variable's name when printed.
-class FileCheckUndefVarError : public ErrorInfo<FileCheckUndefVarError> {
+class UndefVarError : public ErrorInfo<UndefVarError> {
private:
StringRef VarName;
public:
static char ID;
- FileCheckUndefVarError(StringRef VarName) : VarName(VarName) {}
+ UndefVarError(StringRef VarName) : VarName(VarName) {}
StringRef getVarName() const { return VarName; }
@@ -79,7 +79,7 @@ public:
};
/// Class representing a numeric variable and its associated current value.
-class FileCheckNumericVariable {
+class NumericVariable {
private:
/// Name of the numeric variable.
StringRef Name;
@@ -95,8 +95,8 @@ private:
public:
/// Constructor for a variable \p Name defined at line \p DefLineNumber or
/// defined before input is parsed if \p DefLineNumber is None.
- explicit FileCheckNumericVariable(StringRef Name,
- Optional<size_t> DefLineNumber = None)
+ explicit NumericVariable(StringRef Name,
+ Optional<size_t> DefLineNumber = None)
: Name(Name), DefLineNumber(DefLineNumber) {}
/// \returns name of this numeric variable.
@@ -114,47 +114,45 @@ public:
/// \returns the line number where this variable is defined, if any, or None
/// if defined before input is parsed.
- Optional<size_t> getDefLineNumber() { return DefLineNumber; }
+ Optional<size_t> getDefLineNumber() const { return DefLineNumber; }
};
/// Class representing the use of a numeric variable in the AST of an
/// expression.
-class FileCheckNumericVariableUse : public FileCheckExpressionAST {
+class NumericVariableUse : public ExpressionAST {
private:
/// Name of the numeric variable.
StringRef Name;
/// Pointer to the class instance for the variable this use is about.
- FileCheckNumericVariable *NumericVariable;
+ NumericVariable *Variable;
public:
- FileCheckNumericVariableUse(StringRef Name,
- FileCheckNumericVariable *NumericVariable)
- : Name(Name), NumericVariable(NumericVariable) {}
+ NumericVariableUse(StringRef Name, NumericVariable *Variable)
+ : Name(Name), Variable(Variable) {}
/// \returns the value of the variable referenced by this instance.
- Expected<uint64_t> eval() const;
+ Expected<uint64_t> eval() const override;
};
/// Type of functions evaluating a given binary operation.
using binop_eval_t = uint64_t (*)(uint64_t, uint64_t);
/// Class representing a single binary operation in the AST of an expression.
-class FileCheckASTBinop : public FileCheckExpressionAST {
+class BinaryOperation : public ExpressionAST {
private:
/// Left operand.
- std::unique_ptr<FileCheckExpressionAST> LeftOperand;
+ std::unique_ptr<ExpressionAST> LeftOperand;
/// Right operand.
- std::unique_ptr<FileCheckExpressionAST> RightOperand;
+ std::unique_ptr<ExpressionAST> RightOperand;
/// Pointer to function that can evaluate this binary operation.
binop_eval_t EvalBinop;
public:
- FileCheckASTBinop(binop_eval_t EvalBinop,
- std::unique_ptr<FileCheckExpressionAST> LeftOp,
- std::unique_ptr<FileCheckExpressionAST> RightOp)
+ BinaryOperation(binop_eval_t EvalBinop, std::unique_ptr<ExpressionAST> LeftOp,
+ std::unique_ptr<ExpressionAST> RightOp)
: EvalBinop(EvalBinop) {
LeftOperand = std::move(LeftOp);
RightOperand = std::move(RightOp);
@@ -164,13 +162,13 @@ public:
/// using EvalBinop on the result of recursively evaluating the operands.
/// \returns the expression value or an error if an undefined numeric
/// variable is used in one of the operands.
- Expected<uint64_t> eval() const;
+ Expected<uint64_t> eval() const override;
};
class FileCheckPatternContext;
/// Class representing a substitution to perform in the RegExStr string.
-class FileCheckSubstitution {
+class Substitution {
protected:
/// Pointer to a class instance holding, among other things, the table with
/// the values of live string variables at the start of any given CHECK line.
@@ -188,11 +186,11 @@ protected:
size_t InsertIdx;
public:
- FileCheckSubstitution(FileCheckPatternContext *Context, StringRef VarName,
- size_t InsertIdx)
+ Substitution(FileCheckPatternContext *Context, StringRef VarName,
+ size_t InsertIdx)
: Context(Context), FromStr(VarName), InsertIdx(InsertIdx) {}
- virtual ~FileCheckSubstitution() = default;
+ virtual ~Substitution() = default;
/// \returns the string to be substituted for something else.
StringRef getFromString() const { return FromStr; }
@@ -205,29 +203,28 @@ public:
virtual Expected<std::string> getResult() const = 0;
};
-class FileCheckStringSubstitution : public FileCheckSubstitution {
+class StringSubstitution : public Substitution {
public:
- FileCheckStringSubstitution(FileCheckPatternContext *Context,
- StringRef VarName, size_t InsertIdx)
- : FileCheckSubstitution(Context, VarName, InsertIdx) {}
+ StringSubstitution(FileCheckPatternContext *Context, StringRef VarName,
+ size_t InsertIdx)
+ : Substitution(Context, VarName, InsertIdx) {}
/// \returns the text that the string variable in this substitution matched
/// when defined, or an error if the variable is undefined.
Expected<std::string> getResult() const override;
};
-class FileCheckNumericSubstitution : public FileCheckSubstitution {
+class NumericSubstitution : public Substitution {
private:
/// Pointer to the class representing the expression whose value is to be
/// substituted.
- std::unique_ptr<FileCheckExpressionAST> ExpressionAST;
+ std::unique_ptr<ExpressionAST> ExpressionASTPointer;
public:
- FileCheckNumericSubstitution(FileCheckPatternContext *Context, StringRef Expr,
- std::unique_ptr<FileCheckExpressionAST> ExprAST,
- size_t InsertIdx)
- : FileCheckSubstitution(Context, Expr, InsertIdx) {
- ExpressionAST = std::move(ExprAST);
+ NumericSubstitution(FileCheckPatternContext *Context, StringRef Expr,
+ std::unique_ptr<ExpressionAST> ExprAST, size_t InsertIdx)
+ : Substitution(Context, Expr, InsertIdx) {
+ ExpressionASTPointer = std::move(ExprAST);
}
/// \returns a string containing the result of evaluating the expression in
@@ -241,11 +238,11 @@ public:
struct FileCheckDiag;
-/// Class holding the FileCheckPattern global state, shared by all patterns:
-/// tables holding values of variables and whether they are defined or not at
-/// any given time in the matching process.
+/// Class holding the Pattern global state, shared by all patterns: tables
+/// holding values of variables and whether they are defined or not at any
+/// given time in the matching process.
class FileCheckPatternContext {
- friend class FileCheckPattern;
+ friend class Pattern;
private:
/// When matching a given pattern, this holds the value of all the string
@@ -262,21 +259,20 @@ private:
/// When matching a given pattern, this holds the pointers to the classes
/// representing the numeric variables defined in previous patterns. When
/// matching a pattern all definitions for that pattern are recorded in the
- /// NumericVariableDefs table in the FileCheckPattern instance of that
- /// pattern.
- StringMap<FileCheckNumericVariable *> GlobalNumericVariableTable;
+ /// NumericVariableDefs table in the Pattern instance of that pattern.
+ StringMap<NumericVariable *> GlobalNumericVariableTable;
/// Pointer to the class instance representing the @LINE pseudo variable for
/// easily updating its value.
- FileCheckNumericVariable *LineVariable = nullptr;
+ NumericVariable *LineVariable = nullptr;
/// Vector holding pointers to all parsed numeric variables. Used to
/// automatically free them once they are guaranteed to no longer be used.
- std::vector<std::unique_ptr<FileCheckNumericVariable>> NumericVariables;
+ std::vector<std::unique_ptr<NumericVariable>> NumericVariables;
/// Vector holding pointers to all substitutions. Used to automatically free
/// them once they are guaranteed to no longer be used.
- std::vector<std::unique_ptr<FileCheckSubstitution>> Substitutions;
+ std::vector<std::unique_ptr<Substitution>> Substitutions;
public:
/// \returns the value of string variable \p VarName or an error if no such
@@ -303,32 +299,30 @@ public:
private:
/// Makes a new numeric variable and registers it for destruction when the
/// context is destroyed.
- template <class... Types>
- FileCheckNumericVariable *makeNumericVariable(Types... args);
+ template <class... Types> NumericVariable *makeNumericVariable(Types... args);
/// Makes a new string substitution and registers it for destruction when the
/// context is destroyed.
- FileCheckSubstitution *makeStringSubstitution(StringRef VarName,
- size_t InsertIdx);
+ Substitution *makeStringSubstitution(StringRef VarName, size_t InsertIdx);
/// Makes a new numeric substitution and registers it for destruction when
/// the context is destroyed.
- FileCheckSubstitution *
+ Substitution *
makeNumericSubstitution(StringRef ExpressionStr,
- std::unique_ptr<FileCheckExpressionAST> ExpressionAST,
+ std::unique_ptr<ExpressionAST> ExpressionAST,
size_t InsertIdx);
};
/// Class to represent an error holding a diagnostic with location information
/// used when printing it.
-class FileCheckErrorDiagnostic : public ErrorInfo<FileCheckErrorDiagnostic> {
+class ErrorDiagnostic : public ErrorInfo<ErrorDiagnostic> {
private:
SMDiagnostic Diagnostic;
public:
static char ID;
- FileCheckErrorDiagnostic(SMDiagnostic &&Diag) : Diagnostic(Diag) {}
+ ErrorDiagnostic(SMDiagnostic &&Diag) : Diagnostic(Diag) {}
std::error_code convertToErrorCode() const override {
return inconvertibleErrorCode();
@@ -338,7 +332,7 @@ public:
void log(raw_ostream &OS) const override { Diagnostic.print(nullptr, OS); }
static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg) {
- return make_error<FileCheckErrorDiagnostic>(
+ return make_error<ErrorDiagnostic>(
SM.GetMessage(Loc, SourceMgr::DK_Error, ErrMsg));
}
@@ -347,7 +341,7 @@ public:
}
};
-class FileCheckNotFoundError : public ErrorInfo<FileCheckNotFoundError> {
+class NotFoundError : public ErrorInfo<NotFoundError> {
public:
static char ID;
@@ -361,7 +355,7 @@ public:
}
};
-class FileCheckPattern {
+class Pattern {
SMLoc PatternLoc;
/// A fixed string to match as the pattern or empty if this pattern requires
@@ -378,7 +372,7 @@ class FileCheckPattern {
/// RegExStr will contain "foobaz" and we'll get two entries in this vector
/// that tells us to insert the value of string variable "bar" at offset 3
/// and the value of expression "N+1" at offset 6.
- std::vector<FileCheckSubstitution *> Substitutions;
+ std::vector<Substitution *> Substitutions;
/// Maps names of string variables defined in a pattern to the number of
/// their parenthesis group in RegExStr capturing their last definition.
@@ -397,10 +391,10 @@ class FileCheckPattern {
/// It holds the pointer to the class representing the numeric variable whose
/// value is being defined and the number of the parenthesis group in
/// RegExStr to capture that value.
- struct FileCheckNumericVariableMatch {
+ struct NumericVariableMatch {
/// Pointer to class representing the numeric variable whose value is being
/// defined.
- FileCheckNumericVariable *DefinedNumericVariable;
+ NumericVariable *DefinedNumericVariable;
/// Number of the parenthesis group in RegExStr that captures the value of
/// this numeric variable definition.
@@ -408,10 +402,9 @@ class FileCheckPattern {
};
/// Holds the number of the parenthesis group in RegExStr and pointer to the
- /// corresponding FileCheckNumericVariable class instance of all numeric
- /// variable definitions. Used to set the matched value of all those
- /// variables.
- StringMap<FileCheckNumericVariableMatch> NumericVariableDefs;
+ /// corresponding NumericVariable class instance of all numeric variable
+ /// definitions. Used to set the matched value of all those variables.
+ StringMap<NumericVariableMatch> NumericVariableDefs;
/// Pointer to a class instance holding the global state shared by all
/// patterns:
@@ -432,8 +425,8 @@ class FileCheckPattern {
bool IgnoreCase = false;
public:
- FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
- Optional<size_t> Line = None)
+ Pattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
+ Optional<size_t> Line = None)
: Context(Context), CheckTy(Ty), LineNumber(Line) {}
/// \returns the location in source code.
@@ -469,14 +462,12 @@ public:
/// substitution was successful, sets \p DefinedNumericVariable to point to
/// the class representing the numeric variable defined in this numeric
/// substitution block, or None if this block does not define any variable.
- static Expected<std::unique_ptr<FileCheckExpressionAST>>
- parseNumericSubstitutionBlock(
- StringRef Expr,
- Optional<FileCheckNumericVariable *> &DefinedNumericVariable,
+ static Expected<std::unique_ptr<ExpressionAST>> parseNumericSubstitutionBlock(
+ StringRef Expr, Optional<NumericVariable *> &DefinedNumericVariable,
bool IsLegacyLineExpr, Optional<size_t> LineNumber,
FileCheckPatternContext *Context, const SourceMgr &SM);
- /// Parses the pattern in \p PatternStr and initializes this FileCheckPattern
- /// instance accordingly.
+ /// Parses the pattern in \p PatternStr and initializes this Pattern instance
+ /// accordingly.
///
/// \p Prefix provides which prefix is being matched, \p Req describes the
/// global options that influence the parsing such as whitespace
@@ -491,8 +482,8 @@ public:
/// matched string.
///
/// The GlobalVariableTable StringMap in the FileCheckPatternContext class
- /// instance provides the current values of FileCheck string variables and
- /// is updated if this match defines new values. Likewise, the
+ /// instance provides the current values of FileCheck string variables and is
+ /// updated if this match defines new values. Likewise, the
/// GlobalNumericVariableTable StringMap in the same class provides the
/// current values of FileCheck numeric variables and is updated if this
/// match defines new numeric values.
@@ -523,17 +514,17 @@ private:
/// Finds the closing sequence of a regex variable usage or definition.
///
/// \p Str has to point in the beginning of the definition (right after the
- /// opening sequence). \p SM holds the SourceMgr used for error repporting.
+ /// opening sequence). \p SM holds the SourceMgr used for error reporting.
/// \returns the offset of the closing sequence within Str, or npos if it
/// was not found.
- size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
+ static size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
/// Parses \p Expr for the name of a numeric variable to be defined at line
/// \p LineNumber, or before input is parsed if \p LineNumber is None.
/// \returns a pointer to the class instance representing that variable,
/// creating it if needed, or an error holding a diagnostic against \p SM
/// should defining such a variable be invalid.
- static Expected<FileCheckNumericVariable *> parseNumericVariableDefinition(
+ static Expected<NumericVariable *> parseNumericVariableDefinition(
StringRef &Expr, FileCheckPatternContext *Context,
Optional<size_t> LineNumber, const SourceMgr &SM);
/// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use
@@ -542,11 +533,9 @@ private:
/// string and numeric variables. \returns the pointer to the class instance
/// representing that variable if successful, or an error holding a
/// diagnostic against \p SM otherwise.
- static Expected<std::unique_ptr<FileCheckNumericVariableUse>>
- parseNumericVariableUse(StringRef Name, bool IsPseudo,
- Optional<size_t> LineNumber,
- FileCheckPatternContext *Context,
- const SourceMgr &SM);
+ static Expected<std::unique_ptr<NumericVariableUse>> parseNumericVariableUse(
+ StringRef Name, bool IsPseudo, Optional<size_t> LineNumber,
+ FileCheckPatternContext *Context, const SourceMgr &SM);
enum class AllowedOperand { LineVar, Literal, Any };
/// Parses \p Expr for use of a numeric operand at line \p LineNumber, or
/// before input is parsed if \p LineNumber is None. Accepts both literal
@@ -555,7 +544,7 @@ private:
/// numeric variables. \returns the class representing that operand in the
/// AST of the expression or an error holding a diagnostic against \p SM
/// otherwise.
- static Expected<std::unique_ptr<FileCheckExpressionAST>>
+ static Expected<std::unique_ptr<ExpressionAST>>
parseNumericOperand(StringRef &Expr, AllowedOperand AO,
Optional<size_t> LineNumber,
FileCheckPatternContext *Context, const SourceMgr &SM);
@@ -566,8 +555,8 @@ private:
/// the class instance holding the live string and numeric variables.
/// \returns the class representing the binary operation in the AST of the
/// expression, or an error holding a diagnostic against \p SM otherwise.
- static Expected<std::unique_ptr<FileCheckExpressionAST>>
- parseBinop(StringRef &Expr, std::unique_ptr<FileCheckExpressionAST> LeftOp,
+ static Expected<std::unique_ptr<ExpressionAST>>
+ parseBinop(StringRef &Expr, std::unique_ptr<ExpressionAST> LeftOp,
bool IsLegacyLineExpr, Optional<size_t> LineNumber,
FileCheckPatternContext *Context, const SourceMgr &SM);
};
@@ -579,7 +568,7 @@ private:
/// A check that we found in the input file.
struct FileCheckString {
/// The pattern to match.
- FileCheckPattern Pat;
+ Pattern Pat;
/// Which prefix name this check matched.
StringRef Prefix;
@@ -589,9 +578,9 @@ struct FileCheckString {
/// All of the strings that are disallowed from occurring between this match
/// string and the previous one (or start of file).
- std::vector<FileCheckPattern> DagNotStrings;
+ std::vector<Pattern> DagNotStrings;
- FileCheckString(const FileCheckPattern &P, StringRef S, SMLoc L)
+ FileCheckString(const Pattern &P, StringRef S, SMLoc L)
: Pat(P), Prefix(S), Loc(L) {}
/// Matches check string and its "not strings" and/or "dag strings".
@@ -609,12 +598,12 @@ struct FileCheckString {
/// \p Buffer. Errors are reported against \p SM and diagnostics recorded in
/// \p Diags according to the verbosity level set in \p Req.
bool CheckNot(const SourceMgr &SM, StringRef Buffer,
- const std::vector<const FileCheckPattern *> &NotStrings,
+ const std::vector<const Pattern *> &NotStrings,
const FileCheckRequest &Req,
std::vector<FileCheckDiag> *Diags) const;
/// Matches "dag strings" and their mixed "not strings".
size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
- std::vector<const FileCheckPattern *> &NotStrings,
+ std::vector<const Pattern *> &NotStrings,
const FileCheckRequest &Req,
std::vector<FileCheckDiag> *Diags) const;
};
diff --git a/llvm/lib/Support/FileOutputBuffer.cpp b/llvm/lib/Support/FileOutputBuffer.cpp
index 024dd3e57a40..0a5306f684d4 100644
--- a/llvm/lib/Support/FileOutputBuffer.cpp
+++ b/llvm/lib/Support/FileOutputBuffer.cpp
@@ -189,7 +189,10 @@ FileOutputBuffer::create(StringRef Path, size_t Size, unsigned Flags) {
case fs::file_type::regular_file:
case fs::file_type::file_not_found:
case fs::file_type::status_error:
- return createOnDiskBuffer(Path, Size, Mode);
+ if (Flags & F_no_mmap)
+ return createInMemoryBuffer(Path, Size, Mode);
+ else
+ return createOnDiskBuffer(Path, Size, Mode);
default:
return createInMemoryBuffer(Path, Size, Mode);
}
diff --git a/llvm/lib/Support/Host.cpp b/llvm/lib/Support/Host.cpp
index 2a473a1994c2..ef38c1c09413 100644
--- a/llvm/lib/Support/Host.cpp
+++ b/llvm/lib/Support/Host.cpp
@@ -35,7 +35,7 @@
#ifdef _MSC_VER
#include <intrin.h>
#endif
-#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
+#if defined(__APPLE__) && (!defined(__x86_64__))
#include <mach/host_info.h>
#include <mach/mach.h>
#include <mach/mach_host.h>
@@ -140,6 +140,9 @@ StringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) {
.Case("POWER8E", "pwr8")
.Case("POWER8NVL", "pwr8")
.Case("POWER9", "pwr9")
+ // FIXME: If we get a simulator or machine with the capabilities of
+ // mcpu=future, we should revisit this and add the name reported by the
+ // simulator/machine.
.Default(generic);
}
@@ -265,14 +268,12 @@ StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {
unsigned Exynos = (Variant << 12) | Part;
switch (Exynos) {
default:
- // Default by falling through to Exynos M1.
+ // Default by falling through to Exynos M3.
LLVM_FALLTHROUGH;
-
- case 0x1001:
- return "exynos-m1";
-
- case 0x4001:
- return "exynos-m2";
+ case 0x1002:
+ return "exynos-m3";
+ case 0x1003:
+ return "exynos-m4";
}
}
@@ -961,9 +962,9 @@ static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
break; // "btver2"
case 23:
*Type = X86::AMDFAM17H;
- if (Model >= 0x30 && Model <= 0x3f) {
+ if ((Model >= 0x30 && Model <= 0x3f) || Model == 0x71) {
*Subtype = X86::AMDFAM17H_ZNVER2;
- break; // "znver2"; 30h-3fh: Zen2
+ break; // "znver2"; 30h-3fh, 71h: Zen2
}
if (Model <= 0x0f) {
*Subtype = X86::AMDFAM17H_ZNVER1;
@@ -1029,7 +1030,15 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
const unsigned AVXBits = (1 << 27) | (1 << 28);
bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
((EAX & 0x6) == 0x6);
+#if defined(__APPLE__)
+ // Darwin lazily saves the AVX512 context on first use: trust that the OS will
+ // save the AVX512 context if we use AVX512 instructions, even the bit is not
+ // set right now.
+ bool HasAVX512Save = true;
+#else
+ // AVX512 requires additional context to be saved by the OS.
bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
+#endif
if (HasAVX)
setFeature(X86::FEATURE_AVX);
@@ -1222,6 +1231,33 @@ StringRef sys::getHostCPUName() {
StringRef Content = P ? P->getBuffer() : "";
return detail::getHostCPUNameForS390x(Content);
}
+#elif defined(__APPLE__) && defined(__aarch64__)
+StringRef sys::getHostCPUName() {
+ return "cyclone";
+}
+#elif defined(__APPLE__) && defined(__arm__)
+StringRef sys::getHostCPUName() {
+ host_basic_info_data_t hostInfo;
+ mach_msg_type_number_t infoCount;
+
+ infoCount = HOST_BASIC_INFO_COUNT;
+ mach_port_t hostPort = mach_host_self();
+ host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo,
+ &infoCount);
+ mach_port_deallocate(mach_task_self(), hostPort);
+
+ if (hostInfo.cpu_type != CPU_TYPE_ARM) {
+ assert(false && "CPUType not equal to ARM should not be possible on ARM");
+ return "generic";
+ }
+ switch (hostInfo.cpu_subtype) {
+ case CPU_SUBTYPE_ARM_V7S:
+ return "swift";
+ default:;
+ }
+
+ return "generic";
+}
#else
StringRef sys::getHostCPUName() { return "generic"; }
#endif
@@ -1339,8 +1375,15 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
// switch, then we have full AVX support.
bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) &&
!getX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6);
+#if defined(__APPLE__)
+ // Darwin lazily saves the AVX512 context on first use: trust that the OS will
+ // save the AVX512 context if we use AVX512 instructions, even the bit is not
+ // set right now.
+ bool HasAVX512Save = true;
+#else
// AVX512 requires additional context to be saved by the OS.
bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
+#endif
Features["avx"] = HasAVXSave;
Features["fma"] = ((ECX >> 12) & 1) && HasAVXSave;
diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp
index 0d7d7fcc8cb6..bb9b569d2de6 100644
--- a/llvm/lib/Support/InitLLVM.cpp
+++ b/llvm/lib/Support/InitLLVM.cpp
@@ -21,7 +21,11 @@
using namespace llvm;
using namespace llvm::sys;
-InitLLVM::InitLLVM(int &Argc, const char **&Argv) : StackPrinter(Argc, Argv) {
+InitLLVM::InitLLVM(int &Argc, const char **&Argv,
+ bool InstallPipeSignalExitHandler)
+ : StackPrinter(Argc, Argv) {
+ if (InstallPipeSignalExitHandler)
+ sys::SetOneShotPipeSignalFunction(sys::DefaultOneShotPipeSignalHandler);
sys::PrintStackTraceOnErrorSignal(Argv[0]);
install_out_of_memory_new_handler();
diff --git a/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp b/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp
index da6514f7170b..bbc06d186fba 100644
--- a/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp
+++ b/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp
@@ -36,17 +36,6 @@ struct FoldingSetNodeIDBuilder {
operator()(T V) {
ID.AddInteger((unsigned long long)V);
}
- void operator()(itanium_demangle::NodeOrString NS) {
- if (NS.isNode()) {
- ID.AddInteger(0);
- (*this)(NS.asNode());
- } else if (NS.isString()) {
- ID.AddInteger(1);
- (*this)(NS.asString());
- } else {
- ID.AddInteger(2);
- }
- }
void operator()(itanium_demangle::NodeArray A) {
ID.AddInteger(A.size());
for (const Node *N : A)
@@ -307,16 +296,32 @@ ItaniumManglingCanonicalizer::addEquivalence(FragmentKind Kind, StringRef First,
return EquivalenceError::Success;
}
+static ItaniumManglingCanonicalizer::Key
+parseMaybeMangledName(CanonicalizingDemangler &Demangler, StringRef Mangling,
+ bool CreateNewNodes) {
+ Demangler.ASTAllocator.setCreateNewNodes(CreateNewNodes);
+ Demangler.reset(Mangling.begin(), Mangling.end());
+ // Attempt demangling only for names that look like C++ mangled names.
+ // Otherwise, treat them as extern "C" names. We permit the latter to
+ // be remapped by (eg)
+ // encoding 6memcpy 7memmove
+ // consistent with how they are encoded as local-names inside a C++ mangling.
+ Node *N;
+ if (Mangling.startswith("_Z") || Mangling.startswith("__Z") ||
+ Mangling.startswith("___Z") || Mangling.startswith("____Z"))
+ N = Demangler.parse();
+ else
+ N = Demangler.make<itanium_demangle::NameType>(
+ StringView(Mangling.data(), Mangling.size()));
+ return reinterpret_cast<ItaniumManglingCanonicalizer::Key>(N);
+}
+
ItaniumManglingCanonicalizer::Key
ItaniumManglingCanonicalizer::canonicalize(StringRef Mangling) {
- P->Demangler.ASTAllocator.setCreateNewNodes(true);
- P->Demangler.reset(Mangling.begin(), Mangling.end());
- return reinterpret_cast<Key>(P->Demangler.parse());
+ return parseMaybeMangledName(P->Demangler, Mangling, true);
}
ItaniumManglingCanonicalizer::Key
ItaniumManglingCanonicalizer::lookup(StringRef Mangling) {
- P->Demangler.ASTAllocator.setCreateNewNodes(false);
- P->Demangler.reset(Mangling.begin(), Mangling.end());
- return reinterpret_cast<Key>(P->Demangler.parse());
+ return parseMaybeMangledName(P->Demangler, Mangling, false);
}
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index a6c591fca312..8f3f4aa8caea 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -21,8 +21,8 @@ static KnownBits computeForAddCarry(
assert(!(CarryZero && CarryOne) &&
"Carry can't be zero and one at the same time");
- APInt PossibleSumZero = ~LHS.Zero + ~RHS.Zero + !CarryZero;
- APInt PossibleSumOne = LHS.One + RHS.One + CarryOne;
+ APInt PossibleSumZero = LHS.getMaxValue() + RHS.getMaxValue() + !CarryZero;
+ APInt PossibleSumOne = LHS.getMinValue() + RHS.getMinValue() + CarryOne;
// Compute known bits of the carry.
APInt CarryKnownZero = ~(PossibleSumZero ^ LHS.Zero ^ RHS.Zero);
diff --git a/llvm/lib/Support/LockFileManager.cpp b/llvm/lib/Support/LockFileManager.cpp
index 10181192afbd..5c6508c3b007 100644
--- a/llvm/lib/Support/LockFileManager.cpp
+++ b/llvm/lib/Support/LockFileManager.cpp
@@ -290,7 +290,8 @@ LockFileManager::~LockFileManager() {
sys::DontRemoveFileOnSignal(UniqueLockFileName);
}
-LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() {
+LockFileManager::WaitForUnlockResult
+LockFileManager::waitForUnlock(const unsigned MaxSeconds) {
if (getState() != LFS_Shared)
return Res_Success;
@@ -301,9 +302,6 @@ LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() {
Interval.tv_sec = 0;
Interval.tv_nsec = 1000000;
#endif
- // Don't wait more than 40s per iteration. Total timeout for the file
- // to appear is ~1.5 minutes.
- const unsigned MaxSeconds = 40;
do {
// Sleep for the designated interval, to allow the owning process time to
// finish up and remove the lock file.
diff --git a/llvm/lib/Support/Options.cpp b/llvm/lib/Support/Options.cpp
deleted file mode 100644
index 770b7381c20e..000000000000
--- a/llvm/lib/Support/Options.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===- llvm/Support/Options.cpp - Debug options support ---------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the helper objects for defining debug options using the
-// new API built on cl::opt, but not requiring the use of static globals.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Options.h"
-#include "llvm/Support/ManagedStatic.h"
-
-using namespace llvm;
-
-OptionRegistry::~OptionRegistry() {
- for (auto IT = Options.begin(); IT != Options.end(); ++IT)
- delete IT->second;
-}
-
-void OptionRegistry::addOption(void *Key, cl::Option *O) {
- assert(Options.find(Key) == Options.end() &&
- "Argument with this key already registerd");
- Options.insert(std::make_pair(Key, O));
-}
-
-static ManagedStatic<OptionRegistry> OR;
-
-OptionRegistry &OptionRegistry::instance() { return *OR; }
diff --git a/llvm/lib/Support/Parallel.cpp b/llvm/lib/Support/Parallel.cpp
index 355c64b7d079..523665d14b02 100644
--- a/llvm/lib/Support/Parallel.cpp
+++ b/llvm/lib/Support/Parallel.cpp
@@ -8,14 +8,17 @@
#include "llvm/Support/Parallel.h"
#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/ManagedStatic.h"
#if LLVM_ENABLE_THREADS
#include "llvm/Support/Threading.h"
#include <atomic>
+#include <future>
#include <stack>
#include <thread>
+#include <vector>
namespace llvm {
namespace parallel {
@@ -36,30 +39,53 @@ public:
/// in filo order.
class ThreadPoolExecutor : public Executor {
public:
- explicit ThreadPoolExecutor(unsigned ThreadCount = hardware_concurrency())
- : Done(ThreadCount) {
+ explicit ThreadPoolExecutor(unsigned ThreadCount = hardware_concurrency()) {
// Spawn all but one of the threads in another thread as spawning threads
// can take a while.
- std::thread([&, ThreadCount] {
- for (size_t i = 1; i < ThreadCount; ++i) {
- std::thread([=] { work(); }).detach();
+ Threads.reserve(ThreadCount);
+ Threads.resize(1);
+ std::lock_guard<std::mutex> Lock(Mutex);
+ Threads[0] = std::thread([&, ThreadCount] {
+ for (unsigned i = 1; i < ThreadCount; ++i) {
+ Threads.emplace_back([=] { work(); });
+ if (Stop)
+ break;
}
+ ThreadsCreated.set_value();
work();
- }).detach();
+ });
}
- ~ThreadPoolExecutor() override {
- std::unique_lock<std::mutex> Lock(Mutex);
- Stop = true;
- Lock.unlock();
+ void stop() {
+ {
+ std::lock_guard<std::mutex> Lock(Mutex);
+ if (Stop)
+ return;
+ Stop = true;
+ }
Cond.notify_all();
- // Wait for ~Latch.
+ ThreadsCreated.get_future().wait();
}
+ ~ThreadPoolExecutor() override {
+ stop();
+ std::thread::id CurrentThreadId = std::this_thread::get_id();
+ for (std::thread &T : Threads)
+ if (T.get_id() == CurrentThreadId)
+ T.detach();
+ else
+ T.join();
+ }
+
+ struct Deleter {
+ static void call(void *Ptr) { ((ThreadPoolExecutor *)Ptr)->stop(); }
+ };
+
void add(std::function<void()> F) override {
- std::unique_lock<std::mutex> Lock(Mutex);
- WorkStack.push(F);
- Lock.unlock();
+ {
+ std::lock_guard<std::mutex> Lock(Mutex);
+ WorkStack.push(F);
+ }
Cond.notify_one();
}
@@ -75,19 +101,39 @@ private:
Lock.unlock();
Task();
}
- Done.dec();
}
std::atomic<bool> Stop{false};
std::stack<std::function<void()>> WorkStack;
std::mutex Mutex;
std::condition_variable Cond;
- parallel::detail::Latch Done;
+ std::promise<void> ThreadsCreated;
+ std::vector<std::thread> Threads;
};
Executor *Executor::getDefaultExecutor() {
- static ThreadPoolExecutor exec;
- return &exec;
+ // The ManagedStatic enables the ThreadPoolExecutor to be stopped via
+ // llvm_shutdown() which allows a "clean" fast exit, e.g. via _exit(). This
+ // stops the thread pool and waits for any worker thread creation to complete
+ // but does not wait for the threads to finish. The wait for worker thread
+ // creation to complete is important as it prevents intermittent crashes on
+ // Windows due to a race condition between thread creation and process exit.
+ //
+ // The ThreadPoolExecutor will only be destroyed when the static unique_ptr to
+ // it is destroyed, i.e. in a normal full exit. The ThreadPoolExecutor
+ // destructor ensures it has been stopped and waits for worker threads to
+ // finish. The wait is important as it prevents intermittent crashes on
+ // Windows when the process is doing a full exit.
+ //
+ // The Windows crashes appear to only occur with the MSVC static runtimes and
+ // are more frequent with the debug static runtime.
+ //
+ // This also prevents intermittent deadlocks on exit with the MinGW runtime.
+ static ManagedStatic<ThreadPoolExecutor, object_creator<ThreadPoolExecutor>,
+ ThreadPoolExecutor::Deleter>
+ ManagedExec;
+ static std::unique_ptr<ThreadPoolExecutor> Exec(&(*ManagedExec));
+ return Exec.get();
}
} // namespace
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp
index 14def83802da..3c9a08cb4077 100644
--- a/llvm/lib/Support/Path.cpp
+++ b/llvm/lib/Support/Path.cpp
@@ -496,27 +496,50 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
path.append(ext.begin(), ext.end());
}
-void replace_path_prefix(SmallVectorImpl<char> &Path,
+bool replace_path_prefix(SmallVectorImpl<char> &Path,
const StringRef &OldPrefix, const StringRef &NewPrefix,
- Style style) {
+ Style style, bool strict) {
if (OldPrefix.empty() && NewPrefix.empty())
- return;
+ return false;
StringRef OrigPath(Path.begin(), Path.size());
- if (!OrigPath.startswith(OldPrefix))
- return;
+ StringRef OldPrefixDir;
+
+ if (!strict && OldPrefix.size() > OrigPath.size())
+ return false;
+
+ // Ensure OldPrefixDir does not have a trailing separator.
+ if (!OldPrefix.empty() && is_separator(OldPrefix.back()))
+ OldPrefixDir = parent_path(OldPrefix, style);
+ else
+ OldPrefixDir = OldPrefix;
+
+ if (!OrigPath.startswith(OldPrefixDir))
+ return false;
+
+ if (OrigPath.size() > OldPrefixDir.size())
+ if (!is_separator(OrigPath[OldPrefixDir.size()], style) && strict)
+ return false;
// If prefixes have the same size we can simply copy the new one over.
- if (OldPrefix.size() == NewPrefix.size()) {
+ if (OldPrefixDir.size() == NewPrefix.size() && !strict) {
llvm::copy(NewPrefix, Path.begin());
- return;
+ return true;
}
- StringRef RelPath = OrigPath.substr(OldPrefix.size());
+ StringRef RelPath = OrigPath.substr(OldPrefixDir.size());
SmallString<256> NewPath;
path::append(NewPath, style, NewPrefix);
- path::append(NewPath, style, RelPath);
+ if (!RelPath.empty()) {
+ if (!is_separator(RelPath[0], style) || !strict)
+ path::append(NewPath, style, RelPath);
+ else
+ path::append(NewPath, style, relative_path(RelPath, style));
+ }
+
Path.swap(NewPath);
+
+ return true;
}
void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
diff --git a/llvm/lib/Support/SHA1.cpp b/llvm/lib/Support/SHA1.cpp
index 47a5f07fbe7b..a98ca41a3354 100644
--- a/llvm/lib/Support/SHA1.cpp
+++ b/llvm/lib/Support/SHA1.cpp
@@ -16,6 +16,7 @@
#include "llvm/Support/SHA1.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/Host.h"
using namespace llvm;
@@ -26,45 +27,45 @@ using namespace llvm;
#define SHA_BIG_ENDIAN
#endif
-static uint32_t rol(uint32_t Number, int Bits) {
+static inline uint32_t rol(uint32_t Number, int Bits) {
return (Number << Bits) | (Number >> (32 - Bits));
}
-static uint32_t blk0(uint32_t *Buf, int I) { return Buf[I]; }
+static inline uint32_t blk0(uint32_t *Buf, int I) { return Buf[I]; }
-static uint32_t blk(uint32_t *Buf, int I) {
+static inline uint32_t blk(uint32_t *Buf, int I) {
Buf[I & 15] = rol(Buf[(I + 13) & 15] ^ Buf[(I + 8) & 15] ^ Buf[(I + 2) & 15] ^
Buf[I & 15],
1);
return Buf[I & 15];
}
-static void r0(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E,
- int I, uint32_t *Buf) {
+static inline void r0(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D,
+ uint32_t &E, int I, uint32_t *Buf) {
E += ((B & (C ^ D)) ^ D) + blk0(Buf, I) + 0x5A827999 + rol(A, 5);
B = rol(B, 30);
}
-static void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E,
- int I, uint32_t *Buf) {
+static inline void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D,
+ uint32_t &E, int I, uint32_t *Buf) {
E += ((B & (C ^ D)) ^ D) + blk(Buf, I) + 0x5A827999 + rol(A, 5);
B = rol(B, 30);
}
-static void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E,
- int I, uint32_t *Buf) {
+static inline void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D,
+ uint32_t &E, int I, uint32_t *Buf) {
E += (B ^ C ^ D) + blk(Buf, I) + 0x6ED9EBA1 + rol(A, 5);
B = rol(B, 30);
}
-static void r3(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E,
- int I, uint32_t *Buf) {
+static inline void r3(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D,
+ uint32_t &E, int I, uint32_t *Buf) {
E += (((B | C) & D) | (B & C)) + blk(Buf, I) + 0x8F1BBCDC + rol(A, 5);
B = rol(B, 30);
}
-static void r4(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E,
- int I, uint32_t *Buf) {
+static inline void r4(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D,
+ uint32_t &E, int I, uint32_t *Buf) {
E += (B ^ C ^ D) + blk(Buf, I) + 0xCA62C1D6 + rol(A, 5);
B = rol(B, 30);
}
@@ -210,8 +211,31 @@ void SHA1::writebyte(uint8_t Data) {
}
void SHA1::update(ArrayRef<uint8_t> Data) {
- for (auto &C : Data)
- writebyte(C);
+ InternalState.ByteCount += Data.size();
+
+ // Finish the current block.
+ if (InternalState.BufferOffset > 0) {
+ const size_t Remainder = std::min<size_t>(
+ Data.size(), BLOCK_LENGTH - InternalState.BufferOffset);
+ for (size_t I = 0; I < Remainder; ++I)
+ addUncounted(Data[I]);
+ Data = Data.drop_front(Remainder);
+ }
+
+ // Fast buffer filling for large inputs.
+ while (Data.size() >= BLOCK_LENGTH) {
+ assert(InternalState.BufferOffset == 0);
+ assert(BLOCK_LENGTH % 4 == 0);
+ constexpr size_t BLOCK_LENGTH_32 = BLOCK_LENGTH / 4;
+ for (size_t I = 0; I < BLOCK_LENGTH_32; ++I)
+ InternalState.Buffer.L[I] = support::endian::read32be(&Data[I * 4]);
+ hashBlock();
+ Data = Data.drop_front(BLOCK_LENGTH);
+ }
+
+ // Finish the remainder.
+ for (uint8_t C : Data)
+ addUncounted(C);
}
void SHA1::pad() {
diff --git a/llvm/lib/Support/Signals.cpp b/llvm/lib/Support/Signals.cpp
index 173a07f009d2..add6fde0eb5e 100644
--- a/llvm/lib/Support/Signals.cpp
+++ b/llvm/lib/Support/Signals.cpp
@@ -15,19 +15,19 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Options.h"
#include <vector>
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Support/SpecialCaseList.cpp b/llvm/lib/Support/SpecialCaseList.cpp
index 9bd1f18a4ee7..d1ff44cefb08 100644
--- a/llvm/lib/Support/SpecialCaseList.cpp
+++ b/llvm/lib/Support/SpecialCaseList.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Regex.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <string>
#include <system_error>
#include <utility>
@@ -71,9 +72,9 @@ unsigned SpecialCaseList::Matcher::match(StringRef Query) const {
std::unique_ptr<SpecialCaseList>
SpecialCaseList::create(const std::vector<std::string> &Paths,
- std::string &Error) {
+ llvm::vfs::FileSystem &FS, std::string &Error) {
std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
- if (SCL->createInternal(Paths, Error))
+ if (SCL->createInternal(Paths, FS, Error))
return SCL;
return nullptr;
}
@@ -87,19 +88,20 @@ std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB,
}
std::unique_ptr<SpecialCaseList>
-SpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
+SpecialCaseList::createOrDie(const std::vector<std::string> &Paths,
+ llvm::vfs::FileSystem &FS) {
std::string Error;
- if (auto SCL = create(Paths, Error))
+ if (auto SCL = create(Paths, FS, Error))
return SCL;
report_fatal_error(Error);
}
bool SpecialCaseList::createInternal(const std::vector<std::string> &Paths,
- std::string &Error) {
+ vfs::FileSystem &VFS, std::string &Error) {
StringMap<size_t> Sections;
for (const auto &Path : Paths) {
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
- MemoryBuffer::getFile(Path);
+ VFS.getBufferForFile(Path);
if (std::error_code EC = FileOrErr.getError()) {
Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
return false;
diff --git a/llvm/lib/Support/Statistic.cpp b/llvm/lib/Support/Statistic.cpp
index 8b4177c7fba6..25f13871e2e4 100644
--- a/llvm/lib/Support/Statistic.cpp
+++ b/llvm/lib/Support/Statistic.cpp
@@ -38,7 +38,7 @@ using namespace llvm;
/// -stats - Command line option to cause transformations to emit stats about
/// what they did.
///
-static cl::opt<bool> Stats(
+static cl::opt<bool> EnableStats(
"stats",
cl::desc("Enable statistics output from program (available with Asserts)"),
cl::Hidden);
@@ -104,7 +104,7 @@ void TrackingStatistic::RegisterStatistic() {
// Check Initialized again after acquiring the lock.
if (Initialized.load(std::memory_order_relaxed))
return;
- if (Stats || Enabled)
+ if (EnableStats || Enabled)
SI.addStatistic(this);
// Remember we have been registered.
@@ -119,17 +119,17 @@ StatisticInfo::StatisticInfo() {
// Print information when destroyed, iff command line option is specified.
StatisticInfo::~StatisticInfo() {
- if (::Stats || PrintOnExit)
+ if (EnableStats || PrintOnExit)
llvm::PrintStatistics();
}
-void llvm::EnableStatistics(bool PrintOnExit) {
+void llvm::EnableStatistics(bool DoPrintOnExit) {
Enabled = true;
- ::PrintOnExit = PrintOnExit;
+ PrintOnExit = DoPrintOnExit;
}
bool llvm::AreStatisticsEnabled() {
- return Enabled || Stats;
+ return Enabled || EnableStats;
}
void StatisticInfo::sort() {
@@ -242,7 +242,7 @@ void llvm::PrintStatistics() {
// Check if the -stats option is set instead of checking
// !Stats.Stats.empty(). In release builds, Statistics operators
// do nothing, so stats are never Registered.
- if (Stats) {
+ if (EnableStats) {
// Get the stream to write to.
std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
(*OutStream) << "Statistics are disabled. "
diff --git a/llvm/lib/Support/StringRef.cpp b/llvm/lib/Support/StringRef.cpp
index 4bafc4ec7181..104482de4ad7 100644
--- a/llvm/lib/Support/StringRef.cpp
+++ b/llvm/lib/Support/StringRef.cpp
@@ -12,6 +12,7 @@
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/edit_distance.h"
+#include "llvm/Support/Error.h"
#include <bitset>
using namespace llvm;
@@ -372,11 +373,16 @@ void StringRef::split(SmallVectorImpl<StringRef> &A, char Separator,
size_t StringRef::count(StringRef Str) const {
size_t Count = 0;
size_t N = Str.size();
- if (N > Length)
+ if (!N || N > Length)
return 0;
- for (size_t i = 0, e = Length - N + 1; i != e; ++i)
- if (substr(i, N).equals(Str))
+ for (size_t i = 0, e = Length - N + 1; i < e;) {
+ if (substr(i, N).equals(Str)) {
++Count;
+ i += N;
+ }
+ else
+ ++i;
+ }
return Count;
}
@@ -582,8 +588,11 @@ bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const {
bool StringRef::getAsDouble(double &Result, bool AllowInexact) const {
APFloat F(0.0);
- APFloat::opStatus Status =
- F.convertFromString(*this, APFloat::rmNearestTiesToEven);
+ auto StatusOrErr = F.convertFromString(*this, APFloat::rmNearestTiesToEven);
+ if (errorToBool(StatusOrErr.takeError()))
+ return true;
+
+ APFloat::opStatus Status = *StatusOrErr;
if (Status != APFloat::opOK) {
if (!AllowInexact || !(Status & APFloat::opInexact))
return true;
diff --git a/llvm/lib/Support/TargetParser.cpp b/llvm/lib/Support/TargetParser.cpp
index d213b9a8c6af..84ead58b98cd 100644
--- a/llvm/lib/Support/TargetParser.cpp
+++ b/llvm/lib/Support/TargetParser.cpp
@@ -132,7 +132,7 @@ StringRef llvm::AMDGPU::getArchNameR600(GPUKind AK) {
}
AMDGPU::GPUKind llvm::AMDGPU::parseArchAMDGCN(StringRef CPU) {
- for (const auto C : AMDGCNGPUs) {
+ for (const auto &C : AMDGCNGPUs) {
if (CPU == C.Name)
return C.Kind;
}
@@ -141,7 +141,7 @@ AMDGPU::GPUKind llvm::AMDGPU::parseArchAMDGCN(StringRef CPU) {
}
AMDGPU::GPUKind llvm::AMDGPU::parseArchR600(StringRef CPU) {
- for (const auto C : R600GPUs) {
+ for (const auto &C : R600GPUs) {
if (CPU == C.Name)
return C.Kind;
}
@@ -163,12 +163,12 @@ unsigned AMDGPU::getArchAttrR600(GPUKind AK) {
void AMDGPU::fillValidArchListAMDGCN(SmallVectorImpl<StringRef> &Values) {
// XXX: Should this only report unique canonical names?
- for (const auto C : AMDGCNGPUs)
+ for (const auto &C : AMDGCNGPUs)
Values.push_back(C.Name);
}
void AMDGPU::fillValidArchListR600(SmallVectorImpl<StringRef> &Values) {
- for (const auto C : R600GPUs)
+ for (const auto &C : R600GPUs)
Values.push_back(C.Name);
}
diff --git a/llvm/lib/Support/Threading.cpp b/llvm/lib/Support/Threading.cpp
index e5899a60f4db..48750cef5ec2 100644
--- a/llvm/lib/Support/Threading.cpp
+++ b/llvm/lib/Support/Threading.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Threading.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Host.h"
@@ -39,8 +40,8 @@ bool llvm::llvm_is_multithreaded() {
(!defined(_WIN32) && !defined(HAVE_PTHREAD_H))
// Support for non-Win32, non-pthread implementation.
void llvm::llvm_execute_on_thread(void (*Fn)(void *), void *UserData,
- unsigned RequestedStackSize) {
- (void)RequestedStackSize;
+ llvm::Optional<unsigned> StackSizeInBytes) {
+ (void)StackSizeInBytes;
Fn(UserData);
}
@@ -56,6 +57,25 @@ void llvm::set_thread_name(const Twine &Name) {}
void llvm::get_thread_name(SmallVectorImpl<char> &Name) { Name.clear(); }
+#if LLVM_ENABLE_THREADS == 0
+void llvm::llvm_execute_on_thread_async(
+ llvm::unique_function<void()> Func,
+ llvm::Optional<unsigned> StackSizeInBytes) {
+ (void)Func;
+ (void)StackSizeInBytes;
+ report_fatal_error("Spawning a detached thread doesn't make sense with no "
+ "threading support");
+}
+#else
+// Support for non-Win32, non-pthread implementation.
+void llvm::llvm_execute_on_thread_async(
+ llvm::unique_function<void()> Func,
+ llvm::Optional<unsigned> StackSizeInBytes) {
+ (void)StackSizeInBytes;
+ std::thread(std::move(Func)).detach();
+}
+#endif
+
#else
#include <thread>
@@ -84,6 +104,17 @@ unsigned llvm::hardware_concurrency() {
return 1;
}
+namespace {
+struct SyncThreadInfo {
+ void (*UserFn)(void *);
+ void *UserData;
+};
+
+using AsyncThreadInfo = llvm::unique_function<void()>;
+
+enum class JoiningPolicy { Join, Detach };
+} // namespace
+
// Include the platform-specific parts of this class.
#ifdef LLVM_ON_UNIX
#include "Unix/Threading.inc"
@@ -92,4 +123,20 @@ unsigned llvm::hardware_concurrency() {
#include "Windows/Threading.inc"
#endif
+void llvm::llvm_execute_on_thread(void (*Fn)(void *), void *UserData,
+ llvm::Optional<unsigned> StackSizeInBytes) {
+
+ SyncThreadInfo Info = {Fn, UserData};
+ llvm_execute_on_thread_impl(threadFuncSync, &Info, StackSizeInBytes,
+ JoiningPolicy::Join);
+}
+
+void llvm::llvm_execute_on_thread_async(
+ llvm::unique_function<void()> Func,
+ llvm::Optional<unsigned> StackSizeInBytes) {
+ llvm_execute_on_thread_impl(&threadFuncAsync,
+ new AsyncThreadInfo(std::move(Func)),
+ StackSizeInBytes, JoiningPolicy::Detach);
+}
+
#endif
diff --git a/llvm/lib/Support/TimeProfiler.cpp b/llvm/lib/Support/TimeProfiler.cpp
index ca9119e30b65..a7c85509064e 100644
--- a/llvm/lib/Support/TimeProfiler.cpp
+++ b/llvm/lib/Support/TimeProfiler.cpp
@@ -13,8 +13,8 @@
#include "llvm/Support/TimeProfiler.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/JSON.h"
+#include "llvm/Support/Path.h"
#include <cassert>
#include <chrono>
#include <string>
@@ -33,14 +33,14 @@ typedef std::pair<std::string, CountAndDurationType>
NameAndCountAndDurationType;
struct Entry {
- TimePointType Start;
+ const TimePointType Start;
TimePointType End;
- std::string Name;
- std::string Detail;
+ const std::string Name;
+ const std::string Detail;
Entry(TimePointType &&S, TimePointType &&E, std::string &&N, std::string &&Dt)
: Start(std::move(S)), End(std::move(E)), Name(std::move(N)),
- Detail(std::move(Dt)){};
+ Detail(std::move(Dt)) {}
// Calculate timings for FlameGraph. Cast time points to microsecond precision
// rather than casting duration. This avoid truncation issues causing inner
@@ -59,9 +59,9 @@ struct Entry {
};
struct TimeTraceProfiler {
- TimeTraceProfiler() {
- StartTime = steady_clock::now();
- }
+ TimeTraceProfiler(unsigned TimeTraceGranularity = 0, StringRef ProcName = "")
+ : StartTime(steady_clock::now()), ProcName(ProcName),
+ TimeTraceGranularity(TimeTraceGranularity) {}
void begin(std::string Name, llvm::function_ref<std::string()> Detail) {
Stack.emplace_back(steady_clock::now(), TimePointType(), std::move(Name),
@@ -123,7 +123,9 @@ struct TimeTraceProfiler {
J.attribute("ts", StartUs);
J.attribute("dur", DurUs);
J.attribute("name", E.Name);
- J.attributeObject("args", [&] { J.attribute("detail", E.Detail); });
+ if (!E.Detail.empty()) {
+ J.attributeObject("args", [&] { J.attribute("detail", E.Detail); });
+ }
});
}
@@ -168,7 +170,7 @@ struct TimeTraceProfiler {
J.attribute("ts", 0);
J.attribute("ph", "M");
J.attribute("name", "process_name");
- J.attributeObject("args", [&] { J.attribute("name", "clang"); });
+ J.attributeObject("args", [&] { J.attribute("name", ProcName); });
});
J.arrayEnd();
@@ -179,17 +181,19 @@ struct TimeTraceProfiler {
SmallVector<Entry, 16> Stack;
SmallVector<Entry, 128> Entries;
StringMap<CountAndDurationType> CountAndTotalPerName;
- TimePointType StartTime;
+ const TimePointType StartTime;
+ const std::string ProcName;
// Minimum time granularity (in microseconds)
- unsigned TimeTraceGranularity;
+ const unsigned TimeTraceGranularity;
};
-void timeTraceProfilerInitialize(unsigned TimeTraceGranularity) {
+void timeTraceProfilerInitialize(unsigned TimeTraceGranularity,
+ StringRef ProcName) {
assert(TimeTraceProfilerInstance == nullptr &&
"Profiler should not be initialized");
- TimeTraceProfilerInstance = new TimeTraceProfiler();
- TimeTraceProfilerInstance->TimeTraceGranularity = TimeTraceGranularity;
+ TimeTraceProfilerInstance = new TimeTraceProfiler(
+ TimeTraceGranularity, llvm::sys::path::filename(ProcName));
}
void timeTraceProfilerCleanup() {
diff --git a/llvm/lib/Support/Timer.cpp b/llvm/lib/Support/Timer.cpp
index 10c9b8e0b329..613d2eaae6d3 100644
--- a/llvm/lib/Support/Timer.cpp
+++ b/llvm/lib/Support/Timer.cpp
@@ -91,14 +91,15 @@ static TimerGroup *getDefaultTimerGroup() { return &*DefaultTimerGroup; }
// Timer Implementation
//===----------------------------------------------------------------------===//
-void Timer::init(StringRef Name, StringRef Description) {
- init(Name, Description, *getDefaultTimerGroup());
+void Timer::init(StringRef TimerName, StringRef TimerDescription) {
+ init(TimerName, TimerDescription, *getDefaultTimerGroup());
}
-void Timer::init(StringRef Name, StringRef Description, TimerGroup &tg) {
+void Timer::init(StringRef TimerName, StringRef TimerDescription,
+ TimerGroup &tg) {
assert(!TG && "Timer already initialized");
- this->Name.assign(Name.begin(), Name.end());
- this->Description.assign(Description.begin(), Description.end());
+ Name.assign(TimerName.begin(), TimerName.end());
+ Description.assign(TimerDescription.begin(), TimerDescription.end());
Running = Triggered = false;
TG = &tg;
TG->addTimer(*this);
diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp
index d419463e6a5e..2c480c1094a5 100644
--- a/llvm/lib/Support/Triple.cpp
+++ b/llvm/lib/Support/Triple.cpp
@@ -21,55 +21,56 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
case UnknownArch: return "unknown";
case aarch64: return "aarch64";
- case aarch64_be: return "aarch64_be";
case aarch64_32: return "aarch64_32";
+ case aarch64_be: return "aarch64_be";
+ case amdgcn: return "amdgcn";
+ case amdil64: return "amdil64";
+ case amdil: return "amdil";
+ case arc: return "arc";
case arm: return "arm";
case armeb: return "armeb";
- case arc: return "arc";
case avr: return "avr";
- case bpfel: return "bpfel";
case bpfeb: return "bpfeb";
+ case bpfel: return "bpfel";
case hexagon: return "hexagon";
- case mips: return "mips";
- case mipsel: return "mipsel";
+ case hsail64: return "hsail64";
+ case hsail: return "hsail";
+ case kalimba: return "kalimba";
+ case lanai: return "lanai";
+ case le32: return "le32";
+ case le64: return "le64";
case mips64: return "mips64";
case mips64el: return "mips64el";
+ case mips: return "mips";
+ case mipsel: return "mipsel";
case msp430: return "msp430";
+ case nvptx64: return "nvptx64";
+ case nvptx: return "nvptx";
case ppc64: return "powerpc64";
case ppc64le: return "powerpc64le";
case ppc: return "powerpc";
case r600: return "r600";
- case amdgcn: return "amdgcn";
+ case renderscript32: return "renderscript32";
+ case renderscript64: return "renderscript64";
case riscv32: return "riscv32";
case riscv64: return "riscv64";
+ case shave: return "shave";
case sparc: return "sparc";
- case sparcv9: return "sparcv9";
case sparcel: return "sparcel";
+ case sparcv9: return "sparcv9";
+ case spir64: return "spir64";
+ case spir: return "spir";
case systemz: return "s390x";
case tce: return "tce";
case tcele: return "tcele";
case thumb: return "thumb";
case thumbeb: return "thumbeb";
+ case ve: return "ve";
+ case wasm32: return "wasm32";
+ case wasm64: return "wasm64";
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!");
@@ -144,6 +145,8 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) {
case riscv32:
case riscv64: return "riscv";
+
+ case ve: return "ve";
}
}
@@ -151,22 +154,22 @@ StringRef Triple::getVendorTypeName(VendorType Kind) {
switch (Kind) {
case UnknownVendor: return "unknown";
+ case AMD: return "amd";
case Apple: return "apple";
- case PC: return "pc";
- case SCEI: return "scei";
case BGP: return "bgp";
case BGQ: return "bgq";
+ case CSR: return "csr";
case Freescale: return "fsl";
case IBM: return "ibm";
case ImaginationTechnologies: return "img";
+ case Mesa: return "mesa";
case MipsTechnologies: return "mti";
- case NVIDIA: return "nvidia";
- case CSR: return "csr";
case Myriad: return "myriad";
- case AMD: return "amd";
- case Mesa: return "mesa";
- case SUSE: return "suse";
+ case NVIDIA: return "nvidia";
case OpenEmbedded: return "oe";
+ case PC: return "pc";
+ case SCEI: return "scei";
+ case SUSE: return "suse";
}
llvm_unreachable("Invalid VendorType!");
@@ -176,41 +179,41 @@ StringRef Triple::getOSTypeName(OSType Kind) {
switch (Kind) {
case UnknownOS: return "unknown";
+ case AIX: return "aix";
+ case AMDHSA: return "amdhsa";
+ case AMDPAL: return "amdpal";
case Ananas: return "ananas";
+ case CNK: return "cnk";
+ case CUDA: return "cuda";
case CloudABI: return "cloudabi";
+ case Contiki: return "contiki";
case Darwin: return "darwin";
case DragonFly: return "dragonfly";
+ case ELFIAMCU: return "elfiamcu";
+ case Emscripten: return "emscripten";
case FreeBSD: return "freebsd";
case Fuchsia: return "fuchsia";
+ case Haiku: return "haiku";
+ case HermitCore: return "hermit";
+ case Hurd: return "hurd";
case IOS: return "ios";
case KFreeBSD: return "kfreebsd";
case Linux: return "linux";
case Lv2: return "lv2";
case MacOSX: return "macosx";
- case NetBSD: return "netbsd";
- case OpenBSD: return "openbsd";
- case Solaris: return "solaris";
- case Win32: return "windows";
- case Haiku: return "haiku";
+ case Mesa3D: return "mesa3d";
case Minix: return "minix";
- case RTEMS: return "rtems";
- case NaCl: return "nacl";
- case CNK: return "cnk";
- case AIX: return "aix";
- case CUDA: return "cuda";
case NVCL: return "nvcl";
- case AMDHSA: return "amdhsa";
+ case NaCl: return "nacl";
+ case NetBSD: return "netbsd";
+ case OpenBSD: return "openbsd";
case PS4: return "ps4";
- case ELFIAMCU: return "elfiamcu";
+ case RTEMS: return "rtems";
+ case Solaris: return "solaris";
case TvOS: return "tvos";
- case WatchOS: return "watchos";
- case Mesa3D: return "mesa3d";
- case Contiki: return "contiki";
- case AMDPAL: return "amdpal";
- case HermitCore: return "hermit";
- case Hurd: return "hurd";
case WASI: return "wasi";
- case Emscripten: return "emscripten";
+ case WatchOS: return "watchos";
+ case Win32: return "windows";
}
llvm_unreachable("Invalid OSType");
@@ -219,27 +222,25 @@ StringRef Triple::getOSTypeName(OSType Kind) {
StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) {
switch (Kind) {
case UnknownEnvironment: return "unknown";
+ case Android: return "android";
+ case CODE16: return "code16";
+ case CoreCLR: return "coreclr";
+ case Cygnus: return "cygnus";
+ case EABI: return "eabi";
+ case EABIHF: return "eabihf";
case GNU: return "gnu";
- case GNUABIN32: return "gnuabin32";
case GNUABI64: return "gnuabi64";
- case GNUEABIHF: return "gnueabihf";
+ case GNUABIN32: return "gnuabin32";
case GNUEABI: return "gnueabi";
+ case GNUEABIHF: return "gnueabihf";
case GNUX32: return "gnux32";
- case CODE16: return "code16";
- case EABI: return "eabi";
- case EABIHF: return "eabihf";
- case ELFv1: return "elfv1";
- case ELFv2: return "elfv2";
- case Android: return "android";
+ case Itanium: return "itanium";
+ case MSVC: return "msvc";
+ case MacABI: return "macabi";
case Musl: return "musl";
case MuslEABI: return "musleabi";
case MuslEABIHF: return "musleabihf";
- case MSVC: return "msvc";
- case Itanium: return "itanium";
- case Cygnus: return "cygnus";
- case CoreCLR: return "coreclr";
case Simulator: return "simulator";
- case MacABI: return "macabi";
}
llvm_unreachable("Invalid EnvironmentType!");
@@ -315,6 +316,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("wasm64", wasm64)
.Case("renderscript32", renderscript32)
.Case("renderscript64", renderscript64)
+ .Case("ve", ve)
.Default(UnknownArch);
}
@@ -389,7 +391,7 @@ static Triple::ArchType parseArch(StringRef ArchName) {
// FIXME: Do we need to support these?
.Cases("i786", "i886", "i986", Triple::x86)
.Cases("amd64", "x86_64", "x86_64h", Triple::x86_64)
- .Cases("powerpc", "ppc", "ppc32", Triple::ppc)
+ .Cases("powerpc", "powerpcspe", "ppc", "ppc32", Triple::ppc)
.Cases("powerpc64", "ppu", "ppc64", Triple::ppc64)
.Cases("powerpc64le", "ppc64le", Triple::ppc64le)
.Case("xscale", Triple::arm)
@@ -438,11 +440,12 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("spir64", Triple::spir64)
.StartsWith("kalimba", Triple::kalimba)
.Case("lanai", Triple::lanai)
+ .Case("renderscript32", Triple::renderscript32)
+ .Case("renderscript64", Triple::renderscript64)
.Case("shave", Triple::shave)
+ .Case("ve", Triple::ve)
.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
@@ -524,8 +527,6 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) {
return StringSwitch<Triple::EnvironmentType>(EnvironmentName)
.StartsWith("eabihf", Triple::EABIHF)
.StartsWith("eabi", Triple::EABI)
- .StartsWith("elfv1", Triple::ELFv1)
- .StartsWith("elfv2", Triple::ELFv2)
.StartsWith("gnuabin32", Triple::GNUABIN32)
.StartsWith("gnuabi64", Triple::GNUABI64)
.StartsWith("gnueabihf", Triple::GNUEABIHF)
@@ -563,6 +564,9 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) {
(SubArchName.endswith("r6el") || SubArchName.endswith("r6")))
return Triple::MipsSubArch_r6;
+ if (SubArchName == "powerpcspe")
+ return Triple::PPCSubArch_spe;
+
StringRef ARMSubArch = ARM::getCanonicalArchName(SubArchName);
// For now, this is the small part. Early return.
@@ -637,10 +641,10 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) {
static StringRef getObjectFormatTypeName(Triple::ObjectFormatType Kind) {
switch (Kind) {
case Triple::UnknownObjectFormat: return "";
- case Triple::COFF: return "coff";
- case Triple::ELF: return "elf";
+ case Triple::COFF: return "coff";
+ case Triple::ELF: return "elf";
case Triple::MachO: return "macho";
- case Triple::Wasm: return "wasm";
+ case Triple::Wasm: return "wasm";
case Triple::XCOFF: return "xcoff";
}
llvm_unreachable("unknown object format type");
@@ -662,28 +666,28 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
return Triple::ELF;
case Triple::aarch64_be:
- case Triple::arc:
case Triple::amdgcn:
- case Triple::amdil:
case Triple::amdil64:
+ case Triple::amdil:
+ case Triple::arc:
case Triple::armeb:
case Triple::avr:
case Triple::bpfeb:
case Triple::bpfel:
case Triple::hexagon:
- case Triple::lanai:
- case Triple::hsail:
case Triple::hsail64:
+ case Triple::hsail:
case Triple::kalimba:
+ case Triple::lanai:
case Triple::le32:
case Triple::le64:
- case Triple::mips:
case Triple::mips64:
case Triple::mips64el:
+ case Triple::mips:
case Triple::mipsel:
case Triple::msp430:
- case Triple::nvptx:
case Triple::nvptx64:
+ case Triple::nvptx:
case Triple::ppc64le:
case Triple::r600:
case Triple::renderscript32:
@@ -694,17 +698,18 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
case Triple::sparc:
case Triple::sparcel:
case Triple::sparcv9:
- case Triple::spir:
case Triple::spir64:
+ case Triple::spir:
case Triple::systemz:
case Triple::tce:
case Triple::tcele:
case Triple::thumbeb:
+ case Triple::ve:
case Triple::xcore:
return Triple::ELF;
- case Triple::ppc:
case Triple::ppc64:
+ case Triple::ppc:
if (T.isOSDarwin())
return Triple::MachO;
else if (T.isOSAIX())
@@ -1235,55 +1240,56 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
return 16;
case llvm::Triple::aarch64_32:
+ case llvm::Triple::amdil:
case llvm::Triple::arc:
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::hexagon:
+ case llvm::Triple::hsail:
+ case llvm::Triple::kalimba:
+ case llvm::Triple::lanai:
case llvm::Triple::le32:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::nvptx:
case llvm::Triple::ppc:
case llvm::Triple::r600:
+ case llvm::Triple::renderscript32:
case llvm::Triple::riscv32:
+ case llvm::Triple::shave:
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
+ case llvm::Triple::spir:
case llvm::Triple::tce:
case llvm::Triple::tcele:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
+ case llvm::Triple::wasm32:
case llvm::Triple::x86:
case llvm::Triple::xcore:
- case llvm::Triple::amdil:
- 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:
case llvm::Triple::aarch64_be:
case llvm::Triple::amdgcn:
- case llvm::Triple::bpfel:
+ case llvm::Triple::amdil64:
case llvm::Triple::bpfeb:
+ case llvm::Triple::bpfel:
+ case llvm::Triple::hsail64:
case llvm::Triple::le64:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
case llvm::Triple::nvptx64:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
+ case llvm::Triple::renderscript64:
case llvm::Triple::riscv64:
case llvm::Triple::sparcv9:
- case llvm::Triple::systemz:
- case llvm::Triple::x86_64:
- case llvm::Triple::amdil64:
- case llvm::Triple::hsail64:
case llvm::Triple::spir64:
+ case llvm::Triple::systemz:
+ case llvm::Triple::ve:
case llvm::Triple::wasm64:
- case llvm::Triple::renderscript64:
+ case llvm::Triple::x86_64:
return 64;
}
llvm_unreachable("Invalid architecture value");
@@ -1307,60 +1313,61 @@ Triple Triple::get32BitArchVariant() const {
case Triple::UnknownArch:
case Triple::amdgcn:
case Triple::avr:
- case Triple::bpfel:
case Triple::bpfeb:
+ case Triple::bpfel:
case Triple::msp430:
- case Triple::systemz:
case Triple::ppc64le:
+ case Triple::systemz:
+ case Triple::ve:
T.setArch(UnknownArch);
break;
case Triple::aarch64_32:
case Triple::amdil:
- case Triple::hsail:
- case Triple::spir:
case Triple::arc:
case Triple::arm:
case Triple::armeb:
case Triple::hexagon:
+ case Triple::hsail:
case Triple::kalimba:
+ case Triple::lanai:
case Triple::le32:
case Triple::mips:
case Triple::mipsel:
case Triple::nvptx:
case Triple::ppc:
case Triple::r600:
+ case Triple::renderscript32:
case Triple::riscv32:
+ case Triple::shave:
case Triple::sparc:
case Triple::sparcel:
+ case Triple::spir:
case Triple::tce:
case Triple::tcele:
case Triple::thumb:
case Triple::thumbeb:
+ case Triple::wasm32:
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::amdil64: T.setArch(Triple::amdil); break;
+ case Triple::hsail64: T.setArch(Triple::hsail); 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::renderscript64: T.setArch(Triple::renderscript32); break;
case Triple::riscv64: T.setArch(Triple::riscv32); 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::sparcv9: T.setArch(Triple::sparc); 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;
+ case Triple::x86_64: T.setArch(Triple::x86); break;
}
return T;
}
@@ -1376,55 +1383,56 @@ Triple Triple::get64BitArchVariant() const {
case Triple::lanai:
case Triple::msp430:
case Triple::r600:
+ case Triple::shave:
+ case Triple::sparcel:
case Triple::tce:
case Triple::tcele:
case Triple::xcore:
- case Triple::sparcel:
- case Triple::shave:
T.setArch(UnknownArch);
break;
case Triple::aarch64:
case Triple::aarch64_be:
- case Triple::bpfel:
- case Triple::bpfeb:
- case Triple::le64:
- case Triple::amdil64:
case Triple::amdgcn:
+ case Triple::amdil64:
+ case Triple::bpfeb:
+ case Triple::bpfel:
case Triple::hsail64:
- case Triple::spir64:
+ case Triple::le64:
case Triple::mips64:
case Triple::mips64el:
case Triple::nvptx64:
case Triple::ppc64:
case Triple::ppc64le:
+ case Triple::renderscript64:
case Triple::riscv64:
case Triple::sparcv9:
+ case Triple::spir64:
case Triple::systemz:
- case Triple::x86_64:
+ case Triple::ve:
case Triple::wasm64:
- case Triple::renderscript64:
+ case Triple::x86_64:
// Already 64-bit.
break;
case Triple::aarch64_32: T.setArch(Triple::aarch64); break;
+ case Triple::amdil: T.setArch(Triple::amdil64); break;
case Triple::arm: T.setArch(Triple::aarch64); break;
case Triple::armeb: T.setArch(Triple::aarch64_be); break;
+ case Triple::hsail: T.setArch(Triple::hsail64); 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::renderscript32: T.setArch(Triple::renderscript64); break;
case Triple::riscv32: T.setArch(Triple::riscv64); 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::sparc: T.setArch(Triple::sparcv9); 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;
+ case Triple::x86: T.setArch(Triple::x86_64); break;
}
return T;
}
@@ -1450,6 +1458,8 @@ Triple Triple::getBigEndianArchVariant() const {
case Triple::nvptx64:
case Triple::nvptx:
case Triple::r600:
+ case Triple::renderscript32:
+ case Triple::renderscript64:
case Triple::riscv32:
case Triple::riscv64:
case Triple::shave:
@@ -1460,8 +1470,7 @@ Triple Triple::getBigEndianArchVariant() const {
case Triple::x86:
case Triple::x86_64:
case Triple::xcore:
- case Triple::renderscript32:
- case Triple::renderscript64:
+ case Triple::ve:
// ARM is intentionally unsupported here, changing the architecture would
// drop any arch suffixes.
@@ -1470,13 +1479,13 @@ Triple Triple::getBigEndianArchVariant() const {
T.setArch(UnknownArch);
break;
- case Triple::tcele: T.setArch(Triple::tce); 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;
+ case Triple::tcele: T.setArch(Triple::tce); break;
default:
llvm_unreachable("getBigEndianArchVariant: unknown triple.");
}
@@ -1502,13 +1511,13 @@ Triple Triple::getLittleEndianArchVariant() const {
T.setArch(UnknownArch);
break;
- case Triple::tce: T.setArch(Triple::tcele); 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::tce: T.setArch(Triple::tcele); break;
default:
llvm_unreachable("getLittleEndianArchVariant: unknown triple.");
}
@@ -1538,21 +1547,22 @@ bool Triple::isLittleEndian() const {
case Triple::nvptx:
case Triple::ppc64le:
case Triple::r600:
+ case Triple::renderscript32:
+ case Triple::renderscript64:
case Triple::riscv32:
case Triple::riscv64:
case Triple::shave:
case Triple::sparcel:
case Triple::spir64:
case Triple::spir:
+ case Triple::tcele:
case Triple::thumb:
+ case Triple::ve:
case Triple::wasm32:
case Triple::wasm64:
case Triple::x86:
case Triple::x86_64:
case Triple::xcore:
- case Triple::tcele:
- case Triple::renderscript32:
- case Triple::renderscript64:
return true;
default:
return false;
@@ -1607,10 +1617,10 @@ StringRef Triple::getARMCPUForArch(StringRef MArch) const {
case llvm::Triple::Win32:
// FIXME: this is invalid for WindowsCE
return "cortex-a9";
- case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
- case llvm::Triple::WatchOS:
+ case llvm::Triple::MacOSX:
case llvm::Triple::TvOS:
+ case llvm::Triple::WatchOS:
if (MArch == "v7k")
return "cortex-a7";
break;
@@ -1630,10 +1640,10 @@ StringRef Triple::getARMCPUForArch(StringRef MArch) const {
switch (getOS()) {
case llvm::Triple::NetBSD:
switch (getEnvironment()) {
- case llvm::Triple::GNUEABIHF:
- case llvm::Triple::GNUEABI:
- case llvm::Triple::EABIHF:
case llvm::Triple::EABI:
+ case llvm::Triple::EABIHF:
+ case llvm::Triple::GNUEABI:
+ case llvm::Triple::GNUEABIHF:
return "arm926ej-s";
default:
return "strongarm";
diff --git a/llvm/lib/Support/Unix/Memory.inc b/llvm/lib/Support/Unix/Memory.inc
index 05f8e32896fa..79b1759359e1 100644
--- a/llvm/lib/Support/Unix/Memory.inc
+++ b/llvm/lib/Support/Unix/Memory.inc
@@ -42,9 +42,7 @@ extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
extern "C" void __clear_cache(void *, void*);
#endif
-namespace {
-
-int getPosixProtectionFlags(unsigned Flags) {
+static int getPosixProtectionFlags(unsigned Flags) {
switch (Flags & llvm::sys::Memory::MF_RWE_MASK) {
case llvm::sys::Memory::MF_READ:
return PROT_READ;
@@ -76,8 +74,6 @@ int getPosixProtectionFlags(unsigned Flags) {
return PROT_NONE;
}
-} // anonymous namespace
-
namespace llvm {
namespace sys {
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index a617eca3566a..2a03dc682bce 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -38,6 +38,14 @@
#include <mach-o/dyld.h>
#include <sys/attr.h>
#include <copyfile.h>
+#elif defined(__FreeBSD__)
+#include <osreldate.h>
+#if __FreeBSD_version >= 1300057
+#include <sys/auxv.h>
+#else
+#include <machine/elf.h>
+extern char **environ;
+#endif
#elif defined(__DragonFly__)
#include <sys/mount.h>
#endif
@@ -183,13 +191,40 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) {
if (realpath(exe_path, link_path))
return link_path;
}
-#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
- defined(__minix) || defined(__DragonFly__) || \
- defined(__FreeBSD_kernel__) || defined(_AIX)
+#elif defined(__FreeBSD__)
+ // On FreeBSD if the exec path specified in ELF auxiliary vectors is
+ // preferred, if available. /proc/curproc/file and the KERN_PROC_PATHNAME
+ // sysctl may not return the desired path if there are multiple hardlinks
+ // to the file.
+ char exe_path[PATH_MAX];
+#if __FreeBSD_version >= 1300057
+ if (elf_aux_info(AT_EXECPATH, exe_path, sizeof(exe_path)) == 0)
+ return exe_path;
+#else
+ // elf_aux_info(AT_EXECPATH, ... is not available in all supported versions,
+ // fall back to finding the ELF auxiliary vectors after the process's
+ // environment.
+ char **p = ::environ;
+ while (*p++ != 0)
+ ;
+ // Iterate through auxiliary vectors for AT_EXECPATH.
+ for (;;) {
+ switch (*(uintptr_t *)p++) {
+ case AT_EXECPATH:
+ return *p;
+ case AT_NULL:
+ break;
+ }
+ p++;
+ }
+#endif
+ // Fall back to argv[0] if auxiliary vectors are not available.
+ if (getprogpath(exe_path, argv0) != NULL)
+ return exe_path;
+#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__minix) || \
+ defined(__DragonFly__) || defined(__FreeBSD_kernel__) || defined(_AIX)
const char *curproc = "/proc/curproc/file";
char exe_path[PATH_MAX];
- // /proc is not mounted by default under FreeBSD, but gives more accurate
- // information than argv[0] when it is.
if (sys::fs::exists(curproc)) {
ssize_t len = readlink(curproc, exe_path, sizeof(exe_path));
if (len > 0) {
@@ -203,7 +238,7 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) {
// If we don't have procfs mounted, fall back to argv[0]
if (getprogpath(exe_path, argv0) != NULL)
return exe_path;
-#elif defined(__linux__) || defined(__CYGWIN__)
+#elif defined(__linux__) || defined(__CYGWIN__) || defined(__gnu_hurd__)
char exe_path[MAXPATHLEN];
const char *aPath = "/proc/self/exe";
if (sys::fs::exists(aPath)) {
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index 5e0cde4a81ed..f68374d29f02 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -82,18 +82,15 @@ using namespace llvm;
static RETSIGTYPE SignalHandler(int Sig); // defined below.
static RETSIGTYPE InfoSignalHandler(int Sig); // defined below.
-static void DefaultPipeSignalFunction() {
- exit(EX_IOERR);
-}
-
using SignalHandlerFunctionType = void (*)();
/// The function to call if ctrl-c is pressed.
static std::atomic<SignalHandlerFunctionType> InterruptFunction =
ATOMIC_VAR_INIT(nullptr);
static std::atomic<SignalHandlerFunctionType> InfoSignalFunction =
ATOMIC_VAR_INIT(nullptr);
-static std::atomic<SignalHandlerFunctionType> PipeSignalFunction =
- ATOMIC_VAR_INIT(DefaultPipeSignalFunction);
+/// The function to call on SIGPIPE (one-time use only).
+static std::atomic<SignalHandlerFunctionType> OneShotPipeSignalFunction =
+ ATOMIC_VAR_INIT(nullptr);
namespace {
/// Signal-safe removal of files.
@@ -212,7 +209,7 @@ static StringRef Argv0;
/// if there is, it's not our direct responsibility. For whatever reason, our
/// continued execution is no longer desirable.
static const int IntSigs[] = {
- SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR2
+ SIGHUP, SIGINT, SIGTERM, SIGUSR2
};
/// Signals that represent that we have a bug, and our prompt termination has
@@ -243,7 +240,7 @@ static const int InfoSigs[] = {
static const size_t NumSigs =
array_lengthof(IntSigs) + array_lengthof(KillSigs) +
- array_lengthof(InfoSigs);
+ array_lengthof(InfoSigs) + 1 /* SIGPIPE */;
static std::atomic<unsigned> NumRegisteredSignals = ATOMIC_VAR_INIT(0);
@@ -328,6 +325,8 @@ static void RegisterHandlers() { // Not signal-safe.
registerHandler(S, SignalKind::IsKill);
for (auto S : KillSigs)
registerHandler(S, SignalKind::IsKill);
+ if (OneShotPipeSignalFunction)
+ registerHandler(SIGPIPE, SignalKind::IsKill);
for (auto S : InfoSigs)
registerHandler(S, SignalKind::IsInfo);
}
@@ -346,6 +345,22 @@ static void RemoveFilesToRemove() {
FileToRemoveList::removeAllFiles(FilesToRemove);
}
+void sys::CleanupOnSignal(uintptr_t Context) {
+ int Sig = (int)Context;
+
+ if (llvm::is_contained(InfoSigs, Sig)) {
+ InfoSignalHandler(Sig);
+ return;
+ }
+
+ RemoveFilesToRemove();
+
+ if (llvm::is_contained(IntSigs, Sig) || Sig == SIGPIPE)
+ return;
+
+ llvm::sys::RunSignalHandlers();
+}
+
// The signal handler that runs.
static RETSIGTYPE SignalHandler(int Sig) {
// Restore the signal behavior to default, so that the program actually
@@ -362,16 +377,16 @@ static RETSIGTYPE SignalHandler(int Sig) {
{
RemoveFilesToRemove();
+ if (Sig == SIGPIPE)
+ if (auto OldOneShotPipeFunction =
+ OneShotPipeSignalFunction.exchange(nullptr))
+ return OldOneShotPipeFunction();
+
if (std::find(std::begin(IntSigs), std::end(IntSigs), Sig)
!= std::end(IntSigs)) {
if (auto OldInterruptFunction = InterruptFunction.exchange(nullptr))
return OldInterruptFunction();
- // Send a special return code that drivers can check for, from sysexits.h.
- if (Sig == SIGPIPE)
- if (SignalHandlerFunctionType CurrentPipeFunction = PipeSignalFunction)
- CurrentPipeFunction();
-
raise(Sig); // Execute the default handler.
return;
}
@@ -410,11 +425,16 @@ void llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
RegisterHandlers();
}
-void llvm::sys::SetPipeSignalFunction(void (*Handler)()) {
- PipeSignalFunction.exchange(Handler);
+void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
+ OneShotPipeSignalFunction.exchange(Handler);
RegisterHandlers();
}
+void llvm::sys::DefaultOneShotPipeSignalHandler() {
+ // Send a special return code that drivers can check for, from sysexits.h.
+ exit(EX_IOERR);
+}
+
// The public API
bool llvm::sys::RemoveFileOnSignal(StringRef Filename,
std::string* ErrMsg) {
diff --git a/llvm/lib/Support/Unix/Threading.inc b/llvm/lib/Support/Unix/Threading.inc
index ed9a96563055..afb887fc1096 100644
--- a/llvm/lib/Support/Unix/Threading.inc
+++ b/llvm/lib/Support/Unix/Threading.inc
@@ -10,6 +10,8 @@
//
//===----------------------------------------------------------------------===//
+#include "Unix.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
@@ -40,47 +42,56 @@
#include <unistd.h> // For syscall()
#endif
-namespace {
- struct ThreadInfo {
- void(*UserFn)(void *);
- void *UserData;
- };
+static void *threadFuncSync(void *Arg) {
+ SyncThreadInfo *TI = static_cast<SyncThreadInfo *>(Arg);
+ TI->UserFn(TI->UserData);
+ return nullptr;
}
-static void *ExecuteOnThread_Dispatch(void *Arg) {
- ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
- TI->UserFn(TI->UserData);
+static void *threadFuncAsync(void *Arg) {
+ std::unique_ptr<AsyncThreadInfo> Info(static_cast<AsyncThreadInfo *>(Arg));
+ (*Info)();
return nullptr;
}
-void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData,
- unsigned RequestedStackSize) {
- ThreadInfo Info = { Fn, UserData };
- pthread_attr_t Attr;
- pthread_t Thread;
+static void
+llvm_execute_on_thread_impl(void *(*ThreadFunc)(void *), void *Arg,
+ llvm::Optional<unsigned> StackSizeInBytes,
+ JoiningPolicy JP) {
+ int errnum;
// Construct the attributes object.
- if (::pthread_attr_init(&Attr) != 0)
- return;
+ pthread_attr_t Attr;
+ if ((errnum = ::pthread_attr_init(&Attr)) != 0) {
+ ReportErrnumFatal("pthread_attr_init failed", errnum);
+ }
+
+ auto AttrGuard = llvm::make_scope_exit([&] {
+ if ((errnum = ::pthread_attr_destroy(&Attr)) != 0) {
+ ReportErrnumFatal("pthread_attr_destroy failed", errnum);
+ }
+ });
// Set the requested stack size, if given.
- if (RequestedStackSize != 0) {
- if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
- goto error;
+ if (StackSizeInBytes) {
+ if ((errnum = ::pthread_attr_setstacksize(&Attr, *StackSizeInBytes)) != 0) {
+ ReportErrnumFatal("pthread_attr_setstacksize failed", errnum);
+ }
}
// Construct and execute the thread.
- if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
- goto error;
-
- // Wait for the thread and clean up.
- ::pthread_join(Thread, nullptr);
+ pthread_t Thread;
+ if ((errnum = ::pthread_create(&Thread, &Attr, ThreadFunc, Arg)) != 0)
+ ReportErrnumFatal("pthread_create failed", errnum);
-error:
- ::pthread_attr_destroy(&Attr);
+ if (JP == JoiningPolicy::Join) {
+ // Wait for the thread
+ if ((errnum = ::pthread_join(Thread, nullptr)) != 0) {
+ ReportErrnumFatal("pthread_join failed", errnum);
+ }
+ }
}
-
uint64_t llvm::get_threadid() {
#if defined(__APPLE__)
// Calling "mach_thread_self()" bumps the reference count on the thread
diff --git a/llvm/lib/Support/Unix/Unix.h b/llvm/lib/Support/Unix/Unix.h
index 86309b0567f5..1fc9a414f749 100644
--- a/llvm/lib/Support/Unix/Unix.h
+++ b/llvm/lib/Support/Unix/Unix.h
@@ -21,6 +21,7 @@
#include "llvm/Config/config.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Errno.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <assert.h>
#include <cerrno>
@@ -69,6 +70,14 @@ static inline bool MakeErrMsg(
return true;
}
+// Include StrError(errnum) in a fatal error message.
+LLVM_ATTRIBUTE_NORETURN static inline void ReportErrnumFatal(const char *Msg,
+ int errnum) {
+ std::string ErrMsg;
+ MakeErrMsg(&ErrMsg, Msg, errnum);
+ llvm::report_fatal_error(ErrMsg);
+}
+
namespace llvm {
namespace sys {
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index c390cb1b2227..edd4234fe501 100644
--- a/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/llvm/lib/Support/VirtualFileSystem.cpp
@@ -894,7 +894,7 @@ class InMemoryDirIterator : public llvm::vfs::detail::DirIterImpl {
if (I != E) {
SmallString<256> Path(RequestedDirName);
llvm::sys::path::append(Path, I->second->getFileName());
- sys::fs::file_type Type;
+ sys::fs::file_type Type = sys::fs::file_type::type_unknown;
switch (I->second->getKind()) {
case detail::IME_File:
case detail::IME_HardLink:
@@ -1073,6 +1073,19 @@ std::error_code RedirectingFileSystem::isLocal(const Twine &Path,
return ExternalFS->isLocal(Path, Result);
}
+std::error_code RedirectingFileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
+ if (llvm::sys::path::is_absolute(Path, llvm::sys::path::Style::posix) ||
+ llvm::sys::path::is_absolute(Path, llvm::sys::path::Style::windows))
+ return {};
+
+ auto WorkingDir = getCurrentWorkingDirectory();
+ if (!WorkingDir)
+ return WorkingDir.getError();
+
+ llvm::sys::fs::make_absolute(WorkingDir.get(), Path);
+ return {};
+}
+
directory_iterator RedirectingFileSystem::dir_begin(const Twine &Dir,
std::error_code &EC) {
ErrorOr<RedirectingFileSystem::Entry *> E = lookupPath(Dir);
@@ -1428,21 +1441,31 @@ class llvm::vfs::RedirectingFileSystemParser {
return nullptr;
}
- if (IsRootEntry && !sys::path::is_absolute(Name)) {
- assert(NameValueNode && "Name presence should be checked earlier");
- error(NameValueNode,
- "entry with relative path at the root level is not discoverable");
- return nullptr;
+ sys::path::Style path_style = sys::path::Style::native;
+ if (IsRootEntry) {
+ // VFS root entries may be in either Posix or Windows style. Figure out
+ // which style we have, and use it consistently.
+ if (sys::path::is_absolute(Name, sys::path::Style::posix)) {
+ path_style = sys::path::Style::posix;
+ } else if (sys::path::is_absolute(Name, sys::path::Style::windows)) {
+ path_style = sys::path::Style::windows;
+ } else {
+ assert(NameValueNode && "Name presence should be checked earlier");
+ error(NameValueNode,
+ "entry with relative path at the root level is not discoverable");
+ return nullptr;
+ }
}
// Remove trailing slash(es), being careful not to remove the root path
StringRef Trimmed(Name);
- size_t RootPathLen = sys::path::root_path(Trimmed).size();
+ size_t RootPathLen = sys::path::root_path(Trimmed, path_style).size();
while (Trimmed.size() > RootPathLen &&
- sys::path::is_separator(Trimmed.back()))
+ sys::path::is_separator(Trimmed.back(), path_style))
Trimmed = Trimmed.slice(0, Trimmed.size() - 1);
+
// Get the last component
- StringRef LastComponent = sys::path::filename(Trimmed);
+ StringRef LastComponent = sys::path::filename(Trimmed, path_style);
std::unique_ptr<RedirectingFileSystem::Entry> Result;
switch (Kind) {
@@ -1460,12 +1483,12 @@ class llvm::vfs::RedirectingFileSystemParser {
break;
}
- StringRef Parent = sys::path::parent_path(Trimmed);
+ StringRef Parent = sys::path::parent_path(Trimmed, path_style);
if (Parent.empty())
return Result;
// if 'name' contains multiple components, create implicit directory entries
- for (sys::path::reverse_iterator I = sys::path::rbegin(Parent),
+ for (sys::path::reverse_iterator I = sys::path::rbegin(Parent, path_style),
E = sys::path::rend(Parent);
I != E; ++I) {
std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> Entries;
@@ -1671,9 +1694,7 @@ RedirectingFileSystem::lookupPath(sys::path::const_iterator Start,
// Forward the search to the next component in case this is an empty one.
if (!FromName.empty()) {
- if (CaseSensitive ? !Start->equals(FromName)
- : !Start->equals_lower(FromName))
- // failure to match
+ if (!pathComponentMatches(*Start, FromName))
return make_error_code(llvm::errc::no_such_file_or_directory);
++Start;
@@ -1695,6 +1716,7 @@ RedirectingFileSystem::lookupPath(sys::path::const_iterator Start,
if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
return Result;
}
+
return make_error_code(llvm::errc::no_such_file_or_directory);
}
@@ -2073,7 +2095,7 @@ std::error_code VFSFromYamlDirIterImpl::incrementContent(bool IsFirstTime) {
while (Current != End) {
SmallString<128> PathStr(Dir);
llvm::sys::path::append(PathStr, (*Current)->getName());
- sys::fs::file_type Type;
+ sys::fs::file_type Type = sys::fs::file_type::type_unknown;
switch ((*Current)->getKind()) {
case RedirectingFileSystem::EK_Directory:
Type = sys::fs::file_type::directory_file;
diff --git a/llvm/lib/Support/Windows/Memory.inc b/llvm/lib/Support/Windows/Memory.inc
index a67f9c7d0f35..c5566f9910a5 100644
--- a/llvm/lib/Support/Windows/Memory.inc
+++ b/llvm/lib/Support/Windows/Memory.inc
@@ -19,9 +19,7 @@
// The Windows.h header must be the last one included.
#include "WindowsSupport.h"
-namespace {
-
-DWORD getWindowsProtectionFlags(unsigned Flags) {
+static DWORD getWindowsProtectionFlags(unsigned Flags) {
switch (Flags & llvm::sys::Memory::MF_RWE_MASK) {
// Contrary to what you might expect, the Windows page protection flags
// are not a bitwise combination of RWX values
@@ -50,7 +48,7 @@ DWORD getWindowsProtectionFlags(unsigned Flags) {
// While we'd be happy to allocate single pages, the Windows allocation
// granularity may be larger than a single page (in practice, it is 64K)
// so mapping less than that will create an unreachable fragment of memory.
-size_t getAllocationGranularity() {
+static size_t getAllocationGranularity() {
SYSTEM_INFO Info;
::GetSystemInfo(&Info);
if (Info.dwPageSize > Info.dwAllocationGranularity)
@@ -91,8 +89,6 @@ static size_t enableProcessLargePages() {
return 0;
}
-} // namespace
-
namespace llvm {
namespace sys {
diff --git a/llvm/lib/Support/Windows/Process.inc b/llvm/lib/Support/Windows/Process.inc
index 4b91f9f7fc66..3526e3dee6fa 100644
--- a/llvm/lib/Support/Windows/Process.inc
+++ b/llvm/lib/Support/Windows/Process.inc
@@ -439,13 +439,6 @@ const char *Process::ResetColor() {
return 0;
}
-// Include GetLastError() in a fatal error message.
-static void ReportLastErrorFatal(const char *Msg) {
- std::string ErrMsg;
- MakeErrMsg(&ErrMsg, Msg);
- report_fatal_error(ErrMsg);
-}
-
unsigned Process::GetRandomNumber() {
HCRYPTPROV HCPC;
if (!::CryptAcquireContextW(&HCPC, NULL, NULL, PROV_RSA_FULL,
diff --git a/llvm/lib/Support/Windows/Program.inc b/llvm/lib/Support/Windows/Program.inc
index a23ed95fc390..a1482bf17c60 100644
--- a/llvm/lib/Support/Windows/Program.inc
+++ b/llvm/lib/Support/Windows/Program.inc
@@ -197,7 +197,7 @@ static bool Execute(ProcessInfo &PI, StringRef Program,
// An environment block consists of a null-terminated block of
// null-terminated strings. Convert the array of environment variables to
// an environment block by concatenating them.
- for (const auto E : *Env) {
+ for (StringRef E : *Env) {
SmallVector<wchar_t, MAX_PATH> EnvString;
if (std::error_code ec = windows::UTF8ToUTF16(E, EnvString)) {
SetLastError(ec.value());
diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc
index d962daf79348..8b525f1bd4ac 100644
--- a/llvm/lib/Support/Windows/Signals.inc
+++ b/llvm/lib/Support/Windows/Signals.inc
@@ -521,10 +521,13 @@ void sys::PrintStackTraceOnErrorSignal(StringRef Argv0,
extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord);
#endif
-void llvm::sys::PrintStackTrace(raw_ostream &OS) {
- STACKFRAME64 StackFrame = {};
- CONTEXT Context = {};
- ::RtlCaptureContext(&Context);
+static void LocalPrintStackTrace(raw_ostream &OS, PCONTEXT C) {
+ STACKFRAME64 StackFrame{};
+ CONTEXT Context{};
+ if (!C) {
+ ::RtlCaptureContext(&Context);
+ C = &Context;
+ }
#if defined(_M_X64)
StackFrame.AddrPC.Offset = Context.Rip;
StackFrame.AddrStack.Offset = Context.Rsp;
@@ -546,9 +549,12 @@ void llvm::sys::PrintStackTrace(raw_ostream &OS) {
StackFrame.AddrStack.Mode = AddrModeFlat;
StackFrame.AddrFrame.Mode = AddrModeFlat;
PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(),
- StackFrame, &Context);
+ StackFrame, C);
}
+void llvm::sys::PrintStackTrace(raw_ostream &OS) {
+ LocalPrintStackTrace(OS, nullptr);
+}
void llvm::sys::SetInterruptFunction(void (*IF)()) {
RegisterHandler();
@@ -560,7 +566,11 @@ void llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
// Unimplemented.
}
-void llvm::sys::SetPipeSignalFunction(void (*Handler)()) {
+void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
+ // Unimplemented.
+}
+
+void llvm::sys::DefaultOneShotPipeSignalHandler() {
// Unimplemented.
}
@@ -788,6 +798,10 @@ WriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) {
return std::error_code();
}
+void sys::CleanupOnSignal(uintptr_t Context) {
+ LLVMUnhandledExceptionFilter((LPEXCEPTION_POINTERS)Context);
+}
+
static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
Cleanup();
@@ -806,42 +820,9 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
<< "\n";
}
- // Initialize the STACKFRAME structure.
- STACKFRAME64 StackFrame = {};
-
-#if defined(_M_X64)
- StackFrame.AddrPC.Offset = ep->ContextRecord->Rip;
- StackFrame.AddrPC.Mode = AddrModeFlat;
- StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp;
- StackFrame.AddrStack.Mode = AddrModeFlat;
- StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp;
- StackFrame.AddrFrame.Mode = AddrModeFlat;
-#elif defined(_M_IX86)
- StackFrame.AddrPC.Offset = ep->ContextRecord->Eip;
- StackFrame.AddrPC.Mode = AddrModeFlat;
- StackFrame.AddrStack.Offset = ep->ContextRecord->Esp;
- StackFrame.AddrStack.Mode = AddrModeFlat;
- StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp;
- StackFrame.AddrFrame.Mode = AddrModeFlat;
-#elif defined(_M_ARM64) || defined(_M_ARM)
- StackFrame.AddrPC.Offset = ep->ContextRecord->Pc;
- StackFrame.AddrPC.Mode = AddrModeFlat;
- StackFrame.AddrStack.Offset = ep->ContextRecord->Sp;
- StackFrame.AddrStack.Mode = AddrModeFlat;
-#if defined(_M_ARM64)
- StackFrame.AddrFrame.Offset = ep->ContextRecord->Fp;
-#else
- StackFrame.AddrFrame.Offset = ep->ContextRecord->R11;
-#endif
- StackFrame.AddrFrame.Mode = AddrModeFlat;
-#endif
-
- HANDLE hProcess = GetCurrentProcess();
- HANDLE hThread = GetCurrentThread();
- PrintStackTraceForThread(llvm::errs(), hProcess, hThread, StackFrame,
- ep->ContextRecord);
+ LocalPrintStackTrace(llvm::errs(), ep ? ep->ContextRecord : nullptr);
- _exit(ep->ExceptionRecord->ExceptionCode);
+ return EXCEPTION_EXECUTE_HANDLER;
}
static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
diff --git a/llvm/lib/Support/Windows/Threading.inc b/llvm/lib/Support/Windows/Threading.inc
index 96649472cc90..9456efa686ff 100644
--- a/llvm/lib/Support/Windows/Threading.inc
+++ b/llvm/lib/Support/Windows/Threading.inc
@@ -21,36 +21,36 @@
#undef MemoryFence
#endif
-namespace {
- struct ThreadInfo {
- void(*func)(void*);
- void *param;
- };
+static unsigned __stdcall threadFuncSync(void *Arg) {
+ SyncThreadInfo *TI = static_cast<SyncThreadInfo *>(Arg);
+ TI->UserFn(TI->UserData);
+ return 0;
}
-static unsigned __stdcall ThreadCallback(void *param) {
- struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
- info->func(info->param);
-
+static unsigned __stdcall threadFuncAsync(void *Arg) {
+ std::unique_ptr<AsyncThreadInfo> Info(static_cast<AsyncThreadInfo *>(Arg));
+ (*Info)();
return 0;
}
-void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData,
- unsigned RequestedStackSize) {
- struct ThreadInfo param = { Fn, UserData };
-
- HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
- RequestedStackSize, ThreadCallback,
- &param, 0, NULL);
-
- if (hThread) {
- // We actually don't care whether the wait succeeds or fails, in
- // the same way we don't care whether the pthread_join call succeeds
- // or fails. There's not much we could do if this were to fail. But
- // on success, this call will wait until the thread finishes executing
- // before returning.
- (void)::WaitForSingleObject(hThread, INFINITE);
- ::CloseHandle(hThread);
+static void
+llvm_execute_on_thread_impl(unsigned (__stdcall *ThreadFunc)(void *), void *Arg,
+ llvm::Optional<unsigned> StackSizeInBytes,
+ JoiningPolicy JP) {
+ HANDLE hThread = (HANDLE)::_beginthreadex(
+ NULL, StackSizeInBytes.getValueOr(0), ThreadFunc, Arg, 0, NULL);
+
+ if (!hThread) {
+ ReportLastErrorFatal("_beginthreadex failed");
+ }
+
+ if (JP == JoiningPolicy::Join) {
+ if (::WaitForSingleObject(hThread, INFINITE) == WAIT_FAILED) {
+ ReportLastErrorFatal("WaitForSingleObject failed");
+ }
+ }
+ if (::CloseHandle(hThread) == FALSE) {
+ ReportLastErrorFatal("CloseHandle failed");
}
}
diff --git a/llvm/lib/Support/Windows/WindowsSupport.h b/llvm/lib/Support/Windows/WindowsSupport.h
index 2e2e97430b76..bb7e79b86018 100644
--- a/llvm/lib/Support/Windows/WindowsSupport.h
+++ b/llvm/lib/Support/Windows/WindowsSupport.h
@@ -41,6 +41,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/VersionTuple.h"
#include <cassert>
#include <string>
@@ -66,6 +67,13 @@ llvm::VersionTuple GetWindowsOSVersion();
bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix);
+// Include GetLastError() in a fatal error message.
+LLVM_ATTRIBUTE_NORETURN inline void ReportLastErrorFatal(const char *Msg) {
+ std::string ErrMsg;
+ MakeErrMsg(&ErrMsg, Msg);
+ llvm::report_fatal_error(ErrMsg);
+}
+
template <typename HandleTraits>
class ScopedHandle {
typedef typename HandleTraits::handle_type handle_type;
diff --git a/llvm/lib/Support/YAMLParser.cpp b/llvm/lib/Support/YAMLParser.cpp
index 9b2fe9c4418a..d17e7b227f4a 100644
--- a/llvm/lib/Support/YAMLParser.cpp
+++ b/llvm/lib/Support/YAMLParser.cpp
@@ -178,10 +178,10 @@ namespace {
/// others) before the SimpleKey's Tok.
struct SimpleKey {
TokenQueueT::iterator Tok;
- unsigned Column;
- unsigned Line;
- unsigned FlowLevel;
- bool IsRequired;
+ unsigned Column = 0;
+ unsigned Line = 0;
+ unsigned FlowLevel = 0;
+ bool IsRequired = false;
bool operator ==(const SimpleKey &Other) {
return Tok == Other.Tok;
@@ -789,6 +789,7 @@ Token &Scanner::peekNext() {
if (TokenQueue.empty() || NeedMore) {
if (!fetchMoreTokens()) {
TokenQueue.clear();
+ SimpleKeys.clear();
TokenQueue.push_back(Token());
return TokenQueue.front();
}
@@ -932,12 +933,16 @@ void Scanner::scan_ns_uri_char() {
}
bool Scanner::consume(uint32_t Expected) {
- if (Expected >= 0x80)
- report_fatal_error("Not dealing with this yet");
+ if (Expected >= 0x80) {
+ setError("Cannot consume non-ascii characters");
+ return false;
+ }
if (Current == End)
return false;
- if (uint8_t(*Current) >= 0x80)
- report_fatal_error("Not dealing with this yet");
+ if (uint8_t(*Current) >= 0x80) {
+ setError("Cannot consume non-ascii characters");
+ return false;
+ }
if (uint8_t(*Current) == Expected) {
++Current;
++Column;
@@ -1227,7 +1232,10 @@ bool Scanner::scanValue() {
if (i == SK.Tok)
break;
}
- assert(i != e && "SimpleKey not in token queue!");
+ if (i == e) {
+ Failed = true;
+ return false;
+ }
i = TokenQueue.insert(i, T);
// We may also need to add a Block-Mapping-Start token.
@@ -1772,10 +1780,11 @@ Stream::~Stream() = default;
bool Stream::failed() { return scanner->failed(); }
void Stream::printError(Node *N, const Twine &Msg) {
- scanner->printError( N->getSourceRange().Start
+ SMRange Range = N ? N->getSourceRange() : SMRange();
+ scanner->printError( Range.Start
, SourceMgr::DK_Error
, Msg
- , N->getSourceRange());
+ , Range);
}
document_iterator Stream::begin() {
@@ -1934,15 +1943,18 @@ StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue
UnquotedValue = UnquotedValue.substr(1);
break;
default:
- if (UnquotedValue.size() == 1)
- // TODO: Report error.
- break;
+ if (UnquotedValue.size() == 1) {
+ Token T;
+ T.Range = StringRef(UnquotedValue.begin(), 1);
+ setError("Unrecognized escape code", T);
+ return "";
+ }
UnquotedValue = UnquotedValue.substr(1);
switch (UnquotedValue[0]) {
default: {
Token T;
T.Range = StringRef(UnquotedValue.begin(), 1);
- setError("Unrecognized escape code!", T);
+ setError("Unrecognized escape code", T);
return "";
}
case '\r':
@@ -2078,7 +2090,14 @@ Node *KeyValueNode::getKey() {
Node *KeyValueNode::getValue() {
if (Value)
return Value;
- getKey()->skip();
+
+ if (Node* Key = getKey())
+ Key->skip();
+ else {
+ setError("Null key in Key Value.", peekNext());
+ return Value = new (getAllocator()) NullNode(Doc);
+ }
+
if (failed())
return Value = new (getAllocator()) NullNode(Doc);
@@ -2269,8 +2288,8 @@ Document::Document(Stream &S) : stream(S), Root(nullptr) {
bool Document::skip() {
if (stream.scanner->failed())
return false;
- if (!Root)
- getRoot();
+ if (!Root && !getRoot())
+ return false;
Root->skip();
Token &T = peekNext();
if (T.Kind == Token::TK_StreamEnd)
@@ -2394,6 +2413,15 @@ parse_property:
// TODO: Properly handle tags. "[!!str ]" should resolve to !!str "", not
// !!null null.
return new (NodeAllocator) NullNode(stream.CurrentDoc);
+ case Token::TK_FlowMappingEnd:
+ case Token::TK_FlowSequenceEnd:
+ case Token::TK_FlowEntry: {
+ if (Root && (isa<MappingNode>(Root) || isa<SequenceNode>(Root)))
+ return new (NodeAllocator) NullNode(stream.CurrentDoc);
+
+ setError("Unexpected token", T);
+ return nullptr;
+ }
case Token::TK_Error:
return nullptr;
}
diff --git a/llvm/lib/Support/YAMLTraits.cpp b/llvm/lib/Support/YAMLTraits.cpp
index eba22fd14725..5f0cedc71829 100644
--- a/llvm/lib/Support/YAMLTraits.cpp
+++ b/llvm/lib/Support/YAMLTraits.cpp
@@ -87,7 +87,6 @@ bool Input::setCurrentDocument() {
if (DocIterator != Strm->end()) {
Node *N = DocIterator->getRoot();
if (!N) {
- assert(Strm->failed() && "Root is NULL iff parsing failed");
EC = make_error_code(errc::invalid_argument);
return false;
}
@@ -394,7 +393,7 @@ std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) {
auto mapHNode = std::make_unique<MapHNode>(N);
for (KeyValueNode &KVN : *Map) {
Node *KeyNode = KVN.getKey();
- ScalarNode *Key = dyn_cast<ScalarNode>(KeyNode);
+ ScalarNode *Key = dyn_cast_or_null<ScalarNode>(KeyNode);
Node *Value = KVN.getValue();
if (!Key || !Value) {
if (!Key)
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index b9989371f5ea..4bb315f824af 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -82,7 +82,7 @@ raw_ostream::~raw_ostream() {
assert(OutBufCur == OutBufStart &&
"raw_ostream destructor called with non-empty buffer!");
- if (BufferMode == InternalBuffer)
+ if (BufferMode == BufferKind::InternalBuffer)
delete [] OutBufStart;
}
@@ -102,14 +102,14 @@ void raw_ostream::SetBuffered() {
void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,
BufferKind Mode) {
- assert(((Mode == Unbuffered && !BufferStart && Size == 0) ||
- (Mode != Unbuffered && BufferStart && Size != 0)) &&
+ assert(((Mode == BufferKind::Unbuffered && !BufferStart && Size == 0) ||
+ (Mode != BufferKind::Unbuffered && BufferStart && Size != 0)) &&
"stream must be unbuffered or have at least one byte");
// Make sure the current buffer is free of content (we can't flush here; the
// child buffer management logic will be in write_impl).
assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!");
- if (BufferMode == InternalBuffer)
+ if (BufferMode == BufferKind::InternalBuffer)
delete [] OutBufStart;
OutBufStart = BufferStart;
OutBufEnd = OutBufStart+Size;
@@ -223,7 +223,7 @@ raw_ostream &raw_ostream::write(unsigned char C) {
// Group exceptional cases into a single branch.
if (LLVM_UNLIKELY(OutBufCur >= OutBufEnd)) {
if (LLVM_UNLIKELY(!OutBufStart)) {
- if (BufferMode == Unbuffered) {
+ if (BufferMode == BufferKind::Unbuffered) {
write_impl(reinterpret_cast<char*>(&C), 1);
return *this;
}
@@ -243,7 +243,7 @@ raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) {
// Group exceptional cases into a single branch.
if (LLVM_UNLIKELY(size_t(OutBufEnd - OutBufCur) < Size)) {
if (LLVM_UNLIKELY(!OutBufStart)) {
- if (BufferMode == Unbuffered) {
+ if (BufferMode == BufferKind::Unbuffered) {
write_impl(Ptr, Size);
return *this;
}