diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support')
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 ¤t_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, - ¶m, 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; |
