diff options
Diffstat (limited to 'contrib/llvm/lib/Support')
65 files changed, 3334 insertions, 2206 deletions
diff --git a/contrib/llvm/lib/Support/APFloat.cpp b/contrib/llvm/lib/Support/APFloat.cpp index f9370b8..4cfbbf8 100644 --- a/contrib/llvm/lib/Support/APFloat.cpp +++ b/contrib/llvm/lib/Support/APFloat.cpp @@ -19,8 +19,10 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #include <cstring> #include <limits.h> @@ -39,16 +41,15 @@ using namespace llvm; static_assert(integerPartWidth % 4 == 0, "Part width must be divisible by 4!"); namespace llvm { - /* Represents floating point arithmetic semantics. */ struct fltSemantics { /* The largest E such that 2^E is representable; this matches the definition of IEEE 754. */ - APFloat::ExponentType maxExponent; + APFloatBase::ExponentType maxExponent; /* The smallest E such that 2^E is a normalized number; this matches the definition of IEEE 754. */ - APFloat::ExponentType minExponent; + APFloatBase::ExponentType minExponent; /* Number of bits in the significand. This includes the integer bit. */ @@ -58,12 +59,12 @@ namespace llvm { unsigned int sizeInBits; }; - const fltSemantics APFloat::IEEEhalf = { 15, -14, 11, 16 }; - const fltSemantics APFloat::IEEEsingle = { 127, -126, 24, 32 }; - const fltSemantics APFloat::IEEEdouble = { 1023, -1022, 53, 64 }; - const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, 128 }; - const fltSemantics APFloat::x87DoubleExtended = { 16383, -16382, 64, 80 }; - const fltSemantics APFloat::Bogus = { 0, 0, 0, 0 }; + static const fltSemantics semIEEEhalf = {15, -14, 11, 16}; + static const fltSemantics semIEEEsingle = {127, -126, 24, 32}; + static const fltSemantics semIEEEdouble = {1023, -1022, 53, 64}; + static const fltSemantics semIEEEquad = {16383, -16382, 113, 128}; + static const fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80}; + static const fltSemantics semBogus = {0, 0, 0, 0}; /* The PowerPC format consists of two doubles. It does not map cleanly onto the usual format above. It is approximated using twice the @@ -75,8 +76,45 @@ namespace llvm { compile-time arithmetic on PPC double-double numbers, it is not able to represent all possible values held by a PPC double-double number, for example: (long double) 1.0 + (long double) 0x1p-106 - Should this be replaced by a full emulation of PPC double-double? */ - const fltSemantics APFloat::PPCDoubleDouble = { 1023, -1022 + 53, 53 + 53, 128 }; + Should this be replaced by a full emulation of PPC double-double? + + Note: we need to make the value different from semBogus as otherwise + an unsafe optimization may collapse both values to a single address, + and we heavily rely on them having distinct addresses. */ + static const fltSemantics semPPCDoubleDouble = {-1, 0, 0, 0}; + + /* There are temporary semantics for the real PPCDoubleDouble implementation. + Currently, APFloat of PPCDoubleDouble holds one PPCDoubleDoubleImpl as the + high part of double double, and one IEEEdouble as the low part, so that + the old operations operate on PPCDoubleDoubleImpl, while the newly added + operations also populate the IEEEdouble. + + TODO: Once all functions support DoubleAPFloat mode, we'll change all + PPCDoubleDoubleImpl to IEEEdouble and remove PPCDoubleDoubleImpl. */ + static const fltSemantics semPPCDoubleDoubleImpl = {1023, -1022 + 53, 53 + 53, + 128}; + + const fltSemantics &APFloatBase::IEEEhalf() { + return semIEEEhalf; + } + const fltSemantics &APFloatBase::IEEEsingle() { + return semIEEEsingle; + } + const fltSemantics &APFloatBase::IEEEdouble() { + return semIEEEdouble; + } + const fltSemantics &APFloatBase::IEEEquad() { + return semIEEEquad; + } + const fltSemantics &APFloatBase::x87DoubleExtended() { + return semX87DoubleExtended; + } + const fltSemantics &APFloatBase::Bogus() { + return semBogus; + } + const fltSemantics &APFloatBase::PPCDoubleDouble() { + return semPPCDoubleDouble; + } /* A tight upper bound on number of parts required to hold the value pow(5, power) is @@ -94,6 +132,24 @@ namespace llvm { const unsigned int maxPowerOfFiveExponent = maxExponent + maxPrecision - 1; const unsigned int maxPowerOfFiveParts = 2 + ((maxPowerOfFiveExponent * 815) / (351 * integerPartWidth)); + + unsigned int APFloatBase::semanticsPrecision(const fltSemantics &semantics) { + return semantics.precision; + } + APFloatBase::ExponentType + APFloatBase::semanticsMaxExponent(const fltSemantics &semantics) { + return semantics.maxExponent; + } + APFloatBase::ExponentType + APFloatBase::semanticsMinExponent(const fltSemantics &semantics) { + return semantics.minExponent; + } + unsigned int APFloatBase::semanticsSizeInBits(const fltSemantics &semantics) { + return semantics.sizeInBits; + } + + unsigned APFloatBase::getSizeInBits(const fltSemantics &Sem) { + return Sem.sizeInBits; } /* A bunch of private, handy routines. */ @@ -576,10 +632,9 @@ writeSignedDecimal (char *dst, int value) return dst; } +namespace detail { /* Constructors. */ -void -APFloat::initialize(const fltSemantics *ourSemantics) -{ +void IEEEFloat::initialize(const fltSemantics *ourSemantics) { unsigned int count; semantics = ourSemantics; @@ -588,16 +643,12 @@ APFloat::initialize(const fltSemantics *ourSemantics) significand.parts = new integerPart[count]; } -void -APFloat::freeSignificand() -{ +void IEEEFloat::freeSignificand() { if (needsCleanup()) delete [] significand.parts; } -void -APFloat::assign(const APFloat &rhs) -{ +void IEEEFloat::assign(const IEEEFloat &rhs) { assert(semantics == rhs.semantics); sign = rhs.sign; @@ -607,9 +658,7 @@ APFloat::assign(const APFloat &rhs) copySignificand(rhs); } -void -APFloat::copySignificand(const APFloat &rhs) -{ +void IEEEFloat::copySignificand(const IEEEFloat &rhs) { assert(isFiniteNonZero() || category == fcNaN); assert(rhs.partCount() >= partCount()); @@ -620,8 +669,7 @@ APFloat::copySignificand(const APFloat &rhs) /* Make this number a NaN, with an arbitrary but deterministic value for the significand. If double or longer, this is a signalling NaN, which may not be ideal. If float, this is QNaN(0). */ -void APFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) -{ +void IEEEFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) { category = fcNaN; sign = Negative; @@ -663,20 +711,11 @@ void APFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) // For x87 extended precision, we want to make a NaN, not a // pseudo-NaN. Maybe we should expose the ability to make // pseudo-NaNs? - if (semantics == &APFloat::x87DoubleExtended) + if (semantics == &semX87DoubleExtended) APInt::tcSetBit(significand, QNaNBit + 1); } -APFloat APFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, - const APInt *fill) { - APFloat value(Sem, uninitialized); - value.makeNaN(SNaN, Negative, fill); - return value; -} - -APFloat & -APFloat::operator=(const APFloat &rhs) -{ +IEEEFloat &IEEEFloat::operator=(const IEEEFloat &rhs) { if (this != &rhs) { if (semantics != rhs.semantics) { freeSignificand(); @@ -688,8 +727,7 @@ APFloat::operator=(const APFloat &rhs) return *this; } -APFloat & -APFloat::operator=(APFloat &&rhs) { +IEEEFloat &IEEEFloat::operator=(IEEEFloat &&rhs) { freeSignificand(); semantics = rhs.semantics; @@ -698,19 +736,17 @@ APFloat::operator=(APFloat &&rhs) { category = rhs.category; sign = rhs.sign; - rhs.semantics = &Bogus; + rhs.semantics = &semBogus; return *this; } -bool -APFloat::isDenormal() const { +bool IEEEFloat::isDenormal() const { return isFiniteNonZero() && (exponent == semantics->minExponent) && (APInt::tcExtractBit(significandParts(), semantics->precision - 1) == 0); } -bool -APFloat::isSmallest() const { +bool IEEEFloat::isSmallest() const { // The smallest number by magnitude in our format will be the smallest // denormal, i.e. the floating point number with exponent being minimum // exponent and significand bitwise equal to 1 (i.e. with MSB equal to 0). @@ -718,7 +754,7 @@ APFloat::isSmallest() const { significandMSB() == 0; } -bool APFloat::isSignificandAllOnes() const { +bool IEEEFloat::isSignificandAllOnes() const { // Test if the significand excluding the integral bit is all ones. This allows // us to test for binade boundaries. const integerPart *Parts = significandParts(); @@ -740,7 +776,7 @@ bool APFloat::isSignificandAllOnes() const { return true; } -bool APFloat::isSignificandAllZeros() const { +bool IEEEFloat::isSignificandAllZeros() const { // Test if the significand excluding the integral bit is all zeros. This // allows us to test for binade boundaries. const integerPart *Parts = significandParts(); @@ -762,25 +798,22 @@ bool APFloat::isSignificandAllZeros() const { return true; } -bool -APFloat::isLargest() const { +bool IEEEFloat::isLargest() const { // The largest number by magnitude in our format will be the floating point // number with maximum exponent and with significand that is all ones. return isFiniteNonZero() && exponent == semantics->maxExponent && isSignificandAllOnes(); } -bool -APFloat::isInteger() const { +bool IEEEFloat::isInteger() const { // This could be made more efficient; I'm going for obviously correct. if (!isFinite()) return false; - APFloat truncated = *this; + IEEEFloat truncated = *this; truncated.roundToIntegral(rmTowardZero); return compare(truncated) == cmpEqual; } -bool -APFloat::bitwiseIsEqual(const APFloat &rhs) const { +bool IEEEFloat::bitwiseIsEqual(const IEEEFloat &rhs) const { if (this == &rhs) return true; if (semantics != rhs.semantics || @@ -797,7 +830,7 @@ APFloat::bitwiseIsEqual(const APFloat &rhs) const { rhs.significandParts()); } -APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) { +IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, integerPart value) { initialize(&ourSemantics); sign = 0; category = fcNormal; @@ -807,93 +840,54 @@ APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) { normalize(rmNearestTiesToEven, lfExactlyZero); } -APFloat::APFloat(const fltSemantics &ourSemantics) { +IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics) { initialize(&ourSemantics); category = fcZero; sign = false; } -APFloat::APFloat(const fltSemantics &ourSemantics, uninitializedTag tag) { - // Allocates storage if necessary but does not initialize it. - initialize(&ourSemantics); -} +// Delegate to the previous constructor, because later copy constructor may +// actually inspects category, which can't be garbage. +IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, uninitializedTag tag) + : IEEEFloat(ourSemantics) {} -APFloat::APFloat(const fltSemantics &ourSemantics, StringRef text) { - initialize(&ourSemantics); - convertFromString(text, rmNearestTiesToEven); -} - -APFloat::APFloat(const APFloat &rhs) { +IEEEFloat::IEEEFloat(const IEEEFloat &rhs) { initialize(rhs.semantics); assign(rhs); } -APFloat::APFloat(APFloat &&rhs) : semantics(&Bogus) { +IEEEFloat::IEEEFloat(IEEEFloat &&rhs) : semantics(&semBogus) { *this = std::move(rhs); } -APFloat::~APFloat() -{ - freeSignificand(); -} +IEEEFloat::~IEEEFloat() { freeSignificand(); } // Profile - This method 'profiles' an APFloat for use with FoldingSet. -void APFloat::Profile(FoldingSetNodeID& ID) const { +void IEEEFloat::Profile(FoldingSetNodeID &ID) const { ID.Add(bitcastToAPInt()); } -unsigned int -APFloat::partCount() const -{ +unsigned int IEEEFloat::partCount() const { return partCountForBits(semantics->precision + 1); } -unsigned int -APFloat::semanticsPrecision(const fltSemantics &semantics) -{ - return semantics.precision; -} -APFloat::ExponentType -APFloat::semanticsMaxExponent(const fltSemantics &semantics) -{ - return semantics.maxExponent; -} -APFloat::ExponentType -APFloat::semanticsMinExponent(const fltSemantics &semantics) -{ - return semantics.minExponent; -} -unsigned int -APFloat::semanticsSizeInBits(const fltSemantics &semantics) -{ - return semantics.sizeInBits; -} - -const integerPart * -APFloat::significandParts() const -{ - return const_cast<APFloat *>(this)->significandParts(); +const integerPart *IEEEFloat::significandParts() const { + return const_cast<IEEEFloat *>(this)->significandParts(); } -integerPart * -APFloat::significandParts() -{ +integerPart *IEEEFloat::significandParts() { if (partCount() > 1) return significand.parts; else return &significand.part; } -void -APFloat::zeroSignificand() -{ +void IEEEFloat::zeroSignificand() { APInt::tcSet(significandParts(), 0, partCount()); } /* Increment an fcNormal floating point number's significand. */ -void -APFloat::incrementSignificand() -{ +void IEEEFloat::incrementSignificand() { integerPart carry; carry = APInt::tcIncrement(significandParts(), partCount()); @@ -904,9 +898,7 @@ APFloat::incrementSignificand() } /* Add the significand of the RHS. Returns the carry flag. */ -integerPart -APFloat::addSignificand(const APFloat &rhs) -{ +integerPart IEEEFloat::addSignificand(const IEEEFloat &rhs) { integerPart *parts; parts = significandParts(); @@ -919,9 +911,8 @@ APFloat::addSignificand(const APFloat &rhs) /* Subtract the significand of the RHS with a borrow flag. Returns the borrow flag. */ -integerPart -APFloat::subtractSignificand(const APFloat &rhs, integerPart borrow) -{ +integerPart IEEEFloat::subtractSignificand(const IEEEFloat &rhs, + integerPart borrow) { integerPart *parts; parts = significandParts(); @@ -936,9 +927,8 @@ APFloat::subtractSignificand(const APFloat &rhs, integerPart borrow) /* Multiply the significand of the RHS. If ADDEND is non-NULL, add it on to the full-precision result of the multiplication. Returns the lost fraction. */ -lostFraction -APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) -{ +lostFraction IEEEFloat::multiplySignificand(const IEEEFloat &rhs, + const IEEEFloat *addend) { unsigned int omsb; // One, not zero, based MSB. unsigned int partsCount, newPartsCount, precision; integerPart *lhsSignificand; @@ -1011,7 +1001,7 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) significand.parts = fullSignificand; semantics = &extendedSemantics; - APFloat extendedAddend(*addend); + IEEEFloat extendedAddend(*addend); status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored); assert(status == opOK); (void)status; @@ -1045,7 +1035,8 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) // the radix point (i.e. "MSB . rest-significant-bits"). // // Note that the result is not normalized when "omsb < precision". So, the - // caller needs to call APFloat::normalize() if normalized value is expected. + // caller needs to call IEEEFloat::normalize() if normalized value is + // expected. if (omsb > precision) { unsigned int bits, significantParts; lostFraction lf; @@ -1066,9 +1057,7 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) } /* Multiply the significands of LHS and RHS to DST. */ -lostFraction -APFloat::divideSignificand(const APFloat &rhs) -{ +lostFraction IEEEFloat::divideSignificand(const IEEEFloat &rhs) { unsigned int bit, i, partsCount; const integerPart *rhsSignificand; integerPart *lhsSignificand, *dividend, *divisor; @@ -1150,22 +1139,16 @@ APFloat::divideSignificand(const APFloat &rhs) return lost_fraction; } -unsigned int -APFloat::significandMSB() const -{ +unsigned int IEEEFloat::significandMSB() const { return APInt::tcMSB(significandParts(), partCount()); } -unsigned int -APFloat::significandLSB() const -{ +unsigned int IEEEFloat::significandLSB() const { return APInt::tcLSB(significandParts(), partCount()); } /* Note that a zero result is NOT normalized to fcZero. */ -lostFraction -APFloat::shiftSignificandRight(unsigned int bits) -{ +lostFraction IEEEFloat::shiftSignificandRight(unsigned int bits) { /* Our exponent should not overflow. */ assert((ExponentType) (exponent + bits) >= exponent); @@ -1175,9 +1158,7 @@ APFloat::shiftSignificandRight(unsigned int bits) } /* Shift the significand left BITS bits, subtract BITS from its exponent. */ -void -APFloat::shiftSignificandLeft(unsigned int bits) -{ +void IEEEFloat::shiftSignificandLeft(unsigned int bits) { assert(bits < semantics->precision); if (bits) { @@ -1190,9 +1171,8 @@ APFloat::shiftSignificandLeft(unsigned int bits) } } -APFloat::cmpResult -APFloat::compareAbsoluteValue(const APFloat &rhs) const -{ +IEEEFloat::cmpResult +IEEEFloat::compareAbsoluteValue(const IEEEFloat &rhs) const { int compare; assert(semantics == rhs.semantics); @@ -1217,9 +1197,7 @@ APFloat::compareAbsoluteValue(const APFloat &rhs) const /* Handle overflow. Sign is preserved. We either become infinity or the largest finite number. */ -APFloat::opStatus -APFloat::handleOverflow(roundingMode rounding_mode) -{ +IEEEFloat::opStatus IEEEFloat::handleOverflow(roundingMode rounding_mode) { /* Infinity? */ if (rounding_mode == rmNearestTiesToEven || rounding_mode == rmNearestTiesToAway || @@ -1243,11 +1221,9 @@ APFloat::handleOverflow(roundingMode rounding_mode) would need to be rounded away from zero (i.e., by increasing the signficand). This routine must work for fcZero of both signs, and fcNormal numbers. */ -bool -APFloat::roundAwayFromZero(roundingMode rounding_mode, - lostFraction lost_fraction, - unsigned int bit) const -{ +bool IEEEFloat::roundAwayFromZero(roundingMode rounding_mode, + lostFraction lost_fraction, + unsigned int bit) const { /* NaNs and infinities should not have lost fractions. */ assert(isFiniteNonZero() || category == fcZero); @@ -1280,10 +1256,8 @@ APFloat::roundAwayFromZero(roundingMode rounding_mode, llvm_unreachable("Invalid rounding mode found"); } -APFloat::opStatus -APFloat::normalize(roundingMode rounding_mode, - lostFraction lost_fraction) -{ +IEEEFloat::opStatus IEEEFloat::normalize(roundingMode rounding_mode, + lostFraction lost_fraction) { unsigned int omsb; /* One, not zero, based MSB. */ int exponentChange; @@ -1388,9 +1362,8 @@ APFloat::normalize(roundingMode rounding_mode, return (opStatus) (opUnderflow | opInexact); } -APFloat::opStatus -APFloat::addOrSubtractSpecials(const APFloat &rhs, bool subtract) -{ +IEEEFloat::opStatus IEEEFloat::addOrSubtractSpecials(const IEEEFloat &rhs, + bool subtract) { switch (PackCategoriesIntoKey(category, rhs.category)) { default: llvm_unreachable(nullptr); @@ -1445,9 +1418,8 @@ APFloat::addOrSubtractSpecials(const APFloat &rhs, bool subtract) } /* Add or subtract two normal numbers. */ -lostFraction -APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract) -{ +lostFraction IEEEFloat::addOrSubtractSignificand(const IEEEFloat &rhs, + bool subtract) { integerPart carry; lostFraction lost_fraction; int bits; @@ -1461,7 +1433,7 @@ APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract) /* Subtraction is more subtle than one might naively expect. */ if (subtract) { - APFloat temp_rhs(rhs); + IEEEFloat temp_rhs(rhs); bool reverse; if (bits == 0) { @@ -1500,7 +1472,7 @@ APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract) (void)carry; } else { if (bits > 0) { - APFloat temp_rhs(rhs); + IEEEFloat temp_rhs(rhs); lost_fraction = temp_rhs.shiftSignificandRight(bits); carry = addSignificand(temp_rhs); @@ -1517,9 +1489,7 @@ APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract) return lost_fraction; } -APFloat::opStatus -APFloat::multiplySpecials(const APFloat &rhs) -{ +IEEEFloat::opStatus IEEEFloat::multiplySpecials(const IEEEFloat &rhs) { switch (PackCategoriesIntoKey(category, rhs.category)) { default: llvm_unreachable(nullptr); @@ -1561,9 +1531,7 @@ APFloat::multiplySpecials(const APFloat &rhs) } } -APFloat::opStatus -APFloat::divideSpecials(const APFloat &rhs) -{ +IEEEFloat::opStatus IEEEFloat::divideSpecials(const IEEEFloat &rhs) { switch (PackCategoriesIntoKey(category, rhs.category)) { default: llvm_unreachable(nullptr); @@ -1602,9 +1570,7 @@ APFloat::divideSpecials(const APFloat &rhs) } } -APFloat::opStatus -APFloat::modSpecials(const APFloat &rhs) -{ +IEEEFloat::opStatus IEEEFloat::modSpecials(const IEEEFloat &rhs) { switch (PackCategoriesIntoKey(category, rhs.category)) { default: llvm_unreachable(nullptr); @@ -1640,32 +1606,25 @@ APFloat::modSpecials(const APFloat &rhs) } /* Change sign. */ -void -APFloat::changeSign() -{ +void IEEEFloat::changeSign() { /* Look mummy, this one's easy. */ sign = !sign; } -void -APFloat::clearSign() -{ +void IEEEFloat::clearSign() { /* So is this one. */ sign = 0; } -void -APFloat::copySign(const APFloat &rhs) -{ +void IEEEFloat::copySign(const IEEEFloat &rhs) { /* And this one. */ sign = rhs.sign; } /* Normalized addition or subtraction. */ -APFloat::opStatus -APFloat::addOrSubtract(const APFloat &rhs, roundingMode rounding_mode, - bool subtract) -{ +IEEEFloat::opStatus IEEEFloat::addOrSubtract(const IEEEFloat &rhs, + roundingMode rounding_mode, + bool subtract) { opStatus fs; fs = addOrSubtractSpecials(rhs, subtract); @@ -1693,23 +1652,20 @@ APFloat::addOrSubtract(const APFloat &rhs, roundingMode rounding_mode, } /* Normalized addition. */ -APFloat::opStatus -APFloat::add(const APFloat &rhs, roundingMode rounding_mode) -{ +IEEEFloat::opStatus IEEEFloat::add(const IEEEFloat &rhs, + roundingMode rounding_mode) { return addOrSubtract(rhs, rounding_mode, false); } /* Normalized subtraction. */ -APFloat::opStatus -APFloat::subtract(const APFloat &rhs, roundingMode rounding_mode) -{ +IEEEFloat::opStatus IEEEFloat::subtract(const IEEEFloat &rhs, + roundingMode rounding_mode) { return addOrSubtract(rhs, rounding_mode, true); } /* Normalized multiply. */ -APFloat::opStatus -APFloat::multiply(const APFloat &rhs, roundingMode rounding_mode) -{ +IEEEFloat::opStatus IEEEFloat::multiply(const IEEEFloat &rhs, + roundingMode rounding_mode) { opStatus fs; sign ^= rhs.sign; @@ -1726,9 +1682,8 @@ APFloat::multiply(const APFloat &rhs, roundingMode rounding_mode) } /* Normalized divide. */ -APFloat::opStatus -APFloat::divide(const APFloat &rhs, roundingMode rounding_mode) -{ +IEEEFloat::opStatus IEEEFloat::divide(const IEEEFloat &rhs, + roundingMode rounding_mode) { opStatus fs; sign ^= rhs.sign; @@ -1745,11 +1700,9 @@ APFloat::divide(const APFloat &rhs, roundingMode rounding_mode) } /* Normalized remainder. This is not currently correct in all cases. */ -APFloat::opStatus -APFloat::remainder(const APFloat &rhs) -{ +IEEEFloat::opStatus IEEEFloat::remainder(const IEEEFloat &rhs) { opStatus fs; - APFloat V = *this; + IEEEFloat V = *this; unsigned int origSign = sign; fs = V.divide(rhs, rmNearestTiesToEven); @@ -1761,8 +1714,10 @@ APFloat::remainder(const APFloat &rhs) bool ignored; fs = V.convertToInteger(x, parts * integerPartWidth, true, rmNearestTiesToEven, &ignored); - if (fs==opInvalidOp) + if (fs==opInvalidOp) { + delete[] x; return fs; + } fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true, rmNearestTiesToEven); @@ -1782,14 +1737,12 @@ APFloat::remainder(const APFloat &rhs) /* Normalized llvm frem (C fmod). This is not currently correct in all cases. */ -APFloat::opStatus -APFloat::mod(const APFloat &rhs) -{ +IEEEFloat::opStatus IEEEFloat::mod(const IEEEFloat &rhs) { opStatus fs; fs = modSpecials(rhs); if (isFiniteNonZero() && rhs.isFiniteNonZero()) { - APFloat V = *this; + IEEEFloat V = *this; unsigned int origSign = sign; fs = V.divide(rhs, rmNearestTiesToEven); @@ -1801,8 +1754,10 @@ APFloat::mod(const APFloat &rhs) bool ignored; fs = V.convertToInteger(x, parts * integerPartWidth, true, rmTowardZero, &ignored); - if (fs==opInvalidOp) + if (fs==opInvalidOp) { + delete[] x; return fs; + } fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true, rmNearestTiesToEven); @@ -1822,11 +1777,9 @@ APFloat::mod(const APFloat &rhs) } /* Normalized fused-multiply-add. */ -APFloat::opStatus -APFloat::fusedMultiplyAdd(const APFloat &multiplicand, - const APFloat &addend, - roundingMode rounding_mode) -{ +IEEEFloat::opStatus IEEEFloat::fusedMultiplyAdd(const IEEEFloat &multiplicand, + const IEEEFloat &addend, + roundingMode rounding_mode) { opStatus fs; /* Post-multiplication sign, before addition. */ @@ -1867,7 +1820,7 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand, } /* Rounding-mode corrrect round to integral value. */ -APFloat::opStatus APFloat::roundToIntegral(roundingMode rounding_mode) { +IEEEFloat::opStatus IEEEFloat::roundToIntegral(roundingMode rounding_mode) { opStatus fs; // If the exponent is large enough, we know that this value is already @@ -1884,7 +1837,7 @@ APFloat::opStatus APFloat::roundToIntegral(roundingMode rounding_mode) { // addition instead. APInt IntegerConstant(NextPowerOf2(semanticsPrecision(*semantics)), 1); IntegerConstant <<= semanticsPrecision(*semantics)-1; - APFloat MagicConstant(*semantics); + IEEEFloat MagicConstant(*semantics); fs = MagicConstant.convertFromAPInt(IntegerConstant, false, rmNearestTiesToEven); MagicConstant.copySign(*this); @@ -1910,9 +1863,7 @@ APFloat::opStatus APFloat::roundToIntegral(roundingMode rounding_mode) { /* Comparison requires normalized numbers. */ -APFloat::cmpResult -APFloat::compare(const APFloat &rhs) const -{ +IEEEFloat::cmpResult IEEEFloat::compare(const IEEEFloat &rhs) const { cmpResult result; assert(semantics == rhs.semantics); @@ -1982,17 +1933,16 @@ APFloat::compare(const APFloat &rhs) const return result; } -/// APFloat::convert - convert a value of one floating point type to another. +/// IEEEFloat::convert - convert a value of one floating point type to another. /// The return value corresponds to the IEEE754 exceptions. *losesInfo /// records whether the transformation lost information, i.e. whether /// converting the result back to the original type will produce the /// original value (this is almost the same as return value==fsOK, but there /// are edge cases where this is not so). -APFloat::opStatus -APFloat::convert(const fltSemantics &toSemantics, - roundingMode rounding_mode, bool *losesInfo) -{ +IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics, + roundingMode rounding_mode, + bool *losesInfo) { lostFraction lostFraction; unsigned int newPartCount, oldPartCount; opStatus fs; @@ -2005,8 +1955,8 @@ APFloat::convert(const fltSemantics &toSemantics, shift = toSemantics.precision - fromSemantics.precision; bool X86SpecialNan = false; - if (&fromSemantics == &APFloat::x87DoubleExtended && - &toSemantics != &APFloat::x87DoubleExtended && category == fcNaN && + if (&fromSemantics == &semX87DoubleExtended && + &toSemantics != &semX87DoubleExtended && category == fcNaN && (!(*significandParts() & 0x8000000000000000ULL) || !(*significandParts() & 0x4000000000000000ULL))) { // x86 has some unusual NaNs which cannot be represented in any other @@ -2070,7 +2020,7 @@ APFloat::convert(const fltSemantics &toSemantics, // For x87 extended precision, we want to make a NaN, not a special NaN if // the input wasn't special either. - if (!X86SpecialNan && semantics == &APFloat::x87DoubleExtended) + if (!X86SpecialNan && semantics == &semX87DoubleExtended) APInt::tcSetBit(significandParts(), semantics->precision - 1); // gcc forces the Quiet bit on, which means (float)(double)(float_sNan) @@ -2096,12 +2046,9 @@ APFloat::convert(const fltSemantics &toSemantics, Note that for conversions to integer type the C standard requires round-to-zero to always be used. */ -APFloat::opStatus -APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width, - bool isSigned, - roundingMode rounding_mode, - bool *isExact) const -{ +IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( + integerPart *parts, unsigned int width, bool isSigned, + roundingMode rounding_mode, bool *isExact) const { lostFraction lost_fraction; const integerPart *src; unsigned int dstPartsCount, truncatedBits; @@ -2208,11 +2155,11 @@ APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width, the original value. This is almost equivalent to result==opOK, except for negative zeroes. */ -APFloat::opStatus -APFloat::convertToInteger(integerPart *parts, unsigned int width, - bool isSigned, - roundingMode rounding_mode, bool *isExact) const -{ +IEEEFloat::opStatus IEEEFloat::convertToInteger(integerPart *parts, + unsigned int width, + bool isSigned, + roundingMode rounding_mode, + bool *isExact) const { opStatus fs; fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode, @@ -2242,10 +2189,9 @@ APFloat::convertToInteger(integerPart *parts, unsigned int width, an APSInt, whose initial bit-width and signed-ness are used to determine the precision of the conversion. */ -APFloat::opStatus -APFloat::convertToInteger(APSInt &result, - roundingMode rounding_mode, bool *isExact) const -{ +IEEEFloat::opStatus IEEEFloat::convertToInteger(APSInt &result, + roundingMode rounding_mode, + bool *isExact) const { unsigned bitWidth = result.getBitWidth(); SmallVector<uint64_t, 4> parts(result.getNumWords()); opStatus status = convertToInteger( @@ -2258,11 +2204,8 @@ APFloat::convertToInteger(APSInt &result, /* Convert an unsigned integer SRC to a floating point number, rounding according to ROUNDING_MODE. The sign of the floating point number is not modified. */ -APFloat::opStatus -APFloat::convertFromUnsignedParts(const integerPart *src, - unsigned int srcCount, - roundingMode rounding_mode) -{ +IEEEFloat::opStatus IEEEFloat::convertFromUnsignedParts( + const integerPart *src, unsigned int srcCount, roundingMode rounding_mode) { unsigned int omsb, precision, dstCount; integerPart *dst; lostFraction lost_fraction; @@ -2289,11 +2232,8 @@ APFloat::convertFromUnsignedParts(const integerPart *src, return normalize(rounding_mode, lost_fraction); } -APFloat::opStatus -APFloat::convertFromAPInt(const APInt &Val, - bool isSigned, - roundingMode rounding_mode) -{ +IEEEFloat::opStatus IEEEFloat::convertFromAPInt(const APInt &Val, bool isSigned, + roundingMode rounding_mode) { unsigned int partCount = Val.getNumWords(); APInt api = Val; @@ -2309,12 +2249,10 @@ APFloat::convertFromAPInt(const APInt &Val, /* Convert a two's complement integer SRC to a floating point number, rounding according to ROUNDING_MODE. ISSIGNED is true if the integer is signed, in which case it must be sign-extended. */ -APFloat::opStatus -APFloat::convertFromSignExtendedInteger(const integerPart *src, - unsigned int srcCount, - bool isSigned, - roundingMode rounding_mode) -{ +IEEEFloat::opStatus +IEEEFloat::convertFromSignExtendedInteger(const integerPart *src, + unsigned int srcCount, bool isSigned, + roundingMode rounding_mode) { opStatus status; if (isSigned && @@ -2337,11 +2275,10 @@ APFloat::convertFromSignExtendedInteger(const integerPart *src, } /* FIXME: should this just take a const APInt reference? */ -APFloat::opStatus -APFloat::convertFromZeroExtendedInteger(const integerPart *parts, - unsigned int width, bool isSigned, - roundingMode rounding_mode) -{ +IEEEFloat::opStatus +IEEEFloat::convertFromZeroExtendedInteger(const integerPart *parts, + unsigned int width, bool isSigned, + roundingMode rounding_mode) { unsigned int partCount = partCountForBits(width); APInt api = APInt(width, makeArrayRef(parts, partCount)); @@ -2354,9 +2291,9 @@ APFloat::convertFromZeroExtendedInteger(const integerPart *parts, return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode); } -APFloat::opStatus -APFloat::convertFromHexadecimalString(StringRef s, roundingMode rounding_mode) -{ +IEEEFloat::opStatus +IEEEFloat::convertFromHexadecimalString(StringRef s, + roundingMode rounding_mode) { lostFraction lost_fraction = lfExactlyZero; category = fcNormal; @@ -2434,11 +2371,10 @@ APFloat::convertFromHexadecimalString(StringRef s, roundingMode rounding_mode) return normalize(rounding_mode, lost_fraction); } -APFloat::opStatus -APFloat::roundSignificandWithExponent(const integerPart *decSigParts, - unsigned sigPartCount, int exp, - roundingMode rounding_mode) -{ +IEEEFloat::opStatus +IEEEFloat::roundSignificandWithExponent(const integerPart *decSigParts, + unsigned sigPartCount, int exp, + roundingMode rounding_mode) { unsigned int parts, pow5PartCount; fltSemantics calcSemantics = { 32767, -32767, 0, 0 }; integerPart pow5Parts[maxPowerOfFiveParts]; @@ -2460,8 +2396,9 @@ APFloat::roundSignificandWithExponent(const integerPart *decSigParts, excessPrecision = calcSemantics.precision - semantics->precision; truncatedBits = excessPrecision; - APFloat decSig = APFloat::getZero(calcSemantics, sign); - APFloat pow5(calcSemantics); + IEEEFloat decSig(calcSemantics, uninitialized); + decSig.makeZero(sign); + IEEEFloat pow5(calcSemantics); sigStatus = decSig.convertFromUnsignedParts(decSigParts, sigPartCount, rmNearestTiesToEven); @@ -2519,9 +2456,8 @@ APFloat::roundSignificandWithExponent(const integerPart *decSigParts, } } -APFloat::opStatus -APFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) -{ +IEEEFloat::opStatus +IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) { decimalInfo D; opStatus fs; @@ -2637,8 +2573,7 @@ APFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) return fs; } -bool -APFloat::convertFromStringSpecials(StringRef str) { +bool IEEEFloat::convertFromStringSpecials(StringRef str) { if (str.equals("inf") || str.equals("INFINITY")) { makeInf(false); return true; @@ -2662,9 +2597,8 @@ APFloat::convertFromStringSpecials(StringRef str) { return false; } -APFloat::opStatus -APFloat::convertFromString(StringRef str, roundingMode rounding_mode) -{ +IEEEFloat::opStatus IEEEFloat::convertFromString(StringRef str, + roundingMode rounding_mode) { assert(!str.empty() && "Invalid string length"); // Handle special cases. @@ -2714,10 +2648,9 @@ APFloat::convertFromString(StringRef str, roundingMode rounding_mode) 1 (normal numbers) or 2 (normal numbers rounded-away-from-zero with any other digits zero). */ -unsigned int -APFloat::convertToHexString(char *dst, unsigned int hexDigits, - bool upperCase, roundingMode rounding_mode) const -{ +unsigned int IEEEFloat::convertToHexString(char *dst, unsigned int hexDigits, + bool upperCase, + roundingMode rounding_mode) const { char *p; p = dst; @@ -2762,11 +2695,9 @@ APFloat::convertToHexString(char *dst, unsigned int hexDigits, form of a normal floating point number with the specified number of hexadecimal digits. If HEXDIGITS is zero the minimum number of digits necessary to print the value precisely is output. */ -char * -APFloat::convertNormalToHexString(char *dst, unsigned int hexDigits, - bool upperCase, - roundingMode rounding_mode) const -{ +char *IEEEFloat::convertNormalToHexString(char *dst, unsigned int hexDigits, + bool upperCase, + roundingMode rounding_mode) const { unsigned int count, valueBits, shift, partsCount, outputDigits; const char *hexDigitChars; const integerPart *significand; @@ -2866,7 +2797,7 @@ APFloat::convertNormalToHexString(char *dst, unsigned int hexDigits, return writeSignedDecimal (dst, exponent); } -hash_code llvm::hash_value(const APFloat &Arg) { +hash_code hash_value(const IEEEFloat &Arg) { if (!Arg.isFiniteNonZero()) return hash_combine((uint8_t)Arg.category, // NaN has no sign, fix it at zero. @@ -2890,10 +2821,8 @@ hash_code llvm::hash_value(const APFloat &Arg) { // Denormals have exponent minExponent in APFloat, but minExponent-1 in // the actual IEEE respresentations. We compensate for that here. -APInt -APFloat::convertF80LongDoubleAPFloatToAPInt() const -{ - assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended); +APInt IEEEFloat::convertF80LongDoubleAPFloatToAPInt() const { + assert(semantics == (const llvm::fltSemantics*)&semX87DoubleExtended); assert(partCount()==2); uint64_t myexponent, mysignificand; @@ -2922,10 +2851,8 @@ APFloat::convertF80LongDoubleAPFloatToAPInt() const return APInt(80, words); } -APInt -APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const -{ - assert(semantics == (const llvm::fltSemantics*)&PPCDoubleDouble); +APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const { + assert(semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleImpl); assert(partCount()==2); uint64_t words[2]; @@ -2939,14 +2866,14 @@ APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const // Declare fltSemantics before APFloat that uses it (and // saves pointer to it) to ensure correct destruction order. fltSemantics extendedSemantics = *semantics; - extendedSemantics.minExponent = IEEEdouble.minExponent; - APFloat extended(*this); + extendedSemantics.minExponent = semIEEEdouble.minExponent; + IEEEFloat extended(*this); fs = extended.convert(extendedSemantics, rmNearestTiesToEven, &losesInfo); assert(fs == opOK && !losesInfo); (void)fs; - APFloat u(extended); - fs = u.convert(IEEEdouble, rmNearestTiesToEven, &losesInfo); + IEEEFloat u(extended); + fs = u.convert(semIEEEdouble, rmNearestTiesToEven, &losesInfo); assert(fs == opOK || fs == opInexact); (void)fs; words[0] = *u.convertDoubleAPFloatToAPInt().getRawData(); @@ -2960,9 +2887,9 @@ APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const assert(fs == opOK && !losesInfo); (void)fs; - APFloat v(extended); + IEEEFloat v(extended); v.subtract(u, rmNearestTiesToEven); - fs = v.convert(IEEEdouble, rmNearestTiesToEven, &losesInfo); + fs = v.convert(semIEEEdouble, rmNearestTiesToEven, &losesInfo); assert(fs == opOK && !losesInfo); (void)fs; words[1] = *v.convertDoubleAPFloatToAPInt().getRawData(); @@ -2973,10 +2900,8 @@ APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const return APInt(128, words); } -APInt -APFloat::convertQuadrupleAPFloatToAPInt() const -{ - assert(semantics == (const llvm::fltSemantics*)&IEEEquad); +APInt IEEEFloat::convertQuadrupleAPFloatToAPInt() const { + assert(semantics == (const llvm::fltSemantics*)&semIEEEquad); assert(partCount()==2); uint64_t myexponent, mysignificand, mysignificand2; @@ -3009,10 +2934,8 @@ APFloat::convertQuadrupleAPFloatToAPInt() const return APInt(128, words); } -APInt -APFloat::convertDoubleAPFloatToAPInt() const -{ - assert(semantics == (const llvm::fltSemantics*)&IEEEdouble); +APInt IEEEFloat::convertDoubleAPFloatToAPInt() const { + assert(semantics == (const llvm::fltSemantics*)&semIEEEdouble); assert(partCount()==1); uint64_t myexponent, mysignificand; @@ -3039,10 +2962,8 @@ APFloat::convertDoubleAPFloatToAPInt() const (mysignificand & 0xfffffffffffffLL)))); } -APInt -APFloat::convertFloatAPFloatToAPInt() const -{ - assert(semantics == (const llvm::fltSemantics*)&IEEEsingle); +APInt IEEEFloat::convertFloatAPFloatToAPInt() const { + assert(semantics == (const llvm::fltSemantics*)&semIEEEsingle); assert(partCount()==1); uint32_t myexponent, mysignificand; @@ -3068,10 +2989,8 @@ APFloat::convertFloatAPFloatToAPInt() const (mysignificand & 0x7fffff))); } -APInt -APFloat::convertHalfAPFloatToAPInt() const -{ - assert(semantics == (const llvm::fltSemantics*)&IEEEhalf); +APInt IEEEFloat::convertHalfAPFloatToAPInt() const { + assert(semantics == (const llvm::fltSemantics*)&semIEEEhalf); assert(partCount()==1); uint32_t myexponent, mysignificand; @@ -3101,42 +3020,36 @@ APFloat::convertHalfAPFloatToAPInt() const // point constant as it would appear in memory. It is not a conversion, // and treating the result as a normal integer is unlikely to be useful. -APInt -APFloat::bitcastToAPInt() const -{ - if (semantics == (const llvm::fltSemantics*)&IEEEhalf) +APInt IEEEFloat::bitcastToAPInt() const { + if (semantics == (const llvm::fltSemantics*)&semIEEEhalf) return convertHalfAPFloatToAPInt(); - if (semantics == (const llvm::fltSemantics*)&IEEEsingle) + if (semantics == (const llvm::fltSemantics*)&semIEEEsingle) return convertFloatAPFloatToAPInt(); - if (semantics == (const llvm::fltSemantics*)&IEEEdouble) + if (semantics == (const llvm::fltSemantics*)&semIEEEdouble) return convertDoubleAPFloatToAPInt(); - if (semantics == (const llvm::fltSemantics*)&IEEEquad) + if (semantics == (const llvm::fltSemantics*)&semIEEEquad) return convertQuadrupleAPFloatToAPInt(); - if (semantics == (const llvm::fltSemantics*)&PPCDoubleDouble) + if (semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleImpl) return convertPPCDoubleDoubleAPFloatToAPInt(); - assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended && + assert(semantics == (const llvm::fltSemantics*)&semX87DoubleExtended && "unknown format!"); return convertF80LongDoubleAPFloatToAPInt(); } -float -APFloat::convertToFloat() const -{ - assert(semantics == (const llvm::fltSemantics*)&IEEEsingle && +float IEEEFloat::convertToFloat() const { + assert(semantics == (const llvm::fltSemantics*)&semIEEEsingle && "Float semantics are not IEEEsingle"); APInt api = bitcastToAPInt(); return api.bitsToFloat(); } -double -APFloat::convertToDouble() const -{ - assert(semantics == (const llvm::fltSemantics*)&IEEEdouble && +double IEEEFloat::convertToDouble() const { + assert(semantics == (const llvm::fltSemantics*)&semIEEEdouble && "Float semantics are not IEEEdouble"); APInt api = bitcastToAPInt(); return api.bitsToDouble(); @@ -3149,16 +3062,14 @@ APFloat::convertToDouble() const /// exponent = 0, integer bit 1 ("pseudodenormal") /// exponent!=0 nor all 1's, integer bit 0 ("unnormal") /// At the moment, the first two are treated as NaNs, the second two as Normal. -void -APFloat::initFromF80LongDoubleAPInt(const APInt &api) -{ +void IEEEFloat::initFromF80LongDoubleAPInt(const APInt &api) { assert(api.getBitWidth()==80); uint64_t i1 = api.getRawData()[0]; uint64_t i2 = api.getRawData()[1]; uint64_t myexponent = (i2 & 0x7fff); uint64_t mysignificand = i1; - initialize(&APFloat::x87DoubleExtended); + initialize(&semX87DoubleExtended); assert(partCount()==2); sign = static_cast<unsigned int>(i2>>15); @@ -3183,9 +3094,7 @@ APFloat::initFromF80LongDoubleAPInt(const APInt &api) } } -void -APFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) -{ +void IEEEFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) { assert(api.getBitWidth()==128); uint64_t i1 = api.getRawData()[0]; uint64_t i2 = api.getRawData()[1]; @@ -3194,14 +3103,14 @@ APFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) // Get the first double and convert to our format. initFromDoubleAPInt(APInt(64, i1)); - fs = convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo); + fs = convert(semPPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo); assert(fs == opOK && !losesInfo); (void)fs; // Unless we have a special case, add in second double. if (isFiniteNonZero()) { - APFloat v(IEEEdouble, APInt(64, i2)); - fs = v.convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo); + IEEEFloat v(semIEEEdouble, APInt(64, i2)); + fs = v.convert(semPPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo); assert(fs == opOK && !losesInfo); (void)fs; @@ -3209,9 +3118,7 @@ APFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) } } -void -APFloat::initFromQuadrupleAPInt(const APInt &api) -{ +void IEEEFloat::initFromQuadrupleAPInt(const APInt &api) { assert(api.getBitWidth()==128); uint64_t i1 = api.getRawData()[0]; uint64_t i2 = api.getRawData()[1]; @@ -3219,7 +3126,7 @@ APFloat::initFromQuadrupleAPInt(const APInt &api) uint64_t mysignificand = i1; uint64_t mysignificand2 = i2 & 0xffffffffffffLL; - initialize(&APFloat::IEEEquad); + initialize(&semIEEEquad); assert(partCount()==2); sign = static_cast<unsigned int>(i2>>63); @@ -3249,15 +3156,13 @@ APFloat::initFromQuadrupleAPInt(const APInt &api) } } -void -APFloat::initFromDoubleAPInt(const APInt &api) -{ +void IEEEFloat::initFromDoubleAPInt(const APInt &api) { assert(api.getBitWidth()==64); uint64_t i = *api.getRawData(); uint64_t myexponent = (i >> 52) & 0x7ff; uint64_t mysignificand = i & 0xfffffffffffffLL; - initialize(&APFloat::IEEEdouble); + initialize(&semIEEEdouble); assert(partCount()==1); sign = static_cast<unsigned int>(i>>63); @@ -3282,15 +3187,13 @@ APFloat::initFromDoubleAPInt(const APInt &api) } } -void -APFloat::initFromFloatAPInt(const APInt & api) -{ +void IEEEFloat::initFromFloatAPInt(const APInt &api) { assert(api.getBitWidth()==32); uint32_t i = (uint32_t)*api.getRawData(); uint32_t myexponent = (i >> 23) & 0xff; uint32_t mysignificand = i & 0x7fffff; - initialize(&APFloat::IEEEsingle); + initialize(&semIEEEsingle); assert(partCount()==1); sign = i >> 31; @@ -3315,15 +3218,13 @@ APFloat::initFromFloatAPInt(const APInt & api) } } -void -APFloat::initFromHalfAPInt(const APInt & api) -{ +void IEEEFloat::initFromHalfAPInt(const APInt &api) { assert(api.getBitWidth()==16); uint32_t i = (uint32_t)*api.getRawData(); uint32_t myexponent = (i >> 10) & 0x1f; uint32_t mysignificand = i & 0x3ff; - initialize(&APFloat::IEEEhalf); + initialize(&semIEEEhalf); assert(partCount()==1); sign = i >> 15; @@ -3352,53 +3253,26 @@ APFloat::initFromHalfAPInt(const APInt & api) /// we infer the floating point type from the size of the APInt. The /// isIEEE argument distinguishes between PPC128 and IEEE128 (not meaningful /// when the size is anything else). -void -APFloat::initFromAPInt(const fltSemantics* Sem, const APInt& api) -{ - if (Sem == &IEEEhalf) +void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) { + if (Sem == &semIEEEhalf) return initFromHalfAPInt(api); - if (Sem == &IEEEsingle) + if (Sem == &semIEEEsingle) return initFromFloatAPInt(api); - if (Sem == &IEEEdouble) + if (Sem == &semIEEEdouble) return initFromDoubleAPInt(api); - if (Sem == &x87DoubleExtended) + if (Sem == &semX87DoubleExtended) return initFromF80LongDoubleAPInt(api); - if (Sem == &IEEEquad) + if (Sem == &semIEEEquad) return initFromQuadrupleAPInt(api); - if (Sem == &PPCDoubleDouble) + if (Sem == &semPPCDoubleDoubleImpl) return initFromPPCDoubleDoubleAPInt(api); llvm_unreachable(nullptr); } -APFloat -APFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) -{ - switch (BitWidth) { - case 16: - return APFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth)); - case 32: - return APFloat(IEEEsingle, APInt::getAllOnesValue(BitWidth)); - case 64: - return APFloat(IEEEdouble, APInt::getAllOnesValue(BitWidth)); - case 80: - return APFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth)); - case 128: - if (isIEEE) - return APFloat(IEEEquad, APInt::getAllOnesValue(BitWidth)); - return APFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth)); - default: - llvm_unreachable("Unknown floating bit width"); - } -} - -unsigned APFloat::getSizeInBits(const fltSemantics &Sem) { - return Sem.sizeInBits; -} - /// Make this number the largest magnitude normal number in the given /// semantics. -void APFloat::makeLargest(bool Negative) { +void IEEEFloat::makeLargest(bool Negative) { // We want (in interchange format): // sign = {Negative} // exponent = 1..10 @@ -3423,7 +3297,7 @@ void APFloat::makeLargest(bool Negative) { /// Make this number the smallest magnitude denormal number in the given /// semantics. -void APFloat::makeSmallest(bool Negative) { +void IEEEFloat::makeSmallest(bool Negative) { // We want (in interchange format): // sign = {Negative} // exponent = 0..0 @@ -3434,55 +3308,30 @@ void APFloat::makeSmallest(bool Negative) { APInt::tcSet(significandParts(), 1, partCount()); } - -APFloat APFloat::getLargest(const fltSemantics &Sem, bool Negative) { - // We want (in interchange format): - // sign = {Negative} - // exponent = 1..10 - // significand = 1..1 - APFloat Val(Sem, uninitialized); - Val.makeLargest(Negative); - return Val; -} - -APFloat APFloat::getSmallest(const fltSemantics &Sem, bool Negative) { - // We want (in interchange format): - // sign = {Negative} - // exponent = 0..0 - // significand = 0..01 - APFloat Val(Sem, uninitialized); - Val.makeSmallest(Negative); - return Val; -} - -APFloat APFloat::getSmallestNormalized(const fltSemantics &Sem, bool Negative) { - APFloat Val(Sem, uninitialized); - +void IEEEFloat::makeSmallestNormalized(bool Negative) { // We want (in interchange format): // sign = {Negative} // exponent = 0..0 // significand = 10..0 - Val.category = fcNormal; - Val.zeroSignificand(); - Val.sign = Negative; - Val.exponent = Sem.minExponent; - Val.significandParts()[partCountForBits(Sem.precision)-1] |= - (((integerPart) 1) << ((Sem.precision - 1) % integerPartWidth)); - - return Val; + category = fcNormal; + zeroSignificand(); + sign = Negative; + exponent = semantics->minExponent; + significandParts()[partCountForBits(semantics->precision) - 1] |= + (((integerPart)1) << ((semantics->precision - 1) % integerPartWidth)); } -APFloat::APFloat(const fltSemantics &Sem, const APInt &API) { +IEEEFloat::IEEEFloat(const fltSemantics &Sem, const APInt &API) { initFromAPInt(&Sem, API); } -APFloat::APFloat(float f) { - initFromAPInt(&IEEEsingle, APInt::floatToBits(f)); +IEEEFloat::IEEEFloat(float f) { + initFromAPInt(&semIEEEsingle, APInt::floatToBits(f)); } -APFloat::APFloat(double d) { - initFromAPInt(&IEEEdouble, APInt::doubleToBits(d)); +IEEEFloat::IEEEFloat(double d) { + initFromAPInt(&semIEEEdouble, APInt::doubleToBits(d)); } namespace { @@ -3569,9 +3418,8 @@ namespace { } } -void APFloat::toString(SmallVectorImpl<char> &Str, - unsigned FormatPrecision, - unsigned FormatMaxPadding) const { +void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, + unsigned FormatMaxPadding) const { switch (category) { case fcInfinity: if (isNegative()) @@ -3772,7 +3620,7 @@ void APFloat::toString(SmallVectorImpl<char> &Str, Str.push_back(buffer[NDigits-I-1]); } -bool APFloat::getExactInverse(APFloat *inv) const { +bool IEEEFloat::getExactInverse(IEEEFloat *inv) const { // Special floats and denormals have no exact inverse. if (!isFiniteNonZero()) return false; @@ -3783,7 +3631,7 @@ bool APFloat::getExactInverse(APFloat *inv) const { return false; // Get the inverse. - APFloat reciprocal(*semantics, 1ULL); + IEEEFloat reciprocal(*semantics, 1ULL); if (reciprocal.divide(*this, rmNearestTiesToEven) != opOK) return false; @@ -3801,7 +3649,7 @@ bool APFloat::getExactInverse(APFloat *inv) const { return true; } -bool APFloat::isSignaling() const { +bool IEEEFloat::isSignaling() const { if (!isNaN()) return false; @@ -3814,7 +3662,7 @@ bool APFloat::isSignaling() const { /// /// *NOTE* since nextDown(x) = -nextUp(-x), we only implement nextUp with /// appropriate sign switching before/after the computation. -APFloat::opStatus APFloat::next(bool nextDown) { +IEEEFloat::opStatus IEEEFloat::next(bool nextDown) { // If we are performing nextDown, swap sign so we have -x. if (nextDown) changeSign(); @@ -3930,46 +3778,44 @@ APFloat::opStatus APFloat::next(bool nextDown) { return result; } -void -APFloat::makeInf(bool Negative) { +void IEEEFloat::makeInf(bool Negative) { category = fcInfinity; sign = Negative; exponent = semantics->maxExponent + 1; APInt::tcSet(significandParts(), 0, partCount()); } -void -APFloat::makeZero(bool Negative) { +void IEEEFloat::makeZero(bool Negative) { category = fcZero; sign = Negative; exponent = semantics->minExponent-1; APInt::tcSet(significandParts(), 0, partCount()); } -void APFloat::makeQuiet() { +void IEEEFloat::makeQuiet() { assert(isNaN()); APInt::tcSetBit(significandParts(), semantics->precision - 2); } -int llvm::ilogb(const APFloat &Arg) { +int ilogb(const IEEEFloat &Arg) { if (Arg.isNaN()) - return APFloat::IEK_NaN; + return IEEEFloat::IEK_NaN; if (Arg.isZero()) - return APFloat::IEK_Zero; + return IEEEFloat::IEK_Zero; if (Arg.isInfinity()) - return APFloat::IEK_Inf; + return IEEEFloat::IEK_Inf; if (!Arg.isDenormal()) return Arg.exponent; - APFloat Normalized(Arg); + IEEEFloat Normalized(Arg); int SignificandBits = Arg.getSemantics().precision - 1; Normalized.exponent += SignificandBits; - Normalized.normalize(APFloat::rmNearestTiesToEven, lfExactlyZero); + Normalized.normalize(IEEEFloat::rmNearestTiesToEven, lfExactlyZero); return Normalized.exponent - SignificandBits; } -APFloat llvm::scalbn(APFloat X, int Exp, APFloat::roundingMode RoundingMode) { +IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode RoundingMode) { auto MaxExp = X.getSemantics().maxExponent; auto MinExp = X.getSemantics().minExponent; @@ -3990,21 +3836,359 @@ APFloat llvm::scalbn(APFloat X, int Exp, APFloat::roundingMode RoundingMode) { return X; } -APFloat llvm::frexp(const APFloat &Val, int &Exp, APFloat::roundingMode RM) { +IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM) { Exp = ilogb(Val); // Quiet signalling nans. - if (Exp == APFloat::IEK_NaN) { - APFloat Quiet(Val); + if (Exp == IEEEFloat::IEK_NaN) { + IEEEFloat Quiet(Val); Quiet.makeQuiet(); return Quiet; } - if (Exp == APFloat::IEK_Inf) + if (Exp == IEEEFloat::IEK_Inf) return Val; // 1 is added because frexp is defined to return a normalized fraction in // +/-[0.5, 1.0), rather than the usual +/-[1.0, 2.0). - Exp = Exp == APFloat::IEK_Zero ? 0 : Exp + 1; + Exp = Exp == IEEEFloat::IEK_Zero ? 0 : Exp + 1; return scalbn(Val, -Exp, RM); } + +DoubleAPFloat::DoubleAPFloat(const fltSemantics &S) + : Semantics(&S), Floats(new APFloat[2]{APFloat(semPPCDoubleDoubleImpl), + APFloat(semIEEEdouble)}) { + assert(Semantics == &semPPCDoubleDouble); +} + +DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, uninitializedTag) + : Semantics(&S), + Floats(new APFloat[2]{APFloat(semPPCDoubleDoubleImpl, uninitialized), + APFloat(semIEEEdouble, uninitialized)}) { + assert(Semantics == &semPPCDoubleDouble); +} + +DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, integerPart I) + : Semantics(&S), Floats(new APFloat[2]{APFloat(semPPCDoubleDoubleImpl, I), + APFloat(semIEEEdouble)}) { + assert(Semantics == &semPPCDoubleDouble); +} + +DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, const APInt &I) + : Semantics(&S), Floats(new APFloat[2]{ + APFloat(semPPCDoubleDoubleImpl, I), + APFloat(semIEEEdouble, APInt(64, I.getRawData()[1]))}) { + assert(Semantics == &semPPCDoubleDouble); +} + +DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, APFloat &&First, + APFloat &&Second) + : Semantics(&S), + Floats(new APFloat[2]{std::move(First), std::move(Second)}) { + assert(Semantics == &semPPCDoubleDouble); + // TODO Check for First == &IEEEdouble once the transition is done. + assert(&Floats[0].getSemantics() == &semPPCDoubleDoubleImpl || + &Floats[0].getSemantics() == &semIEEEdouble); + assert(&Floats[1].getSemantics() == &semIEEEdouble); +} + +DoubleAPFloat::DoubleAPFloat(const DoubleAPFloat &RHS) + : Semantics(RHS.Semantics), + Floats(RHS.Floats ? new APFloat[2]{APFloat(RHS.Floats[0]), + APFloat(RHS.Floats[1])} + : nullptr) { + assert(Semantics == &semPPCDoubleDouble); +} + +DoubleAPFloat::DoubleAPFloat(DoubleAPFloat &&RHS) + : Semantics(RHS.Semantics), Floats(std::move(RHS.Floats)) { + RHS.Semantics = &semBogus; + assert(Semantics == &semPPCDoubleDouble); +} + +DoubleAPFloat &DoubleAPFloat::operator=(const DoubleAPFloat &RHS) { + if (Semantics == RHS.Semantics && RHS.Floats) { + Floats[0] = RHS.Floats[0]; + Floats[1] = RHS.Floats[1]; + } else if (this != &RHS) { + this->~DoubleAPFloat(); + new (this) DoubleAPFloat(RHS); + } + return *this; +} + +// "Software for Doubled-Precision Floating-Point Computations", +// by Seppo Linnainmaa, ACM TOMS vol 7 no 3, September 1981, pages 272-283. +APFloat::opStatus DoubleAPFloat::addImpl(const APFloat &a, const APFloat &aa, + const APFloat &c, const APFloat &cc, + roundingMode RM) { + int Status = opOK; + APFloat z = a; + Status |= z.add(c, RM); + if (!z.isFinite()) { + if (!z.isInfinity()) { + Floats[0] = std::move(z); + Floats[1].makeZero(false); + return (opStatus)Status; + } + Status = opOK; + auto AComparedToC = a.compareAbsoluteValue(c); + z = cc; + Status |= z.add(aa, RM); + if (AComparedToC == APFloat::cmpGreaterThan) { + // z = cc + aa + c + a; + Status |= z.add(c, RM); + Status |= z.add(a, RM); + } else { + // z = cc + aa + a + c; + Status |= z.add(a, RM); + Status |= z.add(c, RM); + } + if (!z.isFinite()) { + Floats[0] = std::move(z); + Floats[1].makeZero(false); + return (opStatus)Status; + } + Floats[0] = z; + APFloat zz = aa; + Status |= zz.add(cc, RM); + if (AComparedToC == APFloat::cmpGreaterThan) { + // Floats[1] = a - z + c + zz; + Floats[1] = a; + Status |= Floats[1].subtract(z, RM); + Status |= Floats[1].add(c, RM); + Status |= Floats[1].add(zz, RM); + } else { + // Floats[1] = c - z + a + zz; + Floats[1] = c; + Status |= Floats[1].subtract(z, RM); + Status |= Floats[1].add(a, RM); + Status |= Floats[1].add(zz, RM); + } + } else { + // q = a - z; + APFloat q = a; + Status |= q.subtract(z, RM); + + // zz = q + c + (a - (q + z)) + aa + cc; + // Compute a - (q + z) as -((q + z) - a) to avoid temporary copies. + auto zz = q; + Status |= zz.add(c, RM); + Status |= q.add(z, RM); + Status |= q.subtract(a, RM); + q.changeSign(); + Status |= zz.add(q, RM); + Status |= zz.add(aa, RM); + Status |= zz.add(cc, RM); + if (zz.isZero() && !zz.isNegative()) { + Floats[0] = std::move(z); + Floats[1].makeZero(false); + return opOK; + } + Floats[0] = z; + Status |= Floats[0].add(zz, RM); + if (!Floats[0].isFinite()) { + Floats[1].makeZero(false); + return (opStatus)Status; + } + Floats[1] = std::move(z); + Status |= Floats[1].subtract(Floats[0], RM); + Status |= Floats[1].add(zz, RM); + } + return (opStatus)Status; +} + +APFloat::opStatus DoubleAPFloat::addWithSpecial(const DoubleAPFloat &LHS, + const DoubleAPFloat &RHS, + DoubleAPFloat &Out, + roundingMode RM) { + if (LHS.getCategory() == fcNaN) { + Out = LHS; + return opOK; + } + if (RHS.getCategory() == fcNaN) { + Out = RHS; + return opOK; + } + if (LHS.getCategory() == fcZero) { + Out = RHS; + return opOK; + } + if (RHS.getCategory() == fcZero) { + Out = LHS; + return opOK; + } + if (LHS.getCategory() == fcInfinity && RHS.getCategory() == fcInfinity && + LHS.isNegative() != RHS.isNegative()) { + Out.makeNaN(false, Out.isNegative(), nullptr); + return opInvalidOp; + } + if (LHS.getCategory() == fcInfinity) { + Out = LHS; + return opOK; + } + if (RHS.getCategory() == fcInfinity) { + Out = RHS; + return opOK; + } + assert(LHS.getCategory() == fcNormal && RHS.getCategory() == fcNormal); + + // These conversions will go away once PPCDoubleDoubleImpl goes away. + // (PPCDoubleDoubleImpl, IEEEDouble) -> (IEEEDouble, IEEEDouble) + APFloat A(semIEEEdouble, + APInt(64, LHS.Floats[0].bitcastToAPInt().getRawData()[0])), + AA(LHS.Floats[1]), + C(semIEEEdouble, APInt(64, RHS.Floats[0].bitcastToAPInt().getRawData()[0])), + CC(RHS.Floats[1]); + assert(&AA.getSemantics() == &semIEEEdouble); + assert(&CC.getSemantics() == &semIEEEdouble); + Out.Floats[0] = APFloat(semIEEEdouble); + assert(&Out.Floats[1].getSemantics() == &semIEEEdouble); + + auto Ret = Out.addImpl(A, AA, C, CC, RM); + + // (IEEEDouble, IEEEDouble) -> (PPCDoubleDoubleImpl, IEEEDouble) + uint64_t Buffer[] = {Out.Floats[0].bitcastToAPInt().getRawData()[0], + Out.Floats[1].bitcastToAPInt().getRawData()[0]}; + Out.Floats[0] = APFloat(semPPCDoubleDoubleImpl, APInt(128, 2, Buffer)); + return Ret; +} + +APFloat::opStatus DoubleAPFloat::add(const DoubleAPFloat &RHS, + roundingMode RM) { + return addWithSpecial(*this, RHS, *this, RM); +} + +APFloat::opStatus DoubleAPFloat::subtract(const DoubleAPFloat &RHS, + roundingMode RM) { + changeSign(); + auto Ret = add(RHS, RM); + changeSign(); + return Ret; +} + +void DoubleAPFloat::changeSign() { + Floats[0].changeSign(); + Floats[1].changeSign(); +} + +APFloat::cmpResult +DoubleAPFloat::compareAbsoluteValue(const DoubleAPFloat &RHS) const { + auto Result = Floats[0].compareAbsoluteValue(RHS.Floats[0]); + if (Result != cmpEqual) + return Result; + Result = Floats[1].compareAbsoluteValue(RHS.Floats[1]); + if (Result == cmpLessThan || Result == cmpGreaterThan) { + auto Against = Floats[0].isNegative() ^ Floats[1].isNegative(); + auto RHSAgainst = RHS.Floats[0].isNegative() ^ RHS.Floats[1].isNegative(); + if (Against && !RHSAgainst) + return cmpLessThan; + if (!Against && RHSAgainst) + return cmpGreaterThan; + if (!Against && !RHSAgainst) + return Result; + if (Against && RHSAgainst) + return (cmpResult)(cmpLessThan + cmpGreaterThan - Result); + } + return Result; +} + +APFloat::fltCategory DoubleAPFloat::getCategory() const { + return Floats[0].getCategory(); +} + +bool DoubleAPFloat::isNegative() const { return Floats[0].isNegative(); } + +void DoubleAPFloat::makeInf(bool Neg) { + Floats[0].makeInf(Neg); + Floats[1].makeZero(false); +} + +void DoubleAPFloat::makeNaN(bool SNaN, bool Neg, const APInt *fill) { + Floats[0].makeNaN(SNaN, Neg, fill); + Floats[1].makeZero(false); +} + +} // End detail namespace + +APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) { + if (usesLayout<IEEEFloat>(Semantics)) { + new (&IEEE) IEEEFloat(std::move(F)); + return; + } + if (usesLayout<DoubleAPFloat>(Semantics)) { + new (&Double) + DoubleAPFloat(Semantics, APFloat(std::move(F), F.getSemantics()), + APFloat(semIEEEdouble)); + return; + } + llvm_unreachable("Unexpected semantics"); +} + +APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) { + return getIEEE().convertFromString(Str, RM); +} + +hash_code hash_value(const APFloat &Arg) { return hash_value(Arg.getIEEE()); } + +APFloat::APFloat(const fltSemantics &Semantics, StringRef S) + : APFloat(Semantics) { + convertFromString(S, rmNearestTiesToEven); +} + +APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics, + roundingMode RM, bool *losesInfo) { + if (&getSemantics() == &ToSemantics) + return opOK; + if (usesLayout<IEEEFloat>(getSemantics()) && + usesLayout<IEEEFloat>(ToSemantics)) + return U.IEEE.convert(ToSemantics, RM, losesInfo); + if (usesLayout<IEEEFloat>(getSemantics()) && + usesLayout<DoubleAPFloat>(ToSemantics)) { + assert(&ToSemantics == &semPPCDoubleDouble); + auto Ret = U.IEEE.convert(semPPCDoubleDoubleImpl, RM, losesInfo); + *this = APFloat(DoubleAPFloat(semPPCDoubleDouble, std::move(*this), + APFloat(semIEEEdouble)), + ToSemantics); + return Ret; + } + if (usesLayout<DoubleAPFloat>(getSemantics()) && + usesLayout<IEEEFloat>(ToSemantics)) { + auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo); + *this = APFloat(std::move(getIEEE()), ToSemantics); + return Ret; + } + llvm_unreachable("Unexpected semantics"); +} + +APFloat APFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) { + if (isIEEE) { + switch (BitWidth) { + case 16: + return APFloat(semIEEEhalf, APInt::getAllOnesValue(BitWidth)); + case 32: + return APFloat(semIEEEsingle, APInt::getAllOnesValue(BitWidth)); + case 64: + return APFloat(semIEEEdouble, APInt::getAllOnesValue(BitWidth)); + case 80: + return APFloat(semX87DoubleExtended, APInt::getAllOnesValue(BitWidth)); + case 128: + return APFloat(semIEEEquad, APInt::getAllOnesValue(BitWidth)); + default: + llvm_unreachable("Unknown floating bit width"); + } + } else { + assert(BitWidth == 128); + return APFloat(semPPCDoubleDouble, APInt::getAllOnesValue(BitWidth)); + } +} + +void APFloat::print(raw_ostream &OS) const { + SmallVector<char, 16> Buffer; + toString(Buffer); + OS << Buffer << "\n"; +} + +void APFloat::dump() const { print(dbgs()); } + +} // End llvm namespace diff --git a/contrib/llvm/lib/Support/APInt.cpp b/contrib/llvm/lib/Support/APInt.cpp index 66eee99..fb8b451 100644 --- a/contrib/llvm/lib/Support/APInt.cpp +++ b/contrib/llvm/lib/Support/APInt.cpp @@ -22,10 +22,10 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include <climits> #include <cmath> #include <cstdlib> #include <cstring> -#include <limits> using namespace llvm; #define DEBUG_TYPE "apint" @@ -205,7 +205,7 @@ APInt& APInt::operator++() { /// This function subtracts a single "digit" (64-bit word), y, from /// the multi-digit integer array, x[], propagating the borrowed 1 value until -/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// no further borrowing is needed or it runs out of "digits" in x. The result /// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. /// In other words, if y > x then this function returns 1, otherwise 0. /// @returns the borrow out of the subtraction @@ -260,6 +260,14 @@ APInt& APInt::operator+=(const APInt& RHS) { return clearUnusedBits(); } +APInt& APInt::operator+=(uint64_t RHS) { + if (isSingleWord()) + VAL += RHS; + else + add_1(pVal, pVal, getNumWords(), RHS); + return clearUnusedBits(); +} + /// Subtracts the integer array y from the integer array x /// @returns returns the borrow out. /// @brief Generalized subtraction of 64-bit integer arrays. @@ -286,6 +294,14 @@ APInt& APInt::operator-=(const APInt& RHS) { return clearUnusedBits(); } +APInt& APInt::operator-=(uint64_t RHS) { + if (isSingleWord()) + VAL -= RHS; + else + sub_1(pVal, getNumWords(), RHS); + return clearUnusedBits(); +} + /// Multiplies an integer array, x, by a uint64_t integer and places the result /// into dest. /// @returns the carry out of the multiplication. @@ -470,44 +486,6 @@ APInt APInt::operator*(const APInt& RHS) const { return Result; } -APInt APInt::operator+(const APInt& RHS) const { - assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); - if (isSingleWord()) - return APInt(BitWidth, VAL + RHS.VAL); - APInt Result(BitWidth, 0); - add(Result.pVal, this->pVal, RHS.pVal, getNumWords()); - Result.clearUnusedBits(); - return Result; -} - -APInt APInt::operator+(uint64_t RHS) const { - if (isSingleWord()) - return APInt(BitWidth, VAL + RHS); - APInt Result(*this); - add_1(Result.pVal, Result.pVal, getNumWords(), RHS); - Result.clearUnusedBits(); - return Result; -} - -APInt APInt::operator-(const APInt& RHS) const { - assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); - if (isSingleWord()) - return APInt(BitWidth, VAL - RHS.VAL); - APInt Result(BitWidth, 0); - sub(Result.pVal, this->pVal, RHS.pVal, getNumWords()); - Result.clearUnusedBits(); - return Result; -} - -APInt APInt::operator-(uint64_t RHS) const { - if (isSingleWord()) - return APInt(BitWidth, VAL - RHS); - APInt Result(*this); - sub_1(Result.pVal, getNumWords(), RHS); - Result.clearUnusedBits(); - return Result; -} - bool APInt::EqualSlowCase(const APInt& RHS) const { return std::equal(pVal, pVal + getNumWords(), RHS.pVal); } @@ -1064,11 +1042,7 @@ APInt APInt::ashr(unsigned shiftAmt) const { if (isSingleWord()) { if (shiftAmt == BitWidth) return APInt(BitWidth, 0); // undefined - else { - unsigned SignBit = APINT_BITS_PER_WORD - BitWidth; - return APInt(BitWidth, - (((int64_t(VAL) << SignBit) >> SignBit) >> shiftAmt)); - } + return APInt(BitWidth, SignExtend64(VAL, BitWidth) >> shiftAmt); } // If all the bits were shifted out, the result is, technically, undefined. @@ -1521,7 +1495,7 @@ static void KnuthDiv(unsigned *u, unsigned *v, unsigned *q, unsigned* r, assert(n>1 && "n must be > 1"); // b denotes the base of the number system. In our case b is 2^32. - LLVM_CONSTEXPR uint64_t b = uint64_t(1) << 32; + const uint64_t b = uint64_t(1) << 32; DEBUG(dbgs() << "KnuthDiv: m=" << m << " n=" << n << '\n'); DEBUG(dbgs() << "KnuthDiv: original:"); diff --git a/contrib/llvm/lib/Support/ARMBuildAttrs.cpp b/contrib/llvm/lib/Support/ARMBuildAttrs.cpp index 6d34f76..134ef8b 100644 --- a/contrib/llvm/lib/Support/ARMBuildAttrs.cpp +++ b/contrib/llvm/lib/Support/ARMBuildAttrs.cpp @@ -15,7 +15,7 @@ using namespace llvm; namespace { const struct { ARMBuildAttrs::AttrType Attr; - const char *TagName; + StringRef TagName; } ARMAttributeTags[] = { { ARMBuildAttrs::File, "Tag_File" }, { ARMBuildAttrs::Section, "Tag_Section" }, @@ -78,17 +78,23 @@ StringRef AttrTypeAsString(unsigned Attr, bool HasTagPrefix) { StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix) { for (unsigned TI = 0, TE = sizeof(ARMAttributeTags) / sizeof(*ARMAttributeTags); TI != TE; ++TI) - if (ARMAttributeTags[TI].Attr == Attr) - return ARMAttributeTags[TI].TagName + (HasTagPrefix ? 0 : 4); + if (ARMAttributeTags[TI].Attr == Attr) { + auto TagName = ARMAttributeTags[TI].TagName; + return HasTagPrefix ? TagName : TagName.drop_front(4); + } return ""; } int AttrTypeFromString(StringRef Tag) { bool HasTagPrefix = Tag.startswith("Tag_"); - for (unsigned TI = 0, TE = sizeof(ARMAttributeTags) / sizeof(*ARMAttributeTags); - TI != TE; ++TI) - if (StringRef(ARMAttributeTags[TI].TagName + (HasTagPrefix ? 0 : 4)) == Tag) + for (unsigned TI = 0, + TE = sizeof(ARMAttributeTags) / sizeof(*ARMAttributeTags); + TI != TE; ++TI) { + auto TagName = ARMAttributeTags[TI].TagName; + if (TagName.drop_front(HasTagPrefix ? 0 : 4) == Tag) { return ARMAttributeTags[TI].Attr; + } + } return -1; } } diff --git a/contrib/llvm/lib/Support/CachePruning.cpp b/contrib/llvm/lib/Support/CachePruning.cpp index bd42bef..3831625 100644 --- a/contrib/llvm/lib/Support/CachePruning.cpp +++ b/contrib/llvm/lib/Support/CachePruning.cpp @@ -22,6 +22,7 @@ #define DEBUG_TYPE "cache-pruning" #include <set> +#include <system_error> using namespace llvm; @@ -34,6 +35,8 @@ static void writeTimestampFile(StringRef TimestampFile) { /// Prune the cache of files that haven't been accessed in a long time. bool CachePruning::prune() { + using namespace std::chrono; + if (Path.empty()) return false; @@ -44,7 +47,7 @@ bool CachePruning::prune() { if (!isPathDir) return false; - if (Expiration == 0 && PercentageOfAvailableSpace == 0) { + if (Expiration == seconds(0) && PercentageOfAvailableSpace == 0) { DEBUG(dbgs() << "No pruning settings set, exit early\n"); // Nothing will be pruned, early exit return false; @@ -54,7 +57,7 @@ bool CachePruning::prune() { SmallString<128> TimestampFile(Path); sys::path::append(TimestampFile, "llvmcache.timestamp"); sys::fs::file_status FileStatus; - sys::TimeValue CurrentTime = sys::TimeValue::now(); + const auto CurrentTime = system_clock::now(); if (auto EC = sys::fs::status(TimestampFile, FileStatus)) { if (EC == errc::no_such_file_or_directory) { // If the timestamp file wasn't there, create one now. @@ -64,14 +67,14 @@ bool CachePruning::prune() { return false; } } else { - if (Interval) { + if (Interval == seconds(0)) { // Check whether the time stamp is older than our pruning interval. // If not, do nothing. - sys::TimeValue TimeStampModTime = FileStatus.getLastModificationTime(); - auto TimeInterval = sys::TimeValue(sys::TimeValue::SecondsType(Interval)); + const auto TimeStampModTime = FileStatus.getLastModificationTime(); auto TimeStampAge = CurrentTime - TimeStampModTime; - if (TimeStampAge <= TimeInterval) { - DEBUG(dbgs() << "Timestamp file too recent (" << TimeStampAge.seconds() + if (TimeStampAge <= Interval) { + DEBUG(dbgs() << "Timestamp file too recent (" + << duration_cast<seconds>(TimeStampAge).count() << "s old), do not prune.\n"); return false; } @@ -102,7 +105,6 @@ bool CachePruning::prune() { std::error_code EC; SmallString<128> CachePathNative; sys::path::native(Path, CachePathNative); - auto TimeExpiration = sys::TimeValue(sys::TimeValue::SecondsType(Expiration)); // Walk all of the files within this directory. for (sys::fs::directory_iterator File(CachePathNative, EC), FileEnd; File != FileEnd && !EC; File.increment(EC)) { @@ -118,11 +120,11 @@ bool CachePruning::prune() { } // If the file hasn't been used recently enough, delete it - sys::TimeValue FileAccessTime = FileStatus.getLastAccessedTime(); + const auto FileAccessTime = FileStatus.getLastAccessedTime(); auto FileAge = CurrentTime - FileAccessTime; - if (FileAge > TimeExpiration) { - DEBUG(dbgs() << "Remove " << File->path() << " (" << FileAge.seconds() - << "s old)\n"); + if (FileAge > Expiration) { + DEBUG(dbgs() << "Remove " << File->path() << " (" + << duration_cast<seconds>(FileAge).count() << "s old)\n"); sys::fs::remove(File->path()); continue; } diff --git a/contrib/llvm/lib/Support/Chrono.cpp b/contrib/llvm/lib/Support/Chrono.cpp new file mode 100644 index 0000000..cdadbd8 --- /dev/null +++ b/contrib/llvm/lib/Support/Chrono.cpp @@ -0,0 +1,47 @@ +//===- Support/Chrono.cpp - Utilities for Timing Manipulation ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Chrono.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +using namespace sys; + +static inline struct tm getStructTM(TimePoint<> TP) { + struct tm Storage; + std::time_t OurTime = toTimeT(TP); + +#if defined(LLVM_ON_UNIX) + struct tm *LT = ::localtime_r(&OurTime, &Storage); + assert(LT); + (void)LT; +#endif +#if defined(LLVM_ON_WIN32) + int Error = ::localtime_s(&Storage, &OurTime); + assert(!Error); + (void)Error; +#endif + + return Storage; +} + +raw_ostream &operator<<(raw_ostream &OS, TimePoint<> TP) { + struct tm LT = getStructTM(TP); + char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")]; + strftime(Buffer, sizeof(Buffer), "%Y-%m-%d %H:%M:%S", <); + return OS << Buffer << '.' + << format("%.9lu", + long((TP.time_since_epoch() % std::chrono::seconds(1)) + .count())); +} + +} // namespace llvm diff --git a/contrib/llvm/lib/Support/CommandLine.cpp b/contrib/llvm/lib/Support/CommandLine.cpp index a5d2ba2..3889902 100644 --- a/contrib/llvm/lib/Support/CommandLine.cpp +++ b/contrib/llvm/lib/Support/CommandLine.cpp @@ -20,6 +20,7 @@ #include "llvm-c/Support.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -29,10 +30,12 @@ #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include "llvm/Support/StringSaver.h" #include "llvm/Support/raw_ostream.h" #include <cstdlib> @@ -42,6 +45,17 @@ using namespace cl; #define DEBUG_TYPE "commandline" +#if LLVM_ENABLE_ABI_BREAKING_CHECKS +namespace llvm { +// If LLVM_ENABLE_ABI_BREAKING_CHECKS is set the flag -mllvm -reverse-iterate +// can be used to toggle forward/reverse iteration of unordered containers. +// This will help uncover differences in codegen caused due to undefined +// iteration order. +static cl::opt<bool, true> ReverseIteration("reverse-iterate", + cl::location(ReverseIterate<bool>::value)); +} +#endif + //===----------------------------------------------------------------------===// // Template instantiations and anchors. // @@ -90,10 +104,10 @@ public: // Globals for name and overview of program. Program name is not a string to // avoid static ctor/dtor issues. std::string ProgramName; - const char *ProgramOverview; + StringRef ProgramOverview; // This collects additional help to be printed. - std::vector<const char *> MoreHelp; + std::vector<StringRef> MoreHelp; // This collects the different option categories that have been registered. SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories; @@ -101,7 +115,7 @@ public: // This collects the different subcommands that have been registered. SmallPtrSet<SubCommand *, 4> RegisteredSubCommands; - CommandLineParser() : ProgramOverview(nullptr), ActiveSubCommand(nullptr) { + CommandLineParser() : ActiveSubCommand(nullptr) { registerSubCommand(&*TopLevelSubCommand); registerSubCommand(&*AllSubCommands); } @@ -109,9 +123,9 @@ public: void ResetAllOptionOccurrences(); bool ParseCommandLineOptions(int argc, const char *const *argv, - const char *Overview, bool IgnoreErrors); + StringRef Overview, bool IgnoreErrors); - void addLiteralOption(Option &Opt, SubCommand *SC, const char *Name) { + void addLiteralOption(Option &Opt, SubCommand *SC, StringRef Name) { if (Opt.hasArgStr()) return; if (!SC->OptionsMap.insert(std::make_pair(Name, &Opt)).second) { @@ -131,7 +145,7 @@ public: } } - void addLiteralOption(Option &Opt, const char *Name) { + void addLiteralOption(Option &Opt, StringRef Name) { if (Opt.Subs.empty()) addLiteralOption(Opt, &*TopLevelSubCommand, Name); else { @@ -283,7 +297,7 @@ public: void registerSubCommand(SubCommand *sub) { assert(count_if(RegisteredSubCommands, [sub](const SubCommand *Sub) { - return (sub->getName() != nullptr) && + return (!sub->getName().empty()) && (Sub->getName() == sub->getName()); }) == 0 && "Duplicate subcommands"); @@ -298,7 +312,7 @@ public: O->hasArgStr()) addOption(O, sub); else - addLiteralOption(*O, sub, E.first().str().c_str()); + addLiteralOption(*O, sub, E.first()); } } } @@ -307,10 +321,16 @@ public: RegisteredSubCommands.erase(sub); } + iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator> + getRegisteredSubcommands() { + return make_range(RegisteredSubCommands.begin(), + RegisteredSubCommands.end()); + } + void reset() { ActiveSubCommand = nullptr; ProgramName.clear(); - ProgramOverview = nullptr; + ProgramOverview = StringRef(); MoreHelp.clear(); RegisteredOptionCategories.clear(); @@ -328,18 +348,18 @@ private: SubCommand *ActiveSubCommand; Option *LookupOption(SubCommand &Sub, StringRef &Arg, StringRef &Value); - SubCommand *LookupSubCommand(const char *Name); + SubCommand *LookupSubCommand(StringRef Name); }; } // namespace static ManagedStatic<CommandLineParser> GlobalParser; -void cl::AddLiteralOption(Option &O, const char *Name) { +void cl::AddLiteralOption(Option &O, StringRef Name) { GlobalParser->addLiteralOption(O, Name); } -extrahelp::extrahelp(const char *Help) : morehelp(Help) { +extrahelp::extrahelp(StringRef Help) : morehelp(Help) { GlobalParser->MoreHelp.push_back(Help); } @@ -353,6 +373,7 @@ void Option::removeArgument() { GlobalParser->removeOption(this); } void Option::setArgStr(StringRef S) { if (FullyInitialized) GlobalParser->updateArgStr(this, S); + assert((S.empty() || S[0] != '-') && "Option can't start with '-"); ArgStr = S; } @@ -426,13 +447,13 @@ Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg, return I->second; } -SubCommand *CommandLineParser::LookupSubCommand(const char *Name) { - if (Name == nullptr) +SubCommand *CommandLineParser::LookupSubCommand(StringRef Name) { + if (Name.empty()) return &*TopLevelSubCommand; for (auto S : RegisteredSubCommands) { if (S == &*AllSubCommands) continue; - if (S->getName() == nullptr) + if (S->getName().empty()) continue; if (StringRef(S->getName()) == StringRef(Name)) @@ -505,7 +526,6 @@ static bool CommaSeparateAndAddOccurrence(Option *Handler, unsigned pos, return true; // Erase the portion before the comma, AND the comma. Val = Val.substr(Pos + 1); - Value.substr(Pos + 1); // Increment the original value pointer as well. // Check for another comma. Pos = Val.find(','); } @@ -533,7 +553,7 @@ static inline bool ProvideOption(Option *Handler, StringRef ArgName, return Handler->error("requires a value!"); // Steal the next argument, like for '-o filename' assert(argv && "null check"); - Value = argv[++i]; + Value = StringRef(argv[++i]); } break; case ValueDisallowed: @@ -567,7 +587,7 @@ static inline bool ProvideOption(Option *Handler, StringRef ArgName, if (i + 1 >= argc) return Handler->error("not enough values!"); assert(argv && "null check"); - Value = argv[++i]; + Value = StringRef(argv[++i]); if (CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value, MultiArg)) return true; @@ -725,7 +745,7 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, // End the token if this is whitespace. if (isWhitespace(Src[I])) { if (!Token.empty()) - NewArgv.push_back(Saver.save(Token.c_str())); + NewArgv.push_back(Saver.save(StringRef(Token)).data()); Token.clear(); continue; } @@ -736,7 +756,7 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, // Append the last token after hitting EOF with no whitespace. if (!Token.empty()) - NewArgv.push_back(Saver.save(Token.c_str())); + NewArgv.push_back(Saver.save(StringRef(Token)).data()); // Mark the end of response files if (MarkEOLs) NewArgv.push_back(nullptr); @@ -817,7 +837,7 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, if (State == UNQUOTED) { // Whitespace means the end of the token. if (isWhitespace(Src[I])) { - NewArgv.push_back(Saver.save(Token.c_str())); + NewArgv.push_back(Saver.save(StringRef(Token)).data()); Token.clear(); State = INIT; // Mark the end of lines in response files @@ -852,7 +872,7 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, } // Append the last token after hitting EOF with no whitespace. if (!Token.empty()) - NewArgv.push_back(Saver.save(Token.c_str())); + NewArgv.push_back(Saver.save(StringRef(Token)).data()); // Mark the end of response files if (MarkEOLs) NewArgv.push_back(nullptr); @@ -864,10 +884,10 @@ static bool hasUTF8ByteOrderMark(ArrayRef<char> S) { return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf'); } -static bool ExpandResponseFile(const char *FName, StringSaver &Saver, +static bool ExpandResponseFile(StringRef FName, StringSaver &Saver, TokenizerCallback Tokenizer, SmallVectorImpl<const char *> &NewArgv, - bool MarkEOLs = false) { + bool MarkEOLs, bool RelativeNames) { ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr = MemoryBuffer::getFile(FName); if (!MemBufOrErr) @@ -892,6 +912,30 @@ static bool ExpandResponseFile(const char *FName, StringSaver &Saver, // Tokenize the contents into NewArgv. Tokenizer(Str, Saver, NewArgv, MarkEOLs); + // 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(); + } + } + } + return true; } @@ -899,7 +943,7 @@ static bool ExpandResponseFile(const char *FName, StringSaver &Saver, /// StringSaver and tokenization strategy. bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, SmallVectorImpl<const char *> &Argv, - bool MarkEOLs) { + bool MarkEOLs, bool RelativeNames) { unsigned RspFiles = 0; bool AllExpanded = true; @@ -923,11 +967,9 @@ 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. - // FIXME: If a nested response file uses a relative path, is it relative to - // the cwd of the process or the response file? SmallVector<const char *, 0> ExpandedArgv; if (!ExpandResponseFile(Arg + 1, Saver, Tokenizer, ExpandedArgv, - MarkEOLs)) { + MarkEOLs, RelativeNames)) { // We couldn't read this file, so we leave it in the argument stream and // move on. AllExpanded = false; @@ -952,45 +994,26 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, assert(envVar && "Environment variable name missing"); // Get the environment variable they want us to parse options out of. -#ifdef _WIN32 - std::wstring wenvVar; - if (!llvm::ConvertUTF8toWide(envVar, wenvVar)) { - assert(false && - "Unicode conversion of environment variable name failed"); - return; - } - const wchar_t *wenvValue = _wgetenv(wenvVar.c_str()); - if (!wenvValue) - return; - std::string envValueBuffer; - if (!llvm::convertWideToUTF8(wenvValue, envValueBuffer)) { - assert(false && - "Unicode conversion of environment variable value failed"); - return; - } - const char *envValue = envValueBuffer.c_str(); -#else - const char *envValue = getenv(envVar); + llvm::Optional<std::string> envValue = sys::Process::GetEnv(StringRef(envVar)); if (!envValue) return; -#endif // Get program's "name", which we wouldn't know without the caller // telling us. SmallVector<const char *, 20> newArgv; BumpPtrAllocator A; StringSaver Saver(A); - newArgv.push_back(Saver.save(progName)); + newArgv.push_back(Saver.save(progName).data()); // Parse the value of the environment variable into a "command line" // and hand it off to ParseCommandLineOptions(). - TokenizeGNUCommandLine(envValue, Saver, newArgv); + TokenizeGNUCommandLine(*envValue, Saver, newArgv); int newArgc = static_cast<int>(newArgv.size()); - ParseCommandLineOptions(newArgc, &newArgv[0], Overview); + ParseCommandLineOptions(newArgc, &newArgv[0], StringRef(Overview)); } bool cl::ParseCommandLineOptions(int argc, const char *const *argv, - const char *Overview, bool IgnoreErrors) { + StringRef Overview, bool IgnoreErrors) { return GlobalParser->ParseCommandLineOptions(argc, argv, Overview, IgnoreErrors); } @@ -1006,7 +1029,7 @@ void CommandLineParser::ResetAllOptionOccurrences() { bool CommandLineParser::ParseCommandLineOptions(int argc, const char *const *argv, - const char *Overview, + StringRef Overview, bool IgnoreErrors) { assert(hasOptions() && "No options specified!"); @@ -1019,7 +1042,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, argc = static_cast<int>(newArgv.size()); // Copy the program name into ProgName, making sure not to overflow it. - ProgramName = sys::path::filename(argv[0]); + ProgramName = sys::path::filename(StringRef(argv[0])); ProgramOverview = Overview; bool ErrorParsing = false; @@ -1035,7 +1058,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, if (argc >= 2 && argv[FirstArg][0] != '-') { // If the first argument specifies a valid subcommand, start processing // options from the second argument. - ChosenSubCommand = LookupSubCommand(argv[FirstArg]); + ChosenSubCommand = LookupSubCommand(StringRef(argv[FirstArg])); if (ChosenSubCommand != &*TopLevelSubCommand) FirstArg = 2; } @@ -1116,19 +1139,19 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) { // Positional argument! if (ActivePositionalArg) { - ProvidePositionalOption(ActivePositionalArg, argv[i], i); + ProvidePositionalOption(ActivePositionalArg, StringRef(argv[i]), i); continue; // We are done! } if (!PositionalOpts.empty()) { - PositionalVals.push_back(std::make_pair(argv[i], i)); + PositionalVals.push_back(std::make_pair(StringRef(argv[i]), i)); // All of the positional arguments have been fulfulled, give the rest to // the consume after option... if it's specified... // if (PositionalVals.size() >= NumPositionalRequired && ConsumeAfterOpt) { for (++i; i < argc; ++i) - PositionalVals.push_back(std::make_pair(argv[i], i)); + PositionalVals.push_back(std::make_pair(StringRef(argv[i]), i)); break; // Handle outside of the argument processing loop... } @@ -1144,19 +1167,19 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, // If there is a positional argument eating options, check to see if this // option is another positional argument. If so, treat it as an argument, // otherwise feed it to the eating positional. - ArgName = argv[i] + 1; + ArgName = StringRef(argv[i] + 1); // Eat leading dashes. while (!ArgName.empty() && ArgName[0] == '-') ArgName = ArgName.substr(1); Handler = LookupOption(*ChosenSubCommand, ArgName, Value); if (!Handler || Handler->getFormattingFlag() != cl::Positional) { - ProvidePositionalOption(ActivePositionalArg, argv[i], i); + ProvidePositionalOption(ActivePositionalArg, StringRef(argv[i]), i); continue; // We are done! } } else { // We start with a '-', must be an argument. - ArgName = argv[i] + 1; + ArgName = StringRef(argv[i] + 1); // Eat leading dashes. while (!ArgName.empty() && ArgName[0] == '-') ArgName = ArgName.substr(1); @@ -1193,7 +1216,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, for (SmallVectorImpl<Option *>::iterator I = SinkOpts.begin(), E = SinkOpts.end(); I != E; ++I) - (*I)->addOccurrence(i, "", argv[i]); + (*I)->addOccurrence(i, "", StringRef(argv[i])); } continue; } @@ -1212,7 +1235,8 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, errs() << ProgramName << ": Not enough positional command line arguments specified!\n" << "Must specify at least " << NumPositionalRequired - << " positional arguments: See: " << argv[0] << " -help\n"; + << " positional argument" << (NumPositionalRequired > 1 ? "s" : "") + << ": See: " << argv[0] << " - help\n"; } ErrorParsing = true; @@ -1245,7 +1269,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, switch (PositionalOpts[i]->getNumOccurrencesFlag()) { case cl::Optional: Done = true; // Optional arguments want _at most_ one value - // FALL THROUGH + LLVM_FALLTHROUGH; case cl::ZeroOrMore: // Zero or more will take all they can get... case cl::OneOrMore: // One or more will take all they can get... ProvidePositionalOption(PositionalOpts[i], @@ -1299,7 +1323,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, Opt.second->error("must be specified at least once!"); ErrorParsing = true; } - // Fall through + LLVM_FALLTHROUGH; default: break; } @@ -1354,7 +1378,7 @@ bool Option::addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, case Required: if (NumOccurrences > 1) return error("must occur exactly one time!", ArgName); - // Fall through + LLVM_FALLTHROUGH; case OneOrMore: case ZeroOrMore: case ConsumeAfter: @@ -1406,7 +1430,8 @@ void alias::printOptionInfo(size_t GlobalWidth) const { // Return the width of the option tag for printing... size_t basic_parser_impl::getOptionWidth(const Option &O) const { size_t Len = O.ArgStr.size(); - if (const char *ValName = getValueName()) + auto ValName = getValueName(); + if (!ValName.empty()) Len += getValueStr(O, ValName).size() + 3; return Len + 6; @@ -1419,7 +1444,8 @@ void basic_parser_impl::printOptionInfo(const Option &O, size_t GlobalWidth) const { outs() << " -" << O.ArgStr; - if (const char *ValName = getValueName()) + auto ValName = getValueName(); + if (!ValName.empty()) outs() << "=<" << getValueStr(O, ValName) << '>'; printHelpStr(O.HelpStr, GlobalWidth, getOptionWidth(O)); @@ -1529,11 +1555,11 @@ bool parser<float>::parse(Option &O, StringRef ArgName, StringRef Arg, // findOption - Return the option number corresponding to the specified // argument string. If the option is not found, getNumOptions() is returned. // -unsigned generic_parser_base::findOption(const char *Name) { +unsigned generic_parser_base::findOption(StringRef Name) { unsigned e = getNumOptions(); for (unsigned i = 0; i != e; ++i) { - if (strcmp(getOption(i), Name) == 0) + if (getOption(i) == Name) return i; } return e; @@ -1544,12 +1570,12 @@ size_t generic_parser_base::getOptionWidth(const Option &O) const { if (O.hasArgStr()) { size_t Size = O.ArgStr.size() + 6; for (unsigned i = 0, e = getNumOptions(); i != e; ++i) - Size = std::max(Size, std::strlen(getOption(i)) + 8); + Size = std::max(Size, getOption(i).size() + 8); return Size; } else { size_t BaseSize = 0; for (unsigned i = 0, e = getNumOptions(); i != e; ++i) - BaseSize = std::max(BaseSize, std::strlen(getOption(i)) + 8); + BaseSize = std::max(BaseSize, getOption(i).size() + 8); return BaseSize; } } @@ -1564,7 +1590,7 @@ void generic_parser_base::printOptionInfo(const Option &O, printHelpStr(O.HelpStr, GlobalWidth, O.ArgStr.size() + 6); for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { - size_t NumSpaces = GlobalWidth - strlen(getOption(i)) - 8; + size_t NumSpaces = GlobalWidth - getOption(i).size() - 8; outs() << " =" << getOption(i); outs().indent(NumSpaces) << " - " << getDescription(i) << '\n'; } @@ -1572,9 +1598,9 @@ void generic_parser_base::printOptionInfo(const Option &O, if (!O.HelpStr.empty()) outs() << " " << O.HelpStr << '\n'; for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { - const char *Option = getOption(i); + auto Option = getOption(i); outs() << " -" << Option; - printHelpStr(getDescription(i), GlobalWidth, std::strlen(Option) + 8); + printHelpStr(getDescription(i), GlobalWidth, Option.size() + 8); } } } @@ -1596,7 +1622,7 @@ void generic_parser_base::printGenericOptionDiff( continue; outs() << "= " << getOption(i); - size_t L = std::strlen(getOption(i)); + size_t L = getOption(i).size(); size_t NumSpaces = MaxOptWidth > L ? MaxOptWidth - L : 0; outs().indent(NumSpaces) << " (default: "; for (unsigned j = 0; j != NumOpts; ++j) { @@ -1709,9 +1735,9 @@ static void sortSubCommands(const SmallPtrSetImpl<SubCommand *> &SubMap, SmallVectorImpl<std::pair<const char *, SubCommand *>> &Subs) { for (const auto &S : SubMap) { - if (S->getName() == nullptr) + if (S->getName().empty()) continue; - Subs.push_back(std::make_pair(S->getName(), S)); + Subs.push_back(std::make_pair(S->getName().data(), S)); } array_pod_sort(Subs.begin(), Subs.end(), SubNameCompare); } @@ -1734,7 +1760,7 @@ protected: void printSubCommands(StrSubCommandPairVector &Subs, size_t MaxSubLen) { for (const auto &S : Subs) { outs() << " " << S.first; - if (S.second->getDescription()) { + if (!S.second->getDescription().empty()) { outs().indent(MaxSubLen - strlen(S.first)); outs() << " - " << S.second->getDescription(); } @@ -1762,14 +1788,16 @@ public: StrSubCommandPairVector Subs; sortSubCommands(GlobalParser->RegisteredSubCommands, Subs); - if (GlobalParser->ProgramOverview) + if (!GlobalParser->ProgramOverview.empty()) outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n"; - if (Sub == &*TopLevelSubCommand) - outs() << "USAGE: " << GlobalParser->ProgramName - << " [subcommand] [options]"; - else { - if (Sub->getDescription() != nullptr) { + if (Sub == &*TopLevelSubCommand) { + outs() << "USAGE: " << GlobalParser->ProgramName; + if (Subs.size() > 2) + outs() << " [subcommand]"; + outs() << " [options]"; + } else { + if (!Sub->getDescription().empty()) { outs() << "SUBCOMMAND '" << Sub->getName() << "': " << Sub->getDescription() << "\n\n"; } @@ -1787,7 +1815,7 @@ public: if (ConsumeAfterOpt) outs() << " " << ConsumeAfterOpt->HelpStr; - if (Sub == &*TopLevelSubCommand && Subs.size() > 2) { + if (Sub == &*TopLevelSubCommand && !Subs.empty()) { // Compute the maximum subcommand length... size_t MaxSubLen = 0; for (size_t i = 0, e = Subs.size(); i != e; ++i) @@ -1831,7 +1859,7 @@ public: // ordered before B's name. It returns a value greater equal zero otherwise. static int OptionCategoryCompare(OptionCategory *const *A, OptionCategory *const *B) { - return strcmp((*A)->getName(), (*B)->getName()); + return (*A)->getName() == (*B)->getName(); } // Make sure we inherit our base class's operator=() @@ -1888,7 +1916,7 @@ protected: outs() << (*Category)->getName() << ":\n"; // Check if description is set. - if ((*Category)->getDescription() != nullptr) + if (!(*Category)->getDescription().empty()) outs() << (*Category)->getDescription() << "\n\n"; else outs() << "\n"; @@ -2118,10 +2146,15 @@ void cl::AddExtraVersionPrinter(void (*func)()) { StringMap<Option *> &cl::getRegisteredOptions(SubCommand &Sub) { auto &Subs = GlobalParser->RegisteredSubCommands; (void)Subs; - assert(std::find(Subs.begin(), Subs.end(), &Sub) != Subs.end()); + assert(is_contained(Subs, &Sub)); return Sub.OptionsMap; } +iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator> +cl::getRegisteredSubcommands() { + return GlobalParser->getRegisteredSubcommands(); +} + void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) { for (auto &I : Sub.OptionsMap) { if (I.second->Category != &Category && @@ -2149,5 +2182,5 @@ void cl::ResetAllOptionOccurrences() { void LLVMParseCommandLineOptions(int argc, const char *const *argv, const char *Overview) { - llvm::cl::ParseCommandLineOptions(argc, argv, Overview, true); + llvm::cl::ParseCommandLineOptions(argc, argv, StringRef(Overview), true); } diff --git a/contrib/llvm/lib/Support/Compression.cpp b/contrib/llvm/lib/Support/Compression.cpp index b54613e..5d55646 100644 --- a/contrib/llvm/lib/Support/Compression.cpp +++ b/contrib/llvm/lib/Support/Compression.cpp @@ -62,16 +62,23 @@ zlib::Status zlib::compress(StringRef InputBuffer, return Res; } +zlib::Status zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer, + size_t &UncompressedSize) { + Status Res = encodeZlibReturnValue( + ::uncompress((Bytef *)UncompressedBuffer, (uLongf *)&UncompressedSize, + (const Bytef *)InputBuffer.data(), InputBuffer.size())); + // Tell MemorySanitizer that zlib output buffer is fully initialized. + // This avoids a false report when running LLVM with uninstrumented ZLib. + __msan_unpoison(UncompressedBuffer, UncompressedSize); + return Res; +} + zlib::Status zlib::uncompress(StringRef InputBuffer, SmallVectorImpl<char> &UncompressedBuffer, size_t UncompressedSize) { UncompressedBuffer.resize(UncompressedSize); - Status Res = encodeZlibReturnValue(::uncompress( - (Bytef *)UncompressedBuffer.data(), (uLongf *)&UncompressedSize, - (const Bytef *)InputBuffer.data(), InputBuffer.size())); - // Tell MemorySanitizer that zlib output buffer is fully initialized. - // This avoids a false report when running LLVM with uninstrumented ZLib. - __msan_unpoison(UncompressedBuffer.data(), UncompressedSize); + Status Res = + uncompress(InputBuffer, UncompressedBuffer.data(), UncompressedSize); UncompressedBuffer.resize(UncompressedSize); return Res; } @@ -87,6 +94,10 @@ zlib::Status zlib::compress(StringRef InputBuffer, CompressionLevel Level) { return zlib::StatusUnsupported; } +zlib::Status zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer, + size_t &UncompressedSize) { + return zlib::StatusUnsupported; +} zlib::Status zlib::uncompress(StringRef InputBuffer, SmallVectorImpl<char> &UncompressedBuffer, size_t UncompressedSize) { diff --git a/contrib/llvm/lib/Support/ConvertUTF.c b/contrib/llvm/lib/Support/ConvertUTF.cpp index 128459a..39fd218 100644 --- a/contrib/llvm/lib/Support/ConvertUTF.c +++ b/contrib/llvm/lib/Support/ConvertUTF.cpp @@ -53,6 +53,8 @@ #endif #include <assert.h> +namespace llvm { + static const int halfShift = 10; /* used for shifting by 10 bits */ static const UTF32 halfBase = 0x0010000UL; @@ -62,8 +64,6 @@ static const UTF32 halfMask = 0x3FFUL; #define UNI_SUR_HIGH_END (UTF32)0xDBFF #define UNI_SUR_LOW_START (UTF32)0xDC00 #define UNI_SUR_LOW_END (UTF32)0xDFFF -#define false 0 -#define true 1 /* --------------------------------------------------------------------- */ @@ -706,3 +706,5 @@ ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, similarly unrolled loops. --------------------------------------------------------------------- */ + +} // namespace llvm diff --git a/contrib/llvm/lib/Support/DataStream.cpp b/contrib/llvm/lib/Support/DataStream.cpp deleted file mode 100644 index 3b10fc5..0000000 --- a/contrib/llvm/lib/Support/DataStream.cpp +++ /dev/null @@ -1,86 +0,0 @@ -//===--- llvm/Support/DataStream.cpp - Lazy streamed data -----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements DataStreamer, which fetches bytes of Data from -// a stream source. It provides support for streaming (lazy reading) of -// bitcode. An example implementation of streaming from a file or stdin -// is included. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/DataStream.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Program.h" -#include <string> -#include <system_error> -#if !defined(_MSC_VER) && !defined(__MINGW32__) -#include <unistd.h> -#else -#include <io.h> -#endif -using namespace llvm; - -#define DEBUG_TYPE "Data-stream" - -// Interface goals: -// * StreamingMemoryObject doesn't care about complexities like using -// threads/async callbacks to actually overlap download+compile -// * Don't want to duplicate Data in memory -// * Don't need to know total Data len in advance -// Non-goals: -// StreamingMemoryObject already has random access so this interface only does -// in-order streaming (no arbitrary seeking, else we'd have to buffer all the -// Data here in addition to MemoryObject). This also means that if we want -// to be able to to free Data, BitstreamBytes/BitcodeReader will implement it - -STATISTIC(NumStreamFetches, "Number of calls to Data stream fetch"); - -namespace llvm { -DataStreamer::~DataStreamer() {} -} - -namespace { - -// Very simple stream backed by a file. Mostly useful for stdin and debugging; -// actual file access is probably still best done with mmap. -class DataFileStreamer : public DataStreamer { - int Fd; -public: - DataFileStreamer() : Fd(0) {} - ~DataFileStreamer() override { close(Fd); } - size_t GetBytes(unsigned char *buf, size_t len) override { - NumStreamFetches++; - return read(Fd, buf, len); - } - - std::error_code OpenFile(const std::string &Filename) { - if (Filename == "-") { - Fd = 0; - sys::ChangeStdinToBinary(); - return std::error_code(); - } - - return sys::fs::openFileForRead(Filename, Fd); - } -}; - -} - -std::unique_ptr<DataStreamer> -llvm::getDataFileStreamer(const std::string &Filename, std::string *StrError) { - std::unique_ptr<DataFileStreamer> s = make_unique<DataFileStreamer>(); - if (std::error_code e = s->OpenFile(Filename)) { - *StrError = std::string("Could not open ") + Filename + ": " + - e.message() + "\n"; - return nullptr; - } - return std::move(s); -} diff --git a/contrib/llvm/lib/Support/Debug.cpp b/contrib/llvm/lib/Support/Debug.cpp index 323d532..9132911 100644 --- a/contrib/llvm/lib/Support/Debug.cpp +++ b/contrib/llvm/lib/Support/Debug.cpp @@ -32,6 +32,7 @@ #undef isCurrentDebugType #undef setCurrentDebugType +#undef setCurrentDebugTypes using namespace llvm; @@ -62,11 +63,17 @@ bool isCurrentDebugType(const char *DebugType) { /// option were specified. Note that DebugFlag also needs to be set to true for /// debug output to be produced. /// +void setCurrentDebugTypes(const char **Types, unsigned Count); + void setCurrentDebugType(const char *Type) { - CurrentDebugType->clear(); - CurrentDebugType->push_back(Type); + setCurrentDebugTypes(&Type, 1); } +void setCurrentDebugTypes(const char **Types, unsigned Count) { + CurrentDebugType->clear(); + for (size_t T = 0; T < Count; ++T) + CurrentDebugType->push_back(Types[T]); +} } // namespace llvm // All Debug.h functionality is a no-op in NDEBUG mode. diff --git a/contrib/llvm/lib/Support/DeltaAlgorithm.cpp b/contrib/llvm/lib/Support/DeltaAlgorithm.cpp index 9e52874..50ea4e9 100644 --- a/contrib/llvm/lib/Support/DeltaAlgorithm.cpp +++ b/contrib/llvm/lib/Support/DeltaAlgorithm.cpp @@ -9,6 +9,7 @@ #include "llvm/ADT/DeltaAlgorithm.h" #include <algorithm> #include <iterator> +#include <set> using namespace llvm; DeltaAlgorithm::~DeltaAlgorithm() { diff --git a/contrib/llvm/lib/Support/Dwarf.cpp b/contrib/llvm/lib/Support/Dwarf.cpp index 7aea05d..8950e8c 100644 --- a/contrib/llvm/lib/Support/Dwarf.cpp +++ b/contrib/llvm/lib/Support/Dwarf.cpp @@ -18,9 +18,10 @@ using namespace llvm; using namespace dwarf; -const char *llvm::dwarf::TagString(unsigned Tag) { +StringRef llvm::dwarf::TagString(unsigned Tag) { switch (Tag) { - default: return nullptr; + default: + return StringRef(); #define HANDLE_DW_TAG(ID, NAME) \ case DW_TAG_##NAME: \ return "DW_TAG_" #NAME; @@ -35,240 +36,46 @@ unsigned llvm::dwarf::getTag(StringRef TagString) { .Default(DW_TAG_invalid); } -const char *llvm::dwarf::ChildrenString(unsigned Children) { +StringRef llvm::dwarf::ChildrenString(unsigned Children) { switch (Children) { case DW_CHILDREN_no: return "DW_CHILDREN_no"; case DW_CHILDREN_yes: return "DW_CHILDREN_yes"; } - return nullptr; + return StringRef(); } -const char *llvm::dwarf::AttributeString(unsigned Attribute) { +StringRef llvm::dwarf::AttributeString(unsigned Attribute) { switch (Attribute) { - case DW_AT_sibling: return "DW_AT_sibling"; - case DW_AT_location: return "DW_AT_location"; - case DW_AT_name: return "DW_AT_name"; - case DW_AT_ordering: return "DW_AT_ordering"; - case DW_AT_byte_size: return "DW_AT_byte_size"; - case DW_AT_bit_offset: return "DW_AT_bit_offset"; - case DW_AT_bit_size: return "DW_AT_bit_size"; - case DW_AT_stmt_list: return "DW_AT_stmt_list"; - case DW_AT_low_pc: return "DW_AT_low_pc"; - case DW_AT_high_pc: return "DW_AT_high_pc"; - case DW_AT_language: return "DW_AT_language"; - case DW_AT_discr: return "DW_AT_discr"; - case DW_AT_discr_value: return "DW_AT_discr_value"; - case DW_AT_visibility: return "DW_AT_visibility"; - case DW_AT_import: return "DW_AT_import"; - case DW_AT_string_length: return "DW_AT_string_length"; - case DW_AT_common_reference: return "DW_AT_common_reference"; - case DW_AT_comp_dir: return "DW_AT_comp_dir"; - case DW_AT_const_value: return "DW_AT_const_value"; - case DW_AT_containing_type: return "DW_AT_containing_type"; - case DW_AT_default_value: return "DW_AT_default_value"; - case DW_AT_inline: return "DW_AT_inline"; - case DW_AT_is_optional: return "DW_AT_is_optional"; - case DW_AT_lower_bound: return "DW_AT_lower_bound"; - case DW_AT_producer: return "DW_AT_producer"; - case DW_AT_prototyped: return "DW_AT_prototyped"; - case DW_AT_return_addr: return "DW_AT_return_addr"; - case DW_AT_start_scope: return "DW_AT_start_scope"; - case DW_AT_bit_stride: return "DW_AT_bit_stride"; - case DW_AT_upper_bound: return "DW_AT_upper_bound"; - case DW_AT_abstract_origin: return "DW_AT_abstract_origin"; - case DW_AT_accessibility: return "DW_AT_accessibility"; - case DW_AT_address_class: return "DW_AT_address_class"; - case DW_AT_artificial: return "DW_AT_artificial"; - case DW_AT_base_types: return "DW_AT_base_types"; - case DW_AT_calling_convention: return "DW_AT_calling_convention"; - case DW_AT_count: return "DW_AT_count"; - case DW_AT_data_member_location: return "DW_AT_data_member_location"; - case DW_AT_decl_column: return "DW_AT_decl_column"; - case DW_AT_decl_file: return "DW_AT_decl_file"; - case DW_AT_decl_line: return "DW_AT_decl_line"; - case DW_AT_declaration: return "DW_AT_declaration"; - case DW_AT_discr_list: return "DW_AT_discr_list"; - case DW_AT_encoding: return "DW_AT_encoding"; - case DW_AT_external: return "DW_AT_external"; - case DW_AT_frame_base: return "DW_AT_frame_base"; - case DW_AT_friend: return "DW_AT_friend"; - case DW_AT_identifier_case: return "DW_AT_identifier_case"; - case DW_AT_macro_info: return "DW_AT_macro_info"; - case DW_AT_namelist_item: return "DW_AT_namelist_item"; - case DW_AT_priority: return "DW_AT_priority"; - case DW_AT_segment: return "DW_AT_segment"; - case DW_AT_specification: return "DW_AT_specification"; - case DW_AT_static_link: return "DW_AT_static_link"; - case DW_AT_type: return "DW_AT_type"; - case DW_AT_use_location: return "DW_AT_use_location"; - case DW_AT_variable_parameter: return "DW_AT_variable_parameter"; - case DW_AT_virtuality: return "DW_AT_virtuality"; - case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location"; - case DW_AT_allocated: return "DW_AT_allocated"; - case DW_AT_associated: return "DW_AT_associated"; - case DW_AT_data_location: return "DW_AT_data_location"; - case DW_AT_byte_stride: return "DW_AT_byte_stride"; - case DW_AT_entry_pc: return "DW_AT_entry_pc"; - case DW_AT_use_UTF8: return "DW_AT_use_UTF8"; - case DW_AT_extension: return "DW_AT_extension"; - case DW_AT_ranges: return "DW_AT_ranges"; - case DW_AT_trampoline: return "DW_AT_trampoline"; - case DW_AT_call_column: return "DW_AT_call_column"; - case DW_AT_call_file: return "DW_AT_call_file"; - case DW_AT_call_line: return "DW_AT_call_line"; - case DW_AT_description: return "DW_AT_description"; - case DW_AT_binary_scale: return "DW_AT_binary_scale"; - case DW_AT_decimal_scale: return "DW_AT_decimal_scale"; - case DW_AT_small: return "DW_AT_small"; - case DW_AT_decimal_sign: return "DW_AT_decimal_sign"; - case DW_AT_digit_count: return "DW_AT_digit_count"; - case DW_AT_picture_string: return "DW_AT_picture_string"; - case DW_AT_mutable: return "DW_AT_mutable"; - case DW_AT_threads_scaled: return "DW_AT_threads_scaled"; - case DW_AT_explicit: return "DW_AT_explicit"; - case DW_AT_object_pointer: return "DW_AT_object_pointer"; - case DW_AT_endianity: return "DW_AT_endianity"; - case DW_AT_elemental: return "DW_AT_elemental"; - case DW_AT_pure: return "DW_AT_pure"; - case DW_AT_recursive: return "DW_AT_recursive"; - case DW_AT_signature: return "DW_AT_signature"; - case DW_AT_main_subprogram: return "DW_AT_main_subprogram"; - case DW_AT_data_bit_offset: return "DW_AT_data_bit_offset"; - case DW_AT_const_expr: return "DW_AT_const_expr"; - case DW_AT_enum_class: return "DW_AT_enum_class"; - case DW_AT_linkage_name: return "DW_AT_linkage_name"; - case DW_AT_string_length_bit_size: return "DW_AT_string_length_bit_size"; - case DW_AT_string_length_byte_size: return "DW_AT_string_length_byte_size"; - case DW_AT_rank: return "DW_AT_rank"; - case DW_AT_str_offsets_base: return "DW_AT_str_offsets_base"; - case DW_AT_addr_base: return "DW_AT_addr_base"; - case DW_AT_ranges_base: return "DW_AT_ranges_base"; - case DW_AT_dwo_id: return "DW_AT_dwo_id"; - case DW_AT_dwo_name: return "DW_AT_dwo_name"; - case DW_AT_reference: return "DW_AT_reference"; - case DW_AT_rvalue_reference: return "DW_AT_rvalue_reference"; - case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin"; - case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin"; - case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin"; - case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor"; - case DW_AT_MIPS_software_pipeline_depth: - return "DW_AT_MIPS_software_pipeline_depth"; - case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name"; - case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride"; - case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name"; - case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin"; - case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines"; - case DW_AT_MIPS_stride_byte: return "DW_AT_MIPS_stride_byte"; - case DW_AT_MIPS_stride_elem: return "DW_AT_MIPS_stride_elem"; - case DW_AT_MIPS_ptr_dopetype: return "DW_AT_MIPS_ptr_dopetype"; - case DW_AT_MIPS_allocatable_dopetype: - return "DW_AT_MIPS_allocatable_dopetype"; - case DW_AT_MIPS_assumed_shape_dopetype: - return "DW_AT_MIPS_assumed_shape_dopetype"; - case DW_AT_sf_names: return "DW_AT_sf_names"; - case DW_AT_src_info: return "DW_AT_src_info"; - case DW_AT_mac_info: return "DW_AT_mac_info"; - case DW_AT_src_coords: return "DW_AT_src_coords"; - case DW_AT_body_begin: return "DW_AT_body_begin"; - case DW_AT_body_end: return "DW_AT_body_end"; - case DW_AT_GNU_vector: return "DW_AT_GNU_vector"; - case DW_AT_GNU_template_name: return "DW_AT_GNU_template_name"; - case DW_AT_GNU_odr_signature: return "DW_AT_GNU_odr_signature"; - case DW_AT_MIPS_assumed_size: return "DW_AT_MIPS_assumed_size"; - case DW_AT_lo_user: return "DW_AT_lo_user"; - case DW_AT_hi_user: return "DW_AT_hi_user"; - case DW_AT_BORLAND_property_read: return "DW_AT_BORLAND_property_read"; - case DW_AT_BORLAND_property_write: return "DW_AT_BORLAND_property_write"; - case DW_AT_BORLAND_property_implements: return "DW_AT_BORLAND_property_implements"; - case DW_AT_BORLAND_property_index: return "DW_AT_BORLAND_property_index"; - case DW_AT_BORLAND_property_default: return "DW_AT_BORLAND_property_default"; - case DW_AT_BORLAND_Delphi_unit: return "DW_AT_BORLAND_Delphi_unit"; - case DW_AT_BORLAND_Delphi_class: return "DW_AT_BORLAND_Delphi_class"; - case DW_AT_BORLAND_Delphi_record: return "DW_AT_BORLAND_Delphi_record"; - case DW_AT_BORLAND_Delphi_metaclass: return "DW_AT_BORLAND_Delphi_metaclass"; - case DW_AT_BORLAND_Delphi_constructor: return "DW_AT_BORLAND_Delphi_constructor"; - case DW_AT_BORLAND_Delphi_destructor: return "DW_AT_BORLAND_Delphi_destructor"; - case DW_AT_BORLAND_Delphi_anonymous_method: return "DW_AT_BORLAND_Delphi_anonymous_method"; - case DW_AT_BORLAND_Delphi_interface: return "DW_AT_BORLAND_Delphi_interface"; - case DW_AT_BORLAND_Delphi_ABI: return "DW_AT_BORLAND_Delphi_ABI"; - case DW_AT_BORLAND_Delphi_return: return "DW_AT_BORLAND_Delphi_return"; - case DW_AT_BORLAND_Delphi_frameptr: return "DW_AT_BORLAND_Delphi_frameptr"; - case DW_AT_BORLAND_closure: return "DW_AT_BORLAND_closure"; - case DW_AT_APPLE_optimized: return "DW_AT_APPLE_optimized"; - case DW_AT_APPLE_flags: return "DW_AT_APPLE_flags"; - case DW_AT_APPLE_isa: return "DW_AT_APPLE_isa"; - case DW_AT_APPLE_block: return "DW_AT_APPLE_block"; - case DW_AT_APPLE_major_runtime_vers: return "DW_AT_APPLE_major_runtime_vers"; - case DW_AT_APPLE_runtime_class: return "DW_AT_APPLE_runtime_class"; - case DW_AT_APPLE_omit_frame_ptr: return "DW_AT_APPLE_omit_frame_ptr"; - case DW_AT_APPLE_property_name: return "DW_AT_APPLE_property_name"; - case DW_AT_APPLE_property_getter: return "DW_AT_APPLE_property_getter"; - case DW_AT_APPLE_property_setter: return "DW_AT_APPLE_property_setter"; - case DW_AT_APPLE_property_attribute: return "DW_AT_APPLE_property_attribute"; - case DW_AT_APPLE_property: return "DW_AT_APPLE_property"; - case DW_AT_APPLE_objc_complete_type: return "DW_AT_APPLE_objc_complete_type"; - case DW_AT_LLVM_include_path: return "DW_AT_LLVM_include_path"; - case DW_AT_LLVM_config_macros: return "DW_AT_LLVM_config_macros"; - case DW_AT_LLVM_isysroot: return "DW_AT_LLVM_isysroot"; - - // DWARF5 Fission Extension Attribute - case DW_AT_GNU_dwo_name: return "DW_AT_GNU_dwo_name"; - case DW_AT_GNU_dwo_id: return "DW_AT_GNU_dwo_id"; - case DW_AT_GNU_ranges_base: return "DW_AT_GNU_ranges_base"; - case DW_AT_GNU_addr_base: return "DW_AT_GNU_addr_base"; - case DW_AT_GNU_pubnames: return "DW_AT_GNU_pubnames"; - case DW_AT_GNU_pubtypes: return "DW_AT_GNU_pubtypes"; - case DW_AT_GNU_discriminator: return "DW_AT_GNU_discriminator"; + default: + return StringRef(); +#define HANDLE_DW_AT(ID, NAME) \ + case DW_AT_##NAME: \ + return "DW_AT_" #NAME; +#include "llvm/Support/Dwarf.def" } - return nullptr; } -const char *llvm::dwarf::FormEncodingString(unsigned Encoding) { +StringRef llvm::dwarf::FormEncodingString(unsigned Encoding) { switch (Encoding) { - case DW_FORM_addr: return "DW_FORM_addr"; - case DW_FORM_block2: return "DW_FORM_block2"; - case DW_FORM_block4: return "DW_FORM_block4"; - case DW_FORM_data2: return "DW_FORM_data2"; - case DW_FORM_data4: return "DW_FORM_data4"; - case DW_FORM_data8: return "DW_FORM_data8"; - case DW_FORM_string: return "DW_FORM_string"; - case DW_FORM_block: return "DW_FORM_block"; - case DW_FORM_block1: return "DW_FORM_block1"; - case DW_FORM_data1: return "DW_FORM_data1"; - case DW_FORM_flag: return "DW_FORM_flag"; - case DW_FORM_sdata: return "DW_FORM_sdata"; - case DW_FORM_strp: return "DW_FORM_strp"; - case DW_FORM_udata: return "DW_FORM_udata"; - case DW_FORM_ref_addr: return "DW_FORM_ref_addr"; - case DW_FORM_ref1: return "DW_FORM_ref1"; - case DW_FORM_ref2: return "DW_FORM_ref2"; - case DW_FORM_ref4: return "DW_FORM_ref4"; - case DW_FORM_ref8: return "DW_FORM_ref8"; - case DW_FORM_ref_udata: return "DW_FORM_ref_udata"; - case DW_FORM_indirect: return "DW_FORM_indirect"; - case DW_FORM_sec_offset: return "DW_FORM_sec_offset"; - case DW_FORM_exprloc: return "DW_FORM_exprloc"; - case DW_FORM_flag_present: return "DW_FORM_flag_present"; - case DW_FORM_ref_sig8: return "DW_FORM_ref_sig8"; - - // DWARF5 Fission Extension Forms - case DW_FORM_GNU_addr_index: return "DW_FORM_GNU_addr_index"; - case DW_FORM_GNU_str_index: return "DW_FORM_GNU_str_index"; - - // Alternate debug sections proposal (output of "dwz" tool). - case DW_FORM_GNU_ref_alt: return "DW_FORM_GNU_ref_alt"; - case DW_FORM_GNU_strp_alt: return "DW_FORM_GNU_strp_alt"; + default: + return StringRef(); +#define HANDLE_DW_FORM(ID, NAME) \ + case DW_FORM_##NAME: \ + return "DW_FORM_" #NAME; +#include "llvm/Support/Dwarf.def" } - return nullptr; } -const char *llvm::dwarf::OperationEncodingString(unsigned Encoding) { +StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) { switch (Encoding) { - default: return nullptr; + default: + return StringRef(); #define HANDLE_DW_OP(ID, NAME) \ case DW_OP_##NAME: \ return "DW_OP_" #NAME; #include "llvm/Support/Dwarf.def" + case DW_OP_LLVM_fragment: + return "DW_OP_LLVM_fragment"; } } @@ -276,12 +83,14 @@ unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) { return StringSwitch<unsigned>(OperationEncodingString) #define HANDLE_DW_OP(ID, NAME) .Case("DW_OP_" #NAME, DW_OP_##NAME) #include "llvm/Support/Dwarf.def" + .Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment) .Default(0); } -const char *llvm::dwarf::AttributeEncodingString(unsigned Encoding) { +StringRef llvm::dwarf::AttributeEncodingString(unsigned Encoding) { switch (Encoding) { - default: return nullptr; + default: + return StringRef(); #define HANDLE_DW_ATE(ID, NAME) \ case DW_ATE_##NAME: \ return "DW_ATE_" #NAME; @@ -296,7 +105,7 @@ unsigned llvm::dwarf::getAttributeEncoding(StringRef EncodingString) { .Default(0); } -const char *llvm::dwarf::DecimalSignString(unsigned Sign) { +StringRef llvm::dwarf::DecimalSignString(unsigned Sign) { switch (Sign) { case DW_DS_unsigned: return "DW_DS_unsigned"; case DW_DS_leading_overpunch: return "DW_DS_leading_overpunch"; @@ -304,10 +113,10 @@ const char *llvm::dwarf::DecimalSignString(unsigned Sign) { case DW_DS_leading_separate: return "DW_DS_leading_separate"; case DW_DS_trailing_separate: return "DW_DS_trailing_separate"; } - return nullptr; + return StringRef(); } -const char *llvm::dwarf::EndianityString(unsigned Endian) { +StringRef llvm::dwarf::EndianityString(unsigned Endian) { switch (Endian) { case DW_END_default: return "DW_END_default"; case DW_END_big: return "DW_END_big"; @@ -315,32 +124,32 @@ const char *llvm::dwarf::EndianityString(unsigned Endian) { case DW_END_lo_user: return "DW_END_lo_user"; case DW_END_hi_user: return "DW_END_hi_user"; } - return nullptr; + return StringRef(); } -const char *llvm::dwarf::AccessibilityString(unsigned Access) { +StringRef llvm::dwarf::AccessibilityString(unsigned Access) { switch (Access) { // Accessibility codes case DW_ACCESS_public: return "DW_ACCESS_public"; case DW_ACCESS_protected: return "DW_ACCESS_protected"; case DW_ACCESS_private: return "DW_ACCESS_private"; } - return nullptr; + return StringRef(); } -const char *llvm::dwarf::VisibilityString(unsigned Visibility) { +StringRef llvm::dwarf::VisibilityString(unsigned Visibility) { switch (Visibility) { case DW_VIS_local: return "DW_VIS_local"; case DW_VIS_exported: return "DW_VIS_exported"; case DW_VIS_qualified: return "DW_VIS_qualified"; } - return nullptr; + return StringRef(); } -const char *llvm::dwarf::VirtualityString(unsigned Virtuality) { +StringRef llvm::dwarf::VirtualityString(unsigned Virtuality) { switch (Virtuality) { default: - return nullptr; + return StringRef(); #define HANDLE_DW_VIRTUALITY(ID, NAME) \ case DW_VIRTUALITY_##NAME: \ return "DW_VIRTUALITY_" #NAME; @@ -356,10 +165,10 @@ unsigned llvm::dwarf::getVirtuality(StringRef VirtualityString) { .Default(DW_VIRTUALITY_invalid); } -const char *llvm::dwarf::LanguageString(unsigned Language) { +StringRef llvm::dwarf::LanguageString(unsigned Language) { switch (Language) { default: - return nullptr; + return StringRef(); #define HANDLE_DW_LANG(ID, NAME) \ case DW_LANG_##NAME: \ return "DW_LANG_" #NAME; @@ -374,20 +183,20 @@ unsigned llvm::dwarf::getLanguage(StringRef LanguageString) { .Default(0); } -const char *llvm::dwarf::CaseString(unsigned Case) { +StringRef llvm::dwarf::CaseString(unsigned Case) { switch (Case) { case DW_ID_case_sensitive: return "DW_ID_case_sensitive"; case DW_ID_up_case: return "DW_ID_up_case"; case DW_ID_down_case: return "DW_ID_down_case"; case DW_ID_case_insensitive: return "DW_ID_case_insensitive"; } - return nullptr; + return StringRef(); } -const char *llvm::dwarf::ConventionString(unsigned CC) { +StringRef llvm::dwarf::ConventionString(unsigned CC) { switch (CC) { default: - return nullptr; + return StringRef(); #define HANDLE_DW_CC(ID, NAME) \ case DW_CC_##NAME: \ return "DW_CC_" #NAME; @@ -402,64 +211,55 @@ unsigned llvm::dwarf::getCallingConvention(StringRef CCString) { .Default(0); } -const char *llvm::dwarf::InlineCodeString(unsigned Code) { +StringRef llvm::dwarf::InlineCodeString(unsigned Code) { switch (Code) { case DW_INL_not_inlined: return "DW_INL_not_inlined"; case DW_INL_inlined: return "DW_INL_inlined"; case DW_INL_declared_not_inlined: return "DW_INL_declared_not_inlined"; case DW_INL_declared_inlined: return "DW_INL_declared_inlined"; } - return nullptr; + return StringRef(); } -const char *llvm::dwarf::ArrayOrderString(unsigned Order) { +StringRef llvm::dwarf::ArrayOrderString(unsigned Order) { switch (Order) { case DW_ORD_row_major: return "DW_ORD_row_major"; case DW_ORD_col_major: return "DW_ORD_col_major"; } - return nullptr; + return StringRef(); } -const char *llvm::dwarf::DiscriminantString(unsigned Discriminant) { +StringRef llvm::dwarf::DiscriminantString(unsigned Discriminant) { switch (Discriminant) { case DW_DSC_label: return "DW_DSC_label"; case DW_DSC_range: return "DW_DSC_range"; } - return nullptr; + return StringRef(); } -const char *llvm::dwarf::LNStandardString(unsigned Standard) { +StringRef llvm::dwarf::LNStandardString(unsigned Standard) { switch (Standard) { - case DW_LNS_copy: return "DW_LNS_copy"; - case DW_LNS_advance_pc: return "DW_LNS_advance_pc"; - case DW_LNS_advance_line: return "DW_LNS_advance_line"; - case DW_LNS_set_file: return "DW_LNS_set_file"; - case DW_LNS_set_column: return "DW_LNS_set_column"; - case DW_LNS_negate_stmt: return "DW_LNS_negate_stmt"; - case DW_LNS_set_basic_block: return "DW_LNS_set_basic_block"; - case DW_LNS_const_add_pc: return "DW_LNS_const_add_pc"; - case DW_LNS_fixed_advance_pc: return "DW_LNS_fixed_advance_pc"; - case DW_LNS_set_prologue_end: return "DW_LNS_set_prologue_end"; - case DW_LNS_set_epilogue_begin: return "DW_LNS_set_epilogue_begin"; - case DW_LNS_set_isa: return "DW_LNS_set_isa"; + default: + return StringRef(); +#define HANDLE_DW_LNS(ID, NAME) \ + case DW_LNS_##NAME: \ + return "DW_LNS_" #NAME; +#include "llvm/Support/Dwarf.def" } - return nullptr; } -const char *llvm::dwarf::LNExtendedString(unsigned Encoding) { +StringRef llvm::dwarf::LNExtendedString(unsigned Encoding) { switch (Encoding) { - // Line Number Extended Opcode Encodings - case DW_LNE_end_sequence: return "DW_LNE_end_sequence"; - case DW_LNE_set_address: return "DW_LNE_set_address"; - case DW_LNE_define_file: return "DW_LNE_define_file"; - case DW_LNE_set_discriminator: return "DW_LNE_set_discriminator"; - case DW_LNE_lo_user: return "DW_LNE_lo_user"; - case DW_LNE_hi_user: return "DW_LNE_hi_user"; + default: + return StringRef(); +#define HANDLE_DW_LNE(ID, NAME) \ + case DW_LNE_##NAME: \ + return "DW_LNE_" #NAME; +#include "llvm/Support/Dwarf.def" } - return nullptr; } -const char *llvm::dwarf::MacinfoString(unsigned Encoding) { +StringRef llvm::dwarf::MacinfoString(unsigned Encoding) { switch (Encoding) { // Macinfo Type Encodings case DW_MACINFO_define: return "DW_MACINFO_define"; @@ -469,7 +269,7 @@ const char *llvm::dwarf::MacinfoString(unsigned Encoding) { case DW_MACINFO_vendor_ext: return "DW_MACINFO_vendor_ext"; case DW_MACINFO_invalid: return "DW_MACINFO_invalid"; } - return nullptr; + return StringRef(); } unsigned llvm::dwarf::getMacinfo(StringRef MacinfoString) { @@ -482,80 +282,29 @@ unsigned llvm::dwarf::getMacinfo(StringRef MacinfoString) { .Default(DW_MACINFO_invalid); } -const char *llvm::dwarf::CallFrameString(unsigned Encoding) { +StringRef llvm::dwarf::CallFrameString(unsigned Encoding) { switch (Encoding) { - case DW_CFA_nop: return "DW_CFA_nop"; - case DW_CFA_advance_loc: return "DW_CFA_advance_loc"; - case DW_CFA_offset: return "DW_CFA_offset"; - case DW_CFA_restore: return "DW_CFA_restore"; - case DW_CFA_set_loc: return "DW_CFA_set_loc"; - case DW_CFA_advance_loc1: return "DW_CFA_advance_loc1"; - case DW_CFA_advance_loc2: return "DW_CFA_advance_loc2"; - case DW_CFA_advance_loc4: return "DW_CFA_advance_loc4"; - case DW_CFA_offset_extended: return "DW_CFA_offset_extended"; - case DW_CFA_restore_extended: return "DW_CFA_restore_extended"; - case DW_CFA_undefined: return "DW_CFA_undefined"; - case DW_CFA_same_value: return "DW_CFA_same_value"; - case DW_CFA_register: return "DW_CFA_register"; - case DW_CFA_remember_state: return "DW_CFA_remember_state"; - case DW_CFA_restore_state: return "DW_CFA_restore_state"; - case DW_CFA_def_cfa: return "DW_CFA_def_cfa"; - case DW_CFA_def_cfa_register: return "DW_CFA_def_cfa_register"; - case DW_CFA_def_cfa_offset: return "DW_CFA_def_cfa_offset"; - case DW_CFA_def_cfa_expression: return "DW_CFA_def_cfa_expression"; - case DW_CFA_expression: return "DW_CFA_expression"; - case DW_CFA_offset_extended_sf: return "DW_CFA_offset_extended_sf"; - case DW_CFA_def_cfa_sf: return "DW_CFA_def_cfa_sf"; - case DW_CFA_def_cfa_offset_sf: return "DW_CFA_def_cfa_offset_sf"; - case DW_CFA_val_offset: return "DW_CFA_val_offset"; - case DW_CFA_val_offset_sf: return "DW_CFA_val_offset_sf"; - case DW_CFA_val_expression: return "DW_CFA_val_expression"; - case DW_CFA_MIPS_advance_loc8: return "DW_CFA_MIPS_advance_loc8"; - case DW_CFA_GNU_window_save: return "DW_CFA_GNU_window_save"; - case DW_CFA_GNU_args_size: return "DW_CFA_GNU_args_size"; - case DW_CFA_lo_user: return "DW_CFA_lo_user"; - case DW_CFA_hi_user: return "DW_CFA_hi_user"; + default: + return StringRef(); +#define HANDLE_DW_CFA(ID, NAME) \ + case DW_CFA_##NAME: \ + return "DW_CFA_" #NAME; +#include "llvm/Support/Dwarf.def" } - return nullptr; } -const char *llvm::dwarf::ApplePropertyString(unsigned Prop) { +StringRef llvm::dwarf::ApplePropertyString(unsigned Prop) { switch (Prop) { - case DW_APPLE_PROPERTY_readonly: - return "DW_APPLE_PROPERTY_readonly"; - case DW_APPLE_PROPERTY_getter: - return "DW_APPLE_PROPERTY_getter"; - case DW_APPLE_PROPERTY_assign: - return "DW_APPLE_PROPERTY_assign"; - case DW_APPLE_PROPERTY_readwrite: - return "DW_APPLE_PROPERTY_readwrite"; - case DW_APPLE_PROPERTY_retain: - return "DW_APPLE_PROPERTY_retain"; - case DW_APPLE_PROPERTY_copy: - return "DW_APPLE_PROPERTY_copy"; - case DW_APPLE_PROPERTY_nonatomic: - return "DW_APPLE_PROPERTY_nonatomic"; - case DW_APPLE_PROPERTY_setter: - return "DW_APPLE_PROPERTY_setter"; - case DW_APPLE_PROPERTY_atomic: - return "DW_APPLE_PROPERTY_atomic"; - case DW_APPLE_PROPERTY_weak: - return "DW_APPLE_PROPERTY_weak"; - case DW_APPLE_PROPERTY_strong: - return "DW_APPLE_PROPERTY_strong"; - case DW_APPLE_PROPERTY_unsafe_unretained: - return "DW_APPLE_PROPERTY_unsafe_unretained"; - case DW_APPLE_PROPERTY_nullability: - return "DW_APPLE_PROPERTY_nullability"; - case DW_APPLE_PROPERTY_null_resettable: - return "DW_APPLE_PROPERTY_null_resettable"; - case DW_APPLE_PROPERTY_class: - return "DW_APPLE_PROPERTY_class"; + default: + return StringRef(); +#define HANDLE_DW_APPLE_PROPERTY(ID, NAME) \ + case DW_APPLE_PROPERTY_##NAME: \ + return "DW_APPLE_PROPERTY_" #NAME; +#include "llvm/Support/Dwarf.def" } - return nullptr; } -const char *llvm::dwarf::AtomTypeString(unsigned AT) { +StringRef llvm::dwarf::AtomTypeString(unsigned AT) { switch (AT) { case dwarf::DW_ATOM_null: return "DW_ATOM_null"; @@ -568,10 +317,10 @@ const char *llvm::dwarf::AtomTypeString(unsigned AT) { case DW_ATOM_type_flags: return "DW_ATOM_type_flags"; } - return nullptr; + return StringRef(); } -const char *llvm::dwarf::GDBIndexEntryKindString(GDBIndexEntryKind Kind) { +StringRef llvm::dwarf::GDBIndexEntryKindString(GDBIndexEntryKind Kind) { switch (Kind) { case GIEK_NONE: return "NONE"; @@ -593,7 +342,8 @@ const char *llvm::dwarf::GDBIndexEntryKindString(GDBIndexEntryKind Kind) { llvm_unreachable("Unknown GDBIndexEntryKind value"); } -const char *llvm::dwarf::GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage) { +StringRef +llvm::dwarf::GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage) { switch (Linkage) { case GIEL_EXTERNAL: return "EXTERNAL"; @@ -603,7 +353,7 @@ const char *llvm::dwarf::GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage llvm_unreachable("Unknown GDBIndexEntryLinkage value"); } -const char *llvm::dwarf::AttributeValueString(uint16_t Attr, unsigned Val) { +StringRef llvm::dwarf::AttributeValueString(uint16_t Attr, unsigned Val) { switch (Attr) { case DW_AT_accessibility: return AccessibilityString(Val); @@ -631,5 +381,5 @@ const char *llvm::dwarf::AttributeValueString(uint16_t Attr, unsigned Val) { return DiscriminantString(Val); } - return nullptr; + return StringRef(); } diff --git a/contrib/llvm/lib/Support/DynamicLibrary.cpp b/contrib/llvm/lib/Support/DynamicLibrary.cpp index 9a7aeb5..ced21e4 100644 --- a/contrib/llvm/lib/Support/DynamicLibrary.cpp +++ b/contrib/llvm/lib/Support/DynamicLibrary.cpp @@ -41,7 +41,7 @@ char llvm::sys::DynamicLibrary::Invalid = 0; #else -#if HAVE_DLFCN_H +#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) #include <dlfcn.h> using namespace llvm; using namespace llvm::sys; @@ -119,7 +119,7 @@ void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { return i->second; } -#if HAVE_DLFCN_H +#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) // Now search the libraries. if (OpenedHandles) { for (DenseSet<void *>::iterator I = OpenedHandles->begin(), diff --git a/contrib/llvm/lib/Support/Error.cpp b/contrib/llvm/lib/Support/Error.cpp index 6b22691..4730c0b 100644 --- a/contrib/llvm/lib/Support/Error.cpp +++ b/contrib/llvm/lib/Support/Error.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include <system_error> using namespace llvm; @@ -27,7 +28,7 @@ namespace { // deal with the Error value directly, rather than converting to error_code. class ErrorErrorCategory : public std::error_category { public: - const char *name() const LLVM_NOEXCEPT override { return "Error"; } + const char *name() const noexcept override { return "Error"; } std::string message(int condition) const override { switch (static_cast<ErrorErrorCode>(condition)) { @@ -111,3 +112,18 @@ void report_fatal_error(Error Err, bool GenCrashDiag) { } } + +#ifndef _MSC_VER +namespace llvm { + +// One of these two variables will be referenced by a symbol defined in +// llvm-config.h. We provide a link-time (or load time for DSO) failure when +// there is a mismatch in the build configuration of the API client and LLVM. +#if LLVM_ENABLE_ABI_BREAKING_CHECKS +int EnableABIBreakingChecks; +#else +int DisableABIBreakingChecks; +#endif + +} // end namespace llvm +#endif diff --git a/contrib/llvm/lib/Support/FileOutputBuffer.cpp b/contrib/llvm/lib/Support/FileOutputBuffer.cpp index 651e679..57e5a8d 100644 --- a/contrib/llvm/lib/Support/FileOutputBuffer.cpp +++ b/contrib/llvm/lib/Support/FileOutputBuffer.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Errc.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Signals.h" #include <system_error> @@ -28,18 +29,24 @@ using llvm::sys::fs::mapped_file_region; namespace llvm { FileOutputBuffer::FileOutputBuffer(std::unique_ptr<mapped_file_region> R, - StringRef Path, StringRef TmpPath) - : Region(std::move(R)), FinalPath(Path), TempPath(TmpPath) {} + StringRef Path, StringRef TmpPath, + bool IsRegular) + : Region(std::move(R)), FinalPath(Path), TempPath(TmpPath), + IsRegular(IsRegular) {} FileOutputBuffer::~FileOutputBuffer() { + // Close the mapping before deleting the temp file, so that the removal + // succeeds. + Region.reset(); sys::fs::remove(Twine(TempPath)); } ErrorOr<std::unique_ptr<FileOutputBuffer>> FileOutputBuffer::create(StringRef FilePath, size_t Size, unsigned Flags) { - // If file already exists, it must be a regular file (to be mappable). + // Check file is not a regular file, in which case we cannot remove it. sys::fs::file_status Stat; std::error_code EC = sys::fs::status(FilePath, Stat); + bool IsRegular = true; switch (Stat.type()) { case sys::fs::file_type::file_not_found: // If file does not exist, we'll create one. @@ -53,25 +60,34 @@ FileOutputBuffer::create(StringRef FilePath, size_t Size, unsigned Flags) { default: if (EC) return EC; - else - return make_error_code(errc::operation_not_permitted); + IsRegular = false; } - // Delete target file. - EC = sys::fs::remove(FilePath); - if (EC) - return EC; - - unsigned Mode = sys::fs::all_read | sys::fs::all_write; - // If requested, make the output file executable. - if (Flags & F_executable) - Mode |= sys::fs::all_exe; + if (IsRegular) { + // Delete target file. + EC = sys::fs::remove(FilePath); + if (EC) + return EC; + } - // Create new file in same directory but with random name. SmallString<128> TempFilePath; int FD; - EC = sys::fs::createUniqueFile(Twine(FilePath) + ".tmp%%%%%%%", FD, - TempFilePath, Mode); + if (IsRegular) { + unsigned Mode = sys::fs::all_read | sys::fs::all_write; + // If requested, make the output file executable. + if (Flags & F_executable) + Mode |= sys::fs::all_exe; + // Create new file in same directory but with random name. + EC = sys::fs::createUniqueFile(Twine(FilePath) + ".tmp%%%%%%%", FD, + TempFilePath, Mode); + } else { + // Create a temporary file. Since this is a special file, we will not move + // it and the new file can be in another filesystem. This avoids trying to + // create a temporary file in /dev when outputting to /dev/null for example. + EC = sys::fs::createTemporaryFile(sys::path::filename(FilePath), "", FD, + TempFilePath); + } + if (EC) return EC; @@ -96,8 +112,8 @@ FileOutputBuffer::create(StringRef FilePath, size_t Size, unsigned Flags) { if (Ret) return std::error_code(errno, std::generic_category()); - std::unique_ptr<FileOutputBuffer> Buf( - new FileOutputBuffer(std::move(MappedFile), FilePath, TempFilePath)); + std::unique_ptr<FileOutputBuffer> Buf(new FileOutputBuffer( + std::move(MappedFile), FilePath, TempFilePath, IsRegular)); return std::move(Buf); } @@ -105,10 +121,19 @@ std::error_code FileOutputBuffer::commit() { // Unmap buffer, letting OS flush dirty pages to file on disk. Region.reset(); + std::error_code EC; + if (IsRegular) { + // Rename file to final name. + EC = sys::fs::rename(Twine(TempPath), Twine(FinalPath)); + sys::DontRemoveFileOnSignal(TempPath); + } else { + EC = sys::fs::copy_file(TempPath, FinalPath); + std::error_code RMEC = sys::fs::remove(TempPath); + sys::DontRemoveFileOnSignal(TempPath); + if (RMEC) + return RMEC; + } - // Rename file to final name. - std::error_code EC = sys::fs::rename(Twine(TempPath), Twine(FinalPath)); - sys::DontRemoveFileOnSignal(TempPath); return EC; } } // namespace diff --git a/contrib/llvm/lib/Support/FileUtilities.cpp b/contrib/llvm/lib/Support/FileUtilities.cpp index c6a58cc..39dbeff 100644 --- a/contrib/llvm/lib/Support/FileUtilities.cpp +++ b/contrib/llvm/lib/Support/FileUtilities.cpp @@ -14,13 +14,17 @@ #include "llvm/Support/FileUtilities.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include <cctype> +#include <cmath> +#include <cstdint> #include <cstdlib> #include <cstring> +#include <memory> #include <system_error> + using namespace llvm; static bool isSignedChar(char C) { @@ -215,7 +219,7 @@ int llvm::DiffFilesWithTolerance(StringRef NameA, } bool CompareFailed = false; - while (1) { + while (true) { // Scan for the end of file or next difference. while (F1P < File1End && F2P < File2End && *F1P == *F2P) { ++F1P; diff --git a/contrib/llvm/lib/Support/FoldingSet.cpp b/contrib/llvm/lib/Support/FoldingSet.cpp index 52baf86..c9bca7f 100644 --- a/contrib/llvm/lib/Support/FoldingSet.cpp +++ b/contrib/llvm/lib/Support/FoldingSet.cpp @@ -54,8 +54,9 @@ void FoldingSetNodeID::AddPointer(const void *Ptr) { // depend on the host. It doesn't matter, however, because hashing on // pointer values is inherently unstable. Nothing should depend on the // ordering of nodes in the folding set. - Bits.append(reinterpret_cast<unsigned *>(&Ptr), - reinterpret_cast<unsigned *>(&Ptr+1)); + static_assert(sizeof(uintptr_t) <= sizeof(unsigned long long), + "unexpected pointer size"); + AddInteger(reinterpret_cast<uintptr_t>(Ptr)); } void FoldingSetNodeID::AddInteger(signed I) { Bits.push_back(I); @@ -80,8 +81,7 @@ void FoldingSetNodeID::AddInteger(long long I) { } void FoldingSetNodeID::AddInteger(unsigned long long I) { AddInteger(unsigned(I)); - if ((uint64_t)(unsigned)I != I) - Bits.push_back(unsigned(I >> 32)); + AddInteger(unsigned(I >> 32)); } void FoldingSetNodeID::AddString(StringRef String) { @@ -127,8 +127,8 @@ void FoldingSetNodeID::AddString(StringRef String) { // Pos will have overshot size by 4 - #bytes left over. // No need to take endianness into account here - this is always executed. switch (Pos - Size) { - case 1: V = (V << 8) | (unsigned char)String[Size - 3]; // Fall thru. - case 2: V = (V << 8) | (unsigned char)String[Size - 2]; // Fall thru. + case 1: V = (V << 8) | (unsigned char)String[Size - 3]; LLVM_FALLTHROUGH; + case 2: V = (V << 8) | (unsigned char)String[Size - 2]; LLVM_FALLTHROUGH; case 3: V = (V << 8) | (unsigned char)String[Size - 1]; break; default: return; // Nothing left. } diff --git a/contrib/llvm/lib/Support/FormatVariadic.cpp b/contrib/llvm/lib/Support/FormatVariadic.cpp new file mode 100644 index 0000000..de61dae --- /dev/null +++ b/contrib/llvm/lib/Support/FormatVariadic.cpp @@ -0,0 +1,156 @@ +//===- FormatVariadic.cpp - Format string parsing and analysis ----*-C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; + +static Optional<AlignStyle> translateLocChar(char C) { + switch (C) { + case '-': + return AlignStyle::Left; + case '=': + return AlignStyle::Center; + case '+': + return AlignStyle::Right; + default: + return None; + } + LLVM_BUILTIN_UNREACHABLE; +} + +bool formatv_object_base::consumeFieldLayout(StringRef &Spec, AlignStyle &Where, + size_t &Align, char &Pad) { + Where = AlignStyle::Right; + Align = 0; + Pad = ' '; + if (Spec.empty()) + return true; + + if (Spec.size() > 1) { + // A maximum of 2 characters at the beginning can be used for something + // other + // than the width. + // If Spec[1] is a loc char, then Spec[0] is a pad char and Spec[2:...] + // contains the width. + // Otherwise, if Spec[0] is a loc char, then Spec[1:...] contains the width. + // Otherwise, Spec[0:...] contains the width. + if (auto Loc = translateLocChar(Spec[1])) { + Pad = Spec[0]; + Where = *Loc; + Spec = Spec.drop_front(2); + } else if (auto Loc = translateLocChar(Spec[0])) { + Where = *Loc; + Spec = Spec.drop_front(1); + } + } + + bool Failed = Spec.consumeInteger(0, Align); + return !Failed; +} + +Optional<ReplacementItem> +formatv_object_base::parseReplacementItem(StringRef Spec) { + StringRef RepString = Spec.trim("{}"); + + // If the replacement sequence does not start with a non-negative integer, + // this is an error. + char Pad = ' '; + std::size_t Align = 0; + AlignStyle Where = AlignStyle::Right; + StringRef Options; + size_t Index = 0; + RepString = RepString.trim(); + if (RepString.consumeInteger(0, Index)) { + assert(false && "Invalid replacement sequence index!"); + return ReplacementItem{}; + } + RepString = RepString.trim(); + if (!RepString.empty() && RepString.front() == ',') { + RepString = RepString.drop_front(); + if (!consumeFieldLayout(RepString, Where, Align, Pad)) + assert(false && "Invalid replacement field layout specification!"); + } + RepString = RepString.trim(); + if (!RepString.empty() && RepString.front() == ':') { + Options = RepString.drop_front().trim(); + RepString = StringRef(); + } + RepString = RepString.trim(); + if (!RepString.empty()) { + assert(false && "Unexpected characters found in replacement string!"); + } + + return ReplacementItem{Spec, Index, Align, Where, Pad, Options}; +} + +std::pair<ReplacementItem, StringRef> +formatv_object_base::splitLiteralAndReplacement(StringRef Fmt) { + StringRef Rep; + StringRef Remainder; + std::size_t From = 0; + while (From < Fmt.size() && From != StringRef::npos) { + std::size_t BO = Fmt.find_first_of('{', From); + // Everything up until the first brace is a literal. + if (BO != 0) + return std::make_pair(ReplacementItem{Fmt.substr(0, BO)}, Fmt.substr(BO)); + + StringRef Braces = + Fmt.drop_front(BO).take_while([](char C) { return C == '{'; }); + // If there is more than one brace, then some of them are escaped. Treat + // these as replacements. + if (Braces.size() > 1) { + size_t NumEscapedBraces = Braces.size() / 2; + StringRef Middle = Fmt.substr(BO, NumEscapedBraces); + StringRef Right = Fmt.drop_front(BO + NumEscapedBraces * 2); + return std::make_pair(ReplacementItem{Middle}, Right); + } + // An unterminated open brace is undefined. We treat the rest of the string + // as a literal replacement, but we assert to indicate that this is + // undefined and that we consider it an error. + std::size_t BC = Fmt.find_first_of('}', BO); + if (BC == StringRef::npos) { + assert( + false && + "Unterminated brace sequence. Escape with {{ for a literal brace."); + return std::make_pair(ReplacementItem{Fmt}, StringRef()); + } + + // Even if there is a closing brace, if there is another open brace before + // this closing brace, treat this portion as literal, and try again with the + // next one. + std::size_t BO2 = Fmt.find_first_of('{', BO + 1); + if (BO2 < BC) + return std::make_pair(ReplacementItem{Fmt.substr(0, BO2)}, + Fmt.substr(BO2)); + + StringRef Spec = Fmt.slice(BO + 1, BC); + StringRef Right = Fmt.substr(BC + 1); + + auto RI = parseReplacementItem(Spec); + if (RI.hasValue()) + return std::make_pair(*RI, Right); + + // If there was an error parsing the replacement item, treat it as an + // invalid replacement spec, and just continue. + From = BC + 1; + } + return std::make_pair(ReplacementItem{Fmt}, StringRef()); +} + +std::vector<ReplacementItem> +formatv_object_base::parseFormatString(StringRef Fmt) { + std::vector<ReplacementItem> Replacements; + ReplacementItem I; + while (!Fmt.empty()) { + std::tie(I, Fmt) = splitLiteralAndReplacement(Fmt); + if (I.Type != ReplacementType::Empty) + Replacements.push_back(I); + } + return Replacements; +} diff --git a/contrib/llvm/lib/Support/GlobPattern.cpp b/contrib/llvm/lib/Support/GlobPattern.cpp new file mode 100644 index 0000000..8ee2feb --- /dev/null +++ b/contrib/llvm/lib/Support/GlobPattern.cpp @@ -0,0 +1,167 @@ +//===-- GlobPattern.cpp - Glob pattern matcher implementation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a glob pattern matcher. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/GlobPattern.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Errc.h" + +using namespace llvm; + +static bool hasWildcard(StringRef S) { + return S.find_first_of("?*[") != StringRef::npos; +} + +// Expands character ranges and returns a bitmap. +// For example, "a-cf-hz" is expanded to "abcfghz". +static Expected<BitVector> expand(StringRef S, StringRef Original) { + BitVector BV(256, false); + + // Expand X-Y. + for (;;) { + if (S.size() < 3) + break; + + // If it doesn't start with something like X-Y, + // consume the first character and proceed. + if (S[1] != '-') { + BV[S[0]] = true; + S = S.substr(1); + continue; + } + + // It must be in the form of X-Y. + // Validate it and then interpret the range. + if (S[0] > S[2]) + return make_error<StringError>("invalid glob pattern: " + Original, + errc::invalid_argument); + + for (int C = S[0]; C <= S[2]; ++C) + BV[C] = true; + S = S.substr(3); + } + + for (char C : S) + BV[C] = true; + return BV; +} + +// This is a scanner for the glob pattern. +// A glob pattern token is one of "*", "?", "[<chars>]", "[^<chars>]" +// (which is a negative form of "[<chars>]"), or a non-meta character. +// This function returns the first token in S. +static Expected<BitVector> scan(StringRef &S, StringRef Original) { + switch (S[0]) { + case '*': + S = S.substr(1); + // '*' is represented by an empty bitvector. + // All other bitvectors are 256-bit long. + return BitVector(); + case '?': + S = S.substr(1); + return BitVector(256, true); + case '[': { + size_t End = S.find(']', 1); + if (End == StringRef::npos) + return make_error<StringError>("invalid glob pattern: " + Original, + errc::invalid_argument); + + StringRef Chars = S.substr(1, End - 1); + S = S.substr(End + 1); + if (Chars.startswith("^")) { + Expected<BitVector> BV = expand(Chars.substr(1), Original); + if (!BV) + return BV.takeError(); + return BV->flip(); + } + return expand(Chars, Original); + } + default: + BitVector BV(256, false); + BV[S[0]] = true; + S = S.substr(1); + return BV; + } +} + +Expected<GlobPattern> GlobPattern::create(StringRef S) { + GlobPattern Pat; + + // S doesn't contain any metacharacter, + // so the regular string comparison should work. + if (!hasWildcard(S)) { + Pat.Exact = S; + return Pat; + } + + // S is something like "foo*". We can use startswith(). + if (S.endswith("*") && !hasWildcard(S.drop_back())) { + Pat.Prefix = S.drop_back(); + return Pat; + } + + // S is something like "*foo". We can use endswith(). + if (S.startswith("*") && !hasWildcard(S.drop_front())) { + Pat.Suffix = S.drop_front(); + return Pat; + } + + // Otherwise, we need to do real glob pattern matching. + // Parse the pattern now. + StringRef Original = S; + while (!S.empty()) { + Expected<BitVector> BV = scan(S, Original); + if (!BV) + return BV.takeError(); + Pat.Tokens.push_back(*BV); + } + return Pat; +} + +bool GlobPattern::match(StringRef S) const { + if (Exact) + return S == *Exact; + if (Prefix) + return S.startswith(*Prefix); + if (Suffix) + return S.endswith(*Suffix); + return matchOne(Tokens, S); +} + +// Runs glob pattern Pats against string S. +bool GlobPattern::matchOne(ArrayRef<BitVector> Pats, StringRef S) const { + for (;;) { + if (Pats.empty()) + return S.empty(); + + // If Pats[0] is '*', try to match Pats[1..] against all possible + // tail strings of S to see at least one pattern succeeds. + if (Pats[0].size() == 0) { + Pats = Pats.slice(1); + if (Pats.empty()) + // Fast path. If a pattern is '*', it matches anything. + return true; + for (size_t I = 0, E = S.size(); I < E; ++I) + if (matchOne(Pats, S.substr(I))) + return true; + return false; + } + + // If Pats[0] is not '*', it must consume one character. + if (S.empty() || !Pats[0][S[0]]) + return false; + Pats = Pats.slice(1); + S = S.substr(1); + } +} diff --git a/contrib/llvm/lib/Support/Host.cpp b/contrib/llvm/lib/Support/Host.cpp index 12ac19d..d1b4041 100644 --- a/contrib/llvm/lib/Support/Host.cpp +++ b/contrib/llvm/lib/Support/Host.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Host.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" @@ -19,7 +20,9 @@ #include "llvm/Config/config.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" +#include <assert.h> #include <string.h> // Include the platform-specific parts of this class. @@ -69,9 +72,8 @@ static ssize_t LLVM_ATTRIBUTE_UNUSED readCpuInfo(void *Buf, size_t Size) { } #endif -#if defined(i386) || defined(__i386__) || defined(__x86__) || \ - defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64) || \ - defined(_M_X64) +#if defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64__) || defined(_M_X64) enum VendorSignatures { SIG_INTEL = 0x756e6547 /* Genu */, @@ -109,6 +111,7 @@ enum ProcessorTypes { AMDATHLON, AMDFAM14H, AMDFAM16H, + AMDFAM17H, CPU_TYPE_MAX }; @@ -147,6 +150,7 @@ enum ProcessorSubtypes { AMD_BTVER2, AMDFAM15H_BDVER3, AMDFAM15H_BDVER4, + AMDFAM17H_ZNVER1, CPU_SUBTYPE_MAX }; @@ -169,30 +173,63 @@ enum ProcessorFeatures { FEATURE_EM64T }; +// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max). +// Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID +// support. Consequently, for i386, the presence of CPUID is checked first +// via the corresponding eflags bit. +// Removal of cpuid.h header motivated by PR30384 +// Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp +// or test-suite, but are used in external projects e.g. libstdcxx +static bool isCpuIdSupported() { +#if defined(__GNUC__) || defined(__clang__) +#if defined(__i386__) + int __cpuid_supported; + __asm__(" pushfl\n" + " popl %%eax\n" + " movl %%eax,%%ecx\n" + " xorl $0x00200000,%%eax\n" + " pushl %%eax\n" + " popfl\n" + " pushfl\n" + " popl %%eax\n" + " movl $0,%0\n" + " cmpl %%eax,%%ecx\n" + " je 1f\n" + " movl $1,%0\n" + "1:" + : "=r"(__cpuid_supported) + : + : "eax", "ecx"); + if (!__cpuid_supported) + return false; +#endif + return true; +#endif + return true; +} + /// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in /// the specified arguments. If we can't run cpuid on the host, return true. static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { +#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) #if defined(__GNUC__) || defined(__clang__) -#if defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) - // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. - asm("movq\t%%rbx, %%rsi\n\t" - "cpuid\n\t" - "xchgq\t%%rbx, %%rsi\n\t" - : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) - : "a"(value)); - return false; -#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) - asm("movl\t%%ebx, %%esi\n\t" - "cpuid\n\t" - "xchgl\t%%ebx, %%esi\n\t" - : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) - : "a"(value)); - return false; -// pedantic #else returns to appease -Wunreachable-code (so we don't generate -// postprocessed code that looks like "return true; return false;") +#if defined(__x86_64__) + // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. + // FIXME: should we save this for Clang? + __asm__("movq\t%%rbx, %%rsi\n\t" + "cpuid\n\t" + "xchgq\t%%rbx, %%rsi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value)); +#elif defined(__i386__) + __asm__("movl\t%%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl\t%%ebx, %%esi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value)); #else - return true; + assert(0 && "This method is defined only for x86."); #endif #elif defined(_MSC_VER) // The MSVC intrinsic is portable across x86 and x64. @@ -202,6 +239,7 @@ static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, *rEBX = registers[1]; *rECX = registers[2]; *rEDX = registers[3]; +#endif return false; #else return true; @@ -214,15 +252,16 @@ static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, unsigned *rEAX, unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { -#if defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) +#if defined(__x86_64__) || defined(_M_X64) +#if defined(__GNUC__) || defined(__clang__) // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. - asm("movq\t%%rbx, %%rsi\n\t" - "cpuid\n\t" - "xchgq\t%%rbx, %%rsi\n\t" - : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) - : "a"(value), "c"(subleaf)); - return false; + // FIXME: should we save this for Clang? + __asm__("movq\t%%rbx, %%rsi\n\t" + "cpuid\n\t" + "xchgq\t%%rbx, %%rsi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value), "c"(subleaf)); #elif defined(_MSC_VER) int registers[4]; __cpuidex(registers, value, subleaf); @@ -230,18 +269,14 @@ static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, *rEBX = registers[1]; *rECX = registers[2]; *rEDX = registers[3]; - return false; -#else - return true; #endif -#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) -#if defined(__GNUC__) - asm("movl\t%%ebx, %%esi\n\t" - "cpuid\n\t" - "xchgl\t%%ebx, %%esi\n\t" - : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) - : "a"(value), "c"(subleaf)); - return false; +#elif defined(__i386__) || defined(_M_IX86) +#if defined(__GNUC__) || defined(__clang__) + __asm__("movl\t%%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl\t%%ebx, %%esi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value), "c"(subleaf)); #elif defined(_MSC_VER) __asm { mov eax,value @@ -256,17 +291,18 @@ static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, mov esi,rEDX mov dword ptr [esi],edx } - return false; +#endif #else - return true; + assert(0 && "This method is defined only for x86."); #endif + return false; #else return true; #endif } static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) { -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__clang__) // Check xgetbv; this uses a .byte sequence instead of the instruction // directly because older assemblers do not include support for xgetbv and // there is no easy way to conditionally compile based on the assembler used. @@ -440,15 +476,25 @@ getIntelProcessorTypeAndSubtype(unsigned int Family, unsigned int Model, break; // Skylake: - case 0x4e: - *Type = INTEL_COREI7; // "skylake-avx512" - *Subtype = INTEL_COREI7_SKYLAKE_AVX512; - break; - case 0x5e: + case 0x4e: // Skylake mobile + case 0x5e: // Skylake desktop + case 0x8e: // Kaby Lake mobile + case 0x9e: // Kaby Lake desktop *Type = INTEL_COREI7; // "skylake" *Subtype = INTEL_COREI7_SKYLAKE; break; + // Skylake Xeon: + case 0x55: + *Type = INTEL_COREI7; + // Check that we really have AVX512 + if (Features & (1 << FEATURE_AVX512)) { + *Subtype = INTEL_COREI7_SKYLAKE_AVX512; // "skylake-avx512" + } else { + *Subtype = INTEL_COREI7_SKYLAKE; // "skylake" + } + break; + case 0x1c: // Most 45 nm Intel Atom processors case 0x26: // 45 nm Atom Lincroft case 0x27: // 32 nm Atom Medfield @@ -698,6 +744,14 @@ static void getAMDProcessorTypeAndSubtype(unsigned int Family, } *Subtype = AMD_BTVER2; break; // "btver2" + case 23: + *Type = AMDFAM17H; + if (Features & (1 << FEATURE_ADX)) { + *Subtype = AMDFAM17H_ZNVER1; + break; // "znver1" + } + *Subtype = AMD_BTVER1; + break; default: break; // "generic" } @@ -743,6 +797,14 @@ StringRef sys::getHostCPUName() { unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; unsigned MaxLeaf, Vendor; +#if defined(__GNUC__) || defined(__clang__) + //FIXME: include cpuid.h from clang or copy __get_cpuid_max here + // and simplify it to not invoke __cpuid (like cpu_model.c in + // compiler-rt/lib/builtins/cpu_model.c? + // Opting for the second option. + if(!isCpuIdSupported()) + return "generic"; +#endif if (getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX)) return "generic"; if (getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX)) @@ -898,6 +960,15 @@ StringRef sys::getHostCPUName() { default: return "amdfam16"; } + case AMDFAM17H: + switch (Subtype) { + case AMD_BTVER1: + return "btver1"; + case AMDFAM17H_ZNVER1: + return "znver1"; + default: + return "amdfam17"; + } default: return "generic"; } @@ -1027,6 +1098,7 @@ StringRef sys::getHostCPUName() { .Case("POWER7", "pwr7") .Case("POWER8", "pwr8") .Case("POWER8E", "pwr8") + .Case("POWER8NVL", "pwr8") .Case("POWER9", "pwr9") .Default(generic); } @@ -1148,9 +1220,81 @@ StringRef sys::getHostCPUName() { StringRef sys::getHostCPUName() { return "generic"; } #endif -#if defined(i386) || defined(__i386__) || defined(__x86__) || \ - defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64) || \ - defined(_M_X64) +#if defined(__linux__) && defined(__x86_64__) +// On Linux, the number of physical cores can be computed from /proc/cpuinfo, +// using the number of unique physical/core id pairs. The following +// implementation reads the /proc/cpuinfo format on an x86_64 system. +static int computeHostNumPhysicalCores() { + // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be + // mmapped because it appears to have 0 size. + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = + llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo"); + if (std::error_code EC = Text.getError()) { + llvm::errs() << "Can't read " + << "/proc/cpuinfo: " << EC.message() << "\n"; + } + SmallVector<StringRef, 8> strs; + (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1, + /*KeepEmpty=*/false); + int CurPhysicalId = -1; + int CurCoreId = -1; + SmallSet<std::pair<int, int>, 32> UniqueItems; + for (auto &Line : strs) { + Line = Line.trim(); + if (!Line.startswith("physical id") && !Line.startswith("core id")) + continue; + std::pair<StringRef, StringRef> Data = Line.split(':'); + auto Name = Data.first.trim(); + auto Val = Data.second.trim(); + if (Name == "physical id") { + assert(CurPhysicalId == -1 && + "Expected a core id before seeing another physical id"); + Val.getAsInteger(10, CurPhysicalId); + } + if (Name == "core id") { + assert(CurCoreId == -1 && + "Expected a physical id before seeing another core id"); + Val.getAsInteger(10, CurCoreId); + } + if (CurPhysicalId != -1 && CurCoreId != -1) { + UniqueItems.insert(std::make_pair(CurPhysicalId, CurCoreId)); + CurPhysicalId = -1; + CurCoreId = -1; + } + } + return UniqueItems.size(); +} +#elif defined(__APPLE__) && defined(__x86_64__) +#include <sys/param.h> +#include <sys/sysctl.h> + +// Gets the number of *physical cores* on the machine. +static int computeHostNumPhysicalCores() { + uint32_t count; + size_t len = sizeof(count); + sysctlbyname("hw.physicalcpu", &count, &len, NULL, 0); + if (count < 1) { + int nm[2]; + nm[0] = CTL_HW; + nm[1] = HW_AVAILCPU; + sysctl(nm, 2, &count, &len, NULL, 0); + if (count < 1) + return -1; + } + return count; +} +#else +// On other systems, return -1 to indicate unknown. +static int computeHostNumPhysicalCores() { return -1; } +#endif + +int sys::getHostNumPhysicalCores() { + static int NumCores = computeHostNumPhysicalCores(); + return NumCores; +} + +#if defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64__) || defined(_M_X64) bool sys::getHostCPUFeatures(StringMap<bool> &Features) { unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; unsigned MaxLevel; diff --git a/contrib/llvm/lib/Support/IntrusiveRefCntPtr.cpp b/contrib/llvm/lib/Support/IntrusiveRefCntPtr.cpp deleted file mode 100644 index a8b4559..0000000 --- a/contrib/llvm/lib/Support/IntrusiveRefCntPtr.cpp +++ /dev/null @@ -1,14 +0,0 @@ -//== IntrusiveRefCntPtr.cpp - Smart Refcounting Pointer ----------*- C++ -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/IntrusiveRefCntPtr.h" - -using namespace llvm; - -void RefCountedBaseVPTR::anchor() { } diff --git a/contrib/llvm/lib/Support/LockFileManager.cpp b/contrib/llvm/lib/Support/LockFileManager.cpp index 611f94a..444aaa3 100644 --- a/contrib/llvm/lib/Support/LockFileManager.cpp +++ b/contrib/llvm/lib/Support/LockFileManager.cpp @@ -6,13 +6,22 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// + #include "llvm/Support/LockFileManager.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Errc.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" +#include <cerrno> +#include <ctime> +#include <memory> +#include <tuple> +#include <system_error> #include <sys/stat.h> #include <sys/types.h> #if LLVM_ON_WIN32 @@ -31,6 +40,7 @@ #if USE_OSX_GETHOSTUUID #include <uuid/uuid.h> #endif + using namespace llvm; /// \brief Attempt to read the lock file with the given name, if it exists. @@ -112,6 +122,7 @@ bool LockFileManager::processStillExecuting(StringRef HostID, int PID) { } namespace { + /// An RAII helper object ensure that the unique lock file is removed. /// /// Ensures that if there is an error or a signal before we finish acquiring the @@ -127,6 +138,7 @@ public: : Filename(Name), RemoveImmediately(true) { sys::RemoveFileOnSignal(Filename, nullptr); } + ~RemoveUniqueLockFileOnSignal() { if (!RemoveImmediately) { // Leave the signal handler enabled. It will be removed when the lock is @@ -136,8 +148,10 @@ public: sys::fs::remove(Filename); sys::DontRemoveFileOnSignal(Filename); } + void lockAcquired() { RemoveImmediately = false; } }; + } // end anonymous namespace LockFileManager::LockFileManager(StringRef FileName) @@ -202,7 +216,7 @@ LockFileManager::LockFileManager(StringRef FileName) // held since the .lock symlink will point to a nonexistent file. RemoveUniqueLockFileOnSignal RemoveUniqueFile(UniqueLockFileName); - while (1) { + while (true) { // Create a link from the lock file name. If this succeeds, we're done. std::error_code EC = sys::fs::create_link(UniqueLockFileName, LockFileName); diff --git a/contrib/llvm/lib/Support/MD5.cpp b/contrib/llvm/lib/Support/MD5.cpp index ceab580..942571e 100644 --- a/contrib/llvm/lib/Support/MD5.cpp +++ b/contrib/llvm/lib/Support/MD5.cpp @@ -248,33 +248,15 @@ void MD5::final(MD5Result &Result) { memset(&buffer[used], 0, free - 8); lo <<= 3; - buffer[56] = lo; - buffer[57] = lo >> 8; - buffer[58] = lo >> 16; - buffer[59] = lo >> 24; - buffer[60] = hi; - buffer[61] = hi >> 8; - buffer[62] = hi >> 16; - buffer[63] = hi >> 24; + support::endian::write32le(&buffer[56], lo); + support::endian::write32le(&buffer[60], hi); body(makeArrayRef(buffer, 64)); - Result[0] = a; - Result[1] = a >> 8; - Result[2] = a >> 16; - Result[3] = a >> 24; - Result[4] = b; - Result[5] = b >> 8; - Result[6] = b >> 16; - Result[7] = b >> 24; - Result[8] = c; - Result[9] = c >> 8; - Result[10] = c >> 16; - Result[11] = c >> 24; - Result[12] = d; - Result[13] = d >> 8; - Result[14] = d >> 16; - Result[15] = d >> 24; + support::endian::write32le(&Result[0], a); + support::endian::write32le(&Result[4], b); + support::endian::write32le(&Result[8], c); + support::endian::write32le(&Result[12], d); } void MD5::stringifyResult(MD5Result &Result, SmallString<32> &Str) { @@ -283,4 +265,14 @@ void MD5::stringifyResult(MD5Result &Result, SmallString<32> &Str) { Res << format("%.2x", Result[i]); } +std::array<uint8_t, 16> MD5::hash(ArrayRef<uint8_t> Data) { + MD5 Hash; + Hash.update(Data); + MD5::MD5Result Res; + Hash.final(Res); + + std::array<uint8_t, 16> Arr; + memcpy(Arr.data(), Res, sizeof(Res)); + return Arr; +} } diff --git a/contrib/llvm/lib/Support/MemoryBuffer.cpp b/contrib/llvm/lib/Support/MemoryBuffer.cpp index b935cbf..a3a18c9 100644 --- a/contrib/llvm/lib/Support/MemoryBuffer.cpp +++ b/contrib/llvm/lib/Support/MemoryBuffer.cpp @@ -90,9 +90,9 @@ public: /// tail-allocated data. void operator delete(void *p) { ::operator delete(p); } - const char *getBufferIdentifier() const override { - // The name is stored after the class itself. - return reinterpret_cast<const char*>(this + 1); + StringRef getBufferIdentifier() const override { + // The name is stored after the class itself. + return StringRef(reinterpret_cast<const char *>(this + 1)); } BufferKind getBufferKind() const override { @@ -221,9 +221,9 @@ public: /// tail-allocated data. void operator delete(void *p) { ::operator delete(p); } - const char *getBufferIdentifier() const override { + StringRef getBufferIdentifier() const override { // The name is stored after the class itself. - return reinterpret_cast<const char *>(this + 1); + return StringRef(reinterpret_cast<const char *>(this + 1)); } BufferKind getBufferKind() const override { @@ -438,6 +438,18 @@ ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() { return getMemoryBufferForStream(0, "<stdin>"); } +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getFileAsStream(const Twine &Filename) { + int FD; + std::error_code EC = sys::fs::openFileForRead(Filename, FD); + if (EC) + return EC; + ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = + getMemoryBufferForStream(FD, Filename); + close(FD); + return Ret; +} + MemoryBufferRef MemoryBuffer::getMemBufferRef() const { StringRef Data = getBuffer(); StringRef Identifier = getBufferIdentifier(); diff --git a/contrib/llvm/lib/Support/MemoryObject.cpp b/contrib/llvm/lib/Support/MemoryObject.cpp deleted file mode 100644 index d796acf..0000000 --- a/contrib/llvm/lib/Support/MemoryObject.cpp +++ /dev/null @@ -1,14 +0,0 @@ -//===- MemoryObject.cpp - Abstract memory interface -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/MemoryObject.h" -using namespace llvm; - -MemoryObject::~MemoryObject() { -} diff --git a/contrib/llvm/lib/Support/NativeFormatting.cpp b/contrib/llvm/lib/Support/NativeFormatting.cpp new file mode 100644 index 0000000..b951a88 --- /dev/null +++ b/contrib/llvm/lib/Support/NativeFormatting.cpp @@ -0,0 +1,262 @@ +//===- NativeFormatting.cpp - Low level formatting helpers -------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/NativeFormatting.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Format.h" + +using namespace llvm; + +template<typename T, std::size_t N> +static int format_to_buffer(T Value, char (&Buffer)[N]) { + char *EndPtr = std::end(Buffer); + char *CurPtr = EndPtr; + + do { + *--CurPtr = '0' + char(Value % 10); + Value /= 10; + } while (Value); + return EndPtr - CurPtr; +} + +static void writeWithCommas(raw_ostream &S, ArrayRef<char> Buffer) { + assert(!Buffer.empty()); + + ArrayRef<char> ThisGroup; + int InitialDigits = ((Buffer.size() - 1) % 3) + 1; + ThisGroup = Buffer.take_front(InitialDigits); + S.write(ThisGroup.data(), ThisGroup.size()); + + Buffer = Buffer.drop_front(InitialDigits); + assert(Buffer.size() % 3 == 0); + while (!Buffer.empty()) { + S << ','; + ThisGroup = Buffer.take_front(3); + S.write(ThisGroup.data(), 3); + Buffer = Buffer.drop_front(3); + } +} + +template <typename T> +static void write_unsigned_impl(raw_ostream &S, T N, size_t MinDigits, + IntegerStyle Style, bool IsNegative) { + static_assert(std::is_unsigned<T>::value, "Value is not unsigned!"); + + char NumberBuffer[128]; + std::memset(NumberBuffer, '0', sizeof(NumberBuffer)); + + size_t Len = 0; + Len = format_to_buffer(N, NumberBuffer); + + if (IsNegative) + S << '-'; + + if (Len < MinDigits && Style != IntegerStyle::Number) { + for (size_t I = Len; I < MinDigits; ++I) + S << '0'; + } + + if (Style == IntegerStyle::Number) { + writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len)); + } else { + S.write(std::end(NumberBuffer) - Len, Len); + } +} + +template <typename T> +static void write_unsigned(raw_ostream &S, T N, size_t MinDigits, + IntegerStyle Style, bool IsNegative = false) { + // Output using 32-bit div/mod if possible. + if (N == static_cast<uint32_t>(N)) + write_unsigned_impl(S, static_cast<uint32_t>(N), MinDigits, Style, + IsNegative); + else + write_unsigned_impl(S, N, MinDigits, Style, IsNegative); +} + +template <typename T> +static void write_signed(raw_ostream &S, T N, size_t MinDigits, + IntegerStyle Style) { + static_assert(std::is_signed<T>::value, "Value is not signed!"); + + using UnsignedT = typename std::make_unsigned<T>::type; + + if (N >= 0) { + write_unsigned(S, static_cast<UnsignedT>(N), MinDigits, Style); + return; + } + + UnsignedT UN = -(UnsignedT)N; + write_unsigned(S, UN, MinDigits, Style, true); +} + +void llvm::write_integer(raw_ostream &S, unsigned int N, size_t MinDigits, + IntegerStyle Style) { + write_unsigned(S, N, MinDigits, Style); +} + +void llvm::write_integer(raw_ostream &S, int N, size_t MinDigits, + IntegerStyle Style) { + write_signed(S, N, MinDigits, Style); +} + +void llvm::write_integer(raw_ostream &S, unsigned long N, size_t MinDigits, + IntegerStyle Style) { + write_unsigned(S, N, MinDigits, Style); +} + +void llvm::write_integer(raw_ostream &S, long N, size_t MinDigits, + IntegerStyle Style) { + write_signed(S, N, MinDigits, Style); +} + +void llvm::write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits, + IntegerStyle Style) { + write_unsigned(S, N, MinDigits, Style); +} + +void llvm::write_integer(raw_ostream &S, long long N, size_t MinDigits, + IntegerStyle Style) { + write_signed(S, N, MinDigits, Style); +} + +void llvm::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, + Optional<size_t> Width) { + const size_t kMaxWidth = 128u; + + size_t W = std::min(kMaxWidth, Width.getValueOr(0u)); + + unsigned Nibbles = (64 - countLeadingZeros(N) + 3) / 4; + bool Prefix = (Style == HexPrintStyle::PrefixLower || + Style == HexPrintStyle::PrefixUpper); + bool Upper = + (Style == HexPrintStyle::Upper || Style == HexPrintStyle::PrefixUpper); + unsigned PrefixChars = Prefix ? 2 : 0; + unsigned NumChars = + std::max(static_cast<unsigned>(W), std::max(1u, Nibbles) + PrefixChars); + + char NumberBuffer[kMaxWidth]; + ::memset(NumberBuffer, '0', llvm::array_lengthof(NumberBuffer)); + if (Prefix) + NumberBuffer[1] = 'x'; + char *EndPtr = NumberBuffer + NumChars; + char *CurPtr = EndPtr; + while (N) { + unsigned char x = static_cast<unsigned char>(N) % 16; + *--CurPtr = hexdigit(x, !Upper); + N /= 16; + } + + S.write(NumberBuffer, NumChars); +} + +void llvm::write_double(raw_ostream &S, double N, FloatStyle Style, + Optional<size_t> Precision) { + size_t Prec = Precision.getValueOr(getDefaultPrecision(Style)); + + if (std::isnan(N)) { + S << "nan"; + return; + } else if (std::isinf(N)) { + S << "INF"; + return; + } + + char Letter; + if (Style == FloatStyle::Exponent) + Letter = 'e'; + else if (Style == FloatStyle::ExponentUpper) + Letter = 'E'; + else + Letter = 'f'; + + SmallString<8> Spec; + llvm::raw_svector_ostream Out(Spec); + Out << "%." << Prec << Letter; + + if (Style == FloatStyle::Exponent || Style == FloatStyle::ExponentUpper) { +#ifdef _WIN32 +// On MSVCRT and compatible, output of %e is incompatible to Posix +// by default. Number of exponent digits should be at least 2. "%+03d" +// FIXME: Implement our formatter to here or Support/Format.h! +#if defined(__MINGW32__) + // FIXME: It should be generic to C++11. + if (N == 0.0 && std::signbit(N)) { + char NegativeZero[] = "-0.000000e+00"; + if (Style == FloatStyle::ExponentUpper) + NegativeZero[strlen(NegativeZero) - 4] = 'E'; + S << NegativeZero; + return; + } +#else + int fpcl = _fpclass(N); + + // negative zero + if (fpcl == _FPCLASS_NZ) { + char NegativeZero[] = "-0.000000e+00"; + if (Style == FloatStyle::ExponentUpper) + NegativeZero[strlen(NegativeZero) - 4] = 'E'; + S << NegativeZero; + return; + } +#endif + + char buf[32]; + unsigned len; + len = format(Spec.c_str(), N).snprint(buf, sizeof(buf)); + if (len <= sizeof(buf) - 2) { + if (len >= 5 && (buf[len - 5] == 'e' || buf[len - 5] == 'E') && + buf[len - 3] == '0') { + int cs = buf[len - 4]; + if (cs == '+' || cs == '-') { + int c1 = buf[len - 2]; + int c0 = buf[len - 1]; + if (isdigit(static_cast<unsigned char>(c1)) && + isdigit(static_cast<unsigned char>(c0))) { + // Trim leading '0': "...e+012" -> "...e+12\0" + buf[len - 3] = c1; + buf[len - 2] = c0; + buf[--len] = 0; + } + } + } + S << buf; + return; + } +#endif + } + + if (Style == FloatStyle::Percent) + N *= 100.0; + + char Buf[32]; + format(Spec.c_str(), N).snprint(Buf, sizeof(Buf)); + S << Buf; + if (Style == FloatStyle::Percent) + S << '%'; +} + +bool llvm::isPrefixedHexStyle(HexPrintStyle S) { + return (S == HexPrintStyle::PrefixLower || S == HexPrintStyle::PrefixUpper); +} + +size_t llvm::getDefaultPrecision(FloatStyle Style) { + switch (Style) { + case FloatStyle::Exponent: + case FloatStyle::ExponentUpper: + return 6; // Number of decimal places. + case FloatStyle::Fixed: + case FloatStyle::Percent: + return 2; // Number of decimal places. + } + LLVM_BUILTIN_UNREACHABLE; +} diff --git a/contrib/llvm/lib/Support/Path.cpp b/contrib/llvm/lib/Support/Path.cpp index f6355d1..4bb035e 100644 --- a/contrib/llvm/lib/Support/Path.cpp +++ b/contrib/llvm/lib/Support/Path.cpp @@ -571,6 +571,16 @@ void native(SmallVectorImpl<char> &Path) { #endif } +std::string convert_to_slash(StringRef path) { +#ifdef LLVM_ON_WIN32 + std::string s = path.str(); + std::replace(s.begin(), s.end(), '\\', '/'); + return s; +#else + return path; +#endif +} + StringRef filename(StringRef path) { return *rbegin(path); } @@ -707,12 +717,14 @@ static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot) { for (StringRef C : llvm::make_range(path::begin(rel), path::end(rel))) { if (C == ".") continue; - if (remove_dot_dot) { - if (C == "..") { - if (!components.empty()) - components.pop_back(); + // Leading ".." will remain in the path unless it's at the root. + if (remove_dot_dot && C == "..") { + if (!components.empty() && components.back() != "..") { + components.pop_back(); continue; } + if (path::is_absolute(path)) + continue; } components.push_back(C); } @@ -978,62 +990,59 @@ void directory_entry::replace_filename(const Twine &filename, file_status st) { Status = st; } +template <size_t N> +static bool startswith(StringRef Magic, const char (&S)[N]) { + return Magic.startswith(StringRef(S, N - 1)); +} + /// @brief Identify the magic in magic. file_magic identify_magic(StringRef Magic) { if (Magic.size() < 4) return file_magic::unknown; switch ((unsigned char)Magic[0]) { case 0x00: { - // COFF bigobj or short import library file - if (Magic[1] == (char)0x00 && Magic[2] == (char)0xff && - Magic[3] == (char)0xff) { + // COFF bigobj, CL.exe's LTO object file, or short import library file + if (startswith(Magic, "\0\0\xFF\xFF")) { size_t MinSize = offsetof(COFF::BigObjHeader, UUID) + sizeof(COFF::BigObjMagic); if (Magic.size() < MinSize) return file_magic::coff_import_library; - int BigObjVersion = read16le( - Magic.data() + offsetof(COFF::BigObjHeader, Version)); - if (BigObjVersion < COFF::BigObjHeader::MinBigObjectVersion) - return file_magic::coff_import_library; - const char *Start = Magic.data() + offsetof(COFF::BigObjHeader, UUID); - if (memcmp(Start, COFF::BigObjMagic, sizeof(COFF::BigObjMagic)) != 0) - return file_magic::coff_import_library; - return file_magic::coff_object; + if (memcmp(Start, COFF::BigObjMagic, sizeof(COFF::BigObjMagic)) == 0) + return file_magic::coff_object; + if (memcmp(Start, COFF::ClGlObjMagic, sizeof(COFF::BigObjMagic)) == 0) + return file_magic::coff_cl_gl_object; + return file_magic::coff_import_library; } // Windows resource file - const char Expected[] = { 0, 0, 0, 0, '\x20', 0, 0, 0, '\xff' }; - if (Magic.size() >= sizeof(Expected) && - memcmp(Magic.data(), Expected, sizeof(Expected)) == 0) + if (startswith(Magic, "\0\0\0\0\x20\0\0\0\xFF")) return file_magic::windows_resource; // 0x0000 = COFF unknown machine type if (Magic[1] == 0) return file_magic::coff_object; + if (startswith(Magic, "\0asm")) + return file_magic::wasm_object; break; } case 0xDE: // 0x0B17C0DE = BC wraper - if (Magic[1] == (char)0xC0 && Magic[2] == (char)0x17 && - Magic[3] == (char)0x0B) + if (startswith(Magic, "\xDE\xC0\x17\x0B")) return file_magic::bitcode; break; case 'B': - if (Magic[1] == 'C' && Magic[2] == (char)0xC0 && Magic[3] == (char)0xDE) + if (startswith(Magic, "BC\xC0\xDE")) return file_magic::bitcode; break; case '!': - if (Magic.size() >= 8) - if (memcmp(Magic.data(), "!<arch>\n", 8) == 0 || - memcmp(Magic.data(), "!<thin>\n", 8) == 0) - return file_magic::archive; + if (startswith(Magic, "!<arch>\n") || startswith(Magic, "!<thin>\n")) + return file_magic::archive; break; case '\177': - if (Magic.size() >= 18 && Magic[1] == 'E' && Magic[2] == 'L' && - Magic[3] == 'F') { + if (startswith(Magic, "\177ELF") && Magic.size() >= 18) { bool Data2MSB = Magic[5] == 2; unsigned high = Data2MSB ? 16 : 17; unsigned low = Data2MSB ? 17 : 16; - if (Magic[high] == 0) + if (Magic[high] == 0) { switch (Magic[low]) { default: return file_magic::elf; case 1: return file_magic::elf_relocatable; @@ -1041,15 +1050,15 @@ file_magic identify_magic(StringRef Magic) { case 3: return file_magic::elf_shared_object; case 4: return file_magic::elf_core; } - else - // It's still some type of ELF file. - return file_magic::elf; + } + // It's still some type of ELF file. + return file_magic::elf; } break; case 0xCA: - if (Magic[1] == char(0xFE) && Magic[2] == char(0xBA) && - (Magic[3] == char(0xBE) || Magic[3] == char(0xBF))) { + if (startswith(Magic, "\xCA\xFE\xBA\xBE") || + startswith(Magic, "\xCA\xFE\xBA\xBF")) { // This is complicated by an overlap with Java class files. // See the Mach-O section in /usr/share/file/magic for details. if (Magic.size() >= 8 && Magic[7] < 43) @@ -1064,9 +1073,8 @@ file_magic identify_magic(StringRef Magic) { case 0xCE: case 0xCF: { uint16_t type = 0; - if (Magic[0] == char(0xFE) && Magic[1] == char(0xED) && - Magic[2] == char(0xFA) && - (Magic[3] == char(0xCE) || Magic[3] == char(0xCF))) { + if (startswith(Magic, "\xFE\xED\xFA\xCE") || + startswith(Magic, "\xFE\xED\xFA\xCF")) { /* Native endian */ size_t MinSize; if (Magic[3] == char(0xCE)) @@ -1075,9 +1083,8 @@ file_magic identify_magic(StringRef Magic) { MinSize = sizeof(MachO::mach_header_64); if (Magic.size() >= MinSize) type = Magic[12] << 24 | Magic[13] << 12 | Magic[14] << 8 | Magic[15]; - } else if ((Magic[0] == char(0xCE) || Magic[0] == char(0xCF)) && - Magic[1] == char(0xFA) && Magic[2] == char(0xED) && - Magic[3] == char(0xFE)) { + } else if (startswith(Magic, "\xCE\xFA\xED\xFE") || + startswith(Magic, "\xCF\xFA\xED\xFE")) { /* Reverse endian */ size_t MinSize; if (Magic[0] == char(0xCE)) @@ -1120,7 +1127,7 @@ file_magic identify_magic(StringRef Magic) { break; case 'M': // Possible MS-DOS stub on Windows PE file - if (Magic[1] == 'Z') { + if (startswith(Magic, "MZ")) { uint32_t off = read32le(Magic.data() + 0x3c); // PE/COFF file, either EXE or DLL. if (off < Magic.size() && diff --git a/contrib/llvm/lib/Support/PrettyStackTrace.cpp b/contrib/llvm/lib/Support/PrettyStackTrace.cpp index ebad67b..5b079ff 100644 --- a/contrib/llvm/lib/Support/PrettyStackTrace.cpp +++ b/contrib/llvm/lib/Support/PrettyStackTrace.cpp @@ -21,6 +21,7 @@ #include "llvm/Support/Watchdog.h" #include "llvm/Support/raw_ostream.h" +#include <cstdarg> #include <tuple> #ifdef HAVE_CRASHREPORTERCLIENT_H @@ -32,7 +33,7 @@ using namespace llvm; // If backtrace support is not enabled, compile out support for pretty stack // traces. This has the secondary effect of not requiring thread local storage // when backtrace support is disabled. -#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES // We need a thread local pointer to manage the stack of our stack trace // objects, but we *really* cannot tolerate destructors running and do not want @@ -79,7 +80,7 @@ static void PrintCurStackTrace(raw_ostream &OS) { } // Integrate with crash reporter libraries. -#if defined (__APPLE__) && HAVE_CRASHREPORTERCLIENT_H +#if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H) // If any clients of llvm try to link to libCrashReporterClient.a themselves, // only one crash info struct will be used. extern "C" { @@ -88,12 +89,12 @@ struct crashreporter_annotations_t gCRAnnotations __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 }; } -#elif defined (__APPLE__) && HAVE_CRASHREPORTER_INFO -static const char *__crashreporter_info__ = 0; +#elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO +extern "C" const char *__crashreporter_info__ + __attribute__((visibility("hidden"))) = 0; asm(".desc ___crashreporter_info__, 0x10"); #endif - /// CrashHandler - This callback is run if a fatal signal is delivered to the /// process, it prints the pretty stack trace. static void CrashHandler(void *) { @@ -122,11 +123,11 @@ static void CrashHandler(void *) { #endif } -// defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +// defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES #endif PrettyStackTraceEntry::PrettyStackTraceEntry() { -#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES // Link ourselves. NextEntry = PrettyStackTraceHead; PrettyStackTraceHead = this; @@ -134,17 +135,33 @@ PrettyStackTraceEntry::PrettyStackTraceEntry() { } PrettyStackTraceEntry::~PrettyStackTraceEntry() { -#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES assert(PrettyStackTraceHead == this && "Pretty stack trace entry destruction is out of order"); PrettyStackTraceHead = NextEntry; #endif } -void PrettyStackTraceString::print(raw_ostream &OS) const { - OS << Str << "\n"; +void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; } + +PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) { + va_list AP; + va_start(AP, Format); + const int SizeOrError = vsnprintf(nullptr, 0, Format, AP); + va_end(AP); + if (SizeOrError < 0) { + return; + } + + const int Size = SizeOrError + 1; // '\0' + Str.resize(Size); + va_start(AP, Format); + vsnprintf(Str.data(), Size, Format, AP); + va_end(AP); } +void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; } + void PrettyStackTraceProgram::print(raw_ostream &OS) const { OS << "Program arguments: "; // Print the argument list. @@ -153,7 +170,7 @@ void PrettyStackTraceProgram::print(raw_ostream &OS) const { OS << '\n'; } -#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES static bool RegisterCrashPrinter() { sys::AddSignalHandler(CrashHandler, nullptr); return false; @@ -161,7 +178,7 @@ static bool RegisterCrashPrinter() { #endif void llvm::EnablePrettyStackTrace() { -#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES // The first time this is called, we register the crash printer. static bool HandlerRegistered = RegisterCrashPrinter(); (void)HandlerRegistered; @@ -169,7 +186,7 @@ void llvm::EnablePrettyStackTrace() { } const void *llvm::SavePrettyStackState() { -#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES return PrettyStackTraceHead; #else return nullptr; @@ -177,7 +194,7 @@ const void *llvm::SavePrettyStackState() { } void llvm::RestorePrettyStackState(const void *Top) { -#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES PrettyStackTraceHead = static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top)); #endif diff --git a/contrib/llvm/lib/Support/RandomNumberGenerator.cpp b/contrib/llvm/lib/Support/RandomNumberGenerator.cpp index 81d0411..8ea02d7 100644 --- a/contrib/llvm/lib/Support/RandomNumberGenerator.cpp +++ b/contrib/llvm/lib/Support/RandomNumberGenerator.cpp @@ -17,6 +17,11 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#ifdef LLVM_ON_WIN32 +#include "Windows/WindowsSupport.h" +#else +#include "Unix/Unix.h" +#endif using namespace llvm; @@ -42,16 +47,45 @@ RandomNumberGenerator::RandomNumberGenerator(StringRef Salt) { // are using a 64-bit RNG. This isn't a problem since the Mersenne // twister constructor copies these correctly into its initial state. std::vector<uint32_t> Data; - Data.reserve(2 + Salt.size()); - Data.push_back(Seed); - Data.push_back(Seed >> 32); + Data.resize(2 + Salt.size()); + Data[0] = Seed; + Data[1] = Seed >> 32; - std::copy(Salt.begin(), Salt.end(), Data.end()); + std::copy(Salt.begin(), Salt.end(), Data.begin() + 2); std::seed_seq SeedSeq(Data.begin(), Data.end()); Generator.seed(SeedSeq); } -uint_fast64_t RandomNumberGenerator::operator()() { +RandomNumberGenerator::result_type RandomNumberGenerator::operator()() { return Generator(); } + +// Get random vector of specified size +std::error_code llvm::getRandomBytes(void *Buffer, size_t Size) { +#ifdef LLVM_ON_WIN32 + HCRYPTPROV hProvider; + if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { + ScopedCryptContext ScopedHandle(hProvider); + if (CryptGenRandom(hProvider, Size, static_cast<BYTE *>(Buffer))) + return std::error_code(); + } + return std::error_code(GetLastError(), std::system_category()); +#else + int Fd = open("/dev/urandom", O_RDONLY); + if (Fd != -1) { + std::error_code Ret; + ssize_t BytesRead = read(Fd, Buffer, Size); + if (BytesRead == -1) + Ret = std::error_code(errno, std::system_category()); + else if (BytesRead != static_cast<ssize_t>(Size)) + Ret = std::error_code(EIO, std::system_category()); + if (close(Fd) == -1) + Ret = std::error_code(errno, std::system_category()); + + return Ret; + } + return std::error_code(errno, std::system_category()); +#endif +} diff --git a/contrib/llvm/lib/Support/Regex.cpp b/contrib/llvm/lib/Support/Regex.cpp index e8344ef..68ba79e 100644 --- a/contrib/llvm/lib/Support/Regex.cpp +++ b/contrib/llvm/lib/Support/Regex.cpp @@ -19,6 +19,8 @@ #include <string> using namespace llvm; +Regex::Regex() : preg(nullptr), error(REG_BADPAT) {} + Regex::Regex(StringRef regex, unsigned Flags) { unsigned flags = 0; preg = new llvm_regex(); @@ -32,6 +34,13 @@ Regex::Regex(StringRef regex, unsigned Flags) { error = llvm_regcomp(preg, regex.data(), flags|REG_PEND); } +Regex::Regex(Regex &®ex) { + preg = regex.preg; + error = regex.error; + regex.preg = nullptr; + regex.error = REG_BADPAT; +} + Regex::~Regex() { if (preg) { llvm_regfree(preg); @@ -57,6 +66,9 @@ unsigned Regex::getNumMatches() const { } bool Regex::match(StringRef String, SmallVectorImpl<StringRef> *Matches){ + if (error) + return false; + unsigned nmatch = Matches ? preg->re_nsub+1 : 0; // pmatch needs to have at least one element. diff --git a/contrib/llvm/lib/Support/SHA1.cpp b/contrib/llvm/lib/Support/SHA1.cpp index a461d1e..0eefd99 100644 --- a/contrib/llvm/lib/Support/SHA1.cpp +++ b/contrib/llvm/lib/Support/SHA1.cpp @@ -6,8 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// // This code is taken from public domain -// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c) +// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c and +// http://cvsweb.netbsd.org/bsdweb.cgi/src/common/lib/libc/hash/sha1/sha1.c?rev=1.6) // and modified by wrapping it in a C++ interface for LLVM, // and removing unnecessary code. // @@ -25,6 +27,49 @@ using namespace llvm; #define SHA_BIG_ENDIAN #endif +static 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 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) { + 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) { + 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) { + 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) { + 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) { + E += (B ^ C ^ D) + blk(Buf, I) + 0xCA62C1D6 + rol(A, 5); + B = rol(B, 30); +} + /* code */ #define SHA1_K0 0x5a827999 #define SHA1_K20 0x6ed9eba1 @@ -47,56 +92,112 @@ void SHA1::init() { InternalState.BufferOffset = 0; } -static uint32_t rol32(uint32_t number, uint8_t bits) { - return ((number << bits) | (number >> (32 - bits))); -} - void SHA1::hashBlock() { - uint8_t i; - uint32_t a, b, c, d, e, t; - - a = InternalState.State[0]; - b = InternalState.State[1]; - c = InternalState.State[2]; - d = InternalState.State[3]; - e = InternalState.State[4]; - for (i = 0; i < 80; i++) { - if (i >= 16) { - t = InternalState.Buffer[(i + 13) & 15] ^ - InternalState.Buffer[(i + 8) & 15] ^ - InternalState.Buffer[(i + 2) & 15] ^ InternalState.Buffer[i & 15]; - InternalState.Buffer[i & 15] = rol32(t, 1); - } - if (i < 20) { - t = (d ^ (b & (c ^ d))) + SHA1_K0; - } else if (i < 40) { - t = (b ^ c ^ d) + SHA1_K20; - } else if (i < 60) { - t = ((b & c) | (d & (b | c))) + SHA1_K40; - } else { - t = (b ^ c ^ d) + SHA1_K60; - } - t += rol32(a, 5) + e + InternalState.Buffer[i & 15]; - e = d; - d = c; - c = rol32(b, 30); - b = a; - a = t; - } - InternalState.State[0] += a; - InternalState.State[1] += b; - InternalState.State[2] += c; - InternalState.State[3] += d; - InternalState.State[4] += e; + uint32_t A = InternalState.State[0]; + uint32_t B = InternalState.State[1]; + uint32_t C = InternalState.State[2]; + uint32_t D = InternalState.State[3]; + uint32_t E = InternalState.State[4]; + + // 4 rounds of 20 operations each. Loop unrolled. + r0(A, B, C, D, E, 0, InternalState.Buffer.L); + r0(E, A, B, C, D, 1, InternalState.Buffer.L); + r0(D, E, A, B, C, 2, InternalState.Buffer.L); + r0(C, D, E, A, B, 3, InternalState.Buffer.L); + r0(B, C, D, E, A, 4, InternalState.Buffer.L); + r0(A, B, C, D, E, 5, InternalState.Buffer.L); + r0(E, A, B, C, D, 6, InternalState.Buffer.L); + r0(D, E, A, B, C, 7, InternalState.Buffer.L); + r0(C, D, E, A, B, 8, InternalState.Buffer.L); + r0(B, C, D, E, A, 9, InternalState.Buffer.L); + r0(A, B, C, D, E, 10, InternalState.Buffer.L); + r0(E, A, B, C, D, 11, InternalState.Buffer.L); + r0(D, E, A, B, C, 12, InternalState.Buffer.L); + r0(C, D, E, A, B, 13, InternalState.Buffer.L); + r0(B, C, D, E, A, 14, InternalState.Buffer.L); + r0(A, B, C, D, E, 15, InternalState.Buffer.L); + r1(E, A, B, C, D, 16, InternalState.Buffer.L); + r1(D, E, A, B, C, 17, InternalState.Buffer.L); + r1(C, D, E, A, B, 18, InternalState.Buffer.L); + r1(B, C, D, E, A, 19, InternalState.Buffer.L); + + r2(A, B, C, D, E, 20, InternalState.Buffer.L); + r2(E, A, B, C, D, 21, InternalState.Buffer.L); + r2(D, E, A, B, C, 22, InternalState.Buffer.L); + r2(C, D, E, A, B, 23, InternalState.Buffer.L); + r2(B, C, D, E, A, 24, InternalState.Buffer.L); + r2(A, B, C, D, E, 25, InternalState.Buffer.L); + r2(E, A, B, C, D, 26, InternalState.Buffer.L); + r2(D, E, A, B, C, 27, InternalState.Buffer.L); + r2(C, D, E, A, B, 28, InternalState.Buffer.L); + r2(B, C, D, E, A, 29, InternalState.Buffer.L); + r2(A, B, C, D, E, 30, InternalState.Buffer.L); + r2(E, A, B, C, D, 31, InternalState.Buffer.L); + r2(D, E, A, B, C, 32, InternalState.Buffer.L); + r2(C, D, E, A, B, 33, InternalState.Buffer.L); + r2(B, C, D, E, A, 34, InternalState.Buffer.L); + r2(A, B, C, D, E, 35, InternalState.Buffer.L); + r2(E, A, B, C, D, 36, InternalState.Buffer.L); + r2(D, E, A, B, C, 37, InternalState.Buffer.L); + r2(C, D, E, A, B, 38, InternalState.Buffer.L); + r2(B, C, D, E, A, 39, InternalState.Buffer.L); + + r3(A, B, C, D, E, 40, InternalState.Buffer.L); + r3(E, A, B, C, D, 41, InternalState.Buffer.L); + r3(D, E, A, B, C, 42, InternalState.Buffer.L); + r3(C, D, E, A, B, 43, InternalState.Buffer.L); + r3(B, C, D, E, A, 44, InternalState.Buffer.L); + r3(A, B, C, D, E, 45, InternalState.Buffer.L); + r3(E, A, B, C, D, 46, InternalState.Buffer.L); + r3(D, E, A, B, C, 47, InternalState.Buffer.L); + r3(C, D, E, A, B, 48, InternalState.Buffer.L); + r3(B, C, D, E, A, 49, InternalState.Buffer.L); + r3(A, B, C, D, E, 50, InternalState.Buffer.L); + r3(E, A, B, C, D, 51, InternalState.Buffer.L); + r3(D, E, A, B, C, 52, InternalState.Buffer.L); + r3(C, D, E, A, B, 53, InternalState.Buffer.L); + r3(B, C, D, E, A, 54, InternalState.Buffer.L); + r3(A, B, C, D, E, 55, InternalState.Buffer.L); + r3(E, A, B, C, D, 56, InternalState.Buffer.L); + r3(D, E, A, B, C, 57, InternalState.Buffer.L); + r3(C, D, E, A, B, 58, InternalState.Buffer.L); + r3(B, C, D, E, A, 59, InternalState.Buffer.L); + + r4(A, B, C, D, E, 60, InternalState.Buffer.L); + r4(E, A, B, C, D, 61, InternalState.Buffer.L); + r4(D, E, A, B, C, 62, InternalState.Buffer.L); + r4(C, D, E, A, B, 63, InternalState.Buffer.L); + r4(B, C, D, E, A, 64, InternalState.Buffer.L); + r4(A, B, C, D, E, 65, InternalState.Buffer.L); + r4(E, A, B, C, D, 66, InternalState.Buffer.L); + r4(D, E, A, B, C, 67, InternalState.Buffer.L); + r4(C, D, E, A, B, 68, InternalState.Buffer.L); + r4(B, C, D, E, A, 69, InternalState.Buffer.L); + r4(A, B, C, D, E, 70, InternalState.Buffer.L); + r4(E, A, B, C, D, 71, InternalState.Buffer.L); + r4(D, E, A, B, C, 72, InternalState.Buffer.L); + r4(C, D, E, A, B, 73, InternalState.Buffer.L); + r4(B, C, D, E, A, 74, InternalState.Buffer.L); + r4(A, B, C, D, E, 75, InternalState.Buffer.L); + r4(E, A, B, C, D, 76, InternalState.Buffer.L); + r4(D, E, A, B, C, 77, InternalState.Buffer.L); + r4(C, D, E, A, B, 78, InternalState.Buffer.L); + r4(B, C, D, E, A, 79, InternalState.Buffer.L); + + InternalState.State[0] += A; + InternalState.State[1] += B; + InternalState.State[2] += C; + InternalState.State[3] += D; + InternalState.State[4] += E; } -void SHA1::addUncounted(uint8_t data) { - uint8_t *const b = (uint8_t *)InternalState.Buffer; +void SHA1::addUncounted(uint8_t Data) { #ifdef SHA_BIG_ENDIAN - b[InternalState.BufferOffset] = data; + InternalState.Buffer.C[InternalState.BufferOffset] = Data; #else - b[InternalState.BufferOffset ^ 3] = data; + InternalState.Buffer.C[InternalState.BufferOffset ^ 3] = Data; #endif + InternalState.BufferOffset++; if (InternalState.BufferOffset == BLOCK_LENGTH) { hashBlock(); @@ -104,9 +205,9 @@ void SHA1::addUncounted(uint8_t data) { } } -void SHA1::writebyte(uint8_t data) { +void SHA1::writebyte(uint8_t Data) { ++InternalState.ByteCount; - addUncounted(data); + addUncounted(Data); } void SHA1::update(ArrayRef<uint8_t> Data) { @@ -168,3 +269,13 @@ StringRef SHA1::result() { // Return pointer to hash (20 characters) return Hash; } + +std::array<uint8_t, 20> SHA1::hash(ArrayRef<uint8_t> Data) { + SHA1 Hash; + Hash.update(Data); + StringRef S = Hash.final(); + + std::array<uint8_t, 20> Arr; + memcpy(Arr.data(), S.data(), S.size()); + return Arr; +} diff --git a/contrib/llvm/lib/Support/ScaledNumber.cpp b/contrib/llvm/lib/Support/ScaledNumber.cpp index b9432d4..807c9fa 100644 --- a/contrib/llvm/lib/Support/ScaledNumber.cpp +++ b/contrib/llvm/lib/Support/ScaledNumber.cpp @@ -183,7 +183,7 @@ static std::string toStringAPFloat(uint64_t D, int E, unsigned Precision) { // Build the float and print it. uint64_t RawBits[2] = {D, AdjustedE}; - APFloat Float(APFloat::x87DoubleExtended, APInt(80, RawBits)); + APFloat Float(APFloat::x87DoubleExtended(), APInt(80, RawBits)); SmallVector<char, 24> Chars; Float.toString(Chars, Precision, 0); return std::string(Chars.begin(), Chars.end()); diff --git a/contrib/llvm/lib/Support/ScopedPrinter.cpp b/contrib/llvm/lib/Support/ScopedPrinter.cpp index 0225f01..d8ee1ef 100644 --- a/contrib/llvm/lib/Support/ScopedPrinter.cpp +++ b/contrib/llvm/lib/Support/ScopedPrinter.cpp @@ -27,45 +27,18 @@ void ScopedPrinter::printBinaryImpl(StringRef Label, StringRef Str, if (Block) { startLine() << Label; - if (Str.size() > 0) + if (!Str.empty()) OS << ": " << Str; OS << " (\n"; - for (size_t addr = 0, end = Data.size(); addr < end; addr += 16) { - startLine() << format(" %04" PRIX64 ": ", uint64_t(addr)); - // Dump line of hex. - for (size_t i = 0; i < 16; ++i) { - if (i != 0 && i % 4 == 0) - OS << ' '; - if (addr + i < end) - OS << hexdigit((Data[addr + i] >> 4) & 0xF, false) - << hexdigit(Data[addr + i] & 0xF, false); - else - OS << " "; - } - // Print ascii. - OS << " |"; - for (std::size_t i = 0; i < 16 && addr + i < end; ++i) { - if (std::isprint(Data[addr + i] & 0xFF)) - OS << Data[addr + i]; - else - OS << "."; - } - OS << "|\n"; - } - + if (!Data.empty()) + OS << format_bytes_with_ascii(Data, 0, 16, 4, (IndentLevel + 1) * 2, true) + << "\n"; startLine() << ")\n"; } else { startLine() << Label << ":"; - if (Str.size() > 0) + if (!Str.empty()) OS << " " << Str; - OS << " ("; - for (size_t i = 0; i < Data.size(); ++i) { - if (i > 0) - OS << " "; - - OS << format("%02X", static_cast<int>(Data[i])); - } - OS << ")\n"; + OS << " (" << format_bytes(Data, None, Data.size(), 1, 0, true) << ")\n"; } } diff --git a/contrib/llvm/lib/Support/SmallPtrSet.cpp b/contrib/llvm/lib/Support/SmallPtrSet.cpp index 539b4eb..aa12e85 100644 --- a/contrib/llvm/lib/Support/SmallPtrSet.cpp +++ b/contrib/llvm/lib/Support/SmallPtrSet.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/MathExtras.h" #include <algorithm> +#include <cassert> #include <cstdlib> using namespace llvm; @@ -60,38 +61,13 @@ SmallPtrSetImplBase::insert_imp_big(const void *Ptr) { return std::make_pair(Bucket, true); } -bool SmallPtrSetImplBase::erase_imp(const void * Ptr) { - if (isSmall()) { - // Check to see if it is in the set. - for (const void **APtr = CurArray, **E = CurArray + NumNonEmpty; APtr != E; - ++APtr) - if (*APtr == Ptr) { - // If it is in the set, replace this element. - *APtr = getTombstoneMarker(); - ++NumTombstones; - return true; - } - - return false; - } - - // Okay, we know we have space. Find a hash bucket. - void **Bucket = const_cast<void**>(FindBucketFor(Ptr)); - if (*Bucket != Ptr) return false; // Not in the set? - - // Set this as a tombstone. - *Bucket = getTombstoneMarker(); - ++NumTombstones; - return true; -} - const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const { unsigned Bucket = DenseMapInfo<void *>::getHashValue(Ptr) & (CurArraySize-1); unsigned ArraySize = CurArraySize; unsigned ProbeAmt = 1; const void *const *Array = CurArray; const void *const *Tombstone = nullptr; - while (1) { + while (true) { // If we found an empty bucket, the pointer doesn't exist in the set. // Return a tombstone if we've seen one so far, or the empty bucket if // not. diff --git a/contrib/llvm/lib/Support/SourceMgr.cpp b/contrib/llvm/lib/Support/SourceMgr.cpp index 6d44a4d..4cb9b2f 100644 --- a/contrib/llvm/lib/Support/SourceMgr.cpp +++ b/contrib/llvm/lib/Support/SourceMgr.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/SourceMgr.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Locale.h" #include "llvm/Support/MemoryBuffer.h" @@ -25,8 +26,8 @@ static const size_t TabStop = 8; namespace { struct LineNoCacheTy { - unsigned LastQueryBufferID; const char *LastQuery; + unsigned LastQueryBufferID; unsigned LineNoOfQuery; }; } @@ -141,7 +142,7 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind, // location to pull out the source line. SmallVector<std::pair<unsigned, unsigned>, 4> ColRanges; std::pair<unsigned, unsigned> LineAndCol; - const char *BufferID = "<unknown>"; + StringRef BufferID = "<unknown>"; std::string LineStr; if (Loc.isValid()) { @@ -395,8 +396,7 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors, // map like Clang's TextDiagnostic. For now, we'll just handle tabs by // expanding them later, and bail out rather than show incorrect ranges and // misaligned fixits for any other odd characters. - if (std::find_if(LineContents.begin(), LineContents.end(), isNonASCII) != - LineContents.end()) { + if (find_if(LineContents, isNonASCII) != LineContents.end()) { printSourceLine(S, LineContents); return; } diff --git a/contrib/llvm/lib/Support/SpecialCaseList.cpp b/contrib/llvm/lib/Support/SpecialCaseList.cpp index 0ffe444..df524b3 100644 --- a/contrib/llvm/lib/Support/SpecialCaseList.cpp +++ b/contrib/llvm/lib/Support/SpecialCaseList.cpp @@ -15,6 +15,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/SpecialCaseList.h" +#include "llvm/Support/TrigramIndex.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" @@ -32,15 +33,16 @@ namespace llvm { /// reason for doing so is efficiency; StringSet is much faster at matching /// literal strings than Regex. struct SpecialCaseList::Entry { - Entry() {} - Entry(Entry &&Other) - : Strings(std::move(Other.Strings)), RegEx(std::move(Other.RegEx)) {} - StringSet<> Strings; + TrigramIndex Trigrams; std::unique_ptr<Regex> RegEx; bool match(StringRef Query) const { - return Strings.count(Query) || (RegEx && RegEx->match(Query)); + if (Strings.count(Query)) + return true; + if (Trigrams.isDefinitelyOut(Query)) + return false; + return RegEx && RegEx->match(Query); } }; @@ -108,13 +110,15 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) { StringRef Category = SplitRegexp.second; // See if we can store Regexp in Strings. + auto &Entry = Entries[Prefix][Category]; if (Regex::isLiteralERE(Regexp)) { - Entries[Prefix][Category].Strings.insert(Regexp); + Entry.Strings.insert(Regexp); continue; } + Entry.Trigrams.insert(Regexp); // Replace * with .* - for (size_t pos = 0; (pos = Regexp.find("*", pos)) != std::string::npos; + for (size_t pos = 0; (pos = Regexp.find('*', pos)) != std::string::npos; pos += strlen(".*")) { Regexp.replace(pos, strlen("*"), ".*"); } diff --git a/contrib/llvm/lib/Support/Statistic.cpp b/contrib/llvm/lib/Support/Statistic.cpp index cdd3679..0c50dfd 100644 --- a/contrib/llvm/lib/Support/Statistic.cpp +++ b/contrib/llvm/lib/Support/Statistic.cpp @@ -29,7 +29,9 @@ #include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" +#include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/YAMLTraits.h" #include <algorithm> #include <cstring> using namespace llvm; @@ -37,15 +39,16 @@ using namespace llvm; /// -stats - Command line option to cause transformations to emit stats about /// what they did. /// -static cl::opt<bool> -Enabled( - "stats", +static cl::opt<bool> Stats("stats", cl::desc("Enable statistics output from program (available with Asserts)")); static cl::opt<bool> StatsAsJSON("stats-json", cl::desc("Display statistics as json data")); +static bool Enabled; +static bool PrintOnExit; + namespace { /// StatisticInfo - This class is used in a ManagedStatic so that it is created /// on demand (when the first statistic is bumped) and destroyed only when @@ -59,6 +62,7 @@ class StatisticInfo { /// Sort statistics by debugtype,name,description. void sort(); public: + StatisticInfo(); ~StatisticInfo(); void addStatistic(const Statistic *S) { @@ -77,7 +81,7 @@ void Statistic::RegisterStatistic() { // printed. sys::SmartScopedLock<true> Writer(*StatLock); if (!Initialized) { - if (Enabled) + if (Stats || Enabled) StatInfo->addStatistic(this); TsanHappensBefore(this); @@ -89,17 +93,24 @@ void Statistic::RegisterStatistic() { } } +StatisticInfo::StatisticInfo() { + // Ensure timergroup lists are created first so they are destructed after us. + TimerGroup::ConstructTimerLists(); +} + // Print information when destroyed, iff command line option is specified. StatisticInfo::~StatisticInfo() { - llvm::PrintStatistics(); + if (::Stats || PrintOnExit) + llvm::PrintStatistics(); } -void llvm::EnableStatistics() { - Enabled.setValue(true); +void llvm::EnableStatistics(bool PrintOnExit) { + Enabled = true; + ::PrintOnExit = PrintOnExit; } bool llvm::AreStatisticsEnabled() { - return Enabled; + return Enabled || Stats; } void StatisticInfo::sort() { @@ -145,17 +156,6 @@ void llvm::PrintStatistics(raw_ostream &OS) { OS.flush(); } -static void write_json_string_escaped(raw_ostream &OS, const char *string) { - // Out current usage should not need any escaping. Keep it simple and just - // check that the input is pure ASCII without special characers. -#ifndef NDEBUG - for (const unsigned char *c = (const unsigned char*)string; *c != '\0'; ++c) { - assert(*c != '\\' && *c != '\"' && *c >= 0x20 && *c < 0x80); - } -#endif - OS << string; -} - void llvm::PrintStatisticsJSON(raw_ostream &OS) { StatisticInfo &Stats = *StatInfo; @@ -166,13 +166,16 @@ void llvm::PrintStatisticsJSON(raw_ostream &OS) { const char *delim = ""; for (const Statistic *Stat : Stats.Stats) { OS << delim; - OS << "\t\""; - write_json_string_escaped(OS, Stat->getDebugType()); - OS << '.'; - write_json_string_escaped(OS, Stat->getName()); - OS << "\": " << Stat->getValue(); + assert(!yaml::needsQuotes(Stat->getDebugType()) && + "Statistic group/type name is simple."); + assert(!yaml::needsQuotes(Stat->getName()) && "Statistic name is simple"); + OS << "\t\"" << Stat->getDebugType() << '.' << Stat->getName() << "\": " + << Stat->getValue(); delim = ",\n"; } + // Print timers. + TimerGroup::printAllJSONValues(OS, delim); + OS << "\n}\n"; OS.flush(); } @@ -195,7 +198,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 (Enabled) { + if (Stats) { // Get the stream to write to. std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile(); (*OutStream) << "Statistics are disabled. " diff --git a/contrib/llvm/lib/Support/StreamingMemoryObject.cpp b/contrib/llvm/lib/Support/StreamingMemoryObject.cpp deleted file mode 100644 index fb56617..0000000 --- a/contrib/llvm/lib/Support/StreamingMemoryObject.cpp +++ /dev/null @@ -1,138 +0,0 @@ -//===- StreamingMemoryObject.cpp - Streamable data interface -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/StreamingMemoryObject.h" -#include <cassert> -#include <cstddef> -#include <cstring> -using namespace llvm; - -namespace { - -class RawMemoryObject : public MemoryObject { -public: - RawMemoryObject(const unsigned char *Start, const unsigned char *End) : - FirstChar(Start), LastChar(End) { - assert(LastChar >= FirstChar && "Invalid start/end range"); - } - - uint64_t getExtent() const override { - return LastChar - FirstChar; - } - uint64_t readBytes(uint8_t *Buf, uint64_t Size, - uint64_t Address) const override; - const uint8_t *getPointer(uint64_t address, uint64_t size) const override; - bool isValidAddress(uint64_t address) const override { - return validAddress(address); - } - -private: - const uint8_t* const FirstChar; - const uint8_t* const LastChar; - - // These are implemented as inline functions here to avoid multiple virtual - // calls per public function - bool validAddress(uint64_t address) const { - return static_cast<std::ptrdiff_t>(address) < LastChar - FirstChar; - } - - RawMemoryObject(const RawMemoryObject&) = delete; - void operator=(const RawMemoryObject&) = delete; -}; - -uint64_t RawMemoryObject::readBytes(uint8_t *Buf, uint64_t Size, - uint64_t Address) const { - uint64_t BufferSize = LastChar - FirstChar; - if (Address >= BufferSize) - return 0; - - uint64_t End = Address + Size; - if (End > BufferSize) - End = BufferSize; - - assert(static_cast<int64_t>(End - Address) >= 0); - Size = End - Address; - memcpy(Buf, Address + FirstChar, Size); - return Size; -} - -const uint8_t *RawMemoryObject::getPointer(uint64_t address, - uint64_t size) const { - return FirstChar + address; -} -} // anonymous namespace - -namespace llvm { -// If the bitcode has a header, then its size is known, and we don't have to -// block until we actually want to read it. -bool StreamingMemoryObject::isValidAddress(uint64_t address) const { - if (ObjectSize && address < ObjectSize) return true; - return fetchToPos(address); -} - -uint64_t StreamingMemoryObject::getExtent() const { - if (ObjectSize) return ObjectSize; - size_t pos = BytesRead + kChunkSize; - // keep fetching until we run out of bytes - while (fetchToPos(pos)) pos += kChunkSize; - return ObjectSize; -} - -uint64_t StreamingMemoryObject::readBytes(uint8_t *Buf, uint64_t Size, - uint64_t Address) const { - fetchToPos(Address + Size - 1); - // Note: For wrapped bitcode files will set ObjectSize after the - // first call to fetchToPos. In such cases, ObjectSize can be - // smaller than BytesRead. - size_t MaxAddress = - (ObjectSize && ObjectSize < BytesRead) ? ObjectSize : BytesRead; - if (Address >= MaxAddress) - return 0; - - uint64_t End = Address + Size; - if (End > MaxAddress) - End = MaxAddress; - assert(End >= Address); - Size = End - Address; - memcpy(Buf, &Bytes[Address + BytesSkipped], Size); - return Size; -} - -const uint8_t *StreamingMemoryObject::getPointer(uint64_t Address, - uint64_t Size) const { - fetchToPos(Address + Size - 1); - return &Bytes[Address + BytesSkipped]; -} - -bool StreamingMemoryObject::dropLeadingBytes(size_t s) { - if (BytesRead < s) return true; - BytesSkipped = s; - BytesRead -= s; - return false; -} - -void StreamingMemoryObject::setKnownObjectSize(size_t size) { - ObjectSize = size; - Bytes.reserve(size); - if (ObjectSize <= BytesRead) - EOFReached = true; -} - -MemoryObject *getNonStreamedMemoryObject(const unsigned char *Start, - const unsigned char *End) { - return new RawMemoryObject(Start, End); -} - -StreamingMemoryObject::StreamingMemoryObject( - std::unique_ptr<DataStreamer> Streamer) - : Bytes(kChunkSize), Streamer(std::move(Streamer)), BytesRead(0), - BytesSkipped(0), ObjectSize(0), EOFReached(false) { - BytesRead = this->Streamer->GetBytes(&Bytes[0], kChunkSize); -} -} diff --git a/contrib/llvm/lib/Support/StringMap.cpp b/contrib/llvm/lib/Support/StringMap.cpp index 7da9ccb..d2315966 100644 --- a/contrib/llvm/lib/Support/StringMap.cpp +++ b/contrib/llvm/lib/Support/StringMap.cpp @@ -14,7 +14,9 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" #include <cassert> + using namespace llvm; /// Returns the number of buckets to allocate to ensure that the DenseMap can @@ -63,7 +65,6 @@ void StringMapImpl::init(unsigned InitSize) { TheTable[NumBuckets] = (StringMapEntryBase*)2; } - /// LookupBucketFor - Look up the bucket that the specified string should end /// up in. If it already exists as a key in the map, the Item pointer for the /// specified bucket will be non-null. Otherwise, it will be null. In either @@ -81,7 +82,7 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) { unsigned ProbeAmt = 1; int FirstTombstone = -1; - while (1) { + while (true) { StringMapEntryBase *BucketItem = TheTable[BucketNo]; // If we found an empty bucket, this key isn't in the table yet, return it. if (LLVM_LIKELY(!BucketItem)) { @@ -123,7 +124,6 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) { } } - /// FindKey - Look up the bucket that contains the specified key. If it exists /// in the map, return the bucket number of the key. Otherwise return -1. /// This does not modify the map. @@ -135,7 +135,7 @@ int StringMapImpl::FindKey(StringRef Key) const { unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); unsigned ProbeAmt = 1; - while (1) { + while (true) { StringMapEntryBase *BucketItem = TheTable[BucketNo]; // If we found an empty bucket, this key isn't in the table yet, return. if (LLVM_LIKELY(!BucketItem)) @@ -191,8 +191,6 @@ StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { return Result; } - - /// RehashTable - Grow the table, redistributing values into the buckets with /// the appropriate mod-of-hashtable-size. unsigned StringMapImpl::RehashTable(unsigned BucketNo) { diff --git a/contrib/llvm/lib/Support/StringRef.cpp b/contrib/llvm/lib/Support/StringRef.cpp index 8a9da5e..d81250e 100644 --- a/contrib/llvm/lib/Support/StringRef.cpp +++ b/contrib/llvm/lib/Support/StringRef.cpp @@ -69,6 +69,11 @@ bool StringRef::endswith_lower(StringRef Suffix) const { ascii_strncasecmp(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; } +size_t StringRef::find_lower(char C, size_t From) const { + char L = ascii_tolower(C); + return find_if([L](char D) { return ascii_tolower(D) == L; }, From); +} + /// compare_numeric - Compare strings, handle embedded numbers. int StringRef::compare_numeric(StringRef RHS) const { for (size_t I = 0, E = std::min(Length, RHS.Length); I != E; ++I) { @@ -143,16 +148,20 @@ size_t StringRef::find(StringRef Str, size_t From) const { if (From > Length) return npos; + const char *Start = Data + From; + size_t Size = Length - From; + const char *Needle = Str.data(); size_t N = Str.size(); if (N == 0) return From; - - size_t Size = Length - From; if (Size < N) return npos; + if (N == 1) { + const char *Ptr = (const char *)::memchr(Start, Needle[0], Size); + return Ptr == nullptr ? npos : Ptr - Data; + } - const char *Start = Data + From; const char *Stop = Start + (Size - N + 1); // For short haystacks or unsupported needles fall back to the naive algorithm @@ -172,16 +181,40 @@ size_t StringRef::find(StringRef Str, size_t From) const { BadCharSkip[(uint8_t)Str[i]] = N-1-i; do { - if (std::memcmp(Start, Needle, N) == 0) - return Start - Data; + uint8_t Last = Start[N - 1]; + if (LLVM_UNLIKELY(Last == (uint8_t)Needle[N - 1])) + if (std::memcmp(Start, Needle, N - 1) == 0) + return Start - Data; // Otherwise skip the appropriate number of bytes. - Start += BadCharSkip[(uint8_t)Start[N-1]]; + Start += BadCharSkip[Last]; } while (Start < Stop); return npos; } +size_t StringRef::find_lower(StringRef Str, size_t From) const { + StringRef This = substr(From); + while (This.size() >= Str.size()) { + if (This.startswith_lower(Str)) + return From; + This = This.drop_front(); + ++From; + } + return npos; +} + +size_t StringRef::rfind_lower(char C, size_t From) const { + From = std::min(From, Length); + size_t i = From; + while (i != 0) { + --i; + if (ascii_tolower(Data[i]) == ascii_tolower(C)) + return i; + } + return npos; +} + /// rfind - Search for the last string \arg Str in the string. /// /// \return - The index of the last occurrence of \arg Str, or npos if not @@ -198,6 +231,18 @@ size_t StringRef::rfind(StringRef Str) const { return npos; } +size_t StringRef::rfind_lower(StringRef Str) const { + size_t N = Str.size(); + if (N > Length) + return npos; + for (size_t i = Length - N + 1, e = 0; i != e;) { + --i; + if (substr(i, N).equals_lower(Str)) + return i; + } + return npos; +} + /// find_first_of - Find the first character in the string that is in \arg /// Chars, or npos if not found. /// @@ -351,6 +396,9 @@ size_t StringRef::count(StringRef Str) const { } static unsigned GetAutoSenseRadix(StringRef &Str) { + if (Str.empty()) + return 10; + if (Str.startswith("0x") || Str.startswith("0X")) { Str = Str.substr(2); return 16; @@ -366,17 +414,16 @@ static unsigned GetAutoSenseRadix(StringRef &Str) { return 8; } - if (Str.startswith("0")) + if (Str[0] == '0' && Str.size() > 1 && ascii_isdigit(Str[1])) { + Str = Str.substr(1); return 8; - + } + return 10; } - -/// GetAsUnsignedInteger - Workhorse method that converts a integer character -/// sequence of radix up to 36 to an unsigned long long value. -bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix, - unsigned long long &Result) { +bool llvm::consumeUnsignedInteger(StringRef &Str, unsigned Radix, + unsigned long long &Result) { // Autosense radix if not specified. if (Radix == 0) Radix = GetAutoSenseRadix(Str); @@ -385,44 +432,51 @@ bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix, if (Str.empty()) return true; // Parse all the bytes of the string given this radix. Watch for overflow. + StringRef Str2 = Str; Result = 0; - while (!Str.empty()) { + while (!Str2.empty()) { unsigned CharVal; - if (Str[0] >= '0' && Str[0] <= '9') - CharVal = Str[0]-'0'; - else if (Str[0] >= 'a' && Str[0] <= 'z') - CharVal = Str[0]-'a'+10; - else if (Str[0] >= 'A' && Str[0] <= 'Z') - CharVal = Str[0]-'A'+10; + if (Str2[0] >= '0' && Str2[0] <= '9') + CharVal = Str2[0] - '0'; + else if (Str2[0] >= 'a' && Str2[0] <= 'z') + CharVal = Str2[0] - 'a' + 10; + else if (Str2[0] >= 'A' && Str2[0] <= 'Z') + CharVal = Str2[0] - 'A' + 10; else - return true; + break; - // If the parsed value is larger than the integer radix, the string is - // invalid. + // If the parsed value is larger than the integer radix, we cannot + // consume any more characters. if (CharVal >= Radix) - return true; + break; // Add in this character. unsigned long long PrevResult = Result; - Result = Result*Radix+CharVal; + Result = Result * Radix + CharVal; // Check for overflow by shifting back and seeing if bits were lost. - if (Result/Radix < PrevResult) + if (Result / Radix < PrevResult) return true; - Str = Str.substr(1); + Str2 = Str2.substr(1); } + // We consider the operation a failure if no characters were consumed + // successfully. + if (Str.size() == Str2.size()) + return true; + + Str = Str2; return false; } -bool llvm::getAsSignedInteger(StringRef Str, unsigned Radix, - long long &Result) { +bool llvm::consumeSignedInteger(StringRef &Str, unsigned Radix, + long long &Result) { unsigned long long ULLVal; // Handle positive strings first. if (Str.empty() || Str.front() != '-') { - if (getAsUnsignedInteger(Str, Radix, ULLVal) || + if (consumeUnsignedInteger(Str, Radix, ULLVal) || // Check for value so large it overflows a signed value. (long long)ULLVal < 0) return true; @@ -431,17 +485,41 @@ bool llvm::getAsSignedInteger(StringRef Str, unsigned Radix, } // Get the positive part of the value. - if (getAsUnsignedInteger(Str.substr(1), Radix, ULLVal) || + StringRef Str2 = Str.drop_front(1); + if (consumeUnsignedInteger(Str2, Radix, ULLVal) || // Reject values so large they'd overflow as negative signed, but allow // "-0". This negates the unsigned so that the negative isn't undefined // on signed overflow. (long long)-ULLVal > 0) return true; + Str = Str2; Result = -ULLVal; return false; } +/// GetAsUnsignedInteger - Workhorse method that converts a integer character +/// sequence of radix up to 36 to an unsigned long long value. +bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix, + unsigned long long &Result) { + if (consumeUnsignedInteger(Str, Radix, Result)) + return true; + + // For getAsUnsignedInteger, we require the whole string to be consumed or + // else we consider it a failure. + return !Str.empty(); +} + +bool llvm::getAsSignedInteger(StringRef Str, unsigned Radix, + long long &Result) { + if (consumeSignedInteger(Str, Radix, Result)) + return true; + + // For getAsSignedInteger, we require the whole string to be consumed or else + // we consider it a failure. + return !Str.empty(); +} + bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const { StringRef Str = *this; diff --git a/contrib/llvm/lib/Support/StringSaver.cpp b/contrib/llvm/lib/Support/StringSaver.cpp index bbc1fd2..335fce3 100644 --- a/contrib/llvm/lib/Support/StringSaver.cpp +++ b/contrib/llvm/lib/Support/StringSaver.cpp @@ -11,9 +11,9 @@ using namespace llvm; -const char *StringSaver::save(StringRef S) { +StringRef StringSaver::save(StringRef S) { char *P = Alloc.Allocate<char>(S.size() + 1); memcpy(P, S.data(), S.size()); P[S.size()] = '\0'; - return P; + return StringRef(P, S.size()); } diff --git a/contrib/llvm/lib/Support/TarWriter.cpp b/contrib/llvm/lib/Support/TarWriter.cpp new file mode 100644 index 0000000..f06abf4 --- /dev/null +++ b/contrib/llvm/lib/Support/TarWriter.cpp @@ -0,0 +1,189 @@ +//===-- TarWriter.cpp - Tar archive file creator --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// TarWriter class provides a feature to create a tar archive file. +// +// I put emphasis on simplicity over comprehensiveness when implementing this +// class because we don't need a full-fledged archive file generator in LLVM +// at the moment. +// +// The filename field in the Unix V7 tar header is 100 bytes. Longer filenames +// are stored using the PAX extension. The PAX header is standardized in +// POSIX.1-2001. +// +// The struct definition of UstarHeader is copied from +// https://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5 +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/TarWriter.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Path.h" + +using namespace llvm; + +// Each file in an archive must be aligned to this block size. +static const int BlockSize = 512; + +struct UstarHeader { + char Name[100]; + char Mode[8]; + char Uid[8]; + char Gid[8]; + char Size[12]; + char Mtime[12]; + char Checksum[8]; + char TypeFlag; + char Linkname[100]; + char Magic[6]; + char Version[2]; + char Uname[32]; + char Gname[32]; + char DevMajor[8]; + char DevMinor[8]; + char Prefix[155]; + char Pad[12]; +}; +static_assert(sizeof(UstarHeader) == BlockSize, "invalid Ustar header"); + +static UstarHeader makeUstarHeader() { + UstarHeader Hdr = {}; + memcpy(Hdr.Magic, "ustar", 5); // Ustar magic + memcpy(Hdr.Version, "00", 2); // Ustar version + return Hdr; +} + +// A PAX attribute is in the form of "<length> <key>=<value>\n" +// where <length> is the length of the entire string including +// the length field itself. An example string is this. +// +// 25 ctime=1084839148.1212\n +// +// This function create such string. +static std::string formatPax(StringRef Key, StringRef Val) { + int Len = Key.size() + Val.size() + 3; // +3 for " ", "=" and "\n" + + // We need to compute total size twice because appending + // a length field could change total size by one. + int Total = Len + Twine(Len).str().size(); + Total = Len + Twine(Total).str().size(); + return (Twine(Total) + " " + Key + "=" + Val + "\n").str(); +} + +// Headers in tar files must be aligned to 512 byte boundaries. +// This function forwards the current file position to the next boundary. +static void pad(raw_fd_ostream &OS) { + uint64_t Pos = OS.tell(); + OS.seek(alignTo(Pos, BlockSize)); +} + +// Computes a checksum for a tar header. +static void computeChecksum(UstarHeader &Hdr) { + // Before computing a checksum, checksum field must be + // filled with space characters. + memset(Hdr.Checksum, ' ', sizeof(Hdr.Checksum)); + + // Compute a checksum and set it to the checksum field. + unsigned Chksum = 0; + for (size_t I = 0; I < sizeof(Hdr); ++I) + Chksum += reinterpret_cast<uint8_t *>(&Hdr)[I]; + snprintf(Hdr.Checksum, sizeof(Hdr.Checksum), "%06o", Chksum); +} + +// Create a tar header and write it to a given output stream. +static void writePaxHeader(raw_fd_ostream &OS, StringRef Path) { + // A PAX header consists of a 512-byte header followed + // by key-value strings. First, create key-value strings. + std::string PaxAttr = formatPax("path", Path); + + // Create a 512-byte header. + UstarHeader Hdr = makeUstarHeader(); + snprintf(Hdr.Size, sizeof(Hdr.Size), "%011zo", PaxAttr.size()); + Hdr.TypeFlag = 'x'; // PAX magic + computeChecksum(Hdr); + + // Write them down. + OS << StringRef(reinterpret_cast<char *>(&Hdr), sizeof(Hdr)); + OS << PaxAttr; + pad(OS); +} + +// In the Ustar header, a path can be split at any '/' to store +// a path into UstarHeader::Name and UstarHeader::Prefix. This +// function splits a given path for that purpose. +static std::pair<StringRef, StringRef> splitPath(StringRef Path) { + if (Path.size() <= sizeof(UstarHeader::Name)) + return {"", Path}; + size_t Sep = Path.rfind('/', sizeof(UstarHeader::Prefix) + 1); + if (Sep == StringRef::npos) + return {"", Path}; + return {Path.substr(0, Sep), Path.substr(Sep + 1)}; +} + +// Returns true if a given path can be stored to a Ustar header +// without the PAX extension. +static bool fitsInUstar(StringRef Path) { + StringRef Prefix; + StringRef Name; + std::tie(Prefix, Name) = splitPath(Path); + return Name.size() <= sizeof(UstarHeader::Name); +} + +// The PAX header is an extended format, so a PAX header needs +// to be followed by a "real" header. +static void writeUstarHeader(raw_fd_ostream &OS, StringRef Path, size_t Size) { + StringRef Prefix; + StringRef Name; + std::tie(Prefix, Name) = splitPath(Path); + + UstarHeader Hdr = makeUstarHeader(); + memcpy(Hdr.Name, Name.data(), Name.size()); + memcpy(Hdr.Mode, "0000664", 8); + snprintf(Hdr.Size, sizeof(Hdr.Size), "%011zo", Size); + memcpy(Hdr.Prefix, Prefix.data(), Prefix.size()); + computeChecksum(Hdr); + OS << StringRef(reinterpret_cast<char *>(&Hdr), sizeof(Hdr)); +} + +// Creates a TarWriter instance and returns it. +Expected<std::unique_ptr<TarWriter>> TarWriter::create(StringRef OutputPath, + StringRef BaseDir) { + int FD; + if (std::error_code EC = openFileForWrite(OutputPath, FD, sys::fs::F_None)) + return make_error<StringError>("cannot open " + OutputPath, EC); + return std::unique_ptr<TarWriter>(new TarWriter(FD, BaseDir)); +} + +TarWriter::TarWriter(int FD, StringRef BaseDir) + : OS(FD, /*shouldClose=*/true, /*unbuffered=*/false), BaseDir(BaseDir) {} + +// Append a given file to an archive. +void TarWriter::append(StringRef Path, StringRef Data) { + // Write Path and Data. + std::string S = BaseDir + "/" + sys::path::convert_to_slash(Path) + "\0"; + if (fitsInUstar(S)) { + writeUstarHeader(OS, S, Data.size()); + } else { + writePaxHeader(OS, S); + writeUstarHeader(OS, "", Data.size()); + } + + OS << Data; + pad(OS); + + // POSIX requires tar archives end with two null blocks. + // Here, we write the terminator and then seek back, so that + // the file being output is terminated correctly at any moment. + uint64_t Pos = OS.tell(); + OS << std::string(BlockSize * 2, '\0'); + OS.seek(Pos); + OS.flush(); +} diff --git a/contrib/llvm/lib/Support/TargetParser.cpp b/contrib/llvm/lib/Support/TargetParser.cpp index c3f8613..42fab67 100644 --- a/contrib/llvm/lib/Support/TargetParser.cpp +++ b/contrib/llvm/lib/Support/TargetParser.cpp @@ -52,7 +52,7 @@ static const struct { // of the triples and are not conforming with their official names. // Check to see if the expectation should be changed. // FIXME: TableGen this. -static const struct { +template <typename T> struct ArchNames { const char *NameCStr; size_t NameLength; const char *CPUAttrCStr; @@ -61,7 +61,7 @@ static const struct { size_t SubArchLength; unsigned DefaultFPU; unsigned ArchBaseExtensions; - ARM::ArchKind ID; + T ID; ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes. StringRef getName() const { return StringRef(NameCStr, NameLength); } @@ -71,18 +71,22 @@ static const struct { // Sub-Arch name. StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); } -} ARCHNames[] = { +}; +ArchNames<ARM::ArchKind> ARCHNames[] = { #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR}, #include "llvm/Support/ARMTargetParser.def" -},AArch64ARCHNames[] = { -#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ - {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ - sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR}, -#include "llvm/Support/AArch64TargetParser.def" }; +ArchNames<AArch64::ArchKind> AArch64ARCHNames[] = { + #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ + {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ + sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, AArch64::ArchKind::ID, ARCH_ATTR}, + #include "llvm/Support/AArch64TargetParser.def" + }; + + // List of Arch Extension names. // FIXME: TableGen this. static const struct { @@ -122,24 +126,27 @@ static const struct { // When finding the Arch for a CPU, first-found prevails. Sort them accordingly. // When this becomes table-generated, we'd probably need two tables. // FIXME: TableGen this. -static const struct { +template <typename T> struct CpuNames { const char *NameCStr; size_t NameLength; - ARM::ArchKind ArchID; + T ArchID; bool Default; // is $Name the default CPU for $ArchID ? unsigned DefaultExtensions; StringRef getName() const { return StringRef(NameCStr, NameLength); } -} CPUNames[] = { +}; +CpuNames<ARM::ArchKind> CPUNames[] = { #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT }, #include "llvm/Support/ARMTargetParser.def" -},AArch64CPUNames[] = { -#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ - { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT }, -#include "llvm/Support/AArch64TargetParser.def" }; +CpuNames<AArch64::ArchKind> AArch64CPUNames[] = { + #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ + { NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT }, + #include "llvm/Support/AArch64TargetParser.def" + }; + } // namespace // ======================================================= // @@ -193,7 +200,7 @@ unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) { } bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind, - std::vector<const char *> &Features) { + std::vector<StringRef> &Features) { if (HWDivKind == ARM::AEK_INVALID) return false; @@ -212,7 +219,7 @@ bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind, } bool llvm::ARM::getExtensionFeatures(unsigned Extensions, - std::vector<const char *> &Features) { + std::vector<StringRef> &Features) { if (Extensions == ARM::AEK_INVALID) return false; @@ -231,7 +238,7 @@ bool llvm::ARM::getExtensionFeatures(unsigned Extensions, } bool llvm::ARM::getFPUFeatures(unsigned FPUKind, - std::vector<const char *> &Features) { + std::vector<StringRef> &Features) { if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) return false; @@ -344,20 +351,20 @@ StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) { return StringRef(); } -const char *llvm::ARM::getArchExtFeature(StringRef ArchExt) { +StringRef llvm::ARM::getArchExtFeature(StringRef ArchExt) { if (ArchExt.startswith("no")) { StringRef ArchExtBase(ArchExt.substr(2)); for (const auto AE : ARCHExtNames) { if (AE.NegFeature && ArchExtBase == AE.getName()) - return AE.NegFeature; + return StringRef(AE.NegFeature); } } for (const auto AE : ARCHExtNames) { if (AE.Feature && ArchExt == AE.getName()) - return AE.Feature; + return StringRef(AE.Feature); } - return nullptr; + return StringRef(); } StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) { @@ -416,13 +423,13 @@ unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, unsigned ArchKind) { return StringSwitch<unsigned>(CPU) #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ - .Case(NAME, AArch64ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT) + .Case(NAME, DEFAULT_EXT) #include "llvm/Support/AArch64TargetParser.def" .Default(AArch64::AEK_INVALID); } bool llvm::AArch64::getExtensionFeatures(unsigned Extensions, - std::vector<const char *> &Features) { + std::vector<StringRef> &Features) { if (Extensions == AArch64::AEK_INVALID) return false; @@ -446,81 +453,77 @@ bool llvm::AArch64::getExtensionFeatures(unsigned Extensions, } bool llvm::AArch64::getFPUFeatures(unsigned FPUKind, - std::vector<const char *> &Features) { + std::vector<StringRef> &Features) { return ARM::getFPUFeatures(FPUKind, Features); } bool llvm::AArch64::getArchFeatures(unsigned ArchKind, - std::vector<const char *> &Features) { - if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST) - return false; - - if (ArchKind == ARM::AK_ARMV8_1A) + std::vector<StringRef> &Features) { + if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_1A)) Features.push_back("+v8.1a"); - if (ArchKind == ARM::AK_ARMV8_2A) + if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_2A)) Features.push_back("+v8.2a"); - return true; + return ArchKind > static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) && + ArchKind < static_cast<unsigned>(AArch64::ArchKind::AK_LAST); } StringRef llvm::AArch64::getArchName(unsigned ArchKind) { - for (const auto &AI : AArch64ARCHNames) - if (AI.ID == ArchKind) - return AI.getName(); - return StringRef(); + if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) + return StringRef(); + return AArch64ARCHNames[ArchKind].getName(); } StringRef llvm::AArch64::getCPUAttr(unsigned ArchKind) { - for (const auto &AI : AArch64ARCHNames) - if (AI.ID == ArchKind) - return AI.getCPUAttr(); - return StringRef(); + if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) || + ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) + return StringRef(); + return AArch64ARCHNames[ArchKind].getCPUAttr(); } StringRef llvm::AArch64::getSubArch(unsigned ArchKind) { - for (const auto &AI : AArch64ARCHNames) - if (AI.ID == ArchKind) - return AI.getSubArch(); - return StringRef(); + if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) || + ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) + return StringRef(); + return AArch64ARCHNames[ArchKind].getSubArch(); } unsigned llvm::AArch64::getArchAttr(unsigned ArchKind) { - for (const auto &AI : AArch64ARCHNames) - if (AI.ID == ArchKind) - return AI.ArchAttr; - return ARMBuildAttrs::CPUArch::v8_A; + if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) + return ARMBuildAttrs::CPUArch::v8_A; + return AArch64ARCHNames[ArchKind].ArchAttr; } -StringRef llvm::AArch64::getArchExtName(unsigned AArchExtKind) { +StringRef llvm::AArch64::getArchExtName(unsigned ArchExtKind) { for (const auto &AE : AArch64ARCHExtNames) - if (AArchExtKind == AE.ID) + if (ArchExtKind == AE.ID) return AE.getName(); return StringRef(); } -const char *llvm::AArch64::getArchExtFeature(StringRef ArchExt) { +StringRef llvm::AArch64::getArchExtFeature(StringRef ArchExt) { if (ArchExt.startswith("no")) { StringRef ArchExtBase(ArchExt.substr(2)); for (const auto &AE : AArch64ARCHExtNames) { if (AE.NegFeature && ArchExtBase == AE.getName()) - return AE.NegFeature; + return StringRef(AE.NegFeature); } } for (const auto &AE : AArch64ARCHExtNames) if (AE.Feature && ArchExt == AE.getName()) - return AE.Feature; - return nullptr; + return StringRef(AE.Feature); + return StringRef(); } StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) { unsigned AK = parseArch(Arch); - if (AK == ARM::AK_INVALID) + if (AK == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID)) return StringRef(); // Look for multiple AKs to find the default for pair AK+Name. for (const auto &CPU : AArch64CPUNames) - if (CPU.ArchID == AK && CPU.Default) + if (static_cast<unsigned>(CPU.ArchID) == AK && CPU.Default) return CPU.getName(); // If we can't find a default then target the architecture instead @@ -575,6 +578,7 @@ static StringRef getArchSynonym(StringRef Arch) { .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") .Case("v8.1a", "v8.1-a") .Case("v8.2a", "v8.2-a") + .Case("v8r", "v8-r") .Case("v8m.base", "v8-m.base") .Case("v8m.main", "v8-m.main") .Default(Arch); @@ -685,7 +689,7 @@ unsigned llvm::ARM::parseArchISA(StringRef Arch) { .StartsWith("arm64", ARM::IK_AARCH64) .StartsWith("thumb", ARM::IK_THUMB) .StartsWith("arm", ARM::IK_ARM) - .Default(ARM::EK_INVALID); + .Default(ARM::IK_INVALID); } // Little/Big endian @@ -718,6 +722,7 @@ unsigned llvm::ARM::parseArchProfile(StringRef Arch) { case ARM::AK_ARMV8MBaseline: return ARM::PK_M; case ARM::AK_ARMV7R: + case ARM::AK_ARMV8R: return ARM::PK_R; case ARM::AK_ARMV7A: case ARM::AK_ARMV7K: @@ -765,6 +770,7 @@ unsigned llvm::ARM::parseArchVersion(StringRef Arch) { case ARM::AK_ARMV8A: case ARM::AK_ARMV8_1A: case ARM::AK_ARMV8_2A: + case ARM::AK_ARMV8R: case ARM::AK_ARMV8MBaseline: case ARM::AK_ARMV8MMainline: return 8; @@ -784,14 +790,14 @@ unsigned llvm::AArch64::parseFPU(StringRef FPU) { unsigned llvm::AArch64::parseArch(StringRef Arch) { Arch = getCanonicalArchName(Arch); if (checkArchVersion(Arch) < 8) - return ARM::AK_INVALID; + return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID); StringRef Syn = getArchSynonym(Arch); for (const auto A : AArch64ARCHNames) { if (A.getName().endswith(Syn)) - return A.ID; + return static_cast<unsigned>(A.ID); } - return ARM::AK_INVALID; + return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID); } unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) { @@ -805,9 +811,9 @@ unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) { unsigned llvm::AArch64::parseCPUArch(StringRef CPU) { for (const auto C : AArch64CPUNames) { if (CPU == C.getName()) - return C.ArchID; + return static_cast<unsigned>(C.ArchID); } - return ARM::AK_INVALID; + return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID); } // ARM, Thumb, AArch64 diff --git a/contrib/llvm/lib/Support/TargetRegistry.cpp b/contrib/llvm/lib/Support/TargetRegistry.cpp index 02a6d33..bed9ed6 100644 --- a/contrib/llvm/lib/Support/TargetRegistry.cpp +++ b/contrib/llvm/lib/Support/TargetRegistry.cpp @@ -30,8 +30,7 @@ const Target *TargetRegistry::lookupTarget(const std::string &ArchName, // name, because it might be a backend that has no mapping to a target triple. const Target *TheTarget = nullptr; if (!ArchName.empty()) { - auto I = - std::find_if(targets().begin(), targets().end(), + auto I = find_if(targets(), [&](const Target &T) { return ArchName == T.getName(); }); if (I == targets().end()) { @@ -70,7 +69,7 @@ const Target *TargetRegistry::lookupTarget(const std::string &TT, } Triple::ArchType Arch = Triple(TT).getArch(); auto ArchMatch = [&](const Target &T) { return T.ArchMatchFn(Arch); }; - auto I = std::find_if(targets().begin(), targets().end(), ArchMatch); + auto I = find_if(targets(), ArchMatch); if (I == targets().end()) { Error = "No available targets are compatible with this triple."; diff --git a/contrib/llvm/lib/Support/Threading.cpp b/contrib/llvm/lib/Support/Threading.cpp index e8f5622..760f9e2 100644 --- a/contrib/llvm/lib/Support/Threading.cpp +++ b/contrib/llvm/lib/Support/Threading.cpp @@ -15,6 +15,7 @@ #include "llvm/Support/Threading.h" #include "llvm/Config/config.h" #include "llvm/Support/Atomic.h" +#include "llvm/Support/Host.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/thread.h" #include <cassert> @@ -116,3 +117,13 @@ void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, } #endif + +unsigned llvm::heavyweight_hardware_concurrency() { +#if !LLVM_ENABLE_THREADS + return 1; +#endif + int NumPhysical = sys::getHostNumPhysicalCores(); + if (NumPhysical == -1) + return thread::hardware_concurrency(); + return NumPhysical; +} diff --git a/contrib/llvm/lib/Support/TimeValue.cpp b/contrib/llvm/lib/Support/TimeValue.cpp deleted file mode 100644 index 94a4c01..0000000 --- a/contrib/llvm/lib/Support/TimeValue.cpp +++ /dev/null @@ -1,56 +0,0 @@ -//===-- TimeValue.cpp - Implement OS TimeValue Concept ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the operating system TimeValue concept. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/TimeValue.h" -#include "llvm/Config/config.h" - -namespace llvm { - -using namespace sys; - -const TimeValue::SecondsType - TimeValue::PosixZeroTimeSeconds = -946684800; -const TimeValue::SecondsType - TimeValue::Win32ZeroTimeSeconds = -12591158400ULL; - -void TimeValue::normalize() { - if ( nanos_ >= NANOSECONDS_PER_SECOND ) { - do { - seconds_++; - nanos_ -= NANOSECONDS_PER_SECOND; - } while ( nanos_ >= NANOSECONDS_PER_SECOND ); - } else if (nanos_ <= -NANOSECONDS_PER_SECOND ) { - do { - seconds_--; - nanos_ += NANOSECONDS_PER_SECOND; - } while (nanos_ <= -NANOSECONDS_PER_SECOND); - } - - if (seconds_ >= 1 && nanos_ < 0) { - seconds_--; - nanos_ += NANOSECONDS_PER_SECOND; - } else if (seconds_ < 0 && nanos_ > 0) { - seconds_++; - nanos_ -= NANOSECONDS_PER_SECOND; - } -} - -} // namespace llvm - -/// Include the platform-specific portion of TimeValue class -#ifdef LLVM_ON_UNIX -#include "Unix/TimeValue.inc" -#endif -#ifdef LLVM_ON_WIN32 -#include "Windows/TimeValue.inc" -#endif diff --git a/contrib/llvm/lib/Support/Timer.cpp b/contrib/llvm/lib/Support/Timer.cpp index 49bd39e..fbd73d0 100644 --- a/contrib/llvm/lib/Support/Timer.cpp +++ b/contrib/llvm/lib/Support/Timer.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// Interval Timing implementation. +/// \file Interval Timing implementation. // //===----------------------------------------------------------------------===// @@ -21,16 +21,16 @@ #include "llvm/Support/Mutex.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/YAMLTraits.h" using namespace llvm; -// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy -// of constructor/destructor ordering being unspecified by C++. Basically the -// problem is that a Statistic object gets destroyed, which ends up calling -// 'GetLibSupportInfoOutputFile()' (below), which calls this function. -// LibSupportInfoOutputFilename used to be a global variable, but sometimes it -// would get destroyed before the Statistic, causing havoc to ensue. We "fix" -// this by creating the string the first time it is needed and never destroying -// it. +// This ugly hack is brought to you courtesy of constructor/destructor ordering +// being unspecified by C++. Basically the problem is that a Statistic object +// gets destroyed, which ends up calling 'GetLibSupportInfoOutputFile()' +// (below), which calls this function. LibSupportInfoOutputFilename used to be +// a global variable, but sometimes it would get destroyed before the Statistic, +// causing havoc to ensue. We "fix" this by creating the string the first time +// it is needed and never destroying it. static ManagedStatic<std::string> LibSupportInfoOutputFilename; static std::string &getLibSupportInfoOutputFilename() { return *LibSupportInfoOutputFilename; @@ -50,7 +50,6 @@ namespace { cl::Hidden, cl::location(getLibSupportInfoOutputFilename())); } -// Return a file stream to print our output on. std::unique_ptr<raw_fd_ostream> llvm::CreateInfoOutputFile() { const std::string &OutputFilename = getLibSupportInfoOutputFilename(); if (OutputFilename.empty()) @@ -83,7 +82,7 @@ static TimerGroup *getDefaultTimerGroup() { sys::SmartScopedLock<true> Lock(*TimerLock); tmp = DefaultTimerGroup; if (!tmp) { - tmp = new TimerGroup("Miscellaneous Ungrouped Timers"); + tmp = new TimerGroup("misc", "Miscellaneous Ungrouped Timers"); sys::MemoryFence(); DefaultTimerGroup = tmp; } @@ -95,13 +94,14 @@ static TimerGroup *getDefaultTimerGroup() { // Timer Implementation //===----------------------------------------------------------------------===// -void Timer::init(StringRef N) { - init(N, *getDefaultTimerGroup()); +void Timer::init(StringRef Name, StringRef Description) { + init(Name, Description, *getDefaultTimerGroup()); } -void Timer::init(StringRef N, TimerGroup &tg) { +void Timer::init(StringRef Name, StringRef Description, TimerGroup &tg) { assert(!TG && "Timer already initialized"); - Name.assign(N.begin(), N.end()); + this->Name.assign(Name.begin(), Name.end()); + this->Description.assign(Description.begin(), Description.end()); Running = Triggered = false; TG = &tg; TG->addTimer(*this); @@ -118,8 +118,10 @@ static inline size_t getMemUsage() { } TimeRecord TimeRecord::getCurrentTime(bool Start) { + using Seconds = std::chrono::duration<double, std::ratio<1>>; TimeRecord Result; - sys::TimeValue now(0,0), user(0,0), sys(0,0); + sys::TimePoint<> now; + std::chrono::nanoseconds user, sys; if (Start) { Result.MemUsed = getMemUsage(); @@ -129,9 +131,9 @@ TimeRecord TimeRecord::getCurrentTime(bool Start) { Result.MemUsed = getMemUsage(); } - Result.WallTime = now.seconds() + now.microseconds() / 1000000.0; - Result.UserTime = user.seconds() + user.microseconds() / 1000000.0; - Result.SystemTime = sys.seconds() + sys.microseconds() / 1000000.0; + Result.WallTime = Seconds(now.time_since_epoch()).count(); + Result.UserTime = Seconds(user).count(); + Result.SystemTime = Seconds(sys).count(); return Result; } @@ -193,54 +195,44 @@ public: delete I->second.first; } - Timer &get(StringRef Name, StringRef GroupName) { + Timer &get(StringRef Name, StringRef Description, StringRef GroupName, + StringRef GroupDescription) { sys::SmartScopedLock<true> L(*TimerLock); std::pair<TimerGroup*, Name2TimerMap> &GroupEntry = Map[GroupName]; if (!GroupEntry.first) - GroupEntry.first = new TimerGroup(GroupName); + GroupEntry.first = new TimerGroup(GroupName, GroupDescription); Timer &T = GroupEntry.second[Name]; if (!T.isInitialized()) - T.init(Name, *GroupEntry.first); + T.init(Name, Description, *GroupEntry.first); return T; } }; } -static ManagedStatic<Name2TimerMap> NamedTimers; static ManagedStatic<Name2PairMap> NamedGroupedTimers; -static Timer &getNamedRegionTimer(StringRef Name) { - sys::SmartScopedLock<true> L(*TimerLock); - - Timer &T = (*NamedTimers)[Name]; - if (!T.isInitialized()) - T.init(Name); - return T; -} - -NamedRegionTimer::NamedRegionTimer(StringRef Name, - bool Enabled) - : TimeRegion(!Enabled ? nullptr : &getNamedRegionTimer(Name)) {} - -NamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef GroupName, - bool Enabled) - : TimeRegion(!Enabled ? nullptr : &NamedGroupedTimers->get(Name, GroupName)){} +NamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef Description, + StringRef GroupName, + StringRef GroupDescription, bool Enabled) + : TimeRegion(!Enabled ? nullptr + : &NamedGroupedTimers->get(Name, Description, GroupName, + GroupDescription)) {} //===----------------------------------------------------------------------===// // TimerGroup Implementation //===----------------------------------------------------------------------===// -/// TimerGroupList - This is the global list of TimerGroups, maintained by the -/// TimerGroup ctor/dtor and is protected by the TimerLock lock. +/// This is the global list of TimerGroups, maintained by the TimerGroup +/// ctor/dtor and is protected by the TimerLock lock. static TimerGroup *TimerGroupList = nullptr; -TimerGroup::TimerGroup(StringRef name) - : Name(name.begin(), name.end()), FirstTimer(nullptr) { - +TimerGroup::TimerGroup(StringRef Name, StringRef Description) + : Name(Name.begin(), Name.end()), + Description(Description.begin(), Description.end()) { // Add the group to TimerGroupList. sys::SmartScopedLock<true> L(*TimerLock); if (TimerGroupList) @@ -269,7 +261,7 @@ void TimerGroup::removeTimer(Timer &T) { // If the timer was started, move its data to TimersToPrint. if (T.hasTriggered()) - TimersToPrint.emplace_back(T.Time, T.Name); + TimersToPrint.emplace_back(T.Time, T.Name, T.Description); T.TG = nullptr; @@ -303,15 +295,15 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) { std::sort(TimersToPrint.begin(), TimersToPrint.end()); TimeRecord Total; - for (auto &RecordNamePair : TimersToPrint) - Total += RecordNamePair.first; + for (const PrintRecord &Record : TimersToPrint) + Total += Record.Time; // Print out timing header. OS << "===" << std::string(73, '-') << "===\n"; // Figure out how many spaces to indent TimerGroup name. - unsigned Padding = (80-Name.length())/2; + unsigned Padding = (80-Description.length())/2; if (Padding > 80) Padding = 0; // Don't allow "negative" numbers - OS.indent(Padding) << Name << '\n'; + OS.indent(Padding) << Description << '\n'; OS << "===" << std::string(73, '-') << "===\n"; // If this is not an collection of ungrouped times, print the total time. @@ -334,10 +326,10 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) { OS << " --- Name ---\n"; // Loop through all of the timing data, printing it out. - for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) { - const std::pair<TimeRecord, std::string> &Entry = TimersToPrint[e-i-1]; - Entry.first.print(Total, OS); - OS << Entry.second << '\n'; + for (const PrintRecord &Record : make_range(TimersToPrint.rbegin(), + TimersToPrint.rend())) { + Record.Time.print(Total, OS); + OS << Record.Description << '\n'; } Total.print(Total, OS); @@ -347,29 +339,66 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) { TimersToPrint.clear(); } -/// print - Print any started timers in this group and zero them. -void TimerGroup::print(raw_ostream &OS) { - sys::SmartScopedLock<true> L(*TimerLock); - +void TimerGroup::prepareToPrintList() { // See if any of our timers were started, if so add them to TimersToPrint and // reset them. for (Timer *T = FirstTimer; T; T = T->Next) { if (!T->hasTriggered()) continue; - TimersToPrint.emplace_back(T->Time, T->Name); - + TimersToPrint.emplace_back(T->Time, T->Name, T->Description); + // Clear out the time. T->clear(); } +} + +void TimerGroup::print(raw_ostream &OS) { + sys::SmartScopedLock<true> L(*TimerLock); + + prepareToPrintList(); // If any timers were started, print the group. if (!TimersToPrint.empty()) PrintQueuedTimers(OS); } -/// printAll - This static method prints all timers and clears them all out. void TimerGroup::printAll(raw_ostream &OS) { sys::SmartScopedLock<true> L(*TimerLock); for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next) TG->print(OS); } + +void TimerGroup::printJSONValue(raw_ostream &OS, const PrintRecord &R, + const char *suffix, double Value) { + assert(!yaml::needsQuotes(Name) && "TimerGroup name needs no quotes"); + assert(!yaml::needsQuotes(R.Name) && "Timer name needs no quotes"); + OS << "\t\"time." << Name << '.' << R.Name << suffix << "\": " << Value; +} + +const char *TimerGroup::printJSONValues(raw_ostream &OS, const char *delim) { + prepareToPrintList(); + for (const PrintRecord &R : TimersToPrint) { + OS << delim; + delim = ",\n"; + + const TimeRecord &T = R.Time; + printJSONValue(OS, R, ".wall", T.getWallTime()); + OS << delim; + printJSONValue(OS, R, ".user", T.getUserTime()); + OS << delim; + printJSONValue(OS, R, ".sys", T.getSystemTime()); + } + TimersToPrint.clear(); + return delim; +} + +const char *TimerGroup::printAllJSONValues(raw_ostream &OS, const char *delim) { + sys::SmartScopedLock<true> L(*TimerLock); + for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next) + delim = TG->printJSONValues(OS, delim); + return delim; +} + +void TimerGroup::ConstructTimerLists() { + (void)*NamedGroupedTimers; +} diff --git a/contrib/llvm/lib/Support/TrigramIndex.cpp b/contrib/llvm/lib/Support/TrigramIndex.cpp new file mode 100644 index 0000000..85ab528 --- /dev/null +++ b/contrib/llvm/lib/Support/TrigramIndex.cpp @@ -0,0 +1,111 @@ +//===-- TrigramIndex.cpp - a heuristic for SpecialCaseList ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// TrigramIndex implements a heuristic for SpecialCaseList that allows to +// filter out ~99% incoming queries when all regular expressions in the +// SpecialCaseList are simple wildcards with '*' and '.'. If rules are more +// complicated, the check is defeated and it will always pass the queries to a +// full regex. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/TrigramIndex.h" +#include "llvm/ADT/SmallVector.h" + +#include <unordered_map> +#include <set> +#include <string> + +using namespace llvm; + +static const char RegexAdvancedMetachars[] = "()^$|+?[]\\{}"; + +static bool isAdvancedMetachar(unsigned Char) { + return strchr(RegexAdvancedMetachars, Char) != nullptr; +} + +void TrigramIndex::insert(std::string Regex) { + if (Defeated) return; + std::set<unsigned> Was; + unsigned Cnt = 0; + unsigned Tri = 0; + unsigned Len = 0; + bool Escaped = false; + for (unsigned Char : Regex) { + if (!Escaped) { + // Regular expressions allow escaping symbols by preceding it with '\'. + if (Char == '\\') { + Escaped = true; + continue; + } + if (isAdvancedMetachar(Char)) { + // This is a more complicated regex than we can handle here. + Defeated = true; + return; + } + if (Char == '.' || Char == '*') { + Tri = 0; + Len = 0; + continue; + } + } + if (Escaped && Char >= '1' && Char <= '9') { + Defeated = true; + return; + } + // We have already handled escaping and can reset the flag. + Escaped = false; + Tri = ((Tri << 8) + Char) & 0xFFFFFF; + Len++; + if (Len < 3) + continue; + // We don't want the index to grow too much for the popular trigrams, + // as they are weak signals. It's ok to still require them for the + // rules we have already processed. It's just a small additional + // computational cost. + if (Index[Tri].size() >= 4) + continue; + Cnt++; + if (!Was.count(Tri)) { + // Adding the current rule to the index. + Index[Tri].push_back(Counts.size()); + Was.insert(Tri); + } + } + if (!Cnt) { + // This rule does not have remarkable trigrams to rely on. + // We have to always call the full regex chain. + Defeated = true; + return; + } + Counts.push_back(Cnt); +} + +bool TrigramIndex::isDefinitelyOut(StringRef Query) const { + if (Defeated) + return false; + std::vector<unsigned> CurCounts(Counts.size()); + unsigned Tri = 0; + for (size_t I = 0; I < Query.size(); I++) { + Tri = ((Tri << 8) + Query[I]) & 0xFFFFFF; + if (I < 2) + continue; + const auto &II = Index.find(Tri); + if (II == Index.end()) + continue; + for (size_t J : II->second) { + CurCounts[J]++; + // If we have reached a desired limit, we have to look at the query + // more closely by running a full regex. + if (CurCounts[J] >= Counts[J]) + return false; + } + } + return true; +} diff --git a/contrib/llvm/lib/Support/Triple.cpp b/contrib/llvm/lib/Support/Triple.cpp index 2bac2a3..6783b40 100644 --- a/contrib/llvm/lib/Support/Triple.cpp +++ b/contrib/llvm/lib/Support/Triple.cpp @@ -17,7 +17,7 @@ #include <cstring> using namespace llvm; -const char *Triple::getArchTypeName(ArchType Kind) { +StringRef Triple::getArchTypeName(ArchType Kind) { switch (Kind) { case UnknownArch: return "unknown"; @@ -39,11 +39,14 @@ const char *Triple::getArchTypeName(ArchType Kind) { case ppc: return "powerpc"; case r600: return "r600"; case amdgcn: return "amdgcn"; + case riscv32: return "riscv32"; + case riscv64: return "riscv64"; case sparc: return "sparc"; case sparcv9: return "sparcv9"; case sparcel: return "sparcel"; case systemz: return "s390x"; case tce: return "tce"; + case tcele: return "tcele"; case thumb: return "thumb"; case thumbeb: return "thumbeb"; case x86: return "i386"; @@ -71,10 +74,10 @@ const char *Triple::getArchTypeName(ArchType Kind) { llvm_unreachable("Invalid ArchType!"); } -const char *Triple::getArchTypePrefix(ArchType Kind) { +StringRef Triple::getArchTypePrefix(ArchType Kind) { switch (Kind) { default: - return nullptr; + return StringRef(); case aarch64: case aarch64_be: return "aarch64"; @@ -134,10 +137,13 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case shave: return "shave"; case wasm32: case wasm64: return "wasm"; + + case riscv32: + case riscv64: return "riscv"; } } -const char *Triple::getVendorTypeName(VendorType Kind) { +StringRef Triple::getVendorTypeName(VendorType Kind) { switch (Kind) { case UnknownVendor: return "unknown"; @@ -160,7 +166,7 @@ const char *Triple::getVendorTypeName(VendorType Kind) { llvm_unreachable("Invalid VendorType!"); } -const char *Triple::getOSTypeName(OSType Kind) { +StringRef Triple::getOSTypeName(OSType Kind) { switch (Kind) { case UnknownOS: return "unknown"; @@ -168,6 +174,7 @@ const char *Triple::getOSTypeName(OSType Kind) { case Darwin: return "darwin"; case DragonFly: return "dragonfly"; case FreeBSD: return "freebsd"; + case Fuchsia: return "fuchsia"; case IOS: return "ios"; case KFreeBSD: return "kfreebsd"; case Linux: return "linux"; @@ -192,12 +199,13 @@ const char *Triple::getOSTypeName(OSType Kind) { case TvOS: return "tvos"; case WatchOS: return "watchos"; case Mesa3D: return "mesa3d"; + case Contiki: return "contiki"; } llvm_unreachable("Invalid OSType"); } -const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { +StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) { switch (Kind) { case UnknownEnvironment: return "unknown"; case GNU: return "gnu"; @@ -217,6 +225,7 @@ const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { case Cygnus: return "cygnus"; case AMDOpenCL: return "amdopencl"; case CoreCLR: return "coreclr"; + case OpenCL: return "opencl"; } llvm_unreachable("Invalid EnvironmentType!"); @@ -258,12 +267,15 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { .Case("ppc64le", ppc64le) .Case("r600", r600) .Case("amdgcn", amdgcn) + .Case("riscv32", riscv32) + .Case("riscv64", riscv64) .Case("hexagon", hexagon) .Case("sparc", sparc) .Case("sparcel", sparcel) .Case("sparcv9", sparcv9) .Case("systemz", systemz) .Case("tce", tce) + .Case("tcele", tcele) .Case("thumb", thumb) .Case("thumbeb", thumbeb) .Case("x86", x86) @@ -373,12 +385,15 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Case("mips64el", Triple::mips64el) .Case("r600", Triple::r600) .Case("amdgcn", Triple::amdgcn) + .Case("riscv32", Triple::riscv32) + .Case("riscv64", Triple::riscv64) .Case("hexagon", Triple::hexagon) .Cases("s390x", "systemz", Triple::systemz) .Case("sparc", Triple::sparc) .Case("sparcel", Triple::sparcel) .Cases("sparcv9", "sparc64", Triple::sparcv9) .Case("tce", Triple::tce) + .Case("tcele", Triple::tcele) .Case("xcore", Triple::xcore) .Case("nvptx", Triple::nvptx) .Case("nvptx64", Triple::nvptx64) @@ -437,6 +452,7 @@ static Triple::OSType parseOS(StringRef OSName) { .StartsWith("darwin", Triple::Darwin) .StartsWith("dragonfly", Triple::DragonFly) .StartsWith("freebsd", Triple::FreeBSD) + .StartsWith("fuchsia", Triple::Fuchsia) .StartsWith("ios", Triple::IOS) .StartsWith("kfreebsd", Triple::KFreeBSD) .StartsWith("linux", Triple::Linux) @@ -462,6 +478,7 @@ static Triple::OSType parseOS(StringRef OSName) { .StartsWith("tvos", Triple::TvOS) .StartsWith("watchos", Triple::WatchOS) .StartsWith("mesa3d", Triple::Mesa3D) + .StartsWith("contiki", Triple::Contiki) .Default(Triple::UnknownOS); } @@ -484,6 +501,7 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) { .StartsWith("cygnus", Triple::Cygnus) .StartsWith("amdopencl", Triple::AMDOpenCL) .StartsWith("coreclr", Triple::CoreCLR) + .StartsWith("opencl", Triple::OpenCL) .Default(Triple::UnknownEnvironment); } @@ -546,6 +564,8 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) { return Triple::ARMSubArch_v8_1a; case ARM::AK_ARMV8_2A: return Triple::ARMSubArch_v8_2a; + case ARM::AK_ARMV8R: + return Triple::ARMSubArch_v8r; case ARM::AK_ARMV8MBaseline: return Triple::ARMSubArch_v8m_baseline; case ARM::AK_ARMV8MMainline: @@ -555,7 +575,7 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) { } } -static const char *getObjectFormatTypeName(Triple::ObjectFormatType Kind) { +static StringRef getObjectFormatTypeName(Triple::ObjectFormatType Kind) { switch (Kind) { case Triple::UnknownObjectFormat: return ""; case Triple::COFF: return "coff"; @@ -605,6 +625,8 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { case Triple::r600: case Triple::renderscript32: case Triple::renderscript64: + case Triple::riscv32: + case Triple::riscv64: case Triple::shave: case Triple::sparc: case Triple::sparcel: @@ -613,6 +635,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { case Triple::spir64: case Triple::systemz: case Triple::tce: + case Triple::tcele: case Triple::thumbeb: case Triple::wasm32: case Triple::wasm64: @@ -1132,9 +1155,11 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::nvptx: case llvm::Triple::ppc: case llvm::Triple::r600: + case llvm::Triple::riscv32: case llvm::Triple::sparc: case llvm::Triple::sparcel: case llvm::Triple::tce: + case llvm::Triple::tcele: case llvm::Triple::thumb: case llvm::Triple::thumbeb: case llvm::Triple::x86: @@ -1160,6 +1185,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::nvptx64: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: + case llvm::Triple::riscv64: case llvm::Triple::sparcv9: case llvm::Triple::systemz: case llvm::Triple::x86_64: @@ -1212,9 +1238,11 @@ Triple Triple::get32BitArchVariant() const { case Triple::nvptx: case Triple::ppc: case Triple::r600: + case Triple::riscv32: case Triple::sparc: case Triple::sparcel: case Triple::tce: + case Triple::tcele: case Triple::thumb: case Triple::thumbeb: case Triple::x86: @@ -1234,6 +1262,7 @@ Triple Triple::get32BitArchVariant() const { 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::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; @@ -1255,6 +1284,7 @@ Triple Triple::get64BitArchVariant() const { case Triple::msp430: case Triple::r600: case Triple::tce: + case Triple::tcele: case Triple::xcore: case Triple::sparcel: case Triple::shave: @@ -1275,6 +1305,7 @@ Triple Triple::get64BitArchVariant() const { case Triple::nvptx64: case Triple::ppc64: case Triple::ppc64le: + case Triple::riscv64: case Triple::sparcv9: case Triple::systemz: case Triple::x86_64: @@ -1291,6 +1322,7 @@ Triple Triple::get64BitArchVariant() const { 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::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; @@ -1324,6 +1356,8 @@ Triple Triple::getBigEndianArchVariant() const { case Triple::nvptx64: case Triple::nvptx: case Triple::r600: + case Triple::riscv32: + case Triple::riscv64: case Triple::shave: case Triple::spir64: case Triple::spir: @@ -1342,6 +1376,7 @@ 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; @@ -1365,7 +1400,6 @@ Triple Triple::getLittleEndianArchVariant() const { case Triple::ppc: case Triple::sparcv9: case Triple::systemz: - case Triple::tce: // ARM is intentionally unsupported here, changing the architecture would // drop any arch suffixes. @@ -1374,6 +1408,7 @@ 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; @@ -1408,6 +1443,8 @@ bool Triple::isLittleEndian() const { case Triple::nvptx: case Triple::ppc64le: case Triple::r600: + case Triple::riscv32: + case Triple::riscv64: case Triple::shave: case Triple::sparcel: case Triple::spir64: @@ -1418,6 +1455,7 @@ bool Triple::isLittleEndian() const { case Triple::x86: case Triple::x86_64: case Triple::xcore: + case Triple::tcele: case Triple::renderscript32: case Triple::renderscript64: return true; diff --git a/contrib/llvm/lib/Support/Twine.cpp b/contrib/llvm/lib/Support/Twine.cpp index 5e989fb..465c6e6 100644 --- a/contrib/llvm/lib/Support/Twine.cpp +++ b/contrib/llvm/lib/Support/Twine.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -18,6 +19,11 @@ std::string Twine::str() const { if (LHSKind == StdStringKind && RHSKind == EmptyKind) return *LHS.stdString; + // If we're storing a formatv_object, we can avoid an extra copy by formatting + // it immediately and returning the result. + if (LHSKind == FormatvObjectKind && RHSKind == EmptyKind) + return LHS.formatvObject->str(); + // Otherwise, flatten and copy the contents first. SmallString<256> Vec; return toStringRef(Vec).str(); @@ -68,6 +74,9 @@ void Twine::printOneChild(raw_ostream &OS, Child Ptr, case Twine::SmallStringKind: OS << *Ptr.smallString; break; + case Twine::FormatvObjectKind: + OS << *Ptr.formatvObject; + break; case Twine::CharKind: OS << Ptr.character; break; @@ -121,6 +130,9 @@ void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr, case Twine::SmallStringKind: OS << "smallstring:\"" << *Ptr.smallString << "\""; break; + case Twine::FormatvObjectKind: + OS << "formatv:\"" << *Ptr.formatvObject << "\""; + break; case Twine::CharKind: OS << "char:\"" << Ptr.character << "\""; break; diff --git a/contrib/llvm/lib/Support/Unix/Memory.inc b/contrib/llvm/lib/Support/Unix/Memory.inc index f3463e5..edbc793 100644 --- a/contrib/llvm/lib/Support/Unix/Memory.inc +++ b/contrib/llvm/lib/Support/Unix/Memory.inc @@ -91,17 +91,9 @@ Memory::allocateMappedMemory(size_t NumBytes, const size_t NumPages = (NumBytes+PageSize-1)/PageSize; int fd = -1; -#ifdef NEED_DEV_ZERO_FOR_MMAP - static int zero_fd = open("/dev/zero", O_RDWR); - if (zero_fd == -1) { - EC = std::error_code(errno, std::generic_category()); - return MemoryBlock(); - } - fd = zero_fd; -#endif int MMFlags = MAP_PRIVATE | -#ifdef HAVE_MMAP_ANONYMOUS +#ifdef MAP_ANONYMOUS MAP_ANONYMOUS #else MAP_ANON @@ -161,7 +153,10 @@ Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { int Protect = getPosixProtectionFlags(Flags); - int Result = ::mprotect((void*)((uintptr_t)M.Address & ~(PageSize-1)), PageSize*((M.Size+PageSize-1)/PageSize), Protect); + uintptr_t Start = alignAddr((uint8_t *)M.Address - PageSize + 1, PageSize); + uintptr_t End = alignAddr((uint8_t *)M.Address + M.Size, PageSize); + int Result = ::mprotect((void *)Start, End - Start, Protect); + if (Result != 0) return std::error_code(errno, std::generic_category()); @@ -185,17 +180,9 @@ Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, size_t NumPages = (NumBytes+PageSize-1)/PageSize; int fd = -1; -#ifdef NEED_DEV_ZERO_FOR_MMAP - static int zero_fd = open("/dev/zero", O_RDWR); - if (zero_fd == -1) { - MakeErrMsg(ErrMsg, "Can't open /dev/zero device"); - return MemoryBlock(); - } - fd = zero_fd; -#endif int flags = MAP_PRIVATE | -#ifdef HAVE_MMAP_ANONYMOUS +#ifdef MAP_ANONYMOUS MAP_ANONYMOUS #else MAP_ANON diff --git a/contrib/llvm/lib/Support/Unix/Path.inc b/contrib/llvm/lib/Support/Unix/Path.inc index 84aafcb..e0b11aa 100644 --- a/contrib/llvm/lib/Support/Unix/Path.inc +++ b/contrib/llvm/lib/Support/Unix/Path.inc @@ -53,7 +53,7 @@ #include <sys/attr.h> #endif -// Both stdio.h and cstdio are included via different pathes and +// Both stdio.h and cstdio are included via different paths and // stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros // either. #undef ferror @@ -90,7 +90,8 @@ namespace sys { namespace fs { #if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \ - defined(__linux__) || defined(__CYGWIN__) || defined(__DragonFly__) + defined(__linux__) || defined(__CYGWIN__) || defined(__DragonFly__) || \ + defined(_AIX) static int test_dir(char ret[PATH_MAX], const char *dir, const char *bin) { @@ -161,7 +162,7 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) { } #elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ defined(__OpenBSD__) || defined(__minix) || defined(__DragonFly__) || \ - defined(__FreeBSD_kernel__) + defined(__FreeBSD_kernel__) || defined(_AIX) char exe_path[PATH_MAX]; if (getprogpath(exe_path, argv0) != NULL) @@ -197,16 +198,12 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) { return ""; } -TimeValue file_status::getLastAccessedTime() const { - TimeValue Ret; - Ret.fromEpochTime(fs_st_atime); - return Ret; +TimePoint<> file_status::getLastAccessedTime() const { + return toTimePoint(fs_st_atime); } -TimeValue file_status::getLastModificationTime() const { - TimeValue Ret; - Ret.fromEpochTime(fs_st_mtime); - return Ret; +TimePoint<> file_status::getLastModificationTime() const { + return toTimePoint(fs_st_mtime); } UniqueID file_status::getUniqueID() const { @@ -288,6 +285,19 @@ std::error_code create_link(const Twine &to, const Twine &from) { return std::error_code(); } +std::error_code create_hard_link(const Twine &to, const Twine &from) { + // Get arguments. + SmallString<128> from_storage; + SmallString<128> to_storage; + StringRef f = from.toNullTerminatedStringRef(from_storage); + StringRef t = to.toNullTerminatedStringRef(to_storage); + + if (::link(t.begin(), f.begin()) == -1) + return std::error_code(errno, std::generic_category()); + + return std::error_code(); +} + std::error_code remove(const Twine &path, bool IgnoreNonExisting) { SmallString<128> path_storage; StringRef p = path.toNullTerminatedStringRef(path_storage); @@ -329,8 +339,17 @@ std::error_code rename(const Twine &from, const Twine &to) { } std::error_code resize_file(int FD, uint64_t Size) { +#if defined(HAVE_POSIX_FALLOCATE) + // If we have posix_fallocate use it. Unlike ftruncate it always allocates + // space, so we get an error if the disk is full. + if (int Err = ::posix_fallocate(FD, 0, Size)) + return std::error_code(Err, std::generic_category()); +#else + // Use ftruncate as a fallback. It may or may not allocate space. At least on + // OS X with HFS+ it does. if (::ftruncate(FD, Size) == -1) return std::error_code(errno, std::generic_category()); +#endif return std::error_code(); } @@ -436,20 +455,17 @@ std::error_code status(int FD, file_status &Result) { return fillStatus(StatRet, Status, Result); } -std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { +std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time) { #if defined(HAVE_FUTIMENS) timespec Times[2]; - Times[0].tv_sec = Time.toEpochTime(); - Times[0].tv_nsec = 0; - Times[1] = Times[0]; + Times[0] = Times[1] = sys::toTimeSpec(Time); if (::futimens(FD, Times)) return std::error_code(errno, std::generic_category()); return std::error_code(); #elif defined(HAVE_FUTIMES) timeval Times[2]; - Times[0].tv_sec = Time.toEpochTime(); - Times[0].tv_usec = 0; - Times[1] = Times[0]; + Times[0] = Times[1] = sys::toTimeVal( + std::chrono::time_point_cast<std::chrono::microseconds>(Time)); if (::futimes(FD, Times)) return std::error_code(errno, std::generic_category()); return std::error_code(); diff --git a/contrib/llvm/lib/Support/Unix/Process.inc b/contrib/llvm/lib/Support/Unix/Process.inc index d81836b..16f8f5a 100644 --- a/contrib/llvm/lib/Support/Unix/Process.inc +++ b/contrib/llvm/lib/Support/Unix/Process.inc @@ -17,7 +17,6 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" -#include "llvm/Support/TimeValue.h" #if HAVE_FCNTL_H #include <fcntl.h> #endif @@ -60,22 +59,14 @@ using namespace llvm; using namespace sys; -static std::pair<TimeValue, TimeValue> getRUsageTimes() { +static std::pair<std::chrono::microseconds, std::chrono::microseconds> getRUsageTimes() { #if defined(HAVE_GETRUSAGE) struct rusage RU; ::getrusage(RUSAGE_SELF, &RU); - return std::make_pair( - TimeValue( - static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec), - static_cast<TimeValue::NanoSecondsType>( - RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)), - TimeValue( - static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec), - static_cast<TimeValue::NanoSecondsType>( - RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND))); + return { toDuration(RU.ru_utime), toDuration(RU.ru_stime) }; #else #warning Cannot get usage times on this platform - return std::make_pair(TimeValue(), TimeValue()); + return { std::chrono::microseconds::zero(), std::chrono::microseconds::zero() }; #endif } @@ -121,9 +112,9 @@ size_t Process::GetMallocUsage() { #endif } -void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, - TimeValue &sys_time) { - elapsed = TimeValue::now(); +void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time, + std::chrono::nanoseconds &sys_time) { + elapsed = std::chrono::system_clock::now(); std::tie(user_time, sys_time) = getRUsageTimes(); } @@ -429,7 +420,7 @@ const char *Process::ResetColor() { return "\033[0m"; } -#if !defined(HAVE_DECL_ARC4RANDOM) || !HAVE_DECL_ARC4RANDOM +#if !HAVE_DECL_ARC4RANDOM static unsigned GetRandomNumberSeed() { // Attempt to get the initial seed from /dev/urandom, if possible. int urandomFD = open("/dev/urandom", O_RDONLY); @@ -449,13 +440,13 @@ static unsigned GetRandomNumberSeed() { // Otherwise, swizzle the current time and the process ID to form a reasonable // seed. - TimeValue Now = TimeValue::now(); - return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid()); + const auto Now = std::chrono::high_resolution_clock::now(); + return hash_combine(Now.time_since_epoch().count(), ::getpid()); } #endif unsigned llvm::sys::Process::GetRandomNumber() { -#if defined(HAVE_DECL_ARC4RANDOM) && HAVE_DECL_ARC4RANDOM +#if HAVE_DECL_ARC4RANDOM return arc4random(); #else static int x = (static_cast<void>(::srand(GetRandomNumberSeed())), 0); diff --git a/contrib/llvm/lib/Support/Unix/Signals.inc b/contrib/llvm/lib/Support/Unix/Signals.inc index 55fd76d..9752b70 100644 --- a/contrib/llvm/lib/Support/Unix/Signals.inc +++ b/contrib/llvm/lib/Support/Unix/Signals.inc @@ -14,6 +14,7 @@ #include "Unix.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/Support/Format.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" @@ -33,9 +34,6 @@ #if HAVE_SYS_STAT_H #include <sys/stat.h> #endif -#if HAVE_CXXABI_H -#include <cxxabi.h> -#endif #if HAVE_DLFCN_H #include <dlfcn.h> #endif @@ -45,7 +43,7 @@ #if HAVE_LINK_H #include <link.h> #endif -#if HAVE_UNWIND_BACKTRACE +#ifdef HAVE__UNWIND_BACKTRACE // FIXME: We should be able to use <unwind.h> for any target that has an // _Unwind_Backtrace function, but on FreeBSD the configure test passes // despite the function not existing, and on Android, <unwind.h> conflicts @@ -53,7 +51,7 @@ #ifdef __GLIBC__ #include <unwind.h> #else -#undef HAVE_UNWIND_BACKTRACE +#undef HAVE__UNWIND_BACKTRACE #endif #endif @@ -120,14 +118,15 @@ static void RegisterHandler(int Signal) { } #if defined(HAVE_SIGALTSTACK) -// Hold onto the old alternate signal stack so that it's not reported as a leak. -// We don't make any attempt to remove our alt signal stack if we remove our -// signal handlers; that can't be done reliably if someone else is also trying -// to do the same thing. +// Hold onto both the old and new alternate signal stack so that it's not +// reported as a leak. We don't make any attempt to remove our alt signal +// stack if we remove our signal handlers; that can't be done reliably if +// someone else is also trying to do the same thing. static stack_t OldAltStack; +static void* NewAltStackPointer; static void CreateSigAltStack() { - const size_t AltStackSize = MINSIGSTKSZ + 8192; + const size_t AltStackSize = MINSIGSTKSZ + 64 * 1024; // If we're executing on the alternate stack, or we already have an alternate // signal stack that we're happy with, there's nothing for us to do. Don't @@ -140,6 +139,7 @@ static void CreateSigAltStack() { stack_t AltStack = {}; AltStack.ss_sp = reinterpret_cast<char *>(malloc(AltStackSize)); + NewAltStackPointer = AltStack.ss_sp; // Save to avoid reporting a leak. AltStack.ss_size = AltStackSize; if (sigaltstack(&AltStack, &OldAltStack) != 0) free(AltStack.ss_sp); @@ -284,7 +284,7 @@ bool llvm::sys::RemoveFileOnSignal(StringRef Filename, void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) { sys::SmartScopedLock<true> Guard(*SignalsMutex); std::vector<std::string>::reverse_iterator RI = - std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename); + find(reverse(*FilesToRemove), Filename); std::vector<std::string>::iterator I = FilesToRemove->end(); if (RI != FilesToRemove->rend()) I = FilesToRemove->erase(RI.base()-1); @@ -298,7 +298,7 @@ void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { RegisterHandlers(); } -#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) && HAVE_LINK_H && \ +#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && HAVE_LINK_H && \ (defined(__linux__) || defined(__FreeBSD__) || \ defined(__FreeBSD_kernel__) || defined(__NetBSD__)) struct DlIteratePhdrData { @@ -353,9 +353,9 @@ static bool findModulesAndOffsets(void **StackTrace, int Depth, StringSaver &StrPool) { return false; } -#endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) && ... +#endif // defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && ... -#if defined(ENABLE_BACKTRACES) && defined(HAVE_UNWIND_BACKTRACE) +#if ENABLE_BACKTRACES && defined(HAVE__UNWIND_BACKTRACE) static int unwindBacktrace(void **StackTrace, int MaxEntries) { if (MaxEntries < 0) return 0; @@ -393,7 +393,7 @@ static int unwindBacktrace(void **StackTrace, int MaxEntries) { // On glibc systems we have the 'backtrace' function, which works nicely, but // doesn't demangle symbols. void llvm::sys::PrintStackTrace(raw_ostream &OS) { -#if defined(ENABLE_BACKTRACES) +#if ENABLE_BACKTRACES static void *StackTrace[256]; int depth = 0; #if defined(HAVE_BACKTRACE) @@ -401,7 +401,7 @@ void llvm::sys::PrintStackTrace(raw_ostream &OS) { if (!depth) depth = backtrace(StackTrace, static_cast<int>(array_lengthof(StackTrace))); #endif -#if defined(HAVE_UNWIND_BACKTRACE) +#if defined(HAVE__UNWIND_BACKTRACE) // Try _Unwind_Backtrace() if backtrace() failed. if (!depth) depth = unwindBacktrace(StackTrace, @@ -441,12 +441,8 @@ void llvm::sys::PrintStackTrace(raw_ostream &OS) { if (dlinfo.dli_sname != nullptr) { OS << ' '; -# if HAVE_CXXABI_H int res; - char* d = abi::__cxa_demangle(dlinfo.dli_sname, nullptr, nullptr, &res); -# else - char* d = NULL; -# endif + char* d = itaniumDemangle(dlinfo.dli_sname, nullptr, nullptr, &res); if (!d) OS << dlinfo.dli_sname; else OS << d; free(d); @@ -479,7 +475,7 @@ void llvm::sys::PrintStackTraceOnErrorSignal(StringRef Argv0, AddSignalHandler(PrintStackTraceSignalHandler, nullptr); -#if defined(__APPLE__) && defined(ENABLE_CRASH_OVERRIDES) +#if defined(__APPLE__) && ENABLE_CRASH_OVERRIDES // Environment variable to disable any kind of crash dialog. if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) { mach_port_t self = mach_task_self(); diff --git a/contrib/llvm/lib/Support/Unix/TimeValue.inc b/contrib/llvm/lib/Support/Unix/TimeValue.inc deleted file mode 100644 index 042e0da..0000000 --- a/contrib/llvm/lib/Support/Unix/TimeValue.inc +++ /dev/null @@ -1,54 +0,0 @@ -//===- Unix/TimeValue.cpp - Unix TimeValue Implementation -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the Unix specific portion of the TimeValue class. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -//=== WARNING: Implementation here must contain only generic UNIX code that -//=== is guaranteed to work on *all* UNIX variants. -//===----------------------------------------------------------------------===// - -#include "Unix.h" - -namespace llvm { - using namespace sys; - -std::string TimeValue::str() const { - time_t OurTime = time_t(this->toEpochTime()); - struct tm Storage; - struct tm *LT = ::localtime_r(&OurTime, &Storage); - assert(LT); - char Buffer1[sizeof("YYYY-MM-DD HH:MM:SS")]; - strftime(Buffer1, sizeof(Buffer1), "%Y-%m-%d %H:%M:%S", LT); - char Buffer2[sizeof("YYYY-MM-DD HH:MM:SS.MMMUUUNNN")]; - snprintf(Buffer2, sizeof(Buffer2), "%s.%.9u", Buffer1, this->nanoseconds()); - return std::string(Buffer2); -} - -TimeValue TimeValue::now() { - struct timeval the_time; - timerclear(&the_time); - if (0 != ::gettimeofday(&the_time,nullptr)) { - // This is *really* unlikely to occur because the only gettimeofday - // errors concern the timezone parameter which we're passing in as 0. - // In the unlikely case it does happen, just return MinTime, no error - // message needed. - return MinTime(); - } - - return TimeValue( - static_cast<TimeValue::SecondsType>( the_time.tv_sec + - PosixZeroTimeSeconds ), - static_cast<TimeValue::NanoSecondsType>( the_time.tv_usec * - NANOSECONDS_PER_MICROSECOND ) ); -} - -} diff --git a/contrib/llvm/lib/Support/Unix/Unix.h b/contrib/llvm/lib/Support/Unix/Unix.h index 871e612..239a6d6 100644 --- a/contrib/llvm/lib/Support/Unix/Unix.h +++ b/contrib/llvm/lib/Support/Unix/Unix.h @@ -19,7 +19,8 @@ //=== is guaranteed to work on all UNIX variants. //===----------------------------------------------------------------------===// -#include "llvm/Config/config.h" // Get autoconf configuration settings +#include "llvm/Config/config.h" // Get autoconf configuration settings +#include "llvm/Support/Chrono.h" #include "llvm/Support/Errno.h" #include <algorithm> #include <assert.h> @@ -48,6 +49,10 @@ # include <dlfcn.h> #endif +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif + /// This function builds an error message into \p ErrMsg using the \p prefix /// string and the Unix error number given by \p errnum. If errnum is -1, the /// default then the value of errno is used. @@ -65,4 +70,37 @@ static inline bool MakeErrMsg( return true; } +namespace llvm { +namespace sys { + +/// Convert a struct timeval to a duration. Note that timeval can be used both +/// as a time point and a duration. Be sure to check what the input represents. +inline std::chrono::microseconds toDuration(const struct timeval &TV) { + return std::chrono::seconds(TV.tv_sec) + + std::chrono::microseconds(TV.tv_usec); +} + +/// Convert a time point to struct timespec. +inline struct timespec toTimeSpec(TimePoint<> TP) { + using namespace std::chrono; + + struct timespec RetVal; + RetVal.tv_sec = toTimeT(TP); + RetVal.tv_nsec = (TP.time_since_epoch() % seconds(1)).count(); + return RetVal; +} + +/// Convert a time point to struct timeval. +inline struct timeval toTimeVal(TimePoint<std::chrono::microseconds> TP) { + using namespace std::chrono; + + struct timeval RetVal; + RetVal.tv_sec = toTimeT(TP); + RetVal.tv_usec = (TP.time_since_epoch() % seconds(1)).count(); + return RetVal; +} + +} // namespace sys +} // namespace llvm + #endif diff --git a/contrib/llvm/lib/Support/Windows/Path.inc b/contrib/llvm/lib/Support/Windows/Path.inc index fab6aec..27b250b 100644 --- a/contrib/llvm/lib/Support/Windows/Path.inc +++ b/contrib/llvm/lib/Support/Windows/Path.inc @@ -164,24 +164,18 @@ ErrorOr<space_info> disk_space(const Twine &Path) { return SpaceInfo; } -TimeValue file_status::getLastAccessedTime() const { - ULARGE_INTEGER UI; - UI.LowPart = LastAccessedTimeLow; - UI.HighPart = LastAccessedTimeHigh; - - TimeValue Ret; - Ret.fromWin32Time(UI.QuadPart); - return Ret; +TimePoint<> file_status::getLastAccessedTime() const { + FILETIME Time; + Time.dwLowDateTime = LastAccessedTimeLow; + Time.dwHighDateTime = LastAccessedTimeHigh; + return toTimePoint(Time); } -TimeValue file_status::getLastModificationTime() const { - ULARGE_INTEGER UI; - UI.LowPart = LastWriteTimeLow; - UI.HighPart = LastWriteTimeHigh; - - TimeValue Ret; - Ret.fromWin32Time(UI.QuadPart); - return Ret; +TimePoint<> file_status::getLastModificationTime() const { + FILETIME Time; + Time.dwLowDateTime = LastWriteTimeLow; + Time.dwHighDateTime = LastWriteTimeHigh; + return toTimePoint(Time); } std::error_code current_path(SmallVectorImpl<char> &result) { @@ -238,6 +232,10 @@ std::error_code create_link(const Twine &to, const Twine &from) { return std::error_code(); } +std::error_code create_hard_link(const Twine &to, const Twine &from) { + return create_link(to, from); +} + std::error_code remove(const Twine &path, bool IgnoreNonExisting) { SmallVector<wchar_t, 128> path_utf16; @@ -513,12 +511,8 @@ std::error_code status(int FD, file_status &Result) { return getStatus(FileHandle, Result); } -std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { - ULARGE_INTEGER UI; - UI.QuadPart = Time.toWin32Time(); - FILETIME FT; - FT.dwLowDateTime = UI.LowPart; - FT.dwHighDateTime = UI.HighPart; +std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time) { + FILETIME FT = toFILETIME(Time); HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); if (!SetFileTime(FileHandle, NULL, &FT, &FT)) return mapWindowsError(::GetLastError()); diff --git a/contrib/llvm/lib/Support/Windows/Process.inc b/contrib/llvm/lib/Support/Windows/Process.inc index b012991..8d646b3 100644 --- a/contrib/llvm/lib/Support/Windows/Process.inc +++ b/contrib/llvm/lib/Support/Windows/Process.inc @@ -49,18 +49,6 @@ using namespace llvm; using namespace sys; -static TimeValue getTimeValueFromFILETIME(FILETIME Time) { - ULARGE_INTEGER TimeInteger; - TimeInteger.LowPart = Time.dwLowDateTime; - TimeInteger.HighPart = Time.dwHighDateTime; - - // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) - return TimeValue( - static_cast<TimeValue::SecondsType>(TimeInteger.QuadPart / 10000000), - static_cast<TimeValue::NanoSecondsType>( - (TimeInteger.QuadPart % 10000000) * 100)); -} - // This function retrieves the page size using GetNativeSystemInfo() and is // present solely so it can be called once to initialize the self_process member // below. @@ -93,17 +81,17 @@ Process::GetMallocUsage() return size; } -void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, - TimeValue &sys_time) { - elapsed = TimeValue::now(); +void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time, + std::chrono::nanoseconds &sys_time) { + elapsed = std::chrono::system_clock::now();; FILETIME ProcCreate, ProcExit, KernelTime, UserTime; if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, &UserTime) == 0) return; - user_time = getTimeValueFromFILETIME(UserTime); - sys_time = getTimeValueFromFILETIME(KernelTime); + user_time = toDuration(UserTime); + sys_time = toDuration(KernelTime); } // Some LLVM programs such as bugpoint produce core files as a normal part of diff --git a/contrib/llvm/lib/Support/Windows/Signals.inc b/contrib/llvm/lib/Support/Windows/Signals.inc index 1e2fa42..f739421 100644 --- a/contrib/llvm/lib/Support/Windows/Signals.inc +++ b/contrib/llvm/lib/Support/Windows/Signals.inc @@ -28,6 +28,7 @@ #ifdef __MINGW32__ #include <imagehlp.h> #else + #include <crtdbg.h> #include <dbghelp.h> #endif #include <psapi.h> @@ -266,7 +267,7 @@ static BOOL CALLBACK findModuleCallback(PCSTR ModuleName, continue; intptr_t Addr = (intptr_t)Data->StackTrace[I]; if (Beg <= Addr && Addr < End) { - Data->Modules[I] = Data->StrPool->save(ModuleName); + Data->Modules[I] = Data->StrPool->save(ModuleName).data(); Data->Offsets[I] = Addr - Beg; } } @@ -470,7 +471,7 @@ void sys::DontRemoveFileOnSignal(StringRef Filename) { RegisterHandler(); std::vector<std::string>::reverse_iterator I = - std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename); + find(reverse(*FilesToRemove), Filename); if (I != FilesToRemove->rend()) FilesToRemove->erase(I.base()-1); diff --git a/contrib/llvm/lib/Support/Windows/TimeValue.inc b/contrib/llvm/lib/Support/Windows/TimeValue.inc deleted file mode 100644 index b90b4f1..0000000 --- a/contrib/llvm/lib/Support/Windows/TimeValue.inc +++ /dev/null @@ -1,61 +0,0 @@ -//===- Win32/TimeValue.cpp - Win32 TimeValue Implementation -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides the Win32 implementation of the TimeValue class. -// -//===----------------------------------------------------------------------===// - -#include "WindowsSupport.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include <cctype> -#include <time.h> - -using namespace llvm; -using namespace llvm::sys; - -//===----------------------------------------------------------------------===// -//=== WARNING: Implementation here must contain only Win32 specific code. -//===----------------------------------------------------------------------===// - -TimeValue TimeValue::now() { - uint64_t ft; - GetSystemTimeAsFileTime(reinterpret_cast<FILETIME *>(&ft)); - - TimeValue t(0, 0); - t.fromWin32Time(ft); - return t; -} - -std::string TimeValue::str() const { - std::string S; - struct tm *LT; -#ifdef __MINGW32__ - // Old versions of mingw don't have _localtime64_s. Remove this once we drop support - // for them. - time_t OurTime = time_t(this->toEpochTime()); - LT = ::localtime(&OurTime); - assert(LT); -#else - struct tm Storage; - __time64_t OurTime = this->toEpochTime(); - int Error = ::_localtime64_s(&Storage, &OurTime); - assert(!Error); - (void)Error; - LT = &Storage; -#endif - - char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")]; - strftime(Buffer, sizeof(Buffer), "%Y-%m-%d %H:%M:%S", LT); - raw_string_ostream OS(S); - OS << format("%s.%.9u", static_cast<const char *>(Buffer), - this->nanoseconds()); - OS.flush(); - return S; -} diff --git a/contrib/llvm/lib/Support/Windows/WindowsSupport.h b/contrib/llvm/lib/Support/Windows/WindowsSupport.h index 18ecdf4e..c358b99 100644 --- a/contrib/llvm/lib/Support/Windows/WindowsSupport.h +++ b/contrib/llvm/lib/Support/Windows/WindowsSupport.h @@ -39,12 +39,13 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" // Get build system configuration settings +#include "llvm/Support/Chrono.h" #include "llvm/Support/Compiler.h" -#include <system_error> -#include <windows.h> -#include <wincrypt.h> #include <cassert> #include <string> +#include <system_error> +#include <windows.h> +#include <wincrypt.h> // Must be included after windows.h /// Determines if the program is running on Windows 8 or newer. This /// reimplements one of the helpers in the Windows 8.1 SDK, which are intended @@ -211,6 +212,39 @@ c_str(SmallVectorImpl<T> &str) { } namespace sys { + +inline std::chrono::nanoseconds toDuration(FILETIME Time) { + ULARGE_INTEGER TimeInteger; + TimeInteger.LowPart = Time.dwLowDateTime; + TimeInteger.HighPart = Time.dwHighDateTime; + + // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) + return std::chrono::nanoseconds(100 * TimeInteger.QuadPart); +} + +inline TimePoint<> toTimePoint(FILETIME Time) { + ULARGE_INTEGER TimeInteger; + TimeInteger.LowPart = Time.dwLowDateTime; + TimeInteger.HighPart = Time.dwHighDateTime; + + // Adjust for different epoch + TimeInteger.QuadPart -= 11644473600ll * 10000000; + + // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) + return TimePoint<>(std::chrono::nanoseconds(100 * TimeInteger.QuadPart)); +} + +inline FILETIME toFILETIME(TimePoint<> TP) { + ULARGE_INTEGER TimeInteger; + TimeInteger.QuadPart = TP.time_since_epoch().count() / 100; + TimeInteger.QuadPart += 11644473600ll * 10000000; + + FILETIME Time; + Time.dwLowDateTime = TimeInteger.LowPart; + Time.dwHighDateTime = TimeInteger.HighPart; + return Time; +} + namespace path { std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16); diff --git a/contrib/llvm/lib/Support/YAMLParser.cpp b/contrib/llvm/lib/Support/YAMLParser.cpp index 620841c..c17a6f6 100644 --- a/contrib/llvm/lib/Support/YAMLParser.cpp +++ b/contrib/llvm/lib/Support/YAMLParser.cpp @@ -12,12 +12,12 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/YAMLParser.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/AllocatorList.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" @@ -108,7 +108,7 @@ void SequenceNode::anchor() {} void AliasNode::anchor() {} /// Token - A single YAML token. -struct Token : ilist_node<Token> { +struct Token { enum TokenKind { TK_Error, // Uninitialized token. TK_StreamStart, @@ -147,40 +147,7 @@ struct Token : ilist_node<Token> { } } -namespace llvm { -template<> -struct ilist_sentinel_traits<Token> { - Token *createSentinel() const { - return &Sentinel; - } - static void destroySentinel(Token*) {} - - Token *provideInitialHead() const { return createSentinel(); } - Token *ensureHead(Token*) const { return createSentinel(); } - static void noteHead(Token*, Token*) {} - -private: - mutable Token Sentinel; -}; - -template<> -struct ilist_node_traits<Token> { - Token *createNode(const Token &V) { - return new (Alloc.Allocate<Token>()) Token(V); - } - static void deleteNode(Token *V) { V->~Token(); } - - void addNodeToList(Token *) {} - void removeNodeFromList(Token *) {} - void transferNodesFromList(ilist_node_traits & /*SrcTraits*/, - ilist_iterator<Token> /*first*/, - ilist_iterator<Token> /*last*/) {} - - BumpPtrAllocator Alloc; -}; -} - -typedef ilist<Token> TokenQueueT; +typedef llvm::BumpPtrList<Token> TokenQueueT; namespace { /// @brief This struct is used to track simple keys. @@ -265,8 +232,10 @@ namespace yaml { /// @brief Scans YAML tokens from a MemoryBuffer. class Scanner { public: - Scanner(StringRef Input, SourceMgr &SM, bool ShowColors = true); - Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors = true); + Scanner(StringRef Input, SourceMgr &SM, bool ShowColors = true, + std::error_code *EC = nullptr); + Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors = true, + std::error_code *EC = nullptr); /// @brief Parse the next token and return it without popping it. Token &peekNext(); @@ -283,6 +252,10 @@ public: if (Current >= End) Current = End - 1; + // propagate the error if possible + if (EC) + *EC = make_error_code(std::errc::invalid_argument); + // Don't print out more errors after the first one we encounter. The rest // are just the result of the first, and have no meaning. if (!Failed) @@ -393,10 +366,7 @@ private: /// @brief Scan ns-uri-char[39]s starting at Cur. /// /// This updates Cur and Column while scanning. - /// - /// @returns A StringRef starting at Cur which covers the longest contiguous - /// sequence of ns-uri-char. - StringRef scan_ns_uri_char(); + void scan_ns_uri_char(); /// @brief Consume a minimal well-formed code unit subsequence starting at /// \a Cur. Return false if it is not the same Unicode scalar value as @@ -564,6 +534,8 @@ private: /// @brief Potential simple keys. SmallVector<SimpleKey, 4> SimpleKeys; + + std::error_code *EC; }; } // end namespace yaml @@ -758,13 +730,15 @@ std::string yaml::escape(StringRef Input) { return EscapedInput; } -Scanner::Scanner(StringRef Input, SourceMgr &sm, bool ShowColors) - : SM(sm), ShowColors(ShowColors) { +Scanner::Scanner(StringRef Input, SourceMgr &sm, bool ShowColors, + std::error_code *EC) + : SM(sm), ShowColors(ShowColors), EC(EC) { init(MemoryBufferRef(Input, "YAML")); } -Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors) - : SM(SM_), ShowColors(ShowColors) { +Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors, + std::error_code *EC) + : SM(SM_), ShowColors(ShowColors), EC(EC) { init(Buffer); } @@ -802,8 +776,7 @@ Token &Scanner::peekNext() { removeStaleSimpleKeyCandidates(); SimpleKey SK; SK.Tok = TokenQueue.begin(); - if (std::find(SimpleKeys.begin(), SimpleKeys.end(), SK) - == SimpleKeys.end()) + if (!is_contained(SimpleKeys, SK)) break; else NeedMore = true; @@ -819,9 +792,8 @@ Token Scanner::getNext() { // There cannot be any referenced Token's if the TokenQueue is empty. So do a // quick deallocation of them all. - if (TokenQueue.empty()) { - TokenQueue.Alloc.Reset(); - } + if (TokenQueue.empty()) + TokenQueue.resetAlloc(); return Ret; } @@ -918,8 +890,7 @@ static bool is_ns_word_char(const char C) { || (C >= 'A' && C <= 'Z'); } -StringRef Scanner::scan_ns_uri_char() { - StringRef::iterator Start = Current; +void Scanner::scan_ns_uri_char() { while (true) { if (Current == End) break; @@ -935,7 +906,6 @@ StringRef Scanner::scan_ns_uri_char() { } else break; } - return StringRef(Start, Current - Start); } bool Scanner::consume(uint32_t Expected) { @@ -1766,11 +1736,13 @@ bool Scanner::fetchMoreTokens() { return false; } -Stream::Stream(StringRef Input, SourceMgr &SM, bool ShowColors) - : scanner(new Scanner(Input, SM, ShowColors)), CurrentDoc() {} +Stream::Stream(StringRef Input, SourceMgr &SM, bool ShowColors, + std::error_code *EC) + : scanner(new Scanner(Input, SM, ShowColors, EC)), CurrentDoc() {} -Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM, bool ShowColors) - : scanner(new Scanner(InputBuffer, SM, ShowColors)), CurrentDoc() {} +Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM, bool ShowColors, + std::error_code *EC) + : scanner(new Scanner(InputBuffer, SM, ShowColors, EC)), CurrentDoc() {} Stream::~Stream() {} diff --git a/contrib/llvm/lib/Support/YAMLTraits.cpp b/contrib/llvm/lib/Support/YAMLTraits.cpp index 75fac20..9849b3a 100644 --- a/contrib/llvm/lib/Support/YAMLTraits.cpp +++ b/contrib/llvm/lib/Support/YAMLTraits.cpp @@ -44,13 +44,10 @@ void IO::setContext(void *Context) { // Input //===----------------------------------------------------------------------===// -Input::Input(StringRef InputContent, - void *Ctxt, - SourceMgr::DiagHandlerTy DiagHandler, - void *DiagHandlerCtxt) - : IO(Ctxt), - Strm(new Stream(InputContent, SrcMgr)), - CurrentNode(nullptr) { +Input::Input(StringRef InputContent, void *Ctxt, + SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt) + : IO(Ctxt), Strm(new Stream(InputContent, SrcMgr, false, &EC)), + CurrentNode(nullptr) { if (DiagHandler) SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt); DocIterator = Strm->begin(); @@ -121,6 +118,18 @@ void Input::beginMapping() { } } +std::vector<StringRef> Input::keys() { + MapHNode *MN = dyn_cast<MapHNode>(CurrentNode); + std::vector<StringRef> Ret; + if (!MN) { + setError(CurrentNode, "not a mapping"); + return Ret; + } + for (auto &P : MN->Mapping) + Ret.push_back(P.first()); + return Ret; +} + bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault, void *&SaveInfo) { UseDefault = false; @@ -166,7 +175,7 @@ void Input::endMapping() { if (!MN) return; for (const auto &NN : MN->Mapping) { - if (!MN->isValidKey(NN.first())) { + if (!is_contained(MN->ValidKeys, NN.first())) { setError(NN.second.get(), Twine("unknown key '") + NN.first() + "'"); break; } @@ -376,14 +385,6 @@ std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) { } } -bool Input::MapHNode::isValidKey(StringRef Key) { - for (const char *K : ValidKeys) { - if (Key.equals(K)) - return true; - } - return false; -} - void Input::setError(const Twine &Message) { this->setError(CurrentNode, Message); } @@ -454,6 +455,10 @@ void Output::endMapping() { StateStack.pop_back(); } +std::vector<StringRef> Output::keys() { + report_fatal_error("invalid call"); +} + bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault, bool &UseDefault, void *&) { UseDefault = false; diff --git a/contrib/llvm/lib/Support/raw_ostream.cpp b/contrib/llvm/lib/Support/raw_ostream.cpp index 275fe1d..d073802 100644 --- a/contrib/llvm/lib/Support/raw_ostream.cpp +++ b/contrib/llvm/lib/Support/raw_ostream.cpp @@ -20,11 +20,16 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/NativeFormatting.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" +#include <algorithm> #include <cctype> #include <cerrno> +#include <cstdio> +#include <iterator> #include <sys/stat.h> #include <system_error> @@ -110,73 +115,28 @@ void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size, } raw_ostream &raw_ostream::operator<<(unsigned long N) { - // Zero is a special case. - if (N == 0) - return *this << '0'; - - char NumberBuffer[20]; - char *EndPtr = NumberBuffer+sizeof(NumberBuffer); - char *CurPtr = EndPtr; - - while (N) { - *--CurPtr = '0' + char(N % 10); - N /= 10; - } - return write(CurPtr, EndPtr-CurPtr); + write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer); + return *this; } raw_ostream &raw_ostream::operator<<(long N) { - if (N < 0) { - *this << '-'; - // Avoid undefined behavior on LONG_MIN with a cast. - N = -(unsigned long)N; - } - - return this->operator<<(static_cast<unsigned long>(N)); + write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer); + return *this; } raw_ostream &raw_ostream::operator<<(unsigned long long N) { - // Output using 32-bit div/mod when possible. - if (N == static_cast<unsigned long>(N)) - return this->operator<<(static_cast<unsigned long>(N)); - - char NumberBuffer[20]; - char *EndPtr = std::end(NumberBuffer); - char *CurPtr = EndPtr; - - while (N) { - *--CurPtr = '0' + char(N % 10); - N /= 10; - } - return write(CurPtr, EndPtr-CurPtr); + write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer); + return *this; } raw_ostream &raw_ostream::operator<<(long long N) { - if (N < 0) { - *this << '-'; - // Avoid undefined behavior on INT64_MIN with a cast. - N = -(unsigned long long)N; - } - - return this->operator<<(static_cast<unsigned long long>(N)); + write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer); + return *this; } raw_ostream &raw_ostream::write_hex(unsigned long long N) { - // Zero is a special case. - if (N == 0) - return *this << '0'; - - char NumberBuffer[16]; - char *EndPtr = std::end(NumberBuffer); - char *CurPtr = EndPtr; - - while (N) { - unsigned char x = static_cast<unsigned char>(N) % 16; - *--CurPtr = hexdigit(x, /*LowerCase*/true); - N /= 16; - } - - return write(CurPtr, EndPtr-CurPtr); + llvm::write_hex(*this, N, HexPrintStyle::Lower); + return *this; } raw_ostream &raw_ostream::write_escaped(StringRef Str, @@ -220,54 +180,15 @@ raw_ostream &raw_ostream::write_escaped(StringRef Str, } raw_ostream &raw_ostream::operator<<(const void *P) { - *this << '0' << 'x'; - - return write_hex((uintptr_t) P); + llvm::write_hex(*this, (uintptr_t)P, HexPrintStyle::PrefixLower); + return *this; } raw_ostream &raw_ostream::operator<<(double N) { -#ifdef _WIN32 - // On MSVCRT and compatible, output of %e is incompatible to Posix - // by default. Number of exponent digits should be at least 2. "%+03d" - // FIXME: Implement our formatter to here or Support/Format.h! -#if defined(__MINGW32__) - // FIXME: It should be generic to C++11. - if (N == 0.0 && std::signbit(N)) - return *this << "-0.000000e+00"; -#else - int fpcl = _fpclass(N); - - // negative zero - if (fpcl == _FPCLASS_NZ) - return *this << "-0.000000e+00"; -#endif - - char buf[16]; - unsigned len; - len = format("%e", N).snprint(buf, sizeof(buf)); - if (len <= sizeof(buf) - 2) { - if (len >= 5 && buf[len - 5] == 'e' && buf[len - 3] == '0') { - int cs = buf[len - 4]; - if (cs == '+' || cs == '-') { - int c1 = buf[len - 2]; - int c0 = buf[len - 1]; - if (isdigit(static_cast<unsigned char>(c1)) && - isdigit(static_cast<unsigned char>(c0))) { - // Trim leading '0': "...e+012" -> "...e+12\0" - buf[len - 3] = c1; - buf[len - 2] = c0; - buf[--len] = 0; - } - } - } - return this->operator<<(buf); - } -#endif - return this->operator<<(format("%e", N)); + llvm::write_double(*this, N, FloatStyle::Exponent); + return *this; } - - void raw_ostream::flush_nonempty() { assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty."); size_t Length = OutBufCur - OutBufStart; @@ -344,10 +265,10 @@ void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) { // Handle short strings specially, memcpy isn't very good at very short // strings. switch (Size) { - case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH - case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH - case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH - case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH + case 4: OutBufCur[3] = Ptr[3]; LLVM_FALLTHROUGH; + case 3: OutBufCur[2] = Ptr[2]; LLVM_FALLTHROUGH; + case 2: OutBufCur[1] = Ptr[1]; LLVM_FALLTHROUGH; + case 1: OutBufCur[0] = Ptr[0]; LLVM_FALLTHROUGH; case 0: break; default: memcpy(OutBufCur, Ptr, Size); @@ -382,7 +303,7 @@ raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) { // space. Iterate until we win. SmallVector<char, 128> V; - while (1) { + while (true) { V.resize(NextBufferSize); // Try formatting into the SmallVector. @@ -398,6 +319,12 @@ raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) { } } +raw_ostream &raw_ostream::operator<<(const formatv_object_base &Obj) { + SmallString<128> S; + Obj.format(*this); + return *this; +} + raw_ostream &raw_ostream::operator<<(const FormattedString &FS) { unsigned Len = FS.Str.size(); int PadAmount = FS.Width - Len; @@ -411,51 +338,99 @@ raw_ostream &raw_ostream::operator<<(const FormattedString &FS) { raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) { if (FN.Hex) { - unsigned Nibbles = (64 - countLeadingZeros(FN.HexValue)+3)/4; - unsigned PrefixChars = FN.HexPrefix ? 2 : 0; - unsigned Width = std::max(FN.Width, Nibbles + PrefixChars); - - char NumberBuffer[20] = "0x0000000000000000"; - if (!FN.HexPrefix) - NumberBuffer[1] = '0'; - char *EndPtr = NumberBuffer+Width; - char *CurPtr = EndPtr; - unsigned long long N = FN.HexValue; - while (N) { - unsigned char x = static_cast<unsigned char>(N) % 16; - *--CurPtr = hexdigit(x, !FN.Upper); - N /= 16; + HexPrintStyle Style; + if (FN.Upper && FN.HexPrefix) + Style = HexPrintStyle::PrefixUpper; + else if (FN.Upper && !FN.HexPrefix) + Style = HexPrintStyle::Upper; + else if (!FN.Upper && FN.HexPrefix) + Style = HexPrintStyle::PrefixLower; + else + Style = HexPrintStyle::Lower; + llvm::write_hex(*this, FN.HexValue, Style, FN.Width); + } else { + llvm::SmallString<16> Buffer; + llvm::raw_svector_ostream Stream(Buffer); + llvm::write_integer(Stream, FN.DecValue, 0, IntegerStyle::Integer); + if (Buffer.size() < FN.Width) + indent(FN.Width - Buffer.size()); + (*this) << Buffer; + } + return *this; +} + +raw_ostream &raw_ostream::operator<<(const FormattedBytes &FB) { + if (FB.Bytes.empty()) + return *this; + + size_t LineIndex = 0; + auto Bytes = FB.Bytes; + const size_t Size = Bytes.size(); + HexPrintStyle HPS = FB.Upper ? HexPrintStyle::Upper : HexPrintStyle::Lower; + uint64_t OffsetWidth = 0; + if (FB.FirstByteOffset.hasValue()) { + // Figure out how many nibbles are needed to print the largest offset + // represented by this data set, so that we can align the offset field + // to the right width. + size_t Lines = Size / FB.NumPerLine; + uint64_t MaxOffset = *FB.FirstByteOffset + Lines * FB.NumPerLine; + unsigned Power = 0; + if (MaxOffset > 0) + Power = llvm::Log2_64_Ceil(MaxOffset); + OffsetWidth = std::max<uint64_t>(4, llvm::alignTo(Power, 4) / 4); + } + + // The width of a block of data including all spaces for group separators. + unsigned NumByteGroups = + alignTo(FB.NumPerLine, FB.ByteGroupSize) / FB.ByteGroupSize; + unsigned BlockCharWidth = FB.NumPerLine * 2 + NumByteGroups - 1; + + while (!Bytes.empty()) { + indent(FB.IndentLevel); + + if (FB.FirstByteOffset.hasValue()) { + uint64_t Offset = FB.FirstByteOffset.getValue(); + llvm::write_hex(*this, Offset + LineIndex, HPS, OffsetWidth); + *this << ": "; } - return write(NumberBuffer, Width); - } else { - // Zero is a special case. - if (FN.DecValue == 0) { - this->indent(FN.Width-1); - return *this << '0'; + auto Line = Bytes.take_front(FB.NumPerLine); + + size_t CharsPrinted = 0; + // Print the hex bytes for this line in groups + for (size_t I = 0; I < Line.size(); ++I, CharsPrinted += 2) { + if (I && (I % FB.ByteGroupSize) == 0) { + ++CharsPrinted; + *this << " "; + } + llvm::write_hex(*this, Line[I], HPS, 2); } - char NumberBuffer[32]; - char *EndPtr = NumberBuffer+sizeof(NumberBuffer); - char *CurPtr = EndPtr; - bool Neg = (FN.DecValue < 0); - uint64_t N = Neg ? -static_cast<uint64_t>(FN.DecValue) : FN.DecValue; - while (N) { - *--CurPtr = '0' + char(N % 10); - N /= 10; + + if (FB.ASCII) { + // Print any spaces needed for any bytes that we didn't print on this + // line so that the ASCII bytes are correctly aligned. + assert(BlockCharWidth >= CharsPrinted); + indent(BlockCharWidth - CharsPrinted + 2); + *this << "|"; + + // Print the ASCII char values for each byte on this line + for (uint8_t Byte : Line) { + if (isprint(Byte)) + *this << static_cast<char>(Byte); + else + *this << '.'; + } + *this << '|'; } - int Len = EndPtr - CurPtr; - int Pad = FN.Width - Len; - if (Neg) - --Pad; - if (Pad > 0) - this->indent(Pad); - if (Neg) - *this << '-'; - return write(CurPtr, Len); + + Bytes = Bytes.drop_front(Line.size()); + LineIndex += Line.size(); + if (LineIndex < Size) + *this << '\n'; } + return *this; } - /// indent - Insert 'NumSpaces' spaces. raw_ostream &raw_ostream::indent(unsigned NumSpaces) { static const char Spaces[] = " " @@ -475,7 +450,6 @@ raw_ostream &raw_ostream::indent(unsigned NumSpaces) { return *this; } - //===----------------------------------------------------------------------===// // Formatted Output //===----------------------------------------------------------------------===// @@ -563,7 +537,6 @@ raw_fd_ostream::~raw_fd_ostream() { report_fatal_error("IO failure on output stream.", /*GenCrashDiag=*/false); } - void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { assert(FD >= 0 && "File already closed."); pos += Size; @@ -625,7 +598,13 @@ void raw_fd_ostream::close() { uint64_t raw_fd_ostream::seek(uint64_t off) { assert(SupportsSeeking && "Stream does not support seeking!"); flush(); +#ifdef LLVM_ON_WIN32 + pos = ::_lseeki64(FD, off, SEEK_SET); +#elif defined(HAVE_LSEEK64) + pos = ::lseek64(FD, off, SEEK_SET); +#else pos = ::lseek(FD, off, SEEK_SET); +#endif if (pos == (uint64_t)-1) error_detected(); return pos; @@ -740,7 +719,6 @@ raw_ostream &llvm::nulls() { return S; } - //===----------------------------------------------------------------------===// // raw_string_ostream //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Support/xxhash.cpp b/contrib/llvm/lib/Support/xxhash.cpp new file mode 100644 index 0000000..a7d990b --- /dev/null +++ b/contrib/llvm/lib/Support/xxhash.cpp @@ -0,0 +1,134 @@ +/* +* xxHash - Fast Hash algorithm +* Copyright (C) 2012-2016, Yann Collet +* +* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* You can contact the author at : +* - xxHash homepage: http://www.xxhash.com +* - xxHash source repository : https://github.com/Cyan4973/xxHash +*/ + +/* based on revision d2df04efcbef7d7f6886d345861e5dfda4edacc1 Removed + * everything but a simple interface for computing XXh64. */ + +#include "llvm/Support/xxhash.h" +#include "llvm/Support/Endian.h" + +#include <stdlib.h> +#include <string.h> + +using namespace llvm; +using namespace support; + +static uint64_t rotl64(uint64_t X, size_t R) { + return (X << R) | (X >> (64 - R)); +} + +static const uint64_t PRIME64_1 = 11400714785074694791ULL; +static const uint64_t PRIME64_2 = 14029467366897019727ULL; +static const uint64_t PRIME64_3 = 1609587929392839161ULL; +static const uint64_t PRIME64_4 = 9650029242287828579ULL; +static const uint64_t PRIME64_5 = 2870177450012600261ULL; + +static uint64_t round(uint64_t Acc, uint64_t Input) { + Acc += Input * PRIME64_2; + Acc = rotl64(Acc, 31); + Acc *= PRIME64_1; + return Acc; +} + +static uint64_t mergeRound(uint64_t Acc, uint64_t Val) { + Val = round(0, Val); + Acc ^= Val; + Acc = Acc * PRIME64_1 + PRIME64_4; + return Acc; +} + +uint64_t llvm::xxHash64(StringRef Data) { + size_t Len = Data.size(); + uint64_t Seed = 0; + const char *P = Data.data(); + const char *const BEnd = P + Len; + uint64_t H64; + + if (Len >= 32) { + const char *const Limit = BEnd - 32; + uint64_t V1 = Seed + PRIME64_1 + PRIME64_2; + uint64_t V2 = Seed + PRIME64_2; + uint64_t V3 = Seed + 0; + uint64_t V4 = Seed - PRIME64_1; + + do { + V1 = round(V1, endian::read64le(P)); + P += 8; + V2 = round(V2, endian::read64le(P)); + P += 8; + V3 = round(V3, endian::read64le(P)); + P += 8; + V4 = round(V4, endian::read64le(P)); + P += 8; + } while (P <= Limit); + + H64 = rotl64(V1, 1) + rotl64(V2, 7) + rotl64(V3, 12) + rotl64(V4, 18); + H64 = mergeRound(H64, V1); + H64 = mergeRound(H64, V2); + H64 = mergeRound(H64, V3); + H64 = mergeRound(H64, V4); + + } else { + H64 = Seed + PRIME64_5; + } + + H64 += (uint64_t)Len; + + while (P + 8 <= BEnd) { + uint64_t const K1 = round(0, endian::read64le(P)); + H64 ^= K1; + H64 = rotl64(H64, 27) * PRIME64_1 + PRIME64_4; + P += 8; + } + + if (P + 4 <= BEnd) { + H64 ^= (uint64_t)(endian::read32le(P)) * PRIME64_1; + H64 = rotl64(H64, 23) * PRIME64_2 + PRIME64_3; + P += 4; + } + + while (P < BEnd) { + H64 ^= (*P) * PRIME64_5; + H64 = rotl64(H64, 11) * PRIME64_1; + P++; + } + + H64 ^= H64 >> 33; + H64 *= PRIME64_2; + H64 ^= H64 >> 29; + H64 *= PRIME64_3; + H64 ^= H64 >> 32; + + return H64; +} |