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