diff options
Diffstat (limited to 'lib/Support')
54 files changed, 1887 insertions, 1179 deletions
| diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 7989e30..295b16c 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -35,8 +35,7 @@ using namespace llvm;  /* Assumed in hexadecimal significand parsing, and conversion to     hexadecimal strings.  */ -#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1] -COMPILE_TIME_ASSERT(integerPartWidth % 4 == 0); +static_assert(integerPartWidth % 4 == 0, "Part width must be divisible by 4!");  namespace llvm { @@ -212,15 +211,15 @@ skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end,  {    StringRef::iterator p = begin;    *dot = end; -  while (*p == '0' && p != end) +  while (p != end && *p == '0')      p++; -  if (*p == '.') { +  if (p != end && *p == '.') {      *dot = p++;      assert(end - begin != 1 && "Significand has no digits"); -    while (*p == '0' && p != end) +    while (p != end && *p == '0')        p++;    } @@ -927,7 +926,10 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)    assert(semantics == rhs.semantics);    precision = semantics->precision; -  newPartsCount = partCountForBits(precision * 2); + +  // Allocate space for twice as many bits as the original significand, plus one +  // extra bit for the addition to overflow into. +  newPartsCount = partCountForBits(precision * 2 + 1);    if (newPartsCount > 4)      fullSignificand = new integerPart[newPartsCount]; @@ -949,13 +951,14 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)    //   *this = a23 . a22 ... a0 * 2^e1    //     rhs = b23 . b22 ... b0 * 2^e2    // the result of multiplication is: -  //   *this = c47 c46 . c45 ... c0 * 2^(e1+e2) -  // Note that there are two significant bits at the left-hand side of the  -  // radix point. Move the radix point toward left by one bit, and adjust -  // exponent accordingly. -  exponent += 1; - -  if (addend) { +  //   *this = c48 c47 c46 . c45 ... c0 * 2^(e1+e2) +  // Note that there are three significant bits at the left-hand side of the  +  // radix point: two for the multiplication, and an overflow bit for the +  // addition (that will always be zero at this point). Move the radix point +  // toward left by two bits, and adjust exponent accordingly. +  exponent += 2; + +  if (addend && addend->isNonZero()) {      // The intermediate result of the multiplication has "2 * precision"       // signicant bit; adjust the addend to be consistent with mul result.      // @@ -965,13 +968,13 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)      opStatus status;      unsigned int extendedPrecision; -    /* Normalize our MSB.  */ -    extendedPrecision = 2 * precision; -    if (omsb != extendedPrecision) { +    // Normalize our MSB to one below the top bit to allow for overflow. +    extendedPrecision = 2 * precision + 1; +    if (omsb != extendedPrecision - 1) {        assert(extendedPrecision > omsb);        APInt::tcShiftLeft(fullSignificand, newPartsCount, -                         extendedPrecision - omsb); -      exponent -= extendedPrecision - omsb; +                         (extendedPrecision - 1) - omsb); +      exponent -= (extendedPrecision - 1) - omsb;      }      /* Create new semantics.  */ @@ -988,6 +991,14 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)      status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored);      assert(status == opOK);      (void)status; + +    // Shift the significand of the addend right by one bit. This guarantees +    // that the high bit of the significand is zero (same as fullSignificand), +    // so the addition will overflow (if it does overflow at all) into the top bit. +    lost_fraction = extendedAddend.shiftSignificandRight(1); +    assert(lost_fraction == lfExactlyZero && +           "Lost precision while shifting addend for fused-multiply-add."); +      lost_fraction = addOrSubtractSignificand(extendedAddend, false);      /* Restore our state.  */ @@ -1003,7 +1014,7 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)    // having "precision" significant-bits. First, move the radix point from     // poision "2*precision - 1" to "precision - 1". The exponent need to be    // adjusted by "2*precision - 1" - "precision - 1" = "precision". -  exponent -= precision; +  exponent -= precision + 1;    // In case MSB resides at the left-hand side of radix point, shift the    // mantissa right by some amount to make sure the MSB reside right before @@ -1801,7 +1812,7 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand,       extended-precision calculation.  */    if (isFiniteNonZero() &&        multiplicand.isFiniteNonZero() && -      addend.isFiniteNonZero()) { +      addend.isFinite()) {      lostFraction lost_fraction;      lost_fraction = multiplySignificand(multiplicand, &addend); @@ -3377,7 +3388,9 @@ void APFloat::makeLargest(bool Negative) {    // internal consistency.    const unsigned NumUnusedHighBits =      PartCount*integerPartWidth - semantics->precision; -  significand[PartCount - 1] = ~integerPart(0) >> NumUnusedHighBits; +  significand[PartCount - 1] = (NumUnusedHighBits < integerPartWidth) +                                   ? (~integerPart(0) >> NumUnusedHighBits) +                                   : 0;  }  /// Make this number the smallest magnitude denormal number in the given @@ -3904,3 +3917,20 @@ APFloat::makeZero(bool Negative) {    exponent = semantics->minExponent-1;    APInt::tcSet(significandParts(), 0, partCount());    } + +APFloat llvm::scalbn(APFloat X, int Exp) { +  if (X.isInfinity() || X.isZero() || X.isNaN()) +    return std::move(X); + +  auto MaxExp = X.getSemantics().maxExponent; +  auto MinExp = X.getSemantics().minExponent; +  if (Exp > (MaxExp - X.exponent)) +    // Overflow saturates to infinity. +    return APFloat::getInf(X.getSemantics(), X.isNegative()); +  if (Exp < (MinExp - X.exponent)) +    // Underflow saturates to zero. +    return APFloat::getZero(X.getSemantics(), X.isNegative()); + +  X.exponent += Exp; +  return std::move(X); +} diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index fa929eb..c20eeb2 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -454,8 +454,10 @@ APInt APInt::XorSlowCase(const APInt& RHS) const {    for (unsigned i = 0; i < numWords; ++i)      val[i] = pVal[i] ^ RHS.pVal[i]; +  APInt Result(val, getBitWidth());    // 0^0==1 so clear the high bits in case they got set. -  return APInt(val, getBitWidth()).clearUnusedBits(); +  Result.clearUnusedBits(); +  return Result;  }  APInt APInt::operator*(const APInt& RHS) const { @@ -473,7 +475,8 @@ APInt APInt::operator+(const APInt& RHS) const {      return APInt(BitWidth, VAL + RHS.VAL);    APInt Result(BitWidth, 0);    add(Result.pVal, this->pVal, RHS.pVal, getNumWords()); -  return Result.clearUnusedBits(); +  Result.clearUnusedBits(); +  return Result;  }  APInt APInt::operator-(const APInt& RHS) const { @@ -482,7 +485,8 @@ APInt APInt::operator-(const APInt& RHS) const {      return APInt(BitWidth, VAL - RHS.VAL);    APInt Result(BitWidth, 0);    sub(Result.pVal, this->pVal, RHS.pVal, getNumWords()); -  return Result.clearUnusedBits(); +  Result.clearUnusedBits(); +  return Result;  }  bool APInt::EqualSlowCase(const APInt& RHS) const { @@ -1114,7 +1118,9 @@ APInt APInt::ashr(unsigned shiftAmt) const {    uint64_t fillValue = (isNegative() ? -1ULL : 0);    for (unsigned i = breakWord+1; i < getNumWords(); ++i)      val[i] = fillValue; -  return APInt(val, BitWidth).clearUnusedBits(); +  APInt Result(val, BitWidth); +  Result.clearUnusedBits(); +  return Result;  }  /// Logical right-shift this APInt by shiftAmt. @@ -1151,7 +1157,9 @@ APInt APInt::lshr(unsigned shiftAmt) const {    // If we are shifting less than a word, compute the shift with a simple carry    if (shiftAmt < APINT_BITS_PER_WORD) {      lshrNear(val, pVal, getNumWords(), shiftAmt); -    return APInt(val, BitWidth).clearUnusedBits(); +    APInt Result(val, BitWidth); +    Result.clearUnusedBits(); +    return Result;    }    // Compute some values needed by the remaining shift algorithms @@ -1164,7 +1172,9 @@ APInt APInt::lshr(unsigned shiftAmt) const {        val[i] = pVal[i+offset];      for (unsigned i = getNumWords()-offset; i < getNumWords(); i++)        val[i] = 0; -    return APInt(val,BitWidth).clearUnusedBits(); +    APInt Result(val, BitWidth); +    Result.clearUnusedBits(); +    return Result;    }    // Shift the low order words @@ -1178,7 +1188,9 @@ APInt APInt::lshr(unsigned shiftAmt) const {    // Remaining words are 0    for (unsigned i = breakWord+1; i < getNumWords(); ++i)      val[i] = 0; -  return APInt(val, BitWidth).clearUnusedBits(); +  APInt Result(val, BitWidth); +  Result.clearUnusedBits(); +  return Result;  }  /// Left-shift this APInt by shiftAmt. @@ -1211,7 +1223,9 @@ APInt APInt::shlSlowCase(unsigned shiftAmt) const {        val[i] = pVal[i] << shiftAmt | carry;        carry = pVal[i] >> (APINT_BITS_PER_WORD - shiftAmt);      } -    return APInt(val, BitWidth).clearUnusedBits(); +    APInt Result(val, BitWidth); +    Result.clearUnusedBits(); +    return Result;    }    // Compute some values needed by the remaining shift algorithms @@ -1224,7 +1238,9 @@ APInt APInt::shlSlowCase(unsigned shiftAmt) const {        val[i] = 0;      for (unsigned i = offset; i < getNumWords(); i++)        val[i] = pVal[i-offset]; -    return APInt(val,BitWidth).clearUnusedBits(); +    APInt Result(val, BitWidth); +    Result.clearUnusedBits(); +    return Result;    }    // Copy whole words from this to Result. @@ -1235,7 +1251,9 @@ APInt APInt::shlSlowCase(unsigned shiftAmt) const {    val[offset] = pVal[0] << wordShift;    for (i = 0; i < offset; ++i)      val[i] = 0; -  return APInt(val, BitWidth).clearUnusedBits(); +  APInt Result(val, BitWidth); +  Result.clearUnusedBits(); +  return Result;  }  APInt APInt::rotl(const APInt &rotateAmt) const { @@ -1303,7 +1321,7 @@ APInt APInt::sqrt() const {    // Okay, all the short cuts are exhausted. We must compute it. The following    // is a classical Babylonian method for computing the square root. This code -  // was adapted to APINt from a wikipedia article on such computations. +  // was adapted to APInt from a wikipedia article on such computations.    // See http://www.wikipedia.org/ and go to the page named    // Calculate_an_integer_square_root.    unsigned nbits = BitWidth, i = 4; @@ -2046,19 +2064,29 @@ APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const {    return Res;  } -APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const { -  Overflow = ShAmt >= getBitWidth(); +APInt APInt::sshl_ov(const APInt &ShAmt, bool &Overflow) const { +  Overflow = ShAmt.uge(getBitWidth());    if (Overflow) -    ShAmt = getBitWidth()-1; +    return APInt(BitWidth, 0);    if (isNonNegative()) // Don't allow sign change. -    Overflow = ShAmt >= countLeadingZeros(); +    Overflow = ShAmt.uge(countLeadingZeros());    else -    Overflow = ShAmt >= countLeadingOnes(); +    Overflow = ShAmt.uge(countLeadingOnes());    return *this << ShAmt;  } +APInt APInt::ushl_ov(const APInt &ShAmt, bool &Overflow) const { +  Overflow = ShAmt.uge(getBitWidth()); +  if (Overflow) +    return APInt(BitWidth, 0); + +  Overflow = ShAmt.ugt(countLeadingZeros()); + +  return *this << ShAmt; +} + @@ -2270,8 +2298,7 @@ void APInt::print(raw_ostream &OS, bool isSigned) const {  // Assumed by lowHalf, highHalf, partMSB and partLSB.  A fairly safe  // and unrestricting assumption. -#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1] -COMPILE_TIME_ASSERT(integerPartWidth % 2 == 0); +static_assert(integerPartWidth % 2 == 0, "Part width must be divisible by 2!");  /* Some handy functions local to this file.  */  namespace { diff --git a/lib/Support/Android.mk b/lib/Support/Android.mk index 7968697..34448a7 100644 --- a/lib/Support/Android.mk +++ b/lib/Support/Android.mk @@ -22,7 +22,6 @@ support_SRC_FILES := \    DataExtractor.cpp \    Debug.cpp \    DeltaAlgorithm.cpp \ -  Disassembler.cpp \    Dwarf.cpp \    DynamicLibrary.cpp \    Errno.cpp \ @@ -44,10 +43,12 @@ support_SRC_FILES := \    LockFileManager.cpp \    MD5.cpp \    ManagedStatic.cpp \ +  MathExtras.cpp \    Memory.cpp \    MemoryBuffer.cpp \    MemoryObject.cpp \    Mutex.cpp \ +  Options.cpp \    Path.cpp \    PluginLoader.cpp \    PrettyStackTrace.cpp \ @@ -61,15 +62,14 @@ support_SRC_FILES := \    Signals.cpp \    SmallPtrSet.cpp \    SmallVector.cpp \ +  StreamingMemoryObject.cpp \    SourceMgr.cpp \    SpecialCaseList.cpp \    Statistic.cpp \ -  StreamableMemoryObject.cpp \    StringExtras.cpp \    StringMap.cpp \    StringPool.cpp \    StringRef.cpp \ -  StringRefMemoryObject.cpp \    SystemUtils.cpp \    TargetRegistry.cpp \    Threading.cpp \ diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt index 9ecd559..fa62591 100644 --- a/lib/Support/CMakeLists.txt +++ b/lib/Support/CMakeLists.txt @@ -1,3 +1,32 @@ +set(system_libs) +if( NOT MSVC ) +  if( MINGW ) +    set(system_libs ${system_libs} imagehlp psapi shell32) +  elseif( CMAKE_HOST_UNIX ) +    if( HAVE_LIBRT ) +      set(system_libs ${system_libs} rt) +    endif() +    if( HAVE_LIBDL ) +      set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) +    endif() +    if(LLVM_ENABLE_TERMINFO) +      if(HAVE_TERMINFO) +        set(system_libs ${system_libs} ${TERMINFO_LIBS}) +      endif() +    endif() +    if( LLVM_ENABLE_THREADS AND HAVE_LIBATOMIC ) +      set(system_libs ${system_libs} atomic) +    endif() +    if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) +      set(system_libs ${system_libs} pthread) +    endif() +    if ( LLVM_ENABLE_ZLIB AND HAVE_LIBZ ) +      set(system_libs ${system_libs} z) +    endif() +    set(system_libs ${system_libs} m) +  endif( MINGW ) +endif( NOT MSVC ) +  add_llvm_library(LLVMSupport    APFloat.cpp    APInt.cpp @@ -36,9 +65,11 @@ add_llvm_library(LLVMSupport    Locale.cpp    LockFileManager.cpp    ManagedStatic.cpp +  MathExtras.cpp    MemoryBuffer.cpp    MemoryObject.cpp    MD5.cpp +  Options.cpp    PluginLoader.cpp    PrettyStackTrace.cpp    RandomNumberGenerator.cpp @@ -49,12 +80,11 @@ add_llvm_library(LLVMSupport    SourceMgr.cpp    SpecialCaseList.cpp    Statistic.cpp -  StreamableMemoryObject.cpp +  StreamingMemoryObject.cpp    StringExtras.cpp    StringMap.cpp    StringPool.cpp    StringRef.cpp -  StringRefMemoryObject.cpp    SystemUtils.cpp    Timer.cpp    ToolOutputFile.cpp @@ -73,11 +103,9 @@ add_llvm_library(LLVMSupport  # System    Atomic.cpp -  Disassembler.cpp    DynamicLibrary.cpp    Errno.cpp    Host.cpp -  IncludeFile.cpp    Memory.cpp    Mutex.cpp    Path.cpp @@ -117,38 +145,8 @@ add_llvm_library(LLVMSupport    Windows/ThreadLocal.inc    Windows/TimeValue.inc    Windows/Watchdog.inc -  ) -set(system_libs) -if( NOT MSVC ) -  if( MINGW ) -    set(system_libs ${system_libs} imagehlp psapi shell32) -  elseif( CMAKE_HOST_UNIX ) -    if( HAVE_LIBRT ) -      set(system_libs ${system_libs} rt) -    endif() -    if( HAVE_LIBDL ) -      set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) -    endif() -    if(LLVM_ENABLE_TERMINFO) -      if(HAVE_TERMINFO) -        set(system_libs ${system_libs} ${TERMINFO_LIBS}) -      endif() -    endif() -    if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) -      set(system_libs ${system_libs} pthread) -    endif() -    if ( LLVM_ENABLE_ZLIB AND HAVE_LIBZ ) -      set(system_libs ${system_libs} z) -    endif() -  endif( MINGW ) -endif( NOT MSVC ) - -if(POLICY CMP0022 AND BUILD_SHARED_LIBS) -  # FIXME: Should this be really PUBLIC? -  target_link_libraries(LLVMSupport PUBLIC ${system_libs}) -else() -  target_link_libraries(LLVMSupport ${cmake_2_8_12_INTERFACE} ${system_libs}) -endif() +  LINK_LIBS ${system_libs} +  )  set_property(TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS "${system_libs}") diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 87348f7..985c877 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -17,6 +17,7 @@  //===----------------------------------------------------------------------===//  #include "llvm/Support/CommandLine.h" +#include "llvm-c/Support.h"  #include "llvm/ADT/ArrayRef.h"  #include "llvm/ADT/SmallPtrSet.h"  #include "llvm/ADT/SmallString.h" @@ -113,9 +114,15 @@ void Option::addArgument() {  }  void Option::removeArgument() { -  assert(NextRegistered && "argument never registered"); -  assert(RegisteredOptionList == this && "argument is not the last registered"); -  RegisteredOptionList = NextRegistered; +  if (RegisteredOptionList == this) { +    RegisteredOptionList = NextRegistered; +    MarkOptionsChanged(); +    return; +  } +  Option *O = RegisteredOptionList; +  for (; O->NextRegistered != this; O = O->NextRegistered) +    ; +  O->NextRegistered = NextRegistered;    MarkOptionsChanged();  } @@ -158,7 +165,7 @@ static void GetOptionInfo(SmallVectorImpl<Option*> &PositionalOpts,      // Handle named options.      for (size_t i = 0, e = OptionNames.size(); i != e; ++i) {        // Add argument to the argument map! -      if (OptionsMap.GetOrCreateValue(OptionNames[i], O).second != O) { +      if (!OptionsMap.insert(std::make_pair(OptionNames[i], O)).second) {          errs() << ProgramName << ": CommandLine Error: Option '"                 << OptionNames[i] << "' registered more than once!\n";          HadErrors = true; @@ -474,13 +481,18 @@ static bool isGNUSpecial(char C) {  }  void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, -                                SmallVectorImpl<const char *> &NewArgv) { +                                SmallVectorImpl<const char *> &NewArgv, +                                bool MarkEOLs) {    SmallString<128> Token;    for (size_t I = 0, E = Src.size(); I != E; ++I) {      // Consume runs of whitespace.      if (Token.empty()) { -      while (I != E && isWhitespace(Src[I])) +      while (I != E && isWhitespace(Src[I])) { +        // Mark the end of lines in response files +        if (MarkEOLs && Src[I] == '\n') +          NewArgv.push_back(nullptr);          ++I; +      }        if (I == E) break;      } @@ -521,6 +533,9 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver,    // Append the last token after hitting EOF with no whitespace.    if (!Token.empty())      NewArgv.push_back(Saver.SaveString(Token.c_str())); +  // Mark the end of response files +  if (MarkEOLs) +    NewArgv.push_back(nullptr);  }  /// Backslashes are interpreted in a rather complicated way in the Windows-style @@ -562,7 +577,8 @@ static size_t parseBackslash(StringRef Src, size_t I, SmallString<128> &Token) {  }  void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, -                                    SmallVectorImpl<const char *> &NewArgv) { +                                    SmallVectorImpl<const char *> &NewArgv, +                                    bool MarkEOLs) {    SmallString<128> Token;    // This is a small state machine to consume characters until it reaches the @@ -572,8 +588,12 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver,      // INIT state indicates that the current input index is at the start of      // the string or between tokens.      if (State == INIT) { -      if (isWhitespace(Src[I])) +      if (isWhitespace(Src[I])) { +        // Mark the end of lines in response files +        if (MarkEOLs && Src[I] == '\n') +          NewArgv.push_back(nullptr);          continue; +      }        if (Src[I] == '"') {          State = QUOTED;          continue; @@ -596,6 +616,9 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver,          NewArgv.push_back(Saver.SaveString(Token.c_str()));          Token.clear();          State = INIT; +        // Mark the end of lines in response files +        if (MarkEOLs && Src[I] == '\n') +          NewArgv.push_back(nullptr);          continue;        }        if (Src[I] == '"') { @@ -626,20 +649,24 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver,    // Append the last token after hitting EOF with no whitespace.    if (!Token.empty())      NewArgv.push_back(Saver.SaveString(Token.c_str())); +  // Mark the end of response files +  if (MarkEOLs) +    NewArgv.push_back(nullptr);  }  static bool ExpandResponseFile(const char *FName, StringSaver &Saver,                                 TokenizerCallback Tokenizer, -                               SmallVectorImpl<const char *> &NewArgv) { +                               SmallVectorImpl<const char *> &NewArgv, +                               bool MarkEOLs = false) {    ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =        MemoryBuffer::getFile(FName);    if (!MemBufOrErr)      return false; -  std::unique_ptr<MemoryBuffer> MemBuf = std::move(MemBufOrErr.get()); -  StringRef Str(MemBuf->getBufferStart(), MemBuf->getBufferSize()); +  MemoryBuffer &MemBuf = *MemBufOrErr.get(); +  StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize());    // If we have a UTF-16 byte order mark, convert to UTF-8 for parsing. -  ArrayRef<char> BufRef(MemBuf->getBufferStart(), MemBuf->getBufferEnd()); +  ArrayRef<char> BufRef(MemBuf.getBufferStart(), MemBuf.getBufferEnd());    std::string UTF8Buf;    if (hasUTF16ByteOrderMark(BufRef)) {      if (!convertUTF16ToUTF8String(BufRef, UTF8Buf)) @@ -648,7 +675,7 @@ static bool ExpandResponseFile(const char *FName, StringSaver &Saver,    }    // Tokenize the contents into NewArgv. -  Tokenizer(Str, Saver, NewArgv); +  Tokenizer(Str, Saver, NewArgv, MarkEOLs);    return true;  } @@ -656,13 +683,19 @@ static bool ExpandResponseFile(const char *FName, StringSaver &Saver,  /// \brief Expand response files on a command line recursively using the given  /// StringSaver and tokenization strategy.  bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, -                             SmallVectorImpl<const char *> &Argv) { +                             SmallVectorImpl<const char *> &Argv, +                             bool MarkEOLs) {    unsigned RspFiles = 0;    bool AllExpanded = true;    // Don't cache Argv.size() because it can change.    for (unsigned I = 0; I != Argv.size(); ) {      const char *Arg = Argv[I]; +    // Check if it is an EOL marker +    if (Arg == nullptr) { +      ++I; +      continue; +    }      if (Arg[0] != '@') {        ++I;        continue; @@ -678,7 +711,8 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,      // FIXME: If a nested response file uses a relative path, is it relative to      // the cwd of the process or the response file?      SmallVector<const char *, 0> ExpandedArgv; -    if (!ExpandResponseFile(Arg + 1, Saver, Tokenizer, ExpandedArgv)) { +    if (!ExpandResponseFile(Arg + 1, Saver, Tokenizer, ExpandedArgv, +                            MarkEOLs)) {        // We couldn't read this file, so we leave it in the argument stream and        // move on.        AllExpanded = false; @@ -1018,13 +1052,12 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv,    }    // Loop over args and make sure all required args are specified! -  for (StringMap<Option*>::iterator I = Opts.begin(), -         E = Opts.end(); I != E; ++I) { -    switch (I->second->getNumOccurrencesFlag()) { +  for (const auto &Opt : Opts) { +    switch (Opt.second->getNumOccurrencesFlag()) {      case Required:      case OneOrMore: -      if (I->second->getNumOccurrences() == 0) { -        I->second->error("must be specified at least once!"); +      if (Opt.second->getNumOccurrences() == 0) { +        Opt.second->error("must be specified at least once!");          ErrorParsing = true;        }        // Fall through @@ -1422,7 +1455,7 @@ sortOpts(StringMap<Option*> &OptMap,        continue;      // If we've already seen this option, don't add it to the list again. -    if (!OptionSet.insert(I->second)) +    if (!OptionSet.insert(I->second).second)        continue;      Opts.push_back(std::pair<const char *, Option*>(I->getKey().data(), @@ -1807,3 +1840,8 @@ void cl::getRegisteredOptions(StringMap<Option*> &Map)    GetOptionInfo(PositionalOpts, SinkOpts, Map);    return;  } + +void LLVMParseCommandLineOptions(int argc, const char *const *argv, +                                 const char *Overview) { +  llvm::cl::ParseCommandLineOptions(argc, argv, Overview); +} diff --git a/lib/Support/DataStream.cpp b/lib/Support/DataStream.cpp index 32653de..dbf6465 100644 --- a/lib/Support/DataStream.cpp +++ b/lib/Support/DataStream.cpp @@ -32,12 +32,12 @@ using namespace llvm;  #define DEBUG_TYPE "Data-stream"  // Interface goals: -// * StreamableMemoryObject doesn't care about complexities like using +// * StreamingMemoryObject doesn't care about complexities like using  //   threads/async callbacks to actually overlap download+compile  // * Don't want to duplicate Data in memory  // * Don't need to know total Data len in advance  // Non-goals: -// StreamableMemoryObject already has random access so this interface only does +// StreamingMemoryObject already has random access so this interface only does  // in-order streaming (no arbitrary seeking, else we'd have to buffer all the  // Data here in addition to MemoryObject).  This also means that if we want  // to be able to to free Data, BitstreamBytes/BitcodeReader will implement it diff --git a/lib/Support/Debug.cpp b/lib/Support/Debug.cpp index ad4d4ef..8246542 100644 --- a/lib/Support/Debug.cpp +++ b/lib/Support/Debug.cpp @@ -27,6 +27,7 @@  #include "llvm/Support/CommandLine.h"  #include "llvm/Support/Signals.h"  #include "llvm/Support/circular_raw_ostream.h" +#include "llvm/Support/ManagedStatic.h"  using namespace llvm; @@ -50,14 +51,14 @@ DebugBufferSize("debug-buffer-size",                  cl::Hidden,                  cl::init(0)); -static std::string CurrentDebugType; +static ManagedStatic<std::string> CurrentDebugType;  namespace {  struct DebugOnlyOpt {    void operator=(const std::string &Val) const {      DebugFlag |= !Val.empty(); -    CurrentDebugType = Val; +    *CurrentDebugType = Val;    }  }; @@ -86,7 +87,7 @@ static void debug_user_sig_handler(void *Cookie) {  // with the -debug-only=X option.  //  bool llvm::isCurrentDebugType(const char *DebugType) { -  return CurrentDebugType.empty() || DebugType == CurrentDebugType; +  return CurrentDebugType->empty() || DebugType == *CurrentDebugType;  }  /// setCurrentDebugType - Set the current debug type, as if the -debug-only=X @@ -94,7 +95,7 @@ bool llvm::isCurrentDebugType(const char *DebugType) {  /// debug output to be produced.  ///  void llvm::setCurrentDebugType(const char *Type) { -  CurrentDebugType = Type; +  *CurrentDebugType = Type;  }  /// dbgs - Return a circular-buffered debug stream. diff --git a/lib/Support/Disassembler.cpp b/lib/Support/Disassembler.cpp deleted file mode 100644 index 27df3a9..0000000 --- a/lib/Support/Disassembler.cpp +++ /dev/null @@ -1,74 +0,0 @@ -//===- lib/Support/Disassembler.cpp -----------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the necessary glue to call external disassembler -// libraries. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/Disassembler.h" -#include "llvm/Config/config.h" -#include <cassert> -#include <iomanip> -#include <sstream> -#include <string> - -#if USE_UDIS86 -#include <udis86.h> -#endif - -using namespace llvm; - -bool llvm::sys::hasDisassembler() -{ -#if defined (__i386__) || defined (__amd64__) || defined (__x86_64__) -  // We have option to enable udis86 library. -# if USE_UDIS86 -  return true; -#else -  return false; -#endif -#else -  return false; -#endif -} - -std::string llvm::sys::disassembleBuffer(uint8_t* start, size_t length, -                                         uint64_t pc) { -#if (defined (__i386__) || defined (__amd64__) || defined (__x86_64__)) \ -  && USE_UDIS86 -  std::stringstream res; - -  unsigned bits; -# if defined(__i386__) -  bits = 32; -# else -  bits = 64; -# endif - -  ud_t ud_obj; - -  ud_init(&ud_obj); -  ud_set_input_buffer(&ud_obj, start, length); -  ud_set_mode(&ud_obj, bits); -  ud_set_pc(&ud_obj, pc); -  ud_set_syntax(&ud_obj, UD_SYN_ATT); - -  res << std::setbase(16) -      << std::setw(bits/4); - -  while (ud_disassemble(&ud_obj)) { -    res << ud_insn_off(&ud_obj) << ":\t" << ud_insn_asm(&ud_obj) << "\n"; -  } - -  return res.str(); -#else -  return "No disassembler available. See configure help for options.\n"; -#endif -} diff --git a/lib/Support/Dwarf.cpp b/lib/Support/Dwarf.cpp index c9efa61..4b6337e 100644 --- a/lib/Support/Dwarf.cpp +++ b/lib/Support/Dwarf.cpp @@ -17,8 +17,6 @@  using namespace llvm;  using namespace dwarf; -/// TagString - Return the string for the specified tag. -///  const char *llvm::dwarf::TagString(unsigned Tag) {    switch (Tag) {    case DW_TAG_array_type:                return "DW_TAG_array_type"; @@ -82,6 +80,7 @@ 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_expression:                return "DW_TAG_expression";    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_coarray_type:              return "DW_TAG_coarray_type"; @@ -103,8 +102,6 @@ const char *llvm::dwarf::TagString(unsigned Tag) {    return nullptr;  } -/// ChildrenString - Return the string for the specified children flag. -///  const char *llvm::dwarf::ChildrenString(unsigned Children) {    switch (Children) {    case DW_CHILDREN_no:                   return "DW_CHILDREN_no"; @@ -113,8 +110,6 @@ const char *llvm::dwarf::ChildrenString(unsigned Children) {    return nullptr;  } -/// AttributeString - Return the string for the specified attribute. -///  const char *llvm::dwarf::AttributeString(unsigned Attribute) {    switch (Attribute) {    case DW_AT_sibling:                    return "DW_AT_sibling"; @@ -274,8 +269,6 @@ const char *llvm::dwarf::AttributeString(unsigned Attribute) {    return nullptr;  } -/// FormEncodingString - Return the string for the specified form encoding. -///  const char *llvm::dwarf::FormEncodingString(unsigned Encoding) {    switch (Encoding) {    case DW_FORM_addr:                     return "DW_FORM_addr"; @@ -311,8 +304,6 @@ const char *llvm::dwarf::FormEncodingString(unsigned Encoding) {    return nullptr;  } -/// OperationEncodingString - Return the string for the specified operation -/// encoding.  const char *llvm::dwarf::OperationEncodingString(unsigned Encoding) {    switch (Encoding) {    case DW_OP_addr:                       return "DW_OP_addr"; @@ -480,8 +471,6 @@ const char *llvm::dwarf::OperationEncodingString(unsigned Encoding) {    return nullptr;  } -/// AttributeEncodingString - Return the string for the specified attribute -/// encoding.  const char *llvm::dwarf::AttributeEncodingString(unsigned Encoding) {    switch (Encoding) {    case DW_ATE_address:                   return "DW_ATE_address"; @@ -506,8 +495,6 @@ const char *llvm::dwarf::AttributeEncodingString(unsigned Encoding) {    return nullptr;  } -/// DecimalSignString - Return the string for the specified decimal sign -/// attribute.  const char *llvm::dwarf::DecimalSignString(unsigned Sign) {    switch (Sign) {    case DW_DS_unsigned:                   return "DW_DS_unsigned"; @@ -519,8 +506,6 @@ const char *llvm::dwarf::DecimalSignString(unsigned Sign) {    return nullptr;  } -/// EndianityString - Return the string for the specified endianity. -///  const char *llvm::dwarf::EndianityString(unsigned Endian) {    switch (Endian) {    case DW_END_default:                   return "DW_END_default"; @@ -532,8 +517,6 @@ const char *llvm::dwarf::EndianityString(unsigned Endian) {    return nullptr;  } -/// AccessibilityString - Return the string for the specified accessibility. -///  const char *llvm::dwarf::AccessibilityString(unsigned Access) {    switch (Access) {    // Accessibility codes @@ -544,8 +527,6 @@ const char *llvm::dwarf::AccessibilityString(unsigned Access) {    return nullptr;  } -/// VisibilityString - Return the string for the specified visibility. -///  const char *llvm::dwarf::VisibilityString(unsigned Visibility) {    switch (Visibility) {    case DW_VIS_local:                     return "DW_VIS_local"; @@ -555,8 +536,6 @@ const char *llvm::dwarf::VisibilityString(unsigned Visibility) {    return nullptr;  } -/// VirtualityString - Return the string for the specified virtuality. -///  const char *llvm::dwarf::VirtualityString(unsigned Virtuality) {    switch (Virtuality) {    case DW_VIRTUALITY_none:               return "DW_VIRTUALITY_none"; @@ -566,8 +545,6 @@ const char *llvm::dwarf::VirtualityString(unsigned Virtuality) {    return nullptr;  } -/// LanguageString - Return the string for the specified language. -///  const char *llvm::dwarf::LanguageString(unsigned Language) {    switch (Language) {    case DW_LANG_C89:                      return "DW_LANG_C89"; @@ -598,13 +575,12 @@ const char *llvm::dwarf::LanguageString(unsigned Language) {    case DW_LANG_C_plus_plus_11:           return "DW_LANG_C_plus_plus_11";    case DW_LANG_OCaml:                    return "DW_LANG_OCaml";    case DW_LANG_lo_user:                  return "DW_LANG_lo_user"; +  case DW_LANG_Mips_Assembler:           return "DW_LANG_Mips_Assembler";    case DW_LANG_hi_user:                  return "DW_LANG_hi_user";    }    return nullptr;  } -/// CaseString - Return the string for the specified identifier case. -///  const char *llvm::dwarf::CaseString(unsigned Case) {    switch (Case) {    case DW_ID_case_sensitive:             return "DW_ID_case_sensitive"; @@ -615,8 +591,6 @@ const char *llvm::dwarf::CaseString(unsigned Case) {    return nullptr;  } -/// ConventionString - Return the string for the specified calling convention. -///  const char *llvm::dwarf::ConventionString(unsigned Convention) {     switch (Convention) {     case DW_CC_normal:                     return "DW_CC_normal"; @@ -628,8 +602,6 @@ const char *llvm::dwarf::ConventionString(unsigned Convention) {    return nullptr;  } -/// InlineCodeString - Return the string for the specified inline code. -///  const char *llvm::dwarf::InlineCodeString(unsigned Code) {    switch (Code) {    case DW_INL_not_inlined:               return "DW_INL_not_inlined"; @@ -640,8 +612,6 @@ const char *llvm::dwarf::InlineCodeString(unsigned Code) {    return nullptr;  } -/// ArrayOrderString - Return the string for the specified array order. -///  const char *llvm::dwarf::ArrayOrderString(unsigned Order) {    switch (Order) {    case DW_ORD_row_major:                 return "DW_ORD_row_major"; @@ -650,8 +620,6 @@ const char *llvm::dwarf::ArrayOrderString(unsigned Order) {    return nullptr;  } -/// DiscriminantString - Return the string for the specified discriminant -/// descriptor.  const char *llvm::dwarf::DiscriminantString(unsigned Discriminant) {    switch (Discriminant) {    case DW_DSC_label:                     return "DW_DSC_label"; @@ -660,8 +628,6 @@ const char *llvm::dwarf::DiscriminantString(unsigned Discriminant) {    return nullptr;  } -/// LNStandardString - Return the string for the specified line number standard. -///  const char *llvm::dwarf::LNStandardString(unsigned Standard) {    switch (Standard) {    case DW_LNS_copy:                      return "DW_LNS_copy"; @@ -680,8 +646,6 @@ const char *llvm::dwarf::LNStandardString(unsigned Standard) {    return nullptr;  } -/// LNExtendedString - Return the string for the specified line number extended -/// opcode encodings.  const char *llvm::dwarf::LNExtendedString(unsigned Encoding) {    switch (Encoding) {    // Line Number Extended Opcode Encodings @@ -695,8 +659,6 @@ const char *llvm::dwarf::LNExtendedString(unsigned Encoding) {    return nullptr;  } -/// MacinfoString - Return the string for the specified macinfo type encodings. -///  const char *llvm::dwarf::MacinfoString(unsigned Encoding) {    switch (Encoding) {    // Macinfo Type Encodings @@ -709,8 +671,6 @@ const char *llvm::dwarf::MacinfoString(unsigned Encoding) {    return nullptr;  } -/// CallFrameString - Return the string for the specified call frame instruction -/// encodings.  const char *llvm::dwarf::CallFrameString(unsigned Encoding) {    switch (Encoding) {    case DW_CFA_nop:                       return "DW_CFA_nop"; @@ -748,6 +708,36 @@ const char *llvm::dwarf::CallFrameString(unsigned Encoding) {    return nullptr;  } +const char *llvm::dwarf::ApplePropertyString(unsigned Prop) { +  switch (Prop) { +  case DW_APPLE_PROPERTY_readonly: +    return "DW_APPLE_PROPERTY_readonly"; +  case DW_APPLE_PROPERTY_getter: +    return "DW_APPLE_PROPERTY_getter"; +  case DW_APPLE_PROPERTY_assign: +    return "DW_APPLE_PROPERTY_assign"; +  case DW_APPLE_PROPERTY_readwrite: +    return "DW_APPLE_PROPERTY_readwrite"; +  case DW_APPLE_PROPERTY_retain: +    return "DW_APPLE_PROPERTY_retain"; +  case DW_APPLE_PROPERTY_copy: +    return "DW_APPLE_PROPERTY_copy"; +  case DW_APPLE_PROPERTY_nonatomic: +    return "DW_APPLE_PROPERTY_nonatomic"; +  case DW_APPLE_PROPERTY_setter: +    return "DW_APPLE_PROPERTY_setter"; +  case DW_APPLE_PROPERTY_atomic: +    return "DW_APPLE_PROPERTY_atomic"; +  case DW_APPLE_PROPERTY_weak: +    return "DW_APPLE_PROPERTY_weak"; +  case DW_APPLE_PROPERTY_strong: +    return "DW_APPLE_PROPERTY_strong"; +  case DW_APPLE_PROPERTY_unsafe_unretained: +    return "DW_APPLE_PROPERTY_unsafe_unretained"; +  } +  return nullptr; +} +  const char *llvm::dwarf::AtomTypeString(unsigned AT) {    switch (AT) {    case dwarf::DW_ATOM_null: @@ -795,3 +785,34 @@ const char *llvm::dwarf::GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage    }    llvm_unreachable("Unknown GDBIndexEntryLinkage value");  } + +const char *llvm::dwarf::AttributeValueString(uint16_t Attr, unsigned Val) { +  switch (Attr) { +  case DW_AT_accessibility: +    return AccessibilityString(Val); +  case DW_AT_virtuality: +    return VirtualityString(Val); +  case DW_AT_language: +    return LanguageString(Val); +  case DW_AT_encoding: +    return AttributeEncodingString(Val); +  case DW_AT_decimal_sign: +    return DecimalSignString(Val); +  case DW_AT_endianity: +    return EndianityString(Val); +  case DW_AT_visibility: +    return VisibilityString(Val); +  case DW_AT_identifier_case: +    return CaseString(Val); +  case DW_AT_calling_convention: +    return ConventionString(Val); +  case DW_AT_inline: +    return InlineCodeString(Val); +  case DW_AT_ordering: +    return ArrayOrderString(Val); +  case DW_AT_discr_value: +    return DiscriminantString(Val); +  } + +  return nullptr; +} diff --git a/lib/Support/ErrorHandling.cpp b/lib/Support/ErrorHandling.cpp index c36007f..8e65066 100644 --- a/lib/Support/ErrorHandling.cpp +++ b/lib/Support/ErrorHandling.cpp @@ -20,6 +20,7 @@  #include "llvm/Support/Debug.h"  #include "llvm/Support/Errc.h"  #include "llvm/Support/Signals.h" +#include "llvm/Support/ManagedStatic.h"  #include "llvm/Support/Mutex.h"  #include "llvm/Support/MutexGuard.h"  #include "llvm/Support/Threading.h" @@ -41,18 +42,18 @@ using namespace llvm;  static fatal_error_handler_t ErrorHandler = nullptr;  static void *ErrorHandlerUserData = nullptr; -static sys::Mutex ErrorHandlerMutex; +static ManagedStatic<sys::Mutex> ErrorHandlerMutex;  void llvm::install_fatal_error_handler(fatal_error_handler_t handler,                                         void *user_data) { -  llvm::MutexGuard Lock(ErrorHandlerMutex); +  llvm::MutexGuard Lock(*ErrorHandlerMutex);    assert(!ErrorHandler && "Error handler already registered!\n");    ErrorHandler = handler;    ErrorHandlerUserData = user_data;  }  void llvm::remove_fatal_error_handler() { -  llvm::MutexGuard Lock(ErrorHandlerMutex); +  llvm::MutexGuard Lock(*ErrorHandlerMutex);    ErrorHandler = nullptr;    ErrorHandlerUserData = nullptr;  } @@ -75,7 +76,7 @@ void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {    {      // Only acquire the mutex while reading the handler, so as not to invoke a      // user-supplied callback under a lock. -    llvm::MutexGuard Lock(ErrorHandlerMutex); +    llvm::MutexGuard Lock(*ErrorHandlerMutex);      handler = ErrorHandler;      handlerData = ErrorHandlerUserData;    } diff --git a/lib/Support/FileOutputBuffer.cpp b/lib/Support/FileOutputBuffer.cpp index 2e740ca..c62655d 100644 --- a/lib/Support/FileOutputBuffer.cpp +++ b/lib/Support/FileOutputBuffer.cpp @@ -14,18 +14,16 @@  #include "llvm/Support/Errc.h"  #include "llvm/Support/FileOutputBuffer.h"  #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h"  #include "llvm/Support/raw_ostream.h"  #include <system_error>  using llvm::sys::fs::mapped_file_region;  namespace llvm { -FileOutputBuffer::FileOutputBuffer(mapped_file_region * R, +FileOutputBuffer::FileOutputBuffer(std::unique_ptr<mapped_file_region> R,                                     StringRef Path, StringRef TmpPath) -  : Region(R) -  , FinalPath(Path) -  , TempPath(TmpPath) { -} +    : Region(std::move(R)), FinalPath(Path), TempPath(TmpPath) {}  FileOutputBuffer::~FileOutputBuffer() {    sys::fs::remove(Twine(TempPath)); @@ -73,21 +71,20 @@ FileOutputBuffer::create(StringRef FilePath, size_t Size,    if (EC)      return EC; -  std::unique_ptr<mapped_file_region> MappedFile(new mapped_file_region( -      FD, true, mapped_file_region::readwrite, Size, 0, EC)); +  auto MappedFile = llvm::make_unique<mapped_file_region>( +      FD, true, mapped_file_region::readwrite, Size, 0, EC);    if (EC)      return EC; -  Result.reset(new FileOutputBuffer(MappedFile.get(), FilePath, TempFilePath)); -  if (Result) -    MappedFile.release(); +  Result.reset( +      new FileOutputBuffer(std::move(MappedFile), FilePath, TempFilePath));    return std::error_code();  }  std::error_code FileOutputBuffer::commit(int64_t NewSmallerSize) {    // Unmap buffer, letting OS flush dirty pages to file on disk. -  Region.reset(nullptr); +  Region.reset();    // If requested, resize file as part of commit.    if ( NewSmallerSize != -1 ) { diff --git a/lib/Support/FileUtilities.cpp b/lib/Support/FileUtilities.cpp index 8a23491..5316f04 100644 --- a/lib/Support/FileUtilities.cpp +++ b/lib/Support/FileUtilities.cpp @@ -182,7 +182,7 @@ int llvm::DiffFilesWithTolerance(StringRef NameA,        *Error = EC.message();      return 2;    } -  std::unique_ptr<MemoryBuffer> F1 = std::move(F1OrErr.get()); +  MemoryBuffer &F1 = *F1OrErr.get();    ErrorOr<std::unique_ptr<MemoryBuffer>> F2OrErr = MemoryBuffer::getFile(NameB);    if (std::error_code EC = F2OrErr.getError()) { @@ -190,17 +190,17 @@ int llvm::DiffFilesWithTolerance(StringRef NameA,        *Error = EC.message();      return 2;    } -  std::unique_ptr<MemoryBuffer> F2 = std::move(F2OrErr.get()); +  MemoryBuffer &F2 = *F2OrErr.get();    // Okay, now that we opened the files, scan them for the first difference. -  const char *File1Start = F1->getBufferStart(); -  const char *File2Start = F2->getBufferStart(); -  const char *File1End = F1->getBufferEnd(); -  const char *File2End = F2->getBufferEnd(); +  const char *File1Start = F1.getBufferStart(); +  const char *File2Start = F2.getBufferStart(); +  const char *File1End = F1.getBufferEnd(); +  const char *File2End = F2.getBufferEnd();    const char *F1P = File1Start;    const char *F2P = File2Start; -  uint64_t A_size = F1->getBufferSize(); -  uint64_t B_size = F2->getBufferSize(); +  uint64_t A_size = F1.getBufferSize(); +  uint64_t B_size = F2.getBufferSize();    // Are the buffers identical?  Common case: Handle this efficiently.    if (A_size == B_size && diff --git a/lib/Support/GraphWriter.cpp b/lib/Support/GraphWriter.cpp index e68ee43..054df52 100644 --- a/lib/Support/GraphWriter.cpp +++ b/lib/Support/GraphWriter.cpp @@ -105,9 +105,10 @@ struct GraphSession {      SmallVector<StringRef, 8> parts;      Names.split(parts, "|");      for (auto Name : parts) { -      ProgramPath = sys::FindProgramByName(Name); -      if (!ProgramPath.empty()) +      if (ErrorOr<std::string> P = sys::findProgramByName(Name)) { +        ProgramPath = *P;          return true; +      }        Log << "  Tried '" << Name << "'\n";      }      return false; diff --git a/lib/Support/Host.cpp b/lib/Support/Host.cpp index e2dd6d5..8782e2e 100644 --- a/lib/Support/Host.cpp +++ b/lib/Support/Host.cpp @@ -759,13 +759,13 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {  #endif      if (LLVMFeatureStr != "") -      Features.GetOrCreateValue(LLVMFeatureStr).setValue(true); +      Features[LLVMFeatureStr] = true;    }  #if defined(__aarch64__)    // If we have all crypto bits we can add the feature    if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2)) -    Features.GetOrCreateValue("crypto").setValue(true); +    Features["crypto"] = true;  #endif    return true; diff --git a/lib/Support/IncludeFile.cpp b/lib/Support/IncludeFile.cpp deleted file mode 100644 index e67acb3..0000000 --- a/lib/Support/IncludeFile.cpp +++ /dev/null @@ -1,20 +0,0 @@ -//===- lib/Support/IncludeFile.cpp - Ensure Linking Of Implementation -----===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the IncludeFile constructor. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/IncludeFile.h" - -using namespace llvm; - -// This constructor is used to ensure linking of other modules. See the -// llvm/Support/IncludeFile.h header for details. -IncludeFile::IncludeFile(const void*) {} diff --git a/lib/Support/LineIterator.cpp b/lib/Support/LineIterator.cpp index 947a8fb..5baa1a3 100644 --- a/lib/Support/LineIterator.cpp +++ b/lib/Support/LineIterator.cpp @@ -12,16 +12,39 @@  using namespace llvm; -line_iterator::line_iterator(const MemoryBuffer &Buffer, char CommentMarker) +static bool isAtLineEnd(const char *P) { +  if (*P == '\n') +    return true; +  if (*P == '\r' && *(P + 1) == '\n') +    return true; +  return false; +} + +static bool skipIfAtLineEnd(const char *&P) { +  if (*P == '\n') { +    ++P; +    return true; +  } +  if (*P == '\r' && *(P + 1) == '\n') { +    P += 2; +    return true; +  } +  return false; +} + +line_iterator::line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks, +                             char CommentMarker)      : Buffer(Buffer.getBufferSize() ? &Buffer : nullptr), -      CommentMarker(CommentMarker), LineNumber(1), +      CommentMarker(CommentMarker), SkipBlanks(SkipBlanks), LineNumber(1),        CurrentLine(Buffer.getBufferSize() ? Buffer.getBufferStart() : nullptr,                    0) {    // Ensure that if we are constructed on a non-empty memory buffer that it is    // a null terminated buffer.    if (Buffer.getBufferSize()) {      assert(Buffer.getBufferEnd()[0] == '\0'); -    advance(); +    // Make sure we don't skip a leading newline if we're keeping blanks +    if (SkipBlanks || !isAtLineEnd(Buffer.getBufferStart())) +      advance();    }  } @@ -29,25 +52,27 @@ void line_iterator::advance() {    assert(Buffer && "Cannot advance past the end!");    const char *Pos = CurrentLine.end(); -  assert(Pos == Buffer->getBufferStart() || *Pos == '\n' || *Pos == '\0'); +  assert(Pos == Buffer->getBufferStart() || isAtLineEnd(Pos) || *Pos == '\0'); -  if (CommentMarker == '\0') { +  if (skipIfAtLineEnd(Pos)) +    ++LineNumber; +  if (!SkipBlanks && isAtLineEnd(Pos)) { +    // Nothing to do for a blank line. +  } else if (CommentMarker == '\0') {      // If we're not stripping comments, this is simpler. -    size_t Blanks = 0; -    while (Pos[Blanks] == '\n') -      ++Blanks; -    Pos += Blanks; -    LineNumber += Blanks; +    while (skipIfAtLineEnd(Pos)) +      ++LineNumber;    } else {      // Skip comments and count line numbers, which is a bit more complex.      for (;;) { +      if (isAtLineEnd(Pos) && !SkipBlanks) +        break;        if (*Pos == CommentMarker)          do {            ++Pos; -        } while (*Pos != '\0' && *Pos != '\n'); -      if (*Pos != '\n') +        } while (*Pos != '\0' && !isAtLineEnd(Pos)); +      if (!skipIfAtLineEnd(Pos))          break; -      ++Pos;        ++LineNumber;      }    } @@ -61,9 +86,9 @@ void line_iterator::advance() {    // Measure the line.    size_t Length = 0; -  do { +  while (Pos[Length] != '\0' && !isAtLineEnd(&Pos[Length])) {      ++Length; -  } while (Pos[Length] != '\0' && Pos[Length] != '\n'); +  }    CurrentLine = StringRef(Pos, Length);  } diff --git a/lib/Support/LockFileManager.cpp b/lib/Support/LockFileManager.cpp index 3f224e0..5b82c36 100644 --- a/lib/Support/LockFileManager.cpp +++ b/lib/Support/LockFileManager.cpp @@ -39,11 +39,11 @@ LockFileManager::readLockFile(StringRef LockFileName) {      sys::fs::remove(LockFileName);      return None;    } -  std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get()); +  MemoryBuffer &MB = *MBOrErr.get();    StringRef Hostname;    StringRef PIDStr; -  std::tie(Hostname, PIDStr) = getToken(MB->getBuffer(), " "); +  std::tie(Hostname, PIDStr) = getToken(MB.getBuffer(), " ");    PIDStr = PIDStr.substr(PIDStr.find_first_not_of(" "));    int PID;    if (!PIDStr.getAsInteger(10, PID)) { @@ -204,8 +204,8 @@ LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() {      // If the lock file is still expected to be there, check whether it still      // is.      if (!LockFileGone) { -      bool Exists; -      if (!sys::fs::exists(LockFileName.str(), Exists) && !Exists) { +      if (sys::fs::access(LockFileName.c_str(), sys::fs::AccessMode::Exist) == +          errc::no_such_file_or_directory) {          LockFileGone = true;          LockFileJustDisappeared = true;        } diff --git a/lib/Support/MD5.cpp b/lib/Support/MD5.cpp index 514466c..ceab580 100644 --- a/lib/Support/MD5.cpp +++ b/lib/Support/MD5.cpp @@ -208,11 +208,11 @@ void MD5::update(ArrayRef<uint8_t> Data) {      memcpy(&buffer[used], Ptr, free);      Ptr = Ptr + free;      Size -= free; -    body(ArrayRef<uint8_t>(buffer, 64)); +    body(makeArrayRef(buffer, 64));    }    if (Size >= 64) { -    Ptr = body(ArrayRef<uint8_t>(Ptr, Size & ~(unsigned long) 0x3f)); +    Ptr = body(makeArrayRef(Ptr, Size & ~(unsigned long) 0x3f));      Size &= 0x3f;    } @@ -229,7 +229,7 @@ void MD5::update(StringRef Str) {  /// \brief Finish the hash and place the resulting hash into \p result.  /// \param result is assumed to be a minimum of 16-bytes in size. -void MD5::final(MD5Result &result) { +void MD5::final(MD5Result &Result) {    unsigned long used, free;    used = lo & 0x3f; @@ -240,7 +240,7 @@ void MD5::final(MD5Result &result) {    if (free < 8) {      memset(&buffer[used], 0, free); -    body(ArrayRef<uint8_t>(buffer, 64)); +    body(makeArrayRef(buffer, 64));      used = 0;      free = 64;    } @@ -257,30 +257,30 @@ void MD5::final(MD5Result &result) {    buffer[62] = hi >> 16;    buffer[63] = hi >> 24; -  body(ArrayRef<uint8_t>(buffer, 64)); - -  result[0] = a; -  result[1] = a >> 8; -  result[2] = a >> 16; -  result[3] = a >> 24; -  result[4] = b; -  result[5] = b >> 8; -  result[6] = b >> 16; -  result[7] = b >> 24; -  result[8] = c; -  result[9] = c >> 8; -  result[10] = c >> 16; -  result[11] = c >> 24; -  result[12] = d; -  result[13] = d >> 8; -  result[14] = d >> 16; -  result[15] = d >> 24; +  body(makeArrayRef(buffer, 64)); + +  Result[0] = a; +  Result[1] = a >> 8; +  Result[2] = a >> 16; +  Result[3] = a >> 24; +  Result[4] = b; +  Result[5] = b >> 8; +  Result[6] = b >> 16; +  Result[7] = b >> 24; +  Result[8] = c; +  Result[9] = c >> 8; +  Result[10] = c >> 16; +  Result[11] = c >> 24; +  Result[12] = d; +  Result[13] = d >> 8; +  Result[14] = d >> 16; +  Result[15] = d >> 24;  } -void MD5::stringifyResult(MD5Result &result, SmallString<32> &Str) { +void MD5::stringifyResult(MD5Result &Result, SmallString<32> &Str) {    raw_svector_ostream Res(Str);    for (int i = 0; i < 16; ++i) -    Res << format("%.2x", result[i]); +    Res << format("%.2x", Result[i]);  }  } diff --git a/lib/Support/MathExtras.cpp b/lib/Support/MathExtras.cpp new file mode 100644 index 0000000..ba09245 --- /dev/null +++ b/lib/Support/MathExtras.cpp @@ -0,0 +1,32 @@ +//===-- MathExtras.cpp - Implement the MathExtras header --------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the MathExtras.h header +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/MathExtras.h" + +#ifdef _MSC_VER +#include <limits> +#else +#include <math.h> +#endif + +namespace llvm { + +#if defined(_MSC_VER) +  // Visual Studio defines the HUGE_VAL class of macros using purposeful +  // constant arithmetic overflow, which it then warns on when encountered. +  const float huge_valf = std::numeric_limits<float>::infinity(); +#else +  const float huge_valf = HUGE_VALF; +#endif + +} diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp index 5f4b7da..7eb0752 100644 --- a/lib/Support/MemoryBuffer.cpp +++ b/lib/Support/MemoryBuffer.cpp @@ -64,14 +64,17 @@ static void CopyStringRef(char *Memory, StringRef Data) {  namespace {  struct NamedBufferAlloc { -  StringRef Name; -  NamedBufferAlloc(StringRef Name) : Name(Name) {} +  const Twine &Name; +  NamedBufferAlloc(const Twine &Name) : Name(Name) {}  };  }  void *operator new(size_t N, const NamedBufferAlloc &Alloc) { -  char *Mem = static_cast<char *>(operator new(N + Alloc.Name.size() + 1)); -  CopyStringRef(Mem + N, Alloc.Name); +  SmallString<256> NameBuf; +  StringRef NameRef = Alloc.Name.toStringRef(NameBuf); + +  char *Mem = static_cast<char *>(operator new(N + NameRef.size() + 1)); +  CopyStringRef(Mem + N, NameRef);    return Mem;  } @@ -94,71 +97,86 @@ public:  };  } -/// getMemBuffer - Open the specified memory range as a MemoryBuffer.  Note -/// that InputData must be a null terminated if RequiresNullTerminator is true! -MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData, -                                         StringRef BufferName, -                                         bool RequiresNullTerminator) { -  return new (NamedBufferAlloc(BufferName)) +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,  +           uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize); + +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName, +                           bool RequiresNullTerminator) { +  auto *Ret = new (NamedBufferAlloc(BufferName))        MemoryBufferMem(InputData, RequiresNullTerminator); +  return std::unique_ptr<MemoryBuffer>(Ret); +} + +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator) { +  return std::unique_ptr<MemoryBuffer>(getMemBuffer( +      Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator));  } -/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, -/// copying the contents and taking ownership of it.  This has no requirements -/// on EndPtr[0]. -MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData, -                                             StringRef BufferName) { -  MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName); -  if (!Buf) return nullptr; +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getMemBufferCopy(StringRef InputData, const Twine &BufferName) { +  std::unique_ptr<MemoryBuffer> Buf = +      getNewUninitMemBuffer(InputData.size(), BufferName); +  if (!Buf) +    return nullptr;    memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),           InputData.size());    return Buf;  } -/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size -/// that is not initialized.  Note that the caller should initialize the -/// memory allocated by this method.  The memory is owned by the MemoryBuffer -/// object. -MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size, -                                                  StringRef BufferName) { +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getNewUninitMemBuffer(size_t Size, const Twine &BufferName) {    // Allocate space for the MemoryBuffer, the data and the name. It is important    // that MemoryBuffer and data are aligned so PointerIntPair works with them.    // TODO: Is 16-byte alignment enough?  We copy small object files with large    // alignment expectations into this buffer. +  SmallString<256> NameBuf; +  StringRef NameRef = BufferName.toStringRef(NameBuf);    size_t AlignedStringLen = -      RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1, 16); +      RoundUpToAlignment(sizeof(MemoryBufferMem) + NameRef.size() + 1, 16);    size_t RealLen = AlignedStringLen + Size + 1;    char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow)); -  if (!Mem) return nullptr; +  if (!Mem) +    return nullptr;    // The name is stored after the class itself. -  CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName); +  CopyStringRef(Mem + sizeof(MemoryBufferMem), NameRef);    // The buffer begins after the name and must be aligned.    char *Buf = Mem + AlignedStringLen;    Buf[Size] = 0; // Null terminate buffer. -  return new (Mem) MemoryBufferMem(StringRef(Buf, Size), true); +  auto *Ret = new (Mem) MemoryBufferMem(StringRef(Buf, Size), true); +  return std::unique_ptr<MemoryBuffer>(Ret);  } -/// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that -/// is completely initialized to zeros.  Note that the caller should -/// initialize the memory allocated by this method.  The memory is owned by -/// the MemoryBuffer object. -MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) { -  MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName); -  if (!SB) return nullptr; +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) { +  std::unique_ptr<MemoryBuffer> SB = getNewUninitMemBuffer(Size, BufferName); +  if (!SB) +    return nullptr;    memset(const_cast<char*>(SB->getBufferStart()), 0, Size);    return SB;  }  ErrorOr<std::unique_ptr<MemoryBuffer>> -MemoryBuffer::getFileOrSTDIN(StringRef Filename, int64_t FileSize) { -  if (Filename == "-") +MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize) { +  SmallString<256> NameBuf; +  StringRef NameRef = Filename.toStringRef(NameBuf); + +  if (NameRef == "-")      return getSTDIN();    return getFile(Filename, FileSize);  } +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize,  +                           uint64_t Offset) { +  return getFileAux(FilePath, -1, MapSize, Offset, false, false); +} +  //===----------------------------------------------------------------------===//  // MemoryBuffer::getFile implementation. @@ -206,7 +224,7 @@ public:  }  static ErrorOr<std::unique_ptr<MemoryBuffer>> -getMemoryBufferForStream(int FD, StringRef BufferName) { +getMemoryBufferForStream(int FD, const Twine &BufferName) {    const ssize_t ChunkSize = 4096*4;    SmallString<ChunkSize> Buffer;    ssize_t ReadBytes; @@ -221,40 +239,32 @@ getMemoryBufferForStream(int FD, StringRef BufferName) {      Buffer.set_size(Buffer.size() + ReadBytes);    } while (ReadBytes != 0); -  std::unique_ptr<MemoryBuffer> Ret( -      MemoryBuffer::getMemBufferCopy(Buffer, BufferName)); -  return std::move(Ret); +  return MemoryBuffer::getMemBufferCopy(Buffer, BufferName);  } -static ErrorOr<std::unique_ptr<MemoryBuffer>> -getFileAux(const char *Filename, int64_t FileSize, bool RequiresNullTerminator, -           bool IsVolatileSize);  ErrorOr<std::unique_ptr<MemoryBuffer>> -MemoryBuffer::getFile(Twine Filename, int64_t FileSize, +MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize,                        bool RequiresNullTerminator, bool IsVolatileSize) { -  // Ensure the path is null terminated. -  SmallString<256> PathBuf; -  StringRef NullTerminatedName = Filename.toNullTerminatedStringRef(PathBuf); -  return getFileAux(NullTerminatedName.data(), FileSize, RequiresNullTerminator, -                    IsVolatileSize); +  return getFileAux(Filename, FileSize, FileSize, 0, +                    RequiresNullTerminator, IsVolatileSize);  }  static ErrorOr<std::unique_ptr<MemoryBuffer>> -getOpenFileImpl(int FD, const char *Filename, uint64_t FileSize, +getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,                  uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,                  bool IsVolatileSize);  static ErrorOr<std::unique_ptr<MemoryBuffer>> -getFileAux(const char *Filename, int64_t FileSize, bool RequiresNullTerminator, -           bool IsVolatileSize) { +getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, +           uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) {    int FD;    std::error_code EC = sys::fs::openFileForRead(Filename, FD);    if (EC)      return EC;    ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = -      getOpenFileImpl(FD, Filename, FileSize, FileSize, 0, +      getOpenFileImpl(FD, Filename, FileSize, MapSize, Offset,                        RequiresNullTerminator, IsVolatileSize);    close(FD);    return Ret; @@ -305,11 +315,19 @@ static bool shouldUseMmap(int FD,    if ((FileSize & (PageSize -1)) == 0)      return false; +#if defined(__CYGWIN__) +  // Don't try to map files that are exactly a multiple of the physical page size +  // if we need a null terminator. +  // FIXME: We should reorganize again getPageSize() on Win32. +  if ((FileSize & (4096 - 1)) == 0) +    return false; +#endif +    return true;  }  static ErrorOr<std::unique_ptr<MemoryBuffer>> -getOpenFileImpl(int FD, const char *Filename, uint64_t FileSize, +getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,                  uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,                  bool IsVolatileSize) {    static int PageSize = sys::process::get_self()->page_size(); @@ -347,15 +365,15 @@ getOpenFileImpl(int FD, const char *Filename, uint64_t FileSize,        return std::move(Result);    } -  MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename); +  std::unique_ptr<MemoryBuffer> Buf = +      MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);    if (!Buf) {      // Failed to create a buffer. The only way it can fail is if      // new(std::nothrow) returns 0.      return make_error_code(errc::not_enough_memory);    } -  std::unique_ptr<MemoryBuffer> SB(Buf); -  char *BufPtr = const_cast<char*>(SB->getBufferStart()); +  char *BufPtr = const_cast<char *>(Buf->getBufferStart());    size_t BytesLeft = MapSize;  #ifndef HAVE_PREAD @@ -383,21 +401,22 @@ getOpenFileImpl(int FD, const char *Filename, uint64_t FileSize,      BufPtr += NumRead;    } -  return std::move(SB); +  return std::move(Buf);  }  ErrorOr<std::unique_ptr<MemoryBuffer>> -MemoryBuffer::getOpenFile(int FD, const char *Filename, uint64_t FileSize, +MemoryBuffer::getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,                            bool RequiresNullTerminator, bool IsVolatileSize) {    return getOpenFileImpl(FD, Filename, FileSize, FileSize, 0,                           RequiresNullTerminator, IsVolatileSize);  }  ErrorOr<std::unique_ptr<MemoryBuffer>> -MemoryBuffer::getOpenFileSlice(int FD, const char *Filename, uint64_t MapSize, -                               int64_t Offset, bool IsVolatileSize) { +MemoryBuffer::getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, +                               int64_t Offset) { +  assert(MapSize != uint64_t(-1));    return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false, -                         IsVolatileSize); +                         /*IsVolatileSize*/ false);  }  ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() { @@ -409,3 +428,9 @@ ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() {    return getMemoryBufferForStream(0, "<stdin>");  } + +MemoryBufferRef MemoryBuffer::getMemBufferRef() const { +  StringRef Data = getBuffer(); +  StringRef Identifier = getBufferIdentifier(); +  return MemoryBufferRef(Data, Identifier); +} diff --git a/lib/Support/MemoryObject.cpp b/lib/Support/MemoryObject.cpp index 02b5b50..d796acf 100644 --- a/lib/Support/MemoryObject.cpp +++ b/lib/Support/MemoryObject.cpp @@ -12,22 +12,3 @@ using namespace llvm;  MemoryObject::~MemoryObject() {  } - -int MemoryObject::readBytes(uint64_t address, -                            uint64_t size, -                            uint8_t* buf) const { -  uint64_t current = address; -  uint64_t limit = getBase() + getExtent(); - -  if (current + size > limit) -    return -1; - -  while (current - address < size) { -    if (readByte(current, &buf[(current - address)])) -      return -1; -     -    current++; -  } -   -  return 0; -} diff --git a/lib/Support/Options.cpp b/lib/Support/Options.cpp new file mode 100644 index 0000000..7125845 --- /dev/null +++ b/lib/Support/Options.cpp @@ -0,0 +1,33 @@ +//===- llvm/Support/Options.cpp - Debug options support ---------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the helper objects for defining debug options using the +// new API built on cl::opt, but not requiring the use of static globals. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Options.h" +#include "llvm/Support/ManagedStatic.h" + +using namespace llvm; + +OptionRegistry::~OptionRegistry() { +  for (auto IT = Options.begin(); IT != Options.end(); ++IT) +    delete IT->second; +} + +void OptionRegistry::addOption(void *Key, cl::Option *O) { +  assert(Options.find(Key) == Options.end() && +         "Argument with this key already registerd"); +  Options.insert(std::make_pair(Key, O)); +} + +static ManagedStatic<OptionRegistry> OR; + +OptionRegistry &OptionRegistry::instance() { return *OR; } diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp index d5a0ec5..a7a9919 100644 --- a/lib/Support/Path.cpp +++ b/lib/Support/Path.cpp @@ -11,9 +11,10 @@  //  //===----------------------------------------------------------------------===// +#include "llvm/Support/COFF.h" +#include "llvm/Support/Endian.h"  #include "llvm/Support/Errc.h"  #include "llvm/Support/Path.h" -#include "llvm/Support/Endian.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/FileSystem.h"  #include "llvm/Support/Process.h" @@ -164,9 +165,6 @@ enum FSEntity {    FS_Name  }; -// Implemented in Unix/Path.inc and Windows/Path.inc. -static std::error_code TempDir(SmallVectorImpl<char> &result); -  static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD,                                            SmallVectorImpl<char> &ResultPath,                                            bool MakeAbsolute, unsigned Mode, @@ -178,8 +176,7 @@ static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD,      // Make model absolute by prepending a temp directory if it's not already.      if (!sys::path::is_absolute(Twine(ModelStorage))) {        SmallString<128> TDir; -      if (std::error_code EC = TempDir(TDir)) -        return EC; +      sys::path::system_temp_directory(true, TDir);        sys::path::append(TDir, Twine(ModelStorage));        ModelStorage.swap(TDir);      } @@ -214,13 +211,13 @@ retry_random_path:    }    case FS_Name: { -    bool Exists; -    std::error_code EC = sys::fs::exists(ResultPath.begin(), Exists); +    std::error_code EC = +        sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist); +    if (EC == errc::no_such_file_or_directory) +      return std::error_code();      if (EC)        return EC; -    if (Exists) -      goto retry_random_path; -    return std::error_code(); +    goto retry_random_path;    }    case FS_Dir: { @@ -308,7 +305,30 @@ const_iterator &const_iterator::operator++() {    return *this;  } -const_iterator &const_iterator::operator--() { +bool const_iterator::operator==(const const_iterator &RHS) const { +  return Path.begin() == RHS.Path.begin() && Position == RHS.Position; +} + +ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const { +  return Position - RHS.Position; +} + +reverse_iterator rbegin(StringRef Path) { +  reverse_iterator I; +  I.Path = Path; +  I.Position = Path.size(); +  return ++I; +} + +reverse_iterator rend(StringRef Path) { +  reverse_iterator I; +  I.Path = Path; +  I.Component = Path.substr(0, 0); +  I.Position = 0; +  return I; +} + +reverse_iterator &reverse_iterator::operator++() {    // If we're at the end and the previous char was a '/', return '.' unless    // we are the root path.    size_t root_dir_pos = root_dir_start(Path); @@ -335,20 +355,12 @@ const_iterator &const_iterator::operator--() {    return *this;  } -bool const_iterator::operator==(const const_iterator &RHS) const { -  return Path.begin() == RHS.Path.begin() && +bool reverse_iterator::operator==(const reverse_iterator &RHS) const { +  return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&           Position == RHS.Position;  } -bool const_iterator::operator!=(const const_iterator &RHS) const { -  return !(*this == RHS); -} - -ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const { -  return Position - RHS.Position; -} - -const StringRef root_path(StringRef path) { +StringRef root_path(StringRef path) {    const_iterator b = begin(path),                   pos = b,                   e = end(path); @@ -380,7 +392,7 @@ const StringRef root_path(StringRef path) {    return StringRef();  } -const StringRef root_name(StringRef path) { +StringRef root_name(StringRef path) {    const_iterator b = begin(path),                   e = end(path);    if (b != e) { @@ -402,7 +414,7 @@ const StringRef root_name(StringRef path) {    return StringRef();  } -const StringRef root_directory(StringRef path) { +StringRef root_directory(StringRef path) {    const_iterator b = begin(path),                   pos = b,                   e = end(path); @@ -431,7 +443,7 @@ const StringRef root_directory(StringRef path) {    return StringRef();  } -const StringRef relative_path(StringRef path) { +StringRef relative_path(StringRef path) {    StringRef root = root_path(path);    return path.substr(root.size());  } @@ -483,7 +495,7 @@ void append(SmallVectorImpl<char> &path,      path::append(path, *begin);  } -const StringRef parent_path(StringRef path) { +StringRef parent_path(StringRef path) {    size_t end_pos = parent_path_end(path);    if (end_pos == StringRef::npos)      return StringRef(); @@ -525,17 +537,27 @@ void native(const Twine &path, SmallVectorImpl<char> &result) {    native(result);  } -void native(SmallVectorImpl<char> &path) { +void native(SmallVectorImpl<char> &Path) {  #ifdef LLVM_ON_WIN32 -  std::replace(path.begin(), path.end(), '/', '\\'); +  std::replace(Path.begin(), Path.end(), '/', '\\'); +#else +  for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) { +    if (*PI == '\\') { +      auto PN = PI + 1; +      if (PN < PE && *PN == '\\') +        ++PI; // increment once, the for loop will move over the escaped slash +      else +        *PI = '/'; +    } +  }  #endif  } -const StringRef filename(StringRef path) { -  return *(--end(path)); +StringRef filename(StringRef path) { +  return *rbegin(path);  } -const StringRef stem(StringRef path) { +StringRef stem(StringRef path) {    StringRef fname = filename(path);    size_t pos = fname.find_last_of('.');    if (pos == StringRef::npos) @@ -548,7 +570,7 @@ const StringRef stem(StringRef path) {        return fname.substr(0, pos);  } -const StringRef extension(StringRef path) { +StringRef extension(StringRef path) {    StringRef fname = filename(path);    size_t pos = fname.find_last_of('.');    if (pos == StringRef::npos) @@ -573,62 +595,10 @@ bool is_separator(char value) {  static const char preferred_separator_string[] = { preferred_separator, '\0' }; -const StringRef get_separator() { +StringRef get_separator() {    return preferred_separator_string;  } -void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result) { -  result.clear(); - -#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) -  // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. -  // macros defined in <unistd.h> on darwin >= 9 -  int ConfName = erasedOnReboot? _CS_DARWIN_USER_TEMP_DIR -                               : _CS_DARWIN_USER_CACHE_DIR; -  size_t ConfLen = confstr(ConfName, nullptr, 0); -  if (ConfLen > 0) { -    do { -      result.resize(ConfLen); -      ConfLen = confstr(ConfName, result.data(), result.size()); -    } while (ConfLen > 0 && ConfLen != result.size()); - -    if (ConfLen > 0) { -      assert(result.back() == 0); -      result.pop_back(); -      return; -    } - -    result.clear(); -  } -#endif - -  // Check whether the temporary directory is specified by an environment -  // variable. -  const char *EnvironmentVariable; -#ifdef LLVM_ON_WIN32 -  EnvironmentVariable = "TEMP"; -#else -  EnvironmentVariable = "TMPDIR"; -#endif -  if (char *RequestedDir = getenv(EnvironmentVariable)) { -    result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); -    return; -  } - -  // Fall back to a system default. -  const char *DefaultResult; -#ifdef LLVM_ON_WIN32 -  (void)erasedOnReboot; -  DefaultResult = "C:\\TEMP"; -#else -  if (erasedOnReboot) -    DefaultResult = "/tmp"; -  else -    DefaultResult = "/var/tmp"; -#endif -  result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); -} -  bool has_root_name(const Twine &path) {    SmallString<128> path_storage;    StringRef p = path.toStringRef(path_storage); @@ -932,10 +902,23 @@ file_magic identify_magic(StringRef Magic) {      return file_magic::unknown;    switch ((unsigned char)Magic[0]) {      case 0x00: { -      // COFF short import library file +      // COFF bigobj or short import library file        if (Magic[1] == (char)0x00 && Magic[2] == (char)0xff && -          Magic[3] == (char)0xff) -        return file_magic::coff_import_library; +          Magic[3] == (char)0xff) { +        size_t MinSize = offsetof(COFF::BigObjHeader, UUID) + sizeof(COFF::BigObjMagic); +        if (Magic.size() < MinSize) +          return file_magic::coff_import_library; + +        int BigObjVersion = *reinterpret_cast<const support::ulittle16_t*>( +            Magic.data() + offsetof(COFF::BigObjHeader, Version)); +        if (BigObjVersion < COFF::BigObjHeader::MinBigObjectVersion) +          return file_magic::coff_import_library; + +        const char *Start = Magic.data() + offsetof(COFF::BigObjHeader, UUID); +        if (memcmp(Start, COFF::BigObjMagic, sizeof(COFF::BigObjMagic)) != 0) +          return file_magic::coff_import_library; +        return file_magic::coff_object; +      }        // Windows resource file        const char Expected[] = { 0, 0, 0, 0, '\x20', 0, 0, 0, '\xff' };        if (Magic.size() >= sizeof(Expected) && @@ -975,6 +958,9 @@ file_magic identify_magic(StringRef Magic) {              case 3: return file_magic::elf_shared_object;              case 4: return file_magic::elf_core;            } +        else +          // It's still some type of ELF file. +          return file_magic::elf;        }        break; @@ -1016,7 +1002,7 @@ file_magic identify_magic(StringRef Magic) {          case 6: return file_magic::macho_dynamically_linked_shared_lib;          case 7: return file_magic::macho_dynamic_linker;          case 8: return file_magic::macho_bundle; -        case 9: return file_magic::macho_dynamic_linker; +        case 9: return file_magic::macho_dynamically_linked_shared_lib_stub;          case 10: return file_magic::macho_dsym_companion;        }        break; @@ -1037,12 +1023,13 @@ file_magic identify_magic(StringRef Magic) {          return file_magic::coff_object;        break; -    case 0x4d: // Possible MS-DOS stub on Windows PE file -      if (Magic[1] == 0x5a) { +    case 'M': // Possible MS-DOS stub on Windows PE file +      if (Magic[1] == 'Z') {          uint32_t off =            *reinterpret_cast<const support::ulittle32_t*>(Magic.data() + 0x3c);          // PE/COFF file, either EXE or DLL. -        if (off < Magic.size() && memcmp(Magic.data() + off, "PE\0\0",4) == 0) +        if (off < Magic.size() && +            memcmp(Magic.data()+off, COFF::PEMagic, sizeof(COFF::PEMagic)) == 0)            return file_magic::pecoff_executable;        }        break; diff --git a/lib/Support/ScaledNumber.cpp b/lib/Support/ScaledNumber.cpp index 3fe027b..fc6d4e7 100644 --- a/lib/Support/ScaledNumber.cpp +++ b/lib/Support/ScaledNumber.cpp @@ -220,6 +220,9 @@ std::string ScaledNumberBase::toString(uint64_t D, int16_t E, int Width,    } else if (E > -64) {      Above0 = D >> -E;      Below0 = D << (64 + E); +  } else if (E == -64) { +    // Special case: shift by 64 bits is undefined behavior. +    Below0 = D;    } else if (E > -120) {      Below0 = D >> (-E - 64);      Extra = D << (128 + E); diff --git a/lib/Support/SmallPtrSet.cpp b/lib/Support/SmallPtrSet.cpp index a80e095..c87ee7d 100644 --- a/lib/Support/SmallPtrSet.cpp +++ b/lib/Support/SmallPtrSet.cpp @@ -34,18 +34,19 @@ void SmallPtrSetImplBase::shrink_and_clear() {    memset(CurArray, -1, CurArraySize*sizeof(void*));  } -bool SmallPtrSetImplBase::insert_imp(const void * Ptr) { +std::pair<const void *const *, bool> +SmallPtrSetImplBase::insert_imp(const void *Ptr) {    if (isSmall()) {      // Check to see if it is already in the set.      for (const void **APtr = SmallArray, **E = SmallArray+NumElements;           APtr != E; ++APtr)        if (*APtr == Ptr) -        return false; -     +        return std::make_pair(APtr, false); +      // Nope, there isn't.  If we stay small, just 'pushback' now. -    if (NumElements < CurArraySize-1) { +    if (NumElements < CurArraySize) {        SmallArray[NumElements++] = Ptr; -      return true; +      return std::make_pair(SmallArray + (NumElements - 1), true);      }      // Otherwise, hit the big set case, which will call grow.    } @@ -61,14 +62,15 @@ bool SmallPtrSetImplBase::insert_imp(const void * Ptr) {    // Okay, we know we have space.  Find a hash bucket.    const void **Bucket = const_cast<const void**>(FindBucketFor(Ptr)); -  if (*Bucket == Ptr) return false; // Already inserted, good. -   +  if (*Bucket == Ptr) +    return std::make_pair(Bucket, false); // Already inserted, good. +    // Otherwise, insert it!    if (*Bucket == getTombstoneMarker())      --NumTombstones;    *Bucket = Ptr;    ++NumElements;  // Track density. -  return true; +  return std::make_pair(Bucket, true);  }  bool SmallPtrSetImplBase::erase_imp(const void * Ptr) { @@ -200,13 +202,12 @@ SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,    if (that.isSmall()) {      CurArray = SmallArray;      memcpy(CurArray, that.CurArray, sizeof(void *) * CurArraySize); -    return; +  } else { +    // Otherwise, we steal the large memory allocation and no copy is needed. +    CurArray = that.CurArray; +    that.CurArray = that.SmallArray;    } -  // Otherwise, we steal the large memory allocation and no copy is needed. -  CurArray = that.CurArray; -  that.CurArray = that.SmallArray; -    // Make the "that" object small and empty.    that.CurArraySize = SmallSize;    assert(that.CurArray == that.SmallArray); diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp index 003cb56..b50a66b 100644 --- a/lib/Support/SourceMgr.cpp +++ b/lib/Support/SourceMgr.cpp @@ -42,11 +42,6 @@ SourceMgr::~SourceMgr() {    // Delete the line # cache if allocated.    if (LineNoCacheTy *Cache = getCache(LineNoCache))      delete Cache; - -  while (!Buffers.empty()) { -    delete Buffers.back().Buffer; -    Buffers.pop_back(); -  }  }  unsigned SourceMgr::AddIncludeFile(const std::string &Filename, @@ -54,20 +49,20 @@ unsigned SourceMgr::AddIncludeFile(const std::string &Filename,                                     std::string &IncludedFile) {    IncludedFile = Filename;    ErrorOr<std::unique_ptr<MemoryBuffer>> NewBufOrErr = -      MemoryBuffer::getFile(IncludedFile.c_str()); +    MemoryBuffer::getFile(IncludedFile);    // If the file didn't exist directly, see if it's in an include path.    for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBufOrErr;         ++i) {      IncludedFile =          IncludeDirectories[i] + sys::path::get_separator().data() + Filename; -    NewBufOrErr = MemoryBuffer::getFile(IncludedFile.c_str()); +    NewBufOrErr = MemoryBuffer::getFile(IncludedFile);    }    if (!NewBufOrErr)      return 0; -  return AddNewSourceBuffer(NewBufOrErr.get().release(), IncludeLoc); +  return AddNewSourceBuffer(std::move(*NewBufOrErr), IncludeLoc);  }  unsigned SourceMgr::FindBufferContainingLoc(SMLoc Loc) const { diff --git a/lib/Support/SpecialCaseList.cpp b/lib/Support/SpecialCaseList.cpp index 21e43c5..785cc60 100644 --- a/lib/Support/SpecialCaseList.cpp +++ b/lib/Support/SpecialCaseList.cpp @@ -48,10 +48,10 @@ struct SpecialCaseList::Entry {  SpecialCaseList::SpecialCaseList() : Entries() {} -SpecialCaseList *SpecialCaseList::create( -    const StringRef Path, std::string &Error) { +std::unique_ptr<SpecialCaseList> SpecialCaseList::create(StringRef Path, +                                                         std::string &Error) {    if (Path.empty()) -    return new SpecialCaseList(); +    return std::unique_ptr<SpecialCaseList>(new SpecialCaseList());    ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =        MemoryBuffer::getFile(Path);    if (std::error_code EC = FileOrErr.getError()) { @@ -61,17 +61,17 @@ SpecialCaseList *SpecialCaseList::create(    return create(FileOrErr.get().get(), Error);  } -SpecialCaseList *SpecialCaseList::create( -    const MemoryBuffer *MB, std::string &Error) { +std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB, +                                                         std::string &Error) {    std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());    if (!SCL->parse(MB, Error))      return nullptr; -  return SCL.release(); +  return SCL;  } -SpecialCaseList *SpecialCaseList::createOrDie(const StringRef Path) { +std::unique_ptr<SpecialCaseList> SpecialCaseList::createOrDie(StringRef Path) {    std::string Error; -  if (SpecialCaseList *SCL = create(Path, Error)) +  if (auto SCL = create(Path, Error))      return SCL;    report_fatal_error(Error);  } @@ -103,18 +103,6 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {      std::string Regexp = SplitRegexp.first;      StringRef Category = SplitRegexp.second; -    // Backwards compatibility. -    if (Prefix == "global-init") { -      Prefix = "global"; -      Category = "init"; -    } else if (Prefix == "global-init-type") { -      Prefix = "type"; -      Category = "init"; -    } else if (Prefix == "global-init-src") { -      Prefix = "src"; -      Category = "init"; -    } -      // See if we can store Regexp in Strings.      if (Regex::isLiteralERE(Regexp)) {        Entries[Prefix][Category].Strings.insert(Regexp); @@ -157,8 +145,8 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {  SpecialCaseList::~SpecialCaseList() {} -bool SpecialCaseList::inSection(const StringRef Section, const StringRef Query, -                                const StringRef Category) const { +bool SpecialCaseList::inSection(StringRef Section, StringRef Query, +                                StringRef Category) const {    StringMap<StringMap<Entry> >::const_iterator I = Entries.find(Section);    if (I == Entries.end()) return false;    StringMap<Entry>::const_iterator II = I->second.find(Category); diff --git a/lib/Support/StreamableMemoryObject.cpp b/lib/Support/StreamingMemoryObject.cpp index 5cb0680..68beeef 100644 --- a/lib/Support/StreamableMemoryObject.cpp +++ b/lib/Support/StreamingMemoryObject.cpp @@ -1,4 +1,4 @@ -//===- StreamableMemoryObject.cpp - Streamable data interface -------------===// +//===- StreamingMemoryObject.cpp - Streamable data interface -------------===//  //  //                     The LLVM Compiler Infrastructure  // @@ -7,7 +7,7 @@  //  //===----------------------------------------------------------------------===// -#include "llvm/Support/StreamableMemoryObject.h" +#include "llvm/Support/StreamingMemoryObject.h"  #include "llvm/Support/Compiler.h"  #include <cassert>  #include <cstddef> @@ -18,27 +18,22 @@ using namespace llvm;  namespace { -class RawMemoryObject : public StreamableMemoryObject { +class RawMemoryObject : public MemoryObject {  public:    RawMemoryObject(const unsigned char *Start, const unsigned char *End) :      FirstChar(Start), LastChar(End) {      assert(LastChar >= FirstChar && "Invalid start/end range");    } -  uint64_t getBase() const override { return 0; }    uint64_t getExtent() const override {      return LastChar - FirstChar;    } -  int readByte(uint64_t address, uint8_t* ptr) const override; -  int readBytes(uint64_t address, uint64_t size, -                uint8_t *buf) const override; +  uint64_t readBytes(uint8_t *Buf, uint64_t Size, +                     uint64_t Address) const override;    const uint8_t *getPointer(uint64_t address, uint64_t size) const override;    bool isValidAddress(uint64_t address) const override {      return validAddress(address);    } -  bool isObjectEnd(uint64_t address) const override { -    return objectEnd(address); -  }  private:    const uint8_t* const FirstChar; @@ -49,26 +44,25 @@ private:    bool validAddress(uint64_t address) const {      return static_cast<std::ptrdiff_t>(address) < LastChar - FirstChar;    } -  bool objectEnd(uint64_t address) const { -    return static_cast<std::ptrdiff_t>(address) == LastChar - FirstChar; -  }    RawMemoryObject(const RawMemoryObject&) LLVM_DELETED_FUNCTION;    void operator=(const RawMemoryObject&) LLVM_DELETED_FUNCTION;  }; -int RawMemoryObject::readByte(uint64_t address, uint8_t* ptr) const { -  if (!validAddress(address)) return -1; -  *ptr = *((uint8_t *)(uintptr_t)(address + FirstChar)); -  return 0; -} +uint64_t RawMemoryObject::readBytes(uint8_t *Buf, uint64_t Size, +                                    uint64_t Address) const { +  uint64_t BufferSize = LastChar - FirstChar; +  if (Address >= BufferSize) +    return 0; -int RawMemoryObject::readBytes(uint64_t address, -                               uint64_t size, -                               uint8_t *buf) const { -  if (!validAddress(address) || !validAddress(address + size - 1)) return -1; -  memcpy(buf, (uint8_t *)(uintptr_t)(address + FirstChar), size); -  return size; +  uint64_t End = Address + Size; +  if (End > BufferSize) +    End = BufferSize; + +  assert(static_cast<int64_t>(End - Address) >= 0); +  Size = End - Address; +  memcpy(Buf, Address + FirstChar, Size); +  return Size;  }  const uint8_t *RawMemoryObject::getPointer(uint64_t address, @@ -85,12 +79,6 @@ bool StreamingMemoryObject::isValidAddress(uint64_t address) const {      return fetchToPos(address);  } -bool StreamingMemoryObject::isObjectEnd(uint64_t address) const { -  if (ObjectSize) return address == ObjectSize; -  fetchToPos(address); -  return address == ObjectSize && address != 0; -} -  uint64_t StreamingMemoryObject::getExtent() const {    if (ObjectSize) return ObjectSize;    size_t pos = BytesRead + kChunkSize; @@ -99,18 +87,19 @@ uint64_t StreamingMemoryObject::getExtent() const {    return ObjectSize;  } -int StreamingMemoryObject::readByte(uint64_t address, uint8_t* ptr) const { -  if (!fetchToPos(address)) return -1; -  *ptr = Bytes[address + BytesSkipped]; -  return 0; -} - -int StreamingMemoryObject::readBytes(uint64_t address, -                                     uint64_t size, -                                     uint8_t *buf) const { -  if (!fetchToPos(address + size - 1)) return -1; -  memcpy(buf, &Bytes[address + BytesSkipped], size); -  return 0; +uint64_t StreamingMemoryObject::readBytes(uint8_t *Buf, uint64_t Size, +                                          uint64_t Address) const { +  fetchToPos(Address + Size - 1); +  if (Address >= BytesRead) +    return 0; + +  uint64_t End = Address + Size; +  if (End > BytesRead) +    End = BytesRead; +  assert(static_cast<int64_t>(End - Address) >= 0); +  Size = End - Address; +  memcpy(Buf, &Bytes[Address + BytesSkipped], Size); +  return Size;  }  bool StreamingMemoryObject::dropLeadingBytes(size_t s) { @@ -125,13 +114,11 @@ void StreamingMemoryObject::setKnownObjectSize(size_t size) {    Bytes.reserve(size);  } -StreamableMemoryObject *getNonStreamedMemoryObject( -    const unsigned char *Start, const unsigned char *End) { +MemoryObject *getNonStreamedMemoryObject(const unsigned char *Start, +                                         const unsigned char *End) {    return new RawMemoryObject(Start, End);  } -StreamableMemoryObject::~StreamableMemoryObject() { } -  StreamingMemoryObject::StreamingMemoryObject(DataStreamer *streamer) :    Bytes(kChunkSize), Streamer(streamer), BytesRead(0), BytesSkipped(0),    ObjectSize(0), EOFReached(false) { diff --git a/lib/Support/StringRef.cpp b/lib/Support/StringRef.cpp index cde8258..ddece08 100644 --- a/lib/Support/StringRef.cpp +++ b/lib/Support/StringRef.cpp @@ -50,7 +50,7 @@ static int ascii_strncasecmp(const char *LHS, const char *RHS, size_t Length) {  /// compare_lower - Compare strings, ignoring case.  int StringRef::compare_lower(StringRef RHS) const { -  if (int Res = ascii_strncasecmp(Data, RHS.Data, min(Length, RHS.Length))) +  if (int Res = ascii_strncasecmp(Data, RHS.Data, std::min(Length, RHS.Length)))      return Res;    if (Length == RHS.Length)      return 0; @@ -71,7 +71,7 @@ bool StringRef::endswith_lower(StringRef Suffix) const {  /// compare_numeric - Compare strings, handle embedded numbers.  int StringRef::compare_numeric(StringRef RHS) const { -  for (size_t I = 0, E = min(Length, RHS.Length); I != E; ++I) { +  for (size_t I = 0, E = std::min(Length, RHS.Length); I != E; ++I) {      // Check for sequences of digits.      if (ascii_isdigit(Data[I]) && ascii_isdigit(RHS.Data[I])) {        // The longer sequence of numbers is considered larger. @@ -105,8 +105,8 @@ unsigned StringRef::edit_distance(llvm::StringRef Other,                                    bool AllowReplacements,                                    unsigned MaxEditDistance) const {    return llvm::ComputeEditDistance( -      llvm::ArrayRef<char>(data(), size()), -      llvm::ArrayRef<char>(Other.data(), Other.size()), +      makeArrayRef(data(), size()), +      makeArrayRef(Other.data(), Other.size()),        AllowReplacements, MaxEditDistance);  } @@ -146,7 +146,7 @@ size_t StringRef::find(StringRef Str, size_t From) const {    // For short haystacks or unsupported needles fall back to the naive algorithm    if (Length < 16 || N > 255 || N == 0) { -    for (size_t e = Length - N + 1, i = min(From, e); i != e; ++i) +    for (size_t e = Length - N + 1, i = std::min(From, e); i != e; ++i)        if (substr(i, N).equals(Str))          return i;      return npos; @@ -201,7 +201,7 @@ StringRef::size_type StringRef::find_first_of(StringRef Chars,    for (size_type i = 0; i != Chars.size(); ++i)      CharBits.set((unsigned char)Chars[i]); -  for (size_type i = min(From, Length), e = Length; i != e; ++i) +  for (size_type i = std::min(From, Length), e = Length; i != e; ++i)      if (CharBits.test((unsigned char)Data[i]))        return i;    return npos; @@ -210,7 +210,7 @@ StringRef::size_type StringRef::find_first_of(StringRef Chars,  /// find_first_not_of - Find the first character in the string that is not  /// \arg C or npos if not found.  StringRef::size_type StringRef::find_first_not_of(char C, size_t From) const { -  for (size_type i = min(From, Length), e = Length; i != e; ++i) +  for (size_type i = std::min(From, Length), e = Length; i != e; ++i)      if (Data[i] != C)        return i;    return npos; @@ -226,7 +226,7 @@ StringRef::size_type StringRef::find_first_not_of(StringRef Chars,    for (size_type i = 0; i != Chars.size(); ++i)      CharBits.set((unsigned char)Chars[i]); -  for (size_type i = min(From, Length), e = Length; i != e; ++i) +  for (size_type i = std::min(From, Length), e = Length; i != e; ++i)      if (!CharBits.test((unsigned char)Data[i]))        return i;    return npos; @@ -242,7 +242,7 @@ StringRef::size_type StringRef::find_last_of(StringRef Chars,    for (size_type i = 0; i != Chars.size(); ++i)      CharBits.set((unsigned char)Chars[i]); -  for (size_type i = min(From, Length) - 1, e = -1; i != e; --i) +  for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i)      if (CharBits.test((unsigned char)Data[i]))        return i;    return npos; @@ -251,7 +251,7 @@ StringRef::size_type StringRef::find_last_of(StringRef Chars,  /// find_last_not_of - Find the last character in the string that is not  /// \arg C, or npos if not found.  StringRef::size_type StringRef::find_last_not_of(char C, size_t From) const { -  for (size_type i = min(From, Length) - 1, e = -1; i != e; --i) +  for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i)      if (Data[i] != C)        return i;    return npos; @@ -267,7 +267,7 @@ StringRef::size_type StringRef::find_last_not_of(StringRef Chars,    for (size_type i = 0, e = Chars.size(); i != e; ++i)      CharBits.set((unsigned char)Chars[i]); -  for (size_type i = min(From, Length) - 1, e = -1; i != e; --i) +  for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i)      if (!CharBits.test((unsigned char)Data[i]))        return i;    return npos; diff --git a/lib/Support/StringRefMemoryObject.cpp b/lib/Support/StringRefMemoryObject.cpp deleted file mode 100644 index e035ed1..0000000 --- a/lib/Support/StringRefMemoryObject.cpp +++ /dev/null @@ -1,29 +0,0 @@ -//===- lib/Support/StringRefMemoryObject.cpp --------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/StringRefMemoryObject.h" - -using namespace llvm; - -int StringRefMemoryObject::readByte(uint64_t Addr, uint8_t *Byte) const { -  if (Addr >= Base + getExtent() || Addr < Base) -    return -1; -  *Byte = Bytes[Addr - Base]; -  return 0; -} - -int StringRefMemoryObject::readBytes(uint64_t Addr, -                                     uint64_t Size, -                                     uint8_t *Buf) const { -  uint64_t Offset = Addr - Base; -  if (Addr >= Base + getExtent() || Offset + Size > getExtent() || Addr < Base) -    return -1; -  memcpy(Buf, Bytes.data() + Offset, Size); -  return 0; -} diff --git a/lib/Support/TimeValue.cpp b/lib/Support/TimeValue.cpp index 4a70797..136b93e 100644 --- a/lib/Support/TimeValue.cpp +++ b/lib/Support/TimeValue.cpp @@ -22,12 +22,6 @@ const TimeValue::SecondsType  const TimeValue::SecondsType    TimeValue::Win32ZeroTimeSeconds = -12591158400ULL; -const TimeValue TimeValue::MinTime       = TimeValue ( INT64_MIN,0 ); -const TimeValue TimeValue::MaxTime       = TimeValue ( INT64_MAX,0 ); -const TimeValue TimeValue::ZeroTime      = TimeValue ( 0,0 ); -const TimeValue TimeValue::PosixZeroTime = TimeValue ( PosixZeroTimeSeconds,0 ); -const TimeValue TimeValue::Win32ZeroTime = TimeValue ( Win32ZeroTimeSeconds,0 ); -  void  TimeValue::normalize( void ) {    if ( nanos_ >= NANOSECONDS_PER_SECOND ) { diff --git a/lib/Support/Timer.cpp b/lib/Support/Timer.cpp index 210bda7..e1a531a 100644 --- a/lib/Support/Timer.cpp +++ b/lib/Support/Timer.cpp @@ -66,10 +66,10 @@ raw_ostream *llvm::CreateInfoOutputFile() {    // each time -stats or -time-passes wants to print output to it. To    // compensate for this, the test-suite Makefiles have code to delete the    // info output file before running commands which write to it. -  std::string Error; -  raw_ostream *Result = new raw_fd_ostream( -      OutputFilename.c_str(), Error, sys::fs::F_Append | sys::fs::F_Text); -  if (Error.empty()) +  std::error_code EC; +  raw_ostream *Result = new raw_fd_ostream(OutputFilename, EC, +                                           sys::fs::F_Append | sys::fs::F_Text); +  if (!EC)      return Result;    errs() << "Error opening info-output-file '" diff --git a/lib/Support/ToolOutputFile.cpp b/lib/Support/ToolOutputFile.cpp index b5fb20f..8ae977d 100644 --- a/lib/Support/ToolOutputFile.cpp +++ b/lib/Support/ToolOutputFile.cpp @@ -16,8 +16,8 @@  #include "llvm/Support/Signals.h"  using namespace llvm; -tool_output_file::CleanupInstaller::CleanupInstaller(const char *filename) -  : Filename(filename), Keep(false) { +tool_output_file::CleanupInstaller::CleanupInstaller(StringRef Filename) +    : Filename(Filename), Keep(false) {    // Arrange for the file to be deleted if the process is killed.    if (Filename != "-")      sys::RemoveFileOnSignal(Filename); @@ -34,14 +34,13 @@ tool_output_file::CleanupInstaller::~CleanupInstaller() {      sys::DontRemoveFileOnSignal(Filename);  } -tool_output_file::tool_output_file(const char *filename, std::string &ErrorInfo, +tool_output_file::tool_output_file(StringRef Filename, std::error_code &EC,                                     sys::fs::OpenFlags Flags) -    : Installer(filename), OS(filename, ErrorInfo, Flags) { +    : Installer(Filename), OS(Filename, EC, Flags) {    // If open fails, no cleanup is needed. -  if (!ErrorInfo.empty()) +  if (EC)      Installer.Keep = true;  } -tool_output_file::tool_output_file(const char *Filename, int FD) -    : Installer(Filename), OS(FD, true) { -} +tool_output_file::tool_output_file(StringRef Filename, int FD) +    : Installer(Filename), OS(FD, true) {} diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index b74ee13..4a4773e 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -23,8 +23,6 @@ const char *Triple::getArchTypeName(ArchType Kind) {    case aarch64_be:  return "aarch64_be";    case arm:         return "arm";    case armeb:       return "armeb"; -  case arm64:       return "arm64"; -  case arm64_be:    return "arm64_be";    case hexagon:     return "hexagon";    case mips:        return "mips";    case mipsel:      return "mipsel"; @@ -47,7 +45,11 @@ const char *Triple::getArchTypeName(ArchType Kind) {    case nvptx:       return "nvptx";    case nvptx64:     return "nvptx64";    case le32:        return "le32"; +  case le64:        return "le64";    case amdil:       return "amdil"; +  case amdil64:     return "amdil64"; +  case hsail:       return "hsail"; +  case hsail64:     return "hsail64";    case spir:        return "spir";    case spir64:      return "spir64";    case kalimba:     return "kalimba"; @@ -69,9 +71,6 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {    case thumb:    case thumbeb:     return "arm"; -  case arm64:        -  case arm64_be:    return "arm64"; -    case ppc64:    case ppc64le:    case ppc:         return "ppc"; @@ -99,8 +98,15 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {    case nvptx64:     return "nvptx";    case le32:        return "le32"; -  case amdil:       return "amdil"; -  case spir:        return "spir"; +  case le64:        return "le64"; + +  case amdil: +  case amdil64:     return "amdil"; + +  case hsail: +  case hsail64:     return "hsail"; + +  case spir:    case spir64:      return "spir";    case kalimba:     return "kalimba";    } @@ -118,6 +124,7 @@ const char *Triple::getVendorTypeName(VendorType Kind) {    case Freescale: return "fsl";    case IBM: return "ibm";    case ImaginationTechnologies: return "img"; +  case MipsTechnologies: return "mti";    case NVIDIA: return "nvidia";    case CSR: return "csr";    } @@ -129,8 +136,6 @@ const char *Triple::getOSTypeName(OSType Kind) {    switch (Kind) {    case UnknownOS: return "unknown"; -  case AuroraUX: return "auroraux"; -  case Cygwin: return "cygwin";    case Darwin: return "darwin";    case DragonFly: return "dragonfly";    case FreeBSD: return "freebsd"; @@ -139,7 +144,6 @@ const char *Triple::getOSTypeName(OSType Kind) {    case Linux: return "linux";    case Lv2: return "lv2";    case MacOSX: return "macosx"; -  case MinGW32: return "mingw32";    case NetBSD: return "netbsd";    case OpenBSD: return "openbsd";    case Solaris: return "solaris"; @@ -181,10 +185,9 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {    return StringSwitch<Triple::ArchType>(Name)      .Case("aarch64", aarch64)      .Case("aarch64_be", aarch64_be) +    .Case("arm64", aarch64) // "arm64" is an alias for "aarch64"      .Case("arm", arm)      .Case("armeb", armeb) -    .Case("arm64", arm64) -    .Case("arm64_be", arm64_be)      .Case("mips", mips)      .Case("mipsel", mipsel)      .Case("mips64", mips64) @@ -208,40 +211,59 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {      .Case("nvptx", nvptx)      .Case("nvptx64", nvptx64)      .Case("le32", le32) +    .Case("le64", le64)      .Case("amdil", amdil) +    .Case("amdil64", amdil64) +    .Case("hsail", hsail) +    .Case("hsail64", hsail64)      .Case("spir", spir)      .Case("spir64", spir64)      .Case("kalimba", kalimba)      .Default(UnknownArch);  } -// Returns architecture name that is understood by the target assembler. -const char *Triple::getArchNameForAssembler() { -  if (!isOSDarwin() && getVendor() != Triple::Apple) -    return nullptr; - -  return StringSwitch<const char*>(getArchName()) -    .Case("i386", "i386") -    .Case("x86_64", "x86_64") -    .Case("powerpc", "ppc") -    .Case("powerpc64", "ppc64") -    .Case("powerpc64le", "ppc64le") -    .Case("arm", "arm") -    .Cases("armv4t", "thumbv4t", "armv4t") -    .Cases("armv5", "armv5e", "thumbv5", "thumbv5e", "armv5") -    .Cases("armv6", "thumbv6", "armv6") -    .Cases("armv7", "thumbv7", "armv7") -    .Case("armeb", "armeb") -    .Case("arm64", "arm64") -    .Case("arm64_be", "arm64") -    .Case("r600", "r600") -    .Case("nvptx", "nvptx") -    .Case("nvptx64", "nvptx64") -    .Case("le32", "le32") -    .Case("amdil", "amdil") -    .Case("spir", "spir") -    .Case("spir64", "spir64") -    .Default(nullptr); +static Triple::ArchType parseARMArch(StringRef ArchName) { +  size_t offset = StringRef::npos; +  Triple::ArchType arch = Triple::UnknownArch; +  bool isThumb = ArchName.startswith("thumb"); + +  if (ArchName.equals("arm")) +    return Triple::arm; +  if (ArchName.equals("armeb")) +    return Triple::armeb; +  if (ArchName.equals("thumb")) +    return Triple::thumb; +  if (ArchName.equals("thumbeb")) +    return Triple::thumbeb; +  if (ArchName.equals("arm64") || ArchName.equals("aarch64")) +    return Triple::aarch64; +  if (ArchName.equals("aarch64_be")) +    return Triple::aarch64_be; + +  if (ArchName.startswith("armv")) { +    offset = 3; +    arch = Triple::arm; +  } else if (ArchName.startswith("armebv")) { +    offset = 5; +    arch = Triple::armeb; +  } else if (ArchName.startswith("thumbv")) { +    offset = 5; +    arch = Triple::thumb; +  } else if (ArchName.startswith("thumbebv")) { +    offset = 7; +    arch = Triple::thumbeb; +  } +  return StringSwitch<Triple::ArchType>(ArchName.substr(offset)) +    .Cases("v2", "v2a", isThumb ? Triple::UnknownArch : arch) +    .Cases("v3", "v3m", isThumb ? Triple::UnknownArch : arch) +    .Cases("v4", "v4t", arch) +    .Cases("v5", "v5e", "v5t", "v5te", "v5tej", arch) +    .Cases("v6", "v6j", "v6k", "v6m", arch) +    .Cases("v6t2", "v6z", "v6zk", arch) +    .Cases("v7", "v7a", "v7em", "v7l", arch) +    .Cases("v7m", "v7r", "v7s", arch) +    .Cases("v8", "v8a", arch) +    .Default(Triple::UnknownArch);  }  static Triple::ArchType parseArch(StringRef ArchName) { @@ -253,20 +275,10 @@ static Triple::ArchType parseArch(StringRef ArchName) {      .Case("powerpc", Triple::ppc)      .Cases("powerpc64", "ppu", Triple::ppc64)      .Case("powerpc64le", Triple::ppc64le) -    .Case("aarch64", Triple::aarch64) -    .Case("aarch64_be", Triple::aarch64_be) -    .Cases("arm", "xscale", Triple::arm) -    // FIXME: It would be good to replace these with explicit names for all the -    // various suffixes supported. -    .StartsWith("armv", Triple::arm) -    .Case("armeb", Triple::armeb) -    .StartsWith("armebv", Triple::armeb) -    .Case("thumb", Triple::thumb) -    .StartsWith("thumbv", Triple::thumb) -    .Case("thumbeb", Triple::thumbeb) -    .StartsWith("thumbebv", Triple::thumbeb) -    .Case("arm64", Triple::arm64) -    .Case("arm64_be", Triple::arm64_be) +    .Case("xscale", Triple::arm) +    .StartsWith("arm", parseARMArch(ArchName)) +    .StartsWith("thumb", parseARMArch(ArchName)) +    .StartsWith("aarch64", parseARMArch(ArchName))      .Case("msp430", Triple::msp430)      .Cases("mips", "mipseb", "mipsallegrex", Triple::mips)      .Cases("mipsel", "mipsallegrexel", Triple::mipsel) @@ -282,10 +294,14 @@ static Triple::ArchType parseArch(StringRef ArchName) {      .Case("nvptx", Triple::nvptx)      .Case("nvptx64", Triple::nvptx64)      .Case("le32", Triple::le32) +    .Case("le64", Triple::le64)      .Case("amdil", Triple::amdil) +    .Case("amdil64", Triple::amdil64) +    .Case("hsail", Triple::hsail) +    .Case("hsail64", Triple::hsail64)      .Case("spir", Triple::spir)      .Case("spir64", Triple::spir64) -    .Case("kalimba", Triple::kalimba) +    .StartsWith("kalimba", Triple::kalimba)      .Default(Triple::UnknownArch);  } @@ -299,6 +315,7 @@ static Triple::VendorType parseVendor(StringRef VendorName) {      .Case("fsl", Triple::Freescale)      .Case("ibm", Triple::IBM)      .Case("img", Triple::ImaginationTechnologies) +    .Case("mti", Triple::MipsTechnologies)      .Case("nvidia", Triple::NVIDIA)      .Case("csr", Triple::CSR)      .Default(Triple::UnknownVendor); @@ -306,8 +323,6 @@ static Triple::VendorType parseVendor(StringRef VendorName) {  static Triple::OSType parseOS(StringRef OSName) {    return StringSwitch<Triple::OSType>(OSName) -    .StartsWith("auroraux", Triple::AuroraUX) -    .StartsWith("cygwin", Triple::Cygwin)      .StartsWith("darwin", Triple::Darwin)      .StartsWith("dragonfly", Triple::DragonFly)      .StartsWith("freebsd", Triple::FreeBSD) @@ -316,7 +331,6 @@ static Triple::OSType parseOS(StringRef OSName) {      .StartsWith("linux", Triple::Linux)      .StartsWith("lv2", Triple::Lv2)      .StartsWith("macosx", Triple::MacOSX) -    .StartsWith("mingw32", Triple::MinGW32)      .StartsWith("netbsd", Triple::NetBSD)      .StartsWith("openbsd", Triple::OpenBSD)      .StartsWith("solaris", Triple::Solaris) @@ -358,6 +372,31 @@ static Triple::ObjectFormatType parseFormat(StringRef EnvironmentName) {      .Default(Triple::UnknownObjectFormat);  } +static Triple::SubArchType parseSubArch(StringRef SubArchName) { +  return StringSwitch<Triple::SubArchType>(SubArchName) +    .EndsWith("v8", Triple::ARMSubArch_v8) +    .EndsWith("v8a", Triple::ARMSubArch_v8) +    .EndsWith("v7", Triple::ARMSubArch_v7) +    .EndsWith("v7a", Triple::ARMSubArch_v7) +    .EndsWith("v7em", Triple::ARMSubArch_v7em) +    .EndsWith("v7l", Triple::ARMSubArch_v7) +    .EndsWith("v7m", Triple::ARMSubArch_v7m) +    .EndsWith("v7r", Triple::ARMSubArch_v7) +    .EndsWith("v7s", Triple::ARMSubArch_v7s) +    .EndsWith("v6", Triple::ARMSubArch_v6) +    .EndsWith("v6m", Triple::ARMSubArch_v6m) +    .EndsWith("v6t2", Triple::ARMSubArch_v6t2) +    .EndsWith("v5", Triple::ARMSubArch_v5) +    .EndsWith("v5e", Triple::ARMSubArch_v5) +    .EndsWith("v5t", Triple::ARMSubArch_v5) +    .EndsWith("v5te", Triple::ARMSubArch_v5te) +    .EndsWith("v4t", Triple::ARMSubArch_v4t) +    .EndsWith("kalimba3", Triple::KalimbaSubArch_v3) +    .EndsWith("kalimba4", Triple::KalimbaSubArch_v4) +    .EndsWith("kalimba5", Triple::KalimbaSubArch_v5) +    .Default(Triple::NoSubArch); +} +  static const char *getObjectFormatTypeName(Triple::ObjectFormatType Kind) {    switch (Kind) {    case Triple::UnknownObjectFormat: return ""; @@ -383,6 +422,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {  Triple::Triple(const Twine &Str)      : Data(Str.str()),        Arch(parseArch(getArchName())), +      SubArch(parseSubArch(getArchName())),        Vendor(parseVendor(getVendorName())),        OS(parseOS(getOSName())),        Environment(parseEnvironment(getEnvironmentName())), @@ -400,6 +440,7 @@ Triple::Triple(const Twine &Str)  Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr)      : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr).str()),        Arch(parseArch(ArchStr.str())), +      SubArch(parseSubArch(ArchStr.str())),        Vendor(parseVendor(VendorStr.str())),        OS(parseOS(OSStr.str())),        Environment(), ObjectFormat(Triple::UnknownObjectFormat) { @@ -416,6 +457,7 @@ Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,      : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr + Twine('-') +              EnvironmentStr).str()),        Arch(parseArch(ArchStr.str())), +      SubArch(parseSubArch(ArchStr.str())),        Vendor(parseVendor(VendorStr.str())),        OS(parseOS(OSStr.str())),        Environment(parseEnvironment(EnvironmentStr.str())), @@ -425,6 +467,9 @@ Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,  }  std::string Triple::normalize(StringRef Str) { +  bool IsMinGW32 = false; +  bool IsCygwin = false; +    // Parse into components.    SmallVector<StringRef, 4> Components;    Str.split(Components, "-"); @@ -441,8 +486,11 @@ std::string Triple::normalize(StringRef Str) {    if (Components.size() > 1)      Vendor = parseVendor(Components[1]);    OSType OS = UnknownOS; -  if (Components.size() > 2) +  if (Components.size() > 2) {      OS = parseOS(Components[2]); +    IsCygwin = Components[2].startswith("cygwin"); +    IsMinGW32 = Components[2].startswith("mingw"); +  }    EnvironmentType Environment = UnknownEnvironment;    if (Components.size() > 3)      Environment = parseEnvironment(Components[3]); @@ -485,7 +533,9 @@ std::string Triple::normalize(StringRef Str) {          break;        case 2:          OS = parseOS(Comp); -        Valid = OS != UnknownOS; +        IsCygwin = Comp.startswith("cygwin"); +        IsMinGW32 = Comp.startswith("mingw"); +        Valid = OS != UnknownOS || IsCygwin || IsMinGW32;          break;        case 3:          Environment = parseEnvironment(Comp); @@ -565,16 +615,16 @@ std::string Triple::normalize(StringRef Str) {        else          Components[3] = getObjectFormatTypeName(ObjectFormat);      } -  } else if (OS == Triple::MinGW32) { +  } else if (IsMinGW32) {      Components.resize(4);      Components[2] = "windows";      Components[3] = "gnu"; -  } else if (OS == Triple::Cygwin) { +  } else if (IsCygwin) {      Components.resize(4);      Components[2] = "windows";      Components[3] = "cygnus";    } -  if (OS == Triple::MinGW32 || OS == Triple::Cygwin || +  if (IsMinGW32 || IsCygwin ||        (OS == Triple::Win32 && Environment != UnknownEnvironment)) {      if (ObjectFormat != UnknownObjectFormat && ObjectFormat != Triple::COFF) {        Components.resize(5); @@ -716,7 +766,7 @@ void Triple::getiOSVersion(unsigned &Major, unsigned &Minor,      getOSVersion(Major, Minor, Micro);      // Default to 5.0 (or 7.0 for arm64).      if (Major == 0) -      Major = (getArch() == arm64) ? 7 : 5; +      Major = (getArch() == aarch64) ? 7 : 5;      break;    }  } @@ -789,7 +839,6 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {    case llvm::Triple::msp430:      return 16; -  case llvm::Triple::amdil:    case llvm::Triple::arm:    case llvm::Triple::armeb:    case llvm::Triple::hexagon: @@ -805,14 +854,15 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {    case llvm::Triple::thumbeb:    case llvm::Triple::x86:    case llvm::Triple::xcore: +  case llvm::Triple::amdil: +  case llvm::Triple::hsail:    case llvm::Triple::spir:    case llvm::Triple::kalimba:      return 32; -  case llvm::Triple::arm64: -  case llvm::Triple::arm64_be:    case llvm::Triple::aarch64:    case llvm::Triple::aarch64_be: +  case llvm::Triple::le64:    case llvm::Triple::mips64:    case llvm::Triple::mips64el:    case llvm::Triple::nvptx64: @@ -821,6 +871,8 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {    case llvm::Triple::sparcv9:    case llvm::Triple::systemz:    case llvm::Triple::x86_64: +  case llvm::Triple::amdil64: +  case llvm::Triple::hsail64:    case llvm::Triple::spir64:      return 64;    } @@ -845,8 +897,6 @@ Triple Triple::get32BitArchVariant() const {    case Triple::UnknownArch:    case Triple::aarch64:    case Triple::aarch64_be: -  case Triple::arm64: -  case Triple::arm64_be:    case Triple::msp430:    case Triple::systemz:    case Triple::ppc64le: @@ -854,6 +904,7 @@ Triple Triple::get32BitArchVariant() const {      break;    case Triple::amdil: +  case Triple::hsail:    case Triple::spir:    case Triple::arm:    case Triple::armeb: @@ -874,12 +925,15 @@ Triple Triple::get32BitArchVariant() const {      // Already 32-bit.      break; +  case Triple::le64:      T.setArch(Triple::le32);    break;    case Triple::mips64:    T.setArch(Triple::mips);    break;    case Triple::mips64el:  T.setArch(Triple::mipsel);  break;    case Triple::nvptx64:   T.setArch(Triple::nvptx);   break;    case Triple::ppc64:     T.setArch(Triple::ppc);     break;    case Triple::sparcv9:   T.setArch(Triple::sparc);   break;    case Triple::x86_64:    T.setArch(Triple::x86);     break; +  case Triple::amdil64:   T.setArch(Triple::amdil);   break; +  case Triple::hsail64:   T.setArch(Triple::hsail);   break;    case Triple::spir64:    T.setArch(Triple::spir);    break;    }    return T; @@ -889,12 +943,10 @@ Triple Triple::get64BitArchVariant() const {    Triple T(*this);    switch (getArch()) {    case Triple::UnknownArch: -  case Triple::amdil:    case Triple::arm:    case Triple::armeb:    case Triple::hexagon:    case Triple::kalimba: -  case Triple::le32:    case Triple::msp430:    case Triple::r600:    case Triple::tce: @@ -906,6 +958,9 @@ Triple Triple::get64BitArchVariant() const {    case Triple::aarch64:    case Triple::aarch64_be: +  case Triple::le64: +  case Triple::amdil64: +  case Triple::hsail64:    case Triple::spir64:    case Triple::mips64:    case Triple::mips64el: @@ -915,18 +970,102 @@ Triple Triple::get64BitArchVariant() const {    case Triple::sparcv9:    case Triple::systemz:    case Triple::x86_64: -  case Triple::arm64: -  case Triple::arm64_be:      // Already 64-bit.      break; +  case Triple::le32:    T.setArch(Triple::le64);      break;    case Triple::mips:    T.setArch(Triple::mips64);    break;    case Triple::mipsel:  T.setArch(Triple::mips64el);  break;    case Triple::nvptx:   T.setArch(Triple::nvptx64);   break;    case Triple::ppc:     T.setArch(Triple::ppc64);     break;    case Triple::sparc:   T.setArch(Triple::sparcv9);   break;    case Triple::x86:     T.setArch(Triple::x86_64);    break; +  case Triple::amdil:   T.setArch(Triple::amdil64);   break; +  case Triple::hsail:   T.setArch(Triple::hsail64);   break;    case Triple::spir:    T.setArch(Triple::spir64);    break;    }    return T;  } + +// FIXME: tblgen this. +const char *Triple::getARMCPUForArch(StringRef MArch) const { +  if (MArch.empty()) +    MArch = getArchName(); + +  switch (getOS()) { +  case llvm::Triple::FreeBSD: +  case llvm::Triple::NetBSD: +    if (MArch == "armv6") +      return "arm1176jzf-s"; +    break; +  case llvm::Triple::Win32: +    // FIXME: this is invalid for WindowsCE +    return "cortex-a9"; +  default: +    break; +  } + +  const char *result = nullptr; +  size_t offset = StringRef::npos; +  if (MArch.startswith("arm")) +    offset = 3; +  if (MArch.startswith("thumb")) +    offset = 5; +  if (offset != StringRef::npos && MArch.substr(offset, 2) == "eb") +    offset += 2; +  if (offset != StringRef::npos) +    result = llvm::StringSwitch<const char *>(MArch.substr(offset)) +      .Cases("v2", "v2a", "arm2") +      .Case("v3", "arm6") +      .Case("v3m", "arm7m") +      .Case("v4", "strongarm") +      .Case("v4t", "arm7tdmi") +      .Cases("v5", "v5t", "arm10tdmi") +      .Cases("v5e", "v5te", "arm1022e") +      .Case("v5tej", "arm926ej-s") +      .Cases("v6", "v6k", "arm1136jf-s") +      .Case("v6j", "arm1136j-s") +      .Cases("v6z", "v6zk", "arm1176jzf-s") +      .Case("v6t2", "arm1156t2-s") +      .Cases("v6m", "v6-m", "cortex-m0") +      .Cases("v7", "v7a", "v7-a", "v7l", "v7-l", "cortex-a8") +      .Cases("v7s", "v7-s", "swift") +      .Cases("v7r", "v7-r", "cortex-r4") +      .Cases("v7m", "v7-m", "cortex-m3") +      .Cases("v7em", "v7e-m", "cortex-m4") +      .Cases("v8", "v8a", "v8-a", "cortex-a53") +      .Default(nullptr); +  else +    result = llvm::StringSwitch<const char *>(MArch) +      .Case("ep9312", "ep9312") +      .Case("iwmmxt", "iwmmxt") +      .Case("xscale", "xscale") +      .Default(nullptr); + +  if (result) +    return result; + +  // If all else failed, return the most base CPU with thumb interworking +  // supported by LLVM. +  // FIXME: Should warn once that we're falling back. +  switch (getOS()) { +  case llvm::Triple::NetBSD: +    switch (getEnvironment()) { +    case llvm::Triple::GNUEABIHF: +    case llvm::Triple::GNUEABI: +    case llvm::Triple::EABIHF: +    case llvm::Triple::EABI: +      return "arm926ej-s"; +    default: +      return "strongarm"; +    } +  default: +    switch (getEnvironment()) { +    case llvm::Triple::EABIHF: +    case llvm::Triple::GNUEABIHF: +      return "arm1176jzf-s"; +    default: +      return "arm7tdmi"; +    } +  } +} diff --git a/lib/Support/Unix/Host.inc b/lib/Support/Unix/Host.inc index c5d36ff..fcb3638 100644 --- a/lib/Support/Unix/Host.inc +++ b/lib/Support/Unix/Host.inc @@ -1,4 +1,4 @@ - //===- llvm/Support/Unix/Host.inc -------------------------------*- C++ -*-===// +//===- llvm/Support/Unix/Host.inc -------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -22,7 +22,6 @@  #include <sys/utsname.h>  #include <cctype>  #include <string> -#include <cstdlib> // ::getenv  using namespace llvm; @@ -39,7 +38,8 @@ std::string sys::getDefaultTargetTriple() {    StringRef TargetTripleString(LLVM_DEFAULT_TARGET_TRIPLE);    std::pair<StringRef, StringRef> ArchSplit = TargetTripleString.split('-'); -  // Normalize the arch, since the target triple may not actually match the target. +  // Normalize the arch, since the target triple may not actually match the +  // target.    std::string Arch = ArchSplit.first;    std::string Triple(Arch); diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc index 623547a..634d404 100644 --- a/lib/Support/Unix/Path.inc +++ b/lib/Support/Unix/Path.inc @@ -87,22 +87,6 @@ namespace {    };  } -static std::error_code TempDir(SmallVectorImpl<char> &result) { -  // FIXME: Don't use TMPDIR if program is SUID or SGID enabled. -  const char *dir = nullptr; -  (dir = std::getenv("TMPDIR")) || (dir = std::getenv("TMP")) || -      (dir = std::getenv("TEMP")) || (dir = std::getenv("TEMPDIR")) || -#ifdef P_tmpdir -      (dir = P_tmpdir) || -#endif -      (dir = "/tmp"); - -  result.clear(); -  StringRef d(dir); -  result.append(d.begin(), d.end()); -  return std::error_code(); -} -  namespace llvm {  namespace sys  {  namespace fs { @@ -272,19 +256,6 @@ std::error_code create_directory(const Twine &path, bool IgnoreExisting) {    return std::error_code();  } -std::error_code normalize_separators(SmallVectorImpl<char> &Path) { -  for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) { -    if (*PI == '\\') { -      auto PN = PI + 1; -      if (PN < PE && *PN == '\\') -        ++PI; // increment once, the for loop will move over the escaped slash -      else -        *PI = '/'; -    } -  } -  return std::error_code(); -} -  // Note that we are using symbolic link because hard links are not supported by  // all filesystems (SMB doesn't).  std::error_code create_link(const Twine &to, const Twine &from) { @@ -350,38 +321,35 @@ std::error_code resize_file(const Twine &path, uint64_t size) {    return std::error_code();  } -std::error_code exists(const Twine &path, bool &result) { -  SmallString<128> path_storage; -  StringRef p = path.toNullTerminatedStringRef(path_storage); - -  if (::access(p.begin(), F_OK) == -1) { -    if (errno != ENOENT) -      return std::error_code(errno, std::generic_category()); -    result = false; -  } else -    result = true; - -  return std::error_code(); +static int convertAccessMode(AccessMode Mode) { +  switch (Mode) { +  case AccessMode::Exist: +    return F_OK; +  case AccessMode::Write: +    return W_OK; +  case AccessMode::Execute: +    return R_OK | X_OK; // scripts also need R_OK. +  } +  llvm_unreachable("invalid enum");  } -bool can_write(const Twine &Path) { +std::error_code access(const Twine &Path, AccessMode Mode) {    SmallString<128> PathStorage;    StringRef P = Path.toNullTerminatedStringRef(PathStorage); -  return 0 == access(P.begin(), W_OK); -} -bool can_execute(const Twine &Path) { -  SmallString<128> PathStorage; -  StringRef P = Path.toNullTerminatedStringRef(PathStorage); +  if (::access(P.begin(), convertAccessMode(Mode)) == -1) +    return std::error_code(errno, std::generic_category()); -  if (0 != access(P.begin(), R_OK | X_OK)) -    return false; -  struct stat buf; -  if (0 != stat(P.begin(), &buf)) -    return false; -  if (!S_ISREG(buf.st_mode)) -    return false; -  return true; +  if (Mode == AccessMode::Execute) { +    // Don't say that directories are executable. +    struct stat buf; +    if (0 != stat(P.begin(), &buf)) +      return errc::permission_denied; +    if (!S_ISREG(buf.st_mode)) +      return errc::permission_denied; +  } + +  return std::error_code();  }  bool equivalent(file_status A, file_status B) { @@ -678,6 +646,66 @@ bool home_directory(SmallVectorImpl<char> &result) {    return false;  } +static const char *getEnvTempDir() { +  // Check whether the temporary directory is specified by an environment +  // variable. +  const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; +  for (const char *Env : EnvironmentVariables) { +    if (const char *Dir = std::getenv(Env)) +      return Dir; +  } + +  return nullptr; +} + +static const char *getDefaultTempDir(bool ErasedOnReboot) { +#ifdef P_tmpdir +  if ((bool)P_tmpdir) +    return P_tmpdir; +#endif + +  if (ErasedOnReboot) +    return "/tmp"; +  return "/var/tmp"; +} + +void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { +  Result.clear(); + +  if (ErasedOnReboot) { +    // There is no env variable for the cache directory. +    if (const char *RequestedDir = getEnvTempDir()) { +      Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); +      return; +    } +  } + +#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) +  // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. +  // macros defined in <unistd.h> on darwin >= 9 +  int ConfName = ErasedOnReboot? _CS_DARWIN_USER_TEMP_DIR +                               : _CS_DARWIN_USER_CACHE_DIR; +  size_t ConfLen = confstr(ConfName, nullptr, 0); +  if (ConfLen > 0) { +    do { +      Result.resize(ConfLen); +      ConfLen = confstr(ConfName, Result.data(), Result.size()); +    } while (ConfLen > 0 && ConfLen != Result.size()); + +    if (ConfLen > 0) { +      assert(Result.back() == 0); +      Result.pop_back(); +      return; +    } + +    Result.clear(); +  } +#endif + +  const char *RequestedDir = getDefaultTempDir(ErasedOnReboot); +  Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); +} +  } // end namespace path  } // end namespace sys diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index d2c5dbc..a429bb3 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -14,15 +14,25 @@  #include "Unix.h"  #include "llvm/ADT/Hashing.h"  #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ManagedStatic.h"  #include "llvm/Support/Mutex.h"  #include "llvm/Support/MutexGuard.h"  #include "llvm/Support/TimeValue.h" +#if HAVE_FCNTL_H +#include <fcntl.h> +#endif  #ifdef HAVE_SYS_TIME_H  #include <sys/time.h>  #endif  #ifdef HAVE_SYS_RESOURCE_H  #include <sys/resource.h>  #endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#if HAVE_SIGNAL_H +#include <signal.h> +#endif  // DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for  // <stdlib.h> instead. Unix.h includes this for us already.  #if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \ @@ -198,6 +208,97 @@ Process::GetArgumentVector(SmallVectorImpl<const char *> &ArgsOut,    return std::error_code();  } +namespace { +class FDCloser { +public: +  FDCloser(int &FD) : FD(FD), KeepOpen(false) {} +  void keepOpen() { KeepOpen = true; } +  ~FDCloser() { +    if (!KeepOpen && FD >= 0) +      ::close(FD); +  } + +private: +  FDCloser(const FDCloser &) LLVM_DELETED_FUNCTION; +  void operator=(const FDCloser &) LLVM_DELETED_FUNCTION; + +  int &FD; +  bool KeepOpen; +}; +} + +std::error_code Process::FixupStandardFileDescriptors() { +  int NullFD = -1; +  FDCloser FDC(NullFD); +  const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}; +  for (int StandardFD : StandardFDs) { +    struct stat st; +    errno = 0; +    while (fstat(StandardFD, &st) < 0) { +      assert(errno && "expected errno to be set if fstat failed!"); +      // fstat should return EBADF if the file descriptor is closed. +      if (errno == EBADF) +        break; +      // retry fstat if we got EINTR, otherwise bubble up the failure. +      if (errno != EINTR) +        return std::error_code(errno, std::generic_category()); +    } +    // if fstat succeeds, move on to the next FD. +    if (!errno) +      continue; +    assert(errno == EBADF && "expected errno to have EBADF at this point!"); + +    if (NullFD < 0) { +      while ((NullFD = open("/dev/null", O_RDWR)) < 0) { +        if (errno == EINTR) +          continue; +        return std::error_code(errno, std::generic_category()); +      } +    } + +    if (NullFD == StandardFD) +      FDC.keepOpen(); +    else if (dup2(NullFD, StandardFD) < 0) +      return std::error_code(errno, std::generic_category()); +  } +  return std::error_code(); +} + +std::error_code Process::SafelyCloseFileDescriptor(int FD) { +  // Create a signal set filled with *all* signals. +  sigset_t FullSet; +  if (sigfillset(&FullSet) < 0) +    return std::error_code(errno, std::generic_category()); +  // Atomically swap our current signal mask with a full mask. +  sigset_t SavedSet; +#if LLVM_ENABLE_THREADS +  if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet)) +    return std::error_code(EC, std::generic_category()); +#else +  if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0) +    return std::error_code(errno, std::generic_category()); +#endif +  // Attempt to close the file descriptor. +  // We need to save the error, if one occurs, because our subsequent call to +  // pthread_sigmask might tamper with errno. +  int ErrnoFromClose = 0; +  if (::close(FD) < 0) +    ErrnoFromClose = errno; +  // Restore the signal mask back to what we saved earlier. +  int EC = 0; +#if LLVM_ENABLE_THREADS +  EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr); +#else +  if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0) +    EC = errno; +#endif +  // The error code from close takes precedence over the one from +  // pthread_sigmask. +  if (ErrnoFromClose) +    return std::error_code(ErrnoFromClose, std::generic_category()); +  return std::error_code(EC, std::generic_category()); +} +  bool Process::StandardInIsUserInput() {    return FileDescriptorIsDisplayed(STDIN_FILENO);  } @@ -263,11 +364,14 @@ extern "C" int del_curterm(struct term *termp);  extern "C" int tigetnum(char *capname);  #endif +#ifdef HAVE_TERMINFO +static ManagedStatic<sys::Mutex> TermColorMutex; +#endif +  static bool terminalHasColors(int fd) {  #ifdef HAVE_TERMINFO    // First, acquire a global lock because these C routines are thread hostile. -  static sys::Mutex M; -  MutexGuard G(M); +  MutexGuard G(*TermColorMutex);    int errret = 0;    if (setupterm((char *)nullptr, fd, &errret) != 0) diff --git a/lib/Support/Unix/Program.inc b/lib/Support/Unix/Program.inc index 06a33cd..0670ad3 100644 --- a/lib/Support/Unix/Program.inc +++ b/lib/Support/Unix/Program.inc @@ -17,8 +17,10 @@  //===----------------------------------------------------------------------===//  #include "Unix.h" +#include "llvm/ADT/StringExtras.h"  #include "llvm/Support/Compiler.h"  #include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h"  #include <llvm/Config/config.h>  #if HAVE_SYS_STAT_H  #include <sys/stat.h> @@ -53,50 +55,31 @@ using namespace sys;  ProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {} -// This function just uses the PATH environment variable to find the program. -std::string -sys::FindProgramByName(const std::string& progName) { - -  // Check some degenerate cases -  if (progName.length() == 0) // no program -    return ""; -  std::string temp = progName; +ErrorOr<std::string> sys::findProgramByName(StringRef Name, +                                            ArrayRef<StringRef> Paths) { +  assert(!Name.empty() && "Must have a name!");    // Use the given path verbatim if it contains any slashes; this matches    // the behavior of sh(1) and friends. -  if (progName.find('/') != std::string::npos) -    return temp; - -  // At this point, the file name is valid and does not contain slashes. Search -  // for it through the directories specified in the PATH environment variable. +  if (Name.find('/') != StringRef::npos) +    return std::string(Name); -  // Get the path. If its empty, we can't do anything to find it. -  const char *PathStr = getenv("PATH"); -  if (!PathStr) -    return ""; +  if (Paths.empty()) { +    SmallVector<StringRef, 16> SearchPaths; +    SplitString(std::getenv("PATH"), SearchPaths, ":"); +    return findProgramByName(Name, SearchPaths); +  } -  // Now we have a colon separated list of directories to search; try them. -  size_t PathLen = strlen(PathStr); -  while (PathLen) { -    // Find the first colon... -    const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); +  for (auto Path : Paths) { +    if (Path.empty()) +      continue;      // Check to see if this first directory contains the executable... -    SmallString<128> FilePath(PathStr,Colon); -    sys::path::append(FilePath, progName); -    if (sys::fs::can_execute(Twine(FilePath))) -      return FilePath.str();                    // Found the executable! - -    // Nope it wasn't in this directory, check the next path in the list! -    PathLen -= Colon-PathStr; -    PathStr = Colon; - -    // Advance past duplicate colons -    while (*PathStr == ':') { -      PathStr++; -      PathLen--; -    } +    SmallString<128> FilePath(Path); +    sys::path::append(FilePath, Name); +    if (sys::fs::can_execute(FilePath.c_str())) +      return std::string(FilePath.str()); // Found the executable!    } -  return ""; +  return std::errc::no_such_file_or_directory;  }  static bool RedirectIO(const StringRef *Path, int FD, std::string* ErrMsg) { @@ -334,7 +317,6 @@ ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,    pid_t ChildPid = PI.Pid;    if (WaitUntilTerminates) {      SecondsToWait = 0; -    ChildPid = -1; // mimic a wait() using waitpid()    } else if (SecondsToWait) {      // Install a timeout handler.  The handler itself does nothing, but the      // simple fact of having a handler at all causes the wait below to return @@ -440,6 +422,23 @@ ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,      return std::error_code();  } +std::error_code +llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents, +                                 WindowsEncodingMethod Encoding /*unused*/) { +  std::error_code EC; +  llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text); + +  if (EC) +    return EC; + +  OS << Contents; + +  if (OS.has_error()) +    return std::make_error_code(std::errc::io_error); + +  return EC; +} +  bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) {    static long ArgMax = sysconf(_SC_ARG_MAX); @@ -448,13 +447,13 @@ bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) {      return true;    // Conservatively account for space required by environment variables. -  ArgMax /= 2; +  long HalfArgMax = ArgMax / 2;    size_t ArgLength = 0;    for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end();         I != E; ++I) {      ArgLength += strlen(*I) + 1; -    if (ArgLength > size_t(ArgMax)) { +    if (ArgLength > size_t(HalfArgMax)) {        return false;      }    } diff --git a/lib/Support/Unix/RWMutex.inc b/lib/Support/Unix/RWMutex.inc index edcbd52..85a1043 100644 --- a/lib/Support/Unix/RWMutex.inc +++ b/lib/Support/Unix/RWMutex.inc @@ -26,26 +26,26 @@ using namespace sys;  // will therefore deadlock if a thread tries to acquire a read lock  // multiple times. -RWMutexImpl::RWMutexImpl() : data_(new Mutex(false)) { } +RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }  RWMutexImpl::~RWMutexImpl() { -  delete static_cast<Mutex *>(data_); +  delete static_cast<MutexImpl *>(data_);  }  bool RWMutexImpl::reader_acquire() { -  return static_cast<Mutex *>(data_)->acquire(); +  return static_cast<MutexImpl *>(data_)->acquire();  }  bool RWMutexImpl::reader_release() { -  return static_cast<Mutex *>(data_)->release(); +  return static_cast<MutexImpl *>(data_)->release();  }  bool RWMutexImpl::writer_acquire() { -  return static_cast<Mutex *>(data_)->acquire(); +  return static_cast<MutexImpl *>(data_)->acquire();  }  bool RWMutexImpl::writer_release() { -  return static_cast<Mutex *>(data_)->release(); +  return static_cast<MutexImpl *>(data_)->release();  }  } diff --git a/lib/Support/Unix/Signals.inc b/lib/Support/Unix/Signals.inc index 1841fea..e8f4643 100644 --- a/lib/Support/Unix/Signals.inc +++ b/lib/Support/Unix/Signals.inc @@ -14,7 +14,14 @@  #include "Unix.h"  #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h"  #include "llvm/Support/Mutex.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/UniqueLock.h" +#include "llvm/Support/raw_ostream.h"  #include <algorithm>  #include <string>  #include <vector> @@ -36,18 +43,22 @@  #if HAVE_MACH_MACH_H  #include <mach/mach.h>  #endif +#if HAVE_LINK_H +#include <link.h> +#endif  using namespace llvm;  static RETSIGTYPE SignalHandler(int Sig);  // defined below. -static SmartMutex<true> SignalsMutex; +static ManagedStatic<SmartMutex<true> > SignalsMutex;  /// InterruptFunction - The function to call if ctrl-c is pressed.  static void (*InterruptFunction)() = nullptr; -static std::vector<std::string> FilesToRemove; -static std::vector<std::pair<void(*)(void*), void*> > CallBacksToRun; +static ManagedStatic<std::vector<std::string>> FilesToRemove; +static ManagedStatic<std::vector<std::pair<void (*)(void *), void *>>> +    CallBacksToRun;  // IntSigs - Signals that represent requested termination. There's no bug  // or failure, or if there is, it's not our direct responsibility. For whatever @@ -55,7 +66,6 @@ static std::vector<std::pair<void(*)(void*), void*> > CallBacksToRun;  static const int IntSigs[] = {    SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2  }; -static const int *const IntSigsEnd = std::end(IntSigs);  // KillSigs - Signals that represent that we have a bug, and our prompt  // termination has been ordered. @@ -74,7 +84,6 @@ static const int KillSigs[] = {    , SIGEMT  #endif  }; -static const int *const KillSigsEnd = std::end(KillSigs);  static unsigned NumRegisteredSignals = 0;  static struct { @@ -105,8 +114,8 @@ static void RegisterHandlers() {    // If the handlers are already registered, we're done.    if (NumRegisteredSignals != 0) return; -  std::for_each(IntSigs, IntSigsEnd, RegisterHandler); -  std::for_each(KillSigs, KillSigsEnd, RegisterHandler); +  for (auto S : IntSigs) RegisterHandler(S); +  for (auto S : KillSigs) RegisterHandler(S);  }  static void UnregisterHandlers() { @@ -125,11 +134,12 @@ static void UnregisterHandlers() {  static void RemoveFilesToRemove() {    // We avoid iterators in case of debug iterators that allocate or release    // memory. -  for (unsigned i = 0, e = FilesToRemove.size(); i != e; ++i) { +  std::vector<std::string>& FilesToRemoveRef = *FilesToRemove; +  for (unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i) {      // 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(); +    const char *path = FilesToRemoveRef[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. @@ -162,28 +172,31 @@ static RETSIGTYPE SignalHandler(int Sig) {    sigfillset(&SigMask);    sigprocmask(SIG_UNBLOCK, &SigMask, nullptr); -  SignalsMutex.acquire(); -  RemoveFilesToRemove(); - -  if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd) { -    if (InterruptFunction) { -      void (*IF)() = InterruptFunction; -      SignalsMutex.release(); -      InterruptFunction = nullptr; -      IF();        // run the interrupt function. +  { +    unique_lock<SmartMutex<true>> Guard(*SignalsMutex); +    RemoveFilesToRemove(); + +    if (std::find(std::begin(IntSigs), std::end(IntSigs), Sig) +        != std::end(IntSigs)) { +      if (InterruptFunction) { +        void (*IF)() = InterruptFunction; +        Guard.unlock(); +        InterruptFunction = nullptr; +        IF();        // run the interrupt function. +        return; +      } + +      Guard.unlock(); +      raise(Sig);   // Execute the default handler.        return; -    } - -    SignalsMutex.release(); -    raise(Sig);   // Execute the default handler. -    return; +   }    } -  SignalsMutex.release(); -    // Otherwise if it is a fault (like SEGV) run any handler. -  for (unsigned i = 0, e = CallBacksToRun.size(); i != e; ++i) -    CallBacksToRun[i].first(CallBacksToRun[i].second); +  std::vector<std::pair<void (*)(void *), void *>>& CallBacksToRunRef = +      *CallBacksToRun; +  for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) +    CallBacksToRunRef[i].first(CallBacksToRunRef[i].second);  #ifdef __s390__    // On S/390, certain signals are delivered with PSW Address pointing to @@ -196,37 +209,39 @@ static RETSIGTYPE SignalHandler(int Sig) {  }  void llvm::sys::RunInterruptHandlers() { -  SignalsMutex.acquire(); +  sys::SmartScopedLock<true> Guard(*SignalsMutex);    RemoveFilesToRemove(); -  SignalsMutex.release();  }  void llvm::sys::SetInterruptFunction(void (*IF)()) { -  SignalsMutex.acquire(); -  InterruptFunction = IF; -  SignalsMutex.release(); +  { +    sys::SmartScopedLock<true> Guard(*SignalsMutex); +    InterruptFunction = IF; +  }    RegisterHandlers();  }  // RemoveFileOnSignal - The public API  bool llvm::sys::RemoveFileOnSignal(StringRef Filename,                                     std::string* ErrMsg) { -  SignalsMutex.acquire(); -  std::string *OldPtr = FilesToRemove.empty() ? nullptr : &FilesToRemove[0]; -  FilesToRemove.push_back(Filename); - -  // We want to call 'c_str()' on every std::string in this vector so that if -  // the underlying implementation requires a re-allocation, it happens here -  // rather than inside of the signal handler. If we see the vector grow, we -  // have to call it on every entry. If it remains in place, we only need to -  // call it on the latest one. -  if (OldPtr == &FilesToRemove[0]) -    FilesToRemove.back().c_str(); -  else -    for (unsigned i = 0, e = FilesToRemove.size(); i != e; ++i) -      FilesToRemove[i].c_str(); - -  SignalsMutex.release(); +  { +    sys::SmartScopedLock<true> Guard(*SignalsMutex); +    std::vector<std::string>& FilesToRemoveRef = *FilesToRemove; +    std::string *OldPtr = +        FilesToRemoveRef.empty() ? nullptr : &FilesToRemoveRef[0]; +    FilesToRemoveRef.push_back(Filename); + +    // We want to call 'c_str()' on every std::string in this vector so that if +    // the underlying implementation requires a re-allocation, it happens here +    // rather than inside of the signal handler. If we see the vector grow, we +    // have to call it on every entry. If it remains in place, we only need to +    // call it on the latest one. +    if (OldPtr == &FilesToRemoveRef[0]) +      FilesToRemoveRef.back().c_str(); +    else +      for (unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i) +        FilesToRemoveRef[i].c_str(); +  }    RegisterHandlers();    return false; @@ -234,31 +249,166 @@ bool llvm::sys::RemoveFileOnSignal(StringRef Filename,  // DontRemoveFileOnSignal - The public API  void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) { -  SignalsMutex.acquire(); +  sys::SmartScopedLock<true> Guard(*SignalsMutex);    std::vector<std::string>::reverse_iterator RI = -    std::find(FilesToRemove.rbegin(), FilesToRemove.rend(), Filename); -  std::vector<std::string>::iterator I = FilesToRemove.end(); -  if (RI != FilesToRemove.rend()) -    I = FilesToRemove.erase(RI.base()-1); +    std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename); +  std::vector<std::string>::iterator I = FilesToRemove->end(); +  if (RI != FilesToRemove->rend()) +    I = FilesToRemove->erase(RI.base()-1);    // We need to call c_str() on every element which would have been moved by    // the erase. These elements, in a C++98 implementation where c_str()    // requires a reallocation on the first call may have had the call to c_str()    // made on insertion become invalid by being copied down an element. -  for (std::vector<std::string>::iterator E = FilesToRemove.end(); I != E; ++I) +  for (std::vector<std::string>::iterator E = FilesToRemove->end(); I != E; ++I)      I->c_str(); - -  SignalsMutex.release();  }  /// AddSignalHandler - Add a function to be called when a signal is delivered  /// to the process.  The handler can have a cookie passed to it to identify  /// what instance of the handler it is.  void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { -  CallBacksToRun.push_back(std::make_pair(FnPtr, Cookie)); +  CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie));    RegisterHandlers();  } +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) + +#if HAVE_LINK_H && (defined(__linux__) || defined(__FreeBSD__) ||              \ +                    defined(__FreeBSD_kernel__) || defined(__NetBSD__)) +struct DlIteratePhdrData { +  void **StackTrace; +  int depth; +  bool first; +  const char **modules; +  intptr_t *offsets; +  const char *main_exec_name; +}; + +static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { +  DlIteratePhdrData *data = (DlIteratePhdrData*)arg; +  const char *name = data->first ? data->main_exec_name : info->dlpi_name; +  data->first = false; +  for (int i = 0; i < info->dlpi_phnum; i++) { +    const auto *phdr = &info->dlpi_phdr[i]; +    if (phdr->p_type != PT_LOAD) +      continue; +    intptr_t beg = info->dlpi_addr + phdr->p_vaddr; +    intptr_t end = beg + phdr->p_memsz; +    for (int j = 0; j < data->depth; j++) { +      if (data->modules[j]) +        continue; +      intptr_t addr = (intptr_t)data->StackTrace[j]; +      if (beg <= addr && addr < end) { +        data->modules[j] = name; +        data->offsets[j] = addr - info->dlpi_addr; +      } +    } +  } +  return 0; +} + +static bool findModulesAndOffsets(void **StackTrace, int Depth, +                                  const char **Modules, intptr_t *Offsets, +                                  const char *MainExecutableName) { +  DlIteratePhdrData data = {StackTrace, Depth,   true, +                            Modules,    Offsets, MainExecutableName}; +  dl_iterate_phdr(dl_iterate_phdr_cb, &data); +  return true; +} +#else +static bool findModulesAndOffsets(void **StackTrace, int Depth, +                                  const char **Modules, intptr_t *Offsets, +                                  const char *MainExecutableName) { +  return false; +} +#endif + +static bool printSymbolizedStackTrace(void **StackTrace, int Depth, FILE *FD) { +  // FIXME: Subtract necessary number from StackTrace entries to turn return addresses +  // into actual instruction addresses. +  // Use llvm-symbolizer tool to symbolize the stack traces. +  ErrorOr<std::string> LLVMSymbolizerPathOrErr = +      sys::findProgramByName("llvm-symbolizer"); +  if (!LLVMSymbolizerPathOrErr) +    return false; +  const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr; +  // We don't know argv0 or the address of main() at this point, but try +  // to guess it anyway (it's possible on some platforms). +  std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); +  if (MainExecutableName.empty() || +      MainExecutableName.find("llvm-symbolizer") != std::string::npos) +    return false; + +  std::vector<const char *> Modules(Depth, nullptr); +  std::vector<intptr_t> Offsets(Depth, 0); +  if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(), Offsets.data(), +                             MainExecutableName.c_str())) +    return false; +  int InputFD; +  SmallString<32> InputFile, OutputFile; +  sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile); +  sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile); +  FileRemover InputRemover(InputFile.c_str()); +  FileRemover OutputRemover(OutputFile.c_str()); + +  { +    raw_fd_ostream Input(InputFD, true); +    for (int i = 0; i < Depth; i++) { +      if (Modules[i]) +        Input << Modules[i] << " " << (void*)Offsets[i] << "\n"; +    } +  } + +  StringRef InputFileStr(InputFile); +  StringRef OutputFileStr(OutputFile); +  StringRef StderrFileStr; +  const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr, +                                  &StderrFileStr}; +  const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining", +                        "--demangle", nullptr}; +  int RunResult = +      sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects); +  if (RunResult != 0) +    return false; + +  auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str()); +  if (!OutputBuf) +    return false; +  StringRef Output = OutputBuf.get()->getBuffer(); +  SmallVector<StringRef, 32> Lines; +  Output.split(Lines, "\n"); +  auto CurLine = Lines.begin(); +  int frame_no = 0; +  for (int i = 0; i < Depth; i++) { +    if (!Modules[i]) { +      fprintf(FD, "#%d %p\n", frame_no++, StackTrace[i]); +      continue; +    } +    // Read pairs of lines (function name and file/line info) until we +    // encounter empty line. +    for (;;) { +      if (CurLine == Lines.end()) +        return false; +      StringRef FunctionName = *CurLine++; +      if (FunctionName.empty()) +        break; +      fprintf(FD, "#%d %p ", frame_no++, StackTrace[i]); +      if (!FunctionName.startswith("??")) +        fprintf(FD, "%s ", FunctionName.str().c_str()); +      if (CurLine == Lines.end()) +        return false; +      StringRef FileLineInfo = *CurLine++; +      if (!FileLineInfo.startswith("??")) +        fprintf(FD, "%s", FileLineInfo.str().c_str()); +      else +        fprintf(FD, "(%s+%p)", Modules[i], (void *)Offsets[i]); +      fprintf(FD, "\n"); +    } +  } +  return true; +} +#endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)  // PrintStackTrace - In the case of a program crash or fault, print out a stack  // trace so that the user has an indication of why and where we died. @@ -271,6 +421,8 @@ void llvm::sys::PrintStackTrace(FILE *FD) {    // Use backtrace() to output a backtrace on Linux systems with glibc.    int depth = backtrace(StackTrace,                          static_cast<int>(array_lengthof(StackTrace))); +  if (printSymbolizedStackTrace(StackTrace, depth, FD)) +    return;  #if HAVE_DLFCN_H && __GNUG__    int width = 0;    for (int i = 0; i < depth; ++i) { diff --git a/lib/Support/Unix/TimeValue.inc b/lib/Support/Unix/TimeValue.inc index 7d4acf7..042e0da 100644 --- a/lib/Support/Unix/TimeValue.inc +++ b/lib/Support/Unix/TimeValue.inc @@ -41,7 +41,7 @@ TimeValue TimeValue::now() {      // errors concern the timezone parameter which we're passing in as 0.      // In the unlikely case it does happen, just return MinTime, no error      // message needed. -    return MinTime; +    return MinTime();    }    return TimeValue( diff --git a/lib/Support/Unix/Unix.h b/lib/Support/Unix/Unix.h index ba688e3..e16a226 100644 --- a/lib/Support/Unix/Unix.h +++ b/lib/Support/Unix/Unix.h @@ -11,8 +11,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_UNIX_UNIX_H -#define LLVM_SYSTEM_UNIX_UNIX_H +#ifndef LLVM_LIB_SUPPORT_UNIX_UNIX_H +#define LLVM_LIB_SUPPORT_UNIX_UNIX_H  //===----------------------------------------------------------------------===//  //=== WARNING: Implementation here must contain only generic UNIX code that diff --git a/lib/Support/Windows/DynamicLibrary.inc b/lib/Support/Windows/DynamicLibrary.inc index 5ed0b70..79d5f79 100644 --- a/lib/Support/Windows/DynamicLibrary.inc +++ b/lib/Support/Windows/DynamicLibrary.inc @@ -41,32 +41,11 @@ using namespace sys;  static DenseSet<HMODULE> *OpenedHandles; -extern "C" { - -  static BOOL CALLBACK ELM_Callback(WIN32_ELMCB_PCSTR ModuleName, -                                    ULONG_PTR ModuleBase, -                                    ULONG ModuleSize, -                                    PVOID UserContext) -  { -    // Ignore VC++ runtimes prior to 7.1.  Somehow some of them get loaded -    // into the process. -    if (stricmp(ModuleName, "msvci70") != 0 && -        stricmp(ModuleName, "msvcirt") != 0 && -        stricmp(ModuleName, "msvcp50") != 0 && -        stricmp(ModuleName, "msvcp60") != 0 && -        stricmp(ModuleName, "msvcp70") != 0 && -        stricmp(ModuleName, "msvcr70") != 0 && -#ifndef __MINGW32__ -        // Mingw32 uses msvcrt.dll by default. Don't ignore it. -        // Otherwise the user should be aware what they are doing. -        stricmp(ModuleName, "msvcrt") != 0 && -#endif -        stricmp(ModuleName, "msvcrt20") != 0 && -        stricmp(ModuleName, "msvcrt40") != 0) { -      OpenedHandles->insert((HMODULE)ModuleBase); -    } -    return TRUE; -  } +static BOOL CALLBACK +ELM_Callback(WIN32_ELMCB_PCSTR ModuleName, ULONG_PTR ModuleBase, +             ULONG ModuleSize, PVOID UserContext) { +  OpenedHandles->insert((HMODULE)ModuleBase); +  return TRUE;  }  DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, @@ -115,10 +94,24 @@ DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,    extern "C" { extern void *SYM; }  #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO) +#ifdef _M_IX86 +// Win32 on x86 implements certain single-precision math functions as macros. +// These functions are not exported by the DLL, but will still be needed +// for symbol-resolution by the JIT loader. Therefore, this Support libray +// provides helper functions with the same implementation. + +#define INLINE_DEF_SYMBOL1(TYP, SYM)                                           \ +  extern "C" TYP inline_##SYM(TYP _X) { return SYM(_X); } +#define INLINE_DEF_SYMBOL2(TYP, SYM)                                           \ +  extern "C" TYP inline_##SYM(TYP _X, TYP _Y) { return SYM(_X, _Y); } +#endif +  #include "explicit_symbols.inc"  #undef EXPLICIT_SYMBOL  #undef EXPLICIT_SYMBOL2 +#undef INLINE_DEF_SYMBOL1 +#undef INLINE_DEF_SYMBOL2  void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {    SmartScopedLock<true> Lock(*SymbolsMutex); @@ -142,22 +135,32 @@ void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {      }    } -  #define EXPLICIT_SYMBOL(SYM)                    \ -    if (!strcmp(symbolName, #SYM)) return (void*)&SYM; -  #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO)        \ -    if (!strcmp(symbolName, #SYMFROM)) return (void*)&SYMTO; +#define EXPLICIT_SYMBOL(SYM)                                                   \ +  if (!strcmp(symbolName, #SYM))                                               \ +    return (void *)&SYM; +#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO)                                       \ +  if (!strcmp(symbolName, #SYMFROM))                                           \ +    return (void *)&SYMTO; + +#ifdef _M_IX86 +#define INLINE_DEF_SYMBOL1(TYP, SYM)                                           \ +  if (!strcmp(symbolName, #SYM))                                               \ +    return (void *)&inline_##SYM; +#define INLINE_DEF_SYMBOL2(TYP, SYM) INLINE_DEF_SYMBOL1(TYP, SYM) +#endif    { -    #include "explicit_symbols.inc" +#include "explicit_symbols.inc"    } -  #undef EXPLICIT_SYMBOL -  #undef EXPLICIT_SYMBOL2 +#undef EXPLICIT_SYMBOL +#undef EXPLICIT_SYMBOL2 +#undef INLINE_DEF_SYMBOL1 +#undef INLINE_DEF_SYMBOL2    return 0;  } -  void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {    if (!isValid())      return NULL; @@ -166,5 +169,4 @@ void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {    return (void *)(intptr_t)GetProcAddress((HMODULE)Data, symbolName);  } -  } diff --git a/lib/Support/Windows/Host.inc b/lib/Support/Windows/Host.inc index 0c02bf9..fe89fe0a 100644 --- a/lib/Support/Windows/Host.inc +++ b/lib/Support/Windows/Host.inc @@ -1,4 +1,4 @@ -//===- llvm/Support/Win32/Host.inc -------------------------------*- C++ -*-===// +//===- llvm/Support/Win32/Host.inc ------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc index 7a1bc04..365031c 100644 --- a/lib/Support/Windows/Path.inc +++ b/lib/Support/Windows/Path.inc @@ -49,23 +49,6 @@ static std::error_code windows_error(DWORD E) {    return mapWindowsError(E);  } -static std::error_code TempDir(SmallVectorImpl<char> &Result) { -  SmallVector<wchar_t, 64> Res; -retry_temp_dir: -  DWORD Len = ::GetTempPathW(Res.capacity(), Res.begin()); - -  if (Len == 0) -    return windows_error(::GetLastError()); - -  if (Len > Res.capacity()) { -    Res.reserve(Len); -    goto retry_temp_dir; -  } - -  Res.set_size(Len); -  return UTF16ToUTF8(Res.begin(), Res.size(), Result); -} -  static bool is_separator(const wchar_t value) {    switch (value) {    case L'\\': @@ -76,6 +59,59 @@ static bool is_separator(const wchar_t value) {    }  } +// Convert a UTF-8 path to UTF-16.  Also, if the absolute equivalent of the +// path is longer than CreateDirectory can tolerate, make it absolute and +// prefixed by '\\?\'. +static std::error_code widenPath(const Twine &Path8, +                                 SmallVectorImpl<wchar_t> &Path16) { +  const size_t MaxDirLen = MAX_PATH - 12; // Must leave room for 8.3 filename. + +  // Several operations would convert Path8 to SmallString; more efficient to +  // do it once up front. +  SmallString<128> Path8Str; +  Path8.toVector(Path8Str); + +  // If we made this path absolute, how much longer would it get? +  size_t CurPathLen; +  if (llvm::sys::path::is_absolute(Twine(Path8Str))) +    CurPathLen = 0; // No contribution from current_path needed. +  else { +    CurPathLen = ::GetCurrentDirectoryW(0, NULL); +    if (CurPathLen == 0) +      return windows_error(::GetLastError()); +  } + +  // Would the absolute path be longer than our limit? +  if ((Path8Str.size() + CurPathLen) >= MaxDirLen && +      !Path8Str.startswith("\\\\?\\")) { +    SmallString<2*MAX_PATH> FullPath("\\\\?\\"); +    if (CurPathLen) { +      SmallString<80> CurPath; +      if (std::error_code EC = llvm::sys::fs::current_path(CurPath)) +        return EC; +      FullPath.append(CurPath); +    } +    // Traverse the requested path, canonicalizing . and .. as we go (because +    // the \\?\ prefix is documented to treat them as real components). +    // The iterators don't report separators and append() always attaches +    // preferred_separator so we don't need to call native() on the result. +    for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(Path8Str), +                                         E = llvm::sys::path::end(Path8Str); +                                         I != E; ++I) { +      if (I->size() == 1 && *I == ".") +        continue; +      if (I->size() == 2 && *I == "..") +        llvm::sys::path::remove_filename(FullPath); +      else +        llvm::sys::path::append(FullPath, *I); +    } +    return UTF8ToUTF16(FullPath, Path16); +  } + +  // Just use the caller's original path. +  return UTF8ToUTF16(Path8Str, Path16); +} +  namespace llvm {  namespace sys  {  namespace fs { @@ -147,11 +183,9 @@ std::error_code current_path(SmallVectorImpl<char> &result) {  }  std::error_code create_directory(const Twine &path, bool IgnoreExisting) { -  SmallString<128> path_storage;    SmallVector<wchar_t, 128> path_utf16; -  if (std::error_code ec = -          UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) +  if (std::error_code ec = widenPath(path, path_utf16))      return ec;    if (!::CreateDirectoryW(path_utf16.begin(), NULL)) { @@ -163,25 +197,14 @@ std::error_code create_directory(const Twine &path, bool IgnoreExisting) {    return std::error_code();  } -std::error_code normalize_separators(SmallVectorImpl<char> &Path) { -  (void) Path; -  return std::error_code(); -} -  // We can't use symbolic links for windows.  std::error_code create_link(const Twine &to, const Twine &from) { -  // Get arguments. -  SmallString<128> from_storage; -  SmallString<128> to_storage; -  StringRef f = from.toStringRef(from_storage); -  StringRef t = to.toStringRef(to_storage); -    // Convert to utf-16.    SmallVector<wchar_t, 128> wide_from;    SmallVector<wchar_t, 128> wide_to; -  if (std::error_code ec = UTF8ToUTF16(f, wide_from)) +  if (std::error_code ec = widenPath(from, wide_from))      return ec; -  if (std::error_code ec = UTF8ToUTF16(t, wide_to)) +  if (std::error_code ec = widenPath(to, wide_to))      return ec;    if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL)) @@ -191,7 +214,6 @@ std::error_code create_link(const Twine &to, const Twine &from) {  }  std::error_code remove(const Twine &path, bool IgnoreNonExisting) { -  SmallString<128> path_storage;    SmallVector<wchar_t, 128> path_utf16;    file_status ST; @@ -201,8 +223,7 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) {      return std::error_code();    } -  if (std::error_code ec = -          UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) +  if (std::error_code ec = widenPath(path, path_utf16))      return ec;    if (ST.type() == file_type::directory_file) { @@ -222,18 +243,12 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) {  }  std::error_code rename(const Twine &from, const Twine &to) { -  // Get arguments. -  SmallString<128> from_storage; -  SmallString<128> to_storage; -  StringRef f = from.toStringRef(from_storage); -  StringRef t = to.toStringRef(to_storage); -    // Convert to utf-16.    SmallVector<wchar_t, 128> wide_from;    SmallVector<wchar_t, 128> wide_to; -  if (std::error_code ec = UTF8ToUTF16(f, wide_from)) +  if (std::error_code ec = widenPath(from, wide_from))      return ec; -  if (std::error_code ec = UTF8ToUTF16(t, wide_to)) +  if (std::error_code ec = widenPath(to, wide_to))      return ec;    std::error_code ec = std::error_code(); @@ -254,11 +269,9 @@ std::error_code rename(const Twine &from, const Twine &to) {  }  std::error_code resize_file(const Twine &path, uint64_t size) { -  SmallString<128> path_storage;    SmallVector<wchar_t, 128> path_utf16; -  if (std::error_code ec = -          UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) +  if (std::error_code ec = widenPath(path, path_utf16))      return ec;    int fd = ::_wopen(path_utf16.begin(), O_BINARY | _O_RDWR, S_IWRITE); @@ -273,49 +286,27 @@ std::error_code resize_file(const Twine &path, uint64_t size) {    return std::error_code(error, std::generic_category());  } -std::error_code exists(const Twine &path, bool &result) { -  SmallString<128> path_storage; -  SmallVector<wchar_t, 128> path_utf16; +std::error_code access(const Twine &Path, AccessMode Mode) { +  SmallVector<wchar_t, 128> PathUtf16; -  if (std::error_code ec = -          UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) -    return ec; +  if (std::error_code EC = widenPath(Path, PathUtf16)) +    return EC; -  DWORD attributes = ::GetFileAttributesW(path_utf16.begin()); +  DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin()); -  if (attributes == INVALID_FILE_ATTRIBUTES) { +  if (Attributes == INVALID_FILE_ATTRIBUTES) {      // See if the file didn't actually exist.      DWORD LastError = ::GetLastError();      if (LastError != ERROR_FILE_NOT_FOUND &&          LastError != ERROR_PATH_NOT_FOUND)        return windows_error(LastError); -    result = false; -  } else -    result = true; -  return std::error_code(); -} - -bool can_write(const Twine &Path) { -  // FIXME: take security attributes into account. -  SmallString<128> PathStorage; -  SmallVector<wchar_t, 128> PathUtf16; - -  if (UTF8ToUTF16(Path.toStringRef(PathStorage), PathUtf16)) -    return false; - -  DWORD Attr = ::GetFileAttributesW(PathUtf16.begin()); -  return (Attr != INVALID_FILE_ATTRIBUTES) && !(Attr & FILE_ATTRIBUTE_READONLY); -} +    return errc::no_such_file_or_directory; +  } -bool can_execute(const Twine &Path) { -  SmallString<128> PathStorage; -  SmallVector<wchar_t, 128> PathUtf16; +  if (Mode == AccessMode::Write && (Attributes & FILE_ATTRIBUTE_READONLY)) +    return errc::permission_denied; -  if (UTF8ToUTF16(Path.toStringRef(PathStorage), PathUtf16)) -    return false; - -  DWORD Attr = ::GetFileAttributesW(PathUtf16.begin()); -  return Attr != INVALID_FILE_ATTRIBUTES; +  return std::error_code();  }  bool equivalent(file_status A, file_status B) { @@ -424,7 +415,7 @@ std::error_code status(const Twine &path, file_status &result) {      return std::error_code();    } -  if (std::error_code ec = UTF8ToUTF16(path8, path_utf16)) +  if (std::error_code ec = widenPath(path8, path_utf16))      return ec;    DWORD attr = ::GetFileAttributesW(path_utf16.begin()); @@ -567,11 +558,10 @@ mapped_file_region::mapped_file_region(const Twine &path,    , FileDescriptor()    , FileHandle(INVALID_HANDLE_VALUE)    , FileMappingHandle() { -  SmallString<128> path_storage;    SmallVector<wchar_t, 128> path_utf16;    // Convert path to UTF-16. -  if ((ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16))) +  if ((ec = widenPath(path, path_utf16)))      return;    // Get file handle for creating a file mapping. @@ -677,7 +667,7 @@ std::error_code detail::directory_iterator_construct(detail::DirIterState &it,                                                  StringRef path){    SmallVector<wchar_t, 128> path_utf16; -  if (std::error_code ec = UTF8ToUTF16(path, path_utf16)) +  if (std::error_code ec = widenPath(path, path_utf16))      return ec;    // Convert path to the format that Windows is happy with. @@ -760,11 +750,9 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &it) {  }  std::error_code openFileForRead(const Twine &Name, int &ResultFD) { -  SmallString<128> PathStorage;    SmallVector<wchar_t, 128> PathUTF16; -  if (std::error_code EC = -          UTF8ToUTF16(Name.toStringRef(PathStorage), PathUTF16)) +  if (std::error_code EC = widenPath(Name, PathUTF16))      return EC;    HANDLE H = ::CreateFileW(PathUTF16.begin(), GENERIC_READ, @@ -799,11 +787,9 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD,    assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) &&           "Cannot specify both 'excl' and 'append' file creation flags!"); -  SmallString<128> PathStorage;    SmallVector<wchar_t, 128> PathUTF16; -  if (std::error_code EC = -          UTF8ToUTF16(Name.toStringRef(PathStorage), PathUTF16)) +  if (std::error_code EC = widenPath(Name, PathUTF16))      return EC;    DWORD CreationDisposition; @@ -867,6 +853,51 @@ bool home_directory(SmallVectorImpl<char> &result) {    return true;  } +static bool getTempDirEnvVar(const char *Var, SmallVectorImpl<char> &Res) { +  SmallVector<wchar_t, 128> NameUTF16; +  if (windows::UTF8ToUTF16(Var, NameUTF16)) +    return false; + +  SmallVector<wchar_t, 1024> Buf; +  size_t Size = 1024; +  do { +    Buf.reserve(Size); +    Size = +        GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity()); +    if (Size == 0) +      return false; + +    // Try again with larger buffer. +  } while (Size > Buf.capacity()); +  Buf.set_size(Size); + +  if (windows::UTF16ToUTF8(Buf.data(), Size, Res)) +    return false; +  return true; +} + +static bool getTempDirEnvVar(SmallVectorImpl<char> &Res) { +  const char *EnvironmentVariables[] = {"TMP", "TEMP", "USERPROFILE"}; +  for (const char *Env : EnvironmentVariables) { +    if (getTempDirEnvVar(Env, Res)) +      return true; +  } +  return false; +} + +void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { +  (void)ErasedOnReboot; +  Result.clear(); + +  // Check whether the temporary directory is specified by an environment +  // variable. +  if (getTempDirEnvVar(Result)) +    return; + +  // Fall back to a system default. +  const char *DefaultResult = "C:\\TEMP"; +  Result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); +}  } // end namespace path  namespace windows { @@ -896,11 +927,13 @@ std::error_code UTF8ToUTF16(llvm::StringRef utf8,    return std::error_code();  } -std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, -                            llvm::SmallVectorImpl<char> &utf8) { +static +std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16, +                                size_t utf16_len, +                                llvm::SmallVectorImpl<char> &utf8) {    if (utf16_len) {      // Get length. -    int len = ::WideCharToMultiByte(CP_UTF8, 0, utf16, utf16_len, utf8.begin(), +    int len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.begin(),                                      0, NULL, NULL);      if (len == 0) @@ -910,7 +943,7 @@ std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,      utf8.set_size(len);      // Now do the actual conversion. -    len = ::WideCharToMultiByte(CP_UTF8, 0, utf16, utf16_len, utf8.data(), +    len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.data(),                                  utf8.size(), NULL, NULL);      if (len == 0) @@ -923,6 +956,16 @@ std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,    return std::error_code();  } + +std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, +                            llvm::SmallVectorImpl<char> &utf8) { +  return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8); +} + +std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, +                             llvm::SmallVectorImpl<char> &utf8) { +  return UTF16ToCodePage(CP_ACP, utf16, utf16_len, utf8); +}  } // end namespace windows  } // end namespace sys  } // end namespace llvm diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc index 81aee0e..3819e63 100644 --- a/lib/Support/Windows/Process.inc +++ b/lib/Support/Windows/Process.inc @@ -183,36 +183,103 @@ static std::error_code windows_error(DWORD E) {    return mapWindowsError(E);  } +static void AllocateAndPush(const SmallVectorImpl<char> &S, +                            SmallVectorImpl<const char *> &Vector, +                            SpecificBumpPtrAllocator<char> &Allocator) { +  char *Buffer = Allocator.Allocate(S.size() + 1); +  ::memcpy(Buffer, S.data(), S.size()); +  Buffer[S.size()] = '\0'; +  Vector.push_back(Buffer); +} + +/// Convert Arg from UTF-16 to UTF-8 and push it onto Args. +static std::error_code +ConvertAndPushArg(const wchar_t *Arg, SmallVectorImpl<const char *> &Args, +                  SpecificBumpPtrAllocator<char> &Allocator) { +  SmallVector<char, MAX_PATH> ArgString; +  if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), ArgString)) +    return ec; +  AllocateAndPush(ArgString, Args, Allocator); +  return std::error_code(); +} + +/// \brief Perform wildcard expansion of Arg, or just push it into Args if it +/// doesn't have wildcards or doesn't match any files. +static std::error_code +WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args, +               SpecificBumpPtrAllocator<char> &Allocator) { +  if (!wcspbrk(Arg, L"*?")) { +    // Arg does not contain any wildcard characters. This is the common case. +    return ConvertAndPushArg(Arg, Args, Allocator); +  } + +  if (wcscmp(Arg, L"/?") == 0 || wcscmp(Arg, L"-?") == 0) { +    // Don't wildcard expand /?. Always treat it as an option. +    return ConvertAndPushArg(Arg, Args, Allocator); +  } + +  // Extract any directory part of the argument. +  SmallVector<char, MAX_PATH> Dir; +  if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), Dir)) +    return ec; +  sys::path::remove_filename(Dir); +  const int DirSize = Dir.size(); + +  // Search for matching files. +  WIN32_FIND_DATAW FileData; +  HANDLE FindHandle = FindFirstFileW(Arg, &FileData); +  if (FindHandle == INVALID_HANDLE_VALUE) { +    return ConvertAndPushArg(Arg, Args, Allocator); +  } + +  std::error_code ec; +  do { +    SmallVector<char, MAX_PATH> FileName; +    ec = windows::UTF16ToUTF8(FileData.cFileName, wcslen(FileData.cFileName), +                              FileName); +    if (ec) +      break; + +    // Push the filename onto Dir, and remove it afterwards. +    llvm::sys::path::append(Dir, StringRef(FileName.data(), FileName.size())); +    AllocateAndPush(Dir, Args, Allocator); +    Dir.resize(DirSize); +  } while (FindNextFileW(FindHandle, &FileData)); + +  FindClose(FindHandle); +  return ec; +} +  std::error_code  Process::GetArgumentVector(SmallVectorImpl<const char *> &Args,                             ArrayRef<const char *>,                             SpecificBumpPtrAllocator<char> &ArgAllocator) { -  int NewArgCount; -  std::error_code ec; - -  wchar_t **UnicodeCommandLine = CommandLineToArgvW(GetCommandLineW(), -                                                    &NewArgCount); +  int ArgCount; +  wchar_t **UnicodeCommandLine = +      CommandLineToArgvW(GetCommandLineW(), &ArgCount);    if (!UnicodeCommandLine)      return windows_error(::GetLastError()); -  Args.reserve(NewArgCount); +  Args.reserve(ArgCount); +  std::error_code ec; -  for (int i = 0; i < NewArgCount; ++i) { -    SmallVector<char, MAX_PATH> NewArgString; -    ec = windows::UTF16ToUTF8(UnicodeCommandLine[i], -                              wcslen(UnicodeCommandLine[i]), -                              NewArgString); +  for (int i = 0; i < ArgCount; ++i) { +    ec = WildcardExpand(UnicodeCommandLine[i], Args, ArgAllocator);      if (ec)        break; - -    char *Buffer = ArgAllocator.Allocate(NewArgString.size() + 1); -    ::memcpy(Buffer, NewArgString.data(), NewArgString.size() + 1); -    Args.push_back(Buffer);    } +    LocalFree(UnicodeCommandLine); -  if (ec) -    return ec; +  return ec; +} + +std::error_code Process::FixupStandardFileDescriptors() { +  return std::error_code(); +} +std::error_code Process::SafelyCloseFileDescriptor(int FD) { +  if (::close(FD) < 0) +    return std::error_code(errno, std::generic_category());    return std::error_code();  } diff --git a/lib/Support/Windows/Program.inc b/lib/Support/Windows/Program.inc index b2f71ae..72c2a58 100644 --- a/lib/Support/Windows/Program.inc +++ b/lib/Support/Windows/Program.inc @@ -12,7 +12,11 @@  //===----------------------------------------------------------------------===//  #include "WindowsSupport.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ConvertUTF.h"  #include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/WindowsError.h"  #include <cstdio>  #include <fcntl.h>  #include <io.h> @@ -28,43 +32,67 @@ using namespace sys;  ProcessInfo::ProcessInfo() : ProcessHandle(0), Pid(0), ReturnCode(0) {} -// This function just uses the PATH environment variable to find the program. -std::string sys::FindProgramByName(const std::string &progName) { -  // Check some degenerate cases -  if (progName.length() == 0) // no program -    return ""; -  std::string temp = progName; -  // Return paths with slashes verbatim. -  if (progName.find('\\') != std::string::npos || -      progName.find('/') != std::string::npos) -    return temp; - -  // At this point, the file name is valid and does not contain slashes. -  // Let Windows search for it. -  SmallVector<wchar_t, MAX_PATH> progNameUnicode; -  if (windows::UTF8ToUTF16(progName, progNameUnicode)) -    return ""; - -  SmallVector<wchar_t, MAX_PATH> buffer; -  DWORD len = MAX_PATH; -  do { -    buffer.reserve(len); -    len = ::SearchPathW(NULL, progNameUnicode.data(), L".exe", -                        buffer.capacity(), buffer.data(), NULL); - -    // See if it wasn't found. -    if (len == 0) -      return ""; - -    // Buffer was too small; grow and retry. -  } while (len > buffer.capacity()); - -  buffer.set_size(len); -  SmallVector<char, MAX_PATH> result; -  if (windows::UTF16ToUTF8(buffer.begin(), buffer.size(), result)) -    return ""; - -  return std::string(result.data(), result.size()); +ErrorOr<std::string> sys::findProgramByName(StringRef Name, +                                            ArrayRef<StringRef> Paths) { +  assert(!Name.empty() && "Must have a name!"); + +  if (Name.find_first_of("/\\") != StringRef::npos) +    return std::string(Name); + +  const wchar_t *Path = nullptr; +  std::wstring PathStorage; +  if (!Paths.empty()) { +    PathStorage.reserve(Paths.size() * MAX_PATH); +    for (unsigned i = 0; i < Paths.size(); ++i) { +      if (i) +        PathStorage.push_back(L';'); +      StringRef P = Paths[i]; +      SmallVector<wchar_t, MAX_PATH> TmpPath; +      if (std::error_code EC = windows::UTF8ToUTF16(P, TmpPath)) +        return EC; +      PathStorage.append(TmpPath.begin(), TmpPath.end()); +    } +    Path = PathStorage.c_str(); +  } + +  SmallVector<wchar_t, MAX_PATH> U16Name; +  if (std::error_code EC = windows::UTF8ToUTF16(Name, U16Name)) +    return EC; + +  SmallVector<StringRef, 12> PathExts; +  PathExts.push_back(""); +  PathExts.push_back(".exe"); // FIXME: This must be in %PATHEXT%. +  SplitString(std::getenv("PATHEXT"), PathExts, ";"); + +  SmallVector<wchar_t, MAX_PATH> U16Result; +  DWORD Len = MAX_PATH; +  for (StringRef Ext : PathExts) { +    SmallVector<wchar_t, MAX_PATH> U16Ext; +    if (std::error_code EC = windows::UTF8ToUTF16(Ext, U16Ext)) +      return EC; + +    do { +      U16Result.reserve(Len); +      Len = ::SearchPathW(Path, c_str(U16Name), +                          U16Ext.empty() ? nullptr : c_str(U16Ext), +                          U16Result.capacity(), U16Result.data(), nullptr); +    } while (Len > U16Result.capacity()); + +    if (Len != 0) +      break; // Found it. +  } + +  if (Len == 0) +    return mapWindowsError(::GetLastError()); + +  U16Result.set_size(Len); + +  SmallVector<char, MAX_PATH> U8Result; +  if (std::error_code EC = +          windows::UTF16ToUTF8(U16Result.data(), U16Result.size(), U8Result)) +    return EC; + +  return std::string(U8Result.begin(), U8Result.end());  }  static HANDLE RedirectIO(const StringRef *path, int fd, std::string* ErrMsg) { @@ -166,19 +194,7 @@ static unsigned int ArgLenWithQuotes(const char *Str) {  } -static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, -                    const char **envp, const StringRef **redirects, -                    unsigned memoryLimit, std::string *ErrMsg) { -  if (!sys::fs::can_execute(Program)) { -    if (ErrMsg) -      *ErrMsg = "program not executable"; -    return false; -  } - -  // Windows wants a command line, not an array of args, to pass to the new -  // process.  We have to concatenate them all, while quoting the args that -  // have embedded spaces (or are empty). - +static std::unique_ptr<char[]> flattenArgs(const char **args) {    // First, determine the length of the command line.    unsigned len = 0;    for (unsigned i = 0; args[i]; i++) { @@ -216,6 +232,22 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **args,    }    *p = 0; +  return command; +} + +static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, +                    const char **envp, const StringRef **redirects, +                    unsigned memoryLimit, std::string *ErrMsg) { +  if (!sys::fs::can_execute(Program)) { +    if (ErrMsg) +      *ErrMsg = "program not executable"; +    return false; +  } + +  // Windows wants a command line, not an array of args, to pass to the new +  // process.  We have to concatenate them all, while quoting the args that +  // have embedded spaces (or are empty). +  std::unique_ptr<char[]> command = flattenArgs(args);    // The pointer to the environment block for the new process.    std::vector<wchar_t> EnvBlock; @@ -422,20 +454,64 @@ ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,    return WaitResult;  } -  std::error_code sys::ChangeStdinToBinary(){ -  int result = _setmode( _fileno(stdin), _O_BINARY ); +std::error_code sys::ChangeStdinToBinary() { +  int result = _setmode(_fileno(stdin), _O_BINARY);    if (result == -1)      return std::error_code(errno, std::generic_category());    return std::error_code();  } -  std::error_code sys::ChangeStdoutToBinary(){ -  int result = _setmode( _fileno(stdout), _O_BINARY ); +std::error_code sys::ChangeStdoutToBinary() { +  int result = _setmode(_fileno(stdout), _O_BINARY);    if (result == -1)      return std::error_code(errno, std::generic_category());    return std::error_code();  } +std::error_code +llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents, +                                 WindowsEncodingMethod Encoding) { +  std::error_code EC; +  llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text); +  if (EC) +    return EC; + +  if (Encoding == WEM_UTF8) { +    OS << Contents; +  } else if (Encoding == WEM_CurrentCodePage) { +    SmallVector<wchar_t, 1> ArgsUTF16; +    SmallVector<char, 1> ArgsCurCP; + +    if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16))) +      return EC; + +    if ((EC = windows::UTF16ToCurCP( +             ArgsUTF16.data(), ArgsUTF16.size(), ArgsCurCP))) +      return EC; + +    OS.write(ArgsCurCP.data(), ArgsCurCP.size()); +  } else if (Encoding == WEM_UTF16) { +    SmallVector<wchar_t, 1> ArgsUTF16; + +    if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16))) +      return EC; + +    // Endianness guessing +    char BOM[2]; +    uint16_t src = UNI_UTF16_BYTE_ORDER_MARK_NATIVE; +    memcpy(BOM, &src, 2); +    OS.write(BOM, 2); +    OS.write((char *)ArgsUTF16.data(), ArgsUTF16.size() << 1); +  } else { +    llvm_unreachable("Unknown encoding"); +  } + +  if (OS.has_error()) +    return std::make_error_code(std::errc::io_error); + +  return EC; +} +  bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) {    // The documented max length of the command line passed to CreateProcess.    static const size_t MaxCommandStringLength = 32768; diff --git a/lib/Support/Windows/RWMutex.inc b/lib/Support/Windows/RWMutex.inc index 00d0e93..2d1d25f 100644 --- a/lib/Support/Windows/RWMutex.inc +++ b/lib/Support/Windows/RWMutex.inc @@ -84,12 +84,10 @@ RWMutexImpl::RWMutexImpl() {  }  RWMutexImpl::~RWMutexImpl() { -  if (sHasSRW) { -    // Nothing to do in the case of slim reader/writers -  } else { +  if (!sHasSRW)      DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); -    free(data_); -  } +  // Nothing to do in the case of slim reader/writers except free the memory. +  free(data_);  }  bool RWMutexImpl::reader_acquire() { diff --git a/lib/Support/Windows/ThreadLocal.inc b/lib/Support/Windows/ThreadLocal.inc index 3914cf7..14ce619 100644 --- a/lib/Support/Windows/ThreadLocal.inc +++ b/lib/Support/Windows/ThreadLocal.inc @@ -23,7 +23,7 @@ namespace llvm {  using namespace sys;  ThreadLocalImpl::ThreadLocalImpl() : data() { -  typedef int SIZE_TOO_BIG[sizeof(DWORD) <= sizeof(data) ? 1 : -1]; +  static_assert(sizeof(DWORD) <= sizeof(data), "size too big");    DWORD* tls = reinterpret_cast<DWORD*>(&data);    *tls = TlsAlloc();    assert(*tls != TLS_OUT_OF_INDEXES); diff --git a/lib/Support/Windows/WindowsSupport.h b/lib/Support/Windows/WindowsSupport.h index f68835b..6d9c5fb 100644 --- a/lib/Support/Windows/WindowsSupport.h +++ b/lib/Support/Windows/WindowsSupport.h @@ -166,6 +166,9 @@ namespace windows {  std::error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16);  std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,                              SmallVectorImpl<char> &utf8); +/// Convert from UTF16 to the current code page used in the system +std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, +                             SmallVectorImpl<char> &utf8);  } // end namespace windows  } // end namespace sys  } // end namespace llvm. diff --git a/lib/Support/Windows/explicit_symbols.inc b/lib/Support/Windows/explicit_symbols.inc index 379645d..cd56b13 100644 --- a/lib/Support/Windows/explicit_symbols.inc +++ b/lib/Support/Windows/explicit_symbols.inc @@ -63,4 +63,34 @@  /* msvcrt */  #if defined(_MSC_VER)    EXPLICIT_SYMBOL2(alloca, _alloca_probe) + +#ifdef _M_IX86 +#define INLINE_DEF_FLOAT_SYMBOL(SYM, ARGC) INLINE_DEF_SYMBOL##ARGC(float, SYM) +  INLINE_DEF_FLOAT_SYMBOL(acosf, 1) +  INLINE_DEF_FLOAT_SYMBOL(asinf, 1) +  INLINE_DEF_FLOAT_SYMBOL(atanf, 1) +  INLINE_DEF_FLOAT_SYMBOL(atan2f, 2) +  INLINE_DEF_FLOAT_SYMBOL(ceilf, 1) +  INLINE_DEF_FLOAT_SYMBOL(cosf, 1) +  INLINE_DEF_FLOAT_SYMBOL(coshf, 1) +  INLINE_DEF_FLOAT_SYMBOL(expf, 1) +  INLINE_DEF_FLOAT_SYMBOL(floorf, 1) +  INLINE_DEF_FLOAT_SYMBOL(fmodf, 2) +  INLINE_DEF_FLOAT_SYMBOL(logf, 1) +  INLINE_DEF_FLOAT_SYMBOL(powf, 2) +  INLINE_DEF_FLOAT_SYMBOL(sinf, 1) +  INLINE_DEF_FLOAT_SYMBOL(sinhf, 1) +  INLINE_DEF_FLOAT_SYMBOL(sqrtf, 1) +  INLINE_DEF_FLOAT_SYMBOL(tanf, 1) +  INLINE_DEF_FLOAT_SYMBOL(tanhf, 1) + +  // These were added in VS 2013. +#if (1800 <= _MSC_VER && _MSC_VER < 1900) +  INLINE_DEF_FLOAT_SYMBOL(copysignf, 2) +  INLINE_DEF_FLOAT_SYMBOL(fminf, 2) +  INLINE_DEF_FLOAT_SYMBOL(fmaxf, 2) +#endif +#undef INLINE_DEF_FLOAT_SYMBOL +#endif +  #endif diff --git a/lib/Support/YAMLParser.cpp b/lib/Support/YAMLParser.cpp index 3be02ee..4688ff1 100644 --- a/lib/Support/YAMLParser.cpp +++ b/lib/Support/YAMLParser.cpp @@ -259,8 +259,8 @@ namespace yaml {  /// @brief Scans YAML tokens from a MemoryBuffer.  class Scanner {  public: -  Scanner(const StringRef Input, SourceMgr &SM); -  Scanner(MemoryBuffer *Buffer, SourceMgr &SM_); +  Scanner(StringRef Input, SourceMgr &SM); +  Scanner(MemoryBufferRef Buffer, SourceMgr &SM_);    /// @brief Parse the next token and return it without popping it.    Token &peekNext(); @@ -294,6 +294,8 @@ public:    }  private: +  void init(MemoryBufferRef Buffer); +    StringRef currentInput() {      return StringRef(Current, End - Current);    } @@ -469,7 +471,7 @@ private:    SourceMgr &SM;    /// @brief The original input. -  MemoryBuffer *InputBuffer; +  MemoryBufferRef InputBuffer;    /// @brief The current position of the scanner.    StringRef::iterator Current; @@ -699,34 +701,28 @@ std::string yaml::escape(StringRef Input) {    return EscapedInput;  } -Scanner::Scanner(StringRef Input, SourceMgr &sm) -  : SM(sm) -  , Indent(-1) -  , Column(0) -  , Line(0) -  , FlowLevel(0) -  , IsStartOfStream(true) -  , IsSimpleKeyAllowed(true) -  , Failed(false) { -  InputBuffer = MemoryBuffer::getMemBuffer(Input, "YAML"); -  SM.AddNewSourceBuffer(InputBuffer, SMLoc()); -  Current = InputBuffer->getBufferStart(); -  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()); +Scanner::Scanner(StringRef Input, SourceMgr &sm) : SM(sm) { +  init(MemoryBufferRef(Input, "YAML")); +} + +Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_) : SM(SM_) { +  init(Buffer); +} + +void Scanner::init(MemoryBufferRef Buffer) { +  InputBuffer = Buffer; +  Current = InputBuffer.getBufferStart(); +  End = InputBuffer.getBufferEnd(); +  Indent = -1; +  Column = 0; +  Line = 0; +  FlowLevel = 0; +  IsStartOfStream = true; +  IsSimpleKeyAllowed = true; +  Failed = false; +  std::unique_ptr<MemoryBuffer> InputBufferOwner = +      MemoryBuffer::getMemBuffer(Buffer); +  SM.AddNewSourceBuffer(std::move(InputBufferOwner), SMLoc());  }  Token &Scanner::peekNext() { @@ -1524,7 +1520,7 @@ bool Scanner::fetchMoreTokens() {  Stream::Stream(StringRef Input, SourceMgr &SM)      : scanner(new Scanner(Input, SM)), CurrentDoc() {} -Stream::Stream(MemoryBuffer *InputBuffer, SourceMgr &SM) +Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM)      : scanner(new Scanner(InputBuffer, SM)), CurrentDoc() {}  Stream::~Stream() {} diff --git a/lib/Support/YAMLTraits.cpp b/lib/Support/YAMLTraits.cpp index 5212624..81edca2 100644 --- a/lib/Support/YAMLTraits.cpp +++ b/lib/Support/YAMLTraits.cpp @@ -63,6 +63,8 @@ std::error_code Input::error() { return EC; }  void Input::HNode::anchor() {}  void Input::EmptyHNode::anchor() {}  void Input::ScalarHNode::anchor() {} +void Input::MapHNode::anchor() {} +void Input::SequenceHNode::anchor() {}  bool Input::outputting() {    return false; @@ -82,7 +84,7 @@ bool Input::setCurrentDocument() {        ++DocIterator;        return setCurrentDocument();      } -    TopNode.reset(this->createHNodes(N)); +    TopNode = this->createHNodes(N);      CurrentNode = TopNode.get();      return true;    } @@ -133,7 +135,7 @@ bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault,      return false;    }    MN->ValidKeys.push_back(Key); -  HNode *Value = MN->Mapping[Key]; +  HNode *Value = MN->Mapping[Key].get();    if (!Value) {      if (Required)        setError(CurrentNode, Twine("missing required key '") + Key + "'"); @@ -159,7 +161,7 @@ void Input::endMapping() {      return;    for (const auto &NN : MN->Mapping) {      if (!MN->isValidKey(NN.first())) { -      setError(NN.second, Twine("unknown key '") + NN.first() + "'"); +      setError(NN.second.get(), Twine("unknown key '") + NN.first() + "'");        break;      }    } @@ -180,7 +182,7 @@ bool Input::preflightElement(unsigned Index, void *&SaveInfo) {      return false;    if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {      SaveInfo = CurrentNode; -    CurrentNode = SQ->Entries[Index]; +    CurrentNode = SQ->Entries[Index].get();      return true;    }    return false; @@ -202,7 +204,7 @@ bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {      return false;    if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {      SaveInfo = CurrentNode; -    CurrentNode = SQ->Entries[index]; +    CurrentNode = SQ->Entries[index].get();      return true;    }    return false; @@ -253,8 +255,8 @@ bool Input::bitSetMatch(const char *Str, bool) {      return false;    if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {      unsigned Index = 0; -    for (HNode *N : SQ->Entries) { -      if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N)) { +    for (auto &N : SQ->Entries) { +      if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N.get())) {          if (SN->value().equals(Str)) {            BitValuesUsed[Index] = true;            return true; @@ -277,7 +279,7 @@ void Input::endBitSetScalar() {      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"); +        setError(SQ->Entries[i].get(), "unknown bit value");          return;        }      } @@ -302,7 +304,7 @@ void Input::setError(Node *node, const Twine &message) {    EC = make_error_code(errc::invalid_argument);  } -Input::HNode *Input::createHNodes(Node *N) { +std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) {    SmallString<128> StringStorage;    if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) {      StringRef KeyStr = SN->getValue(StringStorage); @@ -313,20 +315,25 @@ Input::HNode *Input::createHNodes(Node *N) {        memcpy(Buf, &StringStorage[0], Len);        KeyStr = StringRef(Buf, Len);      } -    return new ScalarHNode(N, KeyStr); +    return llvm::make_unique<ScalarHNode>(N, KeyStr);    } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) { -    SequenceHNode *SQHNode = new SequenceHNode(N); +    auto SQHNode = llvm::make_unique<SequenceHNode>(N);      for (Node &SN : *SQ) { -      HNode *Entry = this->createHNodes(&SN); +      auto Entry = this->createHNodes(&SN);        if (EC)          break; -      SQHNode->Entries.push_back(Entry); +      SQHNode->Entries.push_back(std::move(Entry));      } -    return SQHNode; +    return std::move(SQHNode);    } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) { -    MapHNode *mapHNode = new MapHNode(N); +    auto mapHNode = llvm::make_unique<MapHNode>(N);      for (KeyValueNode &KVN : *Map) { -      ScalarNode *KeyScalar = dyn_cast<ScalarNode>(KVN.getKey()); +      Node *KeyNode = KVN.getKey(); +      ScalarNode *KeyScalar = dyn_cast<ScalarNode>(KeyNode); +      if (!KeyScalar) { +        setError(KeyNode, "Map key must be a scalar"); +        break; +      }        StringStorage.clear();        StringRef KeyStr = KeyScalar->getValue(StringStorage);        if (!StringStorage.empty()) { @@ -336,14 +343,14 @@ Input::HNode *Input::createHNodes(Node *N) {          memcpy(Buf, &StringStorage[0], Len);          KeyStr = StringRef(Buf, Len);        } -      HNode *ValueHNode = this->createHNodes(KVN.getValue()); +      auto ValueHNode = this->createHNodes(KVN.getValue());        if (EC)          break; -      mapHNode->Mapping[KeyStr] = ValueHNode; +      mapHNode->Mapping[KeyStr] = std::move(ValueHNode);      } -    return mapHNode; +    return std::move(mapHNode);    } else if (isa<NullNode>(N)) { -    return new EmptyHNode(N); +    return llvm::make_unique<EmptyHNode>(N);    } else {      setError(N, "unknown node kind");      return nullptr; @@ -366,18 +373,6 @@ bool Input::canElideEmptySequence() {    return false;  } -Input::MapHNode::~MapHNode() { -  for (auto &N : Mapping) -    delete N.second; -} - -Input::SequenceHNode::~SequenceHNode() { -  for (HNode *N : Entries) -    delete N; -} - - -  //===----------------------------------------------------------------------===//  //  Output  //===----------------------------------------------------------------------===// diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index f7c213a..bbbbe4a 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -20,6 +20,7 @@  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/FileSystem.h"  #include "llvm/Support/Format.h" +#include "llvm/Support/MathExtras.h"  #include "llvm/Support/Process.h"  #include "llvm/Support/Program.h"  #include <cctype> @@ -394,6 +395,62 @@ raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {    }  } +raw_ostream &raw_ostream::operator<<(const FormattedString &FS) { +  unsigned Len = FS.Str.size();  +  int PadAmount = FS.Width - Len; +  if (FS.RightJustify && (PadAmount > 0)) +    this->indent(PadAmount); +  this->operator<<(FS.Str); +  if (!FS.RightJustify && (PadAmount > 0)) +    this->indent(PadAmount); +  return *this; +} + +raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) { +  if (FN.Hex) { +    unsigned Nibbles = (64 - countLeadingZeros(FN.HexValue)+3)/4; +    unsigned Width = (FN.Width > Nibbles+2) ? FN.Width : Nibbles+2; +         +    char NumberBuffer[20] = "0x0000000000000000"; +    char *EndPtr = NumberBuffer+Width; +    char *CurPtr = EndPtr; +    const char A = FN.Upper ? 'A' : 'a'; +    unsigned long long N = FN.HexValue; +    while (N) { +      uintptr_t x = N % 16; +      *--CurPtr = (x < 10 ? '0' + x : A + x - 10); +      N /= 16; +    } + +    return write(NumberBuffer, Width); +  } else { +    // Zero is a special case. +    if (FN.DecValue == 0) { +      this->indent(FN.Width-1); +      return *this << '0'; +    } +    char NumberBuffer[32]; +    char *EndPtr = NumberBuffer+sizeof(NumberBuffer); +    char *CurPtr = EndPtr; +    bool Neg = (FN.DecValue < 0); +    uint64_t N = Neg ? -static_cast<uint64_t>(FN.DecValue) : FN.DecValue; +    while (N) { +      *--CurPtr = '0' + char(N % 10); +      N /= 10; +    } +    int Len = EndPtr - CurPtr; +    int Pad = FN.Width - Len; +    if (Neg)  +      --Pad; +    if (Pad > 0) +      this->indent(Pad); +    if (Neg) +      *this << '-'; +    return write(CurPtr, Len); +  } +} + +  /// indent - Insert 'NumSpaces' spaces.  raw_ostream &raw_ostream::indent(unsigned NumSpaces) {    static const char Spaces[] = "                                " @@ -426,20 +483,14 @@ void format_object_base::home() {  //  raw_fd_ostream  //===----------------------------------------------------------------------===// -/// raw_fd_ostream - Open the specified file for writing. If an error -/// occurs, information about the error is put into ErrorInfo, and the -/// stream should be immediately destroyed; the string will be empty -/// if no error occurred. -raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo, +raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,                                 sys::fs::OpenFlags Flags)      : Error(false), UseAtomicWrites(false), pos(0) { -  assert(Filename && "Filename is null"); -  ErrorInfo.clear(); - +  EC = std::error_code();    // Handle "-" as stdout. Note that when we do this, we consider ourself    // the owner of stdout. This means that we can do things like close the    // file descriptor when we're done and set the "binary" flag globally. -  if (Filename[0] == '-' && Filename[1] == 0) { +  if (Filename == "-") {      FD = STDOUT_FILENO;      // If user requested binary then put stdout into binary mode if      // possible. @@ -450,11 +501,9 @@ raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo,      return;    } -  std::error_code EC = sys::fs::openFileForWrite(Filename, FD, Flags); +  EC = sys::fs::openFileForWrite(Filename, FD, Flags);    if (EC) { -    ErrorInfo = "Error opening output file '" + std::string(Filename) + "': " + -                EC.message();      ShouldClose = false;      return;    } @@ -487,12 +536,8 @@ raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered)  raw_fd_ostream::~raw_fd_ostream() {    if (FD >= 0) {      flush(); -    if (ShouldClose) -      while (::close(FD) != 0) -        if (errno != EINTR) { -          error_detected(); -          break; -        } +    if (ShouldClose && sys::Process::SafelyCloseFileDescriptor(FD)) +      error_detected();    }  #ifdef __MINGW32__ @@ -566,11 +611,8 @@ void raw_fd_ostream::close() {    assert(ShouldClose);    ShouldClose = false;    flush(); -  while (::close(FD) != 0) -    if (errno != EINTR) { -      error_detected(); -      break; -    } +  if (sys::Process::SafelyCloseFileDescriptor(FD)) +    error_detected();    FD = -1;  } @@ -660,7 +702,7 @@ bool raw_fd_ostream::has_colors() const {  /// Use it like: outs() << "foo" << "bar";  raw_ostream &llvm::outs() {    // Set buffer settings to model stdout behavior. -  // Delete the file descriptor when the program exists, forcing error +  // Delete the file descriptor when the program exits, forcing error    // detection. If you don't want this behavior, don't use outs().    static raw_fd_ostream S(STDOUT_FILENO, true);    return S; @@ -729,24 +771,17 @@ void raw_svector_ostream::resync() {  }  void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { -  // If we're writing bytes from the end of the buffer into the smallvector, we -  // don't need to copy the bytes, just commit the bytes because they are -  // already in the right place.    if (Ptr == OS.end()) { -    assert(OS.size() + Size <= OS.capacity() && "Invalid write_impl() call!"); -    OS.set_size(OS.size() + Size); +    // Grow the buffer to include the scratch area without copying. +    size_t NewSize = OS.size() + Size; +    assert(NewSize <= OS.capacity() && "Invalid write_impl() call!"); +    OS.set_size(NewSize);    } else { -    assert(GetNumBytesInBuffer() == 0 && -           "Should be writing from buffer if some bytes in it"); -    // Otherwise, do copy the bytes. -    OS.append(Ptr, Ptr+Size); +    assert(!GetNumBytesInBuffer()); +    OS.append(Ptr, Ptr + Size);    } -  // Grow the vector if necessary. -  if (OS.capacity() - OS.size() < 64) -    OS.reserve(OS.capacity() * 2); - -  // Update the buffer position. +  OS.reserve(OS.size() + 64);    SetBuffer(OS.end(), OS.capacity() - OS.size());  } | 
