aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Support
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Support')
-rw-r--r--lib/Support/APFloat.cpp72
-rw-r--r--lib/Support/APInt.cpp63
-rw-r--r--lib/Support/Android.mk6
-rw-r--r--lib/Support/CMakeLists.txt70
-rw-r--r--lib/Support/CommandLine.cpp80
-rw-r--r--lib/Support/DataStream.cpp4
-rw-r--r--lib/Support/Debug.cpp9
-rw-r--r--lib/Support/Disassembler.cpp74
-rw-r--r--lib/Support/Dwarf.cpp105
-rw-r--r--lib/Support/ErrorHandling.cpp9
-rw-r--r--lib/Support/FileOutputBuffer.cpp19
-rw-r--r--lib/Support/FileUtilities.cpp16
-rw-r--r--lib/Support/GraphWriter.cpp5
-rw-r--r--lib/Support/Host.cpp4
-rw-r--r--lib/Support/IncludeFile.cpp20
-rw-r--r--lib/Support/LineIterator.cpp55
-rw-r--r--lib/Support/LockFileManager.cpp8
-rw-r--r--lib/Support/MD5.cpp48
-rw-r--r--lib/Support/MathExtras.cpp32
-rw-r--r--lib/Support/MemoryBuffer.cpp149
-rw-r--r--lib/Support/MemoryObject.cpp19
-rw-r--r--lib/Support/Options.cpp33
-rw-r--r--lib/Support/Path.cpp173
-rw-r--r--lib/Support/ScaledNumber.cpp3
-rw-r--r--lib/Support/SmallPtrSet.cpp27
-rw-r--r--lib/Support/SourceMgr.cpp11
-rw-r--r--lib/Support/SpecialCaseList.cpp32
-rw-r--r--lib/Support/StreamingMemoryObject.cpp (renamed from lib/Support/StreamableMemoryObject.cpp)79
-rw-r--r--lib/Support/StringRef.cpp22
-rw-r--r--lib/Support/StringRefMemoryObject.cpp29
-rw-r--r--lib/Support/TimeValue.cpp6
-rw-r--r--lib/Support/Timer.cpp8
-rw-r--r--lib/Support/ToolOutputFile.cpp15
-rw-r--r--lib/Support/Triple.cpp283
-rw-r--r--lib/Support/Unix/Host.inc6
-rw-r--r--lib/Support/Unix/Path.inc138
-rw-r--r--lib/Support/Unix/Process.inc108
-rw-r--r--lib/Support/Unix/Program.inc79
-rw-r--r--lib/Support/Unix/RWMutex.inc12
-rw-r--r--lib/Support/Unix/Signals.inc266
-rw-r--r--lib/Support/Unix/TimeValue.inc2
-rw-r--r--lib/Support/Unix/Unix.h4
-rw-r--r--lib/Support/Windows/DynamicLibrary.inc72
-rw-r--r--lib/Support/Windows/Host.inc2
-rw-r--r--lib/Support/Windows/Path.inc231
-rw-r--r--lib/Support/Windows/Process.inc101
-rw-r--r--lib/Support/Windows/Program.inc184
-rw-r--r--lib/Support/Windows/RWMutex.inc8
-rw-r--r--lib/Support/Windows/ThreadLocal.inc2
-rw-r--r--lib/Support/Windows/WindowsSupport.h3
-rw-r--r--lib/Support/Windows/explicit_symbols.inc30
-rw-r--r--lib/Support/YAMLParser.cpp60
-rw-r--r--lib/Support/YAMLTraits.cpp59
-rw-r--r--lib/Support/raw_ostream.cpp111
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());
}