aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Support
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support')
-rw-r--r--contrib/llvm-project/llvm/lib/Support/AArch64TargetParser.cpp48
-rw-r--r--contrib/llvm-project/llvm/lib/Support/ABIBreak.cpp24
-rw-r--r--contrib/llvm-project/llvm/lib/Support/AMDGPUMetadata.cpp1
-rw-r--r--contrib/llvm-project/llvm/lib/Support/APFloat.cpp184
-rw-r--r--contrib/llvm-project/llvm/lib/Support/APInt.cpp131
-rw-r--r--contrib/llvm-project/llvm/lib/Support/ARMAttributeParser.cpp18
-rw-r--r--contrib/llvm-project/llvm/lib/Support/ARMTargetParser.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Support/BinaryStreamReader.cpp8
-rw-r--r--contrib/llvm-project/llvm/lib/Support/CRC.cpp123
-rw-r--r--contrib/llvm-project/llvm/lib/Support/CachePruning.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Support/CommandLine.cpp211
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Compression.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp118
-rw-r--r--contrib/llvm-project/llvm/lib/Support/DataExtractor.cpp160
-rw-r--r--contrib/llvm-project/llvm/lib/Support/DebugCounter.cpp1
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Error.cpp22
-rw-r--r--contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp3
-rw-r--r--contrib/llvm-project/llvm/lib/Support/FileCheck.cpp562
-rw-r--r--contrib/llvm-project/llvm/lib/Support/FileCheckImpl.h613
-rw-r--r--contrib/llvm-project/llvm/lib/Support/FileCollector.cpp268
-rw-r--r--contrib/llvm-project/llvm/lib/Support/FileOutputBuffer.cpp11
-rw-r--r--contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp66
-rw-r--r--contrib/llvm-project/llvm/lib/Support/GlobPattern.cpp23
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Host.cpp97
-rw-r--r--contrib/llvm-project/llvm/lib/Support/InitLLVM.cpp6
-rw-r--r--contrib/llvm-project/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp39
-rw-r--r--contrib/llvm-project/llvm/lib/Support/JSON.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Support/JamCRC.cpp96
-rw-r--r--contrib/llvm-project/llvm/lib/Support/KnownBits.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Support/LockFileManager.cpp6
-rw-r--r--contrib/llvm-project/llvm/lib/Support/ManagedStatic.cpp13
-rw-r--r--contrib/llvm-project/llvm/lib/Support/MemoryBuffer.cpp31
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Mutex.cpp123
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Options.cpp32
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Parallel.cpp113
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Path.cpp47
-rw-r--r--contrib/llvm-project/llvm/lib/Support/PrettyStackTrace.cpp64
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Process.cpp10
-rw-r--r--contrib/llvm-project/llvm/lib/Support/RWMutex.cpp58
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Regex.cpp39
-rw-r--r--contrib/llvm-project/llvm/lib/Support/SHA1.cpp54
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Signals.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Signposts.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Support/SpecialCaseList.cpp18
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Statistic.cpp41
-rw-r--r--contrib/llvm-project/llvm/lib/Support/StringExtras.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Support/StringRef.cpp19
-rw-r--r--contrib/llvm-project/llvm/lib/Support/TargetParser.cpp8
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Threading.cpp51
-rw-r--r--contrib/llvm-project/llvm/lib/Support/TimeProfiler.cpp89
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Timer.cpp21
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Triple.cpp269
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Unix/Memory.inc12
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Unix/Mutex.inc42
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Unix/Path.inc79
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Unix/Process.inc7
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Unix/Program.inc4
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Unix/RWMutex.inc50
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Unix/Signals.inc45
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Unix/Threading.inc63
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Unix/Unix.h9
-rw-r--r--contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp154
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Windows/Memory.inc8
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Windows/Mutex.inc56
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Windows/Path.inc93
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Windows/Process.inc7
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Windows/Program.inc4
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Windows/RWMutex.inc128
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Windows/Signals.inc68
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Windows/Threading.inc50
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Windows/WindowsSupport.h9
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Windows/explicit_symbols.inc6
-rw-r--r--contrib/llvm-project/llvm/lib/Support/YAMLParser.cpp64
-rw-r--r--contrib/llvm-project/llvm/lib/Support/YAMLTraits.cpp19
-rw-r--r--contrib/llvm-project/llvm/lib/Support/Z3Solver.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Support/raw_ostream.cpp47
-rw-r--r--contrib/llvm-project/llvm/lib/Support/regcomp.c7
78 files changed, 3173 insertions, 1829 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/AArch64TargetParser.cpp b/contrib/llvm-project/llvm/lib/Support/AArch64TargetParser.cpp
index 6f1d6d50eee2..b5cd4af0eb3d 100644
--- a/contrib/llvm-project/llvm/lib/Support/AArch64TargetParser.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/ABIBreak.cpp b/contrib/llvm-project/llvm/lib/Support/ABIBreak.cpp
new file mode 100644
index 000000000000..247b635e02b8
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/Support/ABIBreak.cpp
@@ -0,0 +1,24 @@
+//===----- lib/Support/ABIBreak.cpp - EnableABIBreakingChecks -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/abi-breaking.h"
+
+#ifndef _MSC_VER
+namespace llvm {
+
+// One of these two variables will be referenced by a symbol defined in
+// llvm-config.h. We provide a link-time (or load time for DSO) failure when
+// there is a mismatch in the build configuration of the API client and LLVM.
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+int EnableABIBreakingChecks;
+#else
+int DisableABIBreakingChecks;
+#endif
+
+} // end namespace llvm
+#endif
diff --git a/contrib/llvm-project/llvm/lib/Support/AMDGPUMetadata.cpp b/contrib/llvm-project/llvm/lib/Support/AMDGPUMetadata.cpp
index 5f8102299f47..4ea197a97389 100644
--- a/contrib/llvm-project/llvm/lib/Support/AMDGPUMetadata.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/APFloat.cpp b/contrib/llvm-project/llvm/lib/Support/APFloat.cpp
index b79baf1834a7..050c37baefb8 100644
--- a/contrib/llvm-project/llvm/lib/Support/APFloat.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/APInt.cpp b/contrib/llvm-project/llvm/lib/Support/APInt.cpp
index 43173311cd80..9b9cd70078b3 100644
--- a/contrib/llvm-project/llvm/lib/Support/APInt.cpp
+++ b/contrib/llvm-project/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) {
@@ -401,6 +401,33 @@ void APInt::insertBits(const APInt &subBits, unsigned bitPosition) {
}
}
+void APInt::insertBits(uint64_t subBits, unsigned bitPosition, unsigned numBits) {
+ uint64_t maskBits = maskTrailingOnes<uint64_t>(numBits);
+ subBits &= maskBits;
+ if (isSingleWord()) {
+ U.VAL &= ~(maskBits << bitPosition);
+ U.VAL |= subBits << bitPosition;
+ return;
+ }
+
+ unsigned loBit = whichBit(bitPosition);
+ unsigned loWord = whichWord(bitPosition);
+ unsigned hiWord = whichWord(bitPosition + numBits - 1);
+ if (loWord == hiWord) {
+ U.pVal[loWord] &= ~(maskBits << loBit);
+ U.pVal[loWord] |= subBits << loBit;
+ return;
+ }
+
+ static_assert(8 * sizeof(WordType) <= 64, "This code assumes only two words affected");
+ unsigned wordBits = 8 * sizeof(WordType);
+ U.pVal[loWord] &= ~(maskBits << loBit);
+ U.pVal[loWord] |= subBits << loBit;
+
+ U.pVal[hiWord] &= ~(maskBits >> (wordBits - loBit));
+ U.pVal[hiWord] |= subBits >> (wordBits - loBit);
+}
+
APInt APInt::extractBits(unsigned numBits, unsigned bitPosition) const {
assert(numBits > 0 && "Can't extract zero bits");
assert(bitPosition < BitWidth && (numBits + bitPosition) <= BitWidth &&
@@ -438,6 +465,31 @@ APInt APInt::extractBits(unsigned numBits, unsigned bitPosition) const {
return Result.clearUnusedBits();
}
+uint64_t APInt::extractBitsAsZExtValue(unsigned numBits,
+ unsigned bitPosition) const {
+ assert(numBits > 0 && "Can't extract zero bits");
+ assert(bitPosition < BitWidth && (numBits + bitPosition) <= BitWidth &&
+ "Illegal bit extraction");
+ assert(numBits <= 64 && "Illegal bit extraction");
+
+ uint64_t maskBits = maskTrailingOnes<uint64_t>(numBits);
+ if (isSingleWord())
+ return (U.VAL >> bitPosition) & maskBits;
+
+ unsigned loBit = whichBit(bitPosition);
+ unsigned loWord = whichWord(bitPosition);
+ unsigned hiWord = whichWord(bitPosition + numBits - 1);
+ if (loWord == hiWord)
+ return (U.pVal[loWord] >> loBit) & maskBits;
+
+ static_assert(8 * sizeof(WordType) <= 64, "This code assumes only two words affected");
+ unsigned wordBits = 8 * sizeof(WordType);
+ uint64_t retBits = U.pVal[loWord] >> loBit;
+ retBits |= U.pVal[hiWord] << (wordBits - loBit);
+ retBits &= maskBits;
+ return retBits;
+}
+
unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) {
assert(!str.empty() && "Invalid string length");
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 ||
@@ -832,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");
@@ -1996,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
@@ -2738,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);
}
@@ -2881,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;
@@ -2935,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/contrib/llvm-project/llvm/lib/Support/ARMAttributeParser.cpp b/contrib/llvm-project/llvm/lib/Support/ARMAttributeParser.cpp
index df50fff720cd..8a89f4c45fb9 100644
--- a/contrib/llvm-project/llvm/lib/Support/ARMAttributeParser.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/ARMTargetParser.cpp b/contrib/llvm-project/llvm/lib/Support/ARMTargetParser.cpp
index a893991ebe70..f2c22fd93c8b 100644
--- a/contrib/llvm-project/llvm/lib/Support/ARMTargetParser.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/ARMTargetParser.cpp
@@ -174,11 +174,7 @@ 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},
- {"+vfp2d16", "-vfp2d16", FPUVersion::VFPV2, FPURestriction::D16},
- {"+vfp2d16sp", "-vfp2d16sp", FPUVersion::VFPV2, FPURestriction::SP_D16},
{"+vfp2sp", "-vfp2sp", FPUVersion::VFPV2, FPURestriction::SP_D16},
{"+vfp3", "-vfp3", FPUVersion::VFPV3, FPURestriction::None},
{"+vfp3d16", "-vfp3d16", FPUVersion::VFPV3, FPURestriction::D16},
diff --git a/contrib/llvm-project/llvm/lib/Support/BinaryStreamReader.cpp b/contrib/llvm-project/llvm/lib/Support/BinaryStreamReader.cpp
index b17786593bde..a0434bdc6115 100644
--- a/contrib/llvm-project/llvm/lib/Support/BinaryStreamReader.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/CRC.cpp b/contrib/llvm-project/llvm/lib/Support/CRC.cpp
index fd98f3a24003..2bc668beed32 100644
--- a/contrib/llvm-project/llvm/lib/Support/CRC.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/CRC.cpp
@@ -6,63 +6,102 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements llvm::crc32 function.
+// This file contains implementations of CRC functions.
+//
+// The implementation technique is the one mentioned in:
+// D. V. Sarwate. 1988. Computation of cyclic redundancy checks via table
+// look-up. Commun. ACM 31, 8 (August 1988)
+//
+// See also Ross N. Williams "A Painless Guide to CRC Error Detection
+// Algorithms" (https://zlib.net/crc_v3.txt) or Hacker's Delight (2nd ed.)
+// Chapter 14 (Figure 14-7 in particular) for how the algorithm works.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/CRC.h"
+
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Config/config.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Threading.h"
-#include <array>
using namespace llvm;
-#if LLVM_ENABLE_ZLIB == 0 || !HAVE_ZLIB_H
-using CRC32Table = std::array<uint32_t, 256>;
-
-static void initCRC32Table(CRC32Table *Tbl) {
- auto Shuffle = [](uint32_t V) {
- return (V & 1) ? (V >> 1) ^ 0xEDB88320U : V >> 1;
- };
-
- for (size_t I = 0; I < Tbl->size(); ++I) {
- uint32_t V = Shuffle(I);
- V = Shuffle(V);
- V = Shuffle(V);
- V = Shuffle(V);
- V = Shuffle(V);
- V = Shuffle(V);
- V = Shuffle(V);
- (*Tbl)[I] = Shuffle(V);
- }
-}
+#if !LLVM_ENABLE_ZLIB
-uint32_t llvm::crc32(uint32_t CRC, StringRef S) {
- static llvm::once_flag InitFlag;
- static CRC32Table Tbl;
- llvm::call_once(InitFlag, initCRC32Table, &Tbl);
+static const uint32_t CRCTable[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
- const uint8_t *P = reinterpret_cast<const uint8_t *>(S.data());
- size_t Len = S.size();
+uint32_t llvm::crc32(uint32_t CRC, ArrayRef<uint8_t> Data) {
CRC ^= 0xFFFFFFFFU;
- for (; Len >= 8; Len -= 8) {
- CRC = Tbl[(CRC ^ *P++) & 0xFF] ^ (CRC >> 8);
- CRC = Tbl[(CRC ^ *P++) & 0xFF] ^ (CRC >> 8);
- CRC = Tbl[(CRC ^ *P++) & 0xFF] ^ (CRC >> 8);
- CRC = Tbl[(CRC ^ *P++) & 0xFF] ^ (CRC >> 8);
- CRC = Tbl[(CRC ^ *P++) & 0xFF] ^ (CRC >> 8);
- CRC = Tbl[(CRC ^ *P++) & 0xFF] ^ (CRC >> 8);
- CRC = Tbl[(CRC ^ *P++) & 0xFF] ^ (CRC >> 8);
- CRC = Tbl[(CRC ^ *P++) & 0xFF] ^ (CRC >> 8);
+ for (uint8_t Byte : Data) {
+ int TableIdx = (CRC ^ Byte) & 0xff;
+ CRC = CRCTable[TableIdx] ^ (CRC >> 8);
}
- while (Len--)
- CRC = Tbl[(CRC ^ *P++) & 0xFF] ^ (CRC >> 8);
return CRC ^ 0xFFFFFFFFU;
}
+
#else
+
#include <zlib.h>
-uint32_t llvm::crc32(uint32_t CRC, StringRef S) {
- return ::crc32(CRC, (const Bytef *)S.data(), S.size());
+uint32_t llvm::crc32(uint32_t CRC, ArrayRef<uint8_t> Data) {
+ // Zlib's crc32() only takes a 32-bit length, so we have to iterate for larger
+ // sizes. One could use crc32_z() instead, but that's a recent (2017) addition
+ // and may not be available on all systems.
+ do {
+ ArrayRef<uint8_t> Slice = Data.take_front(UINT32_MAX);
+ CRC = ::crc32(CRC, (const Bytef *)Slice.data(), (uInt)Slice.size());
+ Data = Data.drop_front(Slice.size());
+ } while (Data.size() > 0);
+ return CRC;
}
+
#endif
+
+uint32_t llvm::crc32(ArrayRef<uint8_t> Data) { return crc32(0, Data); }
+
+void JamCRC::update(ArrayRef<uint8_t> Data) {
+ CRC ^= 0xFFFFFFFFU; // Undo CRC-32 Init.
+ CRC = crc32(CRC, Data);
+ CRC ^= 0xFFFFFFFFU; // Undo CRC-32 XorOut.
+}
diff --git a/contrib/llvm-project/llvm/lib/Support/CachePruning.cpp b/contrib/llvm-project/llvm/lib/Support/CachePruning.cpp
index 9813eec0e433..7a2f6c53435a 100644
--- a/contrib/llvm-project/llvm/lib/Support/CachePruning.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/CachePruning.cpp
@@ -45,7 +45,7 @@ struct FileInfo {
/// interval option.
static void writeTimestampFile(StringRef TimestampFile) {
std::error_code EC;
- raw_fd_ostream Out(TimestampFile.str(), EC, sys::fs::F_None);
+ raw_fd_ostream Out(TimestampFile.str(), EC, sys::fs::OF_None);
}
static Expected<std::chrono::seconds> parseDuration(StringRef Duration) {
diff --git a/contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp b/contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp
index f39eb7533b43..2db4193ce382 100644
--- a/contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp
@@ -101,9 +101,9 @@ bool CodeGenCoverage::emit(StringRef CoveragePrefix,
std::string CoverageFilename = (CoveragePrefix + Pid).str();
std::error_code EC;
- sys::fs::OpenFlags OpenFlags = sys::fs::F_Append;
+ sys::fs::OpenFlags OpenFlags = sys::fs::OF_Append;
std::unique_ptr<ToolOutputFile> CoverageFile =
- llvm::make_unique<ToolOutputFile>(CoverageFilename, EC, OpenFlags);
+ std::make_unique<ToolOutputFile>(CoverageFilename, EC, OpenFlags);
if (EC)
return false;
diff --git a/contrib/llvm-project/llvm/lib/Support/CommandLine.cpp b/contrib/llvm-project/llvm/lib/Support/CommandLine.cpp
index 25510fa58ff5..cb73380ba383 100644
--- a/contrib/llvm-project/llvm/lib/Support/CommandLine.cpp
+++ b/contrib/llvm-project/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;
}
@@ -692,7 +706,7 @@ static inline bool ProvideOption(Option *Handler, StringRef ArgName,
return false;
}
-static bool ProvidePositionalOption(Option *Handler, StringRef Arg, int i) {
+bool llvm::cl::ProvidePositionalOption(Option *Handler, StringRef Arg, int i) {
int Dummy = i;
return ProvideOption(Handler, Handler->ArgStr, Arg, 0, nullptr, Dummy);
}
@@ -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/contrib/llvm-project/llvm/lib/Support/Compression.cpp b/contrib/llvm-project/llvm/lib/Support/Compression.cpp
index 97d5ffaadf82..4165a2740cd0 100644
--- a/contrib/llvm-project/llvm/lib/Support/Compression.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp b/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp
index c2459256f8fe..356835609830 100644
--- a/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -10,9 +10,14 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Mutex.h"
+#include "llvm/Support/Signals.h"
#include "llvm/Support/ThreadLocal.h"
+#include <mutex>
#include <setjmp.h>
+#if LLVM_ON_UNIX
+#include <sysexits.h> // EX_IOERR
+#endif
+
using namespace llvm;
namespace {
@@ -33,11 +38,11 @@ struct CrashRecoveryContextImpl {
::jmp_buf JumpBuffer;
volatile unsigned Failed : 1;
unsigned SwitchedThread : 1;
+ unsigned ValidJumpBuffer : 1;
public:
- CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC),
- Failed(false),
- SwitchedThread(false) {
+ CrashRecoveryContextImpl(CrashRecoveryContext *CRC) noexcept
+ : CRC(CRC), Failed(false), SwitchedThread(false), ValidJumpBuffer(false) {
Next = CurrentContext->get();
CurrentContext->set(this);
}
@@ -54,7 +59,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,16 +71,22 @@ 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);
+ if (ValidJumpBuffer)
+ longjmp(JumpBuffer, 1);
+
+ // Otherwise let the caller decide of the outcome of the crash. Currently
+ // this occurs when using SEH on Windows with MSVC or clang-cl.
}
};
-
}
-static ManagedStatic<sys::Mutex> gCrashRecoveryContextMutex;
+static ManagedStatic<std::mutex> gCrashRecoveryContextMutex;
static bool gCrashRecoveryEnabled = false;
static ManagedStatic<sys::ThreadLocal<const CrashRecoveryContext>>
@@ -116,7 +131,7 @@ CrashRecoveryContext *CrashRecoveryContext::GetCurrent() {
}
void CrashRecoveryContext::Enable() {
- sys::ScopedLock L(*gCrashRecoveryContextMutex);
+ std::lock_guard<std::mutex> L(*gCrashRecoveryContextMutex);
// FIXME: Shouldn't this be a refcount or something?
if (gCrashRecoveryEnabled)
return;
@@ -125,7 +140,7 @@ void CrashRecoveryContext::Enable() {
}
void CrashRecoveryContext::Disable() {
- sys::ScopedLock L(*gCrashRecoveryContextMutex);
+ std::lock_guard<std::mutex> L(*gCrashRecoveryContextMutex);
if (!gCrashRecoveryEnabled)
return;
gCrashRecoveryEnabled = false;
@@ -160,6 +175,9 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
}
#if defined(_MSC_VER)
+
+#include <windows.h> // for GetExceptionInformation
+
// If _MSC_VER is defined, we must have SEH. Use it if it's available. It's way
// better than VEH. Vectored exception handling catches all exceptions happening
// on the thread with installed exception handlers, so it can interfere with
@@ -171,19 +189,47 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
static void installExceptionOrSignalHandlers() {}
static void uninstallExceptionOrSignalHandlers() {}
+// We need this function because the call to GetExceptionInformation() can only
+// occur inside the __except evaluation block
+static int ExceptionFilter(_EXCEPTION_POINTERS *Except) {
+ // Lookup the current thread local recovery object.
+ const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
+
+ if (!CRCI) {
+ // Something has gone horribly wrong, so let's just tell everyone
+ // to keep searching
+ CrashRecoveryContext::Disable();
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ int RetCode = (int)Except->ExceptionRecord->ExceptionCode;
+ if ((RetCode & 0xF0000000) == 0xE0000000)
+ RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit
+
+ // Handle the crash
+ const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(
+ RetCode, reinterpret_cast<uintptr_t>(Except));
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+#if defined(__clang__) && defined(_M_IX86)
+// Work around PR44697.
+__attribute__((optnone))
+#endif
bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
if (!gCrashRecoveryEnabled) {
Fn();
return true;
}
-
- bool Result = true;
+ assert(!Impl && "Crash recovery context already initialized!");
+ Impl = new CrashRecoveryContextImpl(this);
__try {
Fn();
- } __except (1) { // Catch any exception.
- Result = false;
+ } __except (ExceptionFilter(GetExceptionInformation())) {
+ return false;
}
- return Result;
+ return true;
}
#else // !_MSC_VER
@@ -236,8 +282,13 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
// TODO: We can capture the stack backtrace here and store it on the
// implementation if we so choose.
+ int RetCode = (int)ExceptionInfo->ExceptionRecord->ExceptionCode;
+ if ((RetCode & 0xF0000000) == 0xE0000000)
+ RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit
+
// Handle the crash
- const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash();
+ const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(
+ RetCode, 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 +331,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 +370,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() {
@@ -350,6 +409,7 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this);
Impl = CRCI;
+ CRCI->ValidJumpBuffer = true;
if (setjmp(CRCI->JumpBuffer) != 0) {
return false;
}
@@ -361,10 +421,19 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
#endif // !_MSC_VER
-void CrashRecoveryContext::HandleCrash() {
- CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
+LLVM_ATTRIBUTE_NORETURN
+void CrashRecoveryContext::HandleExit(int RetCode) {
+#if defined(_WIN32)
+ // SEH and VEH
+ ::RaiseException(0xE0000000 | RetCode, 0, 0, NULL);
+#else
+ // On Unix we don't need to raise an exception, we go directly to
+ // HandleCrash(), then longjmp will unwind the stack for us.
+ CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *)Impl;
assert(CRCI && "Crash recovery context never initialized!");
- CRCI->HandleCrash();
+ CRCI->HandleCrash(RetCode, 0 /*no sig num*/);
+#endif
+ llvm_unreachable("Most likely setjmp wasn't called!");
}
// FIXME: Portability.
@@ -404,7 +473,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/contrib/llvm-project/llvm/lib/Support/DataExtractor.cpp b/contrib/llvm-project/llvm/lib/Support/DataExtractor.cpp
index 673bbb4d06f4..a98297cdb35f 100644
--- a/contrib/llvm-project/llvm/lib/Support/DataExtractor.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/DataExtractor.cpp
@@ -7,111 +7,137 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/SwapByteOrder.h"
#include "llvm/Support/LEB128.h"
+#include "llvm/Support/SwapByteOrder.h"
+
using namespace llvm;
+static void unexpectedEndReached(Error *E) {
+ if (E)
+ *E = createStringError(errc::illegal_byte_sequence,
+ "unexpected end of data");
+}
+
+static bool isError(Error *E) { return E && *E; }
+
template <typename T>
-static T getU(uint32_t *offset_ptr, const DataExtractor *de,
- bool isLittleEndian, const char *Data) {
+static T getU(uint64_t *offset_ptr, const DataExtractor *de,
+ bool isLittleEndian, const char *Data, llvm::Error *Err) {
+ ErrorAsOutParameter ErrAsOut(Err);
T val = 0;
- uint32_t offset = *offset_ptr;
- if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) {
- std::memcpy(&val, &Data[offset], sizeof(val));
- if (sys::IsLittleEndianHost != isLittleEndian)
- sys::swapByteOrder(val);
-
- // Advance the offset
- *offset_ptr += sizeof(val);
+ if (isError(Err))
+ return val;
+
+ uint64_t offset = *offset_ptr;
+ if (!de->isValidOffsetForDataOfSize(offset, sizeof(T))) {
+ unexpectedEndReached(Err);
+ return val;
}
+ std::memcpy(&val, &Data[offset], sizeof(val));
+ if (sys::IsLittleEndianHost != isLittleEndian)
+ sys::swapByteOrder(val);
+
+ // Advance the offset
+ *offset_ptr += sizeof(val);
return val;
}
template <typename T>
-static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count,
- const DataExtractor *de, bool isLittleEndian, const char *Data){
- uint32_t offset = *offset_ptr;
-
- if (count > 0 && de->isValidOffsetForDataOfSize(offset, sizeof(*dst)*count)) {
- for (T *value_ptr = dst, *end = dst + count; value_ptr != end;
- ++value_ptr, offset += sizeof(*dst))
- *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data);
- // Advance the offset
- *offset_ptr = offset;
- // Return a non-NULL pointer to the converted data as an indicator of
- // success
- return dst;
+static T *getUs(uint64_t *offset_ptr, T *dst, uint32_t count,
+ const DataExtractor *de, bool isLittleEndian, const char *Data,
+ llvm::Error *Err) {
+ ErrorAsOutParameter ErrAsOut(Err);
+ if (isError(Err))
+ return nullptr;
+
+ uint64_t offset = *offset_ptr;
+
+ if (!de->isValidOffsetForDataOfSize(offset, sizeof(*dst) * count)) {
+ unexpectedEndReached(Err);
+ return nullptr;
}
- return nullptr;
+ for (T *value_ptr = dst, *end = dst + count; value_ptr != end;
+ ++value_ptr, offset += sizeof(*dst))
+ *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data, Err);
+ // Advance the offset
+ *offset_ptr = offset;
+ // Return a non-NULL pointer to the converted data as an indicator of
+ // success
+ return dst;
}
-uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const {
- return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data());
+uint8_t DataExtractor::getU8(uint64_t *offset_ptr, llvm::Error *Err) const {
+ return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);
}
uint8_t *
-DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const {
+DataExtractor::getU8(uint64_t *offset_ptr, uint8_t *dst, uint32_t count) const {
return getUs<uint8_t>(offset_ptr, dst, count, this, IsLittleEndian,
- Data.data());
+ Data.data(), nullptr);
}
+uint8_t *DataExtractor::getU8(Cursor &C, uint8_t *Dst, uint32_t Count) const {
+ return getUs<uint8_t>(&C.Offset, Dst, Count, this, IsLittleEndian,
+ Data.data(), &C.Err);
+}
-uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
- return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data());
+uint16_t DataExtractor::getU16(uint64_t *offset_ptr, llvm::Error *Err) const {
+ return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);
}
-uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst,
+uint16_t *DataExtractor::getU16(uint64_t *offset_ptr, uint16_t *dst,
uint32_t count) const {
return getUs<uint16_t>(offset_ptr, dst, count, this, IsLittleEndian,
- Data.data());
+ Data.data(), nullptr);
}
-uint32_t DataExtractor::getU24(uint32_t *offset_ptr) const {
+uint32_t DataExtractor::getU24(uint64_t *offset_ptr) const {
uint24_t ExtractedVal =
- getU<uint24_t>(offset_ptr, this, IsLittleEndian, Data.data());
+ getU<uint24_t>(offset_ptr, this, IsLittleEndian, Data.data(), nullptr);
// The 3 bytes are in the correct byte order for the host.
return ExtractedVal.getAsUint32(sys::IsLittleEndianHost);
}
-uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
- return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data());
+uint32_t DataExtractor::getU32(uint64_t *offset_ptr, llvm::Error *Err) const {
+ return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);
}
-uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst,
+uint32_t *DataExtractor::getU32(uint64_t *offset_ptr, uint32_t *dst,
uint32_t count) const {
return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
- Data.data());
+ Data.data(), nullptr);
}
-uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
- return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data());
+uint64_t DataExtractor::getU64(uint64_t *offset_ptr, llvm::Error *Err) const {
+ return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);
}
-uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
+uint64_t *DataExtractor::getU64(uint64_t *offset_ptr, uint64_t *dst,
uint32_t count) const {
return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian,
- Data.data());
+ Data.data(), nullptr);
}
-uint64_t
-DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
+uint64_t DataExtractor::getUnsigned(uint64_t *offset_ptr, uint32_t byte_size,
+ llvm::Error *Err) const {
switch (byte_size) {
case 1:
- return getU8(offset_ptr);
+ return getU8(offset_ptr, Err);
case 2:
- return getU16(offset_ptr);
+ return getU16(offset_ptr, Err);
case 4:
- return getU32(offset_ptr);
+ return getU32(offset_ptr, Err);
case 8:
- return getU64(offset_ptr);
+ return getU64(offset_ptr, Err);
}
llvm_unreachable("getUnsigned unhandled case!");
}
int64_t
-DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
+DataExtractor::getSigned(uint64_t *offset_ptr, uint32_t byte_size) const {
switch (byte_size) {
case 1:
return (int8_t)getU8(offset_ptr);
@@ -125,8 +151,8 @@ DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
llvm_unreachable("getSigned unhandled case!");
}
-const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
- uint32_t offset = *offset_ptr;
+const char *DataExtractor::getCStr(uint64_t *offset_ptr) const {
+ uint64_t offset = *offset_ptr;
StringRef::size_type pos = Data.find('\0', offset);
if (pos != StringRef::npos) {
*offset_ptr = pos + 1;
@@ -135,31 +161,38 @@ const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
return nullptr;
}
-StringRef DataExtractor::getCStrRef(uint32_t *OffsetPtr) const {
- uint32_t Start = *OffsetPtr;
+StringRef DataExtractor::getCStrRef(uint64_t *offset_ptr) const {
+ uint64_t Start = *offset_ptr;
StringRef::size_type Pos = Data.find('\0', Start);
if (Pos != StringRef::npos) {
- *OffsetPtr = Pos + 1;
+ *offset_ptr = Pos + 1;
return StringRef(Data.data() + Start, Pos - Start);
}
return StringRef();
}
-uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
+uint64_t DataExtractor::getULEB128(uint64_t *offset_ptr,
+ llvm::Error *Err) const {
assert(*offset_ptr <= Data.size());
+ ErrorAsOutParameter ErrAsOut(Err);
+ if (isError(Err))
+ return 0;
const char *error;
unsigned bytes_read;
uint64_t result = decodeULEB128(
reinterpret_cast<const uint8_t *>(Data.data() + *offset_ptr), &bytes_read,
reinterpret_cast<const uint8_t *>(Data.data() + Data.size()), &error);
- if (error)
+ if (error) {
+ if (Err)
+ *Err = createStringError(errc::illegal_byte_sequence, error);
return 0;
+ }
*offset_ptr += bytes_read;
return result;
}
-int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
+int64_t DataExtractor::getSLEB128(uint64_t *offset_ptr) const {
assert(*offset_ptr <= Data.size());
const char *error;
@@ -172,3 +205,14 @@ int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
*offset_ptr += bytes_read;
return result;
}
+
+void DataExtractor::skip(Cursor &C, uint64_t Length) const {
+ ErrorAsOutParameter ErrAsOut(&C.Err);
+ if (isError(&C.Err))
+ return;
+
+ if (isValidOffsetForDataOfSize(C.Offset, Length))
+ C.Offset += Length;
+ else
+ unexpectedEndReached(&C.Err);
+}
diff --git a/contrib/llvm-project/llvm/lib/Support/DebugCounter.cpp b/contrib/llvm-project/llvm/lib/Support/DebugCounter.cpp
index 6598103658da..1e3ec300964c 100644
--- a/contrib/llvm-project/llvm/lib/Support/DebugCounter.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/Error.cpp b/contrib/llvm-project/llvm/lib/Support/Error.cpp
index 72bc08af2ddb..315a11e967d1 100644
--- a/contrib/llvm-project/llvm/lib/Support/Error.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/Error.cpp
@@ -87,7 +87,7 @@ std::error_code FileError::convertToErrorCode() const {
Error errorCodeToError(std::error_code EC) {
if (!EC)
return Error::success();
- return Error(llvm::make_unique<ECError>(ECError(EC)));
+ return Error(std::make_unique<ECError>(ECError(EC)));
}
std::error_code errorToErrorCode(Error Err) {
@@ -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();
@@ -167,18 +168,3 @@ void LLVMDisposeErrorMessage(char *ErrMsg) { delete[] ErrMsg; }
LLVMErrorTypeId LLVMGetStringErrorTypeId() {
return reinterpret_cast<void *>(&StringError::ID);
}
-
-#ifndef _MSC_VER
-namespace llvm {
-
-// One of these two variables will be referenced by a symbol defined in
-// llvm-config.h. We provide a link-time (or load time for DSO) failure when
-// there is a mismatch in the build configuration of the API client and LLVM.
-#if LLVM_ENABLE_ABI_BREAKING_CHECKS
-int EnableABIBreakingChecks;
-#else
-int DisableABIBreakingChecks;
-#endif
-
-} // end namespace llvm
-#endif
diff --git a/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp b/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp
index 0f13f7a536f1..a9463024c420 100644
--- a/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp
@@ -19,6 +19,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/WindowsError.h"
@@ -122,7 +123,7 @@ void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
// files registered with RemoveFileOnSignal.
sys::RunInterruptHandlers();
- exit(1);
+ sys::Process::Exit(1);
}
void llvm::install_bad_alloc_error_handler(fatal_error_handler_t handler,
diff --git a/contrib/llvm-project/llvm/lib/Support/FileCheck.cpp b/contrib/llvm-project/llvm/lib/Support/FileCheck.cpp
index e0f17787bdf8..2261ecc236c2 100644
--- a/contrib/llvm-project/llvm/lib/Support/FileCheck.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/FileCheck.cpp
@@ -14,35 +14,26 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/FileCheck.h"
+#include "FileCheckImpl.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/FormatVariadic.h"
#include <cstdint>
#include <list>
-#include <map>
#include <tuple>
#include <utility>
using namespace llvm;
-void FileCheckNumericVariable::setValue(uint64_t NewValue) {
- assert(!Value && "Overwriting numeric variable's value is not allowed");
- Value = NewValue;
-}
-
-void FileCheckNumericVariable::clearValue() {
- if (!Value)
- return;
- Value = None;
-}
-
-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();
@@ -60,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)
@@ -75,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;
@@ -94,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,7 +98,7 @@ FileCheckPattern::parseVariable(StringRef &Str, const SourceMgr &SM) {
// StringRef holding all characters considered as horizontal whitespaces by
// FileCheck input canonicalization.
-StringRef SpaceChars = " \t";
+constexpr StringLiteral SpaceChars = " \t";
// Parsing helper function that strips the first character in S and returns it.
static char popFront(StringRef &S) {
@@ -118,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);
@@ -132,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;
@@ -157,11 +145,11 @@ FileCheckPattern::parseNumericVariableDefinition(
return DefinedNumericVariable;
}
-Expected<std::unique_ptr<FileCheckNumericVariableUse>>
-FileCheckPattern::parseNumericVariableUse(StringRef Name, bool IsPseudo,
- const SourceMgr &SM) const {
+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
@@ -173,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 {
@@ -183,23 +171,25 @@ 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 on the same line as used");
+ "numeric variable '" + Name +
+ "' defined earlier in the same CHECK directive");
- return llvm::make_unique<FileCheckNumericVariableUse>(Name, NumericVariable);
+ return std::make_unique<NumericVariableUse>(Name, NumericVariable);
}
-Expected<std::unique_ptr<FileCheckExpressionAST>>
-FileCheckPattern::parseNumericOperand(StringRef &Expr, AllowedOperand AO,
- const SourceMgr &SM) const {
+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,
- ParseVarResult->IsPseudo, SM);
+ ParseVarResult->IsPseudo, LineNumber,
+ Context, SM);
if (AO == AllowedOperand::LineVar)
return ParseVarResult.takeError();
// Ignore the error and retry parsing as a literal.
@@ -209,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 llvm::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) {
@@ -223,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, const SourceMgr &SM) const {
+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);
@@ -244,82 +234,82 @@ FileCheckPattern::parseBinop(StringRef &Expr,
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 =
- parseNumericOperand(Expr, AO, SM);
+ Expected<std::unique_ptr<ExpressionAST>> RightOpResult =
+ parseNumericOperand(Expr, AO, LineNumber, Context, SM);
if (!RightOpResult)
return RightOpResult;
Expr = Expr.ltrim(SpaceChars);
- return llvm::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,
- bool IsLegacyLineExpr, const SourceMgr &SM) const {
- // Parse the numeric variable definition.
+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<ExpressionAST> ExpressionASTPointer = nullptr;
+ StringRef DefExpr = StringRef();
DefinedNumericVariable = None;
+ // Save variable definition expression if any.
size_t DefEnd = Expr.find(':');
if (DefEnd != StringRef::npos) {
- StringRef DefExpr = Expr.substr(0, DefEnd);
- StringRef UseExpr = Expr.substr(DefEnd + 1);
+ DefExpr = Expr.substr(0, DefEnd);
+ Expr = Expr.substr(DefEnd + 1);
+ }
- UseExpr = UseExpr.ltrim(SpaceChars);
- if (!UseExpr.empty())
- return FileCheckErrorDiagnostic::get(
- SM, UseExpr,
- "unexpected string after variable definition: '" + UseExpr + "'");
+ // Parse the expression itself.
+ Expr = Expr.ltrim(SpaceChars);
+ if (!Expr.empty()) {
+ // The first operand in a legacy @LINE expression is always the @LINE
+ // pseudo variable.
+ AllowedOperand AO =
+ IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
+ 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 ErrorDiagnostic::get(
+ SM, Expr,
+ "unexpected characters at end of expression '" + Expr + "'");
+ }
+ if (!ParseResult)
+ return 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)
return ParseResult.takeError();
DefinedNumericVariable = *ParseResult;
-
- return nullptr;
}
- // Parse the expression itself.
- Expr = Expr.ltrim(SpaceChars);
- // The first operand in a legacy @LINE expression is always the @LINE pseudo
- // variable.
- AllowedOperand AO =
- IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
- Expected<std::unique_ptr<FileCheckExpressionAST>> ParseResult =
- parseNumericOperand(Expr, AO, SM);
- while (ParseResult && !Expr.empty()) {
- ParseResult =
- parseBinop(Expr, std::move(*ParseResult), IsLegacyLineExpr, SM);
- // Legacy @LINE expressions only allow 2 operands.
- if (ParseResult && IsLegacyLineExpr && !Expr.empty())
- return FileCheckErrorDiagnostic::get(
- SM, Expr,
- "unexpected characters at end of expression '" + Expr + "'");
- }
- if (!ParseResult)
- return ParseResult;
- return std::move(*ParseResult);
+ 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;
PatternLoc = SMLoc::getFromPointer(PatternStr.data());
@@ -396,14 +386,15 @@ bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
continue;
}
- // String and numeric substitution blocks. String substitution blocks come
+ // String and numeric substitution blocks. Pattern substitution blocks come
// in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some
// other regex) and assigns it to the string variable 'foo'. The latter
- // substitutes foo's value. Numeric substitution blocks work the same way
- // as string ones, but start with a '#' sign after the double brackets.
- // Both string and numeric variable names must satisfy the regular
- // expression "[a-zA-Z_][0-9a-zA-Z_]*" to be valid, as this helps catch
- // some common errors.
+ // substitutes foo's value. Numeric substitution blocks recognize the same
+ // form as string ones, but start with a '#' sign after the double
+ // brackets. They also accept a combined form which sets a numeric variable
+ // to the evaluation of an expression. Both string and numeric variable
+ // names must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" to be
+ // valid, as this helps catch some common errors.
if (PatternStr.startswith("[[")) {
StringRef UnparsedPatternStr = PatternStr.substr(2);
// Find the closing bracket pair ending the match. End is going to be an
@@ -424,6 +415,7 @@ bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
PatternStr = UnparsedPatternStr.substr(End + 2);
bool IsDefinition = false;
+ bool SubstNeeded = false;
// Whether the substitution block is a legacy use of @LINE with string
// substitution block syntax.
bool IsLegacyLineExpr = false;
@@ -444,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());
@@ -454,6 +446,7 @@ bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
bool IsPseudo = ParseVarResult->IsPseudo;
IsDefinition = (VarEndIdx != StringRef::npos);
+ SubstNeeded = !IsDefinition;
if (IsDefinition) {
if ((IsPseudo || !MatchStr.consume_front(":"))) {
SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
@@ -483,27 +476,66 @@ 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, SM);
+ IsLegacyLineExpr, LineNumber, Context,
+ SM);
if (!ParseResult) {
logAllUnhandledErrors(ParseResult.takeError(), errs());
return true;
}
- ExpressionAST = std::move(*ParseResult);
+ ExpressionASTPointer = std::move(*ParseResult);
+ SubstNeeded = ExpressionASTPointer != nullptr;
if (DefinedNumericVariable) {
IsDefinition = true;
DefName = (*DefinedNumericVariable)->getName();
- MatchRegexp = StringRef("[0-9]+");
- } else
+ }
+ if (SubstNeeded)
SubstStr = MatchStr;
+ else
+ MatchRegexp = "[0-9]+";
+ }
+
+ // Handle variable definition: [[<def>:(...)]] and [[#(...)<def>:(...)]].
+ if (IsDefinition) {
+ RegExStr += '(';
+ ++SubstInsertIdx;
+
+ if (IsNumBlock) {
+ NumericVariableMatch NumericVariableDefinition = {
+ *DefinedNumericVariable, CurParen};
+ NumericVariableDefs[DefName] = NumericVariableDefinition;
+ // This store is done here rather than in match() to allow
+ // parseNumericVariableUse() to get the pointer to the class instance
+ // of the right variable definition corresponding to a given numeric
+ // variable use.
+ Context->GlobalNumericVariableTable[DefName] =
+ *DefinedNumericVariable;
+ } else {
+ VariableDefs[DefName] = CurParen;
+ // Mark string variable as defined to detect collisions between
+ // string and numeric variables in parseNumericVariableUse() and
+ // defineCmdlineVariables() when the latter is created later than the
+ // former. We cannot reuse GlobalVariableTable for this by populating
+ // it with an empty string since we would then lose the ability to
+ // detect the use of an undefined variable in match().
+ Context->DefinedVariableTable[DefName] = true;
+ }
+
+ ++CurParen;
}
+ if (!MatchRegexp.empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
+ return true;
+
+ if (IsDefinition)
+ RegExStr += ')';
+
// Handle substitutions: [[foo]] and [[#<foo expr>]].
- if (!IsDefinition) {
+ if (SubstNeeded) {
// Handle substitution of string variables that were defined earlier on
// the same line by emitting a backreference. Expressions do not
// support substituting a numeric variable defined on the same line.
@@ -519,44 +551,15 @@ 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);
}
- continue;
}
-
- // Handle variable definitions: [[<def>:(...)]] and
- // [[#(...)<def>:(...)]].
- if (IsNumBlock) {
- FileCheckNumericVariableMatch NumericVariableDefinition = {
- *DefinedNumericVariable, CurParen};
- NumericVariableDefs[DefName] = NumericVariableDefinition;
- // This store is done here rather than in match() to allow
- // parseNumericVariableUse() to get the pointer to the class instance
- // of the right variable definition corresponding to a given numeric
- // variable use.
- Context->GlobalNumericVariableTable[DefName] = *DefinedNumericVariable;
- } else {
- VariableDefs[DefName] = CurParen;
- // Mark the string variable as defined to detect collisions between
- // string and numeric variables in parseNumericVariableUse() and
- // DefineCmdlineVariables() when the latter is created later than the
- // former. We cannot reuse GlobalVariableTable for this by populating
- // it with an empty string since we would then lose the ability to
- // detect the use of an undefined variable in match().
- Context->DefinedVariableTable[DefName] = true;
- }
- RegExStr += '(';
- ++CurParen;
-
- if (AddRegExToRegEx(MatchRegexp, CurParen, SM))
- return true;
-
- RegExStr += ')';
}
// Handle fixed string matches.
@@ -576,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)) {
@@ -590,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;
@@ -607,9 +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 = 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;
}
@@ -631,10 +635,8 @@ Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,
for (const auto &Substitution : Substitutions) {
// Substitute and check for failure (e.g. use of undefined variable).
Expected<std::string> Value = Substitution->getResult();
- if (!Value) {
- Context->LineVariable->clearValue();
+ if (!Value)
return Value.takeError();
- }
// Plop it into the regex at the adjusted offset.
TmpStr.insert(TmpStr.begin() + Substitution->getIndex() + InsertOffset,
@@ -644,12 +646,14 @@ Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,
// Match the newly constructed regex.
RegExToMatch = TmpStr;
- Context->LineVariable->clearValue();
}
SmallVector<StringRef, 4> MatchInfo;
- if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
- return make_error<FileCheckNotFoundError>();
+ unsigned int Flags = Regex::Newline;
+ if (IgnoreCase)
+ Flags |= Regex::IgnoreCase;
+ if (!Regex(RegExToMatch, Flags).match(Buffer, &MatchInfo))
+ return make_error<NotFoundError>();
// Successful regex match.
assert(!MatchInfo.empty() && "Didn't get any match");
@@ -664,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);
}
@@ -687,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.
//
@@ -704,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) {
@@ -717,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;
@@ -764,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
@@ -815,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(
- llvm::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(
- llvm::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(llvm::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
@@ -1108,18 +1108,24 @@ void FileCheckPatternContext::createLineVariable() {
GlobalNumericVariableTable[LineName] = LineVariable;
}
-bool FileCheck::ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
- std::vector<FileCheckString> &CheckStrings) {
+FileCheck::FileCheck(FileCheckRequest Req)
+ : Req(Req), PatternContext(std::make_unique<FileCheckPatternContext>()),
+ CheckStrings(std::make_unique<std::vector<FileCheckString>>()) {}
+
+FileCheck::~FileCheck() = default;
+
+bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer,
+ Regex &PrefixRE) {
Error DefineError =
- PatternContext.defineCmdlineVariables(Req.GlobalDefines, SM);
+ PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
if (DefineError) {
logAllUnhandledErrors(std::move(DefineError), errs());
return true;
}
- PatternContext.createLineVariable();
+ 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.
@@ -1133,12 +1139,12 @@ bool FileCheck::ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
ImplicitNegativeChecks.push_back(
- FileCheckPattern(Check::CheckNot, &PatternContext));
+ 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.
@@ -1196,7 +1202,7 @@ bool FileCheck::ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
// Parse the pattern.
- FileCheckPattern P(CheckTy, &PatternContext, LineNumber);
+ Pattern P(CheckTy, PatternContext.get(), LineNumber);
if (P.parsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, Req))
return true;
@@ -1214,7 +1220,7 @@ bool FileCheck::ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
// Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||
CheckTy == Check::CheckEmpty) &&
- CheckStrings.empty()) {
+ CheckStrings->empty()) {
StringRef Type = CheckTy == Check::CheckNext
? "NEXT"
: CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";
@@ -1232,21 +1238,21 @@ bool FileCheck::ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
}
// Okay, add the string we captured to the output vector and move on.
- CheckStrings.emplace_back(P, UsedPrefix, PatternLoc);
- std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
+ CheckStrings->emplace_back(P, UsedPrefix, PatternLoc);
+ std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
DagNotMatches = ImplicitNegativeChecks;
}
// Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
// prefix as a filler for the error message.
if (!DagNotMatches.empty()) {
- CheckStrings.emplace_back(
- FileCheckPattern(Check::CheckEOF, &PatternContext, LineNumber + 1),
+ CheckStrings->emplace_back(
+ Pattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1),
*Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data()));
- std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
+ std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
}
- if (CheckStrings.empty()) {
+ if (CheckStrings->empty()) {
errs() << "error: no check strings found with prefix"
<< (Req.CheckPrefixes.size() > 1 ? "es " : " ");
auto I = Req.CheckPrefixes.begin();
@@ -1266,7 +1272,7 @@ bool FileCheck::ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
}
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) {
@@ -1312,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) {
@@ -1341,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)
@@ -1407,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
@@ -1545,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;
@@ -1571,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;
@@ -1595,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!");
@@ -1704,7 +1708,7 @@ FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
// A check prefix must contain only alphanumeric, hyphens and underscores.
static bool ValidateCheckPrefix(StringRef CheckPrefix) {
- Regex Validator("^[a-zA-Z0-9_-]*$");
+ static const Regex Validator("^[a-zA-Z0-9_-]*$");
return Validator.match(CheckPrefix);
}
@@ -1759,11 +1763,32 @@ Error FileCheckPatternContext::defineCmdlineVariables(
unsigned I = 0;
Error Errs = Error::success();
std::string CmdlineDefsDiag;
- StringRef Prefix1 = "Global define #";
- StringRef Prefix2 = ": ";
- for (StringRef CmdlineDef : CmdlineDefines)
- CmdlineDefsDiag +=
- (Prefix1 + Twine(++I) + Prefix2 + CmdlineDef + "\n").str();
+ SmallVector<std::pair<size_t, size_t>, 4> CmdlineDefsIndices;
+ for (StringRef CmdlineDef : CmdlineDefines) {
+ std::string DefPrefix = ("Global define #" + Twine(++I) + ": ").str();
+ size_t EqIdx = CmdlineDef.find('=');
+ if (EqIdx == StringRef::npos) {
+ CmdlineDefsIndices.push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
+ continue;
+ }
+ // Numeric variable definition.
+ if (CmdlineDef[0] == '#') {
+ // Append a copy of the command-line definition adapted to use the same
+ // format as in the input file to be able to reuse
+ // parseNumericSubstitutionBlock.
+ CmdlineDefsDiag += (DefPrefix + CmdlineDef + " (parsed as: [[").str();
+ std::string SubstitutionStr = CmdlineDef;
+ SubstitutionStr[EqIdx] = ':';
+ CmdlineDefsIndices.push_back(
+ std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
+ CmdlineDefsDiag += (SubstitutionStr + Twine("]])\n")).str();
+ } else {
+ CmdlineDefsDiag += DefPrefix;
+ CmdlineDefsIndices.push_back(
+ std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
+ CmdlineDefsDiag += (CmdlineDef + "\n").str();
+ }
+ }
// Create a buffer with fake command line content in order to display
// parsing diagnostic with location information and point to the
@@ -1773,55 +1798,55 @@ Error FileCheckPatternContext::defineCmdlineVariables(
StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
SM.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer), SMLoc());
- SmallVector<StringRef, 4> CmdlineDefsDiagVec;
- CmdlineDefsDiagRef.split(CmdlineDefsDiagVec, '\n', -1 /*MaxSplit*/,
- false /*KeepEmpty*/);
- for (StringRef CmdlineDefDiag : CmdlineDefsDiagVec) {
- unsigned DefStart = CmdlineDefDiag.find(Prefix2) + Prefix2.size();
- StringRef CmdlineDef = CmdlineDefDiag.substr(DefStart);
- size_t EqIdx = CmdlineDef.find('=');
- if (EqIdx == StringRef::npos) {
+ for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
+ StringRef CmdlineDef = CmdlineDefsDiagRef.substr(CmdlineDefIndices.first,
+ CmdlineDefIndices.second);
+ 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;
}
// Numeric variable definition.
if (CmdlineDef[0] == '#') {
- StringRef CmdlineName = CmdlineDef.substr(1, EqIdx - 1);
- Expected<FileCheckNumericVariable *> ParseResult =
- FileCheckPattern::parseNumericVariableDefinition(CmdlineName, this,
- None, SM);
- if (!ParseResult) {
- Errs = joinErrors(std::move(Errs), ParseResult.takeError());
+ // 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<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;
}
-
- StringRef CmdlineVal = CmdlineDef.substr(EqIdx + 1);
- uint64_t Val;
- if (CmdlineVal.getAsInteger(10, Val)) {
- Errs = joinErrors(std::move(Errs),
- FileCheckErrorDiagnostic::get(
- SM, CmdlineVal,
- "invalid value in numeric variable definition '" +
- CmdlineVal + "'"));
+ 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 = ExpressionASTPointer->eval();
+ if (!Value) {
+ Errs = joinErrors(std::move(Errs), Value.takeError());
continue;
}
- FileCheckNumericVariable *DefinedNumericVariable = *ParseResult;
- DefinedNumericVariable->setValue(Val);
+
+ assert(DefinedNumericVariable && "No variable defined");
+ (*DefinedNumericVariable)->setValue(*Value);
// Record this variable definition.
- GlobalNumericVariableTable[DefinedNumericVariable->getName()] =
- DefinedNumericVariable;
+ GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
+ *DefinedNumericVariable;
} else {
// String variable definition.
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;
@@ -1831,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 + "'"));
@@ -1843,15 +1868,15 @@ 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;
}
GlobalVariableTable.insert(CmdlineNameVal);
// Mark the string variable as defined to detect collisions between
- // string and numeric variables in DefineCmdlineVariables when the latter
+ // string and numeric variables in defineCmdlineVariables when the latter
// is created later than the former. We cannot reuse GlobalVariableTable
// for this by populating it with an empty string since we would then
// lose the ability to detect the use of an undefined variable in
@@ -1887,18 +1912,17 @@ void FileCheckPatternContext::clearLocalVars() {
GlobalNumericVariableTable.erase(Var);
}
-bool FileCheck::CheckInput(SourceMgr &SM, StringRef Buffer,
- ArrayRef<FileCheckString> CheckStrings,
+bool FileCheck::checkInput(SourceMgr &SM, StringRef Buffer,
std::vector<FileCheckDiag> *Diags) {
bool ChecksFailed = false;
- unsigned i = 0, j = 0, e = CheckStrings.size();
+ unsigned i = 0, j = 0, e = CheckStrings->size();
while (true) {
StringRef CheckRegion;
if (j == e) {
CheckRegion = Buffer;
} else {
- const FileCheckString &CheckLabelStr = CheckStrings[j];
+ const FileCheckString &CheckLabelStr = (*CheckStrings)[j];
if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
++j;
continue;
@@ -1921,10 +1945,10 @@ bool FileCheck::CheckInput(SourceMgr &SM, StringRef Buffer,
// CHECK-LABEL and it would clear variables defined on the command-line
// before they get used.
if (i != 0 && Req.EnableVarScope)
- PatternContext.clearLocalVars();
+ PatternContext->clearLocalVars();
for (; i != j; ++i) {
- const FileCheckString &CheckStr = CheckStrings[i];
+ const FileCheckString &CheckStr = (*CheckStrings)[i];
// Check each string within the scanned region, including a second check
// of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
diff --git a/contrib/llvm-project/llvm/lib/Support/FileCheckImpl.h b/contrib/llvm-project/llvm/lib/Support/FileCheckImpl.h
new file mode 100644
index 000000000000..dc07d22aefd8
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/Support/FileCheckImpl.h
@@ -0,0 +1,613 @@
+//===-- FileCheckImpl.h - Private FileCheck Interface ------------*- 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 defines the private interfaces of FileCheck. Its purpose is to
+// allow unit testing of FileCheck and to separate the interface from the
+// implementation. It is only meant to be used by FileCheck.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_SUPPORT_FILECHECKIMPL_H
+#define LLVM_LIB_SUPPORT_FILECHECKIMPL_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/SourceMgr.h"
+#include <map>
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+// Numeric substitution handling code.
+//===----------------------------------------------------------------------===//
+
+/// Base class representing the AST of a given expression.
+class ExpressionAST {
+public:
+ virtual ~ExpressionAST() = default;
+
+ /// Evaluates and \returns the value of the expression represented by this
+ /// AST or an error if evaluation fails.
+ virtual Expected<uint64_t> eval() const = 0;
+};
+
+/// Class representing an unsigned literal in the AST of an expression.
+class ExpressionLiteral : public ExpressionAST {
+private:
+ /// Actual value of the literal.
+ uint64_t Value;
+
+public:
+ /// Constructs a literal with the specified value.
+ ExpressionLiteral(uint64_t Val) : Value(Val) {}
+
+ /// \returns the literal's 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 UndefVarError : public ErrorInfo<UndefVarError> {
+private:
+ StringRef VarName;
+
+public:
+ static char ID;
+
+ UndefVarError(StringRef VarName) : VarName(VarName) {}
+
+ StringRef getVarName() const { return VarName; }
+
+ std::error_code convertToErrorCode() const override {
+ return inconvertibleErrorCode();
+ }
+
+ /// Print name of variable associated with this error.
+ void log(raw_ostream &OS) const override {
+ OS << "\"";
+ OS.write_escaped(VarName) << "\"";
+ }
+};
+
+/// Class representing a numeric variable and its associated current value.
+class NumericVariable {
+private:
+ /// Name of the numeric variable.
+ StringRef Name;
+
+ /// Value of numeric variable, if defined, or None otherwise.
+ Optional<uint64_t> Value;
+
+ /// Line number where this variable is defined, or None if defined before
+ /// input is parsed. Used to determine whether a variable is defined on the
+ /// same line as a given use.
+ Optional<size_t> DefLineNumber;
+
+public:
+ /// Constructor for a variable \p Name defined at line \p DefLineNumber or
+ /// defined before input is parsed if \p DefLineNumber is None.
+ explicit NumericVariable(StringRef Name,
+ Optional<size_t> DefLineNumber = None)
+ : Name(Name), DefLineNumber(DefLineNumber) {}
+
+ /// \returns name of this numeric variable.
+ StringRef getName() const { return Name; }
+
+ /// \returns this variable's value.
+ Optional<uint64_t> getValue() const { return Value; }
+
+ /// Sets value of this numeric variable to \p NewValue.
+ void setValue(uint64_t NewValue) { Value = NewValue; }
+
+ /// Clears value of this numeric variable, regardless of whether it is
+ /// currently defined or not.
+ void clearValue() { Value = None; }
+
+ /// \returns the line number where this variable is defined, if any, or None
+ /// if defined before input is parsed.
+ Optional<size_t> getDefLineNumber() const { return DefLineNumber; }
+};
+
+/// Class representing the use of a numeric variable in the AST of an
+/// expression.
+class NumericVariableUse : public ExpressionAST {
+private:
+ /// Name of the numeric variable.
+ StringRef Name;
+
+ /// Pointer to the class instance for the variable this use is about.
+ NumericVariable *Variable;
+
+public:
+ NumericVariableUse(StringRef Name, NumericVariable *Variable)
+ : Name(Name), Variable(Variable) {}
+
+ /// \returns the value of the variable referenced by this instance.
+ 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 BinaryOperation : public ExpressionAST {
+private:
+ /// Left operand.
+ std::unique_ptr<ExpressionAST> LeftOperand;
+
+ /// Right operand.
+ std::unique_ptr<ExpressionAST> RightOperand;
+
+ /// Pointer to function that can evaluate this binary operation.
+ binop_eval_t EvalBinop;
+
+public:
+ 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);
+ }
+
+ /// Evaluates the value of the binary operation represented by this AST,
+ /// 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 override;
+};
+
+class FileCheckPatternContext;
+
+/// Class representing a substitution to perform in the RegExStr string.
+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.
+ /// Used for substituting string variables with the text they were defined
+ /// as. Expressions are linked to the numeric variables they use at
+ /// parse time and directly access the value of the numeric variable to
+ /// evaluate their value.
+ FileCheckPatternContext *Context;
+
+ /// The string that needs to be substituted for something else. For a
+ /// string variable this is its name, otherwise this is the whole expression.
+ StringRef FromStr;
+
+ // Index in RegExStr of where to do the substitution.
+ size_t InsertIdx;
+
+public:
+ Substitution(FileCheckPatternContext *Context, StringRef VarName,
+ size_t InsertIdx)
+ : Context(Context), FromStr(VarName), InsertIdx(InsertIdx) {}
+
+ virtual ~Substitution() = default;
+
+ /// \returns the string to be substituted for something else.
+ StringRef getFromString() const { return FromStr; }
+
+ /// \returns the index where the substitution is to be performed in RegExStr.
+ size_t getIndex() const { return InsertIdx; }
+
+ /// \returns a string containing the result of the substitution represented
+ /// by this class instance or an error if substitution failed.
+ virtual Expected<std::string> getResult() const = 0;
+};
+
+class StringSubstitution : public Substitution {
+public:
+ 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 NumericSubstitution : public Substitution {
+private:
+ /// Pointer to the class representing the expression whose value is to be
+ /// substituted.
+ std::unique_ptr<ExpressionAST> ExpressionASTPointer;
+
+public:
+ 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
+ /// this substitution, or an error if evaluation failed.
+ Expected<std::string> getResult() const override;
+};
+
+//===----------------------------------------------------------------------===//
+// Pattern handling code.
+//===----------------------------------------------------------------------===//
+
+struct FileCheckDiag;
+
+/// 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 Pattern;
+
+private:
+ /// When matching a given pattern, this holds the value of all the string
+ /// variables defined in previous patterns. In a pattern, only the last
+ /// definition for a given variable is recorded in this table.
+ /// Back-references are used for uses after any the other definition.
+ StringMap<StringRef> GlobalVariableTable;
+
+ /// Map of all string variables defined so far. Used at parse time to detect
+ /// a name conflict between a numeric variable and a string variable when
+ /// the former is defined on a later line than the latter.
+ StringMap<bool> DefinedVariableTable;
+
+ /// 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 Pattern instance of that pattern.
+ StringMap<NumericVariable *> GlobalNumericVariableTable;
+
+ /// Pointer to the class instance representing the @LINE pseudo variable for
+ /// easily updating its value.
+ 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<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<Substitution>> Substitutions;
+
+public:
+ /// \returns the value of string variable \p VarName or an error if no such
+ /// variable has been defined.
+ Expected<StringRef> getPatternVarValue(StringRef VarName);
+
+ /// Defines string and numeric variables from definitions given on the
+ /// command line, passed as a vector of [#]VAR=VAL strings in
+ /// \p CmdlineDefines. \returns an error list containing diagnostics against
+ /// \p SM for all definition parsing failures, if any, or Success otherwise.
+ Error defineCmdlineVariables(std::vector<std::string> &CmdlineDefines,
+ SourceMgr &SM);
+
+ /// Create @LINE pseudo variable. Value is set when pattern are being
+ /// matched.
+ void createLineVariable();
+
+ /// Undefines local variables (variables whose name does not start with a '$'
+ /// sign), i.e. removes them from GlobalVariableTable and from
+ /// GlobalNumericVariableTable and also clears the value of numeric
+ /// variables.
+ void clearLocalVars();
+
+private:
+ /// Makes a new numeric variable and registers it for destruction when the
+ /// context is destroyed.
+ template <class... Types> NumericVariable *makeNumericVariable(Types... args);
+
+ /// Makes a new string substitution and registers it for destruction when the
+ /// context is destroyed.
+ Substitution *makeStringSubstitution(StringRef VarName, size_t InsertIdx);
+
+ /// Makes a new numeric substitution and registers it for destruction when
+ /// the context is destroyed.
+ Substitution *
+ makeNumericSubstitution(StringRef ExpressionStr,
+ std::unique_ptr<ExpressionAST> ExpressionAST,
+ size_t InsertIdx);
+};
+
+/// Class to represent an error holding a diagnostic with location information
+/// used when printing it.
+class ErrorDiagnostic : public ErrorInfo<ErrorDiagnostic> {
+private:
+ SMDiagnostic Diagnostic;
+
+public:
+ static char ID;
+
+ ErrorDiagnostic(SMDiagnostic &&Diag) : Diagnostic(Diag) {}
+
+ std::error_code convertToErrorCode() const override {
+ return inconvertibleErrorCode();
+ }
+
+ /// Print diagnostic associated with this error when printing the error.
+ 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<ErrorDiagnostic>(
+ SM.GetMessage(Loc, SourceMgr::DK_Error, ErrMsg));
+ }
+
+ static Error get(const SourceMgr &SM, StringRef Buffer, const Twine &ErrMsg) {
+ return get(SM, SMLoc::getFromPointer(Buffer.data()), ErrMsg);
+ }
+};
+
+class NotFoundError : public ErrorInfo<NotFoundError> {
+public:
+ static char ID;
+
+ std::error_code convertToErrorCode() const override {
+ return inconvertibleErrorCode();
+ }
+
+ /// Print diagnostic associated with this error when printing the error.
+ void log(raw_ostream &OS) const override {
+ OS << "String not found in input";
+ }
+};
+
+class Pattern {
+ SMLoc PatternLoc;
+
+ /// A fixed string to match as the pattern or empty if this pattern requires
+ /// a regex match.
+ StringRef FixedStr;
+
+ /// A regex string to match as the pattern or empty if this pattern requires
+ /// a fixed string to match.
+ std::string RegExStr;
+
+ /// Entries in this vector represent a substitution of a string variable or
+ /// an expression in the RegExStr regex at match time. For example, in the
+ /// case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]",
+ /// 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<Substitution *> Substitutions;
+
+ /// Maps names of string variables defined in a pattern to the number of
+ /// their parenthesis group in RegExStr capturing their last definition.
+ ///
+ /// E.g. for the pattern "foo[[bar:.*]]baz([[bar]][[QUUX]][[bar:.*]])",
+ /// RegExStr will be "foo(.*)baz(\1<quux value>(.*))" where <quux value> is
+ /// the value captured for QUUX on the earlier line where it was defined, and
+ /// VariableDefs will map "bar" to the third parenthesis group which captures
+ /// the second definition of "bar".
+ ///
+ /// Note: uses std::map rather than StringMap to be able to get the key when
+ /// iterating over values.
+ std::map<StringRef, unsigned> VariableDefs;
+
+ /// Structure representing the definition of a numeric variable in a pattern.
+ /// 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 NumericVariableMatch {
+ /// Pointer to class representing the numeric variable whose value is being
+ /// defined.
+ NumericVariable *DefinedNumericVariable;
+
+ /// Number of the parenthesis group in RegExStr that captures the value of
+ /// this numeric variable definition.
+ unsigned CaptureParenGroup;
+ };
+
+ /// Holds the number of the parenthesis group in RegExStr and pointer to the
+ /// 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:
+ /// - separate tables with the values of live string and numeric variables
+ /// respectively at the start of any given CHECK line;
+ /// - table holding whether a string variable has been defined at any given
+ /// point during the parsing phase.
+ FileCheckPatternContext *Context;
+
+ Check::FileCheckType CheckTy;
+
+ /// Line number for this CHECK pattern or None if it is an implicit pattern.
+ /// Used to determine whether a variable definition is made on an earlier
+ /// line to the one with this CHECK.
+ Optional<size_t> LineNumber;
+
+ /// Ignore case while matching if set to true.
+ bool IgnoreCase = false;
+
+public:
+ Pattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
+ Optional<size_t> Line = None)
+ : Context(Context), CheckTy(Ty), LineNumber(Line) {}
+
+ /// \returns the location in source code.
+ SMLoc getLoc() const { return PatternLoc; }
+
+ /// \returns the pointer to the global state for all patterns in this
+ /// FileCheck instance.
+ FileCheckPatternContext *getContext() const { return Context; }
+
+ /// \returns whether \p C is a valid first character for a variable name.
+ static bool isValidVarNameStart(char C);
+
+ /// Parsing information about a variable.
+ struct VariableProperties {
+ StringRef Name;
+ bool IsPseudo;
+ };
+
+ /// Parses the string at the start of \p Str for a variable name. \returns
+ /// a VariableProperties structure holding the variable name and whether it
+ /// is the name of a pseudo variable, or an error holding a diagnostic
+ /// against \p SM if parsing fail. If parsing was successful, also strips
+ /// \p Str from the variable name.
+ static Expected<VariableProperties> parseVariable(StringRef &Str,
+ const SourceMgr &SM);
+ /// Parses \p Expr for a numeric substitution block at line \p LineNumber,
+ /// or before input is parsed if \p LineNumber is None. Parameter
+ /// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE
+ /// expression and \p Context points to the class instance holding the live
+ /// string and numeric variables. \returns a pointer to the class instance
+ /// representing the AST of the expression whose value must be substitued, or
+ /// an error holding a diagnostic against \p SM if parsing fails. If
+ /// 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<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 Pattern instance
+ /// accordingly.
+ ///
+ /// \p Prefix provides which prefix is being matched, \p Req describes the
+ /// global options that influence the parsing such as whitespace
+ /// canonicalization, \p SM provides the SourceMgr used for error reports.
+ /// \returns true in case of an error, false otherwise.
+ bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,
+ const FileCheckRequest &Req);
+ /// Matches the pattern string against the input buffer \p Buffer
+ ///
+ /// \returns the position that is matched or an error indicating why matching
+ /// failed. If there is a match, updates \p MatchLen with the size of the
+ /// 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
+ /// GlobalNumericVariableTable StringMap in the same class provides the
+ /// current values of FileCheck numeric variables and is updated if this
+ /// match defines new numeric values.
+ Expected<size_t> match(StringRef Buffer, size_t &MatchLen,
+ const SourceMgr &SM) const;
+ /// Prints the value of successful substitutions or the name of the undefined
+ /// string or numeric variables preventing a successful substitution.
+ void printSubstitutions(const SourceMgr &SM, StringRef Buffer,
+ SMRange MatchRange = None) const;
+ void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
+ std::vector<FileCheckDiag> *Diags) const;
+
+ bool hasVariable() const {
+ return !(Substitutions.empty() && VariableDefs.empty());
+ }
+
+ Check::FileCheckType getCheckTy() const { return CheckTy; }
+
+ int getCount() const { return CheckTy.getCount(); }
+
+private:
+ bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
+ void AddBackrefToRegEx(unsigned BackrefNum);
+ /// Computes an arbitrary estimate for the quality of matching this pattern
+ /// at the start of \p Buffer; a distance of zero should correspond to a
+ /// perfect match.
+ unsigned computeMatchDistance(StringRef Buffer) const;
+ /// 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 reporting.
+ /// \returns the offset of the closing sequence within Str, or npos if it
+ /// was not found.
+ 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<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
+ /// at line \p LineNumber, or before input is parsed if \p LineNumber is
+ /// None. Parameter \p Context points to the class instance holding the live
+ /// 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<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
+ /// values and numeric variables, depending on the value of \p AO. Parameter
+ /// \p Context points to the class instance holding the live string and
+ /// 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<ExpressionAST>>
+ parseNumericOperand(StringRef &Expr, AllowedOperand AO,
+ Optional<size_t> LineNumber,
+ FileCheckPatternContext *Context, const SourceMgr &SM);
+ /// Parses \p Expr for a binary operation at line \p LineNumber, or before
+ /// input is parsed if \p LineNumber is None. The left operand of this binary
+ /// operation is given in \p LeftOp and \p IsLegacyLineExpr indicates whether
+ /// we are parsing a legacy @LINE expression. Parameter \p Context points to
+ /// 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<ExpressionAST>>
+ parseBinop(StringRef &Expr, std::unique_ptr<ExpressionAST> LeftOp,
+ bool IsLegacyLineExpr, Optional<size_t> LineNumber,
+ FileCheckPatternContext *Context, const SourceMgr &SM);
+};
+
+//===----------------------------------------------------------------------===//
+// Check Strings.
+//===----------------------------------------------------------------------===//
+
+/// A check that we found in the input file.
+struct FileCheckString {
+ /// The pattern to match.
+ Pattern Pat;
+
+ /// Which prefix name this check matched.
+ StringRef Prefix;
+
+ /// The location in the match file that the check string was specified.
+ SMLoc Loc;
+
+ /// All of the strings that are disallowed from occurring between this match
+ /// string and the previous one (or start of file).
+ std::vector<Pattern> DagNotStrings;
+
+ 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".
+ size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
+ size_t &MatchLen, FileCheckRequest &Req,
+ std::vector<FileCheckDiag> *Diags) const;
+
+ /// Verifies that there is a single line in the given \p Buffer. Errors are
+ /// reported against \p SM.
+ bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
+ /// Verifies that there is no newline in the given \p Buffer. Errors are
+ /// reported against \p SM.
+ bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
+ /// Verifies that none of the strings in \p NotStrings are found in the given
+ /// \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 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 Pattern *> &NotStrings,
+ const FileCheckRequest &Req,
+ std::vector<FileCheckDiag> *Diags) const;
+};
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm-project/llvm/lib/Support/FileCollector.cpp b/contrib/llvm-project/llvm/lib/Support/FileCollector.cpp
new file mode 100644
index 000000000000..47fca6413722
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/Support/FileCollector.cpp
@@ -0,0 +1,268 @@
+//===-- FileCollector.cpp ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/FileCollector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+
+using namespace llvm;
+
+static bool isCaseSensitivePath(StringRef Path) {
+ SmallString<256> TmpDest = Path, UpperDest, RealDest;
+
+ // Remove component traversals, links, etc.
+ if (!sys::fs::real_path(Path, TmpDest))
+ return true; // Current default value in vfs.yaml
+ Path = TmpDest;
+
+ // Change path to all upper case and ask for its real path, if the latter
+ // exists and is equal to path, it's not case sensitive. Default to case
+ // sensitive in the absence of real_path, since this is the YAMLVFSWriter
+ // default.
+ UpperDest = Path.upper();
+ if (sys::fs::real_path(UpperDest, RealDest) && Path.equals(RealDest))
+ return false;
+ return true;
+}
+
+FileCollector::FileCollector(std::string Root, std::string OverlayRoot)
+ : Root(std::move(Root)), OverlayRoot(std::move(OverlayRoot)) {
+ sys::fs::create_directories(this->Root, true);
+}
+
+bool FileCollector::getRealPath(StringRef SrcPath,
+ SmallVectorImpl<char> &Result) {
+ SmallString<256> RealPath;
+ StringRef FileName = sys::path::filename(SrcPath);
+ std::string Directory = sys::path::parent_path(SrcPath).str();
+ auto DirWithSymlink = SymlinkMap.find(Directory);
+
+ // Use real_path to fix any symbolic link component present in a path.
+ // Computing the real path is expensive, cache the search through the parent
+ // path Directory.
+ if (DirWithSymlink == SymlinkMap.end()) {
+ auto EC = sys::fs::real_path(Directory, RealPath);
+ if (EC)
+ return false;
+ SymlinkMap[Directory] = RealPath.str();
+ } else {
+ RealPath = DirWithSymlink->second;
+ }
+
+ sys::path::append(RealPath, FileName);
+ Result.swap(RealPath);
+ return true;
+}
+
+void FileCollector::addFile(const Twine &file) {
+ std::lock_guard<std::mutex> lock(Mutex);
+ std::string FileStr = file.str();
+ if (markAsSeen(FileStr))
+ addFileImpl(FileStr);
+}
+
+void FileCollector::addFileImpl(StringRef SrcPath) {
+ // We need an absolute src path to append to the root.
+ SmallString<256> AbsoluteSrc = SrcPath;
+ sys::fs::make_absolute(AbsoluteSrc);
+
+ // Canonicalize src to a native path to avoid mixed separator styles.
+ sys::path::native(AbsoluteSrc);
+
+ // Remove redundant leading "./" pieces and consecutive separators.
+ AbsoluteSrc = sys::path::remove_leading_dotslash(AbsoluteSrc);
+
+ // Canonicalize the source path by removing "..", "." components.
+ SmallString<256> VirtualPath = AbsoluteSrc;
+ sys::path::remove_dots(VirtualPath, /*remove_dot_dot=*/true);
+
+ // If a ".." component is present after a symlink component, remove_dots may
+ // lead to the wrong real destination path. Let the source be canonicalized
+ // like that but make sure we always use the real path for the destination.
+ SmallString<256> CopyFrom;
+ if (!getRealPath(AbsoluteSrc, CopyFrom))
+ CopyFrom = VirtualPath;
+
+ SmallString<256> DstPath = StringRef(Root);
+ sys::path::append(DstPath, sys::path::relative_path(CopyFrom));
+
+ // Always map a canonical src path to its real path into the YAML, by doing
+ // this we map different virtual src paths to the same entry in the VFS
+ // overlay, which is a way to emulate symlink inside the VFS; this is also
+ // needed for correctness, not doing that can lead to module redefinition
+ // errors.
+ addFileToMapping(VirtualPath, DstPath);
+}
+
+/// Set the access and modification time for the given file from the given
+/// status object.
+static std::error_code
+copyAccessAndModificationTime(StringRef Filename,
+ const sys::fs::file_status &Stat) {
+ int FD;
+
+ if (auto EC =
+ sys::fs::openFileForWrite(Filename, FD, sys::fs::CD_OpenExisting))
+ return EC;
+
+ if (auto EC = sys::fs::setLastAccessAndModificationTime(
+ FD, Stat.getLastAccessedTime(), Stat.getLastModificationTime()))
+ return EC;
+
+ if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))
+ return EC;
+
+ return {};
+}
+
+std::error_code FileCollector::copyFiles(bool StopOnError) {
+ for (auto &entry : VFSWriter.getMappings()) {
+ // Create directory tree.
+ if (std::error_code EC =
+ sys::fs::create_directories(sys::path::parent_path(entry.RPath),
+ /*IgnoreExisting=*/true)) {
+ if (StopOnError)
+ return EC;
+ }
+
+ // Get the status of the original file/directory.
+ sys::fs::file_status Stat;
+ if (std::error_code EC = sys::fs::status(entry.VPath, Stat)) {
+ if (StopOnError)
+ return EC;
+ continue;
+ }
+
+ if (Stat.type() == sys::fs::file_type::directory_file) {
+ // Construct a directory when it's just a directory entry.
+ if (std::error_code EC =
+ sys::fs::create_directories(entry.RPath,
+ /*IgnoreExisting=*/true)) {
+ if (StopOnError)
+ return EC;
+ }
+ continue;
+ }
+
+ // Copy file over.
+ if (std::error_code EC = sys::fs::copy_file(entry.VPath, entry.RPath)) {
+ if (StopOnError)
+ return EC;
+ }
+
+ // Copy over permissions.
+ if (auto perms = sys::fs::getPermissions(entry.VPath)) {
+ if (std::error_code EC = sys::fs::setPermissions(entry.RPath, *perms)) {
+ if (StopOnError)
+ return EC;
+ }
+ }
+
+ // Copy over modification time.
+ copyAccessAndModificationTime(entry.RPath, Stat);
+ }
+ return {};
+}
+
+std::error_code FileCollector::writeMapping(StringRef mapping_file) {
+ std::lock_guard<std::mutex> lock(Mutex);
+
+ VFSWriter.setOverlayDir(OverlayRoot);
+ VFSWriter.setCaseSensitivity(isCaseSensitivePath(OverlayRoot));
+ VFSWriter.setUseExternalNames(false);
+
+ std::error_code EC;
+ raw_fd_ostream os(mapping_file, EC, sys::fs::OF_Text);
+ if (EC)
+ return EC;
+
+ VFSWriter.write(os);
+
+ return {};
+}
+
+namespace {
+
+class FileCollectorFileSystem : public vfs::FileSystem {
+public:
+ explicit FileCollectorFileSystem(IntrusiveRefCntPtr<vfs::FileSystem> FS,
+ std::shared_ptr<FileCollector> Collector)
+ : FS(std::move(FS)), Collector(std::move(Collector)) {}
+
+ llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override {
+ auto Result = FS->status(Path);
+ if (Result && Result->exists())
+ Collector->addFile(Path);
+ return Result;
+ }
+
+ llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
+ openFileForRead(const Twine &Path) override {
+ auto Result = FS->openFileForRead(Path);
+ if (Result && *Result)
+ Collector->addFile(Path);
+ return Result;
+ }
+
+ llvm::vfs::directory_iterator dir_begin(const llvm::Twine &Dir,
+ std::error_code &EC) override {
+ auto It = FS->dir_begin(Dir, EC);
+ if (EC)
+ return It;
+ // Collect everything that's listed in case the user needs it.
+ Collector->addFile(Dir);
+ for (; !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
+ if (It->type() == sys::fs::file_type::regular_file ||
+ It->type() == sys::fs::file_type::directory_file ||
+ It->type() == sys::fs::file_type::symlink_file) {
+ Collector->addFile(It->path());
+ }
+ }
+ if (EC)
+ return It;
+ // Return a new iterator.
+ return FS->dir_begin(Dir, EC);
+ }
+
+ std::error_code getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const override {
+ auto EC = FS->getRealPath(Path, Output);
+ if (!EC) {
+ Collector->addFile(Path);
+ if (Output.size() > 0)
+ Collector->addFile(Output);
+ }
+ return EC;
+ }
+
+ std::error_code isLocal(const Twine &Path, bool &Result) override {
+ return FS->isLocal(Path, Result);
+ }
+
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+ return FS->getCurrentWorkingDirectory();
+ }
+
+ std::error_code setCurrentWorkingDirectory(const llvm::Twine &Path) override {
+ return FS->setCurrentWorkingDirectory(Path);
+ }
+
+private:
+ IntrusiveRefCntPtr<vfs::FileSystem> FS;
+ std::shared_ptr<FileCollector> Collector;
+};
+
+} // end anonymous namespace
+
+IntrusiveRefCntPtr<vfs::FileSystem>
+FileCollector::createCollectorVFS(IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
+ std::shared_ptr<FileCollector> Collector) {
+ return new FileCollectorFileSystem(std::move(BaseFS), std::move(Collector));
+}
diff --git a/contrib/llvm-project/llvm/lib/Support/FileOutputBuffer.cpp b/contrib/llvm-project/llvm/lib/Support/FileOutputBuffer.cpp
index 3d6b569f2993..0a5306f684d4 100644
--- a/contrib/llvm-project/llvm/lib/Support/FileOutputBuffer.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/FileOutputBuffer.cpp
@@ -121,7 +121,7 @@ createInMemoryBuffer(StringRef Path, size_t Size, unsigned Mode) {
Size, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
if (EC)
return errorCodeToError(EC);
- return llvm::make_unique<InMemoryBuffer>(Path, MB, Size, Mode);
+ return std::make_unique<InMemoryBuffer>(Path, MB, Size, Mode);
}
static Expected<std::unique_ptr<FileOutputBuffer>>
@@ -146,7 +146,7 @@ createOnDiskBuffer(StringRef Path, size_t Size, unsigned Mode) {
// Mmap it.
std::error_code EC;
- auto MappedFile = llvm::make_unique<fs::mapped_file_region>(
+ auto MappedFile = std::make_unique<fs::mapped_file_region>(
fs::convertFDToNativeFile(File.FD), fs::mapped_file_region::readwrite,
Size, 0, EC);
@@ -157,7 +157,7 @@ createOnDiskBuffer(StringRef Path, size_t Size, unsigned Mode) {
return createInMemoryBuffer(Path, Size, Mode);
}
- return llvm::make_unique<OnDiskBuffer>(Path, std::move(File),
+ return std::make_unique<OnDiskBuffer>(Path, std::move(File),
std::move(MappedFile));
}
@@ -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/contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp b/contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp
index 62eb7bfda195..d11fbb54dc0d 100644
--- a/contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp
@@ -12,9 +12,12 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/FileUtilities.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <cctype>
#include <cmath>
@@ -264,3 +267,66 @@ int llvm::DiffFilesWithTolerance(StringRef NameA,
return CompareFailed;
}
+
+void llvm::AtomicFileWriteError::log(raw_ostream &OS) const {
+ OS << "atomic_write_error: ";
+ switch (Error) {
+ case atomic_write_error::failed_to_create_uniq_file:
+ OS << "failed_to_create_uniq_file";
+ return;
+ case atomic_write_error::output_stream_error:
+ OS << "output_stream_error";
+ return;
+ case atomic_write_error::failed_to_rename_temp_file:
+ OS << "failed_to_rename_temp_file";
+ return;
+ }
+ llvm_unreachable("unknown atomic_write_error value in "
+ "failed_to_rename_temp_file::log()");
+}
+
+llvm::Error llvm::writeFileAtomically(StringRef TempPathModel,
+ StringRef FinalPath, StringRef Buffer) {
+ return writeFileAtomically(TempPathModel, FinalPath,
+ [&Buffer](llvm::raw_ostream &OS) {
+ OS.write(Buffer.data(), Buffer.size());
+ return llvm::Error::success();
+ });
+}
+
+llvm::Error llvm::writeFileAtomically(
+ StringRef TempPathModel, StringRef FinalPath,
+ std::function<llvm::Error(llvm::raw_ostream &)> Writer) {
+ SmallString<128> GeneratedUniqPath;
+ int TempFD;
+ if (sys::fs::createUniqueFile(TempPathModel.str(), TempFD,
+ GeneratedUniqPath)) {
+ return llvm::make_error<AtomicFileWriteError>(
+ atomic_write_error::failed_to_create_uniq_file);
+ }
+ llvm::FileRemover RemoveTmpFileOnFail(GeneratedUniqPath);
+
+ raw_fd_ostream OS(TempFD, /*shouldClose=*/true);
+ if (llvm::Error Err = Writer(OS)) {
+ return Err;
+ }
+
+ OS.close();
+ if (OS.has_error()) {
+ OS.clear_error();
+ return llvm::make_error<AtomicFileWriteError>(
+ atomic_write_error::output_stream_error);
+ }
+
+ if (const std::error_code Error =
+ sys::fs::rename(/*from=*/GeneratedUniqPath.c_str(),
+ /*to=*/FinalPath.str().c_str())) {
+ return llvm::make_error<AtomicFileWriteError>(
+ atomic_write_error::failed_to_rename_temp_file);
+ }
+
+ RemoveTmpFileOnFail.releaseFile();
+ return Error::success();
+}
+
+char llvm::AtomicFileWriteError::ID;
diff --git a/contrib/llvm-project/llvm/lib/Support/GlobPattern.cpp b/contrib/llvm-project/llvm/lib/Support/GlobPattern.cpp
index 6011be86d77f..8dae6941ec77 100644
--- a/contrib/llvm-project/llvm/lib/Support/GlobPattern.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/GlobPattern.cpp
@@ -19,7 +19,7 @@
using namespace llvm;
static bool hasWildcard(StringRef S) {
- return S.find_first_of("?*[") != StringRef::npos;
+ return S.find_first_of("?*[\\") != StringRef::npos;
}
// Expands character ranges and returns a bitmap.
@@ -60,8 +60,9 @@ static Expected<BitVector> expand(StringRef S, StringRef Original) {
}
// This is a scanner for the glob pattern.
-// A glob pattern token is one of "*", "?", "[<chars>]", "[^<chars>]"
-// (which is a negative form of "[<chars>]"), or a non-meta character.
+// A glob pattern token is one of "*", "?", "\", "[<chars>]", "[^<chars>]"
+// (which is a negative form of "[<chars>]"), "[!<chars>]" (which is
+// equivalent to "[^<chars>]"), or a non-meta character.
// This function returns the first token in S.
static Expected<BitVector> scan(StringRef &S, StringRef Original) {
switch (S[0]) {
@@ -74,14 +75,16 @@ static Expected<BitVector> scan(StringRef &S, StringRef Original) {
S = S.substr(1);
return BitVector(256, true);
case '[': {
- size_t End = S.find(']', 1);
+ // ']' is allowed as the first character of a character class. '[]' is
+ // invalid. So, just skip the first character.
+ size_t End = S.find(']', 2);
if (End == StringRef::npos)
return make_error<StringError>("invalid glob pattern: " + Original,
errc::invalid_argument);
StringRef Chars = S.substr(1, End - 1);
S = S.substr(End + 1);
- if (Chars.startswith("^")) {
+ if (Chars.startswith("^") || Chars.startswith("!")) {
Expected<BitVector> BV = expand(Chars.substr(1), Original);
if (!BV)
return BV.takeError();
@@ -89,6 +92,11 @@ static Expected<BitVector> scan(StringRef &S, StringRef Original) {
}
return expand(Chars, Original);
}
+ case '\\':
+ // Eat this character and fall through below to treat it like a non-meta
+ // character.
+ S = S.substr(1);
+ LLVM_FALLTHROUGH;
default:
BitVector BV(256, false);
BV[(uint8_t)S[0]] = true;
@@ -107,8 +115,9 @@ Expected<GlobPattern> GlobPattern::create(StringRef S) {
return Pat;
}
- // S is something like "foo*". We can use startswith().
- if (S.endswith("*") && !hasWildcard(S.drop_back())) {
+ // S is something like "foo*", and the "* is not escaped. We can use
+ // startswith().
+ if (S.endswith("*") && !S.endswith("\\*") && !hasWildcard(S.drop_back())) {
Pat.Prefix = S.drop_back();
return Pat;
}
diff --git a/contrib/llvm-project/llvm/lib/Support/Host.cpp b/contrib/llvm-project/llvm/lib/Support/Host.cpp
index d491912bdc0c..ef38c1c09413 100644
--- a/contrib/llvm-project/llvm/lib/Support/Host.cpp
+++ b/contrib/llvm-project/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";
}
}
@@ -316,7 +317,7 @@ StringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) {
unsigned int Id;
if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) {
if (Id >= 8561 && HaveVectorSupport)
- return "arch13";
+ return "z15";
if (Id >= 3906 && HaveVectorSupport)
return "z14";
if (Id >= 2964 && HaveVectorSupport)
@@ -680,7 +681,7 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
// Skylake Xeon:
case 0x55:
*Type = X86::INTEL_COREI7;
- if (Features3 & (1 << (X86::FEATURE_AVX512BF16 - 64)))
+ if (Features2 & (1 << (X86::FEATURE_AVX512BF16 - 32)))
*Subtype = X86::INTEL_COREI7_COOPERLAKE; // "cooperlake"
else if (Features2 & (1 << (X86::FEATURE_AVX512VNNI - 32)))
*Subtype = X86::INTEL_COREI7_CASCADELAKE; // "cascadelake"
@@ -746,6 +747,13 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
break;
default: // Unknown family 6 CPU, try to guess.
+ // TODO detect tigerlake host
+ if (Features3 & (1 << (X86::FEATURE_AVX512VP2INTERSECT - 64))) {
+ *Type = X86::INTEL_COREI7;
+ *Subtype = X86::INTEL_COREI7_TIGERLAKE;
+ break;
+ }
+
if (Features & (1 << X86::FEATURE_AVX512VBMI2)) {
*Type = X86::INTEL_COREI7;
*Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT;
@@ -758,7 +766,7 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
break;
}
- if (Features3 & (1 << (X86::FEATURE_AVX512BF16 - 64))) {
+ if (Features2 & (1 << (X86::FEATURE_AVX512BF16 - 32))) {
*Type = X86::INTEL_COREI7;
*Subtype = X86::INTEL_COREI7_COOPERLAKE;
break;
@@ -954,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;
@@ -1022,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);
@@ -1034,7 +1050,7 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
setFeature(X86::FEATURE_BMI);
if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
setFeature(X86::FEATURE_AVX2);
- if (HasLeaf7 && ((EBX >> 9) & 1))
+ if (HasLeaf7 && ((EBX >> 8) & 1))
setFeature(X86::FEATURE_BMI2);
if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save)
setFeature(X86::FEATURE_AVX512F);
@@ -1078,6 +1094,13 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
setFeature(X86::FEATURE_AVX5124VNNIW);
if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
setFeature(X86::FEATURE_AVX5124FMAPS);
+ if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save)
+ setFeature(X86::FEATURE_AVX512VP2INTERSECT);
+
+ bool HasLeaf7Subleaf1 =
+ MaxLeaf >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
+ if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)
+ setFeature(X86::FEATURE_AVX512BF16);
unsigned MaxExtLevel;
getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
@@ -1208,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
@@ -1325,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;
@@ -1369,7 +1426,6 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1);
Features["invpcid"] = HasLeaf7 && ((EBX >> 10) & 1);
Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1);
- Features["mpx"] = HasLeaf7 && ((EBX >> 14) & 1);
// AVX512 is only supported if the OS supports the context save for it.
Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
@@ -1499,6 +1555,17 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
return true;
}
+#elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64))
+bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
+ if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE))
+ Features["neon"] = true;
+ if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE))
+ Features["crc"] = true;
+ if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE))
+ Features["crypto"] = true;
+
+ return true;
+}
#else
bool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; }
#endif
diff --git a/contrib/llvm-project/llvm/lib/Support/InitLLVM.cpp b/contrib/llvm-project/llvm/lib/Support/InitLLVM.cpp
index 0d7d7fcc8cb6..bb9b569d2de6 100644
--- a/contrib/llvm-project/llvm/lib/Support/InitLLVM.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp b/contrib/llvm-project/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp
index da6514f7170b..bbc06d186fba 100644
--- a/contrib/llvm-project/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/JSON.cpp b/contrib/llvm-project/llvm/lib/Support/JSON.cpp
index 95e5ed654277..16b1d11efd08 100644
--- a/contrib/llvm-project/llvm/lib/Support/JSON.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/JSON.cpp
@@ -502,7 +502,7 @@ bool Parser::parseError(const char *Msg) {
}
}
Err.emplace(
- llvm::make_unique<ParseError>(Msg, Line, P - StartOfLine, P - Start));
+ std::make_unique<ParseError>(Msg, Line, P - StartOfLine, P - Start));
return false;
}
} // namespace
diff --git a/contrib/llvm-project/llvm/lib/Support/JamCRC.cpp b/contrib/llvm-project/llvm/lib/Support/JamCRC.cpp
deleted file mode 100644
index e043a3c33c28..000000000000
--- a/contrib/llvm-project/llvm/lib/Support/JamCRC.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-//===-- JamCRC.cpp - Cyclic Redundancy Check --------------------*- 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 contains an implementation of JamCRC.
-//
-//===----------------------------------------------------------------------===//
-//
-// The implementation technique is the one mentioned in:
-// D. V. Sarwate. 1988. Computation of cyclic redundancy checks via table
-// look-up. Commun. ACM 31, 8 (August 1988)
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/JamCRC.h"
-#include "llvm/ADT/ArrayRef.h"
-
-using namespace llvm;
-
-static const uint32_t CRCTable[256] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
- 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
- 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
- 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
- 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
- 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
- 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
- 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
- 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
- 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
- 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
- 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
- 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
- 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
- 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
- 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
- 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
- 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
- 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
- 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
- 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
- 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-void JamCRC::update(ArrayRef<char> Data) {
- for (char Byte : Data) {
- int TableIdx = (CRC ^ Byte) & 0xff;
- CRC = CRCTable[TableIdx] ^ (CRC >> 8);
- }
-}
diff --git a/contrib/llvm-project/llvm/lib/Support/KnownBits.cpp b/contrib/llvm-project/llvm/lib/Support/KnownBits.cpp
index a6c591fca312..8f3f4aa8caea 100644
--- a/contrib/llvm-project/llvm/lib/Support/KnownBits.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/LockFileManager.cpp b/contrib/llvm-project/llvm/lib/Support/LockFileManager.cpp
index 10181192afbd..5c6508c3b007 100644
--- a/contrib/llvm-project/llvm/lib/Support/LockFileManager.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/ManagedStatic.cpp b/contrib/llvm-project/llvm/lib/Support/ManagedStatic.cpp
index 28ceb1a70e42..053493f72fb5 100644
--- a/contrib/llvm-project/llvm/lib/Support/ManagedStatic.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/ManagedStatic.cpp
@@ -12,21 +12,20 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Config/config.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/Threading.h"
#include <cassert>
+#include <mutex>
using namespace llvm;
static const ManagedStaticBase *StaticList = nullptr;
-static sys::Mutex *ManagedStaticMutex = nullptr;
+static std::recursive_mutex *ManagedStaticMutex = nullptr;
static llvm::once_flag mutex_init_flag;
static void initializeMutex() {
- ManagedStaticMutex = new sys::Mutex();
+ ManagedStaticMutex = new std::recursive_mutex();
}
-static sys::Mutex* getManagedStaticMutex() {
+static std::recursive_mutex *getManagedStaticMutex() {
llvm::call_once(mutex_init_flag, initializeMutex);
return ManagedStaticMutex;
}
@@ -35,7 +34,7 @@ void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
void (*Deleter)(void*)) const {
assert(Creator);
if (llvm_is_multithreaded()) {
- MutexGuard Lock(*getManagedStaticMutex());
+ std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
if (!Ptr.load(std::memory_order_relaxed)) {
void *Tmp = Creator();
@@ -77,7 +76,7 @@ void ManagedStaticBase::destroy() const {
/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
void llvm::llvm_shutdown() {
- MutexGuard Lock(*getManagedStaticMutex());
+ std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
while (StaticList)
StaticList->destroy();
diff --git a/contrib/llvm-project/llvm/lib/Support/MemoryBuffer.cpp b/contrib/llvm-project/llvm/lib/Support/MemoryBuffer.cpp
index d0e5bb154c1a..e4027ca7bbfd 100644
--- a/contrib/llvm-project/llvm/lib/Support/MemoryBuffer.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/MemoryBuffer.cpp
@@ -211,15 +211,17 @@ static ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
getMemoryBufferForStream(sys::fs::file_t FD, const Twine &BufferName) {
const ssize_t ChunkSize = 4096*4;
SmallString<ChunkSize> Buffer;
- size_t ReadBytes;
// Read into Buffer until we hit EOF.
- do {
+ for (;;) {
Buffer.reserve(Buffer.size() + ChunkSize);
- if (auto EC = sys::fs::readNativeFile(
- FD, makeMutableArrayRef(Buffer.end(), ChunkSize), &ReadBytes))
- return EC;
- Buffer.set_size(Buffer.size() + ReadBytes);
- } while (ReadBytes != 0);
+ Expected<size_t> ReadBytes = sys::fs::readNativeFile(
+ FD, makeMutableArrayRef(Buffer.end(), ChunkSize));
+ if (!ReadBytes)
+ return errorToErrorCode(ReadBytes.takeError());
+ if (*ReadBytes == 0)
+ break;
+ Buffer.set_size(Buffer.size() + *ReadBytes);
+ }
return getMemBufferCopyImpl(Buffer, BufferName);
}
@@ -458,7 +460,20 @@ getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
return make_error_code(errc::not_enough_memory);
}
- sys::fs::readNativeFileSlice(FD, Buf->getBuffer(), Offset);
+ // Read until EOF, zero-initialize the rest.
+ MutableArrayRef<char> ToRead = Buf->getBuffer();
+ while (!ToRead.empty()) {
+ Expected<size_t> ReadBytes =
+ sys::fs::readNativeFileSlice(FD, ToRead, Offset);
+ if (!ReadBytes)
+ return errorToErrorCode(ReadBytes.takeError());
+ if (*ReadBytes == 0) {
+ std::memset(ToRead.data(), 0, ToRead.size());
+ break;
+ }
+ ToRead = ToRead.drop_front(*ReadBytes);
+ Offset += *ReadBytes;
+ }
return std::move(Buf);
}
diff --git a/contrib/llvm-project/llvm/lib/Support/Mutex.cpp b/contrib/llvm-project/llvm/lib/Support/Mutex.cpp
deleted file mode 100644
index 69b7b8126ab1..000000000000
--- a/contrib/llvm-project/llvm/lib/Support/Mutex.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-//===- Mutex.cpp - Mutual Exclusion Lock ------------------------*- 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 llvm::sys::Mutex class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Mutex.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/ErrorHandling.h"
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
-
-#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
-// Define all methods as no-ops if threading is explicitly disabled
-namespace llvm {
-using namespace sys;
-MutexImpl::MutexImpl( bool recursive) { }
-MutexImpl::~MutexImpl() { }
-bool MutexImpl::acquire() { return true; }
-bool MutexImpl::release() { return true; }
-bool MutexImpl::tryacquire() { return true; }
-}
-#else
-
-#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK)
-
-#include <cassert>
-#include <pthread.h>
-#include <stdlib.h>
-
-namespace llvm {
-using namespace sys;
-
-// Construct a Mutex using pthread calls
-MutexImpl::MutexImpl( bool recursive)
- : data_(nullptr)
-{
- // Declare the pthread_mutex data structures
- pthread_mutex_t* mutex =
- static_cast<pthread_mutex_t*>(safe_malloc(sizeof(pthread_mutex_t)));
-
- pthread_mutexattr_t attr;
-
- // Initialize the mutex attributes
- int errorcode = pthread_mutexattr_init(&attr);
- assert(errorcode == 0); (void)errorcode;
-
- // Initialize the mutex as a recursive mutex, if requested, or normal
- // otherwise.
- int kind = ( recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL );
- errorcode = pthread_mutexattr_settype(&attr, kind);
- assert(errorcode == 0);
-
- // Initialize the mutex
- errorcode = pthread_mutex_init(mutex, &attr);
- assert(errorcode == 0);
-
- // Destroy the attributes
- errorcode = pthread_mutexattr_destroy(&attr);
- assert(errorcode == 0);
-
- // Assign the data member
- data_ = mutex;
-}
-
-// Destruct a Mutex
-MutexImpl::~MutexImpl()
-{
- pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
- assert(mutex != nullptr);
- pthread_mutex_destroy(mutex);
- free(mutex);
-}
-
-bool
-MutexImpl::acquire()
-{
- pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
- assert(mutex != nullptr);
-
- int errorcode = pthread_mutex_lock(mutex);
- return errorcode == 0;
-}
-
-bool
-MutexImpl::release()
-{
- pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
- assert(mutex != nullptr);
-
- int errorcode = pthread_mutex_unlock(mutex);
- return errorcode == 0;
-}
-
-bool
-MutexImpl::tryacquire()
-{
- pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
- assert(mutex != nullptr);
-
- int errorcode = pthread_mutex_trylock(mutex);
- return errorcode == 0;
-}
-
-}
-
-#elif defined(LLVM_ON_UNIX)
-#include "Unix/Mutex.inc"
-#elif defined( _WIN32)
-#include "Windows/Mutex.inc"
-#else
-#warning Neither LLVM_ON_UNIX nor _WIN32 was set in Support/Mutex.cpp
-#endif
-#endif
diff --git a/contrib/llvm-project/llvm/lib/Support/Options.cpp b/contrib/llvm-project/llvm/lib/Support/Options.cpp
deleted file mode 100644
index 770b7381c20e..000000000000
--- a/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/Parallel.cpp b/contrib/llvm-project/llvm/lib/Support/Parallel.cpp
index 621bccbf2a4c..523665d14b02 100644
--- a/contrib/llvm-project/llvm/lib/Support/Parallel.cpp
+++ b/contrib/llvm-project/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 {
@@ -32,62 +35,57 @@ public:
static Executor *getDefaultExecutor();
};
-#if defined(_MSC_VER)
-/// An Executor that runs tasks via ConcRT.
-class ConcRTExecutor : public Executor {
- struct Taskish {
- Taskish(std::function<void()> Task) : Task(Task) {}
-
- std::function<void()> Task;
-
- static void run(void *P) {
- Taskish *Self = static_cast<Taskish *>(P);
- Self->Task();
- concurrency::Free(Self);
- }
- };
-
-public:
- virtual void add(std::function<void()> F) {
- Concurrency::CurrentScheduler::ScheduleTask(
- Taskish::run, new (concurrency::Alloc(sizeof(Taskish))) Taskish(F));
- }
-};
-
-Executor *Executor::getDefaultExecutor() {
- static ConcRTExecutor exec;
- return &exec;
-}
-
-#else
/// An implementation of an Executor that runs closures on a thread pool
/// 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();
}
@@ -103,22 +101,41 @@ 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;
-}
-#endif
+ // 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
static std::atomic<int> TaskGroupInstances;
diff --git a/contrib/llvm-project/llvm/lib/Support/Path.cpp b/contrib/llvm-project/llvm/lib/Support/Path.cpp
index c49260125dba..3c9a08cb4077 100644
--- a/contrib/llvm-project/llvm/lib/Support/Path.cpp
+++ b/contrib/llvm-project/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) {
@@ -855,11 +878,11 @@ void make_absolute(const Twine &current_directory,
StringRef p(path.data(), path.size());
bool rootDirectory = path::has_root_directory(p);
- bool rootName =
- (real_style(Style::native) != Style::windows) || path::has_root_name(p);
+ bool rootName = path::has_root_name(p);
// Already absolute.
- if (rootName && rootDirectory)
+ if ((rootName || real_style(Style::native) != Style::windows) &&
+ rootDirectory)
return;
// All of the following conditions will need the current directory.
diff --git a/contrib/llvm-project/llvm/lib/Support/PrettyStackTrace.cpp b/contrib/llvm-project/llvm/lib/Support/PrettyStackTrace.cpp
index aec00baec0e3..bfb238cc8539 100644
--- a/contrib/llvm-project/llvm/lib/Support/PrettyStackTrace.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/PrettyStackTrace.cpp
@@ -121,31 +121,63 @@ extern "C" const char *__crashreporter_info__
asm(".desc ___crashreporter_info__, 0x10");
#endif
-/// CrashHandler - This callback is run if a fatal signal is delivered to the
-/// process, it prints the pretty stack trace.
+static void setCrashLogMessage(const char *msg) LLVM_ATTRIBUTE_UNUSED;
+static void setCrashLogMessage(const char *msg) {
+#ifdef HAVE_CRASHREPORTERCLIENT_H
+ (void)CRSetCrashLogMessage(msg);
+#elif HAVE_CRASHREPORTER_INFO
+ __crashreporter_info__ = msg;
+#endif
+ // Don't reorder subsequent operations: whatever comes after might crash and
+ // we want the system crash handling to see the message we just set.
+ std::atomic_signal_fence(std::memory_order_seq_cst);
+}
+
+#ifdef __APPLE__
+using CrashHandlerString = SmallString<2048>;
+using CrashHandlerStringStorage =
+ std::aligned_storage<sizeof(CrashHandlerString),
+ alignof(CrashHandlerString)>::type;
+static CrashHandlerStringStorage crashHandlerStringStorage;
+#endif
+
+/// This callback is run if a fatal signal is delivered to the process, it
+/// prints the pretty stack trace.
static void CrashHandler(void *) {
#ifndef __APPLE__
// On non-apple systems, just emit the crash stack trace to stderr.
PrintCurStackTrace(errs());
#else
- // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
- // put it into __crashreporter_info__.
- SmallString<2048> TmpStr;
+ // Emit the crash stack trace to a SmallString, put it where the system crash
+ // handling will find it, and also send it to stderr.
+ //
+ // The SmallString is fairly large in the hope that we don't allocate (we're
+ // handling a fatal signal, something is already pretty wrong, allocation
+ // might not work). Further, we don't use a magic static in case that's also
+ // borked. We leak any allocation that does occur because the program is about
+ // to die anyways. This is technically racy if we were handling two fatal
+ // signals, however if we're in that situation a race is the least of our
+ // worries.
+ auto &crashHandlerString =
+ *new (&crashHandlerStringStorage) CrashHandlerString;
+
+ // If we crash while trying to print the stack trace, we still want the system
+ // crash handling to have some partial information. That'll work out as long
+ // as the SmallString doesn't allocate. If it does allocate then the system
+ // crash handling will see some garbage because the inline buffer now contains
+ // a pointer.
+ setCrashLogMessage(crashHandlerString.c_str());
+
{
- raw_svector_ostream Stream(TmpStr);
+ raw_svector_ostream Stream(crashHandlerString);
PrintCurStackTrace(Stream);
}
- if (!TmpStr.empty()) {
-#ifdef HAVE_CRASHREPORTERCLIENT_H
- // Cast to void to avoid warning.
- (void)CRSetCrashLogMessage(TmpStr.c_str());
-#elif HAVE_CRASHREPORTER_INFO
- __crashreporter_info__ = strdup(TmpStr.c_str());
-#endif
- errs() << TmpStr.str();
- }
-
+ if (!crashHandlerString.empty()) {
+ setCrashLogMessage(crashHandlerString.c_str());
+ errs() << crashHandlerString.str();
+ } else
+ setCrashLogMessage("No crash information.");
#endif
}
diff --git a/contrib/llvm-project/llvm/lib/Support/Process.cpp b/contrib/llvm-project/llvm/lib/Support/Process.cpp
index 5b6471008159..509512f643d3 100644
--- a/contrib/llvm-project/llvm/lib/Support/Process.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/Process.cpp
@@ -13,8 +13,9 @@
#include "llvm/Support/Process.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/Config/config.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
@@ -88,6 +89,13 @@ static bool coreFilesPrevented = !LLVM_ENABLE_CRASH_DUMPS;
bool Process::AreCoreFilesPrevented() { return coreFilesPrevented; }
+LLVM_ATTRIBUTE_NORETURN
+void Process::Exit(int RetCode) {
+ if (CrashRecoveryContext *CRC = CrashRecoveryContext::GetCurrent())
+ CRC->HandleExit(RetCode);
+ ::exit(RetCode);
+}
+
// Include the platform-specific parts of this class.
#ifdef LLVM_ON_UNIX
#include "Unix/Process.inc"
diff --git a/contrib/llvm-project/llvm/lib/Support/RWMutex.cpp b/contrib/llvm-project/llvm/lib/Support/RWMutex.cpp
index 7ce856b716c6..5accf73e5f94 100644
--- a/contrib/llvm-project/llvm/lib/Support/RWMutex.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/RWMutex.cpp
@@ -14,24 +14,20 @@
#include "llvm/Support/RWMutex.h"
#include "llvm/Config/config.h"
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
+#if defined(LLVM_USE_RW_MUTEX_IMPL)
+using namespace llvm;
+using namespace sys;
#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
// Define all methods as no-ops if threading is explicitly disabled
-using namespace llvm;
-using namespace sys;
-
RWMutexImpl::RWMutexImpl() = default;
RWMutexImpl::~RWMutexImpl() = default;
-bool RWMutexImpl::reader_acquire() { return true; }
-bool RWMutexImpl::reader_release() { return true; }
-bool RWMutexImpl::writer_acquire() { return true; }
-bool RWMutexImpl::writer_release() { return true; }
+bool RWMutexImpl::lock_shared() { return true; }
+bool RWMutexImpl::unlock_shared() { return true; }
+bool RWMutexImpl::lock() { return true; }
+bool RWMutexImpl::unlock() { return true; }
#else
@@ -41,9 +37,6 @@ bool RWMutexImpl::writer_release() { return true; }
#include <cstdlib>
#include <pthread.h>
-using namespace llvm;
-using namespace sys;
-
// Construct a RWMutex using pthread calls
RWMutexImpl::RWMutexImpl()
{
@@ -75,7 +68,7 @@ RWMutexImpl::~RWMutexImpl()
}
bool
-RWMutexImpl::reader_acquire()
+RWMutexImpl::lock_shared()
{
pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
assert(rwlock != nullptr);
@@ -85,7 +78,7 @@ RWMutexImpl::reader_acquire()
}
bool
-RWMutexImpl::reader_release()
+RWMutexImpl::unlock_shared()
{
pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
assert(rwlock != nullptr);
@@ -95,7 +88,7 @@ RWMutexImpl::reader_release()
}
bool
-RWMutexImpl::writer_acquire()
+RWMutexImpl::lock()
{
pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
assert(rwlock != nullptr);
@@ -105,7 +98,7 @@ RWMutexImpl::writer_acquire()
}
bool
-RWMutexImpl::writer_release()
+RWMutexImpl::unlock()
{
pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
assert(rwlock != nullptr);
@@ -114,11 +107,30 @@ RWMutexImpl::writer_release()
return errorcode == 0;
}
-#elif defined(LLVM_ON_UNIX)
-#include "Unix/RWMutex.inc"
-#elif defined( _WIN32)
-#include "Windows/RWMutex.inc"
#else
-#warning Neither LLVM_ON_UNIX nor _WIN32 was set in Support/Mutex.cpp
+
+RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
+
+RWMutexImpl::~RWMutexImpl() {
+ delete static_cast<MutexImpl *>(data_);
+}
+
+bool RWMutexImpl::lock_shared() {
+ return static_cast<MutexImpl *>(data_)->acquire();
+}
+
+bool RWMutexImpl::unlock_shared() {
+ return static_cast<MutexImpl *>(data_)->release();
+}
+
+bool RWMutexImpl::lock() {
+ return static_cast<MutexImpl *>(data_)->acquire();
+}
+
+bool RWMutexImpl::unlock() {
+ return static_cast<MutexImpl *>(data_)->release();
+}
+
+#endif
#endif
#endif
diff --git a/contrib/llvm-project/llvm/lib/Support/Regex.cpp b/contrib/llvm-project/llvm/lib/Support/Regex.cpp
index 4c1b07038024..8da345d4f140 100644
--- a/contrib/llvm-project/llvm/lib/Support/Regex.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/Regex.cpp
@@ -52,14 +52,24 @@ Regex::~Regex() {
}
}
-bool Regex::isValid(std::string &Error) const {
- if (!error)
- return true;
+namespace {
+/// Utility to convert a regex error code into a human-readable string.
+void RegexErrorToString(int error, struct llvm_regex *preg,
+ std::string &Error) {
size_t len = llvm_regerror(error, preg, nullptr, 0);
Error.resize(len - 1);
llvm_regerror(error, preg, &Error[0], len);
+}
+
+} // namespace
+
+bool Regex::isValid(std::string &Error) const {
+ if (!error)
+ return true;
+
+ RegexErrorToString(error, preg, Error);
return false;
}
@@ -69,8 +79,14 @@ unsigned Regex::getNumMatches() const {
return preg->re_nsub;
}
-bool Regex::match(StringRef String, SmallVectorImpl<StringRef> *Matches){
- if (error)
+bool Regex::match(StringRef String, SmallVectorImpl<StringRef> *Matches,
+ std::string *Error) const {
+ // Reset error, if given.
+ if (Error && !Error->empty())
+ *Error = "";
+
+ // Check if the regex itself didn't successfully compile.
+ if (Error ? !isValid(*Error) : !isValid())
return false;
unsigned nmatch = Matches ? preg->re_nsub+1 : 0;
@@ -83,11 +99,13 @@ bool Regex::match(StringRef String, SmallVectorImpl<StringRef> *Matches){
int rc = llvm_regexec(preg, String.data(), nmatch, pm.data(), REG_STARTEND);
+ // Failure to match is not an error, it's just a normal return value.
+ // Any other error code is considered abnormal, and is logged in the Error.
if (rc == REG_NOMATCH)
return false;
if (rc != 0) {
- // regexec can fail due to invalid pattern or running out of memory.
- error = rc;
+ if (Error)
+ RegexErrorToString(error, preg, *Error);
return false;
}
@@ -112,14 +130,11 @@ bool Regex::match(StringRef String, SmallVectorImpl<StringRef> *Matches){
}
std::string Regex::sub(StringRef Repl, StringRef String,
- std::string *Error) {
+ std::string *Error) const {
SmallVector<StringRef, 8> Matches;
- // Reset error, if given.
- if (Error && !Error->empty()) *Error = "";
-
// Return the input if there was no match.
- if (!match(String, &Matches))
+ if (!match(String, &Matches, Error))
return String;
// Otherwise splice in the replacement string, starting with the prefix before
diff --git a/contrib/llvm-project/llvm/lib/Support/SHA1.cpp b/contrib/llvm-project/llvm/lib/Support/SHA1.cpp
index 47a5f07fbe7b..a98ca41a3354 100644
--- a/contrib/llvm-project/llvm/lib/Support/SHA1.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/Signals.cpp b/contrib/llvm-project/llvm/lib/Support/Signals.cpp
index 173a07f009d2..add6fde0eb5e 100644
--- a/contrib/llvm-project/llvm/lib/Support/Signals.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/Signposts.cpp b/contrib/llvm-project/llvm/lib/Support/Signposts.cpp
index d456f41d2fa6..aa159e1da2ae 100644
--- a/contrib/llvm-project/llvm/lib/Support/Signposts.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/Signposts.cpp
@@ -78,6 +78,8 @@ public:
#if LLVM_SUPPORT_XCODE_SIGNPOSTS
#define HAVE_ANY_SIGNPOST_IMPL 1
+#else
+#define HAVE_ANY_SIGNPOST_IMPL 0
#endif
SignpostEmitter::SignpostEmitter() {
diff --git a/contrib/llvm-project/llvm/lib/Support/SpecialCaseList.cpp b/contrib/llvm-project/llvm/lib/Support/SpecialCaseList.cpp
index 96e09f9552bb..d1ff44cefb08 100644
--- a/contrib/llvm-project/llvm/lib/Support/SpecialCaseList.cpp
+++ b/contrib/llvm-project/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>
@@ -53,7 +54,7 @@ bool SpecialCaseList::Matcher::insert(std::string Regexp,
return false;
RegExes.emplace_back(
- std::make_pair(make_unique<Regex>(std::move(CheckRE)), LineNumber));
+ std::make_pair(std::make_unique<Regex>(std::move(CheckRE)), LineNumber));
return true;
}
@@ -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;
@@ -175,7 +177,7 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB,
// Create this section if it has not been seen before.
if (SectionsMap.find(Section) == SectionsMap.end()) {
- std::unique_ptr<Matcher> M = make_unique<Matcher>();
+ std::unique_ptr<Matcher> M = std::make_unique<Matcher>();
std::string REError;
if (!M->insert(Section, LineNo, REError)) {
Error = (Twine("malformed section ") + Section + ": '" + REError).str();
diff --git a/contrib/llvm-project/llvm/lib/Support/Statistic.cpp b/contrib/llvm-project/llvm/lib/Support/Statistic.cpp
index e4f0535d21aa..25f13871e2e4 100644
--- a/contrib/llvm-project/llvm/lib/Support/Statistic.cpp
+++ b/contrib/llvm-project/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);
@@ -57,7 +57,7 @@ namespace {
/// This class is also used to look up statistic values from applications that
/// use LLVM.
class StatisticInfo {
- std::vector<Statistic*> Stats;
+ std::vector<TrackingStatistic *> Stats;
friend void llvm::PrintStatistics();
friend void llvm::PrintStatistics(raw_ostream &OS);
@@ -66,14 +66,12 @@ class StatisticInfo {
/// Sort statistics by debugtype,name,description.
void sort();
public:
- using const_iterator = std::vector<Statistic *>::const_iterator;
+ using const_iterator = std::vector<TrackingStatistic *>::const_iterator;
StatisticInfo();
~StatisticInfo();
- void addStatistic(Statistic *S) {
- Stats.push_back(S);
- }
+ void addStatistic(TrackingStatistic *S) { Stats.push_back(S); }
const_iterator begin() const { return Stats.begin(); }
const_iterator end() const { return Stats.end(); }
@@ -90,7 +88,7 @@ static ManagedStatic<sys::SmartMutex<true> > StatLock;
/// RegisterStatistic - The first time a statistic is bumped, this method is
/// called.
-void Statistic::RegisterStatistic() {
+void TrackingStatistic::RegisterStatistic() {
// If stats are enabled, inform StatInfo that this statistic should be
// printed.
// llvm_shutdown calls destructors while holding the ManagedStatic mutex.
@@ -106,7 +104,7 @@ void Statistic::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.
@@ -121,29 +119,30 @@ 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() {
- llvm::stable_sort(Stats, [](const Statistic *LHS, const Statistic *RHS) {
- if (int Cmp = std::strcmp(LHS->getDebugType(), RHS->getDebugType()))
- return Cmp < 0;
+ llvm::stable_sort(
+ Stats, [](const TrackingStatistic *LHS, const TrackingStatistic *RHS) {
+ if (int Cmp = std::strcmp(LHS->getDebugType(), RHS->getDebugType()))
+ return Cmp < 0;
- if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
- return Cmp < 0;
+ if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
+ return Cmp < 0;
- return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
- });
+ return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
+ });
}
void StatisticInfo::reset() {
@@ -207,7 +206,7 @@ void llvm::PrintStatisticsJSON(raw_ostream &OS) {
// Print all of the statistics.
OS << "{\n";
const char *delim = "";
- for (const Statistic *Stat : Stats.Stats) {
+ for (const TrackingStatistic *Stat : Stats.Stats) {
OS << delim;
assert(yaml::needsQuotes(Stat->getDebugType()) == yaml::QuotingType::None &&
"Statistic group/type name is simple.");
@@ -243,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/contrib/llvm-project/llvm/lib/Support/StringExtras.cpp b/contrib/llvm-project/llvm/lib/Support/StringExtras.cpp
index bf28b2be5657..af8dd463e125 100644
--- a/contrib/llvm-project/llvm/lib/Support/StringExtras.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/StringExtras.cpp
@@ -60,7 +60,9 @@ void llvm::SplitString(StringRef Source,
void llvm::printEscapedString(StringRef Name, raw_ostream &Out) {
for (unsigned i = 0, e = Name.size(); i != e; ++i) {
unsigned char C = Name[i];
- if (isPrint(C) && C != '\\' && C != '"')
+ if (C == '\\')
+ Out << '\\' << C;
+ else if (isPrint(C) && C != '"')
Out << C;
else
Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
diff --git a/contrib/llvm-project/llvm/lib/Support/StringRef.cpp b/contrib/llvm-project/llvm/lib/Support/StringRef.cpp
index 4bafc4ec7181..104482de4ad7 100644
--- a/contrib/llvm-project/llvm/lib/Support/StringRef.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/TargetParser.cpp b/contrib/llvm-project/llvm/lib/Support/TargetParser.cpp
index d213b9a8c6af..84ead58b98cd 100644
--- a/contrib/llvm-project/llvm/lib/Support/TargetParser.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/Threading.cpp b/contrib/llvm-project/llvm/lib/Support/Threading.cpp
index e5899a60f4db..48750cef5ec2 100644
--- a/contrib/llvm-project/llvm/lib/Support/Threading.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/TimeProfiler.cpp b/contrib/llvm-project/llvm/lib/Support/TimeProfiler.cpp
index bc2340815645..a7c85509064e 100644
--- a/contrib/llvm-project/llvm/lib/Support/TimeProfiler.cpp
+++ b/contrib/llvm-project/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>
@@ -24,48 +24,67 @@ using namespace std::chrono;
namespace llvm {
-static cl::opt<unsigned> TimeTraceGranularity(
- "time-trace-granularity",
- cl::desc(
- "Minimum time granularity (in microseconds) traced by time profiler"),
- cl::init(500));
-
TimeTraceProfiler *TimeTraceProfilerInstance = nullptr;
typedef duration<steady_clock::rep, steady_clock::period> DurationType;
+typedef time_point<steady_clock> TimePointType;
typedef std::pair<size_t, DurationType> CountAndDurationType;
typedef std::pair<std::string, CountAndDurationType>
NameAndCountAndDurationType;
struct Entry {
- time_point<steady_clock> Start;
- DurationType Duration;
- std::string Name;
- std::string Detail;
-
- Entry(time_point<steady_clock> &&S, DurationType &&D, std::string &&N,
- std::string &&Dt)
- : Start(std::move(S)), Duration(std::move(D)), Name(std::move(N)),
- Detail(std::move(Dt)){};
+ const TimePointType Start;
+ TimePointType End;
+ 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)) {}
+
+ // Calculate timings for FlameGraph. Cast time points to microsecond precision
+ // rather than casting duration. This avoid truncation issues causing inner
+ // scopes overruning outer scopes.
+ steady_clock::rep getFlameGraphStartUs(TimePointType StartTime) const {
+ return (time_point_cast<microseconds>(Start) -
+ time_point_cast<microseconds>(StartTime))
+ .count();
+ }
+
+ steady_clock::rep getFlameGraphDurUs() const {
+ return (time_point_cast<microseconds>(End) -
+ time_point_cast<microseconds>(Start))
+ .count();
+ }
};
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(), DurationType{}, std::move(Name),
+ Stack.emplace_back(steady_clock::now(), TimePointType(), std::move(Name),
Detail());
}
void end() {
assert(!Stack.empty() && "Must call begin() first");
auto &E = Stack.back();
- E.Duration = steady_clock::now() - E.Start;
+ E.End = steady_clock::now();
+
+ // Check that end times monotonically increase.
+ assert((Entries.empty() ||
+ (E.getFlameGraphStartUs(StartTime) + E.getFlameGraphDurUs() >=
+ Entries.back().getFlameGraphStartUs(StartTime) +
+ Entries.back().getFlameGraphDurUs())) &&
+ "TimeProfiler scope ended earlier than previous scope");
- // Only include sections longer than TimeTraceGranularity msec.
- if (duration_cast<microseconds>(E.Duration).count() > TimeTraceGranularity)
+ // Calculate duration at full precision for overall counts.
+ DurationType Duration = E.End - E.Start;
+
+ // Only include sections longer or equal to TimeTraceGranularity msec.
+ if (duration_cast<microseconds>(Duration).count() >= TimeTraceGranularity)
Entries.emplace_back(E);
// Track total time taken by each "name", but only the topmost levels of
@@ -78,7 +97,7 @@ struct TimeTraceProfiler {
}) == Stack.rend()) {
auto &CountAndTotal = CountAndTotalPerName[E.Name];
CountAndTotal.first++;
- CountAndTotal.second += E.Duration;
+ CountAndTotal.second += Duration;
}
Stack.pop_back();
@@ -94,8 +113,8 @@ struct TimeTraceProfiler {
// Emit all events for the main flame graph.
for (const auto &E : Entries) {
- auto StartUs = duration_cast<microseconds>(E.Start - StartTime).count();
- auto DurUs = duration_cast<microseconds>(E.Duration).count();
+ auto StartUs = E.getFlameGraphStartUs(StartTime);
+ auto DurUs = E.getFlameGraphDurUs();
J.object([&]{
J.attribute("pid", 1);
@@ -104,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); });
+ }
});
}
@@ -149,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();
@@ -160,13 +181,19 @@ struct TimeTraceProfiler {
SmallVector<Entry, 16> Stack;
SmallVector<Entry, 128> Entries;
StringMap<CountAndDurationType> CountAndTotalPerName;
- time_point<steady_clock> StartTime;
+ const TimePointType StartTime;
+ const std::string ProcName;
+
+ // Minimum time granularity (in microseconds)
+ const unsigned TimeTraceGranularity;
};
-void timeTraceProfilerInitialize() {
+void timeTraceProfilerInitialize(unsigned TimeTraceGranularity,
+ StringRef ProcName) {
assert(TimeTraceProfilerInstance == nullptr &&
"Profiler should not be initialized");
- TimeTraceProfilerInstance = new TimeTraceProfiler();
+ TimeTraceProfilerInstance = new TimeTraceProfiler(
+ TimeTraceGranularity, llvm::sys::path::filename(ProcName));
}
void timeTraceProfilerCleanup() {
diff --git a/contrib/llvm-project/llvm/lib/Support/Timer.cpp b/contrib/llvm-project/llvm/lib/Support/Timer.cpp
index 2a7ff1eaaf63..613d2eaae6d3 100644
--- a/contrib/llvm-project/llvm/lib/Support/Timer.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/Timer.cpp
@@ -58,23 +58,23 @@ namespace {
std::unique_ptr<raw_fd_ostream> llvm::CreateInfoOutputFile() {
const std::string &OutputFilename = getLibSupportInfoOutputFilename();
if (OutputFilename.empty())
- return llvm::make_unique<raw_fd_ostream>(2, false); // stderr.
+ return std::make_unique<raw_fd_ostream>(2, false); // stderr.
if (OutputFilename == "-")
- return llvm::make_unique<raw_fd_ostream>(1, false); // stdout.
+ return std::make_unique<raw_fd_ostream>(1, false); // stdout.
// Append mode is used because the info output file is opened and closed
// each time -stats or -time-passes wants to print output to it. To
// compensate for this, the test-suite Makefiles have code to delete the
// info output file before running commands which write to it.
std::error_code EC;
- auto Result = llvm::make_unique<raw_fd_ostream>(
- OutputFilename, EC, sys::fs::F_Append | sys::fs::F_Text);
+ auto Result = std::make_unique<raw_fd_ostream>(
+ OutputFilename, EC, sys::fs::OF_Append | sys::fs::OF_Text);
if (!EC)
return Result;
errs() << "Error opening info-output-file '"
<< OutputFilename << " for appending!\n";
- return llvm::make_unique<raw_fd_ostream>(2, false); // stderr.
+ return std::make_unique<raw_fd_ostream>(2, false); // stderr.
}
namespace {
@@ -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/contrib/llvm-project/llvm/lib/Support/Triple.cpp b/contrib/llvm-project/llvm/lib/Support/Triple.cpp
index 18b013e1df3f..2c480c1094a5 100644
--- a/contrib/llvm-project/llvm/lib/Support/Triple.cpp
+++ b/contrib/llvm-project/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);
}
@@ -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)
@@ -640,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");
@@ -665,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:
@@ -697,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())
@@ -1238,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");
@@ -1310,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;
}
@@ -1379,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;
}
@@ -1453,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:
@@ -1463,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.
@@ -1473,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.");
}
@@ -1505,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.");
}
@@ -1541,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;
@@ -1610,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;
@@ -1633,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/contrib/llvm-project/llvm/lib/Support/Unix/Memory.inc b/contrib/llvm-project/llvm/lib/Support/Unix/Memory.inc
index a0927da50e48..79b1759359e1 100644
--- a/contrib/llvm-project/llvm/lib/Support/Unix/Memory.inc
+++ b/contrib/llvm-project/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 {
@@ -176,7 +172,7 @@ Memory::releaseMappedMemory(MemoryBlock &M) {
std::error_code
Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) {
- static const size_t PageSize = Process::getPageSizeEstimate();
+ static const Align PageSize = Align(Process::getPageSizeEstimate());
if (M.Address == nullptr || M.AllocatedSize == 0)
return std::error_code();
@@ -184,8 +180,8 @@ Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) {
return std::error_code(EINVAL, std::generic_category());
int Protect = getPosixProtectionFlags(Flags);
- uintptr_t Start = alignAddr((uint8_t *)M.Address - PageSize + 1, PageSize);
- uintptr_t End = alignAddr((uint8_t *)M.Address + M.AllocatedSize, PageSize);
+ uintptr_t Start = alignAddr((const uint8_t *)M.Address - PageSize.value() + 1, PageSize);
+ uintptr_t End = alignAddr((const uint8_t *)M.Address + M.AllocatedSize, PageSize);
bool InvalidateCache = (Flags & MF_EXEC);
diff --git a/contrib/llvm-project/llvm/lib/Support/Unix/Mutex.inc b/contrib/llvm-project/llvm/lib/Support/Unix/Mutex.inc
deleted file mode 100644
index 2c982b38d6ff..000000000000
--- a/contrib/llvm-project/llvm/lib/Support/Unix/Mutex.inc
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- llvm/Support/Unix/Mutex.inc - Unix Mutex Implementation ---*- 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 Unix specific (non-pthread) Mutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-namespace llvm
-{
-using namespace sys;
-
-MutexImpl::MutexImpl( bool recursive)
-{
-}
-
-MutexImpl::~MutexImpl()
-{
-}
-
-bool
-MutexImpl::release()
-{
- return true;
-}
-
-bool
-MutexImpl::tryacquire( void )
-{
- return true;
-}
-
-}
diff --git a/contrib/llvm-project/llvm/lib/Support/Unix/Path.inc b/contrib/llvm-project/llvm/lib/Support/Unix/Path.inc
index a64ef8a6da3a..2a03dc682bce 100644
--- a/contrib/llvm-project/llvm/lib/Support/Unix/Path.inc
+++ b/contrib/llvm-project/llvm/lib/Support/Unix/Path.inc
@@ -201,8 +201,8 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) {
if (elf_aux_info(AT_EXECPATH, exe_path, sizeof(exe_path)) == 0)
return exe_path;
#else
- // elf_aux_info(AT_EXECPATH, ... is not available on older FreeBSD. Fall
- // back to finding the ELF auxiliary vectors after the processes's
+ // 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)
@@ -221,12 +221,12 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) {
// 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) || \
+#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__minix) || \
defined(__DragonFly__) || defined(__FreeBSD_kernel__) || defined(_AIX)
- StringRef curproc("/proc/curproc/file");
+ const char *curproc = "/proc/curproc/file";
char exe_path[PATH_MAX];
if (sys::fs::exists(curproc)) {
- ssize_t len = readlink(curproc.str().c_str(), exe_path, sizeof(exe_path));
+ ssize_t len = readlink(curproc, exe_path, sizeof(exe_path));
if (len > 0) {
// Null terminate the string for realpath. readlink never null
// terminates its output.
@@ -238,12 +238,12 @@ 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];
- StringRef aPath("/proc/self/exe");
+ const char *aPath = "/proc/self/exe";
if (sys::fs::exists(aPath)) {
// /proc is not always mounted under Linux (chroot for example).
- ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path));
+ ssize_t len = readlink(aPath, exe_path, sizeof(exe_path));
if (len < 0)
return "";
@@ -478,7 +478,7 @@ static bool is_local_impl(struct STATVFS &Vfs) {
std::unique_ptr<char[]> Buf;
int Tries = 3;
while (Tries--) {
- Buf = llvm::make_unique<char[]>(BufSize);
+ Buf = std::make_unique<char[]>(BufSize);
Ret = mntctl(MCTL_QUERY, BufSize, Buf.get());
if (Ret != 0)
break;
@@ -868,7 +868,10 @@ std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) {
static file_type direntType(dirent* Entry) {
// Most platforms provide the file type in the dirent: Linux/BSD/Mac.
// The DTTOIF macro lets us reuse our status -> type conversion.
-#if defined(_DIRENT_HAVE_D_TYPE) && defined(DTTOIF)
+ // Note that while glibc provides a macro to see if this is supported,
+ // _DIRENT_HAVE_D_TYPE, it's not defined on BSD/Mac, so we test for the
+ // d_type-to-mode_t conversion macro instead.
+#if defined(DTTOIF)
return typeForMode(DTTOIF(Entry->d_type));
#else
// Other platforms such as Solaris require a stat() to get the type.
@@ -919,9 +922,9 @@ static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags,
else if (Access == (FA_Read | FA_Write))
Result |= O_RDWR;
- // This is for compatibility with old code that assumed F_Append implied
+ // This is for compatibility with old code that assumed OF_Append implied
// would open an existing file. See Windows/Path.inc for a longer comment.
- if (Flags & F_Append)
+ if (Flags & OF_Append)
Disp = CD_OpenAlways;
if (Disp == CD_CreateNew) {
@@ -936,7 +939,7 @@ static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags,
// Nothing special, just don't add O_CREAT and we get these semantics.
}
- if (Flags & F_Append)
+ if (Flags & OF_Append)
Result |= O_APPEND;
#ifdef O_CLOEXEC
@@ -1031,44 +1034,28 @@ file_t getStdinHandle() { return 0; }
file_t getStdoutHandle() { return 1; }
file_t getStderrHandle() { return 2; }
-std::error_code readNativeFile(file_t FD, MutableArrayRef<char> Buf,
- size_t *BytesRead) {
- *BytesRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Buf.size());
- if (ssize_t(*BytesRead) == -1)
- return std::error_code(errno, std::generic_category());
- return std::error_code();
+Expected<size_t> readNativeFile(file_t FD, MutableArrayRef<char> Buf) {
+ ssize_t NumRead =
+ sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Buf.size());
+ if (ssize_t(NumRead) == -1)
+ return errorCodeToError(std::error_code(errno, std::generic_category()));
+ return NumRead;
}
-std::error_code readNativeFileSlice(file_t FD, MutableArrayRef<char> Buf,
- size_t Offset) {
- char *BufPtr = Buf.data();
- size_t BytesLeft = Buf.size();
-
-#ifndef HAVE_PREAD
- // If we don't have pread, seek to Offset.
- if (lseek(FD, Offset, SEEK_SET) == -1)
- return std::error_code(errno, std::generic_category());
-#endif
-
- while (BytesLeft) {
+Expected<size_t> readNativeFileSlice(file_t FD, MutableArrayRef<char> Buf,
+ uint64_t Offset) {
#ifdef HAVE_PREAD
- ssize_t NumRead = sys::RetryAfterSignal(-1, ::pread, FD, BufPtr, BytesLeft,
- Buf.size() - BytesLeft + Offset);
+ ssize_t NumRead =
+ sys::RetryAfterSignal(-1, ::pread, FD, Buf.data(), Buf.size(), Offset);
#else
- ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, BufPtr, BytesLeft);
+ if (lseek(FD, Offset, SEEK_SET) == -1)
+ return errorCodeToError(std::error_code(errno, std::generic_category()));
+ ssize_t NumRead =
+ sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Buf.size());
#endif
- if (NumRead == -1) {
- // Error while reading.
- return std::error_code(errno, std::generic_category());
- }
- if (NumRead == 0) {
- memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer.
- break;
- }
- BytesLeft -= NumRead;
- BufPtr += NumRead;
- }
- return std::error_code();
+ if (NumRead == -1)
+ return errorCodeToError(std::error_code(errno, std::generic_category()));
+ return NumRead;
}
std::error_code closeFile(file_t &F) {
diff --git a/contrib/llvm-project/llvm/lib/Support/Unix/Process.inc b/contrib/llvm-project/llvm/lib/Support/Unix/Process.inc
index 4115ee396582..dfe81d7e2833 100644
--- a/contrib/llvm-project/llvm/lib/Support/Unix/Process.inc
+++ b/contrib/llvm-project/llvm/lib/Support/Unix/Process.inc
@@ -15,8 +15,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/config.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/MutexGuard.h"
+#include <mutex>
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
@@ -327,13 +326,13 @@ extern "C" int tigetnum(char *capname);
#endif
#ifdef HAVE_TERMINFO
-static ManagedStatic<sys::Mutex> TermColorMutex;
+static ManagedStatic<std::mutex> TermColorMutex;
#endif
static bool terminalHasColors(int fd) {
#ifdef HAVE_TERMINFO
// First, acquire a global lock because these C routines are thread hostile.
- MutexGuard G(*TermColorMutex);
+ std::lock_guard<std::mutex> G(*TermColorMutex);
int errret = 0;
if (setupterm(nullptr, fd, &errret) != 0)
diff --git a/contrib/llvm-project/llvm/lib/Support/Unix/Program.inc b/contrib/llvm-project/llvm/lib/Support/Unix/Program.inc
index c4123a64046f..520685a0e987 100644
--- a/contrib/llvm-project/llvm/lib/Support/Unix/Program.inc
+++ b/contrib/llvm-project/llvm/lib/Support/Unix/Program.inc
@@ -136,7 +136,7 @@ static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg,
if (int Err = posix_spawn_file_actions_addopen(
FileActions, FD, File,
FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666))
- return MakeErrMsg(ErrMsg, "Cannot dup2", Err);
+ return MakeErrMsg(ErrMsg, "Cannot posix_spawn_file_actions_addopen", Err);
return false;
}
#endif
@@ -444,7 +444,7 @@ std::error_code
llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
WindowsEncodingMethod Encoding /*unused*/) {
std::error_code EC;
- llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text);
+ llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::OF_Text);
if (EC)
return EC;
diff --git a/contrib/llvm-project/llvm/lib/Support/Unix/RWMutex.inc b/contrib/llvm-project/llvm/lib/Support/Unix/RWMutex.inc
deleted file mode 100644
index 8b47dfa0f85c..000000000000
--- a/contrib/llvm-project/llvm/lib/Support/Unix/RWMutex.inc
+++ /dev/null
@@ -1,50 +0,0 @@
-//= llvm/Support/Unix/RWMutex.inc - Unix Reader/Writer Mutual Exclusion Lock =//
-//
-// 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 Unix specific (non-pthread) RWMutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Mutex.h"
-
-namespace llvm {
-
-using namespace sys;
-
-// This naive implementation treats readers the same as writers. This
-// will therefore deadlock if a thread tries to acquire a read lock
-// multiple times.
-
-RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
-
-RWMutexImpl::~RWMutexImpl() {
- delete static_cast<MutexImpl *>(data_);
-}
-
-bool RWMutexImpl::reader_acquire() {
- return static_cast<MutexImpl *>(data_)->acquire();
-}
-
-bool RWMutexImpl::reader_release() {
- return static_cast<MutexImpl *>(data_)->release();
-}
-
-bool RWMutexImpl::writer_acquire() {
- return static_cast<MutexImpl *>(data_)->acquire();
-}
-
-bool RWMutexImpl::writer_release() {
- return static_cast<MutexImpl *>(data_)->release();
-}
-
-}
diff --git a/contrib/llvm-project/llvm/lib/Support/Unix/Signals.inc b/contrib/llvm-project/llvm/lib/Support/Unix/Signals.inc
index 634c16aa36c7..f68374d29f02 100644
--- a/contrib/llvm-project/llvm/lib/Support/Unix/Signals.inc
+++ b/contrib/llvm-project/llvm/lib/Support/Unix/Signals.inc
@@ -43,7 +43,6 @@
#include "llvm/Support/Mutex.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/SaveAndRestore.h"
-#include "llvm/Support/UniqueLock.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <string>
@@ -89,6 +88,9 @@ static std::atomic<SignalHandlerFunctionType> InterruptFunction =
ATOMIC_VAR_INIT(nullptr);
static std::atomic<SignalHandlerFunctionType> InfoSignalFunction =
ATOMIC_VAR_INIT(nullptr);
+/// 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.
@@ -207,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
@@ -238,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);
@@ -323,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);
}
@@ -341,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
@@ -357,15 +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)
- exit(EX_IOERR);
-
raise(Sig); // Execute the default handler.
return;
}
@@ -404,6 +425,16 @@ void llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
RegisterHandlers();
}
+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/contrib/llvm-project/llvm/lib/Support/Unix/Threading.inc b/contrib/llvm-project/llvm/lib/Support/Unix/Threading.inc
index ed9a96563055..afb887fc1096 100644
--- a/contrib/llvm-project/llvm/lib/Support/Unix/Threading.inc
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/Unix/Unix.h b/contrib/llvm-project/llvm/lib/Support/Unix/Unix.h
index 86309b0567f5..1fc9a414f749 100644
--- a/contrib/llvm-project/llvm/lib/Support/Unix/Unix.h
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp b/contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp
index 5d3480e97148..edd4234fe501 100644
--- a/contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp
@@ -176,9 +176,9 @@ class RealFile : public File {
Status S;
std::string RealName;
- RealFile(file_t FD, StringRef NewName, StringRef NewRealPathName)
- : FD(FD), S(NewName, {}, {}, {}, {}, {},
- llvm::sys::fs::file_type::status_error, {}),
+ RealFile(file_t RawFD, StringRef NewName, StringRef NewRealPathName)
+ : FD(RawFD), S(NewName, {}, {}, {}, {}, {},
+ llvm::sys::fs::file_type::status_error, {}),
RealName(NewRealPathName.str()) {
assert(FD != kInvalidFile && "Invalid or inactive file descriptor");
}
@@ -349,7 +349,7 @@ IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
}
std::unique_ptr<FileSystem> vfs::createPhysicalFileSystem() {
- return llvm::make_unique<RealFileSystem>(false);
+ return std::make_unique<RealFileSystem>(false);
}
namespace {
@@ -754,7 +754,7 @@ bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
ResolvedUser, ResolvedGroup, 0, sys::fs::file_type::directory_file,
NewDirectoryPerms);
Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
- Name, llvm::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
+ Name, std::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
continue;
}
@@ -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:
@@ -989,6 +989,16 @@ std::error_code InMemoryFileSystem::isLocal(const Twine &Path, bool &Result) {
// RedirectingFileSystem implementation
//===-----------------------------------------------------------------------===/
+RedirectingFileSystem::RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> FS)
+ : ExternalFS(std::move(FS)) {
+ if (ExternalFS)
+ if (auto ExternalWorkingDirectory =
+ ExternalFS->getCurrentWorkingDirectory()) {
+ WorkingDirectory = *ExternalWorkingDirectory;
+ ExternalFSValidWD = true;
+ }
+}
+
// FIXME: reuse implementation common with OverlayFSDirIterImpl as these
// iterators are conceptually similar.
class llvm::vfs::VFSFromYamlDirIterImpl
@@ -1035,12 +1045,27 @@ public:
llvm::ErrorOr<std::string>
RedirectingFileSystem::getCurrentWorkingDirectory() const {
- return ExternalFS->getCurrentWorkingDirectory();
+ return WorkingDirectory;
}
std::error_code
RedirectingFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
- return ExternalFS->setCurrentWorkingDirectory(Path);
+ // Don't change the working directory if the path doesn't exist.
+ if (!exists(Path))
+ return errc::no_such_file_or_directory;
+
+ // Always change the external FS but ignore its result.
+ if (ExternalFS) {
+ auto EC = ExternalFS->setCurrentWorkingDirectory(Path);
+ ExternalFSValidWD = !static_cast<bool>(EC);
+ }
+
+ SmallString<128> AbsolutePath;
+ Path.toVector(AbsolutePath);
+ if (std::error_code EC = makeAbsolute(AbsolutePath))
+ return EC;
+ WorkingDirectory = AbsolutePath.str();
+ return {};
}
std::error_code RedirectingFileSystem::isLocal(const Twine &Path,
@@ -1048,12 +1073,25 @@ 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);
if (!E) {
EC = E.getError();
- if (IsFallthrough && EC == errc::no_such_file_or_directory)
+ if (shouldUseExternalFS() && EC == errc::no_such_file_or_directory)
return ExternalFS->dir_begin(Dir, EC);
return {};
}
@@ -1071,7 +1109,7 @@ directory_iterator RedirectingFileSystem::dir_begin(const Twine &Dir,
auto *D = cast<RedirectingFileSystem::RedirectingDirectoryEntry>(*E);
return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(
Dir, D->contents_begin(), D->contents_end(),
- /*IterateExternalFS=*/IsFallthrough, *ExternalFS, EC));
+ /*IterateExternalFS=*/shouldUseExternalFS(), *ExternalFS, EC));
}
void RedirectingFileSystem::setExternalContentsPrefixDir(StringRef PrefixDir) {
@@ -1082,20 +1120,19 @@ StringRef RedirectingFileSystem::getExternalContentsPrefixDir() const {
return ExternalContentsPrefixDir;
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void RedirectingFileSystem::dump() const {
+void RedirectingFileSystem::dump(raw_ostream &OS) const {
for (const auto &Root : Roots)
- dumpEntry(Root.get());
+ dumpEntry(OS, Root.get());
}
-LLVM_DUMP_METHOD void
-RedirectingFileSystem::dumpEntry(RedirectingFileSystem::Entry *E,
- int NumSpaces) const {
+void RedirectingFileSystem::dumpEntry(raw_ostream &OS,
+ RedirectingFileSystem::Entry *E,
+ int NumSpaces) const {
StringRef Name = E->getName();
for (int i = 0, e = NumSpaces; i < e; ++i)
- dbgs() << " ";
- dbgs() << "'" << Name.str().c_str() << "'"
- << "\n";
+ OS << " ";
+ OS << "'" << Name.str().c_str() << "'"
+ << "\n";
if (E->getKind() == RedirectingFileSystem::EK_Directory) {
auto *DE = dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(E);
@@ -1103,9 +1140,12 @@ RedirectingFileSystem::dumpEntry(RedirectingFileSystem::Entry *E,
for (std::unique_ptr<Entry> &SubEntry :
llvm::make_range(DE->contents_begin(), DE->contents_end()))
- dumpEntry(SubEntry.get(), NumSpaces + 2);
+ dumpEntry(OS, SubEntry.get(), NumSpaces + 2);
}
}
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void RedirectingFileSystem::dump() const { dump(dbgs()); }
#endif
/// A helper class to hold the common YAML parsing state.
@@ -1209,7 +1249,7 @@ class llvm::vfs::RedirectingFileSystemParser {
// ... or create a new one
std::unique_ptr<RedirectingFileSystem::Entry> E =
- llvm::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
+ std::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
Name, Status("", getNextVirtualUniqueID(),
std::chrono::system_clock::now(), 0, 0, 0,
file_type::directory_file, sys::fs::all_all));
@@ -1221,7 +1261,7 @@ class llvm::vfs::RedirectingFileSystemParser {
}
auto *DE =
- dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(ParentEntry);
+ cast<RedirectingFileSystem::RedirectingDirectoryEntry>(ParentEntry);
DE->addContent(std::move(E));
return DE->getLastContent();
}
@@ -1232,9 +1272,7 @@ class llvm::vfs::RedirectingFileSystemParser {
StringRef Name = SrcE->getName();
switch (SrcE->getKind()) {
case RedirectingFileSystem::EK_Directory: {
- auto *DE =
- dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(SrcE);
- assert(DE && "Must be a directory");
+ auto *DE = cast<RedirectingFileSystem::RedirectingDirectoryEntry>(SrcE);
// Empty directories could be present in the YAML as a way to
// describe a file for a current directory after some of its subdir
// is parsed. This only leads to redundant walks, ignore it.
@@ -1246,13 +1284,12 @@ class llvm::vfs::RedirectingFileSystemParser {
break;
}
case RedirectingFileSystem::EK_File: {
- auto *FE = dyn_cast<RedirectingFileSystem::RedirectingFileEntry>(SrcE);
- assert(FE && "Must be a file");
assert(NewParentE && "Parent entry must exist");
- auto *DE = dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(
- NewParentE);
+ auto *FE = cast<RedirectingFileSystem::RedirectingFileEntry>(SrcE);
+ auto *DE =
+ cast<RedirectingFileSystem::RedirectingDirectoryEntry>(NewParentE);
DE->addContent(
- llvm::make_unique<RedirectingFileSystem::RedirectingFileEntry>(
+ std::make_unique<RedirectingFileSystem::RedirectingFileEntry>(
Name, FE->getExternalContentsPath(), FE->getUseName()));
break;
}
@@ -1404,31 +1441,41 @@ 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) {
case RedirectingFileSystem::EK_File:
- Result = llvm::make_unique<RedirectingFileSystem::RedirectingFileEntry>(
+ Result = std::make_unique<RedirectingFileSystem::RedirectingFileEntry>(
LastComponent, std::move(ExternalContentsPath), UseExternalName);
break;
case RedirectingFileSystem::EK_Directory:
Result =
- llvm::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
+ std::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
LastComponent, std::move(EntryArrayContents),
Status("", getNextVirtualUniqueID(),
std::chrono::system_clock::now(), 0, 0, 0,
@@ -1436,18 +1483,18 @@ 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;
Entries.push_back(std::move(Result));
Result =
- llvm::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
+ std::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
*I, std::move(Entries),
Status("", getNextVirtualUniqueID(),
std::chrono::system_clock::now(), 0, 0, 0,
@@ -1573,7 +1620,7 @@ RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
RedirectingFileSystemParser P(Stream);
std::unique_ptr<RedirectingFileSystem> FS(
- new RedirectingFileSystem(std::move(ExternalFS)));
+ new RedirectingFileSystem(ExternalFS));
if (!YAMLFilePath.empty()) {
// Use the YAML path from -ivfsoverlay to compute the dir to be prefixed
@@ -1647,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;
@@ -1671,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);
}
@@ -1702,7 +1748,7 @@ ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path,
ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path) {
ErrorOr<RedirectingFileSystem::Entry *> Result = lookupPath(Path);
if (!Result) {
- if (IsFallthrough &&
+ if (shouldUseExternalFS() &&
Result.getError() == llvm::errc::no_such_file_or_directory) {
return ExternalFS->status(Path);
}
@@ -1740,7 +1786,7 @@ ErrorOr<std::unique_ptr<File>>
RedirectingFileSystem::openFileForRead(const Twine &Path) {
ErrorOr<RedirectingFileSystem::Entry *> E = lookupPath(Path);
if (!E) {
- if (IsFallthrough &&
+ if (shouldUseExternalFS() &&
E.getError() == llvm::errc::no_such_file_or_directory) {
return ExternalFS->openFileForRead(Path);
}
@@ -1763,7 +1809,7 @@ RedirectingFileSystem::openFileForRead(const Twine &Path) {
Status S = getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
*ExternalStatus);
return std::unique_ptr<File>(
- llvm::make_unique<FileWithFixedStatus>(std::move(*Result), S));
+ std::make_unique<FileWithFixedStatus>(std::move(*Result), S));
}
std::error_code
@@ -1771,7 +1817,7 @@ RedirectingFileSystem::getRealPath(const Twine &Path,
SmallVectorImpl<char> &Output) const {
ErrorOr<RedirectingFileSystem::Entry *> Result = lookupPath(Path);
if (!Result) {
- if (IsFallthrough &&
+ if (shouldUseExternalFS() &&
Result.getError() == llvm::errc::no_such_file_or_directory) {
return ExternalFS->getRealPath(Path, Output);
}
@@ -1784,8 +1830,8 @@ RedirectingFileSystem::getRealPath(const Twine &Path,
}
// Even if there is a directory entry, fall back to ExternalFS if allowed,
// because directories don't have a single external contents path.
- return IsFallthrough ? ExternalFS->getRealPath(Path, Output)
- : llvm::errc::invalid_argument;
+ return shouldUseExternalFS() ? ExternalFS->getRealPath(Path, Output)
+ : llvm::errc::invalid_argument;
}
IntrusiveRefCntPtr<FileSystem>
@@ -2049,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/contrib/llvm-project/llvm/lib/Support/Windows/Memory.inc b/contrib/llvm-project/llvm/lib/Support/Windows/Memory.inc
index a67f9c7d0f35..c5566f9910a5 100644
--- a/contrib/llvm-project/llvm/lib/Support/Windows/Memory.inc
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/Windows/Mutex.inc b/contrib/llvm-project/llvm/lib/Support/Windows/Mutex.inc
deleted file mode 100644
index b55b14febf2c..000000000000
--- a/contrib/llvm-project/llvm/lib/Support/Windows/Mutex.inc
+++ /dev/null
@@ -1,56 +0,0 @@
-//===- llvm/Support/Win32/Mutex.inc - Win32 Mutex Implementation -*- 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 Win32 specific (non-pthread) Mutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic Win32 code that
-//=== is guaranteed to work on *all* Win32 variants.
-//===----------------------------------------------------------------------===//
-
-#include "WindowsSupport.h"
-#include "llvm/Support/Mutex.h"
-
-namespace llvm {
-
-sys::MutexImpl::MutexImpl(bool /*recursive*/)
-{
- data_ = new CRITICAL_SECTION;
- InitializeCriticalSection((LPCRITICAL_SECTION)data_);
-}
-
-sys::MutexImpl::~MutexImpl()
-{
- DeleteCriticalSection((LPCRITICAL_SECTION)data_);
- delete (LPCRITICAL_SECTION)data_;
- data_ = 0;
-}
-
-bool
-sys::MutexImpl::acquire()
-{
- EnterCriticalSection((LPCRITICAL_SECTION)data_);
- return true;
-}
-
-bool
-sys::MutexImpl::release()
-{
- LeaveCriticalSection((LPCRITICAL_SECTION)data_);
- return true;
-}
-
-bool
-sys::MutexImpl::tryacquire()
-{
- return TryEnterCriticalSection((LPCRITICAL_SECTION)data_);
-}
-
-}
diff --git a/contrib/llvm-project/llvm/lib/Support/Windows/Path.inc b/contrib/llvm-project/llvm/lib/Support/Windows/Path.inc
index 5704930aeecc..c3b13abef5de 100644
--- a/contrib/llvm-project/llvm/lib/Support/Windows/Path.inc
+++ b/contrib/llvm-project/llvm/lib/Support/Windows/Path.inc
@@ -371,13 +371,19 @@ static std::error_code realPathFromHandle(HANDLE H,
if (std::error_code EC = realPathFromHandle(H, Buffer))
return EC;
- const wchar_t *Data = Buffer.data();
+ // Strip the \\?\ prefix. We don't want it ending up in output, and such
+ // paths don't get canonicalized by file APIs.
+ wchar_t *Data = Buffer.data();
DWORD CountChars = Buffer.size();
- if (CountChars >= 4) {
- if (0 == ::memcmp(Data, L"\\\\?\\", 8)) {
- CountChars -= 4;
- Data += 4;
- }
+ if (CountChars >= 8 && ::memcmp(Data, L"\\\\?\\UNC\\", 16) == 0) {
+ // Convert \\?\UNC\foo\bar to \\foo\bar
+ CountChars -= 6;
+ Data += 6;
+ Data[0] = '\\';
+ } else if (CountChars >= 4 && ::memcmp(Data, L"\\\\?\\", 8) == 0) {
+ // Convert \\?\c:\foo to c:\foo
+ CountChars -= 4;
+ Data += 4;
}
// Convert the result from UTF-16 to UTF-8.
@@ -1217,57 +1223,34 @@ file_t getStdinHandle() { return ::GetStdHandle(STD_INPUT_HANDLE); }
file_t getStdoutHandle() { return ::GetStdHandle(STD_OUTPUT_HANDLE); }
file_t getStderrHandle() { return ::GetStdHandle(STD_ERROR_HANDLE); }
-std::error_code readNativeFileImpl(file_t FileHandle, char *BufPtr, size_t BytesToRead,
- size_t *BytesRead, OVERLAPPED *Overlap) {
+Expected<size_t> readNativeFileImpl(file_t FileHandle,
+ MutableArrayRef<char> Buf,
+ OVERLAPPED *Overlap) {
// ReadFile can only read 2GB at a time. The caller should check the number of
// bytes and read in a loop until termination.
- DWORD BytesToRead32 =
- std::min(size_t(std::numeric_limits<DWORD>::max()), BytesToRead);
- DWORD BytesRead32 = 0;
- bool Success =
- ::ReadFile(FileHandle, BufPtr, BytesToRead32, &BytesRead32, Overlap);
- *BytesRead = BytesRead32;
- if (!Success) {
- DWORD Err = ::GetLastError();
- // Pipe EOF is not an error.
- if (Err == ERROR_BROKEN_PIPE)
- return std::error_code();
- return mapWindowsError(Err);
- }
- return std::error_code();
-}
-
-std::error_code readNativeFile(file_t FileHandle, MutableArrayRef<char> Buf,
- size_t *BytesRead) {
- return readNativeFileImpl(FileHandle, Buf.data(), Buf.size(), BytesRead,
- /*Overlap=*/nullptr);
-}
-
-std::error_code readNativeFileSlice(file_t FileHandle,
- MutableArrayRef<char> Buf, size_t Offset) {
- char *BufPtr = Buf.data();
- size_t BytesLeft = Buf.size();
-
- while (BytesLeft) {
- uint64_t CurOff = Buf.size() - BytesLeft + Offset;
- OVERLAPPED Overlapped = {};
- Overlapped.Offset = uint32_t(CurOff);
- Overlapped.OffsetHigh = uint32_t(uint64_t(CurOff) >> 32);
-
- size_t BytesRead = 0;
- if (auto EC = readNativeFileImpl(FileHandle, BufPtr, BytesLeft, &BytesRead,
- &Overlapped))
- return EC;
-
- // Once we reach EOF, zero the remaining bytes in the buffer.
- if (BytesRead == 0) {
- memset(BufPtr, 0, BytesLeft);
- break;
- }
- BytesLeft -= BytesRead;
- BufPtr += BytesRead;
- }
- return std::error_code();
+ DWORD BytesToRead =
+ std::min(size_t(std::numeric_limits<DWORD>::max()), Buf.size());
+ DWORD BytesRead = 0;
+ if (::ReadFile(FileHandle, Buf.data(), BytesToRead, &BytesRead, Overlap))
+ return BytesRead;
+ DWORD Err = ::GetLastError();
+ // EOF is not an error.
+ if (Err == ERROR_BROKEN_PIPE || Err == ERROR_HANDLE_EOF)
+ return BytesRead;
+ return errorCodeToError(mapWindowsError(Err));
+}
+
+Expected<size_t> readNativeFile(file_t FileHandle, MutableArrayRef<char> Buf) {
+ return readNativeFileImpl(FileHandle, Buf, /*Overlap=*/nullptr);
+}
+
+Expected<size_t> readNativeFileSlice(file_t FileHandle,
+ MutableArrayRef<char> Buf,
+ uint64_t Offset) {
+ OVERLAPPED Overlapped = {};
+ Overlapped.Offset = uint32_t(Offset);
+ Overlapped.OffsetHigh = uint32_t(Offset >> 32);
+ return readNativeFileImpl(FileHandle, Buf, &Overlapped);
}
std::error_code closeFile(file_t &F) {
diff --git a/contrib/llvm-project/llvm/lib/Support/Windows/Process.inc b/contrib/llvm-project/llvm/lib/Support/Windows/Process.inc
index 4b91f9f7fc66..3526e3dee6fa 100644
--- a/contrib/llvm-project/llvm/lib/Support/Windows/Process.inc
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/Windows/Program.inc b/contrib/llvm-project/llvm/lib/Support/Windows/Program.inc
index 0f54e59ee55b..a1482bf17c60 100644
--- a/contrib/llvm-project/llvm/lib/Support/Windows/Program.inc
+++ b/contrib/llvm-project/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());
@@ -470,7 +470,7 @@ std::error_code
llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
WindowsEncodingMethod Encoding) {
std::error_code EC;
- llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::F_Text);
+ llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OF_Text);
if (EC)
return EC;
diff --git a/contrib/llvm-project/llvm/lib/Support/Windows/RWMutex.inc b/contrib/llvm-project/llvm/lib/Support/Windows/RWMutex.inc
deleted file mode 100644
index 8df9bc394160..000000000000
--- a/contrib/llvm-project/llvm/lib/Support/Windows/RWMutex.inc
+++ /dev/null
@@ -1,128 +0,0 @@
-//= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =//
-//
-// 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 Win32 specific (non-pthread) RWMutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic Win32 code that
-//=== is guaranteed to work on *all* Win32 variants.
-//===----------------------------------------------------------------------===//
-
-#include "WindowsSupport.h"
-
-namespace llvm {
-
-// Windows has slim read-writer lock support on Vista and higher, so we
-// will attempt to load the APIs. If they exist, we will use them, and
-// if not, we will fall back on critical sections. When we drop support
-// for XP, we can stop lazy-loading these APIs and just use them directly.
-#if defined(__MINGW32__)
- // Taken from WinNT.h
- typedef struct _RTL_SRWLOCK {
- PVOID Ptr;
- } RTL_SRWLOCK, *PRTL_SRWLOCK;
-
- // Taken from WinBase.h
- typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
-#endif
-
-static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL;
-
-static bool sHasSRW = false;
-
-static bool loadSRW() {
- static bool sChecked = false;
- if (!sChecked) {
- sChecked = true;
-
- if (HMODULE hLib = ::GetModuleHandleW(L"Kernel32.dll")) {
- fpInitializeSRWLock =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "InitializeSRWLock");
- fpAcquireSRWLockExclusive =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "AcquireSRWLockExclusive");
- fpAcquireSRWLockShared =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "AcquireSRWLockShared");
- fpReleaseSRWLockExclusive =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "ReleaseSRWLockExclusive");
- fpReleaseSRWLockShared =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "ReleaseSRWLockShared");
-
- if (fpInitializeSRWLock != NULL) {
- sHasSRW = true;
- }
- }
- }
- return sHasSRW;
-}
-
-sys::RWMutexImpl::RWMutexImpl() {
- if (loadSRW()) {
- data_ = safe_calloc(1, sizeof(SRWLOCK));
- fpInitializeSRWLock(static_cast<PSRWLOCK>(data_));
- } else {
- data_ = safe_calloc(1, sizeof(CRITICAL_SECTION));
- InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
-}
-
-sys::RWMutexImpl::~RWMutexImpl() {
- if (!sHasSRW)
- DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- // Nothing to do in the case of slim reader/writers except free the memory.
- free(data_);
-}
-
-bool sys::RWMutexImpl::reader_acquire() {
- if (sHasSRW) {
- fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_));
- } else {
- EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-bool sys::RWMutexImpl::reader_release() {
- if (sHasSRW) {
- fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_));
- } else {
- LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-bool sys::RWMutexImpl::writer_acquire() {
- if (sHasSRW) {
- fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_));
- } else {
- EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-bool sys::RWMutexImpl::writer_release() {
- if (sHasSRW) {
- fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_));
- } else {
- LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-
-}
diff --git a/contrib/llvm-project/llvm/lib/Support/Windows/Signals.inc b/contrib/llvm-project/llvm/lib/Support/Windows/Signals.inc
index 6a820ef22b1e..09e19ae41f1a 100644
--- a/contrib/llvm-project/llvm/lib/Support/Windows/Signals.inc
+++ b/contrib/llvm-project/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,6 +566,13 @@ void llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
// Unimplemented.
}
+void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
+ // Unimplemented.
+}
+
+void llvm::sys::DefaultOneShotPipeSignalHandler() {
+ // Unimplemented.
+}
/// Add a function to be called when a signal is delivered to the process. The
/// handler can have a cookie passed to it to identify what instance of the
@@ -785,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();
@@ -803,42 +820,15 @@ 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
+ // Stack unwinding appears to modify the context. Copy it to preserve the
+ // caller's context.
+ CONTEXT ContextCopy;
+ if (ep)
+ memcpy(&ContextCopy, ep->ContextRecord, sizeof(ContextCopy));
- HANDLE hProcess = GetCurrentProcess();
- HANDLE hThread = GetCurrentThread();
- PrintStackTraceForThread(llvm::errs(), hProcess, hThread, StackFrame,
- ep->ContextRecord);
+ LocalPrintStackTrace(llvm::errs(), ep ? &ContextCopy : nullptr);
- _exit(ep->ExceptionRecord->ExceptionCode);
+ return EXCEPTION_EXECUTE_HANDLER;
}
static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
diff --git a/contrib/llvm-project/llvm/lib/Support/Windows/Threading.inc b/contrib/llvm-project/llvm/lib/Support/Windows/Threading.inc
index 96649472cc90..9456efa686ff 100644
--- a/contrib/llvm-project/llvm/lib/Support/Windows/Threading.inc
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/Windows/WindowsSupport.h b/contrib/llvm-project/llvm/lib/Support/Windows/WindowsSupport.h
index fed9b2f462ef..bb7e79b86018 100644
--- a/contrib/llvm-project/llvm/lib/Support/Windows/WindowsSupport.h
+++ b/contrib/llvm-project/llvm/lib/Support/Windows/WindowsSupport.h
@@ -38,8 +38,10 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h" // Get build system configuration settings
+#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>
@@ -65,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/contrib/llvm-project/llvm/lib/Support/Windows/explicit_symbols.inc b/contrib/llvm-project/llvm/lib/Support/Windows/explicit_symbols.inc
index bbbf7ea6a777..0a4fda1d4e8c 100644
--- a/contrib/llvm-project/llvm/lib/Support/Windows/explicit_symbols.inc
+++ b/contrib/llvm-project/llvm/lib/Support/Windows/explicit_symbols.inc
@@ -90,12 +90,6 @@
INLINE_DEF_FLOAT_SYMBOL(tanf, 1)
INLINE_DEF_FLOAT_SYMBOL(tanhf, 1)
- // These were added in VS 2013.
-#if (1800 <= _MSC_VER && _MSC_VER < 1900)
- INLINE_DEF_FLOAT_SYMBOL(copysignf, 2)
- INLINE_DEF_FLOAT_SYMBOL(fminf, 2)
- INLINE_DEF_FLOAT_SYMBOL(fmaxf, 2)
-#endif
#undef INLINE_DEF_FLOAT_SYMBOL
#endif
diff --git a/contrib/llvm-project/llvm/lib/Support/YAMLParser.cpp b/contrib/llvm-project/llvm/lib/Support/YAMLParser.cpp
index 9b2fe9c4418a..d17e7b227f4a 100644
--- a/contrib/llvm-project/llvm/lib/Support/YAMLParser.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/llvm/lib/Support/YAMLTraits.cpp b/contrib/llvm-project/llvm/lib/Support/YAMLTraits.cpp
index 09eb36943de9..5f0cedc71829 100644
--- a/contrib/llvm-project/llvm/lib/Support/YAMLTraits.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/YAMLTraits.cpp
@@ -40,7 +40,7 @@ IO::IO(void *Context) : Ctxt(Context) {}
IO::~IO() = default;
-void *IO::getContext() {
+void *IO::getContext() const {
return Ctxt;
}
@@ -79,7 +79,7 @@ void Input::ScalarHNode::anchor() {}
void Input::MapHNode::anchor() {}
void Input::SequenceHNode::anchor() {}
-bool Input::outputting() {
+bool Input::outputting() const {
return false;
}
@@ -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;
}
@@ -377,12 +376,12 @@ std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) {
// Copy string to permanent storage
KeyStr = StringStorage.str().copy(StringAllocator);
}
- return llvm::make_unique<ScalarHNode>(N, KeyStr);
+ return std::make_unique<ScalarHNode>(N, KeyStr);
} else if (BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N)) {
StringRef ValueCopy = BSN->getValue().copy(StringAllocator);
- return llvm::make_unique<ScalarHNode>(N, ValueCopy);
+ return std::make_unique<ScalarHNode>(N, ValueCopy);
} else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) {
- auto SQHNode = llvm::make_unique<SequenceHNode>(N);
+ auto SQHNode = std::make_unique<SequenceHNode>(N);
for (Node &SN : *SQ) {
auto Entry = createHNodes(&SN);
if (EC)
@@ -391,10 +390,10 @@ std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) {
}
return std::move(SQHNode);
} else if (MappingNode *Map = dyn_cast<MappingNode>(N)) {
- auto mapHNode = llvm::make_unique<MapHNode>(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)
@@ -416,7 +415,7 @@ std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) {
}
return std::move(mapHNode);
} else if (isa<NullNode>(N)) {
- return llvm::make_unique<EmptyHNode>(N);
+ return std::make_unique<EmptyHNode>(N);
} else {
setError(N, "unknown node kind");
return nullptr;
@@ -440,7 +439,7 @@ Output::Output(raw_ostream &yout, void *context, int WrapColumn)
Output::~Output() = default;
-bool Output::outputting() {
+bool Output::outputting() const {
return true;
}
diff --git a/contrib/llvm-project/llvm/lib/Support/Z3Solver.cpp b/contrib/llvm-project/llvm/lib/Support/Z3Solver.cpp
index f1a6fdf87cf2..a83d0f441a4b 100644
--- a/contrib/llvm-project/llvm/lib/Support/Z3Solver.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/Z3Solver.cpp
@@ -886,7 +886,7 @@ public:
llvm::SMTSolverRef llvm::CreateZ3Solver() {
#if LLVM_WITH_Z3
- return llvm::make_unique<Z3Solver>();
+ return std::make_unique<Z3Solver>();
#else
llvm::report_fatal_error("LLVM was not compiled with Z3 support, rebuild "
"with -DLLVM_ENABLE_Z3_SOLVER=ON",
diff --git a/contrib/llvm-project/llvm/lib/Support/raw_ostream.cpp b/contrib/llvm-project/llvm/lib/Support/raw_ostream.cpp
index 2baccaa0cbd7..4bb315f824af 100644
--- a/contrib/llvm-project/llvm/lib/Support/raw_ostream.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/raw_ostream.cpp
@@ -65,13 +65,24 @@
using namespace llvm;
+const raw_ostream::Colors raw_ostream::BLACK;
+const raw_ostream::Colors raw_ostream::RED;
+const raw_ostream::Colors raw_ostream::GREEN;
+const raw_ostream::Colors raw_ostream::YELLOW;
+const raw_ostream::Colors raw_ostream::BLUE;
+const raw_ostream::Colors raw_ostream::MAGENTA;
+const raw_ostream::Colors raw_ostream::CYAN;
+const raw_ostream::Colors raw_ostream::WHITE;
+const raw_ostream::Colors raw_ostream::SAVEDCOLOR;
+const raw_ostream::Colors raw_ostream::RESET;
+
raw_ostream::~raw_ostream() {
// raw_ostream's subclasses should take care to flush the buffer
// in their destructors.
assert(OutBufCur == OutBufStart &&
"raw_ostream destructor called with non-empty buffer!");
- if (BufferMode == InternalBuffer)
+ if (BufferMode == BufferKind::InternalBuffer)
delete [] OutBufStart;
}
@@ -91,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;
@@ -133,6 +144,14 @@ raw_ostream &raw_ostream::write_hex(unsigned long long N) {
return *this;
}
+raw_ostream &raw_ostream::operator<<(Colors C) {
+ if (C == Colors::RESET)
+ resetColor();
+ else
+ changeColor(C);
+ return *this;
+}
+
raw_ostream &raw_ostream::write_uuid(const uuid_t UUID) {
for (int Idx = 0; Idx < 16; ++Idx) {
*this << format("%02" PRIX32, UUID[Idx]);
@@ -204,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;
}
@@ -224,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;
}
@@ -784,11 +803,15 @@ size_t raw_fd_ostream::preferred_buffer_size() const {
raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold,
bool bg) {
+ if (!ColorEnabled)
+ return *this;
+
if (sys::Process::ColorNeedsFlush())
flush();
const char *colorcode =
- (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg)
- : sys::Process::OutputColor(colors, bold, bg);
+ (colors == SAVEDCOLOR)
+ ? sys::Process::OutputBold(bg)
+ : sys::Process::OutputColor(static_cast<char>(colors), bold, bg);
if (colorcode) {
size_t len = strlen(colorcode);
write(colorcode, len);
@@ -799,6 +822,9 @@ raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold,
}
raw_ostream &raw_fd_ostream::resetColor() {
+ if (!ColorEnabled)
+ return *this;
+
if (sys::Process::ColorNeedsFlush())
flush();
const char *colorcode = sys::Process::ResetColor();
@@ -812,6 +838,9 @@ raw_ostream &raw_fd_ostream::resetColor() {
}
raw_ostream &raw_fd_ostream::reverseColor() {
+ if (!ColorEnabled)
+ return *this;
+
if (sys::Process::ColorNeedsFlush())
flush();
const char *colorcode = sys::Process::OutputReverse();
@@ -843,7 +872,7 @@ void raw_fd_ostream::anchor() {}
raw_ostream &llvm::outs() {
// Set buffer settings to model stdout behavior.
std::error_code EC;
- static raw_fd_ostream S("-", EC, sys::fs::F_None);
+ static raw_fd_ostream S("-", EC, sys::fs::OF_None);
assert(!EC);
return S;
}
diff --git a/contrib/llvm-project/llvm/lib/Support/regcomp.c b/contrib/llvm-project/llvm/lib/Support/regcomp.c
index 12669ab75d1a..ee2a1d87a267 100644
--- a/contrib/llvm-project/llvm/lib/Support/regcomp.c
+++ b/contrib/llvm-project/llvm/lib/Support/regcomp.c
@@ -48,6 +48,7 @@
#include "regex2.h"
#include "llvm/Config/config.h"
+#include "llvm/Support/Compiler.h"
/* character-class table */
static struct cclass {
@@ -537,7 +538,7 @@ p_ere_exp(struct parse *p)
break;
case '{': /* okay as ordinary except if digit follows */
REQUIRE(!MORE() || !isdigit((uch)PEEK()), REG_BADRPT);
- /* FALLTHROUGH */
+ LLVM_FALLTHROUGH;
default:
ordinary(p, c);
break;
@@ -733,7 +734,7 @@ p_simp_re(struct parse *p,
break;
case '*':
REQUIRE(starordinary, REG_BADRPT);
- /* FALLTHROUGH */
+ LLVM_FALLTHROUGH;
default:
ordinary(p, (char)c);
break;
@@ -1635,7 +1636,7 @@ findmust(struct parse *p, struct re_guts *g)
return;
}
} while (OP(s) != O_QUEST && OP(s) != O_CH);
- /* fallthrough */
+ LLVM_FALLTHROUGH;
default: /* things that break a sequence */
if (newlen > g->mlen) { /* ends one */
start = newstart;