diff options
author | Stephen Hines <srhines@google.com> | 2012-03-05 14:40:54 -0800 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2012-03-05 14:40:54 -0800 |
commit | c02a5c5e8d9c1fd2a20ad4aed40f328564e95b40 (patch) | |
tree | 9a892d465bc8a229322b6c296c346250a95ecd6c /lib/Support | |
parent | 2987cbcdaef9e14f635b6f9ac32c58ff26a2fc0f (diff) | |
parent | c3384c93c0e4c50da4ad093f08997507f9281c75 (diff) | |
download | external_llvm-c02a5c5e8d9c1fd2a20ad4aed40f328564e95b40.zip external_llvm-c02a5c5e8d9c1fd2a20ad4aed40f328564e95b40.tar.gz external_llvm-c02a5c5e8d9c1fd2a20ad4aed40f328564e95b40.tar.bz2 |
Merge branch 'upstream' into merge-20120305
Conflicts:
lib/Support/Atomic.cpp
Change-Id: I563b3bc2a82942ccbae5bed42e53b9149a8bf3a0
Diffstat (limited to 'lib/Support')
34 files changed, 1487 insertions, 790 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 70e7afd..409d4fb 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -14,8 +14,9 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include <limits.h> @@ -1150,9 +1151,6 @@ APFloat::roundAwayFromZero(roundingMode rounding_mode, assert(lost_fraction != lfExactlyZero); switch (rounding_mode) { - default: - llvm_unreachable(0); - case rmNearestTiesToAway: return lost_fraction == lfExactlyHalf || lost_fraction == lfMoreThanHalf; @@ -1175,6 +1173,7 @@ APFloat::roundAwayFromZero(roundingMode rounding_mode, case rmTowardNegative: return sign == true; } + llvm_unreachable("Invalid rounding mode found"); } APFloat::opStatus @@ -2683,21 +2682,19 @@ APFloat::convertNormalToHexString(char *dst, unsigned int hexDigits, return writeSignedDecimal (dst, exponent); } -// For good performance it is desirable for different APFloats -// to produce different integers. -uint32_t -APFloat::getHashValue() const -{ - if (category==fcZero) return sign<<8 | semantics->precision ; - else if (category==fcInfinity) return sign<<9 | semantics->precision; - else if (category==fcNaN) return 1<<10 | semantics->precision; - else { - uint32_t hash = sign<<11 | semantics->precision | exponent<<12; - const integerPart* p = significandParts(); - for (int i=partCount(); i>0; i--, p++) - hash ^= ((uint32_t)*p) ^ (uint32_t)((*p)>>32); - return hash; - } +hash_code llvm::hash_value(const APFloat &Arg) { + if (Arg.category != APFloat::fcNormal) + return hash_combine((uint8_t)Arg.category, + // NaN has no sign, fix it at zero. + Arg.isNaN() ? (uint8_t)0 : (uint8_t)Arg.sign, + Arg.semantics->precision); + + // Normal floats need their exponent and significand hashed. + return hash_combine((uint8_t)Arg.category, (uint8_t)Arg.sign, + Arg.semantics->precision, Arg.exponent, + hash_combine_range( + Arg.significandParts(), + Arg.significandParts() + Arg.partCount())); } // Conversion from APFloat to/from host float/double. It may eventually be @@ -3342,7 +3339,7 @@ namespace { // Rounding down is just a truncation, except we also want to drop // trailing zeros from the new result. if (buffer[FirstSignificant - 1] < '5') { - while (buffer[FirstSignificant] == '0') + while (FirstSignificant < N && buffer[FirstSignificant] == '0') FirstSignificant++; exp += FirstSignificant; diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index 506225f..031bbb8 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -14,9 +14,10 @@ #define DEBUG_TYPE "apint" #include "llvm/ADT/APInt.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -675,93 +676,11 @@ unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) { } } -// From http://www.burtleburtle.net, byBob Jenkins. -// When targeting x86, both GCC and LLVM seem to recognize this as a -// rotate instruction. -#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) - -// From http://www.burtleburtle.net, by Bob Jenkins. -#define mix(a,b,c) \ - { \ - a -= c; a ^= rot(c, 4); c += b; \ - b -= a; b ^= rot(a, 6); a += c; \ - c -= b; c ^= rot(b, 8); b += a; \ - a -= c; a ^= rot(c,16); c += b; \ - b -= a; b ^= rot(a,19); a += c; \ - c -= b; c ^= rot(b, 4); b += a; \ - } - -// From http://www.burtleburtle.net, by Bob Jenkins. -#define final(a,b,c) \ - { \ - c ^= b; c -= rot(b,14); \ - a ^= c; a -= rot(c,11); \ - b ^= a; b -= rot(a,25); \ - c ^= b; c -= rot(b,16); \ - a ^= c; a -= rot(c,4); \ - b ^= a; b -= rot(a,14); \ - c ^= b; c -= rot(b,24); \ - } - -// hashword() was adapted from http://www.burtleburtle.net, by Bob -// Jenkins. k is a pointer to an array of uint32_t values; length is -// the length of the key, in 32-bit chunks. This version only handles -// keys that are a multiple of 32 bits in size. -static inline uint32_t hashword(const uint64_t *k64, size_t length) -{ - const uint32_t *k = reinterpret_cast<const uint32_t *>(k64); - uint32_t a,b,c; - - /* Set up the internal state */ - a = b = c = 0xdeadbeef + (((uint32_t)length)<<2); - - /*------------------------------------------------- handle most of the key */ - while (length > 3) { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 3; - k += 3; - } - - /*------------------------------------------- handle the last 3 uint32_t's */ - switch (length) { /* all the case statements fall through */ - case 3 : c+=k[2]; - case 2 : b+=k[1]; - case 1 : a+=k[0]; - final(a,b,c); - case 0: /* case 0: nothing left to add */ - break; - } - /*------------------------------------------------------ report the result */ - return c; -} +hash_code llvm::hash_value(const APInt &Arg) { + if (Arg.isSingleWord()) + return hash_combine(Arg.VAL); -// hashword8() was adapted from http://www.burtleburtle.net, by Bob -// Jenkins. This computes a 32-bit hash from one 64-bit word. When -// targeting x86 (32 or 64 bit), both LLVM and GCC compile this -// function into about 35 instructions when inlined. -static inline uint32_t hashword8(const uint64_t k64) -{ - uint32_t a,b,c; - a = b = c = 0xdeadbeef + 4; - b += k64 >> 32; - a += k64 & 0xffffffff; - final(a,b,c); - return c; -} -#undef final -#undef mix -#undef rot - -uint64_t APInt::getHashValue() const { - uint64_t hash; - if (isSingleWord()) - hash = hashword8(VAL); - else - hash = hashword(pVal, getNumWords()*2); - return hash; + return hash_combine_range(Arg.pVal, Arg.pVal + Arg.getNumWords()); } /// HiBits - This function returns the high "numBits" bits of this APInt. @@ -1123,6 +1042,18 @@ APInt APInt::sextOrTrunc(unsigned width) const { return *this; } +APInt APInt::zextOrSelf(unsigned width) const { + if (BitWidth < width) + return zext(width); + return *this; +} + +APInt APInt::sextOrSelf(unsigned width) const { + if (BitWidth < width) + return sext(width); + return *this; +} + /// Arithmetic right-shift this APInt by shiftAmt. /// @brief Arithmetic right-shift function. APInt APInt::ashr(const APInt &shiftAmt) const { @@ -1222,7 +1153,7 @@ APInt APInt::lshr(const APInt &shiftAmt) const { /// @brief Logical right-shift function. APInt APInt::lshr(unsigned shiftAmt) const { if (isSingleWord()) { - if (shiftAmt == BitWidth) + if (shiftAmt >= BitWidth) return APInt(BitWidth, 0); else return APInt(BitWidth, this->VAL >> shiftAmt); @@ -1338,14 +1269,10 @@ APInt APInt::rotl(const APInt &rotateAmt) const { } APInt APInt::rotl(unsigned rotateAmt) const { + rotateAmt %= BitWidth; if (rotateAmt == 0) return *this; - // Don't get too fancy, just use existing shift/or facilities - APInt hi(*this); - APInt lo(*this); - hi.shl(rotateAmt); - lo.lshr(BitWidth - rotateAmt); - return hi | lo; + return shl(rotateAmt) | lshr(BitWidth - rotateAmt); } APInt APInt::rotr(const APInt &rotateAmt) const { @@ -1353,14 +1280,10 @@ APInt APInt::rotr(const APInt &rotateAmt) const { } APInt APInt::rotr(unsigned rotateAmt) const { + rotateAmt %= BitWidth; if (rotateAmt == 0) return *this; - // Don't get too fancy, just use existing shift/or facilities - APInt hi(*this); - APInt lo(*this); - lo.lshr(rotateAmt); - hi.shl(BitWidth - rotateAmt); - return hi | lo; + return lshr(rotateAmt) | shl(BitWidth - rotateAmt); } // Square Root - this method computes and returns the square root of "this". @@ -2189,7 +2112,7 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, bool formatAsCLiteral) const { assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2 || Radix == 36) && - "Radix should be 2, 8, 10, or 16!"); + "Radix should be 2, 8, 10, 16, or 36!"); const char *Prefix = ""; if (formatAsCLiteral) { @@ -2202,9 +2125,13 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, case 8: Prefix = "0"; break; + case 10: + break; // No prefix case 16: Prefix = "0x"; break; + default: + llvm_unreachable("Invalid radix!"); } } diff --git a/lib/Support/Allocator.cpp b/lib/Support/Allocator.cpp index 215b0f2..b897830 100644 --- a/lib/Support/Allocator.cpp +++ b/lib/Support/Allocator.cpp @@ -22,8 +22,8 @@ namespace llvm { BumpPtrAllocator::BumpPtrAllocator(size_t size, size_t threshold, SlabAllocator &allocator) - : SlabSize(size), SizeThreshold(threshold), Allocator(allocator), - CurSlab(0), BytesAllocated(0) { } + : SlabSize(size), SizeThreshold(std::min(size, threshold)), + Allocator(allocator), CurSlab(0), BytesAllocated(0) { } BumpPtrAllocator::~BumpPtrAllocator() { DeallocateSlabs(CurSlab); diff --git a/lib/Support/Atomic.cpp b/lib/Support/Atomic.cpp index b3a730d..015b9c5 100644 --- a/lib/Support/Atomic.cpp +++ b/lib/Support/Atomic.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Atomic.h" -#include "llvm/Config/config.h" +#include "llvm/Config/llvm-config.h" #if defined(ANDROID_TARGET_BUILD) # include "sys/atomics.h" #endif diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt index 63a833c..0b69238 100644 --- a/lib/Support/CMakeLists.txt +++ b/lib/Support/CMakeLists.txt @@ -16,6 +16,7 @@ add_llvm_library(LLVMSupport ConstantRange.cpp CrashRecoveryContext.cpp DataExtractor.cpp + DataStream.cpp Debug.cpp DeltaAlgorithm.cpp DAGDeltaAlgorithm.cpp @@ -25,10 +26,14 @@ add_llvm_library(LLVMSupport FoldingSet.cpp FormattedStream.cpp GraphWriter.cpp + Hashing.cpp IntEqClasses.cpp IntervalMap.cpp + IntrusiveRefCntPtr.cpp IsInf.cpp IsNAN.cpp + JSONParser.cpp + LockFileManager.cpp ManagedStatic.cpp MemoryBuffer.cpp MemoryObject.cpp @@ -39,6 +44,7 @@ add_llvm_library(LLVMSupport SmallVector.cpp SourceMgr.cpp Statistic.cpp + StreamableMemoryObject.cpp StringExtras.cpp StringMap.cpp StringPool.cpp diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index ce93449..d1ec4b0 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -266,8 +266,8 @@ static bool CommaSeparateAndAddOccurence(Option *Handler, unsigned pos, /// and a null value (StringRef()). The later is accepted for arguments that /// don't allow a value (-foo) the former is rejected (-foo=). static inline bool ProvideOption(Option *Handler, StringRef ArgName, - StringRef Value, int argc, char **argv, - int &i) { + StringRef Value, int argc, + const char *const *argv, int &i) { // Is this a multi-argument option? unsigned NumAdditionalVals = Handler->getNumAdditionalVals(); @@ -292,12 +292,6 @@ static inline bool ProvideOption(Option *Handler, StringRef ArgName, break; case ValueOptional: break; - - default: - errs() << ProgramName - << ": Bad ValueMask flag! CommandLine usage error:" - << Handler->getValueExpectedFlag() << "\n"; - llvm_unreachable(0); } // If this isn't a multi-arg option, just run the handler. @@ -501,10 +495,10 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, /// ExpandResponseFiles - Copy the contents of argv into newArgv, /// substituting the contents of the response files for the arguments /// of type @file. -static void ExpandResponseFiles(unsigned argc, char** argv, +static void ExpandResponseFiles(unsigned argc, const char*const* argv, std::vector<char*>& newArgv) { for (unsigned i = 1; i != argc; ++i) { - char *arg = argv[i]; + const char *arg = argv[i]; if (arg[0] == '@') { sys::PathWithStatus respFile(++arg); @@ -534,7 +528,7 @@ static void ExpandResponseFiles(unsigned argc, char** argv, } } -void cl::ParseCommandLineOptions(int argc, char **argv, +void cl::ParseCommandLineOptions(int argc, const char * const *argv, const char *Overview, bool ReadResponseFiles) { // Process all registered options. SmallVector<Option*, 4> PositionalOpts; @@ -888,7 +882,6 @@ bool Option::addOccurrence(unsigned pos, StringRef ArgName, case OneOrMore: case ZeroOrMore: case ConsumeAfter: break; - default: return error("bad num occurrences flag value!"); } return handleOccurrence(pos, ArgName, Value); @@ -1352,7 +1345,7 @@ class VersionPrinter { public: void print() { raw_ostream &OS = outs(); - OS << "Low Level Virtual Machine (http://llvm.org/):\n" + OS << "LLVM (http://llvm.org/):\n" << " " << PACKAGE_NAME << " version " << PACKAGE_VERSION; #ifdef LLVM_VERSION_INFO OS << LLVM_VERSION_INFO; diff --git a/lib/Support/ConstantRange.cpp b/lib/Support/ConstantRange.cpp index 5743479..5206cf1 100644 --- a/lib/Support/ConstantRange.cpp +++ b/lib/Support/ConstantRange.cpp @@ -55,7 +55,7 @@ ConstantRange ConstantRange::makeICmpRegion(unsigned Pred, uint32_t W = CR.getBitWidth(); switch (Pred) { - default: assert(0 && "Invalid ICmp predicate to makeICmpRegion()"); + default: llvm_unreachable("Invalid ICmp predicate to makeICmpRegion()"); case CmpInst::ICMP_EQ: return CR; case CmpInst::ICMP_NE: @@ -161,8 +161,7 @@ APInt ConstantRange::getSetSize() const { APInt ConstantRange::getUnsignedMax() const { if (isFullSet() || isWrappedSet()) return APInt::getMaxValue(getBitWidth()); - else - return getUpper() - 1; + return getUpper() - 1; } /// getUnsignedMin - Return the smallest unsigned value contained in the @@ -171,8 +170,7 @@ APInt ConstantRange::getUnsignedMax() const { APInt ConstantRange::getUnsignedMin() const { if (isFullSet() || (isWrappedSet() && getUpper() != 0)) return APInt::getMinValue(getBitWidth()); - else - return getLower(); + return getLower(); } /// getSignedMax - Return the largest signed value contained in the @@ -183,14 +181,11 @@ APInt ConstantRange::getSignedMax() const { if (!isWrappedSet()) { if (getLower().sle(getUpper() - 1)) return getUpper() - 1; - else - return SignedMax; - } else { - if (getLower().isNegative() == getUpper().isNegative()) - return SignedMax; - else - return getUpper() - 1; + return SignedMax; } + if (getLower().isNegative() == getUpper().isNegative()) + return SignedMax; + return getUpper() - 1; } /// getSignedMin - Return the smallest signed value contained in the @@ -201,18 +196,13 @@ APInt ConstantRange::getSignedMin() const { if (!isWrappedSet()) { if (getLower().sle(getUpper() - 1)) return getLower(); - else + return SignedMin; + } + if ((getUpper() - 1).slt(getLower())) { + if (getUpper() != SignedMin) return SignedMin; - } else { - if ((getUpper() - 1).slt(getLower())) { - if (getUpper() != SignedMin) - return SignedMin; - else - return getLower(); - } else { - return getLower(); - } } + return getLower(); } /// contains - Return true if the specified value is in the set. @@ -223,8 +213,7 @@ bool ConstantRange::contains(const APInt &V) const { if (!isWrappedSet()) return Lower.ule(V) && V.ult(Upper); - else - return Lower.ule(V) || V.ult(Upper); + return Lower.ule(V) || V.ult(Upper); } /// contains - Return true if the argument is a subset of this range. @@ -284,15 +273,14 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const { return ConstantRange(CR.Lower, Upper); return CR; - } else { - if (Upper.ult(CR.Upper)) - return *this; + } + if (Upper.ult(CR.Upper)) + return *this; - if (Lower.ult(CR.Upper)) - return ConstantRange(Lower, CR.Upper); + if (Lower.ult(CR.Upper)) + return ConstantRange(Lower, CR.Upper); - return ConstantRange(getBitWidth(), false); - } + return ConstantRange(getBitWidth(), false); } if (isWrappedSet() && !CR.isWrappedSet()) { @@ -305,9 +293,9 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const { if (getSetSize().ult(CR.getSetSize())) return *this; - else - return CR; - } else if (CR.Lower.ult(Lower)) { + return CR; + } + if (CR.Lower.ult(Lower)) { if (CR.Upper.ule(Lower)) return ConstantRange(getBitWidth(), false); @@ -320,15 +308,15 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const { if (CR.Lower.ult(Upper)) { if (getSetSize().ult(CR.getSetSize())) return *this; - else - return CR; + return CR; } if (CR.Lower.ult(Lower)) return ConstantRange(Lower, CR.Upper); return CR; - } else if (CR.Upper.ult(Lower)) { + } + if (CR.Upper.ult(Lower)) { if (CR.Lower.ult(Lower)) return *this; @@ -336,8 +324,7 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const { } if (getSetSize().ult(CR.getSetSize())) return *this; - else - return CR; + return CR; } @@ -362,8 +349,7 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const { APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; if (d1.ult(d2)) return ConstantRange(Lower, CR.Upper); - else - return ConstantRange(CR.Lower, Upper); + return ConstantRange(CR.Lower, Upper); } APInt L = Lower, U = Upper; @@ -396,8 +382,7 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const { APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; if (d1.ult(d2)) return ConstantRange(Lower, CR.Upper); - else - return ConstantRange(CR.Lower, Upper); + return ConstantRange(CR.Lower, Upper); } // ----U L----- : this @@ -407,13 +392,11 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const { // ------U L---- : this // L-----U : CR - if (CR.Lower.ult(Upper) && CR.Upper.ult(Lower)) - return ConstantRange(Lower, CR.Upper); + assert(CR.Lower.ult(Upper) && CR.Upper.ult(Lower) && + "ConstantRange::unionWith missed a case with one range wrapped"); + return ConstantRange(Lower, CR.Upper); } - assert(isWrappedSet() && CR.isWrappedSet() && - "ConstantRange::unionWith missed wrapped union unwrapped case"); - // ------U L---- and ------U L---- : this // -U L----------- and ------------U L : CR if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper)) @@ -479,10 +462,9 @@ ConstantRange ConstantRange::zextOrTrunc(uint32_t DstTySize) const { unsigned SrcTySize = getBitWidth(); if (SrcTySize > DstTySize) return truncate(DstTySize); - else if (SrcTySize < DstTySize) + if (SrcTySize < DstTySize) return zeroExtend(DstTySize); - else - return *this; + return *this; } /// sextOrTrunc - make this range have the bit width given by \p DstTySize. The @@ -491,10 +473,9 @@ ConstantRange ConstantRange::sextOrTrunc(uint32_t DstTySize) const { unsigned SrcTySize = getBitWidth(); if (SrcTySize > DstTySize) return truncate(DstTySize); - else if (SrcTySize < DstTySize) + if (SrcTySize < DstTySize) return signExtend(DstTySize); - else - return *this; + return *this; } ConstantRange @@ -673,11 +654,10 @@ ConstantRange::lshr(const ConstantRange &Other) const { } ConstantRange ConstantRange::inverse() const { - if (isFullSet()) { + if (isFullSet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); - } else if (isEmptySet()) { + if (isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/true); - } return ConstantRange(Upper, Lower); } diff --git a/lib/Support/CrashRecoveryContext.cpp b/lib/Support/CrashRecoveryContext.cpp index 263114c..e2af0bc 100644 --- a/lib/Support/CrashRecoveryContext.cpp +++ b/lib/Support/CrashRecoveryContext.cpp @@ -165,7 +165,6 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) // Note that we don't actually get here because HandleCrash calls // longjmp, which means the HandleCrash function never returns. llvm_unreachable("Handled the crash, should have longjmp'ed out of here"); - return EXCEPTION_CONTINUE_SEARCH; } // Because the Enable and Disable calls are static, it means that diff --git a/lib/Support/DataExtractor.cpp b/lib/Support/DataExtractor.cpp index b946c1d..dc21155 100644 --- a/lib/Support/DataExtractor.cpp +++ b/lib/Support/DataExtractor.cpp @@ -75,7 +75,7 @@ uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const { uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst, uint32_t count) const { return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian, - Data.data());; + Data.data()); } uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const { diff --git a/lib/Support/DataStream.cpp b/lib/Support/DataStream.cpp new file mode 100644 index 0000000..94d14a5 --- /dev/null +++ b/lib/Support/DataStream.cpp @@ -0,0 +1,98 @@ +//===--- 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. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "Data-stream" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/DataStream.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/system_error.h" +#include <string> +#include <cerrno> +#include <cstdio> +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include <unistd.h> +#else +#include <io.h> +#endif +#include <fcntl.h> +using namespace llvm; + +// Interface goals: +// * StreamableMemoryObject 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: +// StreamableMemoryObject 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) {} + virtual ~DataFileStreamer() { + close(Fd); + } + virtual size_t GetBytes(unsigned char *buf, size_t len) { + NumStreamFetches++; + return read(Fd, buf, len); + } + + error_code OpenFile(const std::string &Filename) { + if (Filename == "-") { + Fd = 0; + sys::Program::ChangeStdinToBinary(); + return error_code::success(); + } + + int OpenFlags = O_RDONLY; +#ifdef O_BINARY + OpenFlags |= O_BINARY; // Open input file in binary mode on win32. +#endif + Fd = ::open(Filename.c_str(), OpenFlags); + if (Fd == -1) + return error_code(errno, posix_category()); + return error_code::success(); + } +}; + +} + +namespace llvm { +DataStreamer *getDataFileStreamer(const std::string &Filename, + std::string *StrError) { + DataFileStreamer *s = new DataFileStreamer(); + if (error_code e = s->OpenFile(Filename)) { + *StrError = std::string("Could not open ") + Filename + ": " + + e.message() + "\n"; + return NULL; + } + return s; +} + +} diff --git a/lib/Support/Dwarf.cpp b/lib/Support/Dwarf.cpp index 95a9550..b317e49 100644 --- a/lib/Support/Dwarf.cpp +++ b/lib/Support/Dwarf.cpp @@ -95,6 +95,7 @@ const char *llvm::dwarf::TagString(unsigned Tag) { return "DW_TAG_GNU_template_parameter_pack"; case DW_TAG_GNU_formal_parameter_pack: return "DW_TAG_GNU_formal_parameter_pack"; + case DW_TAG_APPLE_Property: return "DW_TAG_APPLE_property"; } return 0; } @@ -245,6 +246,7 @@ const char *llvm::dwarf::AttributeString(unsigned Attribute) { 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"; } return 0; diff --git a/lib/Support/FileUtilities.cpp b/lib/Support/FileUtilities.cpp index 4c8c0c6..f9e9cf0 100644 --- a/lib/Support/FileUtilities.cpp +++ b/lib/Support/FileUtilities.cpp @@ -200,7 +200,6 @@ int llvm::DiffFilesWithTolerance(const sys::PathWithStatus &FileA, // Now its safe to mmap the files into memory because both files // have a non-zero size. - error_code ec; OwningPtr<MemoryBuffer> F1; if (error_code ec = MemoryBuffer::getFile(FileA.c_str(), F1)) { if (Error) diff --git a/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp index 17b8271..e029970 100644 --- a/lib/Support/FoldingSet.cpp +++ b/lib/Support/FoldingSet.cpp @@ -15,6 +15,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Hashing.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -29,24 +30,7 @@ using namespace llvm; /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, /// used to lookup the node in the FoldingSetImpl. unsigned FoldingSetNodeIDRef::ComputeHash() const { - // This is adapted from SuperFastHash by Paul Hsieh. - unsigned Hash = static_cast<unsigned>(Size); - for (const unsigned *BP = Data, *E = BP+Size; BP != E; ++BP) { - unsigned Data = *BP; - Hash += Data & 0xFFFF; - unsigned Tmp = ((Data >> 16) << 11) ^ Hash; - Hash = (Hash << 16) ^ Tmp; - Hash += Hash >> 11; - } - - // Force "avalanching" of final 127 bits. - Hash ^= Hash << 3; - Hash += Hash >> 5; - Hash ^= Hash << 4; - Hash += Hash >> 17; - Hash ^= Hash << 25; - Hash += Hash >> 6; - return Hash; + return static_cast<unsigned>(hash_combine_range(Data, Data+Size)); } bool FoldingSetNodeIDRef::operator==(FoldingSetNodeIDRef RHS) const { diff --git a/lib/Support/Hashing.cpp b/lib/Support/Hashing.cpp new file mode 100644 index 0000000..c69efb7 --- /dev/null +++ b/lib/Support/Hashing.cpp @@ -0,0 +1,29 @@ +//===-------------- lib/Support/Hashing.cpp -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides implementation bits for the LLVM common hashing +// infrastructure. Documentation and most of the other information is in the +// header file. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Hashing.h" + +using namespace llvm; + +// Provide a definition and static initializer for the fixed seed. This +// initializer should always be zero to ensure its value can never appear to be +// non-zero, even during dynamic initialization. +size_t llvm::hashing::detail::fixed_seed_override = 0; + +// Implement the function for forced setting of the fixed seed. +// FIXME: Use atomic operations here so that there is no data race. +void llvm::set_fixed_execution_hash_seed(size_t fixed_value) { + hashing::detail::fixed_seed_override = fixed_value; +} diff --git a/lib/Support/Host.cpp b/lib/Support/Host.cpp index 86d1c5d..0f06964 100644 --- a/lib/Support/Host.cpp +++ b/lib/Support/Host.cpp @@ -61,6 +61,8 @@ static bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX, *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__) @@ -87,9 +89,14 @@ static bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX, mov dword ptr [esi],edx } return false; +// pedantic #else returns to appease -Wunreachable-code (so we don't generate +// postprocessed code that looks like "return true; return false;") + #else + return true; #endif -#endif +#else return true; +#endif } static void DetectX86FamilyModel(unsigned EAX, unsigned &Family, @@ -298,6 +305,8 @@ std::string sys::getHostCPUName() { } case 16: return "amdfam10"; + case 20: + return "btver1"; case 21: return "bdver1"; default: diff --git a/lib/Support/IntrusiveRefCntPtr.cpp b/lib/Support/IntrusiveRefCntPtr.cpp new file mode 100644 index 0000000..a8b4559 --- /dev/null +++ b/lib/Support/IntrusiveRefCntPtr.cpp @@ -0,0 +1,14 @@ +//== 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/lib/Support/JSONParser.cpp b/lib/Support/JSONParser.cpp new file mode 100644 index 0000000..5dfcf29 --- /dev/null +++ b/lib/Support/JSONParser.cpp @@ -0,0 +1,302 @@ +//===--- JSONParser.cpp - Simple JSON parser ------------------------------===// +// +// 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 JSON parser. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/JSONParser.h" + +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/MemoryBuffer.h" + +using namespace llvm; + +JSONParser::JSONParser(StringRef Input, SourceMgr *SM) + : SM(SM), Failed(false) { + InputBuffer = MemoryBuffer::getMemBuffer(Input, "JSON"); + SM->AddNewSourceBuffer(InputBuffer, SMLoc()); + End = InputBuffer->getBuffer().end(); + Position = InputBuffer->getBuffer().begin(); +} + +JSONValue *JSONParser::parseRoot() { + if (Position != InputBuffer->getBuffer().begin()) + report_fatal_error("Cannot reuse JSONParser."); + if (isWhitespace()) + nextNonWhitespace(); + if (errorIfAtEndOfFile("'[' or '{' at start of JSON text")) + return 0; + switch (*Position) { + case '[': + return new (ValueAllocator.Allocate<JSONArray>(1)) JSONArray(this); + case '{': + return new (ValueAllocator.Allocate<JSONObject>(1)) JSONObject(this); + default: + setExpectedError("'[' or '{' at start of JSON text", *Position); + return 0; + } +} + +bool JSONParser::validate() { + JSONValue *Root = parseRoot(); + if (Root == NULL) { + return false; + } + return skip(*Root); +} + +bool JSONParser::skip(const JSONAtom &Atom) { + switch(Atom.getKind()) { + case JSONAtom::JK_Array: + case JSONAtom::JK_Object: + return skipContainer(*cast<JSONContainer>(&Atom)); + case JSONAtom::JK_String: + return true; + case JSONAtom::JK_KeyValuePair: + return skip(*cast<JSONKeyValuePair>(&Atom)->Value); + } + llvm_unreachable("Impossible enum value."); +} + +// Sets the current error to: +// "expected <Expected>, but found <Found>". +void JSONParser::setExpectedError(StringRef Expected, StringRef Found) { + SM->PrintMessage(SMLoc::getFromPointer(Position), SourceMgr::DK_Error, + "expected " + Expected + ", but found " + Found + ".", ArrayRef<SMRange>()); + Failed = true; +} + +// Sets the current error to: +// "expected <Expected>, but found <Found>". +void JSONParser::setExpectedError(StringRef Expected, char Found) { + setExpectedError(Expected, ("'" + StringRef(&Found, 1) + "'").str()); +} + +// If there is no character available, returns true and sets the current error +// to: "expected <Expected>, but found EOF.". +bool JSONParser::errorIfAtEndOfFile(StringRef Expected) { + if (Position == End) { + setExpectedError(Expected, "EOF"); + return true; + } + return false; +} + +// Sets the current error if the current character is not C to: +// "expected 'C', but got <current character>". +bool JSONParser::errorIfNotAt(char C, StringRef Message) { + if (*Position != C) { + std::string Expected = + ("'" + StringRef(&C, 1) + "' " + Message).str(); + if (Position == End) + setExpectedError(Expected, "EOF"); + else + setExpectedError(Expected, *Position); + return true; + } + return false; +} + +// Forbidding inlining improves performance by roughly 20%. +// FIXME: Remove once llvm optimizes this to the faster version without hints. +LLVM_ATTRIBUTE_NOINLINE static bool +wasEscaped(StringRef::iterator First, StringRef::iterator Position); + +// Returns whether a character at 'Position' was escaped with a leading '\'. +// 'First' specifies the position of the first character in the string. +static bool wasEscaped(StringRef::iterator First, + StringRef::iterator Position) { + assert(Position - 1 >= First); + StringRef::iterator I = Position - 1; + // We calulate the number of consecutive '\'s before the current position + // by iterating backwards through our string. + while (I >= First && *I == '\\') --I; + // (Position - 1 - I) now contains the number of '\'s before the current + // position. If it is odd, the character at 'Positon' was escaped. + return (Position - 1 - I) % 2 == 1; +} + +// Parses a JSONString, assuming that the current position is on a quote. +JSONString *JSONParser::parseString() { + assert(Position != End); + assert(!isWhitespace()); + if (errorIfNotAt('"', "at start of string")) + return 0; + StringRef::iterator First = Position + 1; + + // Benchmarking shows that this loop is the hot path of the application with + // about 2/3rd of the runtime cycles. Since escaped quotes are not the common + // case, and multiple escaped backslashes before escaped quotes are very rare, + // we pessimize this case to achieve a smaller inner loop in the common case. + // We're doing that by having a quick inner loop that just scans for the next + // quote. Once we find the quote we check the last character to see whether + // the quote might have been escaped. If the last character is not a '\', we + // know the quote was not escaped and have thus found the end of the string. + // If the immediately preceding character was a '\', we have to scan backwards + // to see whether the previous character was actually an escaped backslash, or + // an escape character for the quote. If we find that the current quote was + // escaped, we continue parsing for the next quote and repeat. + // This optimization brings around 30% performance improvements. + do { + // Step over the current quote. + ++Position; + // Find the next quote. + while (Position != End && *Position != '"') + ++Position; + if (errorIfAtEndOfFile("'\"' at end of string")) + return 0; + // Repeat until the previous character was not a '\' or was an escaped + // backslash. + } while (*(Position - 1) == '\\' && wasEscaped(First, Position)); + + return new (ValueAllocator.Allocate<JSONString>()) + JSONString(StringRef(First, Position - First)); +} + + +// Advances the position to the next non-whitespace position. +void JSONParser::nextNonWhitespace() { + do { + ++Position; + } while (isWhitespace()); +} + +// Checks if there is a whitespace character at the current position. +bool JSONParser::isWhitespace() { + return *Position == ' ' || *Position == '\t' || + *Position == '\n' || *Position == '\r'; +} + +bool JSONParser::failed() const { + return Failed; +} + +// Parses a JSONValue, assuming that the current position is at the first +// character of the value. +JSONValue *JSONParser::parseValue() { + assert(Position != End); + assert(!isWhitespace()); + switch (*Position) { + case '[': + return new (ValueAllocator.Allocate<JSONArray>(1)) JSONArray(this); + case '{': + return new (ValueAllocator.Allocate<JSONObject>(1)) JSONObject(this); + case '"': + return parseString(); + default: + setExpectedError("'[', '{' or '\"' at start of value", *Position); + return 0; + } +} + +// Parses a JSONKeyValuePair, assuming that the current position is at the first +// character of the key, value pair. +JSONKeyValuePair *JSONParser::parseKeyValuePair() { + assert(Position != End); + assert(!isWhitespace()); + + JSONString *Key = parseString(); + if (Key == 0) + return 0; + + nextNonWhitespace(); + if (errorIfNotAt(':', "between key and value")) + return 0; + + nextNonWhitespace(); + const JSONValue *Value = parseValue(); + if (Value == 0) + return 0; + + return new (ValueAllocator.Allocate<JSONKeyValuePair>(1)) + JSONKeyValuePair(Key, Value); +} + +/// \brief Parses the first element of a JSON array or object, or closes the +/// array. +/// +/// The method assumes that the current position is before the first character +/// of the element, with possible white space in between. When successful, it +/// returns the new position after parsing the element. Otherwise, if there is +/// no next value, it returns a default constructed StringRef::iterator. +StringRef::iterator JSONParser::parseFirstElement(JSONAtom::Kind ContainerKind, + char StartChar, char EndChar, + const JSONAtom *&Element) { + assert(*Position == StartChar); + Element = 0; + nextNonWhitespace(); + if (errorIfAtEndOfFile("value or end of container at start of container")) + return StringRef::iterator(); + + if (*Position == EndChar) + return StringRef::iterator(); + + Element = parseElement(ContainerKind); + if (Element == 0) + return StringRef::iterator(); + + return Position; +} + +/// \brief Parses the next element of a JSON array or object, or closes the +/// array. +/// +/// The method assumes that the current position is before the ',' which +/// separates the next element from the current element. When successful, it +/// returns the new position after parsing the element. Otherwise, if there is +/// no next value, it returns a default constructed StringRef::iterator. +StringRef::iterator JSONParser::parseNextElement(JSONAtom::Kind ContainerKind, + char EndChar, + const JSONAtom *&Element) { + Element = 0; + nextNonWhitespace(); + if (errorIfAtEndOfFile("',' or end of container for next element")) + return 0; + + if (*Position == ',') { + nextNonWhitespace(); + if (errorIfAtEndOfFile("element in container")) + return StringRef::iterator(); + + Element = parseElement(ContainerKind); + if (Element == 0) + return StringRef::iterator(); + + return Position; + } else if (*Position == EndChar) { + return StringRef::iterator(); + } else { + setExpectedError("',' or end of container for next element", *Position); + return StringRef::iterator(); + } +} + +const JSONAtom *JSONParser::parseElement(JSONAtom::Kind ContainerKind) { + switch (ContainerKind) { + case JSONAtom::JK_Array: + return parseValue(); + case JSONAtom::JK_Object: + return parseKeyValuePair(); + default: + llvm_unreachable("Impossible code path"); + } +} + +bool JSONParser::skipContainer(const JSONContainer &Container) { + for (JSONContainer::AtomIterator I = Container.atom_current(), + E = Container.atom_end(); + I != E; ++I) { + assert(*I != 0); + if (!skip(**I)) + return false; + } + return !failed(); +} diff --git a/lib/Support/LockFileManager.cpp b/lib/Support/LockFileManager.cpp new file mode 100644 index 0000000..64404a1 --- /dev/null +++ b/lib/Support/LockFileManager.cpp @@ -0,0 +1,216 @@ +//===--- LockFileManager.cpp - File-level Locking Utility------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "llvm/Support/LockFileManager.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" +#include <fstream> +#include <sys/types.h> +#include <sys/stat.h> +#if LLVM_ON_WIN32 +#include <windows.h> +#endif +#if LLVM_ON_UNIX +#include <unistd.h> +#endif +using namespace llvm; + +/// \brief Attempt to read the lock file with the given name, if it exists. +/// +/// \param LockFileName The name of the lock file to read. +/// +/// \returns The process ID of the process that owns this lock file +Optional<std::pair<std::string, int> > +LockFileManager::readLockFile(StringRef LockFileName) { + // Check whether the lock file exists. If not, clearly there's nothing + // to read, so we just return. + bool Exists = false; + if (sys::fs::exists(LockFileName, Exists) || !Exists) + return Optional<std::pair<std::string, int> >(); + + // Read the owning host and PID out of the lock file. If it appears that the + // owning process is dead, the lock file is invalid. + int PID = 0; + std::string Hostname; + std::ifstream Input(LockFileName.str().c_str()); + if (Input >> Hostname >> PID && PID > 0 && + processStillExecuting(Hostname, PID)) + return std::make_pair(Hostname, PID); + + // Delete the lock file. It's invalid anyway. + bool Existed; + sys::fs::remove(LockFileName, Existed); + return Optional<std::pair<std::string, int> >(); +} + +bool LockFileManager::processStillExecuting(StringRef Hostname, int PID) { +#if LLVM_ON_UNIX + char MyHostname[256]; + MyHostname[255] = 0; + MyHostname[0] = 0; + gethostname(MyHostname, 255); + // Check whether the process is dead. If so, we're done. + if (MyHostname == Hostname && getsid(PID) == -1 && errno == ESRCH) + return false; +#endif + + return true; +} + +LockFileManager::LockFileManager(StringRef FileName) +{ + LockFileName = FileName; + LockFileName += ".lock"; + + // If the lock file already exists, don't bother to try to create our own + // lock file; it won't work anyway. Just figure out who owns this lock file. + if ((Owner = readLockFile(LockFileName))) + return; + + // Create a lock file that is unique to this instance. + UniqueLockFileName = LockFileName; + UniqueLockFileName += "-%%%%%%%%"; + int UniqueLockFileID; + if (error_code EC + = sys::fs::unique_file(UniqueLockFileName.str(), + UniqueLockFileID, + UniqueLockFileName, + /*makeAbsolute=*/false)) { + Error = EC; + return; + } + + // Write our process ID to our unique lock file. + { + raw_fd_ostream Out(UniqueLockFileID, /*shouldClose=*/true); + +#if LLVM_ON_UNIX + // FIXME: move getpid() call into LLVM + char hostname[256]; + hostname[255] = 0; + hostname[0] = 0; + gethostname(hostname, 255); + Out << hostname << ' ' << getpid(); +#else + Out << "localhost 1"; +#endif + Out.close(); + + if (Out.has_error()) { + // We failed to write out PID, so make up an excuse, remove the + // unique lock file, and fail. + Error = make_error_code(errc::no_space_on_device); + bool Existed; + sys::fs::remove(UniqueLockFileName.c_str(), Existed); + return; + } + } + + // Create a hard link from the lock file name. If this succeeds, we're done. + error_code EC + = sys::fs::create_hard_link(UniqueLockFileName.str(), + LockFileName.str()); + if (EC == errc::success) + return; + + // Creating the hard link failed. + +#ifdef LLVM_ON_UNIX + // The creation of the hard link may appear to fail, but if stat'ing the + // unique file returns a link count of 2, then we can still declare success. + struct stat StatBuf; + if (stat(UniqueLockFileName.c_str(), &StatBuf) == 0 && + StatBuf.st_nlink == 2) + return; +#endif + + // Someone else managed to create the lock file first. Wipe out our unique + // lock file (it's useless now) and read the process ID from the lock file. + bool Existed; + sys::fs::remove(UniqueLockFileName.str(), Existed); + if ((Owner = readLockFile(LockFileName))) + return; + + // There is a lock file that nobody owns; try to clean it up and report + // an error. + sys::fs::remove(LockFileName.str(), Existed); + Error = EC; +} + +LockFileManager::LockFileState LockFileManager::getState() const { + if (Owner) + return LFS_Shared; + + if (Error) + return LFS_Error; + + return LFS_Owned; +} + +LockFileManager::~LockFileManager() { + if (getState() != LFS_Owned) + return; + + // Since we own the lock, remove the lock file and our own unique lock file. + bool Existed; + sys::fs::remove(LockFileName.str(), Existed); + sys::fs::remove(UniqueLockFileName.str(), Existed); +} + +void LockFileManager::waitForUnlock() { + if (getState() != LFS_Shared) + return; + +#if LLVM_ON_WIN32 + unsigned long Interval = 1; +#else + struct timespec Interval; + Interval.tv_sec = 0; + Interval.tv_nsec = 1000000; +#endif + // Don't wait more than an hour for the file to appear. + const unsigned MaxSeconds = 3600; + do { + // Sleep for the designated interval, to allow the owning process time to + // finish up and remove the lock file. + // FIXME: Should we hook in to system APIs to get a notification when the + // lock file is deleted? +#if LLVM_ON_WIN32 + Sleep(Interval); +#else + nanosleep(&Interval, NULL); +#endif + // If the file no longer exists, we're done. + bool Exists = false; + if (!sys::fs::exists(LockFileName.str(), Exists) && !Exists) + return; + + if (!processStillExecuting((*Owner).first, (*Owner).second)) + return; + + // Exponentially increase the time we wait for the lock to be removed. +#if LLVM_ON_WIN32 + Interval *= 2; +#else + Interval.tv_sec *= 2; + Interval.tv_nsec *= 2; + if (Interval.tv_nsec >= 1000000000) { + ++Interval.tv_sec; + Interval.tv_nsec -= 1000000000; + } +#endif + } while ( +#if LLVM_ON_WIN32 + Interval < MaxSeconds * 1000 +#else + Interval.tv_sec < (time_t)MaxSeconds +#endif + ); + + // Give up. +} diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp index 1a40972..4b15587 100644 --- a/lib/Support/MemoryBuffer.cpp +++ b/lib/Support/MemoryBuffer.cpp @@ -36,8 +36,6 @@ #include <fcntl.h> using namespace llvm; -namespace { const llvm::error_code success; } - //===----------------------------------------------------------------------===// // MemoryBuffer implementation itself. //===----------------------------------------------------------------------===// @@ -306,7 +304,7 @@ error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, RealMapOffset)) { result.reset(GetNamedBuffer<MemoryBufferMMapFile>( StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator)); - return success; + return error_code::success(); } } @@ -344,7 +342,7 @@ error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, } result.swap(SB); - return success; + return error_code::success(); } //===----------------------------------------------------------------------===// @@ -373,5 +371,5 @@ error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) { } while (ReadBytes != 0); result.reset(getMemBufferCopy(Buffer, "<stdin>")); - return success; + return error_code::success(); } diff --git a/lib/Support/Mutex.cpp b/lib/Support/Mutex.cpp index 6a873cb..da5baab 100644 --- a/lib/Support/Mutex.cpp +++ b/lib/Support/Mutex.cpp @@ -40,109 +40,80 @@ bool MutexImpl::tryacquire() { return true; } namespace llvm { using namespace sys; - -// This variable is useful for situations where the pthread library has been -// compiled with weak linkage for its interface symbols. This allows the -// threading support to be turned off by simply not linking against -lpthread. -// In that situation, the value of pthread_mutex_init will be 0 and -// consequently pthread_enabled will be false. In such situations, all the -// pthread operations become no-ops and the functions all return false. If -// pthread_mutex_init does have an address, then mutex support is enabled. -// Note: all LLVM tools will link against -lpthread if its available since it -// is configured into the LIBS variable. -// Note: this line of code generates a warning if pthread_mutex_init is not -// declared with weak linkage. It's safe to ignore the warning. -static const bool pthread_enabled = true; - // Construct a Mutex using pthread calls MutexImpl::MutexImpl( bool recursive) : data_(0) { - if (pthread_enabled) - { - // Declare the pthread_mutex data structures - pthread_mutex_t* mutex = - static_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t))); - pthread_mutexattr_t attr; - - // Initialize the mutex attributes - int errorcode = pthread_mutexattr_init(&attr); - assert(errorcode == 0); - - // Initialize the mutex as a recursive mutex, if requested, or normal - // otherwise. - int kind = ( recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL ); - errorcode = pthread_mutexattr_settype(&attr, kind); - assert(errorcode == 0); + // Declare the pthread_mutex data structures + pthread_mutex_t* mutex = + static_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t))); + pthread_mutexattr_t attr; + + // Initialize the mutex attributes + int errorcode = pthread_mutexattr_init(&attr); + assert(errorcode == 0); (void)errorcode; + + // Initialize the mutex as a recursive mutex, if requested, or normal + // otherwise. + int kind = ( recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL ); + errorcode = pthread_mutexattr_settype(&attr, kind); + assert(errorcode == 0); #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) - // Make it a process local mutex - errorcode = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); - assert(errorcode == 0); + // Make it a process local mutex + errorcode = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); + assert(errorcode == 0); #endif - // Initialize the mutex - errorcode = pthread_mutex_init(mutex, &attr); - assert(errorcode == 0); + // Initialize the mutex + errorcode = pthread_mutex_init(mutex, &attr); + assert(errorcode == 0); - // Destroy the attributes - errorcode = pthread_mutexattr_destroy(&attr); - assert(errorcode == 0); + // Destroy the attributes + errorcode = pthread_mutexattr_destroy(&attr); + assert(errorcode == 0); - // Assign the data member - data_ = mutex; - } + // Assign the data member + data_ = mutex; } // Destruct a Mutex MutexImpl::~MutexImpl() { - if (pthread_enabled) - { - pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); - assert(mutex != 0); - pthread_mutex_destroy(mutex); - free(mutex); - } + pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); + assert(mutex != 0); + pthread_mutex_destroy(mutex); + free(mutex); } bool MutexImpl::acquire() { - if (pthread_enabled) - { - pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); - assert(mutex != 0); - - int errorcode = pthread_mutex_lock(mutex); - return errorcode == 0; - } else return false; + pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); + assert(mutex != 0); + + int errorcode = pthread_mutex_lock(mutex); + return errorcode == 0; } bool MutexImpl::release() { - if (pthread_enabled) - { - pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); - assert(mutex != 0); - - int errorcode = pthread_mutex_unlock(mutex); - return errorcode == 0; - } else return false; + pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); + assert(mutex != 0); + + int errorcode = pthread_mutex_unlock(mutex); + return errorcode == 0; } bool MutexImpl::tryacquire() { - if (pthread_enabled) - { - pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); - assert(mutex != 0); - - int errorcode = pthread_mutex_trylock(mutex); - return errorcode == 0; - } else return false; + pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); + assert(mutex != 0); + + int errorcode = pthread_mutex_trylock(mutex); + return errorcode == 0; } } diff --git a/lib/Support/PathV2.cpp b/lib/Support/PathV2.cpp index 7cc434b..786e1a1 100644 --- a/lib/Support/PathV2.cpp +++ b/lib/Support/PathV2.cpp @@ -24,15 +24,13 @@ namespace { using llvm::sys::path::is_separator; #ifdef LLVM_ON_WIN32 - const StringRef separators = "\\/"; - const char prefered_separator = '\\'; + const char *separators = "\\/"; + const char prefered_separator = '\\'; #else - const StringRef separators = "/"; - const char prefered_separator = '/'; + const char separators = '/'; + const char prefered_separator = '/'; #endif - const llvm::error_code success; - StringRef find_first_component(StringRef path) { // Look for this first component in the following order. // * empty (in this case we return an empty string) @@ -348,7 +346,7 @@ const StringRef root_directory(StringRef path) { const StringRef relative_path(StringRef path) { StringRef root = root_path(path); - return root.substr(root.size()); + return path.substr(root.size()); } void append(SmallVectorImpl<char> &path, const Twine &a, @@ -602,12 +600,16 @@ namespace fs { error_code make_absolute(SmallVectorImpl<char> &path) { StringRef p(path.data(), path.size()); - bool rootName = path::has_root_name(p), - rootDirectory = path::has_root_directory(p); + bool rootDirectory = path::has_root_directory(p), +#ifdef LLVM_ON_WIN32 + rootName = path::has_root_name(p); +#else + rootName = true; +#endif // Already absolute. if (rootName && rootDirectory) - return success; + return error_code::success(); // All of the following conditions will need the current directory. SmallString<128> current_dir; @@ -619,7 +621,7 @@ error_code make_absolute(SmallVectorImpl<char> &path) { path::append(current_dir, p); // Set path to the result. path.swap(current_dir); - return success; + return error_code::success(); } if (!rootName && rootDirectory) { @@ -628,7 +630,7 @@ error_code make_absolute(SmallVectorImpl<char> &path) { path::append(curDirRootName, p); // Set path to the result. path.swap(curDirRootName); - return success; + return error_code::success(); } if (rootName && !rootDirectory) { @@ -640,7 +642,7 @@ error_code make_absolute(SmallVectorImpl<char> &path) { SmallString<128> res; path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath); path.swap(res); - return success; + return error_code::success(); } llvm_unreachable("All rootName and rootDirectory combinations should have " @@ -679,7 +681,7 @@ error_code is_directory(const Twine &path, bool &result) { if (error_code ec = status(path, st)) return ec; result = is_directory(st); - return success; + return error_code::success(); } bool is_regular_file(file_status status) { @@ -691,7 +693,7 @@ error_code is_regular_file(const Twine &path, bool &result) { if (error_code ec = status(path, st)) return ec; result = is_regular_file(st); - return success; + return error_code::success(); } bool is_symlink(file_status status) { @@ -703,7 +705,7 @@ error_code is_symlink(const Twine &path, bool &result) { if (error_code ec = status(path, st)) return ec; result = is_symlink(st); - return success; + return error_code::success(); } bool is_other(file_status status) { @@ -730,13 +732,13 @@ error_code has_magic(const Twine &path, const Twine &magic, bool &result) { if (ec == errc::value_too_large) { // Magic.size() > file_size(Path). result = false; - return success; + return error_code::success(); } return ec; } result = Magic == Buffer; - return success; + return error_code::success(); } /// @brief Identify the magic in magic. @@ -857,7 +859,7 @@ error_code identify_magic(const Twine &path, file_magic &result) { return ec; result = identify_magic(Magic); - return success; + return error_code::success(); } namespace { @@ -884,7 +886,7 @@ error_code remove_all_r(StringRef path, file_type ft, uint32_t &count) { ++count; } - return success; + return error_code::success(); } } // end unnamed namespace diff --git a/lib/Support/RWMutex.cpp b/lib/Support/RWMutex.cpp index d14b976..6a34f2d 100644 --- a/lib/Support/RWMutex.cpp +++ b/lib/Support/RWMutex.cpp @@ -42,107 +42,75 @@ bool RWMutexImpl::writer_release() { return true; } namespace llvm { using namespace sys; - -// This variable is useful for situations where the pthread library has been -// compiled with weak linkage for its interface symbols. This allows the -// threading support to be turned off by simply not linking against -lpthread. -// In that situation, the value of pthread_mutex_init will be 0 and -// consequently pthread_enabled will be false. In such situations, all the -// pthread operations become no-ops and the functions all return false. If -// pthread_rwlock_init does have an address, then rwlock support is enabled. -// Note: all LLVM tools will link against -lpthread if its available since it -// is configured into the LIBS variable. -// Note: this line of code generates a warning if pthread_rwlock_init is not -// declared with weak linkage. It's safe to ignore the warning. -static const bool pthread_enabled = true; - // Construct a RWMutex using pthread calls RWMutexImpl::RWMutexImpl() : data_(0) { - if (pthread_enabled) - { - // Declare the pthread_rwlock data structures - pthread_rwlock_t* rwlock = - static_cast<pthread_rwlock_t*>(malloc(sizeof(pthread_rwlock_t))); + // Declare the pthread_rwlock data structures + pthread_rwlock_t* rwlock = + static_cast<pthread_rwlock_t*>(malloc(sizeof(pthread_rwlock_t))); #ifdef __APPLE__ - // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. - bzero(rwlock, sizeof(pthread_rwlock_t)); + // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. + bzero(rwlock, sizeof(pthread_rwlock_t)); #endif - // Initialize the rwlock - int errorcode = pthread_rwlock_init(rwlock, NULL); - (void)errorcode; - assert(errorcode == 0); + // Initialize the rwlock + int errorcode = pthread_rwlock_init(rwlock, NULL); + (void)errorcode; + assert(errorcode == 0); - // Assign the data member - data_ = rwlock; - } + // Assign the data member + data_ = rwlock; } // Destruct a RWMutex RWMutexImpl::~RWMutexImpl() { - if (pthread_enabled) - { - pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); - assert(rwlock != 0); - pthread_rwlock_destroy(rwlock); - free(rwlock); - } + pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); + assert(rwlock != 0); + pthread_rwlock_destroy(rwlock); + free(rwlock); } bool RWMutexImpl::reader_acquire() { - if (pthread_enabled) - { - pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); - assert(rwlock != 0); - - int errorcode = pthread_rwlock_rdlock(rwlock); - return errorcode == 0; - } else return false; + pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_rdlock(rwlock); + return errorcode == 0; } bool RWMutexImpl::reader_release() { - if (pthread_enabled) - { - pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); - assert(rwlock != 0); - - int errorcode = pthread_rwlock_unlock(rwlock); - return errorcode == 0; - } else return false; + pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_unlock(rwlock); + return errorcode == 0; } bool RWMutexImpl::writer_acquire() { - if (pthread_enabled) - { - pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); - assert(rwlock != 0); - - int errorcode = pthread_rwlock_wrlock(rwlock); - return errorcode == 0; - } else return false; + pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_wrlock(rwlock); + return errorcode == 0; } bool RWMutexImpl::writer_release() { - if (pthread_enabled) - { - pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); - assert(rwlock != 0); - - int errorcode = pthread_rwlock_unlock(rwlock); - return errorcode == 0; - } else return false; + pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_unlock(rwlock); + return errorcode == 0; } } diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp index 5a6090d..bbe36b2 100644 --- a/lib/Support/SourceMgr.cpp +++ b/lib/Support/SourceMgr.cpp @@ -244,7 +244,6 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S) const { } switch (Kind) { - default: assert(0 && "Unknown diagnostic kind"); case SourceMgr::DK_Error: S << "error: "; break; case SourceMgr::DK_Warning: S << "warning: "; break; case SourceMgr::DK_Note: S << "note: "; break; diff --git a/lib/Support/StreamableMemoryObject.cpp b/lib/Support/StreamableMemoryObject.cpp new file mode 100644 index 0000000..c23f07b --- /dev/null +++ b/lib/Support/StreamableMemoryObject.cpp @@ -0,0 +1,140 @@ +//===- StreamableMemoryObject.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/StreamableMemoryObject.h" +#include <cassert> +#include <cstring> + + +using namespace llvm; + +namespace { + +class RawMemoryObject : public StreamableMemoryObject { +public: + RawMemoryObject(const unsigned char *Start, const unsigned char *End) : + FirstChar(Start), LastChar(End) { + assert(LastChar > FirstChar && "Invalid start/end range"); + } + + virtual uint64_t getBase() const { return 0; } + virtual uint64_t getExtent() const { return LastChar - FirstChar; } + virtual int readByte(uint64_t address, uint8_t* ptr) const; + virtual int readBytes(uint64_t address, + uint64_t size, + uint8_t* buf, + uint64_t* copied) const; + virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const; + virtual bool isValidAddress(uint64_t address) const { + return validAddress(address); + } + virtual bool isObjectEnd(uint64_t address) const {return objectEnd(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<ptrdiff_t>(address) < LastChar - FirstChar; + } + bool objectEnd(uint64_t address) const { + return static_cast<ptrdiff_t>(address) == LastChar - FirstChar; + } + + RawMemoryObject(const RawMemoryObject&); // DO NOT IMPLEMENT + void operator=(const RawMemoryObject&); // DO NOT IMPLEMENT +}; + +int RawMemoryObject::readByte(uint64_t address, uint8_t* ptr) const { + if (!validAddress(address)) return -1; + *ptr = *((uint8_t *)(uintptr_t)(address + FirstChar)); + return 0; +} + +int RawMemoryObject::readBytes(uint64_t address, + uint64_t size, + uint8_t* buf, + uint64_t* copied) const { + if (!validAddress(address) || !validAddress(address + size - 1)) return -1; + memcpy(buf, (uint8_t *)(uintptr_t)(address + FirstChar), size); + if (copied) *copied = 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); +} + +bool StreamingMemoryObject::isObjectEnd(uint64_t address) const { + if (ObjectSize) return address == ObjectSize; + fetchToPos(address); + return address == ObjectSize && address != 0; +} + +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; +} + +int StreamingMemoryObject::readByte(uint64_t address, uint8_t* ptr) const { + if (!fetchToPos(address)) return -1; + *ptr = Bytes[address + BytesSkipped]; + return 0; +} + +int StreamingMemoryObject::readBytes(uint64_t address, + uint64_t size, + uint8_t* buf, + uint64_t* copied) const { + if (!fetchToPos(address + size - 1)) return -1; + memcpy(buf, &Bytes[address + BytesSkipped], size); + if (copied) *copied = size; + return 0; +} + +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); +} + +StreamableMemoryObject *getNonStreamedMemoryObject( + const unsigned char *Start, const unsigned char *End) { + return new RawMemoryObject(Start, End); +} + +StreamableMemoryObject::~StreamableMemoryObject() { } + +StreamingMemoryObject::StreamingMemoryObject(DataStreamer *streamer) : + Bytes(kChunkSize), Streamer(streamer), BytesRead(0), BytesSkipped(0), + ObjectSize(0), EOFReached(false) { + BytesRead = streamer->GetBytes(&Bytes[0], kChunkSize); +} +} diff --git a/lib/Support/StringExtras.cpp b/lib/Support/StringExtras.cpp index 49c5ac4..d77ad7f 100644 --- a/lib/Support/StringExtras.cpp +++ b/lib/Support/StringExtras.cpp @@ -57,24 +57,3 @@ void llvm::SplitString(StringRef Source, S = getToken(S.second, Delimiters); } } - -void llvm::StringRef::split(SmallVectorImpl<StringRef> &A, - StringRef Separators, int MaxSplit, - bool KeepEmpty) const { - StringRef rest = *this; - - // rest.data() is used to distinguish cases like "a," that splits into - // "a" + "" and "a" that splits into "a" + 0. - for (int splits = 0; - rest.data() != NULL && (MaxSplit < 0 || splits < MaxSplit); - ++splits) { - std::pair<llvm::StringRef, llvm::StringRef> p = rest.split(Separators); - - if (p.first.size() != 0 || KeepEmpty) - A.push_back(p.first); - rest = p.second; - } - // If we have a tail left, add it. - if (rest.data() != NULL && (rest.size() != 0 || KeepEmpty)) - A.push_back(rest); -} diff --git a/lib/Support/StringMap.cpp b/lib/Support/StringMap.cpp index a1ac512..c131fe0 100644 --- a/lib/Support/StringMap.cpp +++ b/lib/Support/StringMap.cpp @@ -39,11 +39,13 @@ void StringMapImpl::init(unsigned InitSize) { NumItems = 0; NumTombstones = 0; - TheTable = (ItemBucket*)calloc(NumBuckets+1, sizeof(ItemBucket)); - + TheTable = (StringMapEntryBase **)calloc(NumBuckets+1, + sizeof(StringMapEntryBase **) + + sizeof(unsigned)); + // Allocate one extra bucket, set it to look filled so the iterators stop at // end. - TheTable[NumBuckets].Item = (StringMapEntryBase*)2; + TheTable[NumBuckets] = (StringMapEntryBase*)2; } @@ -60,29 +62,29 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) { } unsigned FullHashValue = HashString(Name); unsigned BucketNo = FullHashValue & (HTSize-1); - + unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); + unsigned ProbeAmt = 1; int FirstTombstone = -1; while (1) { - ItemBucket &Bucket = TheTable[BucketNo]; - StringMapEntryBase *BucketItem = Bucket.Item; + StringMapEntryBase *BucketItem = TheTable[BucketNo]; // If we found an empty bucket, this key isn't in the table yet, return it. if (BucketItem == 0) { // If we found a tombstone, we want to reuse the tombstone instead of an // empty bucket. This reduces probing. if (FirstTombstone != -1) { - TheTable[FirstTombstone].FullHashValue = FullHashValue; + HashTable[FirstTombstone] = FullHashValue; return FirstTombstone; } - Bucket.FullHashValue = FullHashValue; + HashTable[BucketNo] = FullHashValue; return BucketNo; } if (BucketItem == getTombstoneVal()) { // Skip over tombstones. However, remember the first one we see. if (FirstTombstone == -1) FirstTombstone = BucketNo; - } else if (Bucket.FullHashValue == FullHashValue) { + } else if (HashTable[BucketNo] == FullHashValue) { // If the full hash value matches, check deeply for a match. The common // case here is that we are only looking at the buckets (for item info // being non-null and for the full hash value) not at the items. This @@ -115,18 +117,18 @@ int StringMapImpl::FindKey(StringRef Key) const { if (HTSize == 0) return -1; // Really empty table? unsigned FullHashValue = HashString(Key); unsigned BucketNo = FullHashValue & (HTSize-1); - + unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); + unsigned ProbeAmt = 1; while (1) { - ItemBucket &Bucket = TheTable[BucketNo]; - StringMapEntryBase *BucketItem = Bucket.Item; + StringMapEntryBase *BucketItem = TheTable[BucketNo]; // If we found an empty bucket, this key isn't in the table yet, return. if (BucketItem == 0) return -1; if (BucketItem == getTombstoneVal()) { // Ignore tombstones. - } else if (Bucket.FullHashValue == FullHashValue) { + } else if (HashTable[BucketNo] == FullHashValue) { // If the full hash value matches, check deeply for a match. The common // case here is that we are only looking at the buckets (for item info // being non-null and for the full hash value) not at the items. This @@ -165,8 +167,8 @@ StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { int Bucket = FindKey(Key); if (Bucket == -1) return 0; - StringMapEntryBase *Result = TheTable[Bucket].Item; - TheTable[Bucket].Item = getTombstoneVal(); + StringMapEntryBase *Result = TheTable[Bucket]; + TheTable[Bucket] = getTombstoneVal(); --NumItems; ++NumTombstones; assert(NumItems + NumTombstones <= NumBuckets); @@ -180,6 +182,7 @@ StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { /// the appropriate mod-of-hashtable-size. void StringMapImpl::RehashTable() { unsigned NewSize; + unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); // If the hash table is now more than 3/4 full, or if fewer than 1/8 of // the buckets are empty (meaning that many are filled with tombstones), @@ -194,19 +197,23 @@ void StringMapImpl::RehashTable() { // Allocate one extra bucket which will always be non-empty. This allows the // iterators to stop at end. - ItemBucket *NewTableArray =(ItemBucket*)calloc(NewSize+1, sizeof(ItemBucket)); - NewTableArray[NewSize].Item = (StringMapEntryBase*)2; - + StringMapEntryBase **NewTableArray = + (StringMapEntryBase **)calloc(NewSize+1, sizeof(StringMapEntryBase *) + + sizeof(unsigned)); + unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1); + NewTableArray[NewSize] = (StringMapEntryBase*)2; + // Rehash all the items into their new buckets. Luckily :) we already have // the hash values available, so we don't have to rehash any strings. - for (ItemBucket *IB = TheTable, *E = TheTable+NumBuckets; IB != E; ++IB) { - if (IB->Item && IB->Item != getTombstoneVal()) { + for (unsigned I = 0, E = NumBuckets; I != E; ++I) { + StringMapEntryBase *Bucket = TheTable[I]; + if (Bucket && Bucket != getTombstoneVal()) { // Fast case, bucket available. - unsigned FullHash = IB->FullHashValue; + unsigned FullHash = HashTable[I]; unsigned NewBucket = FullHash & (NewSize-1); - if (NewTableArray[NewBucket].Item == 0) { - NewTableArray[FullHash & (NewSize-1)].Item = IB->Item; - NewTableArray[FullHash & (NewSize-1)].FullHashValue = FullHash; + if (NewTableArray[NewBucket] == 0) { + NewTableArray[FullHash & (NewSize-1)] = Bucket; + NewHashArray[FullHash & (NewSize-1)] = FullHash; continue; } @@ -214,11 +221,11 @@ void StringMapImpl::RehashTable() { unsigned ProbeSize = 1; do { NewBucket = (NewBucket + ProbeSize++) & (NewSize-1); - } while (NewTableArray[NewBucket].Item); + } while (NewTableArray[NewBucket]); // Finally found a slot. Fill it in. - NewTableArray[NewBucket].Item = IB->Item; - NewTableArray[NewBucket].FullHashValue = FullHash; + NewTableArray[NewBucket] = Bucket; + NewHashArray[NewBucket] = FullHash; } } diff --git a/lib/Support/StringRef.cpp b/lib/Support/StringRef.cpp index e73c6e3..1c28bf8 100644 --- a/lib/Support/StringRef.cpp +++ b/lib/Support/StringRef.cpp @@ -10,6 +10,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/edit_distance.h" #include <bitset> using namespace llvm; @@ -84,57 +86,10 @@ int StringRef::compare_numeric(StringRef RHS) const { unsigned StringRef::edit_distance(llvm::StringRef Other, bool AllowReplacements, unsigned MaxEditDistance) { - // The algorithm implemented below is the "classic" - // dynamic-programming algorithm for computing the Levenshtein - // distance, which is described here: - // - // http://en.wikipedia.org/wiki/Levenshtein_distance - // - // Although the algorithm is typically described using an m x n - // array, only two rows are used at a time, so this implemenation - // just keeps two separate vectors for those two rows. - size_type m = size(); - size_type n = Other.size(); - - const unsigned SmallBufferSize = 64; - unsigned SmallBuffer[SmallBufferSize]; - llvm::OwningArrayPtr<unsigned> Allocated; - unsigned *previous = SmallBuffer; - if (2*(n + 1) > SmallBufferSize) { - previous = new unsigned [2*(n+1)]; - Allocated.reset(previous); - } - unsigned *current = previous + (n + 1); - - for (unsigned i = 0; i <= n; ++i) - previous[i] = i; - - for (size_type y = 1; y <= m; ++y) { - current[0] = y; - unsigned BestThisRow = current[0]; - - for (size_type x = 1; x <= n; ++x) { - if (AllowReplacements) { - current[x] = min(previous[x-1] + ((*this)[y-1] == Other[x-1]? 0u:1u), - min(current[x-1], previous[x])+1); - } - else { - if ((*this)[y-1] == Other[x-1]) current[x] = previous[x-1]; - else current[x] = min(current[x-1], previous[x]) + 1; - } - BestThisRow = min(BestThisRow, current[x]); - } - - if (MaxEditDistance && BestThisRow > MaxEditDistance) - return MaxEditDistance + 1; - - unsigned *tmp = current; - current = previous; - previous = tmp; - } - - unsigned Result = previous[n]; - return Result; + return llvm::ComputeEditDistance( + llvm::ArrayRef<char>(data(), size()), + llvm::ArrayRef<char>(Other.data(), Other.size()), + AllowReplacements, MaxEditDistance); } //===----------------------------------------------------------------------===// @@ -275,6 +230,27 @@ StringRef::size_type StringRef::find_last_of(StringRef Chars, return npos; } +void StringRef::split(SmallVectorImpl<StringRef> &A, + StringRef Separators, int MaxSplit, + bool KeepEmpty) const { + StringRef rest = *this; + + // rest.data() is used to distinguish cases like "a," that splits into + // "a" + "" and "a" that splits into "a" + 0. + for (int splits = 0; + rest.data() != NULL && (MaxSplit < 0 || splits < MaxSplit); + ++splits) { + std::pair<StringRef, StringRef> p = rest.split(Separators); + + if (KeepEmpty || p.first.size() != 0) + A.push_back(p.first); + rest = p.second; + } + // If we have a tail left, add it. + if (rest.data() != NULL && (rest.size() != 0 || KeepEmpty)) + A.push_back(rest); +} + //===----------------------------------------------------------------------===// // Helpful Algorithms //===----------------------------------------------------------------------===// @@ -472,3 +448,9 @@ bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const { return false; } + + +// Implementation of StringRef hashing. +hash_code llvm::hash_value(StringRef S) { + return hash_combine_range(S.begin(), S.end()); +} diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index 8f58e70..94333a3 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -9,13 +9,14 @@ #include "llvm/ADT/Triple.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" #include <cstring> using namespace llvm; const char *Triple::getArchTypeName(ArchType Kind) { switch (Kind) { - case InvalidArch: return "<invalid>"; case UnknownArch: return "unknown"; case arm: return "arm"; @@ -42,7 +43,7 @@ const char *Triple::getArchTypeName(ArchType Kind) { case amdil: return "amdil"; } - return "<invalid>"; + llvm_unreachable("Invalid ArchType!"); } const char *Triple::getArchTypePrefix(ArchType Kind) { @@ -86,7 +87,7 @@ const char *Triple::getVendorTypeName(VendorType Kind) { case SCEI: return "scei"; } - return "<invalid>"; + llvm_unreachable("Invalid VendorType!"); } const char *Triple::getOSTypeName(OSType Kind) { @@ -106,7 +107,6 @@ const char *Triple::getOSTypeName(OSType Kind) { case MinGW32: return "mingw32"; case NetBSD: return "netbsd"; case OpenBSD: return "openbsd"; - case Psp: return "psp"; case Solaris: return "solaris"; case Win32: return "win32"; case Haiku: return "haiku"; @@ -115,70 +115,49 @@ const char *Triple::getOSTypeName(OSType Kind) { case NativeClient: return "nacl"; } - return "<invalid>"; + llvm_unreachable("Invalid OSType"); } const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { switch (Kind) { case UnknownEnvironment: return "unknown"; case GNU: return "gnu"; + case GNUEABIHF: return "gnueabihf"; case GNUEABI: return "gnueabi"; case EABI: return "eabi"; case MachO: return "macho"; + case ANDROIDEABI: return "androideabi"; } - return "<invalid>"; + llvm_unreachable("Invalid EnvironmentType!"); } Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { - if (Name == "arm") - return arm; - if (Name == "cellspu") - return cellspu; - if (Name == "mips") - return mips; - if (Name == "mipsel") - return mipsel; - if (Name == "mips64") - return mips64; - if (Name == "mips64el") - return mips64el; - if (Name == "msp430") - return msp430; - if (Name == "ppc64") - return ppc64; - if (Name == "ppc32") - return ppc; - if (Name == "ppc") - return ppc; - if (Name == "mblaze") - return mblaze; - if (Name == "hexagon") - return hexagon; - if (Name == "sparc") - return sparc; - if (Name == "sparcv9") - return sparcv9; - if (Name == "tce") - return tce; - if (Name == "thumb") - return thumb; - if (Name == "x86") - return x86; - if (Name == "x86-64") - return x86_64; - if (Name == "xcore") - return xcore; - if (Name == "ptx32") - return ptx32; - if (Name == "ptx64") - return ptx64; - if (Name == "le32") - return le32; - if (Name == "amdil") - return amdil; - - return UnknownArch; + return StringSwitch<Triple::ArchType>(Name) + .Case("arm", arm) + .Case("cellspu", cellspu) + .Case("mips", mips) + .Case("mipsel", mipsel) + .Case("mips64", mips64) + .Case("mips64el", mips64el) + .Case("msp430", msp430) + .Case("ppc64", ppc64) + .Case("ppc32", ppc) + .Case("ppc", ppc) + .Case("mblaze", mblaze) + .Case("hexagon", hexagon) + .Case("sparc", sparc) + .Case("sparcv9", sparcv9) + .Case("tce", tce) + .Case("thumb", thumb) + .Case("x86", x86) + .Case("x86-64", x86_64) + .Case("xcore", xcore) + .Case("ptx32", ptx32) + .Case("ptx64", ptx64) + .Case("le32", le32) + .Case("amdil", amdil) + .Default(UnknownArch); } Triple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) { @@ -194,36 +173,21 @@ Triple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) { // This code must be kept in sync with Clang's Darwin specific argument // translation. - if (Str == "ppc" || Str == "ppc601" || Str == "ppc603" || Str == "ppc604" || - Str == "ppc604e" || Str == "ppc750" || Str == "ppc7400" || - Str == "ppc7450" || Str == "ppc970") - return Triple::ppc; - - if (Str == "ppc64") - return Triple::ppc64; - - if (Str == "i386" || Str == "i486" || Str == "i486SX" || Str == "pentium" || - Str == "i586" || Str == "pentpro" || Str == "i686" || Str == "pentIIm3" || - Str == "pentIIm5" || Str == "pentium4") - return Triple::x86; - - if (Str == "x86_64") - return Triple::x86_64; - - // This is derived from the driver driver. - if (Str == "arm" || Str == "armv4t" || Str == "armv5" || Str == "xscale" || - Str == "armv6" || Str == "armv7" || Str == "armv7f" || Str == "armv7k" || - Str == "armv7s") - return Triple::arm; - - if (Str == "ptx32") - return Triple::ptx32; - if (Str == "ptx64") - return Triple::ptx64; - if (Str == "amdil") - return Triple::amdil; - - return Triple::UnknownArch; + return StringSwitch<ArchType>(Str) + .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", Triple::ppc) + .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", Triple::ppc) + .Case("ppc64", Triple::ppc64) + .Cases("i386", "i486", "i486SX", "i586", "i686", Triple::x86) + .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4", + Triple::x86) + .Case("x86_64", Triple::x86_64) + // This is derived from the driver driver. + .Cases("arm", "armv4t", "armv5", "armv6", Triple::arm) + .Cases("armv7", "armv7f", "armv7k", "armv7s", "xscale", Triple::arm) + .Case("ptx32", Triple::ptx32) + .Case("ptx64", Triple::ptx64) + .Case("amdil", Triple::amdil) + .Default(Triple::UnknownArch); } // Returns architecture name that is understood by the target assembler. @@ -231,184 +195,145 @@ const char *Triple::getArchNameForAssembler() { if (!isOSDarwin() && getVendor() != Triple::Apple) return NULL; - StringRef Str = getArchName(); - if (Str == "i386") - return "i386"; - if (Str == "x86_64") - return "x86_64"; - if (Str == "powerpc") - return "ppc"; - if (Str == "powerpc64") - return "ppc64"; - if (Str == "mblaze" || Str == "microblaze") - return "mblaze"; - if (Str == "arm") - return "arm"; - if (Str == "armv4t" || Str == "thumbv4t") - return "armv4t"; - if (Str == "armv5" || Str == "armv5e" || Str == "thumbv5" - || Str == "thumbv5e") - return "armv5"; - if (Str == "armv6" || Str == "thumbv6") - return "armv6"; - if (Str == "armv7" || Str == "thumbv7") - return "armv7"; - if (Str == "ptx32") - return "ptx32"; - if (Str == "ptx64") - return "ptx64"; - if (Str == "le32") - return "le32"; - if (Str == "amdil") - return "amdil"; - return NULL; + return StringSwitch<const char*>(getArchName()) + .Case("i386", "i386") + .Case("x86_64", "x86_64") + .Case("powerpc", "ppc") + .Case("powerpc64", "ppc64") + .Cases("mblaze", "microblaze", "mblaze") + .Case("arm", "arm") + .Cases("armv4t", "thumbv4t", "armv4t") + .Cases("armv5", "armv5e", "thumbv5", "thumbv5e", "armv5") + .Cases("armv6", "thumbv6", "armv6") + .Cases("armv7", "thumbv7", "armv7") + .Case("ptx32", "ptx32") + .Case("ptx64", "ptx64") + .Case("le32", "le32") + .Case("amdil", "amdil") + .Default(NULL); } -// +static Triple::ArchType parseArch(StringRef ArchName) { + return StringSwitch<Triple::ArchType>(ArchName) + .Cases("i386", "i486", "i586", "i686", Triple::x86) + // FIXME: Do we need to support these? + .Cases("i786", "i886", "i986", Triple::x86) + .Cases("amd64", "x86_64", Triple::x86_64) + .Case("powerpc", Triple::ppc) + .Cases("powerpc64", "ppu", Triple::ppc64) + .Case("mblaze", Triple::mblaze) + .Cases("arm", "xscale", Triple::arm) + // FIXME: It would be good to replace these with explicit names for all the + // various suffixes supported. + .StartsWith("armv", Triple::arm) + .Case("thumb", Triple::thumb) + .StartsWith("thumbv", Triple::thumb) + .Cases("spu", "cellspu", Triple::cellspu) + .Case("msp430", Triple::msp430) + .Cases("mips", "mipseb", "mipsallegrex", Triple::mips) + .Cases("mipsel", "mipsallegrexel", Triple::mipsel) + .Cases("mips64", "mips64eb", Triple::mips64) + .Case("mips64el", Triple::mips64el) + .Case("hexagon", Triple::hexagon) + .Case("sparc", Triple::sparc) + .Case("sparcv9", Triple::sparcv9) + .Case("tce", Triple::tce) + .Case("xcore", Triple::xcore) + .Case("ptx32", Triple::ptx32) + .Case("ptx64", Triple::ptx64) + .Case("le32", Triple::le32) + .Case("amdil", Triple::amdil) + .Default(Triple::UnknownArch); +} -Triple::ArchType Triple::ParseArch(StringRef ArchName) { - if (ArchName.size() == 4 && ArchName[0] == 'i' && - ArchName[2] == '8' && ArchName[3] == '6' && - ArchName[1] - '3' < 6) // i[3-9]86 - return x86; - else if (ArchName == "amd64" || ArchName == "x86_64") - return x86_64; - else if (ArchName == "powerpc") - return ppc; - else if ((ArchName == "powerpc64") || (ArchName == "ppu")) - return ppc64; - else if (ArchName == "mblaze") - return mblaze; - else if (ArchName == "arm" || - ArchName.startswith("armv") || - ArchName == "xscale") - return arm; - else if (ArchName == "thumb" || - ArchName.startswith("thumbv")) - return thumb; - else if (ArchName == "spu" || ArchName == "cellspu") - return cellspu; - else if (ArchName == "msp430") - return msp430; - else if (ArchName == "mips" || ArchName == "mipseb" || - ArchName == "mipsallegrex") - return mips; - else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" || - ArchName == "psp") - return mipsel; - else if (ArchName == "mips64" || ArchName == "mips64eb") - return mips64; - else if (ArchName == "mips64el") - return mips64el; - else if (ArchName == "hexagon") - return hexagon; - else if (ArchName == "sparc") - return sparc; - else if (ArchName == "sparcv9") - return sparcv9; - else if (ArchName == "tce") - return tce; - else if (ArchName == "xcore") - return xcore; - else if (ArchName == "ptx32") - return ptx32; - else if (ArchName == "ptx64") - return ptx64; - else if (ArchName == "le32") - return le32; - else if (ArchName == "amdil") - return amdil; - else - return UnknownArch; +static Triple::VendorType parseVendor(StringRef VendorName) { + return StringSwitch<Triple::VendorType>(VendorName) + .Case("apple", Triple::Apple) + .Case("pc", Triple::PC) + .Case("scei", Triple::SCEI) + .Default(Triple::UnknownVendor); } -Triple::VendorType Triple::ParseVendor(StringRef VendorName) { - if (VendorName == "apple") - return Apple; - else if (VendorName == "pc") - return PC; - else if (VendorName == "scei") - return SCEI; - else - return UnknownVendor; -} - -Triple::OSType Triple::ParseOS(StringRef OSName) { - if (OSName.startswith("auroraux")) - return AuroraUX; - else if (OSName.startswith("cygwin")) - return Cygwin; - else if (OSName.startswith("darwin")) - return Darwin; - else if (OSName.startswith("dragonfly")) - return DragonFly; - else if (OSName.startswith("freebsd")) - return FreeBSD; - else if (OSName.startswith("ios")) - return IOS; - else if (OSName.startswith("kfreebsd")) - return KFreeBSD; - else if (OSName.startswith("linux")) - return Linux; - else if (OSName.startswith("lv2")) - return Lv2; - else if (OSName.startswith("macosx")) - return MacOSX; - else if (OSName.startswith("mingw32")) - return MinGW32; - else if (OSName.startswith("netbsd")) - return NetBSD; - else if (OSName.startswith("openbsd")) - return OpenBSD; - else if (OSName.startswith("psp")) - return Psp; - else if (OSName.startswith("solaris")) - return Solaris; - else if (OSName.startswith("win32")) - return Win32; - else if (OSName.startswith("haiku")) - return Haiku; - else if (OSName.startswith("minix")) - return Minix; - else if (OSName.startswith("rtems")) - return RTEMS; - else if (OSName.startswith("nacl")) - return NativeClient; - else - return UnknownOS; -} - -Triple::EnvironmentType Triple::ParseEnvironment(StringRef EnvironmentName) { - if (EnvironmentName.startswith("eabi")) - return EABI; - else if (EnvironmentName.startswith("gnueabi")) - return GNUEABI; - else if (EnvironmentName.startswith("gnu")) - return GNU; - else if (EnvironmentName.startswith("macho")) - return MachO; - else - return UnknownEnvironment; +static Triple::OSType parseOS(StringRef OSName) { + return StringSwitch<Triple::OSType>(OSName) + .StartsWith("auroraux", Triple::AuroraUX) + .StartsWith("cygwin", Triple::Cygwin) + .StartsWith("darwin", Triple::Darwin) + .StartsWith("dragonfly", Triple::DragonFly) + .StartsWith("freebsd", Triple::FreeBSD) + .StartsWith("ios", Triple::IOS) + .StartsWith("kfreebsd", Triple::KFreeBSD) + .StartsWith("linux", Triple::Linux) + .StartsWith("lv2", Triple::Lv2) + .StartsWith("macosx", Triple::MacOSX) + .StartsWith("mingw32", Triple::MinGW32) + .StartsWith("netbsd", Triple::NetBSD) + .StartsWith("openbsd", Triple::OpenBSD) + .StartsWith("solaris", Triple::Solaris) + .StartsWith("win32", Triple::Win32) + .StartsWith("haiku", Triple::Haiku) + .StartsWith("minix", Triple::Minix) + .StartsWith("rtems", Triple::RTEMS) + .StartsWith("nacl", Triple::NativeClient) + .Default(Triple::UnknownOS); } -void Triple::Parse() const { - assert(!isInitialized() && "Invalid parse call."); +static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) { + return StringSwitch<Triple::EnvironmentType>(EnvironmentName) + .StartsWith("eabi", Triple::EABI) + .StartsWith("gnueabihf", Triple::GNUEABIHF) + .StartsWith("gnueabi", Triple::GNUEABI) + .StartsWith("gnu", Triple::GNU) + .StartsWith("macho", Triple::MachO) + .StartsWith("androideabi", Triple::ANDROIDEABI) + .Default(Triple::UnknownEnvironment); +} - Arch = ParseArch(getArchName()); - Vendor = ParseVendor(getVendorName()); - OS = ParseOS(getOSName()); - Environment = ParseEnvironment(getEnvironmentName()); +/// \brief Construct a triple from the string representation provided. +/// +/// This stores the string representation and parses the various pieces into +/// enum members. +Triple::Triple(const Twine &Str) + : Data(Str.str()), + Arch(parseArch(getArchName())), + Vendor(parseVendor(getVendorName())), + OS(parseOS(getOSName())), + Environment(parseEnvironment(getEnvironmentName())) { +} - assert(isInitialized() && "Failed to initialize!"); +/// \brief Construct a triple from string representations of the architecture, +/// vendor, and OS. +/// +/// This joins each argument into a canonical string representation and parses +/// them into enum members. It leaves the environment unknown and omits it from +/// the string representation. +Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr) + : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr).str()), + Arch(parseArch(ArchStr.str())), + Vendor(parseVendor(VendorStr.str())), + OS(parseOS(OSStr.str())), + Environment() { +} + +/// \brief Construct a triple from string representations of the architecture, +/// vendor, OS, and environment. +/// +/// This joins each argument into a canonical string representation and parses +/// them into enum members. +Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr, + const Twine &EnvironmentStr) + : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr + Twine('-') + + EnvironmentStr).str()), + Arch(parseArch(ArchStr.str())), + Vendor(parseVendor(VendorStr.str())), + OS(parseOS(OSStr.str())), + Environment(parseEnvironment(EnvironmentStr.str())) { } std::string Triple::normalize(StringRef Str) { // Parse into components. SmallVector<StringRef, 4> Components; - for (size_t First = 0, Last = 0; Last != StringRef::npos; First = Last + 1) { - Last = Str.find('-', First); - Components.push_back(Str.slice(First, Last)); - } + Str.split(Components, "-"); // If the first component corresponds to a known architecture, preferentially // use it for the architecture. If the second component corresponds to a @@ -417,16 +342,16 @@ std::string Triple::normalize(StringRef Str) { // valid os. ArchType Arch = UnknownArch; if (Components.size() > 0) - Arch = ParseArch(Components[0]); + Arch = parseArch(Components[0]); VendorType Vendor = UnknownVendor; if (Components.size() > 1) - Vendor = ParseVendor(Components[1]); + Vendor = parseVendor(Components[1]); OSType OS = UnknownOS; if (Components.size() > 2) - OS = ParseOS(Components[2]); + OS = parseOS(Components[2]); EnvironmentType Environment = UnknownEnvironment; if (Components.size() > 3) - Environment = ParseEnvironment(Components[3]); + Environment = parseEnvironment(Components[3]); // Note which components are already in their final position. These will not // be moved. @@ -452,22 +377,21 @@ std::string Triple::normalize(StringRef Str) { bool Valid = false; StringRef Comp = Components[Idx]; switch (Pos) { - default: - assert(false && "unexpected component type!"); + default: llvm_unreachable("unexpected component type!"); case 0: - Arch = ParseArch(Comp); + Arch = parseArch(Comp); Valid = Arch != UnknownArch; break; case 1: - Vendor = ParseVendor(Comp); + Vendor = parseVendor(Comp); Valid = Vendor != UnknownVendor; break; case 2: - OS = ParseOS(Comp); + OS = parseOS(Comp); Valid = OS != UnknownOS; break; case 3: - Environment = ParseEnvironment(Comp); + Environment = parseEnvironment(Comp); Valid = Environment != UnknownEnvironment; break; } @@ -488,7 +412,8 @@ std::string Triple::normalize(StringRef Str) { // components to the right. for (unsigned i = Pos; !CurrentComponent.empty(); ++i) { // Skip over any fixed components. - while (i < array_lengthof(Found) && Found[i]) ++i; + while (i < array_lengthof(Found) && Found[i]) + ++i; // Place the component at the new position, getting the component // that was at this position - it will be moved right. std::swap(CurrentComponent, Components[i]); @@ -516,7 +441,8 @@ std::string Triple::normalize(StringRef Str) { Components.push_back(CurrentComponent); // Advance Idx to the component's new position. - while (++Idx < array_lengthof(Found) && Found[Idx]) {} + while (++Idx < array_lengthof(Found) && Found[Idx]) + ; } while (Idx < Pos); // Add more until the final position is reached. } assert(Pos < Components.size() && Components[Pos] == Comp && @@ -606,9 +532,47 @@ void Triple::getOSVersion(unsigned &Major, unsigned &Minor, } } +bool Triple::getMacOSXVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const { + getOSVersion(Major, Minor, Micro); + + switch (getOS()) { + default: llvm_unreachable("unexpected OS for Darwin triple"); + case Darwin: + // Default to darwin8, i.e., MacOSX 10.4. + if (Major == 0) + Major = 8; + // Darwin version numbers are skewed from OS X versions. + if (Major < 4) + return false; + Micro = 0; + Minor = Major - 4; + Major = 10; + break; + case MacOSX: + // Default to 10.4. + if (Major == 0) { + Major = 10; + Minor = 4; + } + if (Major != 10) + return false; + break; + case IOS: + // Ignore the version from the triple. This is only handled because the + // the clang driver combines OS X and IOS support into a common Darwin + // toolchain that wants to know the OS X version number even when targeting + // IOS. + Major = 10; + Minor = 4; + Micro = 0; + break; + } + return true; +} + void Triple::setTriple(const Twine &Str) { - Data = Str.str(); - Arch = InvalidArch; + *this = Triple(Str); } void Triple::setArch(ArchType Kind) { @@ -658,3 +622,123 @@ void Triple::setEnvironmentName(StringRef Str) { void Triple::setOSAndEnvironmentName(StringRef Str) { setTriple(getArchName() + "-" + getVendorName() + "-" + Str); } + +static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { + switch (Arch) { + case llvm::Triple::UnknownArch: + return 0; + + case llvm::Triple::msp430: + return 16; + + case llvm::Triple::amdil: + case llvm::Triple::arm: + case llvm::Triple::cellspu: + case llvm::Triple::hexagon: + case llvm::Triple::le32: + case llvm::Triple::mblaze: + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::ppc: + case llvm::Triple::ptx32: + case llvm::Triple::sparc: + case llvm::Triple::tce: + case llvm::Triple::thumb: + case llvm::Triple::x86: + case llvm::Triple::xcore: + return 32; + + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + case llvm::Triple::ppc64: + case llvm::Triple::ptx64: + case llvm::Triple::sparcv9: + case llvm::Triple::x86_64: + return 64; + } + llvm_unreachable("Invalid architecture value"); +} + +bool Triple::isArch64Bit() const { + return getArchPointerBitWidth(getArch()) == 64; +} + +bool Triple::isArch32Bit() const { + return getArchPointerBitWidth(getArch()) == 32; +} + +bool Triple::isArch16Bit() const { + return getArchPointerBitWidth(getArch()) == 16; +} + +Triple Triple::get32BitArchVariant() const { + Triple T(*this); + switch (getArch()) { + case Triple::UnknownArch: + case Triple::msp430: + T.setArch(UnknownArch); + break; + + case Triple::amdil: + case Triple::arm: + case Triple::cellspu: + case Triple::hexagon: + case Triple::le32: + case Triple::mblaze: + case Triple::mips: + case Triple::mipsel: + case Triple::ppc: + case Triple::ptx32: + case Triple::sparc: + case Triple::tce: + case Triple::thumb: + case Triple::x86: + case Triple::xcore: + // Already 32-bit. + break; + + case Triple::mips64: T.setArch(Triple::mips); break; + case Triple::mips64el: T.setArch(Triple::mipsel); break; + case Triple::ppc64: T.setArch(Triple::ppc); break; + case Triple::ptx64: T.setArch(Triple::ptx32); break; + case Triple::sparcv9: T.setArch(Triple::sparc); break; + case Triple::x86_64: T.setArch(Triple::x86); break; + } + return T; +} + +Triple Triple::get64BitArchVariant() const { + Triple T(*this); + switch (getArch()) { + case Triple::UnknownArch: + case Triple::amdil: + case Triple::arm: + case Triple::cellspu: + case Triple::hexagon: + case Triple::le32: + case Triple::mblaze: + case Triple::msp430: + case Triple::tce: + case Triple::thumb: + case Triple::xcore: + T.setArch(UnknownArch); + break; + + case Triple::mips64: + case Triple::mips64el: + case Triple::ppc64: + case Triple::ptx64: + case Triple::sparcv9: + case Triple::x86_64: + // Already 64-bit. + break; + + case Triple::mips: T.setArch(Triple::mips64); break; + case Triple::mipsel: T.setArch(Triple::mips64el); break; + case Triple::ppc: T.setArch(Triple::ppc64); break; + case Triple::ptx32: T.setArch(Triple::ptx64); break; + case Triple::sparc: T.setArch(Triple::sparcv9); break; + case Triple::x86: T.setArch(Triple::x86_64); break; + } + return T; +} diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc index aebb4ab..7d79947 100644 --- a/lib/Support/Unix/PathV2.inc +++ b/lib/Support/Unix/PathV2.inc @@ -89,7 +89,7 @@ namespace { result.clear(); StringRef d(dir); result.append(d.begin(), d.end()); - return success; + return error_code::success(); } } @@ -112,7 +112,7 @@ error_code current_path(SmallVectorImpl<char> &result) { } result.set_size(strlen(result.data())); - return success; + return error_code::success(); } error_code copy_file(const Twine &from, const Twine &to, copy_option copt) { @@ -171,7 +171,7 @@ error_code copy_file(const Twine &from, const Twine &to, copy_option copt) { if (sz_read < 0) return error_code(errno, system_category()); - return success; + return error_code::success(); } error_code create_directory(const Twine &path, bool &existed) { @@ -185,7 +185,7 @@ error_code create_directory(const Twine &path, bool &existed) { } else existed = false; - return success; + return error_code::success(); } error_code create_hard_link(const Twine &to, const Twine &from) { @@ -198,7 +198,7 @@ error_code create_hard_link(const Twine &to, const Twine &from) { if (::link(t.begin(), f.begin()) == -1) return error_code(errno, system_category()); - return success; + return error_code::success(); } error_code create_symlink(const Twine &to, const Twine &from) { @@ -211,7 +211,7 @@ error_code create_symlink(const Twine &to, const Twine &from) { if (::symlink(t.begin(), f.begin()) == -1) return error_code(errno, system_category()); - return success; + return error_code::success(); } error_code remove(const Twine &path, bool &existed) { @@ -225,7 +225,7 @@ error_code remove(const Twine &path, bool &existed) { } else existed = true; - return success; + return error_code::success(); } error_code rename(const Twine &from, const Twine &to) { @@ -247,7 +247,7 @@ error_code rename(const Twine &from, const Twine &to) { return error_code(errno, system_category()); } - return success; + return error_code::success(); } error_code resize_file(const Twine &path, uint64_t size) { @@ -257,7 +257,7 @@ error_code resize_file(const Twine &path, uint64_t size) { if (::truncate(p.begin(), size) == -1) return error_code(errno, system_category()); - return success; + return error_code::success(); } error_code exists(const Twine &path, bool &result) { @@ -272,7 +272,7 @@ error_code exists(const Twine &path, bool &result) { } else result = true; - return success; + return error_code::success(); } bool equivalent(file_status A, file_status B) { @@ -286,7 +286,7 @@ error_code equivalent(const Twine &A, const Twine &B, bool &result) { if (error_code ec = status(A, fsA)) return ec; if (error_code ec = status(B, fsB)) return ec; result = equivalent(fsA, fsB); - return success; + return error_code::success(); } error_code file_size(const Twine &path, uint64_t &result) { @@ -300,7 +300,7 @@ error_code file_size(const Twine &path, uint64_t &result) { return make_error_code(errc::operation_not_permitted); result = status.st_size; - return success; + return error_code::success(); } error_code status(const Twine &path, file_status &result) { @@ -335,7 +335,7 @@ error_code status(const Twine &path, file_status &result) { result.st_dev = status.st_dev; result.st_ino = status.st_ino; - return success; + return error_code::success(); } error_code unique_file(const Twine &model, int &result_fd, @@ -430,7 +430,7 @@ rety_open_create: result_path.append(d.begin(), d.end()); result_fd = RandomFD; - return success; + return error_code::success(); } error_code detail::directory_iterator_construct(detail::DirIterState &it, @@ -452,7 +452,7 @@ error_code detail::directory_iterator_destruct(detail::DirIterState &it) { ::closedir(reinterpret_cast<DIR *>(it.IterationHandle)); it.IterationHandle = 0; it.CurrentEntry = directory_entry(); - return success; + return error_code::success(); } error_code detail::directory_iterator_increment(detail::DirIterState &it) { @@ -469,7 +469,7 @@ error_code detail::directory_iterator_increment(detail::DirIterState &it) { } else return directory_iterator_destruct(it); - return success; + return error_code::success(); } error_code get_magic(const Twine &path, uint32_t len, @@ -500,7 +500,7 @@ error_code get_magic(const Twine &path, uint32_t len, } std::fclose(file); result.set_size(len); - return success; + return error_code::success(); } } // end namespace fs diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index da440fd..5cdb11c 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -293,7 +293,3 @@ const char *Process::OutputBold(bool bg) { const char *Process::ResetColor() { return "\033[0m"; } - -void Process::SetWorkingDirectory(std::string Path) { - ::chdir(Path.c_str()); -} diff --git a/lib/Support/Unix/Signals.inc b/lib/Support/Unix/Signals.inc index e286869..75b91ea 100644 --- a/lib/Support/Unix/Signals.inc +++ b/lib/Support/Unix/Signals.inc @@ -30,6 +30,10 @@ #include <dlfcn.h> #include <cxxabi.h> #endif +#if HAVE_MACH_MACH_H +#include <mach/mach.h> +#endif + using namespace llvm; static RETSIGTYPE SignalHandler(int Sig); // defined below. @@ -261,6 +265,22 @@ static void PrintStackTrace(void *) { /// SIGSEGV) is delivered to the process, print a stack trace and then exit. void llvm::sys::PrintStackTraceOnErrorSignal() { AddSignalHandler(PrintStackTrace, 0); + +#if defined(__APPLE__) + // Environment variable to disable any kind of crash dialog. + if (getenv("LLVM_DISABLE_CRASH_REPORT")) { + mach_port_t self = mach_task_self(); + + exception_mask_t mask = EXC_MASK_CRASH; + + kern_return_t ret = task_set_exception_ports(self, + mask, + NULL, + EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, + NULL); + (void)ret; + } +#endif } diff --git a/lib/Support/Windows/PathV2.inc b/lib/Support/Windows/PathV2.inc index 7ca33c0..e9ce5d9 100644 --- a/lib/Support/Windows/PathV2.inc +++ b/lib/Support/Windows/PathV2.inc @@ -62,7 +62,7 @@ namespace { utf16.push_back(0); utf16.pop_back(); - return success; + return error_code::success(); } error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, @@ -92,7 +92,7 @@ namespace { utf8.push_back(0); utf8.pop_back(); - return success; + return error_code::success(); } error_code TempDir(SmallVectorImpl<wchar_t> &result) { @@ -108,7 +108,7 @@ namespace { } result.set_size(len); - return success; + return error_code::success(); } bool is_separator(const wchar_t value) { @@ -167,7 +167,7 @@ retry_cur_dir: if (len == 0) return windows_error(::GetLastError()); - return success; + return error_code::success(); } error_code copy_file(const Twine &from, const Twine &to, copy_option copt) { @@ -190,7 +190,7 @@ error_code copy_file(const Twine &from, const Twine &to, copy_option copt) { if (res == 0) return windows_error(::GetLastError()); - return success; + return error_code::success(); } error_code create_directory(const Twine &path, bool &existed) { @@ -210,7 +210,7 @@ error_code create_directory(const Twine &path, bool &existed) { } else existed = false; - return success; + return error_code::success(); } error_code create_hard_link(const Twine &to, const Twine &from) { @@ -229,7 +229,7 @@ error_code create_hard_link(const Twine &to, const Twine &from) { if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL)) return windows_error(::GetLastError()); - return success; + return error_code::success(); } error_code create_symlink(const Twine &to, const Twine &from) { @@ -252,7 +252,7 @@ error_code create_symlink(const Twine &to, const Twine &from) { if (!create_symbolic_link_api(wide_from.begin(), wide_to.begin(), 0)) return windows_error(::GetLastError()); - return success; + return error_code::success(); } error_code remove(const Twine &path, bool &existed) { @@ -285,7 +285,7 @@ error_code remove(const Twine &path, bool &existed) { existed = true; } - return success; + return error_code::success(); } error_code rename(const Twine &from, const Twine &to) { @@ -305,7 +305,7 @@ error_code rename(const Twine &from, const Twine &to) { MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) return windows_error(::GetLastError()); - return success; + return error_code::success(); } error_code resize_file(const Twine &path, uint64_t size) { @@ -347,7 +347,7 @@ error_code exists(const Twine &path, bool &result) { result = false; } else result = true; - return success; + return error_code::success(); } bool equivalent(file_status A, file_status B) { @@ -366,7 +366,7 @@ error_code equivalent(const Twine &A, const Twine &B, bool &result) { if (error_code ec = status(A, fsA)) return ec; if (error_code ec = status(B, fsB)) return ec; result = equivalent(fsA, fsB); - return success; + return error_code::success(); } error_code file_size(const Twine &path, uint64_t &result) { @@ -387,7 +387,7 @@ error_code file_size(const Twine &path, uint64_t &result) { (uint64_t(FileData.nFileSizeHigh) << (sizeof(FileData.nFileSizeLow) * 8)) + FileData.nFileSizeLow; - return success; + return error_code::success(); } static bool isReservedName(StringRef path) { @@ -420,7 +420,7 @@ error_code status(const Twine &path, file_status &result) { StringRef path8 = path.toStringRef(path_storage); if (isReservedName(path8)) { result = file_status(file_type::character_file); - return success; + return error_code::success(); } if (error_code ec = UTF8ToUTF16(path8, path_utf16)) @@ -470,7 +470,7 @@ error_code status(const Twine &path, file_status &result) { result.VolumeSerialNumber = Info.dwVolumeSerialNumber; } - return success; + return error_code::success(); handle_status_error: error_code ec = windows_error(::GetLastError()); @@ -484,7 +484,7 @@ handle_status_error: return ec; } - return success; + return error_code::success(); } error_code unique_file(const Twine &model, int &result_fd, @@ -611,7 +611,7 @@ retry_create_file: } result_fd = fd; - return success; + return error_code::success(); } error_code get_magic(const Twine &path, uint32_t len, @@ -653,7 +653,7 @@ error_code get_magic(const Twine &path, uint32_t len, } result.set_size(len); - return success; + return error_code::success(); } error_code detail::directory_iterator_construct(detail::DirIterState &it, @@ -705,7 +705,7 @@ error_code detail::directory_iterator_construct(detail::DirIterState &it, path::append(directory_entry_path, directory_entry_name_utf8.str()); it.CurrentEntry = directory_entry(directory_entry_path.str()); - return success; + return error_code::success(); } error_code detail::directory_iterator_destruct(detail::DirIterState &it) { @@ -714,7 +714,7 @@ error_code detail::directory_iterator_destruct(detail::DirIterState &it) { ScopedFindHandle close(HANDLE(it.IterationHandle)); it.IterationHandle = 0; it.CurrentEntry = directory_entry(); - return success; + return error_code::success(); } error_code detail::directory_iterator_increment(detail::DirIterState &it) { @@ -740,7 +740,7 @@ error_code detail::directory_iterator_increment(detail::DirIterState &it) { return ec; it.CurrentEntry.replace_filename(Twine(directory_entry_path_utf8)); - return success; + return error_code::success(); } } // end namespace fs diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc index fe54eb1..913b073 100644 --- a/lib/Support/Windows/Process.inc +++ b/lib/Support/Windows/Process.inc @@ -220,8 +220,4 @@ const char *Process::ResetColor() { return 0; } -void Process::SetWorkingDirectory(std::string Path) { - ::_chdir(Path.c_str()); -} - } diff --git a/lib/Support/Windows/Signals.inc b/lib/Support/Windows/Signals.inc index 3a7e90b..38308f6 100644 --- a/lib/Support/Windows/Signals.inc +++ b/lib/Support/Windows/Signals.inc @@ -239,7 +239,7 @@ static void RegisterHandler() { SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); // Environment variable to disable any kind of crash dialog. - if (getenv("LLVM_DISABLE_CRT_DEBUG")) { + if (getenv("LLVM_DISABLE_CRASH_REPORT")) { #ifdef _MSC_VER _CrtSetReportHook(CRTReportHook); #endif |