diff options
Diffstat (limited to 'lib/Support')
59 files changed, 1849 insertions, 677 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index f143e6d..0e3c619 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -19,8 +19,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" -#include <limits.h> #include <cstring> +#include <limits.h> using namespace llvm; @@ -46,22 +46,27 @@ namespace llvm { /* Number of bits in the significand. This includes the integer bit. */ unsigned int precision; - - /* True if arithmetic is supported. */ - unsigned int arithmeticOK; }; - const fltSemantics APFloat::IEEEhalf = { 15, -14, 11, true }; - const fltSemantics APFloat::IEEEsingle = { 127, -126, 24, true }; - const fltSemantics APFloat::IEEEdouble = { 1023, -1022, 53, true }; - const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, true }; - const fltSemantics APFloat::x87DoubleExtended = { 16383, -16382, 64, true }; - const fltSemantics APFloat::Bogus = { 0, 0, 0, true }; - - // The PowerPC format consists of two doubles. It does not map cleanly - // onto the usual format above. For now only storage of constants of - // this type is supported, no arithmetic. - const fltSemantics APFloat::PPCDoubleDouble = { 1023, -1022, 106, false }; + const fltSemantics APFloat::IEEEhalf = { 15, -14, 11 }; + const fltSemantics APFloat::IEEEsingle = { 127, -126, 24 }; + const fltSemantics APFloat::IEEEdouble = { 1023, -1022, 53 }; + const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113 }; + const fltSemantics APFloat::x87DoubleExtended = { 16383, -16382, 64 }; + const fltSemantics APFloat::Bogus = { 0, 0, 0 }; + + /* The PowerPC format consists of two doubles. It does not map cleanly + onto the usual format above. It is approximated using twice the + mantissa bits. Note that for exponents near the double minimum, + we no longer can represent the full 106 mantissa bits, so those + will be treated as denormal numbers. + + FIXME: While this approximation is equivalent to what GCC uses for + compile-time arithmetic on PPC double-double numbers, it is not able + to represent all possible values held by a PPC double-double number, + for example: (long double) 1.0 + (long double) 0x1p-106 + Should this be replaced by a full emulation of PPC double-double? */ + const fltSemantics APFloat::PPCDoubleDouble = { 1023, -1022 + 53, 53 + 53 }; /* A tight upper bound on number of parts required to hold the value pow(5, power) is @@ -116,12 +121,6 @@ hexDigitValue(unsigned int c) return -1U; } -static inline void -assertArithmeticOK(const llvm::fltSemantics &semantics) { - assert(semantics.arithmeticOK && - "Compile-time arithmetic does not support these semantics"); -} - /* Return the value of a decimal exponent of the form [+-]ddddddd. @@ -612,8 +611,6 @@ APFloat::assign(const APFloat &rhs) sign = rhs.sign; category = rhs.category; exponent = rhs.exponent; - sign2 = rhs.sign2; - exponent2 = rhs.exponent2; if (category == fcNormal || category == fcNaN) copySignificand(rhs); } @@ -700,6 +697,13 @@ APFloat::operator=(const APFloat &rhs) } bool +APFloat::isDenormal() const { + return isNormal() && (exponent == semantics->minExponent) && + (APInt::tcExtractBit(significandParts(), + semantics->precision - 1) == 0); +} + +bool APFloat::bitwiseIsEqual(const APFloat &rhs) const { if (this == &rhs) return true; @@ -707,16 +711,10 @@ APFloat::bitwiseIsEqual(const APFloat &rhs) const { category != rhs.category || sign != rhs.sign) return false; - if (semantics==(const llvm::fltSemantics*)&PPCDoubleDouble && - sign2 != rhs.sign2) - return false; if (category==fcZero || category==fcInfinity) return true; else if (category==fcNormal && exponent!=rhs.exponent) return false; - else if (semantics==(const llvm::fltSemantics*)&PPCDoubleDouble && - exponent2!=rhs.exponent2) - return false; else { int i= partCount(); const integerPart* p=significandParts(); @@ -729,9 +727,7 @@ APFloat::bitwiseIsEqual(const APFloat &rhs) const { } } -APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) - : exponent2(0), sign2(0) { - assertArithmeticOK(ourSemantics); +APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) { initialize(&ourSemantics); sign = 0; zeroSignificand(); @@ -740,24 +736,19 @@ APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) normalize(rmNearestTiesToEven, lfExactlyZero); } -APFloat::APFloat(const fltSemantics &ourSemantics) : exponent2(0), sign2(0) { - assertArithmeticOK(ourSemantics); +APFloat::APFloat(const fltSemantics &ourSemantics) { initialize(&ourSemantics); category = fcZero; sign = false; } -APFloat::APFloat(const fltSemantics &ourSemantics, uninitializedTag tag) - : exponent2(0), sign2(0) { - assertArithmeticOK(ourSemantics); +APFloat::APFloat(const fltSemantics &ourSemantics, uninitializedTag tag) { // Allocates storage if necessary but does not initialize it. initialize(&ourSemantics); } APFloat::APFloat(const fltSemantics &ourSemantics, - fltCategory ourCategory, bool negative) - : exponent2(0), sign2(0) { - assertArithmeticOK(ourSemantics); + fltCategory ourCategory, bool negative) { initialize(&ourSemantics); category = ourCategory; sign = negative; @@ -767,14 +758,12 @@ APFloat::APFloat(const fltSemantics &ourSemantics, makeNaN(); } -APFloat::APFloat(const fltSemantics &ourSemantics, StringRef text) - : exponent2(0), sign2(0) { - assertArithmeticOK(ourSemantics); +APFloat::APFloat(const fltSemantics &ourSemantics, StringRef text) { initialize(&ourSemantics); convertFromString(text, rmNearestTiesToEven); } -APFloat::APFloat(const APFloat &rhs) : exponent2(0), sign2(0) { +APFloat::APFloat(const APFloat &rhs) { initialize(rhs.semantics); assign(rhs); } @@ -1561,8 +1550,6 @@ APFloat::addOrSubtract(const APFloat &rhs, roundingMode rounding_mode, { opStatus fs; - assertArithmeticOK(*semantics); - fs = addOrSubtractSpecials(rhs, subtract); /* This return code means it was not a simple case. */ @@ -1607,7 +1594,6 @@ APFloat::multiply(const APFloat &rhs, roundingMode rounding_mode) { opStatus fs; - assertArithmeticOK(*semantics); sign ^= rhs.sign; fs = multiplySpecials(rhs); @@ -1627,7 +1613,6 @@ APFloat::divide(const APFloat &rhs, roundingMode rounding_mode) { opStatus fs; - assertArithmeticOK(*semantics); sign ^= rhs.sign; fs = divideSpecials(rhs); @@ -1649,7 +1634,6 @@ APFloat::remainder(const APFloat &rhs) APFloat V = *this; unsigned int origSign = sign; - assertArithmeticOK(*semantics); fs = V.divide(rhs, rmNearestTiesToEven); if (fs == opDivByZero) return fs; @@ -1684,7 +1668,6 @@ APFloat::opStatus APFloat::mod(const APFloat &rhs, roundingMode rounding_mode) { opStatus fs; - assertArithmeticOK(*semantics); fs = modSpecials(rhs); if (category == fcNormal && rhs.category == fcNormal) { @@ -1728,8 +1711,6 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand, { opStatus fs; - assertArithmeticOK(*semantics); - /* Post-multiplication sign, before addition. */ sign ^= multiplicand.sign; @@ -1770,12 +1751,11 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand, /* Rounding-mode corrrect round to integral value. */ APFloat::opStatus APFloat::roundToIntegral(roundingMode rounding_mode) { opStatus fs; - assertArithmeticOK(*semantics); // If the exponent is large enough, we know that this value is already // integral, and the arithmetic below would potentially cause it to saturate // to +/-Inf. Bail out early instead. - if (exponent+1 >= (int)semanticsPrecision(*semantics)) + if (category == fcNormal && exponent+1 >= (int)semanticsPrecision(*semantics)) return opOK; // The algorithm here is quite simple: we add 2^(p-1), where p is the @@ -1817,7 +1797,6 @@ APFloat::compare(const APFloat &rhs) const { cmpResult result; - assertArithmeticOK(*semantics); assert(semantics == rhs.semantics); switch (convolve(category, rhs.category)) { @@ -1902,8 +1881,6 @@ APFloat::convert(const fltSemantics &toSemantics, int shift; const fltSemantics &fromSemantics = *semantics; - assertArithmeticOK(fromSemantics); - assertArithmeticOK(toSemantics); lostFraction = lfExactlyZero; newPartCount = partCountForBits(toSemantics.precision + 1); oldPartCount = partCount(); @@ -1988,8 +1965,6 @@ APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width, const integerPart *src; unsigned int dstPartsCount, truncatedBits; - assertArithmeticOK(*semantics); - *isExact = false; /* Handle the three special cases first. */ @@ -2151,7 +2126,6 @@ APFloat::convertFromUnsignedParts(const integerPart *src, integerPart *dst; lostFraction lost_fraction; - assertArithmeticOK(*semantics); category = fcNormal; omsb = APInt::tcMSB(src, srcCount) + 1; dst = significandParts(); @@ -2202,7 +2176,6 @@ APFloat::convertFromSignExtendedInteger(const integerPart *src, { opStatus status; - assertArithmeticOK(*semantics); if (isSigned && APInt::tcExtractBit(src, srcCount * integerPartWidth - 1)) { integerPart *copy; @@ -2336,7 +2309,7 @@ APFloat::roundSignificandWithExponent(const integerPart *decSigParts, roundingMode rounding_mode) { unsigned int parts, pow5PartCount; - fltSemantics calcSemantics = { 32767, -32767, 0, true }; + fltSemantics calcSemantics = { 32767, -32767, 0 }; integerPart pow5Parts[maxPowerOfFiveParts]; bool isNearest; @@ -2528,7 +2501,6 @@ APFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) APFloat::opStatus APFloat::convertFromString(StringRef str, roundingMode rounding_mode) { - assertArithmeticOK(*semantics); assert(!str.empty() && "Invalid string length"); /* Handle a leading minus sign. */ @@ -2580,8 +2552,6 @@ APFloat::convertToHexString(char *dst, unsigned int hexDigits, { char *p; - assertArithmeticOK(*semantics); - p = dst; if (sign) *dst++ = '-'; @@ -2790,42 +2760,48 @@ APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const assert(semantics == (const llvm::fltSemantics*)&PPCDoubleDouble); assert(partCount()==2); - uint64_t myexponent, mysignificand, myexponent2, mysignificand2; - - if (category==fcNormal) { - myexponent = exponent + 1023; //bias - myexponent2 = exponent2 + 1023; - mysignificand = significandParts()[0]; - mysignificand2 = significandParts()[1]; - if (myexponent==1 && !(mysignificand & 0x10000000000000LL)) - myexponent = 0; // denormal - if (myexponent2==1 && !(mysignificand2 & 0x10000000000000LL)) - myexponent2 = 0; // denormal - } else if (category==fcZero) { - myexponent = 0; - mysignificand = 0; - myexponent2 = 0; - mysignificand2 = 0; - } else if (category==fcInfinity) { - myexponent = 0x7ff; - myexponent2 = 0; - mysignificand = 0; - mysignificand2 = 0; + uint64_t words[2]; + opStatus fs; + bool losesInfo; + + // Convert number to double. To avoid spurious underflows, we re- + // normalize against the "double" minExponent first, and only *then* + // truncate the mantissa. The result of that second conversion + // may be inexact, but should never underflow. + // Declare fltSemantics before APFloat that uses it (and + // saves pointer to it) to ensure correct destruction order. + fltSemantics extendedSemantics = *semantics; + extendedSemantics.minExponent = IEEEdouble.minExponent; + APFloat extended(*this); + fs = extended.convert(extendedSemantics, rmNearestTiesToEven, &losesInfo); + assert(fs == opOK && !losesInfo); + (void)fs; + + APFloat u(extended); + fs = u.convert(IEEEdouble, rmNearestTiesToEven, &losesInfo); + assert(fs == opOK || fs == opInexact); + (void)fs; + words[0] = *u.convertDoubleAPFloatToAPInt().getRawData(); + + // If conversion was exact or resulted in a special case, we're done; + // just set the second double to zero. Otherwise, re-convert back to + // the extended format and compute the difference. This now should + // convert exactly to double. + if (u.category == fcNormal && losesInfo) { + fs = u.convert(extendedSemantics, rmNearestTiesToEven, &losesInfo); + assert(fs == opOK && !losesInfo); + (void)fs; + + APFloat v(extended); + v.subtract(u, rmNearestTiesToEven); + fs = v.convert(IEEEdouble, rmNearestTiesToEven, &losesInfo); + assert(fs == opOK && !losesInfo); + (void)fs; + words[1] = *v.convertDoubleAPFloatToAPInt().getRawData(); } else { - assert(category == fcNaN && "Unknown category"); - myexponent = 0x7ff; - mysignificand = significandParts()[0]; - myexponent2 = exponent2; - mysignificand2 = significandParts()[1]; + words[1] = 0; } - uint64_t words[2]; - words[0] = ((uint64_t)(sign & 1) << 63) | - ((myexponent & 0x7ff) << 52) | - (mysignificand & 0xfffffffffffffLL); - words[1] = ((uint64_t)(sign2 & 1) << 63) | - ((myexponent2 & 0x7ff) << 52) | - (mysignificand2 & 0xfffffffffffffLL); return APInt(128, words); } @@ -3045,47 +3021,23 @@ APFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) assert(api.getBitWidth()==128); uint64_t i1 = api.getRawData()[0]; uint64_t i2 = api.getRawData()[1]; - uint64_t myexponent = (i1 >> 52) & 0x7ff; - uint64_t mysignificand = i1 & 0xfffffffffffffLL; - uint64_t myexponent2 = (i2 >> 52) & 0x7ff; - uint64_t mysignificand2 = i2 & 0xfffffffffffffLL; + opStatus fs; + bool losesInfo; - initialize(&APFloat::PPCDoubleDouble); - assert(partCount()==2); + // Get the first double and convert to our format. + initFromDoubleAPInt(APInt(64, i1)); + fs = convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo); + assert(fs == opOK && !losesInfo); + (void)fs; - sign = static_cast<unsigned int>(i1>>63); - sign2 = static_cast<unsigned int>(i2>>63); - if (myexponent==0 && mysignificand==0) { - // exponent, significand meaningless - // exponent2 and significand2 are required to be 0; we don't check - category = fcZero; - } else if (myexponent==0x7ff && mysignificand==0) { - // exponent, significand meaningless - // exponent2 and significand2 are required to be 0; we don't check - category = fcInfinity; - } else if (myexponent==0x7ff && mysignificand!=0) { - // exponent meaningless. So is the whole second word, but keep it - // for determinism. - category = fcNaN; - exponent2 = myexponent2; - significandParts()[0] = mysignificand; - significandParts()[1] = mysignificand2; - } else { - category = fcNormal; - // Note there is no category2; the second word is treated as if it is - // fcNormal, although it might be something else considered by itself. - exponent = myexponent - 1023; - exponent2 = myexponent2 - 1023; - significandParts()[0] = mysignificand; - significandParts()[1] = mysignificand2; - if (myexponent==0) // denormal - exponent = -1022; - else - significandParts()[0] |= 0x10000000000000LL; // integer bit - if (myexponent2==0) - exponent2 = -1022; - else - significandParts()[1] |= 0x10000000000000LL; // integer bit + // Unless we have a special case, add in second double. + if (category == fcNormal) { + APFloat v(APInt(64, i2)); + fs = v.convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo); + assert(fs == opOK && !losesInfo); + (void)fs; + + add(v, rmNearestTiesToEven); } } @@ -3311,15 +3263,15 @@ APFloat APFloat::getSmallestNormalized(const fltSemantics &Sem, bool Negative) { return Val; } -APFloat::APFloat(const APInt& api, bool isIEEE) : exponent2(0), sign2(0) { +APFloat::APFloat(const APInt& api, bool isIEEE) { initFromAPInt(api, isIEEE); } -APFloat::APFloat(float f) : exponent2(0), sign2(0) { +APFloat::APFloat(float f) { initFromAPInt(APInt::floatToBits(f)); } -APFloat::APFloat(double d) : exponent2(0), sign2(0) { +APFloat::APFloat(double d) { initFromAPInt(APInt::doubleToBits(d)); } @@ -3610,11 +3562,6 @@ void APFloat::toString(SmallVectorImpl<char> &Str, } bool APFloat::getExactInverse(APFloat *inv) const { - // We can only guarantee the existence of an exact inverse for IEEE floats. - if (semantics != &IEEEhalf && semantics != &IEEEsingle && - semantics != &IEEEdouble && semantics != &IEEEquad) - return false; - // Special floats and denormals have no exact inverse. if (category != fcNormal) return false; diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index 38cfaed..61e503b 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -23,9 +23,9 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include <cmath> -#include <limits> -#include <cstring> #include <cstdlib> +#include <cstring> +#include <limits> using namespace llvm; /// A utility function for allocating memory, checking for allocation failures, diff --git a/lib/Support/Allocator.cpp b/lib/Support/Allocator.cpp index b897830..28f4e64 100644 --- a/lib/Support/Allocator.cpp +++ b/lib/Support/Allocator.cpp @@ -13,9 +13,9 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Memory.h" #include "llvm/Support/Recycler.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Memory.h" #include <cstring> namespace llvm { diff --git a/lib/Support/Atomic.cpp b/lib/Support/Atomic.cpp index 58497b9..13d16d4 100644 --- a/lib/Support/Atomic.cpp +++ b/lib/Support/Atomic.cpp @@ -24,11 +24,15 @@ using namespace llvm; #undef MemoryFence #endif +#if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210) +#define GNU_ATOMICS +#endif + void sys::MemoryFence() { #if LLVM_HAS_ATOMICS == 0 return; #else -# if defined(__GNUC__) +# if defined(GNU_ATOMICS) __sync_synchronize(); # elif defined(_MSC_VER) MemoryBarrier(); @@ -49,7 +53,7 @@ sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, #elif defined(ANDROID_TARGET_BUILD) return android_atomic_cmpxchg((int32_t)old_value, (int32_t)new_value, (volatile int*)ptr); -#elif defined(__GNUC__) +#elif defined(GNU_ATOMICS) return __sync_val_compare_and_swap(ptr, old_value, new_value); #elif defined(_MSC_VER) return InterlockedCompareExchange(ptr, new_value, old_value); @@ -64,7 +68,7 @@ sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) { return *ptr; #elif defined(ANDROID_TARGET_BUILD) return android_atomic_inc((volatile int*)ptr); -#elif defined(__GNUC__) +#elif defined(GNU_ATOMICS) return __sync_add_and_fetch(ptr, 1); #elif defined(_MSC_VER) return InterlockedIncrement(ptr); @@ -79,7 +83,7 @@ sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) { return *ptr; #elif defined(ANDROID_TARGET_BUILD) return android_atomic_dec((volatile int*)ptr); -#elif defined(__GNUC__) +#elif defined(GNU_ATOMICS) return __sync_sub_and_fetch(ptr, 1); #elif defined(_MSC_VER) return InterlockedDecrement(ptr); @@ -94,7 +98,7 @@ sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) { return *ptr; #elif defined(ANDROID_TARGET_BUILD) return android_atomic_add((int32_t)val, (volatile int*)ptr); -#elif defined(__GNUC__) +#elif defined(GNU_ATOMICS) return __sync_add_and_fetch(ptr, val); #elif defined(_MSC_VER) return InterlockedExchangeAdd(ptr, val) + val; diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt index 83baf60..f294a17 100644 --- a/lib/Support/CMakeLists.txt +++ b/lib/Support/CMakeLists.txt @@ -1,9 +1,3 @@ -## FIXME: This only requires RTTI because tblgen uses it. Fix that. -set(LLVM_REQUIRES_RTTI 1) -if( MINGW ) - set(LLVM_REQUIRES_EH 1) -endif() - add_llvm_library(LLVMSupport APFloat.cpp APInt.cpp @@ -56,6 +50,7 @@ add_llvm_library(LLVMSupport Triple.cpp Twine.cpp YAMLParser.cpp + YAMLTraits.cpp raw_os_ostream.cpp raw_ostream.cpp regcomp.c diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 593315d..53fcf06 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -17,20 +17,20 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/Path.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" #include <cerrno> #include <cstdlib> using namespace llvm; @@ -464,7 +464,7 @@ static void ParseCStringVector(std::vector<char *> &OutputVector, /// an environment variable (whose name is given in ENVVAR). /// void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, - const char *Overview, bool ReadResponseFiles) { + const char *Overview) { // Check args. assert(progName && "Program name not specified"); assert(envVar && "Environment variable name missing"); @@ -483,7 +483,7 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, // and hand it off to ParseCommandLineOptions(). ParseCStringVector(newArgv, envValue); int newArgc = static_cast<int>(newArgv.size()); - ParseCommandLineOptions(newArgc, &newArgv[0], Overview, ReadResponseFiles); + ParseCommandLineOptions(newArgc, &newArgv[0], Overview); // Free all the strdup()ed strings. for (std::vector<char*>::iterator i = newArgv.begin(), e = newArgv.end(); @@ -529,7 +529,7 @@ static void ExpandResponseFiles(unsigned argc, const char*const* argv, } void cl::ParseCommandLineOptions(int argc, const char * const *argv, - const char *Overview, bool ReadResponseFiles) { + const char *Overview) { // Process all registered options. SmallVector<Option*, 4> PositionalOpts; SmallVector<Option*, 4> SinkOpts; @@ -541,12 +541,10 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // Expand response files. std::vector<char*> newArgv; - if (ReadResponseFiles) { - newArgv.push_back(strdup(argv[0])); - ExpandResponseFiles(argc, argv, newArgv); - argv = &newArgv[0]; - argc = static_cast<int>(newArgv.size()); - } + newArgv.push_back(strdup(argv[0])); + ExpandResponseFiles(argc, argv, newArgv); + argv = &newArgv[0]; + argc = static_cast<int>(newArgv.size()); // Copy the program name into ProgName, making sure not to overflow it. std::string ProgName = sys::path::filename(argv[0]); @@ -839,12 +837,10 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, MoreHelp->clear(); // Free the memory allocated by ExpandResponseFiles. - if (ReadResponseFiles) { - // Free all the strdup()ed strings. - for (std::vector<char*>::iterator i = newArgv.begin(), e = newArgv.end(); - i != e; ++i) - free(*i); - } + // Free all the strdup()ed strings. + for (std::vector<char*>::iterator i = newArgv.begin(), e = newArgv.end(); + i != e; ++i) + free(*i); // If we had an error processing our arguments, don't let the program execute if (ErrorParsing) exit(1); diff --git a/lib/Support/ConstantRange.cpp b/lib/Support/ConstantRange.cpp index 720ef36..5c58950 100644 --- a/lib/Support/ConstantRange.cpp +++ b/lib/Support/ConstantRange.cpp @@ -21,7 +21,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/InstrTypes.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/Support/ConstantRange.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/Support/CrashRecoveryContext.cpp b/lib/Support/CrashRecoveryContext.cpp index e175056..182c362 100644 --- a/lib/Support/CrashRecoveryContext.cpp +++ b/lib/Support/CrashRecoveryContext.cpp @@ -10,11 +10,11 @@ #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/ADT/SmallString.h" #include "llvm/Config/config.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/ThreadLocal.h" -#include "llvm/Support/ErrorHandling.h" -#include <setjmp.h> #include <cstdio> +#include <setjmp.h> using namespace llvm; namespace { diff --git a/lib/Support/DAGDeltaAlgorithm.cpp b/lib/Support/DAGDeltaAlgorithm.cpp index 1e89c6a..34e82cf 100644 --- a/lib/Support/DAGDeltaAlgorithm.cpp +++ b/lib/Support/DAGDeltaAlgorithm.cpp @@ -122,7 +122,7 @@ private: DDA.UpdatedSearchState(Changes, Sets, Required); } - /// ExecuteOneTest - Execute a single test predicate on the change set \arg S. + /// ExecuteOneTest - Execute a single test predicate on the change set \p S. bool ExecuteOneTest(const changeset_ty &S) { // Check dependencies invariant. DEBUG({ @@ -143,8 +143,8 @@ public: changeset_ty Run(); - /// GetTestResult - Get the test result for the active set \arg Changes with - /// \arg Required changes from the cache, executing the test if necessary. + /// GetTestResult - Get the test result for the active set \p Changes with + /// \p Required changes from the cache, executing the test if necessary. /// /// \param Changes - The set of active changes being minimized, which should /// have their pred closure included in the test. @@ -163,11 +163,11 @@ class DeltaActiveSetHelper : public DeltaAlgorithm { protected: /// UpdatedSearchState - Callback used when the search state changes. virtual void UpdatedSearchState(const changeset_ty &Changes, - const changesetlist_ty &Sets) { + const changesetlist_ty &Sets) LLVM_OVERRIDE { DDAI.UpdatedSearchState(Changes, Sets, Required); } - virtual bool ExecuteOneTest(const changeset_ty &S) { + virtual bool ExecuteOneTest(const changeset_ty &S) LLVM_OVERRIDE { return DDAI.GetTestResult(S, Required); } diff --git a/lib/Support/DataStream.cpp b/lib/Support/DataStream.cpp index 94d14a5..0a02281 100644 --- a/lib/Support/DataStream.cpp +++ b/lib/Support/DataStream.cpp @@ -15,13 +15,13 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "Data-stream" -#include "llvm/ADT/Statistic.h" #include "llvm/Support/DataStream.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Support/Program.h" #include "llvm/Support/system_error.h" -#include <string> #include <cerrno> #include <cstdio> +#include <string> #if !defined(_MSC_VER) && !defined(__MINGW32__) #include <unistd.h> #else @@ -58,7 +58,7 @@ public: virtual ~DataFileStreamer() { close(Fd); } - virtual size_t GetBytes(unsigned char *buf, size_t len) { + virtual size_t GetBytes(unsigned char *buf, size_t len) LLVM_OVERRIDE { NumStreamFetches++; return read(Fd, buf, len); } diff --git a/lib/Support/Debug.cpp b/lib/Support/Debug.cpp index c8e8900..0c0f15e 100644 --- a/lib/Support/Debug.cpp +++ b/lib/Support/Debug.cpp @@ -23,10 +23,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/circular_raw_ostream.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/circular_raw_ostream.h" using namespace llvm; diff --git a/lib/Support/DeltaAlgorithm.cpp b/lib/Support/DeltaAlgorithm.cpp index 9e52874..a1e3311 100644 --- a/lib/Support/DeltaAlgorithm.cpp +++ b/lib/Support/DeltaAlgorithm.cpp @@ -27,13 +27,15 @@ bool DeltaAlgorithm::GetTestResult(const changeset_ty &Changes) { void DeltaAlgorithm::Split(const changeset_ty &S, changesetlist_ty &Res) { // FIXME: Allow clients to provide heuristics for improved splitting. + // Get the iterator to the middle. + unsigned N = S.size() / 2; + changeset_ty::iterator middle(S.begin()); + std::advance(middle, N); + + // Create each vector using the middle as the split. + changeset_ty LHS(S.begin(), middle); + changeset_ty RHS(middle, S.end()); - // FIXME: This is really slow. - changeset_ty LHS, RHS; - unsigned idx = 0, N = S.size() / 2; - for (changeset_ty::const_iterator it = S.begin(), - ie = S.end(); it != ie; ++it, ++idx) - ((idx < N) ? LHS : RHS).insert(*it); if (!LHS.empty()) Res.push_back(LHS); if (!RHS.empty()) diff --git a/lib/Support/Disassembler.cpp b/lib/Support/Disassembler.cpp index c6d73bc..b3244fa 100644 --- a/lib/Support/Disassembler.cpp +++ b/lib/Support/Disassembler.cpp @@ -12,13 +12,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Config/config.h" #include "llvm/Support/Disassembler.h" - +#include "llvm/Config/config.h" #include <cassert> #include <iomanip> -#include <string> #include <sstream> +#include <string> #if USE_UDIS86 #include <udis86.h> diff --git a/lib/Support/Dwarf.cpp b/lib/Support/Dwarf.cpp index 5c59a3e..615efb8 100644 --- a/lib/Support/Dwarf.cpp +++ b/lib/Support/Dwarf.cpp @@ -80,8 +80,6 @@ const char *llvm::dwarf::TagString(unsigned Tag) { case DW_TAG_hi_user: return "DW_TAG_hi_user"; case DW_TAG_auto_variable: return "DW_TAG_auto_variable"; case DW_TAG_arg_variable: return "DW_TAG_arg_variable"; - case DW_TAG_return_variable: return "DW_TAG_return_variable"; - case DW_TAG_vector_type: return "DW_TAG_vector_type"; case DW_TAG_rvalue_reference_type: return "DW_TAG_rvalue_reference_type"; case DW_TAG_template_alias: return "DW_TAG_template_alias"; case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; @@ -248,6 +246,14 @@ const char *llvm::dwarf::AttributeString(unsigned Attribute) { 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"; + + // DWARF5 Fission Extension Attribute + case DW_AT_GNU_dwo_name: return "DW_AT_GNU_dwo_name"; + case DW_AT_GNU_dwo_id: return "DW_AT_GNU_dwo_id"; + case DW_AT_GNU_ranges_base: return "DW_AT_GNU_ranges_base"; + case DW_AT_GNU_addr_base: return "DW_AT_GNU_addr_base"; + case DW_AT_GNU_pubnames: return "DW_AT_GNU_pubnames"; + case DW_AT_GNU_pubtypes: return "DW_AT_GNU_pubtypes"; } return 0; } @@ -281,6 +287,10 @@ const char *llvm::dwarf::FormEncodingString(unsigned Encoding) { case DW_FORM_exprloc: return "DW_FORM_exprloc"; case DW_FORM_flag_present: return "DW_FORM_flag_present"; case DW_FORM_ref_sig8: return "DW_FORM_ref_sig8"; + + // DWARF5 Fission Extension Forms + case DW_FORM_GNU_addr_index: return "DW_FORM_GNU_addr_index"; + case DW_FORM_GNU_str_index: return "DW_FORM_GNU_str_index"; } return 0; } @@ -445,6 +455,10 @@ const char *llvm::dwarf::OperationEncodingString(unsigned Encoding) { case DW_OP_stack_value: return "DW_OP_stack_value"; case DW_OP_lo_user: return "DW_OP_lo_user"; case DW_OP_hi_user: return "DW_OP_hi_user"; + + // DWARF5 Fission Proposal Op Extensions + case DW_OP_GNU_addr_index: return "DW_OP_GNU_addr_index"; + case DW_OP_GNU_const_index: return "DW_OP_GNU_const_index"; } return 0; } diff --git a/lib/Support/DynamicLibrary.cpp b/lib/Support/DynamicLibrary.cpp index 45fec36..d40439a 100644 --- a/lib/Support/DynamicLibrary.cpp +++ b/lib/Support/DynamicLibrary.cpp @@ -13,11 +13,11 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Mutex.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Config/config.h" +#include "llvm/Support/Mutex.h" #include <cstdio> #include <cstring> diff --git a/lib/Support/Errno.cpp b/lib/Support/Errno.cpp index dd218f6..730220f 100644 --- a/lib/Support/Errno.cpp +++ b/lib/Support/Errno.cpp @@ -13,6 +13,7 @@ #include "llvm/Support/Errno.h" #include "llvm/Config/config.h" // Get autoconf configuration settings +#include "llvm/Support/raw_ostream.h" #if HAVE_STRING_H #include <string.h> @@ -39,7 +40,7 @@ std::string StrError(int errnum) { const int MaxErrStrLen = 2000; char buffer[MaxErrStrLen]; buffer[0] = '\0'; - char* str = buffer; + std::string str; #ifdef HAVE_STRERROR_R // strerror_r is thread-safe. if (errnum) @@ -49,21 +50,25 @@ std::string StrError(int errnum) { str = strerror_r(errnum,buffer,MaxErrStrLen-1); # else strerror_r(errnum,buffer,MaxErrStrLen-1); + str = buffer; # endif #elif HAVE_DECL_STRERROR_S // "Windows Secure API" - if (errnum) + if (errnum) { strerror_s(buffer, MaxErrStrLen - 1, errnum); + str = buffer; + } #elif defined(HAVE_STRERROR) // Copy the thread un-safe result of strerror into // the buffer as fast as possible to minimize impact // of collision of strerror in multiple threads. if (errnum) - strncpy(buffer,strerror(errnum),MaxErrStrLen-1); - buffer[MaxErrStrLen-1] = '\0'; + str = strerror(errnum); #else // Strange that this system doesn't even have strerror // but, oh well, just use a generic message - sprintf(buffer, "Error #%d", errnum); + raw_string_ostream stream(str); + stream << "Error #" << errnum; + stream.flush(); #endif return str; } diff --git a/lib/Support/ErrorHandling.cpp b/lib/Support/ErrorHandling.cpp index e6cc57d..d4382e5 100644 --- a/lib/Support/ErrorHandling.cpp +++ b/lib/Support/ErrorHandling.cpp @@ -12,14 +12,14 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" +#include "llvm/Config/config.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" #include "llvm/Support/Threading.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Config/config.h" +#include "llvm/Support/raw_ostream.h" #include <cassert> #include <cstdlib> diff --git a/lib/Support/FileOutputBuffer.cpp b/lib/Support/FileOutputBuffer.cpp index 7dc9587..cd430f2 100644 --- a/lib/Support/FileOutputBuffer.cpp +++ b/lib/Support/FileOutputBuffer.cpp @@ -12,37 +12,28 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/FileOutputBuffer.h" - #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" +using llvm::sys::fs::mapped_file_region; namespace llvm { - - -FileOutputBuffer::FileOutputBuffer(uint8_t *Start, uint8_t *End, - StringRef Path, StringRef TmpPath) - : BufferStart(Start), BufferEnd(End) { - FinalPath.assign(Path); - TempPath.assign(TmpPath); +FileOutputBuffer::FileOutputBuffer(mapped_file_region * R, + StringRef Path, StringRef TmpPath) + : Region(R) + , FinalPath(Path) + , TempPath(TmpPath) { } - FileOutputBuffer::~FileOutputBuffer() { - // If not already commited, delete buffer and remove temp file. - if ( BufferStart != NULL ) { - sys::fs::unmap_file_pages((void*)BufferStart, getBufferSize()); - bool Existed; - sys::fs::remove(Twine(TempPath), Existed); - } + bool Existed; + sys::fs::remove(Twine(TempPath), Existed); } - -error_code FileOutputBuffer::create(StringRef FilePath, - size_t Size, +error_code FileOutputBuffer::create(StringRef FilePath, + size_t Size, OwningPtr<FileOutputBuffer> &Result, unsigned Flags) { // If file already exists, it must be a regular file (to be mappable). @@ -70,34 +61,27 @@ error_code FileOutputBuffer::create(StringRef FilePath, EC = sys::fs::remove(FilePath, Existed); if (EC) return EC; - + // Create new file in same directory but with random name. SmallString<128> TempFilePath; int FD; - EC = sys::fs::unique_file(Twine(FilePath) + ".tmp%%%%%%%", - FD, TempFilePath, false, 0644); + EC = sys::fs::unique_file(Twine(FilePath) + ".tmp%%%%%%%", + FD, TempFilePath, false, 0644); if (EC) return EC; - - // The unique_file() interface leaks lower layers and returns a file - // descriptor. There is no way to directly close it, so use this hack - // to hand it off to raw_fd_ostream to close for us. - { - raw_fd_ostream Dummy(FD, /*shouldClose=*/true); - } - - // Resize file to requested initial size - EC = sys::fs::resize_file(Twine(TempFilePath), Size); + + OwningPtr<mapped_file_region> MappedFile( + new mapped_file_region(FD, mapped_file_region::readwrite, Size, 0, EC)); if (EC) return EC; - + // If requested, make the output file executable. if ( Flags & F_executable ) { sys::fs::file_status Stat2; EC = sys::fs::status(Twine(TempFilePath), Stat2); if (EC) return EC; - + sys::fs::perms new_perms = Stat2.permissions(); if ( new_perms & sys::fs::owner_read ) new_perms |= sys::fs::owner_exe; @@ -111,38 +95,25 @@ error_code FileOutputBuffer::create(StringRef FilePath, return EC; } - // Memory map new file. - void *Base; - EC = sys::fs::map_file_pages(Twine(TempFilePath), 0, Size, true, Base); - if (EC) - return EC; - - // Create FileOutputBuffer object to own mapped range. - uint8_t *Start = reinterpret_cast<uint8_t*>(Base); - Result.reset(new FileOutputBuffer(Start, Start+Size, FilePath, TempFilePath)); - - return error_code::success(); -} + Result.reset(new FileOutputBuffer(MappedFile.get(), FilePath, TempFilePath)); + if (Result) + MappedFile.take(); + return error_code::success(); +} error_code FileOutputBuffer::commit(int64_t NewSmallerSize) { // Unmap buffer, letting OS flush dirty pages to file on disk. - void *Start = reinterpret_cast<void*>(BufferStart); - error_code EC = sys::fs::unmap_file_pages(Start, getBufferSize()); - if (EC) - return EC; - + Region.reset(0); + // If requested, resize file as part of commit. if ( NewSmallerSize != -1 ) { - EC = sys::fs::resize_file(Twine(TempPath), NewSmallerSize); + error_code EC = sys::fs::resize_file(Twine(TempPath), NewSmallerSize); if (EC) return EC; } - + // Rename file to final name. return sys::fs::rename(Twine(TempPath), Twine(FinalPath)); } - - } // namespace - diff --git a/lib/Support/FileUtilities.cpp b/lib/Support/FileUtilities.cpp index f9e9cf0..fc8a2f3 100644 --- a/lib/Support/FileUtilities.cpp +++ b/lib/Support/FileUtilities.cpp @@ -13,15 +13,15 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/FileUtilities.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/SmallString.h" +#include <cctype> #include <cstdlib> #include <cstring> -#include <cctype> using namespace llvm; static bool isSignedChar(char C) { diff --git a/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp index 4d489a8..36e33b5 100644 --- a/lib/Support/FoldingSet.cpp +++ b/lib/Support/FoldingSet.cpp @@ -8,9 +8,7 @@ //===----------------------------------------------------------------------===// // // This file implements a hash set that can be used to remove duplication of -// nodes in a graph. This code was originally created by Chris Lattner for use -// with SelectionDAGCSEMap, but was isolated to provide use across the llvm code -// set. +// nodes in a graph. // //===----------------------------------------------------------------------===// @@ -18,8 +16,8 @@ #include "llvm/ADT/Hashing.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/Host.h" +#include "llvm/Support/MathExtras.h" #include <cassert> #include <cstring> using namespace llvm; @@ -150,7 +148,7 @@ unsigned FoldingSetNodeID::ComputeHash() const { /// operator== - Used to compare two nodes to each other. /// -bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS)const{ +bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS) const { return *this == FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size()); } @@ -162,7 +160,7 @@ bool FoldingSetNodeID::operator==(FoldingSetNodeIDRef RHS) const { /// Used to compare the "ordering" of two nodes as defined by the /// profiled bits and their ordering defined by memcmp(). -bool FoldingSetNodeID::operator<(const FoldingSetNodeID &RHS)const{ +bool FoldingSetNodeID::operator<(const FoldingSetNodeID &RHS) const { return *this < FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size()); } diff --git a/lib/Support/GraphWriter.cpp b/lib/Support/GraphWriter.cpp index f6aaf83..669c238 100644 --- a/lib/Support/GraphWriter.cpp +++ b/lib/Support/GraphWriter.cpp @@ -11,11 +11,11 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/CommandLine.h" #include "llvm/Support/GraphWriter.h" +#include "llvm/Config/config.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" -#include "llvm/Config/config.h" using namespace llvm; static cl::opt<bool> ViewBackground("view-background", cl::Hidden, diff --git a/lib/Support/Host.cpp b/lib/Support/Host.cpp index 9a2c39d..5ad5308 100644 --- a/lib/Support/Host.cpp +++ b/lib/Support/Host.cpp @@ -11,14 +11,14 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Support/Host.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Config/config.h" #include "llvm/Support/DataStream.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/Host.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Config/config.h" #include <string.h> // Include the platform-specific parts of this class. @@ -234,6 +234,8 @@ std::string sys::getHostCPUName() { case 37: // Intel Core i7, laptop version. case 44: // Intel Core i7 processor and Intel Xeon processor. All // processors are manufactured using the 32 nm process. + case 46: // Nehalem EX + case 47: // Westmere EX return "corei7"; // SandyBridge: @@ -303,6 +305,7 @@ std::string sys::getHostCPUName() { case 8: return "k6-2"; case 9: case 13: return "k6-3"; + case 10: return "geode"; default: return "pentium"; } case 6: @@ -500,6 +503,7 @@ std::string sys::getHostCPUName() { .Case("0xb76", "arm1176jz-s") .Case("0xc08", "cortex-a8") .Case("0xc09", "cortex-a9") + .Case("0xc0f", "cortex-a15") .Case("0xc20", "cortex-m0") .Case("0xc23", "cortex-m3") .Case("0xc24", "cortex-m4") @@ -513,6 +517,64 @@ std::string sys::getHostCPUName() { } #endif +#if defined(__linux__) && defined(__arm__) +bool sys::getHostCPUFeatures(StringMap<bool> &Features) { + std::string Err; + DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err); + if (!DS) { + DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n"); + return false; + } + + // Read 1024 bytes from /proc/cpuinfo, which should contain the Features line + // in all cases. + char buffer[1024]; + size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer)); + delete DS; + + StringRef Str(buffer, CPUInfoSize); + + SmallVector<StringRef, 32> Lines; + Str.split(Lines, "\n"); + + // Look for the CPU implementer line. + StringRef Implementer; + for (unsigned I = 0, E = Lines.size(); I != E; ++I) + if (Lines[I].startswith("CPU implementer")) + Implementer = Lines[I].substr(15).ltrim("\t :"); + + if (Implementer == "0x41") { // ARM Ltd. + SmallVector<StringRef, 32> CPUFeatures; + + // Look for the CPU features. + for (unsigned I = 0, E = Lines.size(); I != E; ++I) + if (Lines[I].startswith("Features")) { + Lines[I].split(CPUFeatures, " "); + break; + } + + for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { + StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I]) + .Case("half", "fp16") + .Case("neon", "neon") + .Case("vfpv3", "vfp3") + .Case("vfpv3d16", "d16") + .Case("vfpv4", "vfp4") + .Case("idiva", "hwdiv-arm") + .Case("idivt", "hwdiv") + .Default(""); + + if (LLVMFeatureStr != "") + Features.GetOrCreateValue(LLVMFeatureStr).setValue(true); + } + + return true; + } + + return false; +} +#else bool sys::getHostCPUFeatures(StringMap<bool> &Features){ return false; } +#endif diff --git a/lib/Support/LocaleWindows.inc b/lib/Support/LocaleWindows.inc index 6827ac1..28e429c 100644 --- a/lib/Support/LocaleWindows.inc +++ b/lib/Support/LocaleWindows.inc @@ -12,4 +12,4 @@ bool isPrint(int c) { } } -}
\ No newline at end of file +} diff --git a/lib/Support/LocaleXlocale.inc b/lib/Support/LocaleXlocale.inc index f595e7c..389fe3d 100644 --- a/lib/Support/LocaleXlocale.inc +++ b/lib/Support/LocaleXlocale.inc @@ -1,5 +1,5 @@ -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/ManagedStatic.h" #include <cassert> #include <xlocale.h> diff --git a/lib/Support/LockFileManager.cpp b/lib/Support/LockFileManager.cpp index 59bfcfc..075d8a5 100644 --- a/lib/Support/LockFileManager.cpp +++ b/lib/Support/LockFileManager.cpp @@ -10,8 +10,8 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" #include <fstream> -#include <sys/types.h> #include <sys/stat.h> +#include <sys/types.h> #if LLVM_ON_WIN32 #include <windows.h> #endif diff --git a/lib/Support/Makefile b/lib/Support/Makefile index d68e500..4a2185d 100644 --- a/lib/Support/Makefile +++ b/lib/Support/Makefile @@ -11,9 +11,6 @@ LEVEL = ../.. LIBRARYNAME = LLVMSupport BUILD_ARCHIVE = 1 -## FIXME: This only requires RTTI because tblgen uses it. Fix that. -REQUIRES_RTTI = 1 - EXTRA_DIST = Unix Win32 README.txt include $(LEVEL)/Makefile.common diff --git a/lib/Support/Memory.cpp b/lib/Support/Memory.cpp index 8617365..f9a4903 100644 --- a/lib/Support/Memory.cpp +++ b/lib/Support/Memory.cpp @@ -13,16 +13,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Memory.h" -#include "llvm/Support/Valgrind.h" #include "llvm/Config/config.h" - -#if defined(__mips__) -#include <sys/cachectl.h> -#endif - -namespace llvm { -using namespace sys; -} +#include "llvm/Support/Valgrind.h" // Include the platform-specific parts of this class. #ifdef LLVM_ON_UNIX @@ -31,55 +23,3 @@ using namespace sys; #ifdef LLVM_ON_WIN32 #include "Windows/Memory.inc" #endif - -extern "C" void sys_icache_invalidate(const void *Addr, size_t len); - -/// InvalidateInstructionCache - Before the JIT can run a block of code -/// that has been emitted it must invalidate the instruction cache on some -/// platforms. -void llvm::sys::Memory::InvalidateInstructionCache(const void *Addr, - size_t Len) { - -// icache invalidation for PPC and ARM. -#if defined(__APPLE__) - -# if (defined(__POWERPC__) || defined (__ppc__) || \ - defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__) - sys_icache_invalidate(const_cast<void *>(Addr), Len); -# endif - -#else - -# if (defined(__POWERPC__) || defined (__ppc__) || \ - defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__) - const size_t LineSize = 32; - - const intptr_t Mask = ~(LineSize - 1); - const intptr_t StartLine = ((intptr_t) Addr) & Mask; - const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask; - - for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) - asm volatile("dcbf 0, %0" : : "r"(Line)); - asm volatile("sync"); - - for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) - asm volatile("icbi 0, %0" : : "r"(Line)); - asm volatile("isync"); -# elif defined(__arm__) && defined(__GNUC__) - // FIXME: Can we safely always call this for __GNUC__ everywhere? - const char *Start = static_cast<const char *>(Addr); - const char *End = Start + Len; - __clear_cache(const_cast<char *>(Start), const_cast<char *>(End)); -# elif defined(__mips__) && defined(ANDROID) - // NOTE: The declaration of "cacheflush" in bionic: - // extern int cacheflush(long start, long end, long flags); - cacheflush((long)Addr, (long)(Addr+Len), BCACHE); -# elif defined(__mips__) - const char *Start = static_cast<const char *>(Addr); - cacheflush(const_cast<char *>(Start), Len, BCACHE); -# endif - -#endif // end apple - - ValgrindDiscardTranslations(Addr, Len); -} diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp index 992f03c..65b4332 100644 --- a/lib/Support/MemoryBuffer.cpp +++ b/lib/Support/MemoryBuffer.cpp @@ -15,24 +15,27 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/Config/config.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include "llvm/Support/system_error.h" #include <cassert> +#include <cerrno> #include <cstdio> #include <cstring> -#include <cerrno> #include <new> -#include <sys/types.h> #include <sys/stat.h> +#include <sys/types.h> #if !defined(_MSC_VER) && !defined(__MINGW32__) #include <unistd.h> #else #include <io.h> +#ifndef S_ISFIFO +#define S_ISFIFO(x) (0) +#endif #endif #include <fcntl.h> using namespace llvm; @@ -81,12 +84,12 @@ public: init(InputData.begin(), InputData.end(), RequiresNullTerminator); } - virtual const char *getBufferIdentifier() const { + virtual const char *getBufferIdentifier() const LLVM_OVERRIDE { // The name is stored after the class itself. return reinterpret_cast<const char*>(this + 1); } - - virtual BufferKind getBufferKind() const { + + virtual BufferKind getBufferKind() const LLVM_OVERRIDE { return MemoryBuffer_Malloc; } }; @@ -184,7 +187,7 @@ public: : MemoryBufferMem(Buffer, RequiresNullTerminator) { } ~MemoryBufferMMapFile() { - static int PageSize = sys::Process::GetPageSize(); + static int PageSize = sys::process::get_self()->page_size(); uintptr_t Start = reinterpret_cast<uintptr_t>(getBufferStart()); size_t Size = getBufferSize(); @@ -194,13 +197,34 @@ public: sys::Path::UnMapFilePages(reinterpret_cast<const char*>(RealStart), RealSize); } - - virtual BufferKind getBufferKind() const { + + virtual BufferKind getBufferKind() const LLVM_OVERRIDE { return MemoryBuffer_MMap; } }; } +static error_code getMemoryBufferForStream(int FD, + StringRef BufferName, + OwningPtr<MemoryBuffer> &result) { + const ssize_t ChunkSize = 4096*4; + SmallString<ChunkSize> Buffer; + ssize_t ReadBytes; + // Read into Buffer until we hit EOF. + do { + Buffer.reserve(Buffer.size() + ChunkSize); + ReadBytes = read(FD, Buffer.end(), ChunkSize); + if (ReadBytes == -1) { + if (errno == EINTR) continue; + return error_code(errno, posix_category()); + } + Buffer.set_size(Buffer.size() + ReadBytes); + } while (ReadBytes != 0); + + result.reset(MemoryBuffer::getMemBufferCopy(Buffer, BufferName)); + return error_code::success(); +} + error_code MemoryBuffer::getFile(StringRef Filename, OwningPtr<MemoryBuffer> &result, int64_t FileSize, @@ -285,7 +309,7 @@ error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, uint64_t FileSize, uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator) { - static int PageSize = sys::Process::GetPageSize(); + static int PageSize = sys::process::get_self()->page_size(); // Default is to map the full file. if (MapSize == uint64_t(-1)) { @@ -297,6 +321,13 @@ error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, if (fstat(FD, &FileInfo) == -1) { return error_code(errno, posix_category()); } + + // If this is a named pipe, we can't trust the size. Create the memory + // buffer by copying off the stream. + if (S_ISFIFO(FileInfo.st_mode)) { + return getMemoryBufferForStream(FD, Filename, result); + } + FileSize = FileInfo.st_size; } MapSize = FileSize; @@ -370,20 +401,5 @@ error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) { // fallback if it fails. sys::Program::ChangeStdinToBinary(); - const ssize_t ChunkSize = 4096*4; - SmallString<ChunkSize> Buffer; - ssize_t ReadBytes; - // Read into Buffer until we hit EOF. - do { - Buffer.reserve(Buffer.size() + ChunkSize); - ReadBytes = read(0, Buffer.end(), ChunkSize); - if (ReadBytes == -1) { - if (errno == EINTR) continue; - return error_code(errno, posix_category()); - } - Buffer.set_size(Buffer.size() + ReadBytes); - } while (ReadBytes != 0); - - result.reset(getMemBufferCopy(Buffer, "<stdin>")); - return error_code::success(); + return getMemoryBufferForStream(0, "<stdin>", result); } diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp index db4a56b..d070375 100644 --- a/lib/Support/Path.cpp +++ b/lib/Support/Path.cpp @@ -12,10 +12,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Path.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Config/config.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/FileSystem.h" #include <cassert> #include <cstring> #include <ostream> diff --git a/lib/Support/PathV2.cpp b/lib/Support/PathV2.cpp index 46571c0..98d7382 100644 --- a/lib/Support/PathV2.cpp +++ b/lib/Support/PathV2.cpp @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/PathV2.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" #include <cctype> #include <cstdio> #include <cstring> diff --git a/lib/Support/PluginLoader.cpp b/lib/Support/PluginLoader.cpp index 2924cfa..358137f 100644 --- a/lib/Support/PluginLoader.cpp +++ b/lib/Support/PluginLoader.cpp @@ -12,11 +12,11 @@ //===----------------------------------------------------------------------===// #define DONT_GET_PLUGIN_LOADER_OPTION -#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PluginLoader.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" +#include "llvm/Support/raw_ostream.h" #include <vector> using namespace llvm; diff --git a/lib/Support/PrettyStackTrace.cpp b/lib/Support/PrettyStackTrace.cpp index ef33073..21d56ad 100644 --- a/lib/Support/PrettyStackTrace.cpp +++ b/lib/Support/PrettyStackTrace.cpp @@ -12,12 +12,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Config/config.h" // Get autoconf configuration settings #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Config/config.h" // Get autoconf configuration settings #include "llvm/Support/Signals.h" #include "llvm/Support/ThreadLocal.h" -#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" #ifdef HAVE_CRASHREPORTERCLIENT_H #include <CrashReporterClient.h> diff --git a/lib/Support/Process.cpp b/lib/Support/Process.cpp index 88ca7c3..2c0d37b 100644 --- a/lib/Support/Process.cpp +++ b/lib/Support/Process.cpp @@ -11,10 +11,11 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/Process.h" #include "llvm/Config/config.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Process.h" -namespace llvm { +using namespace llvm; using namespace sys; //===----------------------------------------------------------------------===// @@ -22,8 +23,63 @@ using namespace sys; //=== independent code. //===----------------------------------------------------------------------===// +// Empty virtual destructor to anchor the vtable for the process class. +process::~process() {} + +self_process *process::get_self() { + // Use a function local static for thread safe initialization and allocate it + // as a raw pointer to ensure it is never destroyed. + static self_process *SP = new self_process(); + + return SP; } +#if defined(_MSC_VER) +// Visual Studio complains that the self_process destructor never exits. This +// doesn't make much sense, as that's the whole point of calling abort... Just +// silence this warning. +#pragma warning(push) +#pragma warning(disable:4722) +#endif + +// The destructor for the self_process subclass must never actually be +// executed. There should be at most one instance of this class, and that +// instance should live until the process terminates to avoid the potential for +// racy accesses during shutdown. +self_process::~self_process() { + llvm_unreachable("This destructor must never be executed!"); +} + +/// \brief A helper function to compute the elapsed wall-time since the program +/// started. +/// +/// Note that this routine actually computes the elapsed wall time since the +/// first time it was called. However, we arrange to have it called during the +/// startup of the process to get approximately correct results. +static TimeValue getElapsedWallTime() { + static TimeValue &StartTime = *new TimeValue(TimeValue::now()); + return TimeValue::now() - StartTime; +} + +/// \brief A special global variable to ensure we call \c getElapsedWallTime +/// during global initialization of the program. +/// +/// Note that this variable is never referenced elsewhere. Doing so could +/// create race conditions during program startup or shutdown. +static volatile TimeValue DummyTimeValue = getElapsedWallTime(); + +// Implement this routine by using the static helpers above. They're already +// portable. +TimeValue self_process::get_wall_time() const { + return getElapsedWallTime(); +} + + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + + // Include the platform-specific parts of this class. #ifdef LLVM_ON_UNIX #include "Unix/Process.inc" diff --git a/lib/Support/Regex.cpp b/lib/Support/Regex.cpp index d293da0..efc8b90 100644 --- a/lib/Support/Regex.cpp +++ b/lib/Support/Regex.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Regex.h" +#include "regex_impl.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/SmallVector.h" -#include "regex_impl.h" #include <string> using namespace llvm; @@ -27,7 +27,9 @@ Regex::Regex(StringRef regex, unsigned Flags) { flags |= REG_ICASE; if (Flags & Newline) flags |= REG_NEWLINE; - error = llvm_regcomp(preg, regex.data(), flags|REG_EXTENDED|REG_PEND); + if (!(Flags & BasicRegex)) + flags |= REG_EXTENDED; + error = llvm_regcomp(preg, regex.data(), flags|REG_PEND); } Regex::~Regex() { diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp index e4e01be..6540319 100644 --- a/lib/Support/SourceMgr.cpp +++ b/lib/Support/SourceMgr.cpp @@ -13,10 +13,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/Twine.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" using namespace llvm; @@ -304,7 +304,7 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S, for (unsigned r = 0, e = Ranges.size(); r != e; ++r) { std::pair<unsigned, unsigned> R = Ranges[r]; for (unsigned i = R.first, - e = std::min(R.second, (unsigned)LineContents.size())+1; i != e; ++i) + e = std::min(R.second, (unsigned)LineContents.size()); i != e; ++i) CaretLine[i] = '~'; } diff --git a/lib/Support/Statistic.cpp b/lib/Support/Statistic.cpp index d8a6ad3..3a65221 100644 --- a/lib/Support/Statistic.cpp +++ b/lib/Support/Statistic.cpp @@ -22,13 +22,13 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Mutex.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cstring> using namespace llvm; diff --git a/lib/Support/StreamableMemoryObject.cpp b/lib/Support/StreamableMemoryObject.cpp index fe3752a..59e27a2 100644 --- a/lib/Support/StreamableMemoryObject.cpp +++ b/lib/Support/StreamableMemoryObject.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/StreamableMemoryObject.h" +#include "llvm/Support/Compiler.h" #include <cassert> #include <cstring> @@ -23,18 +24,23 @@ public: 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 uint64_t getBase() const LLVM_OVERRIDE { return 0; } + virtual uint64_t getExtent() const LLVM_OVERRIDE { + return LastChar - FirstChar; + } + virtual int readByte(uint64_t address, uint8_t* ptr) const LLVM_OVERRIDE; 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 { + uint64_t* copied) const LLVM_OVERRIDE; + virtual const uint8_t *getPointer(uint64_t address, + uint64_t size) const LLVM_OVERRIDE; + virtual bool isValidAddress(uint64_t address) const LLVM_OVERRIDE { return validAddress(address); } - virtual bool isObjectEnd(uint64_t address) const {return objectEnd(address);} + virtual bool isObjectEnd(uint64_t address) const LLVM_OVERRIDE { + return objectEnd(address); + } private: const uint8_t* const FirstChar; @@ -49,8 +55,8 @@ private: return static_cast<ptrdiff_t>(address) == LastChar - FirstChar; } - RawMemoryObject(const RawMemoryObject&); // DO NOT IMPLEMENT - void operator=(const RawMemoryObject&); // DO NOT IMPLEMENT + RawMemoryObject(const RawMemoryObject&) LLVM_DELETED_FUNCTION; + void operator=(const RawMemoryObject&) LLVM_DELETED_FUNCTION; }; int RawMemoryObject::readByte(uint64_t address, uint8_t* ptr) const { diff --git a/lib/Support/StringRef.cpp b/lib/Support/StringRef.cpp index 8aab4b2..d7a0bfa 100644 --- a/lib/Support/StringRef.cpp +++ b/lib/Support/StringRef.cpp @@ -9,10 +9,9 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/APInt.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/edit_distance.h" - #include <bitset> using namespace llvm; @@ -350,8 +349,8 @@ bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix, unsigned long long PrevResult = Result; Result = Result*Radix+CharVal; - // Check for overflow. - if (Result < PrevResult) + // Check for overflow by shifting back and seeing if bits were lost. + if (Result/Radix < PrevResult) return true; Str = Str.substr(1); diff --git a/lib/Support/Threading.cpp b/lib/Support/Threading.cpp index 7483225..13fba2e 100644 --- a/lib/Support/Threading.cpp +++ b/lib/Support/Threading.cpp @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Threading.h" +#include "llvm/Config/config.h" #include "llvm/Support/Atomic.h" #include "llvm/Support/Mutex.h" -#include "llvm/Config/config.h" #include <cassert> using namespace llvm; diff --git a/lib/Support/Timer.cpp b/lib/Support/Timer.cpp index 598e8ad..896d869 100644 --- a/lib/Support/Timer.cpp +++ b/lib/Support/Timer.cpp @@ -12,15 +12,15 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Timer.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/Process.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringMap.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; // CreateInfoOutputFile - Return a file stream to print our output on. diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index d1dc7c8..eefb96b 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/Triple.h" +#include "llvm/ADT/STLExtras.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; @@ -20,7 +20,6 @@ const char *Triple::getArchTypeName(ArchType Kind) { case UnknownArch: return "unknown"; case arm: return "arm"; - case cellspu: return "cellspu"; case hexagon: return "hexagon"; case mips: return "mips"; case mipsel: return "mipsel"; @@ -42,6 +41,8 @@ const char *Triple::getArchTypeName(ArchType Kind) { case nvptx64: return "nvptx64"; case le32: return "le32"; case amdil: return "amdil"; + case spir: return "spir"; + case spir64: return "spir64"; } llvm_unreachable("Invalid ArchType!"); @@ -55,8 +56,6 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case arm: case thumb: return "arm"; - case cellspu: return "spu"; - case ppc64: case ppc: return "ppc"; @@ -83,6 +82,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case nvptx64: return "nvptx"; case le32: return "le32"; case amdil: return "amdil"; + case spir: return "spir"; + case spir64: return "spir"; } } @@ -96,6 +97,7 @@ const char *Triple::getVendorTypeName(VendorType Kind) { case BGP: return "bgp"; case BGQ: return "bgq"; case Freescale: return "fsl"; + case IBM: return "ibm"; } llvm_unreachable("Invalid VendorType!"); @@ -123,9 +125,10 @@ const char *Triple::getOSTypeName(OSType Kind) { case Haiku: return "haiku"; case Minix: return "minix"; case RTEMS: return "rtems"; - case NativeClient: return "nacl"; + case NaCl: return "nacl"; case CNK: return "cnk"; case Bitrig: return "bitrig"; + case AIX: return "aix"; } llvm_unreachable("Invalid OSType"); @@ -140,6 +143,7 @@ const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { case EABI: return "eabi"; case MachO: return "macho"; case Android: return "android"; + case ELF: return "elf"; } llvm_unreachable("Invalid EnvironmentType!"); @@ -148,7 +152,6 @@ const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { return StringSwitch<Triple::ArchType>(Name) .Case("arm", arm) - .Case("cellspu", cellspu) .Case("mips", mips) .Case("mipsel", mipsel) .Case("mips64", mips64) @@ -171,40 +174,11 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { .Case("nvptx64", nvptx64) .Case("le32", le32) .Case("amdil", amdil) + .Case("spir", spir) + .Case("spir64", spir64) .Default(UnknownArch); } -Triple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) { - // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for - // archs which Darwin doesn't use. - - // The matching this routine does is fairly pointless, since it is neither the - // complete architecture list, nor a reasonable subset. The problem is that - // historically the driver driver accepts this and also ties its -march= - // handling to the architecture name, so we need to be careful before removing - // support for it. - - // This code must be kept in sync with Clang's Darwin specific argument - // translation. - - 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("r600", Triple::r600) - .Case("nvptx", Triple::nvptx) - .Case("nvptx64", Triple::nvptx64) - .Case("amdil", Triple::amdil) - .Default(Triple::UnknownArch); -} - // Returns architecture name that is understood by the target assembler. const char *Triple::getArchNameForAssembler() { if (!isOSDarwin() && getVendor() != Triple::Apple) @@ -226,6 +200,8 @@ const char *Triple::getArchNameForAssembler() { .Case("nvptx64", "nvptx64") .Case("le32", "le32") .Case("amdil", "amdil") + .Case("spir", "spir") + .Case("spir64", "spir64") .Default(NULL); } @@ -244,7 +220,6 @@ static Triple::ArchType parseArch(StringRef ArchName) { .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) @@ -260,6 +235,8 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Case("nvptx64", Triple::nvptx64) .Case("le32", Triple::le32) .Case("amdil", Triple::amdil) + .Case("spir", Triple::spir) + .Case("spir64", Triple::spir64) .Default(Triple::UnknownArch); } @@ -271,6 +248,7 @@ static Triple::VendorType parseVendor(StringRef VendorName) { .Case("bgp", Triple::BGP) .Case("bgq", Triple::BGQ) .Case("fsl", Triple::Freescale) + .Case("ibm", Triple::IBM) .Default(Triple::UnknownVendor); } @@ -294,9 +272,10 @@ static Triple::OSType parseOS(StringRef OSName) { .StartsWith("haiku", Triple::Haiku) .StartsWith("minix", Triple::Minix) .StartsWith("rtems", Triple::RTEMS) - .StartsWith("nacl", Triple::NativeClient) + .StartsWith("nacl", Triple::NaCl) .StartsWith("cnk", Triple::CNK) .StartsWith("bitrig", Triple::Bitrig) + .StartsWith("aix", Triple::AIX) .Default(Triple::UnknownOS); } @@ -308,6 +287,7 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) { .StartsWith("gnu", Triple::GNU) .StartsWith("macho", Triple::MachO) .StartsWith("android", Triple::Android) + .StartsWith("elf", Triple::ELF) .Default(Triple::UnknownEnvironment); } @@ -678,7 +658,6 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::amdil: case llvm::Triple::arm: - case llvm::Triple::cellspu: case llvm::Triple::hexagon: case llvm::Triple::le32: case llvm::Triple::mblaze: @@ -692,6 +671,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::thumb: case llvm::Triple::x86: case llvm::Triple::xcore: + case llvm::Triple::spir: return 32; case llvm::Triple::mips64: @@ -700,6 +680,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::ppc64: case llvm::Triple::sparcv9: case llvm::Triple::x86_64: + case llvm::Triple::spir64: return 64; } llvm_unreachable("Invalid architecture value"); @@ -726,8 +707,8 @@ Triple Triple::get32BitArchVariant() const { break; case Triple::amdil: + case Triple::spir: case Triple::arm: - case Triple::cellspu: case Triple::hexagon: case Triple::le32: case Triple::mblaze: @@ -750,6 +731,7 @@ Triple Triple::get32BitArchVariant() const { case Triple::ppc64: T.setArch(Triple::ppc); break; case Triple::sparcv9: T.setArch(Triple::sparc); break; case Triple::x86_64: T.setArch(Triple::x86); break; + case Triple::spir64: T.setArch(Triple::spir); break; } return T; } @@ -760,7 +742,6 @@ Triple Triple::get64BitArchVariant() const { case Triple::UnknownArch: case Triple::amdil: case Triple::arm: - case Triple::cellspu: case Triple::hexagon: case Triple::le32: case Triple::mblaze: @@ -772,6 +753,7 @@ Triple Triple::get64BitArchVariant() const { T.setArch(UnknownArch); break; + case Triple::spir64: case Triple::mips64: case Triple::mips64el: case Triple::nvptx64: @@ -787,6 +769,7 @@ Triple Triple::get64BitArchVariant() const { case Triple::ppc: T.setArch(Triple::ppc64); break; case Triple::sparc: T.setArch(Triple::sparcv9); break; case Triple::x86: T.setArch(Triple::x86_64); break; + case Triple::spir: T.setArch(Triple::spir64); break; } return T; } diff --git a/lib/Support/Unix/Memory.inc b/lib/Support/Unix/Memory.inc index 5a57a28..40d6b3f 100644 --- a/lib/Support/Unix/Memory.inc +++ b/lib/Support/Unix/Memory.inc @@ -13,6 +13,7 @@ #include "Unix.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Process.h" #ifdef HAVE_SYS_MMAN_H @@ -23,18 +24,150 @@ #include <mach/mach.h> #endif +#if defined(__mips__) +# if defined(__OpenBSD__) +# include <mips64/sysarch.h> +# else +# include <sys/cachectl.h> +# endif +#endif + +extern "C" void sys_icache_invalidate(const void *Addr, size_t len); + +namespace { + +int getPosixProtectionFlags(unsigned Flags) { + switch (Flags) { + case llvm::sys::Memory::MF_READ: + return PROT_READ; + case llvm::sys::Memory::MF_WRITE: + return PROT_WRITE; + case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_WRITE: + return PROT_READ | PROT_WRITE; + case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC: + return PROT_READ | PROT_EXEC; + case llvm::sys::Memory::MF_READ | + llvm::sys::Memory::MF_WRITE | + llvm::sys::Memory::MF_EXEC: + return PROT_READ | PROT_WRITE | PROT_EXEC; + case llvm::sys::Memory::MF_EXEC: + return PROT_EXEC; + default: + llvm_unreachable("Illegal memory protection flag specified!"); + } + // Provide a default return value as required by some compilers. + return PROT_NONE; +} + +} // namespace + +namespace llvm { +namespace sys { + +MemoryBlock +Memory::allocateMappedMemory(size_t NumBytes, + const MemoryBlock *const NearBlock, + unsigned PFlags, + error_code &EC) { + EC = error_code::success(); + if (NumBytes == 0) + return MemoryBlock(); + + static const size_t PageSize = process::get_self()->page_size(); + const size_t NumPages = (NumBytes+PageSize-1)/PageSize; + + int fd = -1; +#ifdef NEED_DEV_ZERO_FOR_MMAP + static int zero_fd = open("/dev/zero", O_RDWR); + if (zero_fd == -1) { + EC = error_code(errno, system_category()); + return MemoryBlock(); + } + fd = zero_fd; +#endif + + int MMFlags = MAP_PRIVATE | +#ifdef HAVE_MMAP_ANONYMOUS + MAP_ANONYMOUS +#else + MAP_ANON +#endif + ; // Ends statement above + + int Protect = getPosixProtectionFlags(PFlags); + + // Use any near hint and the page size to set a page-aligned starting address + uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) + + NearBlock->size() : 0; + if (Start && Start % PageSize) + Start += PageSize - Start % PageSize; + + void *Addr = ::mmap(reinterpret_cast<void*>(Start), PageSize*NumPages, + Protect, MMFlags, fd, 0); + if (Addr == MAP_FAILED) { + if (NearBlock) //Try again without a near hint + return allocateMappedMemory(NumBytes, 0, PFlags, EC); + + EC = error_code(errno, system_category()); + return MemoryBlock(); + } + + MemoryBlock Result; + Result.Address = Addr; + Result.Size = NumPages*PageSize; + + if (PFlags & MF_EXEC) + Memory::InvalidateInstructionCache(Result.Address, Result.Size); + + return Result; +} + +error_code +Memory::releaseMappedMemory(MemoryBlock &M) { + if (M.Address == 0 || M.Size == 0) + return error_code::success(); + + if (0 != ::munmap(M.Address, M.Size)) + return error_code(errno, system_category()); + + M.Address = 0; + M.Size = 0; + + return error_code::success(); +} + +error_code +Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { + if (M.Address == 0 || M.Size == 0) + return error_code::success(); + + if (!Flags) + return error_code(EINVAL, generic_category()); + + int Protect = getPosixProtectionFlags(Flags); + + int Result = ::mprotect(M.Address, M.Size, Protect); + if (Result != 0) + return error_code(errno, system_category()); + + if (Flags & MF_EXEC) + Memory::InvalidateInstructionCache(M.Address, M.Size); + + return error_code::success(); +} + /// AllocateRWX - Allocate a slab of memory with read/write/execute /// permissions. This is typically used for JIT applications where we want /// to emit code to the memory then jump to it. Getting this type of memory /// is very OS specific. /// -llvm::sys::MemoryBlock -llvm::sys::Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, - std::string *ErrMsg) { +MemoryBlock +Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, + std::string *ErrMsg) { if (NumBytes == 0) return MemoryBlock(); - size_t pageSize = Process::GetPageSize(); - size_t NumPages = (NumBytes+pageSize-1)/pageSize; + size_t PageSize = process::get_self()->page_size(); + size_t NumPages = (NumBytes+PageSize-1)/PageSize; int fd = -1; #ifdef NEED_DEV_ZERO_FOR_MMAP @@ -58,10 +191,10 @@ llvm::sys::Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, NearBlock->size() : 0; #if defined(__APPLE__) && defined(__arm__) - void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_EXEC, + void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_EXEC, flags, fd, 0); #else - void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, + void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, flags, fd, 0); #endif if (pa == MAP_FAILED) { @@ -74,40 +207,40 @@ llvm::sys::Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, #if defined(__APPLE__) && defined(__arm__) kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)pa, - (vm_size_t)(pageSize*NumPages), 0, + (vm_size_t)(PageSize*NumPages), 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); if (KERN_SUCCESS != kr) { MakeErrMsg(ErrMsg, "vm_protect max RX failed"); - return sys::MemoryBlock(); + return MemoryBlock(); } kr = vm_protect(mach_task_self(), (vm_address_t)pa, - (vm_size_t)(pageSize*NumPages), 0, + (vm_size_t)(PageSize*NumPages), 0, VM_PROT_READ | VM_PROT_WRITE); if (KERN_SUCCESS != kr) { MakeErrMsg(ErrMsg, "vm_protect RW failed"); - return sys::MemoryBlock(); + return MemoryBlock(); } #endif MemoryBlock result; result.Address = pa; - result.Size = NumPages*pageSize; + result.Size = NumPages*PageSize; return result; } -bool llvm::sys::Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { +bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { if (M.Address == 0 || M.Size == 0) return false; if (0 != ::munmap(M.Address, M.Size)) return MakeErrMsg(ErrMsg, "Can't release RWX Memory"); return false; } -bool llvm::sys::Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) { +bool Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) { #if defined(__APPLE__) && defined(__arm__) if (M.Address == 0 || M.Size == 0) return false; - sys::Memory::InvalidateInstructionCache(M.Address, M.Size); + Memory::InvalidateInstructionCache(M.Address, M.Size); kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address, (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_WRITE); return KERN_SUCCESS == kr; @@ -116,10 +249,10 @@ bool llvm::sys::Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) { #endif } -bool llvm::sys::Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) { +bool Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) { #if defined(__APPLE__) && defined(__arm__) if (M.Address == 0 || M.Size == 0) return false; - sys::Memory::InvalidateInstructionCache(M.Address, M.Size); + Memory::InvalidateInstructionCache(M.Address, M.Size); kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address, (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); return KERN_SUCCESS == kr; @@ -128,7 +261,7 @@ bool llvm::sys::Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) { #endif } -bool llvm::sys::Memory::setRangeWritable(const void *Addr, size_t Size) { +bool Memory::setRangeWritable(const void *Addr, size_t Size) { #if defined(__APPLE__) && defined(__arm__) kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr, (vm_size_t)Size, 0, @@ -139,7 +272,7 @@ bool llvm::sys::Memory::setRangeWritable(const void *Addr, size_t Size) { #endif } -bool llvm::sys::Memory::setRangeExecutable(const void *Addr, size_t Size) { +bool Memory::setRangeExecutable(const void *Addr, size_t Size) { #if defined(__APPLE__) && defined(__arm__) kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr, (vm_size_t)Size, 0, @@ -149,3 +282,52 @@ bool llvm::sys::Memory::setRangeExecutable(const void *Addr, size_t Size) { return true; #endif } + +/// InvalidateInstructionCache - Before the JIT can run a block of code +/// that has been emitted it must invalidate the instruction cache on some +/// platforms. +void Memory::InvalidateInstructionCache(const void *Addr, + size_t Len) { + +// icache invalidation for PPC and ARM. +#if defined(__APPLE__) + +# if (defined(__POWERPC__) || defined (__ppc__) || \ + defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__) + sys_icache_invalidate(const_cast<void *>(Addr), Len); +# endif + +#else + +# if (defined(__POWERPC__) || defined (__ppc__) || \ + defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__) + const size_t LineSize = 32; + + const intptr_t Mask = ~(LineSize - 1); + const intptr_t StartLine = ((intptr_t) Addr) & Mask; + const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask; + + for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) + asm volatile("dcbf 0, %0" : : "r"(Line)); + asm volatile("sync"); + + for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) + asm volatile("icbi 0, %0" : : "r"(Line)); + asm volatile("isync"); +# elif defined(__arm__) && defined(__GNUC__) + // FIXME: Can we safely always call this for __GNUC__ everywhere? + const char *Start = static_cast<const char *>(Addr); + const char *End = Start + Len; + __clear_cache(const_cast<char *>(Start), const_cast<char *>(End)); +# elif defined(__mips__) + const char *Start = static_cast<const char *>(Addr); + cacheflush(const_cast<char *>(Start), Len, BCACHE); +# endif + +#endif // end apple + + ValgrindDiscardTranslations(Addr, Len); +} + +} // namespace sys +} // namespace llvm diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc index 6bddbdf..6a5ebb8 100644 --- a/lib/Support/Unix/Path.inc +++ b/lib/Support/Unix/Path.inc @@ -261,7 +261,8 @@ Path::GetCurrentDirectory() { } #if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ - defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) + defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \ + defined(__linux__) || defined(__CYGWIN__) static int test_dir(char buf[PATH_MAX], char ret[PATH_MAX], const char *dir, const char *bin) @@ -337,9 +338,17 @@ Path Path::GetMainExecutable(const char *argv0, void *MainAddr) { return Path(exe_path); #elif defined(__linux__) || defined(__CYGWIN__) char exe_path[MAXPATHLEN]; - ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path)); - if (len >= 0) - return Path(StringRef(exe_path, len)); + StringRef aPath("/proc/self/exe"); + if (sys::fs::exists(aPath)) { + // /proc is not always mounted under Linux (chroot for example). + ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path)); + if (len >= 0) + return Path(StringRef(exe_path, len)); + } else { + // Fall back to the classical detection. + if (getprogpath(exe_path, argv0) != NULL) + return Path(exe_path); + } #elif defined(HAVE_DLFCN_H) // Use dladdr to get executable path if available. Dl_info DLInfo; diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc index f59551e..dc43b59 100644 --- a/lib/Support/Unix/PathV2.inc +++ b/lib/Support/Unix/PathV2.inc @@ -426,9 +426,10 @@ rety_open_create: // If the file existed, try again, otherwise, error. if (errno == errc::file_exists) goto retry_random_path; - // The path prefix doesn't exist. - if (errno == errc::no_such_file_or_directory) { - StringRef p(RandomPath.begin(), RandomPath.size()); + // If path prefix doesn't exist, try to create it. + if (errno == errc::no_such_file_or_directory && + !exists(path::parent_path(RandomPath))) { + StringRef p(RandomPath); SmallString<64> dir_to_create; for (path::const_iterator i = path::begin(p), e = --path::end(p); i != e; ++i) { @@ -547,7 +548,7 @@ mapped_file_region::~mapped_file_region() { ::munmap(Mapping, Size); } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES mapped_file_region::mapped_file_region(mapped_file_region &&other) : Mode(other.Mode), Size(other.Size), Mapping(other.Mapping) { other.Mapping = 0; @@ -576,7 +577,7 @@ const char *mapped_file_region::const_data() const { } int mapped_file_region::alignment() { - return Process::GetPageSize(); + return process::get_self()->page_size(); } error_code detail::directory_iterator_construct(detail::DirIterState &it, diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index 5204147..1335b78 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -44,9 +44,49 @@ using namespace llvm; using namespace sys; -unsigned -Process::GetPageSize() -{ + +process::id_type self_process::get_id() { + return getpid(); +} + +static std::pair<TimeValue, TimeValue> getRUsageTimes() { +#if defined(HAVE_GETRUSAGE) + struct rusage RU; + ::getrusage(RUSAGE_SELF, &RU); + return std::make_pair( + TimeValue( + static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec), + static_cast<TimeValue::NanoSecondsType>( + RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)), + TimeValue( + static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec), + static_cast<TimeValue::NanoSecondsType>( + RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND))); +#else +#warning Cannot get usage times on this platform + return std::make_pair(TimeValue(), TimeValue()); +#endif +} + +TimeValue self_process::get_user_time() const { +#if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0 + // Try to get a high resolution CPU timer. + struct timespec TS; + if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0) + return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec), + static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec)); +#endif + + // Otherwise fall back to rusage based timing. + return getRUsageTimes().first; +} + +TimeValue self_process::get_system_time() const { + // We can only collect system time by inspecting the results of getrusage. + return getRUsageTimes().second; +} + +static unsigned getPageSize() { #if defined(__CYGWIN__) // On Cygwin, getpagesize() returns 64k but the page size for the purposes of // memory protection and mmap() is 4k. @@ -62,6 +102,12 @@ Process::GetPageSize() return static_cast<unsigned>(page_size); } +// This constructor guaranteed to be run exactly once on a single thread, and +// sets up various process invariants that can be queried cheaply from then on. +self_process::self_process() : PageSize(getPageSize()) { +} + + size_t Process::GetMallocUsage() { #if defined(HAVE_MALLINFO) struct mallinfo mi; @@ -86,49 +132,10 @@ size_t Process::GetMallocUsage() { #endif } -size_t -Process::GetTotalMemoryUsage() -{ -#if defined(HAVE_MALLINFO) - struct mallinfo mi = ::mallinfo(); - return mi.uordblks + mi.hblkhd; -#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H) - malloc_statistics_t Stats; - malloc_zone_statistics(malloc_default_zone(), &Stats); - return Stats.size_allocated; // darwin -#elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__) - struct rusage usage; - ::getrusage(RUSAGE_SELF, &usage); - return usage.ru_maxrss; -#else -#warning Cannot get total memory size on this platform - return 0; -#endif -} - -void -Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time, - TimeValue& sys_time) -{ +void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, + TimeValue &sys_time) { elapsed = TimeValue::now(); -#if defined(HAVE_GETRUSAGE) - struct rusage usage; - ::getrusage(RUSAGE_SELF, &usage); - user_time = TimeValue( - static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ), - static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec * - TimeValue::NANOSECONDS_PER_MICROSECOND ) ); - sys_time = TimeValue( - static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ), - static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec * - TimeValue::NANOSECONDS_PER_MICROSECOND ) ); -#else -#warning Cannot get usage times on this platform - user_time.seconds(0); - user_time.microseconds(0); - sys_time.seconds(0); - sys_time.microseconds(0); -#endif + llvm::tie(user_time, sys_time) = getRUsageTimes(); } int Process::GetCurrentUserId() { @@ -318,7 +325,7 @@ static unsigned GetRandomNumberSeed() { // Otherwise, swizzle the current time and the process ID to form a reasonable // seed. - TimeValue Now = llvm::TimeValue::now(); + TimeValue Now = TimeValue::now(); return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid()); } #endif diff --git a/lib/Support/Unix/Program.inc b/lib/Support/Unix/Program.inc index e5990d0..c384316 100644 --- a/lib/Support/Unix/Program.inc +++ b/lib/Support/Unix/Program.inc @@ -16,9 +16,9 @@ //=== is guaranteed to work on *all* UNIX variants. //===----------------------------------------------------------------------===// -#include <llvm/Config/config.h> -#include "llvm/Support/FileSystem.h" #include "Unix.h" +#include "llvm/Support/FileSystem.h" +#include <llvm/Config/config.h> #if HAVE_SYS_STAT_H #include <sys/stat.h> #endif @@ -47,11 +47,6 @@ Program::Program() : Data_(0) {} Program::~Program() {} -unsigned Program::GetPid() const { - uint64_t pid = reinterpret_cast<uint64_t>(Data_); - return static_cast<unsigned>(pid); -} - // This function just uses the PATH environment variable to find the program. Path Program::FindProgramByName(const std::string& progName) { @@ -394,24 +389,6 @@ Program::Wait(const sys::Path &path, #endif } -bool -Program::Kill(std::string* ErrMsg) { - if (Data_ == 0) { - MakeErrMsg(ErrMsg, "Process not started!"); - return true; - } - - uint64_t pid64 = reinterpret_cast<uint64_t>(Data_); - pid_t pid = static_cast<pid_t>(pid64); - - if (kill(pid, SIGKILL) != 0) { - MakeErrMsg(ErrMsg, "The process couldn't be killed!"); - return true; - } - - return false; -} - error_code Program::ChangeStdinToBinary(){ // Do nothing, as Unix doesn't differentiate between text and binary. return make_error_code(errc::success); diff --git a/lib/Support/Unix/Signals.inc b/lib/Support/Unix/Signals.inc index 2f1e382..4a2496f 100644 --- a/lib/Support/Unix/Signals.inc +++ b/lib/Support/Unix/Signals.inc @@ -15,9 +15,9 @@ #include "Unix.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Mutex.h" +#include <algorithm> #include <string> #include <vector> -#include <algorithm> #if HAVE_EXECINFO_H # include <execinfo.h> // For backtrace(). #endif @@ -121,17 +121,29 @@ static void UnregisterHandlers() { /// NB: This must be an async signal safe function. It cannot allocate or free /// memory, even in debug builds. static void RemoveFilesToRemove() { - // Note: avoid iterators in case of debug iterators that allocate or release + // We avoid iterators in case of debug iterators that allocate or release // memory. for (unsigned i = 0, e = FilesToRemove.size(); i != e; ++i) { - // Note that we don't want to use any external code here, and we don't care - // about errors. We're going to try as hard as we can as often as we need - // to to make these files go away. If these aren't files, too bad. - // - // We do however rely on a std::string implementation for which repeated - // calls to 'c_str()' don't allocate memory. We pre-call 'c_str()' on all - // of these strings to try to ensure this is safe. - unlink(FilesToRemove[i].c_str()); + // We rely on a std::string implementation for which repeated calls to + // 'c_str()' don't allocate memory. We pre-call 'c_str()' on all of these + // strings to try to ensure this is safe. + const char *path = FilesToRemove[i].c_str(); + + // Get the status so we can determine if it's a file or directory. If we + // can't stat the file, ignore it. + struct stat buf; + if (stat(path, &buf) != 0) + continue; + + // If this is not a regular file, ignore it. We want to prevent removal of + // special files like /dev/null, even if the compiler is being run with the + // super-user permissions. + if (!S_ISREG(buf.st_mode)) + continue; + + // Otherwise, remove the file. We ignore any errors here as there is nothing + // else we can do. + unlink(path); } } @@ -243,7 +255,7 @@ void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { // On glibc systems we have the 'backtrace' function, which works nicely, but // doesn't demangle symbols. static void PrintStackTrace(void *) { -#ifdef HAVE_BACKTRACE +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) static void* StackTrace[256]; // Use backtrace() to output a backtrace on Linux systems with glibc. int depth = backtrace(StackTrace, diff --git a/lib/Support/Unix/Unix.h b/lib/Support/Unix/Unix.h index 361f297..051f56f 100644 --- a/lib/Support/Unix/Unix.h +++ b/lib/Support/Unix/Unix.h @@ -21,12 +21,12 @@ #include "llvm/Config/config.h" // Get autoconf configuration settings #include "llvm/Support/Errno.h" -#include <cstdlib> +#include <algorithm> +#include <cerrno> #include <cstdio> +#include <cstdlib> #include <cstring> -#include <cerrno> #include <string> -#include <algorithm> #ifdef HAVE_UNISTD_H #include <unistd.h> diff --git a/lib/Support/Windows/Memory.inc b/lib/Support/Windows/Memory.inc index fcc7283..4c5aebd 100644 --- a/lib/Support/Windows/Memory.inc +++ b/lib/Support/Windows/Memory.inc @@ -12,51 +12,165 @@ // //===----------------------------------------------------------------------===// -#include "Windows.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Process.h" +// The Windows.h header must be the last one included. +#include "Windows.h" + +namespace { + +DWORD getWindowsProtectionFlags(unsigned Flags) { + switch (Flags) { + // Contrary to what you might expect, the Windows page protection flags + // are not a bitwise combination of RWX values + case llvm::sys::Memory::MF_READ: + return PAGE_READONLY; + case llvm::sys::Memory::MF_WRITE: + // Note: PAGE_WRITE is not supported by VirtualProtect + return PAGE_READWRITE; + case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_WRITE: + return PAGE_READWRITE; + case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC: + return PAGE_EXECUTE_READ; + case llvm::sys::Memory::MF_READ | + llvm::sys::Memory::MF_WRITE | + llvm::sys::Memory::MF_EXEC: + return PAGE_EXECUTE_READWRITE; + case llvm::sys::Memory::MF_EXEC: + return PAGE_EXECUTE; + default: + llvm_unreachable("Illegal memory protection flag specified!"); + } + // Provide a default return value as required by some compilers. + return PAGE_NOACCESS; +} + +size_t getAllocationGranularity() { + SYSTEM_INFO Info; + ::GetSystemInfo(&Info); + if (Info.dwPageSize > Info.dwAllocationGranularity) + return Info.dwPageSize; + else + return Info.dwAllocationGranularity; +} + +} // namespace + namespace llvm { -using namespace sys; +namespace sys { //===----------------------------------------------------------------------===// //=== WARNING: Implementation here must contain only Win32 specific code //=== and must not be UNIX code //===----------------------------------------------------------------------===// -MemoryBlock Memory::AllocateRWX(size_t NumBytes, - const MemoryBlock *NearBlock, - std::string *ErrMsg) { - if (NumBytes == 0) return MemoryBlock(); +MemoryBlock Memory::allocateMappedMemory(size_t NumBytes, + const MemoryBlock *const NearBlock, + unsigned Flags, + error_code &EC) { + EC = error_code::success(); + if (NumBytes == 0) + return MemoryBlock(); + + // While we'd be happy to allocate single pages, the Windows allocation + // granularity may be larger than a single page (in practice, it is 64K) + // so mapping less than that will create an unreachable fragment of memory. + static const size_t Granularity = getAllocationGranularity(); + const size_t NumBlocks = (NumBytes+Granularity-1)/Granularity; - static const size_t pageSize = Process::GetPageSize(); - size_t NumPages = (NumBytes+pageSize-1)/pageSize; + uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) + + NearBlock->size() + : NULL; - PVOID start = NearBlock ? static_cast<unsigned char *>(NearBlock->base()) + - NearBlock->size() : NULL; + // If the requested address is not aligned to the allocation granularity, + // round up to get beyond NearBlock. VirtualAlloc would have rounded down. + if (Start && Start % Granularity != 0) + Start += Granularity - Start % Granularity; - void *pa = VirtualAlloc(start, NumPages*pageSize, MEM_RESERVE | MEM_COMMIT, - PAGE_EXECUTE_READWRITE); - if (pa == NULL) { + DWORD Protect = getWindowsProtectionFlags(Flags); + + void *PA = ::VirtualAlloc(reinterpret_cast<void*>(Start), + NumBlocks*Granularity, + MEM_RESERVE | MEM_COMMIT, Protect); + if (PA == NULL) { if (NearBlock) { // Try again without the NearBlock hint - return AllocateRWX(NumBytes, NULL, ErrMsg); + return allocateMappedMemory(NumBytes, NULL, Flags, EC); } - MakeErrMsg(ErrMsg, "Can't allocate RWX Memory: "); + EC = error_code(::GetLastError(), system_category()); return MemoryBlock(); } - MemoryBlock result; - result.Address = pa; - result.Size = NumPages*pageSize; - return result; + MemoryBlock Result; + Result.Address = PA; + Result.Size = NumBlocks*Granularity; + ; + if (Flags & MF_EXEC) + Memory::InvalidateInstructionCache(Result.Address, Result.Size); + + return Result; } -bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { - if (M.Address == 0 || M.Size == 0) return false; +error_code Memory::releaseMappedMemory(MemoryBlock &M) { + if (M.Address == 0 || M.Size == 0) + return error_code::success(); + if (!VirtualFree(M.Address, 0, MEM_RELEASE)) - return MakeErrMsg(ErrMsg, "Can't release RWX Memory: "); - return false; + return error_code(::GetLastError(), system_category()); + + M.Address = 0; + M.Size = 0; + + return error_code::success(); +} + +error_code Memory::protectMappedMemory(const MemoryBlock &M, + unsigned Flags) { + if (M.Address == 0 || M.Size == 0) + return error_code::success(); + + DWORD Protect = getWindowsProtectionFlags(Flags); + + DWORD OldFlags; + if (!VirtualProtect(M.Address, M.Size, Protect, &OldFlags)) + return error_code(::GetLastError(), system_category()); + + if (Flags & MF_EXEC) + Memory::InvalidateInstructionCache(M.Address, M.Size); + + return error_code::success(); +} + +/// InvalidateInstructionCache - Before the JIT can run a block of code +/// that has been emitted it must invalidate the instruction cache on some +/// platforms. +void Memory::InvalidateInstructionCache( + const void *Addr, size_t Len) { + FlushInstructionCache(GetCurrentProcess(), Addr, Len); +} + + +MemoryBlock Memory::AllocateRWX(size_t NumBytes, + const MemoryBlock *NearBlock, + std::string *ErrMsg) { + MemoryBlock MB; + error_code EC; + MB = allocateMappedMemory(NumBytes, NearBlock, + MF_READ|MF_WRITE|MF_EXEC, EC); + if (EC != error_code::success() && ErrMsg) { + MakeErrMsg(ErrMsg, EC.message()); + } + return MB; +} + +bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { + error_code EC = releaseMappedMemory(M); + if (EC == error_code::success()) + return false; + MakeErrMsg(ErrMsg, EC.message()); + return true; } static DWORD getProtection(const void *addr) { @@ -93,7 +207,7 @@ bool Memory::setRangeWritable(const void *Addr, size_t Size) { } DWORD oldProt; - sys::Memory::InvalidateInstructionCache(Addr, Size); + Memory::InvalidateInstructionCache(Addr, Size); return ::VirtualProtect(const_cast<LPVOID>(Addr), Size, prot, &oldProt) == TRUE; } @@ -112,9 +226,10 @@ bool Memory::setRangeExecutable(const void *Addr, size_t Size) { } DWORD oldProt; - sys::Memory::InvalidateInstructionCache(Addr, Size); + Memory::InvalidateInstructionCache(Addr, Size); return ::VirtualProtect(const_cast<LPVOID>(Addr), Size, prot, &oldProt) == TRUE; } -} +} // namespace sys +} // namespace llvm diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc index 2280b34..98d8a18 100644 --- a/lib/Support/Windows/Path.inc +++ b/lib/Support/Windows/Path.inc @@ -17,8 +17,8 @@ //===----------------------------------------------------------------------===// #include "Windows.h" -#include <malloc.h> #include <cstdio> +#include <malloc.h> // We need to undo a macro defined in Windows.h, otherwise we won't compile: #undef CopyFile diff --git a/lib/Support/Windows/PathV2.inc b/lib/Support/Windows/PathV2.inc index 696768b..2e6cc96 100644 --- a/lib/Support/Windows/PathV2.inc +++ b/lib/Support/Windows/PathV2.inc @@ -328,7 +328,7 @@ error_code resize_file(const Twine &path, uint64_t size) { path_utf16)) return ec; - int fd = ::_wopen(path_utf16.begin(), O_BINARY, S_IREAD | S_IWRITE); + int fd = ::_wopen(path_utf16.begin(), O_BINARY | _O_RDWR, S_IWRITE); if (fd == -1) return error_code(errno, generic_category()); #ifdef HAVE__CHSIZE_S @@ -794,7 +794,7 @@ mapped_file_region::mapped_file_region(const Twine &path, SmallVector<wchar_t, 128> path_utf16; // Convert path to UTF-16. - if (ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) + if ((ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16))) return; // Get file handle for creating a file mapping. @@ -861,7 +861,7 @@ mapped_file_region::~mapped_file_region() { ::CloseHandle(FileHandle); } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES mapped_file_region::mapped_file_region(mapped_file_region &&other) : Mode(other.Mode) , Size(other.Size) diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc index e29eb6d..ad94128 100644 --- a/lib/Support/Windows/Process.inc +++ b/lib/Support/Windows/Process.inc @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "Windows.h" -#include <psapi.h> -#include <malloc.h> -#include <io.h> #include <direct.h> +#include <io.h> +#include <malloc.h> +#include <psapi.h> #ifdef __MINGW32__ #if (HAVE_LIBPSAPI != 1) @@ -35,13 +35,47 @@ # define _HEAPOK (-2) #endif -namespace llvm { +using namespace llvm; using namespace sys; + +process::id_type self_process::get_id() { + return GetCurrentProcess(); +} + +static TimeValue getTimeValueFromFILETIME(FILETIME Time) { + ULARGE_INTEGER TimeInteger; + TimeInteger.LowPart = Time.dwLowDateTime; + TimeInteger.HighPart = Time.dwHighDateTime; + + // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) + return TimeValue( + static_cast<TimeValue::SecondsType>(TimeInteger.QuadPart / 10000000), + static_cast<TimeValue::NanoSecondsType>( + (TimeInteger.QuadPart % 10000000) * 100)); +} + +TimeValue self_process::get_user_time() const { + FILETIME ProcCreate, ProcExit, KernelTime, UserTime; + if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, + &UserTime) == 0) + return TimeValue(); + + return getTimeValueFromFILETIME(UserTime); +} + +TimeValue self_process::get_system_time() const { + FILETIME ProcCreate, ProcExit, KernelTime, UserTime; + if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, + &UserTime) == 0) + return TimeValue(); + + return getTimeValueFromFILETIME(KernelTime); +} + // This function retrieves the page size using GetSystemInfo and is present -// solely so it can be called once in Process::GetPageSize to initialize the -// static variable PageSize. -inline unsigned GetPageSizeOnce() { +// solely so it can be called once to initialize the self_process member below. +static unsigned getPageSize() { // NOTE: A 32-bit application running under WOW64 is supposed to use // GetNativeSystemInfo. However, this interface is not present prior // to Windows XP so to use it requires dynamic linking. It is not clear @@ -52,12 +86,12 @@ inline unsigned GetPageSizeOnce() { return static_cast<unsigned>(info.dwPageSize); } -unsigned -Process::GetPageSize() { - static const unsigned PageSize = GetPageSizeOnce(); - return PageSize; +// This constructor guaranteed to be run exactly once on a single thread, and +// sets up various process invariants that can be queried cheaply from then on. +self_process::self_process() : PageSize(getPageSize()) { } + size_t Process::GetMallocUsage() { @@ -72,30 +106,17 @@ Process::GetMallocUsage() return size; } -size_t -Process::GetTotalMemoryUsage() -{ - PROCESS_MEMORY_COUNTERS pmc; - GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); - return pmc.PagefileUsage; -} - -void -Process::GetTimeUsage( - TimeValue& elapsed, TimeValue& user_time, TimeValue& sys_time) -{ +void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, + TimeValue &sys_time) { elapsed = TimeValue::now(); - uint64_t ProcCreate, ProcExit, KernelTime, UserTime; - GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate, - (FILETIME*)&ProcExit, (FILETIME*)&KernelTime, - (FILETIME*)&UserTime); + FILETIME ProcCreate, ProcExit, KernelTime, UserTime; + if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, + &UserTime) == 0) + return; - // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) - user_time.seconds( UserTime / 10000000 ); - user_time.nanoseconds( unsigned(UserTime % 10000000) * 100 ); - sys_time.seconds( KernelTime / 10000000 ); - sys_time.nanoseconds( unsigned(KernelTime % 10000000) * 100 ); + user_time = getTimeValueFromFILETIME(UserTime); + sys_time = getTimeValueFromFILETIME(KernelTime); } int Process::GetCurrentUserId() @@ -255,5 +276,3 @@ const char *Process::ResetColor() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors()); return 0; } - -} diff --git a/lib/Support/Windows/Program.inc b/lib/Support/Windows/Program.inc index 80ccaa6..691d6d4 100644 --- a/lib/Support/Windows/Program.inc +++ b/lib/Support/Windows/Program.inc @@ -13,9 +13,9 @@ #include "Windows.h" #include <cstdio> -#include <malloc.h> -#include <io.h> #include <fcntl.h> +#include <io.h> +#include <malloc.h> //===----------------------------------------------------------------------===// //=== WARNING: Implementation here must contain only Win32 specific code @@ -43,11 +43,6 @@ Program::~Program() { } } -unsigned Program::GetPid() const { - Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_); - return wpi->dwProcessId; -} - // This function just uses the PATH environment variable to find the program. Path Program::FindProgramByName(const std::string& progName) { @@ -380,23 +375,6 @@ Program::Wait(const Path &path, return 1; } -bool -Program::Kill(std::string* ErrMsg) { - if (Data_ == 0) { - MakeErrMsg(ErrMsg, "Process not started!"); - return true; - } - - Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_); - HANDLE hProcess = wpi->hProcess; - if (TerminateProcess(hProcess, 1) == 0) { - MakeErrMsg(ErrMsg, "The process couldn't be killed!"); - return true; - } - - return false; -} - error_code Program::ChangeStdinToBinary(){ int result = _setmode( _fileno(stdin), _O_BINARY ); if (result == -1) diff --git a/lib/Support/Windows/Signals.inc b/lib/Support/Windows/Signals.inc index 38308f6..a969753 100644 --- a/lib/Support/Windows/Signals.inc +++ b/lib/Support/Windows/Signals.inc @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "Windows.h" +#include <algorithm> #include <stdio.h> #include <vector> -#include <algorithm> #ifdef __MINGW32__ #include <imagehlp.h> diff --git a/lib/Support/YAMLParser.cpp b/lib/Support/YAMLParser.cpp index 7c353c8..2cead20 100644 --- a/lib/Support/YAMLParser.cpp +++ b/lib/Support/YAMLParser.cpp @@ -12,16 +12,15 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/YAMLParser.h" - -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/ilist_node.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace yaml; @@ -252,6 +251,7 @@ namespace yaml { class Scanner { public: Scanner(const StringRef Input, SourceMgr &SM); + Scanner(MemoryBuffer *Buffer, SourceMgr &SM_); /// @brief Parse the next token and return it without popping it. Token &peekNext(); @@ -708,6 +708,21 @@ Scanner::Scanner(StringRef Input, SourceMgr &sm) End = InputBuffer->getBufferEnd(); } +Scanner::Scanner(MemoryBuffer *Buffer, SourceMgr &SM_) + : SM(SM_) + , InputBuffer(Buffer) + , Current(InputBuffer->getBufferStart()) + , End(InputBuffer->getBufferEnd()) + , Indent(-1) + , Column(0) + , Line(0) + , FlowLevel(0) + , IsStartOfStream(true) + , IsSimpleKeyAllowed(true) + , Failed(false) { + SM.AddNewSourceBuffer(InputBuffer, SMLoc()); +} + Token &Scanner::peekNext() { // If the current token is a possible simple key, keep parsing until we // can confirm. @@ -903,6 +918,7 @@ bool Scanner::consume(uint32_t Expected) { void Scanner::skip(uint32_t Distance) { Current += Distance; Column += Distance; + assert(Current <= End && "Skipped past the end"); } bool Scanner::isBlankOrBreak(StringRef::iterator Position) { @@ -1239,6 +1255,12 @@ bool Scanner::scanFlowScalar(bool IsDoubleQuoted) { } } } + + if (Current == End) { + setError("Expected quote at end of scalar", Current); + return false; + } + skip(1); // Skip ending quote. Token T; T.Kind = Token::TK_Scalar; @@ -1525,6 +1547,10 @@ Stream::Stream(StringRef Input, SourceMgr &SM) : scanner(new Scanner(Input, SM)) , CurrentDoc(0) {} +Stream::Stream(MemoryBuffer *InputBuffer, SourceMgr &SM) + : scanner(new Scanner(InputBuffer, SM)) + , CurrentDoc(0) {} + Stream::~Stream() {} bool Stream::failed() { return scanner->failed(); } diff --git a/lib/Support/YAMLTraits.cpp b/lib/Support/YAMLTraits.cpp new file mode 100644 index 0000000..9da2aa7 --- /dev/null +++ b/lib/Support/YAMLTraits.cpp @@ -0,0 +1,827 @@ +//===- lib/Support/YAMLTraits.cpp -----------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/YAMLTraits.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/YAMLParser.h" +#include "llvm/Support/raw_ostream.h" +#include <cstring> +using namespace llvm; +using namespace yaml; + +//===----------------------------------------------------------------------===// +// IO +//===----------------------------------------------------------------------===// + +IO::IO(void *Context) : Ctxt(Context) { +} + +IO::~IO() { +} + +void *IO::getContext() { + return Ctxt; +} + +void IO::setContext(void *Context) { + Ctxt = Context; +} + +//===----------------------------------------------------------------------===// +// Input +//===----------------------------------------------------------------------===// + +Input::Input(StringRef InputContent, void *Ctxt) + : IO(Ctxt), + Strm(new Stream(InputContent, SrcMgr)), + CurrentNode(NULL) { + DocIterator = Strm->begin(); +} + +Input::~Input() { + +} + +error_code Input::error() { + return EC; +} + +void Input::setDiagHandler(SourceMgr::DiagHandlerTy Handler, void *Ctxt) { + SrcMgr.setDiagHandler(Handler, Ctxt); +} + +bool Input::outputting() { + return false; +} + +bool Input::setCurrentDocument() { + if (DocIterator != Strm->end()) { + Node *N = DocIterator->getRoot(); + if (isa<NullNode>(N)) { + // Empty files are allowed and ignored + ++DocIterator; + return setCurrentDocument(); + } + TopNode.reset(this->createHNodes(N)); + CurrentNode = TopNode.get(); + return true; + } + return false; +} + +void Input::nextDocument() { + ++DocIterator; +} + +void Input::beginMapping() { + if (EC) + return; + MapHNode *MN = dyn_cast<MapHNode>(CurrentNode); + if (MN) { + MN->ValidKeys.clear(); + } +} + +bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault, + void *&SaveInfo) { + UseDefault = false; + if (EC) + return false; + MapHNode *MN = dyn_cast<MapHNode>(CurrentNode); + if (!MN) { + setError(CurrentNode, "not a mapping"); + return false; + } + MN->ValidKeys.push_back(Key); + HNode *Value = MN->Mapping[Key]; + if (!Value) { + if (Required) + setError(CurrentNode, Twine("missing required key '") + Key + "'"); + else + UseDefault = true; + return false; + } + SaveInfo = CurrentNode; + CurrentNode = Value; + return true; +} + +void Input::postflightKey(void *saveInfo) { + CurrentNode = reinterpret_cast<HNode *>(saveInfo); +} + +void Input::endMapping() { + if (EC) + return; + MapHNode *MN = dyn_cast<MapHNode>(CurrentNode); + if (!MN) + return; + for (MapHNode::NameToNode::iterator i = MN->Mapping.begin(), + End = MN->Mapping.end(); i != End; ++i) { + if (!MN->isValidKey(i->first)) { + setError(i->second, Twine("unknown key '") + i->first + "'"); + break; + } + } +} + +unsigned Input::beginSequence() { + if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { + return SQ->Entries.size(); + } + return 0; +} + +void Input::endSequence() { +} + +bool Input::preflightElement(unsigned Index, void *&SaveInfo) { + if (EC) + return false; + if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { + SaveInfo = CurrentNode; + CurrentNode = SQ->Entries[Index]; + return true; + } + return false; +} + +void Input::postflightElement(void *SaveInfo) { + CurrentNode = reinterpret_cast<HNode *>(SaveInfo); +} + +unsigned Input::beginFlowSequence() { + if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { + return SQ->Entries.size(); + } + return 0; +} + +bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) { + if (EC) + return false; + if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { + SaveInfo = CurrentNode; + CurrentNode = SQ->Entries[index]; + return true; + } + return false; +} + +void Input::postflightFlowElement(void *SaveInfo) { + CurrentNode = reinterpret_cast<HNode *>(SaveInfo); +} + +void Input::endFlowSequence() { +} + +void Input::beginEnumScalar() { + ScalarMatchFound = false; +} + +bool Input::matchEnumScalar(const char *Str, bool) { + if (ScalarMatchFound) + return false; + if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { + if (SN->value().equals(Str)) { + ScalarMatchFound = true; + return true; + } + } + return false; +} + +void Input::endEnumScalar() { + if (!ScalarMatchFound) { + setError(CurrentNode, "unknown enumerated scalar"); + } +} + +bool Input::beginBitSetScalar(bool &DoClear) { + BitValuesUsed.clear(); + if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { + BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false); + } else { + setError(CurrentNode, "expected sequence of bit values"); + } + DoClear = true; + return true; +} + +bool Input::bitSetMatch(const char *Str, bool) { + if (EC) + return false; + if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { + unsigned Index = 0; + for (std::vector<HNode *>::iterator i = SQ->Entries.begin(), + End = SQ->Entries.end(); i != End; ++i) { + if (ScalarHNode *SN = dyn_cast<ScalarHNode>(*i)) { + if (SN->value().equals(Str)) { + BitValuesUsed[Index] = true; + return true; + } + } else { + setError(CurrentNode, "unexpected scalar in sequence of bit values"); + } + ++Index; + } + } else { + setError(CurrentNode, "expected sequence of bit values"); + } + return false; +} + +void Input::endBitSetScalar() { + if (EC) + return; + if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { + assert(BitValuesUsed.size() == SQ->Entries.size()); + for (unsigned i = 0; i < SQ->Entries.size(); ++i) { + if (!BitValuesUsed[i]) { + setError(SQ->Entries[i], "unknown bit value"); + return; + } + } + } +} + +void Input::scalarString(StringRef &S) { + if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { + S = SN->value(); + } else { + setError(CurrentNode, "unexpected scalar"); + } +} + +void Input::setError(HNode *hnode, const Twine &message) { + this->setError(hnode->_node, message); +} + +void Input::setError(Node *node, const Twine &message) { + Strm->printError(node, message); + EC = make_error_code(errc::invalid_argument); +} + +Input::HNode *Input::createHNodes(Node *N) { + SmallString<128> StringStorage; + if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) { + StringRef KeyStr = SN->getValue(StringStorage); + if (!StringStorage.empty()) { + // Copy string to permanent storage + unsigned Len = StringStorage.size(); + char *Buf = StringAllocator.Allocate<char>(Len); + memcpy(Buf, &StringStorage[0], Len); + KeyStr = StringRef(Buf, Len); + } + return new ScalarHNode(N, KeyStr); + } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) { + SequenceHNode *SQHNode = new SequenceHNode(N); + for (SequenceNode::iterator i = SQ->begin(), End = SQ->end(); i != End; + ++i) { + HNode *Entry = this->createHNodes(i); + if (EC) + break; + SQHNode->Entries.push_back(Entry); + } + return SQHNode; + } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) { + MapHNode *mapHNode = new MapHNode(N); + for (MappingNode::iterator i = Map->begin(), End = Map->end(); i != End; + ++i) { + ScalarNode *KeyScalar = dyn_cast<ScalarNode>(i->getKey()); + StringStorage.clear(); + StringRef KeyStr = KeyScalar->getValue(StringStorage); + if (!StringStorage.empty()) { + // Copy string to permanent storage + unsigned Len = StringStorage.size(); + char *Buf = StringAllocator.Allocate<char>(Len); + memcpy(Buf, &StringStorage[0], Len); + KeyStr = StringRef(Buf, Len); + } + HNode *ValueHNode = this->createHNodes(i->getValue()); + if (EC) + break; + mapHNode->Mapping[KeyStr] = ValueHNode; + } + return mapHNode; + } else if (isa<NullNode>(N)) { + return new EmptyHNode(N); + } else { + setError(N, "unknown node kind"); + return NULL; + } +} + +bool Input::MapHNode::isValidKey(StringRef Key) { + for (SmallVector<const char *, 6>::iterator i = ValidKeys.begin(), + End = ValidKeys.end(); i != End; ++i) { + if (Key.equals(*i)) + return true; + } + return false; +} + +void Input::setError(const Twine &Message) { + this->setError(CurrentNode, Message); +} + +Input::MapHNode::~MapHNode() { + for (MapHNode::NameToNode::iterator i = Mapping.begin(), End = Mapping.end(); + i != End; ++i) { + delete i->second; + } +} + +Input::SequenceHNode::~SequenceHNode() { + for (std::vector<HNode*>::iterator i = Entries.begin(), End = Entries.end(); + i != End; ++i) { + delete *i; + } +} + + + +//===----------------------------------------------------------------------===// +// Output +//===----------------------------------------------------------------------===// + +Output::Output(raw_ostream &yout, void *context) + : IO(context), + Out(yout), + Column(0), + ColumnAtFlowStart(0), + NeedBitValueComma(false), + NeedFlowSequenceComma(false), + EnumerationMatchFound(false), + NeedsNewLine(false) { +} + +Output::~Output() { +} + +bool Output::outputting() { + return true; +} + +void Output::beginMapping() { + StateStack.push_back(inMapFirstKey); + NeedsNewLine = true; +} + +void Output::endMapping() { + StateStack.pop_back(); +} + +bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault, + bool &UseDefault, void *&) { + UseDefault = false; + if (Required || !SameAsDefault) { + this->newLineCheck(); + this->paddedKey(Key); + return true; + } + return false; +} + +void Output::postflightKey(void *) { + if (StateStack.back() == inMapFirstKey) { + StateStack.pop_back(); + StateStack.push_back(inMapOtherKey); + } +} + +void Output::beginDocuments() { + this->outputUpToEndOfLine("---"); +} + +bool Output::preflightDocument(unsigned index) { + if (index > 0) + this->outputUpToEndOfLine("\n---"); + return true; +} + +void Output::postflightDocument() { +} + +void Output::endDocuments() { + output("\n...\n"); +} + +unsigned Output::beginSequence() { + StateStack.push_back(inSeq); + NeedsNewLine = true; + return 0; +} + +void Output::endSequence() { + StateStack.pop_back(); +} + +bool Output::preflightElement(unsigned, void *&) { + return true; +} + +void Output::postflightElement(void *) { +} + +unsigned Output::beginFlowSequence() { + StateStack.push_back(inFlowSeq); + this->newLineCheck(); + ColumnAtFlowStart = Column; + output("[ "); + NeedFlowSequenceComma = false; + return 0; +} + +void Output::endFlowSequence() { + StateStack.pop_back(); + this->outputUpToEndOfLine(" ]"); +} + +bool Output::preflightFlowElement(unsigned, void *&) { + if (NeedFlowSequenceComma) + output(", "); + if (Column > 70) { + output("\n"); + for (int i = 0; i < ColumnAtFlowStart; ++i) + output(" "); + Column = ColumnAtFlowStart; + output(" "); + } + return true; +} + +void Output::postflightFlowElement(void *) { + NeedFlowSequenceComma = true; +} + +void Output::beginEnumScalar() { + EnumerationMatchFound = false; +} + +bool Output::matchEnumScalar(const char *Str, bool Match) { + if (Match && !EnumerationMatchFound) { + this->newLineCheck(); + this->outputUpToEndOfLine(Str); + EnumerationMatchFound = true; + } + return false; +} + +void Output::endEnumScalar() { + if (!EnumerationMatchFound) + llvm_unreachable("bad runtime enum value"); +} + +bool Output::beginBitSetScalar(bool &DoClear) { + this->newLineCheck(); + output("[ "); + NeedBitValueComma = false; + DoClear = false; + return true; +} + +bool Output::bitSetMatch(const char *Str, bool Matches) { + if (Matches) { + if (NeedBitValueComma) + output(", "); + this->output(Str); + NeedBitValueComma = true; + } + return false; +} + +void Output::endBitSetScalar() { + this->outputUpToEndOfLine(" ]"); +} + +void Output::scalarString(StringRef &S) { + this->newLineCheck(); + if (S.find('\n') == StringRef::npos) { + // No embedded new-line chars, just print string. + this->outputUpToEndOfLine(S); + return; + } + unsigned i = 0; + unsigned j = 0; + unsigned End = S.size(); + output("'"); // Starting single quote. + const char *Base = S.data(); + while (j < End) { + // Escape a single quote by doubling it. + if (S[j] == '\'') { + output(StringRef(&Base[i], j - i + 1)); + output("'"); + i = j + 1; + } + ++j; + } + output(StringRef(&Base[i], j - i)); + this->outputUpToEndOfLine("'"); // Ending single quote. +} + +void Output::setError(const Twine &message) { +} + +void Output::output(StringRef s) { + Column += s.size(); + Out << s; +} + +void Output::outputUpToEndOfLine(StringRef s) { + this->output(s); + if (StateStack.empty() || StateStack.back() != inFlowSeq) + NeedsNewLine = true; +} + +void Output::outputNewLine() { + Out << "\n"; + Column = 0; +} + +// if seq at top, indent as if map, then add "- " +// if seq in middle, use "- " if firstKey, else use " " +// + +void Output::newLineCheck() { + if (!NeedsNewLine) + return; + NeedsNewLine = false; + + this->outputNewLine(); + + assert(StateStack.size() > 0); + unsigned Indent = StateStack.size() - 1; + bool OutputDash = false; + + if (StateStack.back() == inSeq) { + OutputDash = true; + } else if ((StateStack.size() > 1) && (StateStack.back() == inMapFirstKey) && + (StateStack[StateStack.size() - 2] == inSeq)) { + --Indent; + OutputDash = true; + } + + for (unsigned i = 0; i < Indent; ++i) { + output(" "); + } + if (OutputDash) { + output("- "); + } + +} + +void Output::paddedKey(StringRef key) { + output(key); + output(":"); + const char *spaces = " "; + if (key.size() < strlen(spaces)) + output(&spaces[key.size()]); + else + output(" "); +} + +//===----------------------------------------------------------------------===// +// traits for built-in types +//===----------------------------------------------------------------------===// + +void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) { + Out << (Val ? "true" : "false"); +} + +StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) { + if (Scalar.equals("true")) { + Val = true; + return StringRef(); + } else if (Scalar.equals("false")) { + Val = false; + return StringRef(); + } + return "invalid boolean"; +} + +void ScalarTraits<StringRef>::output(const StringRef &Val, void *, + raw_ostream &Out) { + Out << Val; +} + +StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *, + StringRef &Val) { + Val = Scalar; + return StringRef(); +} + +void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *, + raw_ostream &Out) { + // use temp uin32_t because ostream thinks uint8_t is a character + uint32_t Num = Val; + Out << Num; +} + +StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) { + unsigned long long n; + if (getAsUnsignedInteger(Scalar, 0, n)) + return "invalid number"; + if (n > 0xFF) + return "out of range number"; + Val = n; + return StringRef(); +} + +void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *, + raw_ostream &Out) { + Out << Val; +} + +StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *, + uint16_t &Val) { + unsigned long long n; + if (getAsUnsignedInteger(Scalar, 0, n)) + return "invalid number"; + if (n > 0xFFFF) + return "out of range number"; + Val = n; + return StringRef(); +} + +void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *, + raw_ostream &Out) { + Out << Val; +} + +StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *, + uint32_t &Val) { + unsigned long long n; + if (getAsUnsignedInteger(Scalar, 0, n)) + return "invalid number"; + if (n > 0xFFFFFFFFUL) + return "out of range number"; + Val = n; + return StringRef(); +} + +void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *, + raw_ostream &Out) { + Out << Val; +} + +StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *, + uint64_t &Val) { + unsigned long long N; + if (getAsUnsignedInteger(Scalar, 0, N)) + return "invalid number"; + Val = N; + return StringRef(); +} + +void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) { + // use temp in32_t because ostream thinks int8_t is a character + int32_t Num = Val; + Out << Num; +} + +StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) { + long long N; + if (getAsSignedInteger(Scalar, 0, N)) + return "invalid number"; + if ((N > 127) || (N < -128)) + return "out of range number"; + Val = N; + return StringRef(); +} + +void ScalarTraits<int16_t>::output(const int16_t &Val, void *, + raw_ostream &Out) { + Out << Val; +} + +StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) { + long long N; + if (getAsSignedInteger(Scalar, 0, N)) + return "invalid number"; + if ((N > INT16_MAX) || (N < INT16_MIN)) + return "out of range number"; + Val = N; + return StringRef(); +} + +void ScalarTraits<int32_t>::output(const int32_t &Val, void *, + raw_ostream &Out) { + Out << Val; +} + +StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) { + long long N; + if (getAsSignedInteger(Scalar, 0, N)) + return "invalid number"; + if ((N > INT32_MAX) || (N < INT32_MIN)) + return "out of range number"; + Val = N; + return StringRef(); +} + +void ScalarTraits<int64_t>::output(const int64_t &Val, void *, + raw_ostream &Out) { + Out << Val; +} + +StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) { + long long N; + if (getAsSignedInteger(Scalar, 0, N)) + return "invalid number"; + Val = N; + return StringRef(); +} + +void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) { + Out << format("%g", Val); +} + +StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) { + SmallString<32> buff(Scalar.begin(), Scalar.end()); + char *end; + Val = strtod(buff.c_str(), &end); + if (*end != '\0') + return "invalid floating point number"; + return StringRef(); +} + +void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) { + Out << format("%g", Val); +} + +StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) { + SmallString<32> buff(Scalar.begin(), Scalar.end()); + char *end; + Val = strtod(buff.c_str(), &end); + if (*end != '\0') + return "invalid floating point number"; + return StringRef(); +} + +void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) { + uint8_t Num = Val; + Out << format("0x%02X", Num); +} + +StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) { + unsigned long long n; + if (getAsUnsignedInteger(Scalar, 0, n)) + return "invalid hex8 number"; + if (n > 0xFF) + return "out of range hex8 number"; + Val = n; + return StringRef(); +} + +void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) { + uint16_t Num = Val; + Out << format("0x%04X", Num); +} + +StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) { + unsigned long long n; + if (getAsUnsignedInteger(Scalar, 0, n)) + return "invalid hex16 number"; + if (n > 0xFFFF) + return "out of range hex16 number"; + Val = n; + return StringRef(); +} + +void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) { + uint32_t Num = Val; + Out << format("0x%08X", Num); +} + +StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) { + unsigned long long n; + if (getAsUnsignedInteger(Scalar, 0, n)) + return "invalid hex32 number"; + if (n > 0xFFFFFFFFUL) + return "out of range hex32 number"; + Val = n; + return StringRef(); +} + +void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) { + uint64_t Num = Val; + Out << format("0x%016llX", Num); +} + +StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) { + unsigned long long Num; + if (getAsUnsignedInteger(Scalar, 0, Num)) + return "invalid hex64 number"; + Val = Num; + return StringRef(); +} diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index 7cd5364..106864d 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -12,16 +12,16 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/Program.h" -#include "llvm/Support/Process.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Config/config.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" #include "llvm/Support/system_error.h" -#include "llvm/ADT/STLExtras.h" #include <cctype> #include <cerrno> #include <sys/stat.h> diff --git a/lib/Support/regcomp.c b/lib/Support/regcomp.c index 46c91a9..74d9186 100644 --- a/lib/Support/regcomp.c +++ b/lib/Support/regcomp.c @@ -303,6 +303,7 @@ p_ere_exp(struct parse *p) sopno pos; int count; int count2; + int backrefnum; sopno subno; int wascaret = 0; @@ -370,7 +371,34 @@ p_ere_exp(struct parse *p) case '\\': REQUIRE(MORE(), REG_EESCAPE); c = GETNEXT(); - ordinary(p, c); + if (c >= '1' && c <= '9') { + /* \[0-9] is taken to be a back-reference to a previously specified + * matching group. backrefnum will hold the number. The matching + * group must exist (i.e. if \4 is found there must have been at + * least 4 matching groups specified in the pattern previously). + */ + backrefnum = c - '0'; + if (p->pend[backrefnum] == 0) { + SETERROR(REG_ESUBREG); + break; + } + + /* Make sure everything checks out and emit the sequence + * that marks a back-reference to the parse structure. + */ + assert(backrefnum <= p->g->nsub); + EMIT(OBACK_, backrefnum); + assert(p->pbegin[backrefnum] != 0); + assert(OP(p->strip[p->pbegin[backrefnum]]) != OLPAREN); + assert(OP(p->strip[p->pend[backrefnum]]) != ORPAREN); + (void) dupl(p, p->pbegin[backrefnum]+1, p->pend[backrefnum]); + EMIT(O_BACK, backrefnum); + p->g->backrefs = 1; + } else { + /* Other chars are simply themselves when escaped with a backslash. + */ + ordinary(p, c); + } break; case '{': /* okay as ordinary except if digit follows */ REQUIRE(!MORE() || !isdigit((uch)PEEK()), REG_BADRPT); diff --git a/lib/Support/system_error.cpp b/lib/Support/system_error.cpp index 56898de..b22745a 100644 --- a/lib/Support/system_error.cpp +++ b/lib/Support/system_error.cpp @@ -13,8 +13,8 @@ #include "llvm/Support/system_error.h" #include "llvm/Support/Errno.h" -#include <string> #include <cstring> +#include <string> namespace llvm { @@ -48,8 +48,8 @@ _do_message::message(int ev) const { class _generic_error_category : public _do_message { public: - virtual const char* name() const; - virtual std::string message(int ev) const; + virtual const char* name() const LLVM_OVERRIDE; + virtual std::string message(int ev) const LLVM_OVERRIDE; }; const char* @@ -74,9 +74,9 @@ generic_category() { class _system_error_category : public _do_message { public: - virtual const char* name() const; - virtual std::string message(int ev) const; - virtual error_condition default_error_condition(int ev) const; + virtual const char* name() const LLVM_OVERRIDE; + virtual std::string message(int ev) const LLVM_OVERRIDE; + virtual error_condition default_error_condition(int ev) const LLVM_OVERRIDE; }; const char* |
