summaryrefslogtreecommitdiffstats
path: root/lib/Support
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Support')
-rw-r--r--lib/Support/APFloat.cpp38
-rw-r--r--lib/Support/APInt.cpp4
-rw-r--r--lib/Support/CMakeLists.txt1
-rw-r--r--lib/Support/CommandLine.cpp8
-rw-r--r--lib/Support/ConstantRange.cpp84
-rw-r--r--lib/Support/CrashRecoveryContext.cpp2
-rw-r--r--lib/Support/Debug.cpp10
-rw-r--r--lib/Support/Errno.cpp2
-rw-r--r--lib/Support/FileOutputBuffer.cpp148
-rw-r--r--lib/Support/GraphWriter.cpp1
-rw-r--r--lib/Support/Host.cpp198
-rw-r--r--lib/Support/Memory.cpp11
-rw-r--r--lib/Support/MemoryBuffer.cpp19
-rw-r--r--lib/Support/Mutex.cpp3
-rw-r--r--lib/Support/Path.cpp7
-rw-r--r--lib/Support/PathV2.cpp2
-rw-r--r--lib/Support/SourceMgr.cpp121
-rw-r--r--lib/Support/StreamableMemoryObject.cpp2
-rw-r--r--lib/Support/StringMap.cpp2
-rw-r--r--lib/Support/StringRef.cpp44
-rw-r--r--lib/Support/TargetRegistry.cpp41
-rw-r--r--lib/Support/ThreadLocal.cpp28
-rw-r--r--lib/Support/Triple.cpp68
-rw-r--r--lib/Support/Unix/Path.inc7
-rw-r--r--lib/Support/Unix/PathV2.inc134
-rw-r--r--lib/Support/Unix/Process.inc53
-rw-r--r--lib/Support/Unix/Signals.inc50
-rw-r--r--lib/Support/Unix/Unix.h10
-rw-r--r--lib/Support/Windows/Path.inc16
-rw-r--r--lib/Support/Windows/PathV2.inc72
-rw-r--r--lib/Support/Windows/Process.inc14
-rw-r--r--lib/Support/Windows/RWMutex.inc6
-rw-r--r--lib/Support/Windows/ThreadLocal.inc13
-rw-r--r--lib/Support/YAMLParser.cpp50
-rw-r--r--lib/Support/raw_ostream.cpp7
35 files changed, 1009 insertions, 267 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 409d4fb..2139df5 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -1765,6 +1765,32 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand,
return fs;
}
+/* Rounding-mode corrrect round to integral value. */
+APFloat::opStatus APFloat::roundToIntegral(roundingMode rounding_mode) {
+ opStatus fs;
+ assertArithmeticOK(*semantics);
+
+ // The algorithm here is quite simple: we add 2^(p-1), where p is the
+ // precision of our format, and then subtract it back off again. The choice
+ // of rounding modes for the addition/subtraction determines the rounding mode
+ // for our integral rounding as well.
+ APInt IntegerConstant(NextPowerOf2(semanticsPrecision(*semantics)),
+ 1 << (semanticsPrecision(*semantics)-1));
+ APFloat MagicConstant(*semantics);
+ fs = MagicConstant.convertFromAPInt(IntegerConstant, false,
+ rmNearestTiesToEven);
+ if (fs != opOK)
+ return fs;
+
+ fs = add(MagicConstant, rounding_mode);
+ if (fs != opOK && fs != opInexact)
+ return fs;
+
+ fs = subtract(MagicConstant, rounding_mode);
+ return fs;
+}
+
+
/* Comparison requires normalized numbers. */
APFloat::cmpResult
APFloat::compare(const APFloat &rhs) const
@@ -3278,16 +3304,8 @@ APFloat::APFloat(double d) : exponent2(0), sign2(0) {
}
namespace {
- static void append(SmallVectorImpl<char> &Buffer,
- unsigned N, const char *Str) {
- unsigned Start = Buffer.size();
- Buffer.set_size(Start + N);
- memcpy(&Buffer[Start], Str, N);
- }
-
- template <unsigned N>
- void append(SmallVectorImpl<char> &Buffer, const char (&Str)[N]) {
- append(Buffer, N, Str);
+ void append(SmallVectorImpl<char> &Buffer, StringRef Str) {
+ Buffer.append(Str.begin(), Str.end());
}
/// Removes data from the given significand until it is no more
diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index 9b81fe7..38cfaed 100644
--- a/lib/Support/APInt.cpp
+++ b/lib/Support/APInt.cpp
@@ -1135,7 +1135,7 @@ APInt APInt::lshr(unsigned shiftAmt) const {
// If all the bits were shifted out, the result is 0. This avoids issues
// with shifting by the size of the integer type, which produces undefined
// results. We define these "undefined results" to always be 0.
- if (shiftAmt == BitWidth)
+ if (shiftAmt >= BitWidth)
return APInt(BitWidth, 0);
// If none of the bits are shifted out, the result is *this. This avoids
@@ -1446,7 +1446,7 @@ APInt::mu APInt::magicu(unsigned LeadingZeros) const {
APInt signedMin = APInt::getSignedMinValue(d.getBitWidth());
APInt signedMax = APInt::getSignedMaxValue(d.getBitWidth());
- nc = allOnes - (-d).urem(d);
+ nc = allOnes - (allOnes - d).urem(d);
p = d.getBitWidth() - 1; // initialize p
q1 = signedMin.udiv(nc); // initialize q1 = 2p/nc
r1 = signedMin - q1*nc; // initialize r1 = rem(2p,nc)
diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt
index 9103327..83baf60 100644
--- a/lib/Support/CMakeLists.txt
+++ b/lib/Support/CMakeLists.txt
@@ -23,6 +23,7 @@ add_llvm_library(LLVMSupport
Dwarf.cpp
ErrorHandling.cpp
FileUtilities.cpp
+ FileOutputBuffer.cpp
FoldingSet.cpp
FormattedStream.cpp
GraphWriter.cpp
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index e6fdf16..593315d1 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -219,10 +219,10 @@ static Option *LookupNearestOption(StringRef Arg,
if (!Best || Distance < BestDistance) {
Best = O;
BestDistance = Distance;
- if (RHS.empty() || !PermitValue)
- NearestString = OptionNames[i];
- else
- NearestString = std::string(OptionNames[i]) + "=" + RHS.str();
+ if (RHS.empty() || !PermitValue)
+ NearestString = OptionNames[i];
+ else
+ NearestString = std::string(OptionNames[i]) + "=" + RHS.str();
}
}
}
diff --git a/lib/Support/ConstantRange.cpp b/lib/Support/ConstantRange.cpp
index 5206cf1..720ef36 100644
--- a/lib/Support/ConstantRange.cpp
+++ b/lib/Support/ConstantRange.cpp
@@ -143,16 +143,17 @@ bool ConstantRange::isSignWrappedSet() const {
/// getSetSize - Return the number of elements in this set.
///
APInt ConstantRange::getSetSize() const {
- if (isEmptySet())
- return APInt(getBitWidth(), 0);
- if (getBitWidth() == 1) {
- if (Lower != Upper) // One of T or F in the set...
- return APInt(2, 1);
- return APInt(2, 2); // Must be full set...
+ if (isEmptySet())
+ return APInt(getBitWidth()+1, 0);
+
+ if (isFullSet()) {
+ APInt Size(getBitWidth()+1, 0);
+ Size.setBit(getBitWidth());
+ return Size;
}
- // Simply subtract the bounds...
- return Upper - Lower;
+ // This is also correct for wrapped sets.
+ return (Upper - Lower).zext(getBitWidth()+1);
}
/// getUnsignedMax - Return the largest unsigned value contained in the
@@ -248,6 +249,12 @@ ConstantRange ConstantRange::subtract(const APInt &Val) const {
return ConstantRange(Lower - Val, Upper - Val);
}
+/// \brief Subtract the specified range from this range (aka relative complement
+/// of the sets).
+ConstantRange ConstantRange::difference(const ConstantRange &CR) const {
+ return intersectWith(CR.inverse());
+}
+
/// intersectWith - Return the range that results from the intersection of this
/// range with another range. The resultant range is guaranteed to include all
/// elements contained in both input ranges, and to have the smallest possible
@@ -288,7 +295,7 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
if (CR.Upper.ult(Upper))
return CR;
- if (CR.Upper.ult(Lower))
+ if (CR.Upper.ule(Lower))
return ConstantRange(CR.Lower, Upper);
if (getSetSize().ult(CR.getSetSize()))
@@ -316,7 +323,7 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
return CR;
}
- if (CR.Upper.ult(Lower)) {
+ if (CR.Upper.ule(Lower)) {
if (CR.Lower.ult(Lower))
return *this;
@@ -420,9 +427,13 @@ ConstantRange ConstantRange::zeroExtend(uint32_t DstTySize) const {
unsigned SrcTySize = getBitWidth();
assert(SrcTySize < DstTySize && "Not a value extension");
- if (isFullSet() || isWrappedSet())
+ if (isFullSet() || isWrappedSet()) {
// Change into [0, 1 << src bit width)
- return ConstantRange(APInt(DstTySize,0), APInt(DstTySize,1).shl(SrcTySize));
+ APInt LowerExt(DstTySize, 0);
+ if (!Upper) // special case: [X, 0) -- not really wrapping around
+ LowerExt = Lower.zext(DstTySize);
+ return ConstantRange(LowerExt, APInt(DstTySize, 1).shl(SrcTySize));
+ }
return ConstantRange(Lower.zext(DstTySize), Upper.zext(DstTySize));
}
@@ -450,10 +461,53 @@ ConstantRange ConstantRange::signExtend(uint32_t DstTySize) const {
/// truncated to the specified type.
ConstantRange ConstantRange::truncate(uint32_t DstTySize) const {
assert(getBitWidth() > DstTySize && "Not a value truncation");
- if (isFullSet() || getSetSize().getActiveBits() > DstTySize)
+ if (isEmptySet())
+ return ConstantRange(DstTySize, /*isFullSet=*/false);
+ if (isFullSet())
return ConstantRange(DstTySize, /*isFullSet=*/true);
- return ConstantRange(Lower.trunc(DstTySize), Upper.trunc(DstTySize));
+ APInt MaxValue = APInt::getMaxValue(DstTySize).zext(getBitWidth());
+ APInt MaxBitValue(getBitWidth(), 0);
+ MaxBitValue.setBit(DstTySize);
+
+ APInt LowerDiv(Lower), UpperDiv(Upper);
+ ConstantRange Union(DstTySize, /*isFullSet=*/false);
+
+ // Analyze wrapped sets in their two parts: [0, Upper) \/ [Lower, MaxValue]
+ // We use the non-wrapped set code to analyze the [Lower, MaxValue) part, and
+ // then we do the union with [MaxValue, Upper)
+ if (isWrappedSet()) {
+ // if Upper is greater than Max Value, it covers the whole truncated range.
+ if (Upper.uge(MaxValue))
+ return ConstantRange(DstTySize, /*isFullSet=*/true);
+
+ Union = ConstantRange(APInt::getMaxValue(DstTySize),Upper.trunc(DstTySize));
+ UpperDiv = APInt::getMaxValue(getBitWidth());
+
+ // Union covers the MaxValue case, so return if the remaining range is just
+ // MaxValue.
+ if (LowerDiv == UpperDiv)
+ return Union;
+ }
+
+ // Chop off the most significant bits that are past the destination bitwidth.
+ if (LowerDiv.uge(MaxValue)) {
+ APInt Div(getBitWidth(), 0);
+ APInt::udivrem(LowerDiv, MaxBitValue, Div, LowerDiv);
+ UpperDiv = UpperDiv - MaxBitValue * Div;
+ }
+
+ if (UpperDiv.ule(MaxValue))
+ return ConstantRange(LowerDiv.trunc(DstTySize),
+ UpperDiv.trunc(DstTySize)).unionWith(Union);
+
+ // The truncated value wrapps around. Check if we can do better than fullset.
+ APInt UpperModulo = UpperDiv - MaxBitValue;
+ if (UpperModulo.ult(LowerDiv))
+ return ConstantRange(LowerDiv.trunc(DstTySize),
+ UpperModulo.trunc(DstTySize)).unionWith(Union);
+
+ return ConstantRange(DstTySize, /*isFullSet=*/true);
}
/// zextOrTrunc - make this range have the bit width given by \p DstTySize. The
@@ -529,8 +583,6 @@ ConstantRange::multiply(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
- if (isFullSet() || Other.isFullSet())
- return ConstantRange(getBitWidth(), /*isFullSet=*/true);
APInt this_min = getUnsignedMin().zext(getBitWidth() * 2);
APInt this_max = getUnsignedMax().zext(getBitWidth() * 2);
diff --git a/lib/Support/CrashRecoveryContext.cpp b/lib/Support/CrashRecoveryContext.cpp
index e2af0bc..e175056 100644
--- a/lib/Support/CrashRecoveryContext.cpp
+++ b/lib/Support/CrashRecoveryContext.cpp
@@ -223,7 +223,7 @@ void CrashRecoveryContext::Disable() {
#include <signal.h>
-static int Signals[] = { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP };
+static const int Signals[] = { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP };
static const unsigned NumSignals = sizeof(Signals) / sizeof(Signals[0]);
static struct sigaction PrevActions[NumSignals];
diff --git a/lib/Support/Debug.cpp b/lib/Support/Debug.cpp
index 9fdb12e..c8e8900 100644
--- a/lib/Support/Debug.cpp
+++ b/lib/Support/Debug.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements a handle way of adding debugging information to your
+// This file implements a handy way of adding debugging information to your
// code, without it being enabled all of the time, and without having to add
// command line options to enable it.
//
@@ -18,8 +18,8 @@
// can specify '-debug-only=foo' to enable JUST the debug information for the
// foo class.
//
-// When compiling in release mode, the -debug-* options and all code in DEBUG()
-// statements disappears, so it does not effect the runtime of the code.
+// When compiling without assertions, the -debug-* options and all code in
+// DEBUG() statements disappears, so it does not affect the runtime of the code.
//
//===----------------------------------------------------------------------===//
@@ -89,11 +89,11 @@ bool llvm::isCurrentDebugType(const char *DebugType) {
return CurrentDebugType.empty() || DebugType == CurrentDebugType;
}
-/// SetCurrentDebugType - Set the current debug type, as if the -debug-only=X
+/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X
/// option were specified. Note that DebugFlag also needs to be set to true for
/// debug output to be produced.
///
-void llvm::SetCurrentDebugType(const char *Type) {
+void llvm::setCurrentDebugType(const char *Type) {
CurrentDebugType = Type;
}
diff --git a/lib/Support/Errno.cpp b/lib/Support/Errno.cpp
index 18c6581..dd218f6 100644
--- a/lib/Support/Errno.cpp
+++ b/lib/Support/Errno.cpp
@@ -52,7 +52,7 @@ std::string StrError(int errnum) {
# endif
#elif HAVE_DECL_STRERROR_S // "Windows Secure API"
if (errnum)
- strerror_s(buffer, errnum);
+ strerror_s(buffer, MaxErrStrLen - 1, errnum);
#elif defined(HAVE_STRERROR)
// Copy the thread un-safe result of strerror into
// the buffer as fast as possible to minimize impact
diff --git a/lib/Support/FileOutputBuffer.cpp b/lib/Support/FileOutputBuffer.cpp
new file mode 100644
index 0000000..7dc9587
--- /dev/null
+++ b/lib/Support/FileOutputBuffer.cpp
@@ -0,0 +1,148 @@
+//===- FileOutputBuffer.cpp - File Output Buffer ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating a in-memory buffer that will be written to a file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/FileOutputBuffer.h"
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+
+namespace llvm {
+
+
+FileOutputBuffer::FileOutputBuffer(uint8_t *Start, uint8_t *End,
+ StringRef Path, StringRef TmpPath)
+ : BufferStart(Start), BufferEnd(End) {
+ FinalPath.assign(Path);
+ TempPath.assign(TmpPath);
+}
+
+
+FileOutputBuffer::~FileOutputBuffer() {
+ // If not already commited, delete buffer and remove temp file.
+ if ( BufferStart != NULL ) {
+ sys::fs::unmap_file_pages((void*)BufferStart, getBufferSize());
+ bool Existed;
+ sys::fs::remove(Twine(TempPath), Existed);
+ }
+}
+
+
+error_code FileOutputBuffer::create(StringRef FilePath,
+ size_t Size,
+ OwningPtr<FileOutputBuffer> &Result,
+ unsigned Flags) {
+ // If file already exists, it must be a regular file (to be mappable).
+ sys::fs::file_status Stat;
+ error_code EC = sys::fs::status(FilePath, Stat);
+ switch (Stat.type()) {
+ case sys::fs::file_type::file_not_found:
+ // If file does not exist, we'll create one.
+ break;
+ case sys::fs::file_type::regular_file: {
+ // If file is not currently writable, error out.
+ // FIXME: There is no sys::fs:: api for checking this.
+ // FIXME: In posix, you use the access() call to check this.
+ }
+ break;
+ default:
+ if (EC)
+ return EC;
+ else
+ return make_error_code(errc::operation_not_permitted);
+ }
+
+ // Delete target file.
+ bool Existed;
+ EC = sys::fs::remove(FilePath, Existed);
+ if (EC)
+ return EC;
+
+ // Create new file in same directory but with random name.
+ SmallString<128> TempFilePath;
+ int FD;
+ EC = sys::fs::unique_file(Twine(FilePath) + ".tmp%%%%%%%",
+ FD, TempFilePath, false, 0644);
+ if (EC)
+ return EC;
+
+ // The unique_file() interface leaks lower layers and returns a file
+ // descriptor. There is no way to directly close it, so use this hack
+ // to hand it off to raw_fd_ostream to close for us.
+ {
+ raw_fd_ostream Dummy(FD, /*shouldClose=*/true);
+ }
+
+ // Resize file to requested initial size
+ EC = sys::fs::resize_file(Twine(TempFilePath), Size);
+ if (EC)
+ return EC;
+
+ // If requested, make the output file executable.
+ if ( Flags & F_executable ) {
+ sys::fs::file_status Stat2;
+ EC = sys::fs::status(Twine(TempFilePath), Stat2);
+ if (EC)
+ return EC;
+
+ sys::fs::perms new_perms = Stat2.permissions();
+ if ( new_perms & sys::fs::owner_read )
+ new_perms |= sys::fs::owner_exe;
+ if ( new_perms & sys::fs::group_read )
+ new_perms |= sys::fs::group_exe;
+ if ( new_perms & sys::fs::others_read )
+ new_perms |= sys::fs::others_exe;
+ new_perms |= sys::fs::add_perms;
+ EC = sys::fs::permissions(Twine(TempFilePath), new_perms);
+ if (EC)
+ return EC;
+ }
+
+ // Memory map new file.
+ void *Base;
+ EC = sys::fs::map_file_pages(Twine(TempFilePath), 0, Size, true, Base);
+ if (EC)
+ return EC;
+
+ // Create FileOutputBuffer object to own mapped range.
+ uint8_t *Start = reinterpret_cast<uint8_t*>(Base);
+ Result.reset(new FileOutputBuffer(Start, Start+Size, FilePath, TempFilePath));
+
+ return error_code::success();
+}
+
+
+error_code FileOutputBuffer::commit(int64_t NewSmallerSize) {
+ // Unmap buffer, letting OS flush dirty pages to file on disk.
+ void *Start = reinterpret_cast<void*>(BufferStart);
+ error_code EC = sys::fs::unmap_file_pages(Start, getBufferSize());
+ if (EC)
+ return EC;
+
+ // If requested, resize file as part of commit.
+ if ( NewSmallerSize != -1 ) {
+ EC = sys::fs::resize_file(Twine(TempPath), NewSmallerSize);
+ if (EC)
+ return EC;
+ }
+
+ // Rename file to final name.
+ return sys::fs::rename(Twine(TempPath), Twine(FinalPath));
+}
+
+
+} // namespace
+
diff --git a/lib/Support/GraphWriter.cpp b/lib/Support/GraphWriter.cpp
index 32126ec..f6aaf83 100644
--- a/lib/Support/GraphWriter.cpp
+++ b/lib/Support/GraphWriter.cpp
@@ -99,7 +99,6 @@ void llvm::DisplayGraph(const sys::Path &Filename, bool wait,
case GraphProgram::NEATO: args.push_back("-f"); args.push_back("neato");break;
case GraphProgram::TWOPI: args.push_back("-f"); args.push_back("twopi");break;
case GraphProgram::CIRCO: args.push_back("-f"); args.push_back("circo");break;
- default: errs() << "Unknown graph layout name; using default.\n";
}
args.push_back(0);
diff --git a/lib/Support/Host.cpp b/lib/Support/Host.cpp
index 0f06964..9a2c39d 100644
--- a/lib/Support/Host.cpp
+++ b/lib/Support/Host.cpp
@@ -11,7 +11,13 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/DataStream.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Config/config.h"
#include <string.h>
@@ -25,6 +31,12 @@
#ifdef _MSC_VER
#include <intrin.h>
#endif
+#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
+#include <mach/mach.h>
+#include <mach/mach_host.h>
+#include <mach/host_info.h>
+#include <mach/machine.h>
+#endif
//===----------------------------------------------------------------------===//
//
@@ -230,11 +242,18 @@ std::string sys::getHostCPUName() {
case 45:
return "corei7-avx";
- case 28: // Intel Atom processor. All processors are manufactured using
- // the 45 nm process
+ // Ivy Bridge:
+ case 58:
+ return "core-avx-i";
+
+ case 28: // Most 45 nm Intel Atom processors
+ case 38: // 45 nm Atom Lincroft
+ case 39: // 32 nm Atom Medfield
+ case 53: // 32 nm Atom Midview
+ case 54: // 32 nm Atom Midview
return "atom";
- default: return "i686";
+ default: return (Em64T) ? "x86-64" : "i686";
}
case 15: {
switch (Model) {
@@ -315,6 +334,179 @@ std::string sys::getHostCPUName() {
}
return "generic";
}
+#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
+std::string sys::getHostCPUName() {
+ host_basic_info_data_t hostInfo;
+ mach_msg_type_number_t infoCount;
+
+ infoCount = HOST_BASIC_INFO_COUNT;
+ host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo,
+ &infoCount);
+
+ if (hostInfo.cpu_type != CPU_TYPE_POWERPC) return "generic";
+
+ switch(hostInfo.cpu_subtype) {
+ case CPU_SUBTYPE_POWERPC_601: return "601";
+ case CPU_SUBTYPE_POWERPC_602: return "602";
+ case CPU_SUBTYPE_POWERPC_603: return "603";
+ case CPU_SUBTYPE_POWERPC_603e: return "603e";
+ case CPU_SUBTYPE_POWERPC_603ev: return "603ev";
+ case CPU_SUBTYPE_POWERPC_604: return "604";
+ case CPU_SUBTYPE_POWERPC_604e: return "604e";
+ case CPU_SUBTYPE_POWERPC_620: return "620";
+ case CPU_SUBTYPE_POWERPC_750: return "750";
+ case CPU_SUBTYPE_POWERPC_7400: return "7400";
+ case CPU_SUBTYPE_POWERPC_7450: return "7450";
+ case CPU_SUBTYPE_POWERPC_970: return "970";
+ default: ;
+ }
+
+ return "generic";
+}
+#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__))
+std::string sys::getHostCPUName() {
+ // Access to the Processor Version Register (PVR) on PowerPC is privileged,
+ // and so we must use an operating-system interface to determine the current
+ // processor type. On Linux, this is exposed through the /proc/cpuinfo file.
+ const char *generic = "generic";
+
+ // Note: We cannot mmap /proc/cpuinfo here and then process the resulting
+ // memory buffer because the 'file' has 0 size (it can be read from only
+ // as a stream).
+
+ std::string Err;
+ DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err);
+ if (!DS) {
+ DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n");
+ return generic;
+ }
+
+ // The cpu line is second (after the 'processor: 0' line), so if this
+ // buffer is too small then something has changed (or is wrong).
+ char buffer[1024];
+ size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer));
+ delete DS;
+
+ const char *CPUInfoStart = buffer;
+ const char *CPUInfoEnd = buffer + CPUInfoSize;
+
+ const char *CIP = CPUInfoStart;
+
+ const char *CPUStart = 0;
+ size_t CPULen = 0;
+
+ // We need to find the first line which starts with cpu, spaces, and a colon.
+ // After the colon, there may be some additional spaces and then the cpu type.
+ while (CIP < CPUInfoEnd && CPUStart == 0) {
+ if (CIP < CPUInfoEnd && *CIP == '\n')
+ ++CIP;
+
+ if (CIP < CPUInfoEnd && *CIP == 'c') {
+ ++CIP;
+ if (CIP < CPUInfoEnd && *CIP == 'p') {
+ ++CIP;
+ if (CIP < CPUInfoEnd && *CIP == 'u') {
+ ++CIP;
+ while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
+ ++CIP;
+
+ if (CIP < CPUInfoEnd && *CIP == ':') {
+ ++CIP;
+ while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
+ ++CIP;
+
+ if (CIP < CPUInfoEnd) {
+ CPUStart = CIP;
+ while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
+ *CIP != ',' && *CIP != '\n'))
+ ++CIP;
+ CPULen = CIP - CPUStart;
+ }
+ }
+ }
+ }
+ }
+
+ if (CPUStart == 0)
+ while (CIP < CPUInfoEnd && *CIP != '\n')
+ ++CIP;
+ }
+
+ if (CPUStart == 0)
+ return generic;
+
+ return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
+ .Case("604e", "604e")
+ .Case("604", "604")
+ .Case("7400", "7400")
+ .Case("7410", "7400")
+ .Case("7447", "7400")
+ .Case("7455", "7450")
+ .Case("G4", "g4")
+ .Case("POWER4", "970")
+ .Case("PPC970FX", "970")
+ .Case("PPC970MP", "970")
+ .Case("G5", "g5")
+ .Case("POWER5", "g5")
+ .Case("A2", "a2")
+ .Case("POWER6", "pwr6")
+ .Case("POWER7", "pwr7")
+ .Default(generic);
+}
+#elif defined(__linux__) && defined(__arm__)
+std::string sys::getHostCPUName() {
+ // The cpuid register on arm is not accessible from user space. On Linux,
+ // it is exposed through the /proc/cpuinfo file.
+ // Note: We cannot mmap /proc/cpuinfo here and then process the resulting
+ // memory buffer because the 'file' has 0 size (it can be read from only
+ // as a stream).
+
+ std::string Err;
+ DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err);
+ if (!DS) {
+ DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n");
+ return "generic";
+ }
+
+ // Read 1024 bytes from /proc/cpuinfo, which should contain the CPU part line
+ // in all cases.
+ char buffer[1024];
+ size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer));
+ delete DS;
+
+ StringRef Str(buffer, CPUInfoSize);
+
+ SmallVector<StringRef, 32> Lines;
+ Str.split(Lines, "\n");
+
+ // Look for the CPU implementer line.
+ StringRef Implementer;
+ for (unsigned I = 0, E = Lines.size(); I != E; ++I)
+ if (Lines[I].startswith("CPU implementer"))
+ Implementer = Lines[I].substr(15).ltrim("\t :");
+
+ if (Implementer == "0x41") // ARM Ltd.
+ // Look for the CPU part line.
+ for (unsigned I = 0, E = Lines.size(); I != E; ++I)
+ if (Lines[I].startswith("CPU part"))
+ // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
+ // values correspond to the "Part number" in the CP15/c0 register. The
+ // contents are specified in the various processor manuals.
+ return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
+ .Case("0x926", "arm926ej-s")
+ .Case("0xb02", "mpcore")
+ .Case("0xb36", "arm1136j-s")
+ .Case("0xb56", "arm1156t2-s")
+ .Case("0xb76", "arm1176jz-s")
+ .Case("0xc08", "cortex-a8")
+ .Case("0xc09", "cortex-a9")
+ .Case("0xc20", "cortex-m0")
+ .Case("0xc23", "cortex-m3")
+ .Case("0xc24", "cortex-m4")
+ .Default("generic");
+
+ return "generic";
+}
#else
std::string sys::getHostCPUName() {
return "generic";
diff --git a/lib/Support/Memory.cpp b/lib/Support/Memory.cpp
index 2a1642a..22f7494 100644
--- a/lib/Support/Memory.cpp
+++ b/lib/Support/Memory.cpp
@@ -45,7 +45,7 @@ void llvm::sys::Memory::InvalidateInstructionCache(const void *Addr,
# if (defined(__POWERPC__) || defined (__ppc__) || \
defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__)
- sys_icache_invalidate(Addr, Len);
+ sys_icache_invalidate(const_cast<void *>(Addr), Len);
# endif
#else
@@ -67,11 +67,12 @@ void llvm::sys::Memory::InvalidateInstructionCache(const void *Addr,
asm volatile("isync");
# elif defined(__arm__) && defined(__GNUC__)
// FIXME: Can we safely always call this for __GNUC__ everywhere?
- char *Start = (char*) Addr;
- char *End = Start + Len;
- __clear_cache(Start, End);
+ const char *Start = static_cast<const char *>(Addr);
+ const char *End = Start + Len;
+ __clear_cache(const_cast<char *>(Start), const_cast<char *>(End));
# elif defined(__mips__)
- cacheflush((char*)Addr, Len, BCACHE);
+ const char *Start = static_cast<const char *>(Addr);
+ cacheflush(const_cast<char *>(Start), Len, BCACHE);
# endif
#endif // end apple
diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp
index 16e5c7a..992f03c 100644
--- a/lib/Support/MemoryBuffer.cpp
+++ b/lib/Support/MemoryBuffer.cpp
@@ -17,6 +17,7 @@
#include "llvm/Config/config.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Errno.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
@@ -214,6 +215,14 @@ error_code MemoryBuffer::getFile(const char *Filename,
OwningPtr<MemoryBuffer> &result,
int64_t FileSize,
bool RequiresNullTerminator) {
+ // First check that the "file" is not a directory
+ bool is_dir = false;
+ error_code err = sys::fs::is_directory(Filename, is_dir);
+ if (err)
+ return err;
+ if (is_dir)
+ return make_error_code(errc::is_a_directory);
+
int OpenFlags = O_RDONLY;
#ifdef O_BINARY
OpenFlags |= O_BINARY; // Open input file in binary mode on win32.
@@ -304,16 +313,6 @@ error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
RealMapOffset)) {
result.reset(GetNamedBuffer<MemoryBufferMMapFile>(
StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator));
-
- if (RequiresNullTerminator && result->getBufferEnd()[0] != '\0') {
- // There could be a racing issue that resulted in the file being larger
- // than the FileSize passed by the caller. We already have an assertion
- // for this in MemoryBuffer::init() but have a runtime guarantee that
- // the buffer will be null-terminated here, so do a copy that adds a
- // null-terminator.
- result.reset(MemoryBuffer::getMemBufferCopy(result->getBuffer(),
- Filename));
- }
return error_code::success();
}
}
diff --git a/lib/Support/Mutex.cpp b/lib/Support/Mutex.cpp
index da5baab..4e4a026 100644
--- a/lib/Support/Mutex.cpp
+++ b/lib/Support/Mutex.cpp
@@ -59,7 +59,8 @@ MutexImpl::MutexImpl( bool recursive)
errorcode = pthread_mutexattr_settype(&attr, kind);
assert(errorcode == 0);
-#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && \
+ !defined(__DragonFly__) && !defined(__Bitrig__)
// Make it a process local mutex
errorcode = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
assert(errorcode == 0);
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index dcddeda..db4a56b 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -60,8 +60,11 @@ sys::IdentifyFileType(const char *magic, unsigned length) {
case '\177':
if (magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') {
- if (length >= 18 && magic[17] == 0)
- switch (magic[16]) {
+ bool Data2MSB = magic[5] == 2;
+ unsigned high = Data2MSB ? 16 : 17;
+ unsigned low = Data2MSB ? 17 : 16;
+ if (length >= 18 && magic[high] == 0)
+ switch (magic[low]) {
default: break;
case 1: return ELF_Relocatable_FileType;
case 2: return ELF_Executable_FileType;
diff --git a/lib/Support/PathV2.cpp b/lib/Support/PathV2.cpp
index e2a69a6..46571c0 100644
--- a/lib/Support/PathV2.cpp
+++ b/lib/Support/PathV2.cpp
@@ -744,6 +744,8 @@ error_code has_magic(const Twine &path, const Twine &magic, bool &result) {
/// @brief Identify the magic in magic.
file_magic identify_magic(StringRef magic) {
+ if (magic.size() < 4)
+ return file_magic::unknown;
switch ((unsigned char)magic[0]) {
case 0xDE: // 0x0B17C0DE = BC wraper
if (magic[1] == (char)0xC0 && magic[2] == (char)0x17 &&
diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp
index 15278c5..e4e01be 100644
--- a/lib/Support/SourceMgr.cpp
+++ b/lib/Support/SourceMgr.cpp
@@ -79,9 +79,10 @@ int SourceMgr::FindBufferContainingLoc(SMLoc Loc) const {
return -1;
}
-/// FindLineNumber - Find the line number for the specified location in the
-/// specified file. This is not a fast method.
-unsigned SourceMgr::FindLineNumber(SMLoc Loc, int BufferID) const {
+/// getLineAndColumn - Find the line and column number for the specified
+/// location in the specified file. This is not a fast method.
+std::pair<unsigned, unsigned>
+SourceMgr::getLineAndColumn(SMLoc Loc, int BufferID) const {
if (BufferID == -1) BufferID = FindBufferContainingLoc(Loc);
assert(BufferID != -1 && "Invalid Location!");
@@ -91,7 +92,8 @@ unsigned SourceMgr::FindLineNumber(SMLoc Loc, int BufferID) const {
// location.
unsigned LineNo = 1;
- const char *Ptr = Buff->getBufferStart();
+ const char *BufStart = Buff->getBufferStart();
+ const char *Ptr = BufStart;
// If we have a line number cache, and if the query is to a later point in the
// same file, start searching from the last query location. This optimizes
@@ -108,7 +110,6 @@ unsigned SourceMgr::FindLineNumber(SMLoc Loc, int BufferID) const {
for (; SMLoc::getFromPointer(Ptr) != Loc; ++Ptr)
if (*Ptr == '\n') ++LineNo;
-
// Allocate the line number cache if it doesn't exist.
if (LineNoCache == 0)
LineNoCache = new LineNoCacheTy();
@@ -118,7 +119,10 @@ unsigned SourceMgr::FindLineNumber(SMLoc Loc, int BufferID) const {
Cache.LastQueryBufferID = BufferID;
Cache.LastQuery = Ptr;
Cache.LineNoOfQuery = LineNo;
- return LineNo;
+
+ size_t NewlineOffs = StringRef(BufStart, Ptr-BufStart).find_last_of("\n\r");
+ if (NewlineOffs == StringRef::npos) NewlineOffs = ~(size_t)0;
+ return std::make_pair(LineNo, Ptr-BufStart-NewlineOffs);
}
void SourceMgr::PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const {
@@ -145,50 +149,59 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
ArrayRef<SMRange> Ranges) const {
// First thing to do: find the current buffer containing the specified
- // location.
- int CurBuf = FindBufferContainingLoc(Loc);
- assert(CurBuf != -1 && "Invalid or unspecified location!");
-
- MemoryBuffer *CurMB = getBufferInfo(CurBuf).Buffer;
-
- // Scan backward to find the start of the line.
- const char *LineStart = Loc.getPointer();
- while (LineStart != CurMB->getBufferStart() &&
- LineStart[-1] != '\n' && LineStart[-1] != '\r')
- --LineStart;
-
- // Get the end of the line.
- const char *LineEnd = Loc.getPointer();
- while (LineEnd != CurMB->getBufferEnd() &&
- LineEnd[0] != '\n' && LineEnd[0] != '\r')
- ++LineEnd;
- std::string LineStr(LineStart, LineEnd);
-
- // Convert any ranges to column ranges that only intersect the line of the
- // location.
+ // location to pull out the source line.
SmallVector<std::pair<unsigned, unsigned>, 4> ColRanges;
- for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
- SMRange R = Ranges[i];
- if (!R.isValid()) continue;
-
- // If the line doesn't contain any part of the range, then ignore it.
- if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
- continue;
-
- // Ignore pieces of the range that go onto other lines.
- if (R.Start.getPointer() < LineStart)
- R.Start = SMLoc::getFromPointer(LineStart);
- if (R.End.getPointer() > LineEnd)
- R.End = SMLoc::getFromPointer(LineEnd);
+ std::pair<unsigned, unsigned> LineAndCol;
+ const char *BufferID = "<unknown>";
+ std::string LineStr;
+
+ if (Loc.isValid()) {
+ int CurBuf = FindBufferContainingLoc(Loc);
+ assert(CurBuf != -1 && "Invalid or unspecified location!");
+
+ MemoryBuffer *CurMB = getBufferInfo(CurBuf).Buffer;
+ BufferID = CurMB->getBufferIdentifier();
- // Translate from SMLoc ranges to column ranges.
- ColRanges.push_back(std::make_pair(R.Start.getPointer()-LineStart,
- R.End.getPointer()-LineStart));
+ // Scan backward to find the start of the line.
+ const char *LineStart = Loc.getPointer();
+ const char *BufStart = CurMB->getBufferStart();
+ while (LineStart != BufStart && LineStart[-1] != '\n' &&
+ LineStart[-1] != '\r')
+ --LineStart;
+
+ // Get the end of the line.
+ const char *LineEnd = Loc.getPointer();
+ const char *BufEnd = CurMB->getBufferEnd();
+ while (LineEnd != BufEnd && LineEnd[0] != '\n' && LineEnd[0] != '\r')
+ ++LineEnd;
+ LineStr = std::string(LineStart, LineEnd);
+
+ // Convert any ranges to column ranges that only intersect the line of the
+ // location.
+ for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
+ SMRange R = Ranges[i];
+ if (!R.isValid()) continue;
+
+ // If the line doesn't contain any part of the range, then ignore it.
+ if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
+ continue;
+
+ // Ignore pieces of the range that go onto other lines.
+ if (R.Start.getPointer() < LineStart)
+ R.Start = SMLoc::getFromPointer(LineStart);
+ if (R.End.getPointer() > LineEnd)
+ R.End = SMLoc::getFromPointer(LineEnd);
+
+ // Translate from SMLoc ranges to column ranges.
+ ColRanges.push_back(std::make_pair(R.Start.getPointer()-LineStart,
+ R.End.getPointer()-LineStart));
+ }
+
+ LineAndCol = getLineAndColumn(Loc, CurBuf);
}
-
- return SMDiagnostic(*this, Loc,
- CurMB->getBufferIdentifier(), FindLineNumber(Loc, CurBuf),
- Loc.getPointer()-LineStart, Kind, Msg.str(),
+
+ return SMDiagnostic(*this, Loc, BufferID, LineAndCol.first,
+ LineAndCol.second-1, Kind, Msg.str(),
LineStr, ColRanges);
}
@@ -205,9 +218,11 @@ void SourceMgr::PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
raw_ostream &OS = errs();
- int CurBuf = FindBufferContainingLoc(Loc);
- assert(CurBuf != -1 && "Invalid or unspecified location!");
- PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS);
+ if (Loc != SMLoc()) {
+ int CurBuf = FindBufferContainingLoc(Loc);
+ assert(CurBuf != -1 && "Invalid or unspecified location!");
+ PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS);
+ }
Diagnostic.print(0, OS, ShowColors);
}
@@ -228,8 +243,8 @@ SMDiagnostic::SMDiagnostic(const SourceMgr &sm, SMLoc L, const std::string &FN,
void SMDiagnostic::print(const char *ProgName, raw_ostream &S,
bool ShowColors) const {
- // Display colors only if OS goes to a tty.
- ShowColors &= S.is_displayed();
+ // Display colors only if OS supports colors.
+ ShowColors &= S.has_colors();
if (ShowColors)
S.changeColor(raw_ostream::SAVEDCOLOR, true);
@@ -343,5 +358,3 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S,
S << '\n';
}
-
-
diff --git a/lib/Support/StreamableMemoryObject.cpp b/lib/Support/StreamableMemoryObject.cpp
index c23f07b..fe3752a 100644
--- a/lib/Support/StreamableMemoryObject.cpp
+++ b/lib/Support/StreamableMemoryObject.cpp
@@ -20,7 +20,7 @@ class RawMemoryObject : public StreamableMemoryObject {
public:
RawMemoryObject(const unsigned char *Start, const unsigned char *End) :
FirstChar(Start), LastChar(End) {
- assert(LastChar > FirstChar && "Invalid start/end range");
+ assert(LastChar >= FirstChar && "Invalid start/end range");
}
virtual uint64_t getBase() const { return 0; }
diff --git a/lib/Support/StringMap.cpp b/lib/Support/StringMap.cpp
index c131fe0..c2fc261 100644
--- a/lib/Support/StringMap.cpp
+++ b/lib/Support/StringMap.cpp
@@ -189,7 +189,7 @@ void StringMapImpl::RehashTable() {
// grow/rehash the table.
if (NumItems*4 > NumBuckets*3) {
NewSize = NumBuckets*2;
- } else if (NumBuckets-(NumItems+NumTombstones) < NumBuckets/8) {
+ } else if (NumBuckets-(NumItems+NumTombstones) <= NumBuckets/8) {
NewSize = NumBuckets;
} else {
return;
diff --git a/lib/Support/StringRef.cpp b/lib/Support/StringRef.cpp
index abe570f..8aab4b2 100644
--- a/lib/Support/StringRef.cpp
+++ b/lib/Support/StringRef.cpp
@@ -12,6 +12,7 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/edit_distance.h"
+
#include <bitset>
using namespace llvm;
@@ -230,6 +231,31 @@ StringRef::size_type StringRef::find_last_of(StringRef Chars,
return npos;
}
+/// 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)
+ if (Data[i] != C)
+ return i;
+ return npos;
+}
+
+/// find_last_not_of - Find the last character in the string that is not in
+/// \arg Chars, or npos if not found.
+///
+/// Note: O(size() + Chars.size())
+StringRef::size_type StringRef::find_last_not_of(StringRef Chars,
+ size_t From) const {
+ std::bitset<1 << CHAR_BIT> CharBits;
+ 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)
+ if (!CharBits.test((unsigned char)Data[i]))
+ return i;
+ return npos;
+}
+
void StringRef::split(SmallVectorImpl<StringRef> &A,
StringRef Separators, int MaxSplit,
bool KeepEmpty) const {
@@ -272,14 +298,22 @@ static unsigned GetAutoSenseRadix(StringRef &Str) {
if (Str.startswith("0x")) {
Str = Str.substr(2);
return 16;
- } else if (Str.startswith("0b")) {
+ }
+
+ if (Str.startswith("0b")) {
Str = Str.substr(2);
return 2;
- } else if (Str.startswith("0")) {
+ }
+
+ if (Str.startswith("0o")) {
+ Str = Str.substr(2);
return 8;
- } else {
- return 10;
}
+
+ if (Str.startswith("0"))
+ return 8;
+
+ return 10;
}
@@ -383,7 +417,7 @@ bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const {
unsigned BitWidth = Log2Radix * Str.size();
if (BitWidth < Result.getBitWidth())
BitWidth = Result.getBitWidth(); // don't shrink the result
- else
+ else if (BitWidth > Result.getBitWidth())
Result = Result.zext(BitWidth);
APInt RadixAP, CharAP; // unused unless !IsPowerOf2Radix
diff --git a/lib/Support/TargetRegistry.cpp b/lib/Support/TargetRegistry.cpp
index 53c8d84..9c81327 100644
--- a/lib/Support/TargetRegistry.cpp
+++ b/lib/Support/TargetRegistry.cpp
@@ -23,6 +23,47 @@ TargetRegistry::iterator TargetRegistry::begin() {
return iterator(FirstTarget);
}
+const Target *TargetRegistry::lookupTarget(const std::string &ArchName,
+ Triple &TheTriple,
+ std::string &Error) {
+ // Allocate target machine. First, check whether the user has explicitly
+ // specified an architecture to compile for. If so we have to look it up by
+ // name, because it might be a backend that has no mapping to a target triple.
+ const Target *TheTarget = 0;
+ if (!ArchName.empty()) {
+ for (TargetRegistry::iterator it = TargetRegistry::begin(),
+ ie = TargetRegistry::end(); it != ie; ++it) {
+ if (ArchName == it->getName()) {
+ TheTarget = &*it;
+ break;
+ }
+ }
+
+ if (!TheTarget) {
+ Error = "error: invalid target '" + ArchName + "'.\n";
+ return 0;
+ }
+
+ // Adjust the triple to match (if known), otherwise stick with the
+ // given triple.
+ Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
+ if (Type != Triple::UnknownArch)
+ TheTriple.setArch(Type);
+ } else {
+ // Get the target specific parser.
+ std::string TempError;
+ TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError);
+ if (TheTarget == 0) {
+ Error = ": error: unable to get target for '"
+ + TheTriple.getTriple()
+ + "', see --version and --triple.\n";
+ return 0;
+ }
+ }
+
+ return TheTarget;
+}
+
const Target *TargetRegistry::lookupTarget(const std::string &TT,
std::string &Error) {
// Provide special warning when no targets are initialized.
diff --git a/lib/Support/ThreadLocal.cpp b/lib/Support/ThreadLocal.cpp
index 08b12b6..0587aae 100644
--- a/lib/Support/ThreadLocal.cpp
+++ b/lib/Support/ThreadLocal.cpp
@@ -25,9 +25,18 @@ namespace llvm {
using namespace sys;
ThreadLocalImpl::ThreadLocalImpl() { }
ThreadLocalImpl::~ThreadLocalImpl() { }
-void ThreadLocalImpl::setInstance(const void* d) { data = const_cast<void*>(d);}
-const void* ThreadLocalImpl::getInstance() { return data; }
-void ThreadLocalImpl::removeInstance() { data = 0; }
+void ThreadLocalImpl::setInstance(const void* d) {
+ typedef int SIZE_TOO_BIG[sizeof(d) <= sizeof(data) ? 1 : -1];
+ void **pd = reinterpret_cast<void**>(&data);
+ *pd = const_cast<void*>(d);
+}
+const void* ThreadLocalImpl::getInstance() {
+ void **pd = reinterpret_cast<void**>(&data);
+ return *pd;
+}
+void ThreadLocalImpl::removeInstance() {
+ setInstance(0);
+}
}
#else
@@ -40,31 +49,30 @@ void ThreadLocalImpl::removeInstance() { data = 0; }
namespace llvm {
using namespace sys;
-ThreadLocalImpl::ThreadLocalImpl() : data(0) {
- pthread_key_t* key = new pthread_key_t;
+ThreadLocalImpl::ThreadLocalImpl() : data() {
+ typedef int SIZE_TOO_BIG[sizeof(pthread_key_t) <= sizeof(data) ? 1 : -1];
+ pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
int errorcode = pthread_key_create(key, NULL);
assert(errorcode == 0);
(void) errorcode;
- data = (void*)key;
}
ThreadLocalImpl::~ThreadLocalImpl() {
- pthread_key_t* key = static_cast<pthread_key_t*>(data);
+ pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
int errorcode = pthread_key_delete(*key);
assert(errorcode == 0);
(void) errorcode;
- delete key;
}
void ThreadLocalImpl::setInstance(const void* d) {
- pthread_key_t* key = static_cast<pthread_key_t*>(data);
+ pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
int errorcode = pthread_setspecific(*key, d);
assert(errorcode == 0);
(void) errorcode;
}
const void* ThreadLocalImpl::getInstance() {
- pthread_key_t* key = static_cast<pthread_key_t*>(data);
+ pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
return pthread_getspecific(*key);
}
diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp
index 44a1b38..cca549d 100644
--- a/lib/Support/Triple.cpp
+++ b/lib/Support/Triple.cpp
@@ -38,8 +38,8 @@ const char *Triple::getArchTypeName(ArchType Kind) {
case x86_64: return "x86_64";
case xcore: return "xcore";
case mblaze: return "mblaze";
- case ptx32: return "ptx32";
- case ptx64: return "ptx64";
+ case nvptx: return "nvptx";
+ case nvptx64: return "nvptx64";
case le32: return "le32";
case amdil: return "amdil";
}
@@ -62,7 +62,12 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {
case mblaze: return "mblaze";
- case hexagon: return "hexagon";
+ case mips:
+ case mipsel:
+ case mips64:
+ case mips64el:return "mips";
+
+ case hexagon: return "hexagon";
case r600: return "r600";
@@ -74,8 +79,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {
case xcore: return "xcore";
- case ptx32: return "ptx";
- case ptx64: return "ptx";
+ case nvptx: return "nvptx";
+ case nvptx64: return "nvptx";
case le32: return "le32";
case amdil: return "amdil";
}
@@ -119,6 +124,7 @@ const char *Triple::getOSTypeName(OSType Kind) {
case RTEMS: return "rtems";
case NativeClient: return "nacl";
case CNK: return "cnk";
+ case Bitrig: return "bitrig";
}
llvm_unreachable("Invalid OSType");
@@ -160,8 +166,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("x86", x86)
.Case("x86-64", x86_64)
.Case("xcore", xcore)
- .Case("ptx32", ptx32)
- .Case("ptx64", ptx64)
+ .Case("nvptx", nvptx)
+ .Case("nvptx64", nvptx64)
.Case("le32", le32)
.Case("amdil", amdil)
.Default(UnknownArch);
@@ -192,8 +198,8 @@ Triple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) {
.Cases("arm", "armv4t", "armv5", "armv6", Triple::arm)
.Cases("armv7", "armv7f", "armv7k", "armv7s", "xscale", Triple::arm)
.Case("r600", Triple::r600)
- .Case("ptx32", Triple::ptx32)
- .Case("ptx64", Triple::ptx64)
+ .Case("nvptx", Triple::nvptx)
+ .Case("nvptx64", Triple::nvptx64)
.Case("amdil", Triple::amdil)
.Default(Triple::UnknownArch);
}
@@ -215,8 +221,8 @@ const char *Triple::getArchNameForAssembler() {
.Cases("armv6", "thumbv6", "armv6")
.Cases("armv7", "thumbv7", "armv7")
.Case("r600", "r600")
- .Case("ptx32", "ptx32")
- .Case("ptx64", "ptx64")
+ .Case("nvptx", "nvptx")
+ .Case("nvptx64", "nvptx64")
.Case("le32", "le32")
.Case("amdil", "amdil")
.Default(NULL);
@@ -249,8 +255,8 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("sparcv9", Triple::sparcv9)
.Case("tce", Triple::tce)
.Case("xcore", Triple::xcore)
- .Case("ptx32", Triple::ptx32)
- .Case("ptx64", Triple::ptx64)
+ .Case("nvptx", Triple::nvptx)
+ .Case("nvptx64", Triple::nvptx64)
.Case("le32", Triple::le32)
.Case("amdil", Triple::amdil)
.Default(Triple::UnknownArch);
@@ -288,6 +294,7 @@ static Triple::OSType parseOS(StringRef OSName) {
.StartsWith("rtems", Triple::RTEMS)
.StartsWith("nacl", Triple::NativeClient)
.StartsWith("cnk", Triple::CNK)
+ .StartsWith("bitrig", Triple::Bitrig)
.Default(Triple::UnknownOS);
}
@@ -584,6 +591,29 @@ bool Triple::getMacOSXVersion(unsigned &Major, unsigned &Minor,
return true;
}
+void Triple::getiOSVersion(unsigned &Major, unsigned &Minor,
+ unsigned &Micro) const {
+ switch (getOS()) {
+ default: llvm_unreachable("unexpected OS for Darwin triple");
+ case Darwin:
+ case MacOSX:
+ // Ignore the version from the triple. This is only handled because the
+ // the clang driver combines OS X and IOS support into a common Darwin
+ // toolchain that wants to know the iOS version number even when targeting
+ // OS X.
+ Major = 3;
+ Minor = 0;
+ Micro = 0;
+ break;
+ case IOS:
+ getOSVersion(Major, Minor, Micro);
+ // Default to 3.0.
+ if (Major == 0)
+ Major = 3;
+ break;
+ }
+}
+
void Triple::setTriple(const Twine &Str) {
*this = Triple(Str);
}
@@ -652,8 +682,8 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::mblaze:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
+ case llvm::Triple::nvptx:
case llvm::Triple::ppc:
- case llvm::Triple::ptx32:
case llvm::Triple::r600:
case llvm::Triple::sparc:
case llvm::Triple::tce:
@@ -664,8 +694,8 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
+ case llvm::Triple::nvptx64:
case llvm::Triple::ppc64:
- case llvm::Triple::ptx64:
case llvm::Triple::sparcv9:
case llvm::Triple::x86_64:
return 64;
@@ -701,8 +731,8 @@ Triple Triple::get32BitArchVariant() const {
case Triple::mblaze:
case Triple::mips:
case Triple::mipsel:
+ case Triple::nvptx:
case Triple::ppc:
- case Triple::ptx32:
case Triple::r600:
case Triple::sparc:
case Triple::tce:
@@ -714,8 +744,8 @@ Triple Triple::get32BitArchVariant() const {
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::ptx64: T.setArch(Triple::ptx32); break;
case Triple::sparcv9: T.setArch(Triple::sparc); break;
case Triple::x86_64: T.setArch(Triple::x86); break;
}
@@ -742,8 +772,8 @@ Triple Triple::get64BitArchVariant() const {
case Triple::mips64:
case Triple::mips64el:
+ case Triple::nvptx64:
case Triple::ppc64:
- case Triple::ptx64:
case Triple::sparcv9:
case Triple::x86_64:
// Already 64-bit.
@@ -751,8 +781,8 @@ Triple Triple::get64BitArchVariant() const {
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::ptx32: T.setArch(Triple::ptx64); break;
case Triple::sparc: T.setArch(Triple::sparcv9); break;
case Triple::x86: T.setArch(Triple::x86_64); break;
}
diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc
index ddc1e0f..6bddbdf 100644
--- a/lib/Support/Unix/Path.inc
+++ b/lib/Support/Unix/Path.inc
@@ -260,7 +260,7 @@ Path::GetCurrentDirectory() {
return Path(pathname);
}
-#if defined(__FreeBSD__) || defined (__NetBSD__) || \
+#if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__)
static int
test_dir(char buf[PATH_MAX], char ret[PATH_MAX],
@@ -329,7 +329,7 @@ Path Path::GetMainExecutable(const char *argv0, void *MainAddr) {
if (realpath(exe_path, link_path))
return Path(link_path);
}
-#elif defined(__FreeBSD__) || defined (__NetBSD__) || \
+#elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__)
char exe_path[PATH_MAX];
@@ -884,7 +884,8 @@ const char *Path::MapInFilePages(int FD, size_t FileSize, off_t Offset) {
}
void Path::UnMapFilePages(const char *BasePtr, size_t FileSize) {
- ::munmap((void*)BasePtr, FileSize);
+ const void *Addr = static_cast<const void *>(BasePtr);
+ ::munmap(const_cast<void *>(Addr), FileSize);
}
} // end llvm namespace
diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc
index edb101e..99f8cd4 100644
--- a/lib/Support/Unix/PathV2.inc
+++ b/lib/Support/Unix/PathV2.inc
@@ -17,12 +17,16 @@
//===----------------------------------------------------------------------===//
#include "Unix.h"
+#include "llvm/Support/Process.h"
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
@@ -46,6 +50,12 @@
#include <limits.h>
#endif
+// Both stdio.h and cstdio are included via different pathes and
+// stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros
+// either.
+#undef ferror
+#undef feof
+
// For GNU Hurd
#if defined(__GNU__) && !defined(PATH_MAX)
# define PATH_MAX 4096
@@ -272,8 +282,7 @@ error_code exists(const Twine &path, bool &result) {
SmallString<128> path_storage;
StringRef p = path.toNullTerminatedStringRef(path_storage);
- struct stat status;
- if (::stat(p.begin(), &status) == -1) {
+ if (::access(p.begin(), F_OK) == -1) {
if (errno != errc::no_such_file_or_directory)
return error_code(errno, system_category());
result = false;
@@ -285,8 +294,8 @@ error_code exists(const Twine &path, bool &result) {
bool equivalent(file_status A, file_status B) {
assert(status_known(A) && status_known(B));
- return A.st_dev == B.st_dev &&
- A.st_ino == B.st_ino;
+ return A.fs_st_dev == B.fs_st_dev &&
+ A.fs_st_ino == B.fs_st_ino;
}
error_code equivalent(const Twine &A, const Twine &B, bool &result) {
@@ -325,30 +334,62 @@ error_code status(const Twine &path, file_status &result) {
return ec;
}
+ perms prms = static_cast<perms>(status.st_mode & perms_mask);
+
if (S_ISDIR(status.st_mode))
- result = file_status(file_type::directory_file);
+ result = file_status(file_type::directory_file, prms);
else if (S_ISREG(status.st_mode))
- result = file_status(file_type::regular_file);
+ result = file_status(file_type::regular_file, prms);
else if (S_ISBLK(status.st_mode))
- result = file_status(file_type::block_file);
+ result = file_status(file_type::block_file, prms);
else if (S_ISCHR(status.st_mode))
- result = file_status(file_type::character_file);
+ result = file_status(file_type::character_file, prms);
else if (S_ISFIFO(status.st_mode))
- result = file_status(file_type::fifo_file);
+ result = file_status(file_type::fifo_file, prms);
else if (S_ISSOCK(status.st_mode))
- result = file_status(file_type::socket_file);
+ result = file_status(file_type::socket_file, prms);
else
- result = file_status(file_type::type_unknown);
+ result = file_status(file_type::type_unknown, prms);
- result.st_dev = status.st_dev;
- result.st_ino = status.st_ino;
+ result.fs_st_dev = status.st_dev;
+ result.fs_st_ino = status.st_ino;
return error_code::success();
}
+// Modifies permissions on a file.
+error_code permissions(const Twine &path, perms prms) {
+ if ((prms & add_perms) && (prms & remove_perms))
+ llvm_unreachable("add_perms and remove_perms are mutually exclusive");
+
+ // Get current permissions
+ file_status info;
+ if (error_code ec = status(path, info)) {
+ return ec;
+ }
+
+ // Set updated permissions.
+ SmallString<128> path_storage;
+ StringRef p = path.toNullTerminatedStringRef(path_storage);
+ perms permsToSet;
+ if (prms & add_perms) {
+ permsToSet = (info.permissions() | prms) & perms_mask;
+ } else if (prms & remove_perms) {
+ permsToSet = (info.permissions() & ~prms) & perms_mask;
+ } else {
+ permsToSet = prms & perms_mask;
+ }
+ if (::chmod(p.begin(), static_cast<mode_t>(permsToSet))) {
+ return error_code(errno, system_category());
+ }
+
+ return error_code::success();
+}
+
+// Since this is most often used for temporary files, mode defaults to 0600.
error_code unique_file(const Twine &model, int &result_fd,
- SmallVectorImpl<char> &result_path,
- bool makeAbsolute) {
+ SmallVectorImpl<char> &result_path,
+ bool makeAbsolute, unsigned mode) {
SmallString<128> Model;
model.toVector(Model);
// Null terminate.
@@ -365,37 +406,20 @@ error_code unique_file(const Twine &model, int &result_fd,
}
}
- // Replace '%' with random chars. From here on, DO NOT modify model. It may be
- // needed if the randomly chosen path already exists.
- SmallString<128> RandomPath;
- RandomPath.reserve(Model.size() + 1);
- ::srand(::time(NULL));
+ // From here on, DO NOT modify model. It may be needed if the randomly chosen
+ // path already exists.
+ SmallString<128> RandomPath = Model;
retry_random_path:
- // This is opened here instead of above to make it easier to track when to
- // close it. Collisions should be rare enough for the possible extra syscalls
- // not to matter.
- FILE *RandomSource = ::fopen("/dev/urandom", "r");
- RandomPath.set_size(0);
- for (SmallVectorImpl<char>::const_iterator i = Model.begin(),
- e = Model.end(); i != e; ++i) {
- if (*i == '%') {
- char val = 0;
- if (RandomSource)
- val = fgetc(RandomSource);
- else
- val = ::rand();
- RandomPath.push_back("0123456789abcdef"[val & 15]);
- } else
- RandomPath.push_back(*i);
+ // Replace '%' with random chars.
+ for (unsigned i = 0, e = Model.size(); i != e; ++i) {
+ if (Model[i] == '%')
+ RandomPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
}
- if (RandomSource)
- ::fclose(RandomSource);
-
// Try to open + create the file.
rety_open_create:
- int RandomFD = ::open(RandomPath.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600);
+ int RandomFD = ::open(RandomPath.c_str(), O_RDWR | O_CREAT | O_EXCL, mode);
if (RandomFD == -1) {
// If the file existed, try again, otherwise, error.
if (errno == errc::file_exists)
@@ -511,6 +535,36 @@ error_code get_magic(const Twine &path, uint32_t len,
return error_code::success();
}
+error_code map_file_pages(const Twine &path, off_t file_offset, size_t size,
+ bool map_writable, void *&result) {
+ SmallString<128> path_storage;
+ StringRef name = path.toNullTerminatedStringRef(path_storage);
+ int oflags = map_writable ? O_RDWR : O_RDONLY;
+ int ofd = ::open(name.begin(), oflags);
+ if ( ofd == -1 )
+ return error_code(errno, system_category());
+ AutoFD fd(ofd);
+ int flags = map_writable ? MAP_SHARED : MAP_PRIVATE;
+ int prot = map_writable ? (PROT_READ|PROT_WRITE) : PROT_READ;
+#ifdef MAP_FILE
+ flags |= MAP_FILE;
+#endif
+ result = ::mmap(0, size, prot, flags, fd, file_offset);
+ if (result == MAP_FAILED) {
+ return error_code(errno, system_category());
+ }
+
+ return error_code::success();
+}
+
+error_code unmap_file_pages(void *base, size_t size) {
+ if ( ::munmap(base, size) == -1 )
+ return error_code(errno, system_category());
+
+ return error_code::success();
+}
+
+
} // end namespace fs
} // end namespace sys
} // end namespace llvm
diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc
index f640462..5204147 100644
--- a/lib/Support/Unix/Process.inc
+++ b/lib/Support/Unix/Process.inc
@@ -12,15 +12,18 @@
//===----------------------------------------------------------------------===//
#include "Unix.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Support/TimeValue.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
-// DragonFly BSD has deprecated <malloc.h> for <stdlib.h> instead,
-// Unix.h includes this for us already.
-#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__)
+// 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__) && \
+ !defined(__OpenBSD__) && !defined(__Bitrig__)
#include <malloc.h>
#endif
#ifdef HAVE_MALLOC_MALLOC_H
@@ -247,16 +250,18 @@ static bool terminalHasColors() {
return false;
}
+bool Process::FileDescriptorHasColors(int fd) {
+ // A file descriptor has colors if it is displayed and the terminal has
+ // colors.
+ return FileDescriptorIsDisplayed(fd) && terminalHasColors();
+}
+
bool Process::StandardOutHasColors() {
- if (!StandardOutIsDisplayed())
- return false;
- return terminalHasColors();
+ return FileDescriptorHasColors(STDOUT_FILENO);
}
bool Process::StandardErrHasColors() {
- if (!StandardErrIsDisplayed())
- return false;
- return terminalHasColors();
+ return FileDescriptorHasColors(STDERR_FILENO);
}
bool Process::ColorNeedsFlush() {
@@ -297,3 +302,33 @@ const char *Process::OutputReverse() {
const char *Process::ResetColor() {
return "\033[0m";
}
+
+#if !defined(HAVE_ARC4RANDOM)
+static unsigned GetRandomNumberSeed() {
+ // Attempt to get the initial seed from /dev/urandom, if possible.
+ if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
+ unsigned seed;
+ int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
+ ::fclose(RandomSource);
+
+ // Return the seed if the read was successful.
+ if (count == 1)
+ return seed;
+ }
+
+ // Otherwise, swizzle the current time and the process ID to form a reasonable
+ // seed.
+ TimeValue Now = llvm::TimeValue::now();
+ return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
+}
+#endif
+
+unsigned llvm::sys::Process::GetRandomNumber() {
+#if defined(HAVE_ARC4RANDOM)
+ return arc4random();
+#else
+ static int x = (::srand(GetRandomNumberSeed()), 0);
+ (void)x;
+ return ::rand();
+#endif
+}
diff --git a/lib/Support/Unix/Signals.inc b/lib/Support/Unix/Signals.inc
index c9ec9fc..5195116 100644
--- a/lib/Support/Unix/Signals.inc
+++ b/lib/Support/Unix/Signals.inc
@@ -15,6 +15,7 @@
#include "Unix.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Mutex.h"
+#include <string>
#include <vector>
#include <algorithm>
#if HAVE_EXECINFO_H
@@ -43,7 +44,7 @@ static SmartMutex<true> SignalsMutex;
/// InterruptFunction - The function to call if ctrl-c is pressed.
static void (*InterruptFunction)() = 0;
-static std::vector<sys::Path> FilesToRemove;
+static std::vector<std::string> FilesToRemove;
static std::vector<std::pair<void(*)(void*), void*> > CallBacksToRun;
// IntSigs - Signals that may interrupt the program at any time.
@@ -117,10 +118,20 @@ static void UnregisterHandlers() {
/// RemoveFilesToRemove - Process the FilesToRemove list. This function
/// should be called with the SignalsMutex lock held.
+/// NB: This must be an async signal safe function. It cannot allocate or free
+/// memory, even in debug builds.
static void RemoveFilesToRemove() {
- while (!FilesToRemove.empty()) {
- FilesToRemove.back().eraseFromDisk(true);
- FilesToRemove.pop_back();
+ // Note: avoid iterators in case of debug iterators that allocate or release
+ // memory.
+ for (unsigned i = 0, e = FilesToRemove.size(); i != e; ++i) {
+ // Note that we don't want to use any external code here, and we don't care
+ // about errors. We're going to try as hard as we can as often as we need
+ // to to make these files go away. If these aren't files, too bad.
+ //
+ // We do however rely on a std::string implementation for which repeated
+ // calls to 'c_str()' don't allocate memory. We pre-call 'c_str()' on all
+ // of these strings to try to ensure this is safe.
+ unlink(FilesToRemove[i].c_str());
}
}
@@ -178,7 +189,19 @@ void llvm::sys::SetInterruptFunction(void (*IF)()) {
bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename,
std::string* ErrMsg) {
SignalsMutex.acquire();
- FilesToRemove.push_back(Filename);
+ std::string *OldPtr = FilesToRemove.empty() ? 0 : &FilesToRemove[0];
+ FilesToRemove.push_back(Filename.str());
+
+ // 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();
@@ -189,10 +212,19 @@ bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename,
// DontRemoveFileOnSignal - The public API
void llvm::sys::DontRemoveFileOnSignal(const sys::Path &Filename) {
SignalsMutex.acquire();
- std::vector<sys::Path>::reverse_iterator I =
- std::find(FilesToRemove.rbegin(), FilesToRemove.rend(), Filename);
- if (I != FilesToRemove.rend())
- FilesToRemove.erase(I.base()-1);
+ std::vector<std::string>::reverse_iterator RI =
+ std::find(FilesToRemove.rbegin(), FilesToRemove.rend(), Filename.str());
+ 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)
+ I->c_str();
+
SignalsMutex.release();
}
diff --git a/lib/Support/Unix/Unix.h b/lib/Support/Unix/Unix.h
index b7be311..361f297 100644
--- a/lib/Support/Unix/Unix.h
+++ b/lib/Support/Unix/Unix.h
@@ -44,16 +44,10 @@
#include <assert.h>
#endif
-#ifdef TIME_WITH_SYS_TIME
+#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
-# include <time.h>
-#else
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
#endif
+#include <time.h>
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc
index d8dc522..2280b34 100644
--- a/lib/Support/Windows/Path.inc
+++ b/lib/Support/Windows/Path.inc
@@ -188,8 +188,20 @@ static Path *TempDirectory;
Path
Path::GetTemporaryDirectory(std::string* ErrMsg) {
- if (TempDirectory)
+ if (TempDirectory) {
+#if defined(_MSC_VER)
+ // Visual Studio gets confused and emits a diagnostic about calling exists,
+ // even though this is the implementation for PathV1. Temporarily
+ // disable the deprecated warning message
+ #pragma warning(push)
+ #pragma warning(disable:4996)
+#endif
+ assert(TempDirectory->exists() && "Who has removed TempDirectory?");
+#if defined(_MSC_VER)
+ #pragma warning(pop)
+#endif
return *TempDirectory;
+ }
char pathname[MAX_PATH];
if (!GetTempPath(MAX_PATH, pathname)) {
@@ -201,7 +213,7 @@ Path::GetTemporaryDirectory(std::string* ErrMsg) {
Path result;
result.set(pathname);
- // Append a subdirectory passed on our process id so multiple LLVMs don't
+ // Append a subdirectory based on our process id so multiple LLVMs don't
// step on each other's toes.
#ifdef __MINGW32__
// Mingw's Win32 header files are broken.
diff --git a/lib/Support/Windows/PathV2.inc b/lib/Support/Windows/PathV2.inc
index e9ce5d9..66eeab0 100644
--- a/lib/Support/Windows/PathV2.inc
+++ b/lib/Support/Windows/PathV2.inc
@@ -301,11 +301,21 @@ error_code rename(const Twine &from, const Twine &to) {
if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec;
if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec;
- if (!::MoveFileExW(wide_from.begin(), wide_to.begin(),
- MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
- return windows_error(::GetLastError());
+ error_code ec = error_code::success();
+ for (int i = 0; i < 2000; i++) {
+ if (::MoveFileExW(wide_from.begin(), wide_to.begin(),
+ MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
+ return error_code::success();
+ ec = windows_error(::GetLastError());
+ if (ec != windows_error::access_denied)
+ break;
+ // Retry MoveFile() at ACCESS_DENIED.
+ // System scanners (eg. indexer) might open the source file when
+ // It is written and closed.
+ ::Sleep(1);
+ }
- return error_code::success();
+ return ec;
}
error_code resize_file(const Twine &path, uint64_t size) {
@@ -487,9 +497,46 @@ handle_status_error:
return error_code::success();
}
+
+// Modifies permissions on a file.
+error_code permissions(const Twine &path, perms prms) {
+#if 0 // verify code below before enabling:
+ // If the permissions bits are not trying to modify
+ // "write" permissions, there is nothing to do.
+ if (!(prms & (owner_write|group_write|others_write)))
+ return error_code::success();
+
+ SmallString<128> path_storage;
+ SmallVector<wchar_t, 128> path_utf16;
+
+ if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage),
+ path_utf16))
+ return ec;
+
+ DWORD attributes = ::GetFileAttributesW(path_utf16.begin());
+
+ if (prms & add_perms) {
+ attributes &= ~FILE_ATTRIBUTE_READONLY;
+ }
+ else if (prms & remove_perms) {
+ attributes |= FILE_ATTRIBUTE_READONLY;
+ }
+ else {
+ assert(0 && "neither add_perms or remove_perms is set");
+ }
+
+ if ( ! ::SetFileAttributesW(path_utf16.begin(), attributes))
+ return windows_error(::GetLastError());
+#endif
+ return error_code::success();
+}
+
+
+// FIXME: mode should be used here and default to user r/w only,
+// it currently comes in as a UNIX mode.
error_code unique_file(const Twine &model, int &result_fd,
- SmallVectorImpl<char> &result_path,
- bool makeAbsolute) {
+ SmallVectorImpl<char> &result_path,
+ bool makeAbsolute, unsigned mode) {
// Use result_path as temp storage.
result_path.set_size(0);
StringRef m = model.toStringRef(result_path);
@@ -743,6 +790,19 @@ error_code detail::directory_iterator_increment(detail::DirIterState &it) {
return error_code::success();
}
+error_code map_file_pages(const Twine &path, off_t file_offset, size_t size,
+ bool map_writable, void *&result) {
+ assert(0 && "NOT IMPLEMENTED");
+ return windows_error::invalid_function;
+}
+
+error_code unmap_file_pages(void *base, size_t size) {
+ assert(0 && "NOT IMPLEMENTED");
+ return windows_error::invalid_function;
+}
+
+
+
} // end namespace fs
} // end namespace sys
} // end namespace llvm
diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc
index 9a388b4..e29eb6d 100644
--- a/lib/Support/Windows/Process.inc
+++ b/lib/Support/Windows/Process.inc
@@ -133,7 +133,7 @@ bool Process::StandardErrIsDisplayed() {
}
bool Process::FileDescriptorIsDisplayed(int fd) {
- DWORD Mode; // Unused
+ DWORD Mode; // Unused
return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
}
@@ -153,13 +153,17 @@ unsigned Process::StandardErrColumns() {
return Columns;
}
-// It always has colors.
-bool Process::StandardErrHasColors() {
- return StandardErrIsDisplayed();
+// The terminal always has colors.
+bool Process::FileDescriptorHasColors(int fd) {
+ return FileDescriptorIsDisplayed(fd);
}
bool Process::StandardOutHasColors() {
- return StandardOutIsDisplayed();
+ return FileDescriptorHasColors(1);
+}
+
+bool Process::StandardErrHasColors() {
+ return FileDescriptorHasColors(2);
}
namespace {
diff --git a/lib/Support/Windows/RWMutex.inc b/lib/Support/Windows/RWMutex.inc
index 26b9bba..9593923 100644
--- a/lib/Support/Windows/RWMutex.inc
+++ b/lib/Support/Windows/RWMutex.inc
@@ -67,9 +67,9 @@ static bool loadSRW() {
"ReleaseSRWLockShared");
::FreeLibrary(hLib);
- if (fpInitializeSRWLock != NULL) {
- sHasSRW = true;
- }
+ if (fpInitializeSRWLock != NULL) {
+ sHasSRW = true;
+ }
}
}
return sHasSRW;
diff --git a/lib/Support/Windows/ThreadLocal.inc b/lib/Support/Windows/ThreadLocal.inc
index 512462d..057deb3 100644
--- a/lib/Support/Windows/ThreadLocal.inc
+++ b/lib/Support/Windows/ThreadLocal.inc
@@ -22,26 +22,25 @@
namespace llvm {
using namespace sys;
-ThreadLocalImpl::ThreadLocalImpl() {
- DWORD* tls = new DWORD;
+ThreadLocalImpl::ThreadLocalImpl() : data() {
+ typedef int SIZE_TOO_BIG[sizeof(DWORD) <= sizeof(data) ? 1 : -1];
+ DWORD* tls = reinterpret_cast<DWORD*>(&data);
*tls = TlsAlloc();
assert(*tls != TLS_OUT_OF_INDEXES);
- data = tls;
}
ThreadLocalImpl::~ThreadLocalImpl() {
- DWORD* tls = static_cast<DWORD*>(data);
+ DWORD* tls = reinterpret_cast<DWORD*>(&data);
TlsFree(*tls);
- delete tls;
}
const void* ThreadLocalImpl::getInstance() {
- DWORD* tls = static_cast<DWORD*>(data);
+ DWORD* tls = reinterpret_cast<DWORD*>(&data);
return TlsGetValue(*tls);
}
void ThreadLocalImpl::setInstance(const void* d){
- DWORD* tls = static_cast<DWORD*>(data);
+ DWORD* tls = reinterpret_cast<DWORD*>(&data);
int errorcode = TlsSetValue(*tls, const_cast<void*>(d));
assert(errorcode != 0);
(void)errorcode;
diff --git a/lib/Support/YAMLParser.cpp b/lib/Support/YAMLParser.cpp
index d38b51b..7c353c8 100644
--- a/lib/Support/YAMLParser.cpp
+++ b/lib/Support/YAMLParser.cpp
@@ -27,12 +27,12 @@ using namespace llvm;
using namespace yaml;
enum UnicodeEncodingForm {
- UEF_UTF32_LE, //< UTF-32 Little Endian
- UEF_UTF32_BE, //< UTF-32 Big Endian
- UEF_UTF16_LE, //< UTF-16 Little Endian
- UEF_UTF16_BE, //< UTF-16 Big Endian
- UEF_UTF8, //< UTF-8 or ascii.
- UEF_Unknown //< Not a valid Unicode encoding.
+ UEF_UTF32_LE, ///< UTF-32 Little Endian
+ UEF_UTF32_BE, ///< UTF-32 Big Endian
+ UEF_UTF16_LE, ///< UTF-16 Little Endian
+ UEF_UTF16_BE, ///< UTF-16 Big Endian
+ UEF_UTF8, ///< UTF-8 or ascii.
+ UEF_Unknown ///< Not a valid Unicode encoding.
};
/// EncodingInfo - Holds the encoding type and length of the byte order mark if
@@ -489,9 +489,6 @@ private:
/// @brief Can the next token be the start of a simple key?
bool IsSimpleKeyAllowed;
- /// @brief Is the next token required to start a simple key?
- bool IsSimpleKeyRequired;
-
/// @brief True if an error has occurred.
bool Failed;
@@ -658,7 +655,7 @@ std::string yaml::escape(StringRef Input) {
EscapedInput += "\\r";
else if (*i == 0x1B)
EscapedInput += "\\e";
- else if (*i >= 0 && *i < 0x20) { // Control characters not handled above.
+ else if ((unsigned char)*i < 0x20) { // Control characters not handled above.
std::string HexStr = utohexstr(*i);
EscapedInput += "\\x" + std::string(2 - HexStr.size(), '0') + HexStr;
} else if (*i & 0x80) { // UTF-8 multiple code unit subsequence.
@@ -704,7 +701,6 @@ Scanner::Scanner(StringRef Input, SourceMgr &sm)
, FlowLevel(0)
, IsStartOfStream(true)
, IsSimpleKeyAllowed(true)
- , IsSimpleKeyRequired(false)
, Failed(false) {
InputBuffer = MemoryBuffer::getMemBuffer(Input, "YAML");
SM.AddNewSourceBuffer(InputBuffer, SMLoc());
@@ -755,6 +751,8 @@ Token Scanner::getNext() {
}
StringRef::iterator Scanner::skip_nb_char(StringRef::iterator Position) {
+ if (Position == End)
+ return Position;
// Check 7 bit c-printable - b-char.
if ( *Position == 0x09
|| (*Position >= 0x20 && *Position <= 0x7E))
@@ -778,6 +776,8 @@ StringRef::iterator Scanner::skip_nb_char(StringRef::iterator Position) {
}
StringRef::iterator Scanner::skip_b_break(StringRef::iterator Position) {
+ if (Position == End)
+ return Position;
if (*Position == 0x0D) {
if (Position + 1 != End && *(Position + 1) == 0x0A)
return Position + 2;
@@ -1211,7 +1211,9 @@ bool Scanner::scanFlowScalar(bool IsDoubleQuoted) {
++Current;
// Repeat until the previous character was not a '\' or was an escaped
// backslash.
- } while (*(Current - 1) == '\\' && wasEscaped(Start + 1, Current));
+ } while ( Current != End
+ && *(Current - 1) == '\\'
+ && wasEscaped(Start + 1, Current));
} else {
skip(1);
while (true) {
@@ -1624,9 +1626,7 @@ StringRef ScalarNode::getValue(SmallVectorImpl<char> &Storage) const {
return UnquotedValue;
}
// Plain or block.
- size_t trimtrail = Value.rfind(' ');
- return Value.drop_back(
- trimtrail == StringRef::npos ? 0 : Value.size() - trimtrail);
+ return Value.rtrim(" ");
}
StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue
@@ -1732,8 +1732,10 @@ StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue
if (UnquotedValue.size() < 3)
// TODO: Report error.
break;
- unsigned int UnicodeScalarValue = 0;
- UnquotedValue.substr(1, 2).getAsInteger(16, UnicodeScalarValue);
+ unsigned int UnicodeScalarValue;
+ if (UnquotedValue.substr(1, 2).getAsInteger(16, UnicodeScalarValue))
+ // TODO: Report error.
+ UnicodeScalarValue = 0xFFFD;
encodeUTF8(UnicodeScalarValue, Storage);
UnquotedValue = UnquotedValue.substr(2);
break;
@@ -1742,8 +1744,10 @@ StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue
if (UnquotedValue.size() < 5)
// TODO: Report error.
break;
- unsigned int UnicodeScalarValue = 0;
- UnquotedValue.substr(1, 4).getAsInteger(16, UnicodeScalarValue);
+ unsigned int UnicodeScalarValue;
+ if (UnquotedValue.substr(1, 4).getAsInteger(16, UnicodeScalarValue))
+ // TODO: Report error.
+ UnicodeScalarValue = 0xFFFD;
encodeUTF8(UnicodeScalarValue, Storage);
UnquotedValue = UnquotedValue.substr(4);
break;
@@ -1752,8 +1756,10 @@ StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue
if (UnquotedValue.size() < 9)
// TODO: Report error.
break;
- unsigned int UnicodeScalarValue = 0;
- UnquotedValue.substr(1, 8).getAsInteger(16, UnicodeScalarValue);
+ unsigned int UnicodeScalarValue;
+ if (UnquotedValue.substr(1, 8).getAsInteger(16, UnicodeScalarValue))
+ // TODO: Report error.
+ UnicodeScalarValue = 0xFFFD;
encodeUTF8(UnicodeScalarValue, Storage);
UnquotedValue = UnquotedValue.substr(8);
break;
@@ -2113,5 +2119,3 @@ bool Document::expectToken(int TK) {
}
return true;
}
-
-OwningPtr<Document> document_iterator::NullDoc;
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index 86cdca1..fa69c2d 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -528,7 +528,8 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
} else {
// Use ::writev() where available.
#if defined(HAVE_WRITEV)
- struct iovec IOV = { (void*) Ptr, Size };
+ const void *Addr = static_cast<const void *>(Ptr);
+ struct iovec IOV = {const_cast<void *>(Addr), Size };
ret = ::writev(FD, &IOV, 1);
#else
ret = ::write(FD, Ptr, Size);
@@ -650,6 +651,10 @@ bool raw_fd_ostream::is_displayed() const {
return sys::Process::FileDescriptorIsDisplayed(FD);
}
+bool raw_fd_ostream::has_colors() const {
+ return sys::Process::FileDescriptorHasColors(FD);
+}
+
//===----------------------------------------------------------------------===//
// outs(), errs(), nulls()
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud