diff options
author | dim <dim@FreeBSD.org> | 2017-04-02 17:24:58 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2017-04-02 17:24:58 +0000 |
commit | 60b571e49a90d38697b3aca23020d9da42fc7d7f (patch) | |
tree | 99351324c24d6cb146b6285b6caffa4d26fce188 /contrib/llvm/lib/Support | |
parent | bea1b22c7a9bce1dfdd73e6e5b65bc4752215180 (diff) | |
download | FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.zip FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.tar.gz |
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release:
MFC r309142 (by emaste):
Add WITH_LLD_AS_LD build knob
If set it installs LLD as /usr/bin/ld. LLD (as of version 3.9) is not
capable of linking the world and kernel, but can self-host and link many
substantial applications. GNU ld continues to be used for the world and
kernel build, regardless of how this knob is set.
It is on by default for arm64, and off for all other CPU architectures.
Sponsored by: The FreeBSD Foundation
MFC r310840:
Reapply 310775, now it also builds correctly if lldb is disabled:
Move llvm-objdump from CLANG_EXTRAS to installed by default
We currently install three tools from binutils 2.17.50: as, ld, and
objdump. Work is underway to migrate to a permissively-licensed
tool-chain, with one goal being the retirement of binutils 2.17.50.
LLVM's llvm-objdump is intended to be compatible with GNU objdump
although it is currently missing some options and may have formatting
differences. Enable it by default for testing and further investigation.
It may later be changed to install as /usr/bin/objdump, it becomes a
fully viable replacement.
Reviewed by: emaste
Differential Revision: https://reviews.freebsd.org/D8879
MFC r312855 (by emaste):
Rename LLD_AS_LD to LLD_IS_LD, for consistency with CLANG_IS_CC
Reported by: Dan McGregor <dan.mcgregor usask.ca>
MFC r313559 | glebius | 2017-02-10 18:34:48 +0100 (Fri, 10 Feb 2017) | 5 lines
Don't check struct rtentry on FreeBSD, it is an internal kernel structure.
On other systems it may be API structure for SIOCADDRT/SIOCDELRT.
Reviewed by: emaste, dim
MFC r314152 (by jkim):
Remove an assembler flag, which is redundant since r309124. The upstream
took care of it by introducing a macro NO_EXEC_STACK_DIRECTIVE.
http://llvm.org/viewvc/llvm-project?rev=273500&view=rev
Reviewed by: dim
MFC r314564:
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
4.0.0 (branches/release_40 296509). The release will follow soon.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Also note that as of 4.0.0, lld should be able to link the base system
on amd64 and aarch64. See the WITH_LLD_IS_LLD setting in src.conf(5).
Though please be aware that this is work in progress.
Release notes for llvm, clang and lld will be available here:
<http://releases.llvm.org/4.0.0/docs/ReleaseNotes.html>
<http://releases.llvm.org/4.0.0/tools/clang/docs/ReleaseNotes.html>
<http://releases.llvm.org/4.0.0/tools/lld/docs/ReleaseNotes.html>
Thanks to Ed Maste, Jan Beich, Antoine Brodin and Eric Fiselier for
their help.
Relnotes: yes
Exp-run: antoine
PR: 215969, 216008
MFC r314708:
For now, revert r287232 from upstream llvm trunk (by Daniil Fukalov):
[SCEV] limit recursion depth of CompareSCEVComplexity
Summary:
CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled
loop) and runs almost infinite time.
Added cache of "equal" SCEV pairs to earlier cutoff of further
estimation. Recursion depth limit was also introduced as a parameter.
Reviewers: sanjoy
Subscribers: mzolotukhin, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D26389
This commit is the cause of excessive compile times on skein_block.c
(and possibly other files) during kernel builds on amd64.
We never saw the problematic behavior described in this upstream commit,
so for now it is better to revert it. An upstream bug has been filed
here: https://bugs.llvm.org/show_bug.cgi?id=32142
Reported by: mjg
MFC r314795:
Reapply r287232 from upstream llvm trunk (by Daniil Fukalov):
[SCEV] limit recursion depth of CompareSCEVComplexity
Summary:
CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled
loop) and runs almost infinite time.
Added cache of "equal" SCEV pairs to earlier cutoff of further
estimation. Recursion depth limit was also introduced as a parameter.
Reviewers: sanjoy
Subscribers: mzolotukhin, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D26389
Pull in r296992 from upstream llvm trunk (by Sanjoy Das):
[SCEV] Decrease the recursion threshold for CompareValueComplexity
Fixes PR32142.
r287232 accidentally increased the recursion threshold for
CompareValueComplexity from 2 to 32. This change reverses that
change by introducing a separate flag for CompareValueComplexity's
threshold.
The latter revision fixes the excessive compile times for skein_block.c.
MFC r314907 | mmel | 2017-03-08 12:40:27 +0100 (Wed, 08 Mar 2017) | 7 lines
Unbreak ARMv6 world.
The new compiler_rt library imported with clang 4.0.0 have several fatal
issues (non-functional __udivsi3 for example) with ARM specific instrict
functions. As temporary workaround, until upstream solve these problems,
disable all thumb[1][2] related feature.
MFC r315016:
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release.
We were already very close to the last release candidate, so this is a
pretty minor update.
Relnotes: yes
MFC r316005:
Revert r314907, and pull in r298713 from upstream compiler-rt trunk (by
Weiming Zhao):
builtins: Select correct code fragments when compiling for Thumb1/Thum2/ARM ISA.
Summary:
Value of __ARM_ARCH_ISA_THUMB isn't based on the actual compilation
mode (-mthumb, -marm), it reflect's capability of given CPU.
Due to this:
- use __tbumb__ and __thumb2__ insteand of __ARM_ARCH_ISA_THUMB
- use '.thumb' directive consistently in all affected files
- decorate all thumb functions using
DEFINE_COMPILERRT_THUMB_FUNCTION()
---------
Note: This patch doesn't fix broken Thumb1 variant of __udivsi3 !
Reviewers: weimingz, rengolin, compnerd
Subscribers: aemerson, dim
Differential Revision: https://reviews.llvm.org/D30938
Discussed with: mmel
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; +} |