aboutsummaryrefslogtreecommitdiff
path: root/lib/Support
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Support')
-rw-r--r--lib/Support/APFloat.cpp9
-rw-r--r--lib/Support/CMakeLists.txt1
-rw-r--r--lib/Support/ConstantRange.cpp2
-rw-r--r--lib/Support/Dwarf.cpp4
-rw-r--r--lib/Support/DynamicLibrary.cpp2
-rw-r--r--lib/Support/FoldingSet.cpp4
-rw-r--r--lib/Support/Host.cpp58
-rw-r--r--lib/Support/LockFileManager.cpp16
-rw-r--r--lib/Support/MemoryBuffer.cpp4
-rw-r--r--lib/Support/Path.cpp1
-rw-r--r--lib/Support/Process.cpp60
-rw-r--r--lib/Support/SourceMgr.cpp193
-rw-r--r--lib/Support/Unix/Memory.inc20
-rw-r--r--lib/Support/Unix/PathV2.inc13
-rw-r--r--lib/Support/Unix/Process.inc102
-rw-r--r--lib/Support/Unix/Program.inc23
-rw-r--r--lib/Support/Unix/Signals.inc26
-rw-r--r--lib/Support/Windows/Process.inc81
-rw-r--r--lib/Support/Windows/Program.inc22
-rw-r--r--lib/Support/Windows/Signals.inc4
-rw-r--r--lib/Support/YAMLTraits.cpp827
21 files changed, 1271 insertions, 201 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 17f38918b3..4a7a5d1a05 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -697,6 +697,13 @@ APFloat::operator=(const APFloat &rhs)
}
bool
+APFloat::isDenormal() const {
+ return isNormal() && (exponent == semantics->minExponent) &&
+ (APInt::tcExtractBit(significandParts(),
+ semantics->precision - 1) == 0);
+}
+
+bool
APFloat::bitwiseIsEqual(const APFloat &rhs) const {
if (this == &rhs)
return true;
@@ -3441,7 +3448,7 @@ void APFloat::toString(SmallVectorImpl<char> &Str,
AdjustToPrecision(significand, exp, FormatPrecision);
- llvm::SmallVector<char, 256> buffer;
+ SmallVector<char, 256> buffer;
// Fill the buffer.
unsigned precision = significand.getBitWidth();
diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt
index 6af0f4a6c9..f294a175e7 100644
--- a/lib/Support/CMakeLists.txt
+++ b/lib/Support/CMakeLists.txt
@@ -50,6 +50,7 @@ add_llvm_library(LLVMSupport
Triple.cpp
Twine.cpp
YAMLParser.cpp
+ YAMLTraits.cpp
raw_os_ostream.cpp
raw_ostream.cpp
regcomp.c
diff --git a/lib/Support/ConstantRange.cpp b/lib/Support/ConstantRange.cpp
index 720ef36c46..5c5895026b 100644
--- a/lib/Support/ConstantRange.cpp
+++ b/lib/Support/ConstantRange.cpp
@@ -21,7 +21,7 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/InstrTypes.h"
+#include "llvm/IR/InstrTypes.h"
#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/lib/Support/Dwarf.cpp b/lib/Support/Dwarf.cpp
index de70b0c00c..615efb8b0e 100644
--- a/lib/Support/Dwarf.cpp
+++ b/lib/Support/Dwarf.cpp
@@ -80,8 +80,6 @@ const char *llvm::dwarf::TagString(unsigned Tag) {
case DW_TAG_hi_user: return "DW_TAG_hi_user";
case DW_TAG_auto_variable: return "DW_TAG_auto_variable";
case DW_TAG_arg_variable: return "DW_TAG_arg_variable";
- case DW_TAG_return_variable: return "DW_TAG_return_variable";
- case DW_TAG_vector_type: return "DW_TAG_vector_type";
case DW_TAG_rvalue_reference_type: return "DW_TAG_rvalue_reference_type";
case DW_TAG_template_alias: return "DW_TAG_template_alias";
case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop";
@@ -249,7 +247,7 @@ const char *llvm::dwarf::AttributeString(unsigned Attribute) {
case DW_AT_APPLE_property: return "DW_AT_APPLE_property";
case DW_AT_APPLE_objc_complete_type: return "DW_AT_APPLE_objc_complete_type";
- // DWARF5 Fission Extension Attributes
+ // DWARF5 Fission Extension Attribute
case DW_AT_GNU_dwo_name: return "DW_AT_GNU_dwo_name";
case DW_AT_GNU_dwo_id: return "DW_AT_GNU_dwo_id";
case DW_AT_GNU_ranges_base: return "DW_AT_GNU_ranges_base";
diff --git a/lib/Support/DynamicLibrary.cpp b/lib/Support/DynamicLibrary.cpp
index b04681d577..153014f790 100644
--- a/lib/Support/DynamicLibrary.cpp
+++ b/lib/Support/DynamicLibrary.cpp
@@ -46,7 +46,7 @@ void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
void *symbolValue) {
SmartScopedLock<true> lock(getMutex());
if (ExplicitSymbols == 0)
- ExplicitSymbols = new llvm::StringMap<void*>();
+ ExplicitSymbols = new StringMap<void*>();
(*ExplicitSymbols)[symbolName] = symbolValue;
}
diff --git a/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp
index 9c44c9348b..36e33b5aaf 100644
--- a/lib/Support/FoldingSet.cpp
+++ b/lib/Support/FoldingSet.cpp
@@ -148,7 +148,7 @@ unsigned FoldingSetNodeID::ComputeHash() const {
/// operator== - Used to compare two nodes to each other.
///
-bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS)const{
+bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS) const {
return *this == FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size());
}
@@ -160,7 +160,7 @@ bool FoldingSetNodeID::operator==(FoldingSetNodeIDRef RHS) const {
/// Used to compare the "ordering" of two nodes as defined by the
/// profiled bits and their ordering defined by memcmp().
-bool FoldingSetNodeID::operator<(const FoldingSetNodeID &RHS)const{
+bool FoldingSetNodeID::operator<(const FoldingSetNodeID &RHS) const {
return *this < FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size());
}
diff --git a/lib/Support/Host.cpp b/lib/Support/Host.cpp
index 35bfb49a1f..5ad5308c41 100644
--- a/lib/Support/Host.cpp
+++ b/lib/Support/Host.cpp
@@ -517,6 +517,64 @@ std::string sys::getHostCPUName() {
}
#endif
+#if defined(__linux__) && defined(__arm__)
+bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
+ std::string Err;
+ DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err);
+ if (!DS) {
+ DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n");
+ return false;
+ }
+
+ // Read 1024 bytes from /proc/cpuinfo, which should contain the Features line
+ // in all cases.
+ char buffer[1024];
+ size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer));
+ delete DS;
+
+ StringRef Str(buffer, CPUInfoSize);
+
+ SmallVector<StringRef, 32> Lines;
+ Str.split(Lines, "\n");
+
+ // Look for the CPU implementer line.
+ StringRef Implementer;
+ for (unsigned I = 0, E = Lines.size(); I != E; ++I)
+ if (Lines[I].startswith("CPU implementer"))
+ Implementer = Lines[I].substr(15).ltrim("\t :");
+
+ if (Implementer == "0x41") { // ARM Ltd.
+ SmallVector<StringRef, 32> CPUFeatures;
+
+ // Look for the CPU features.
+ for (unsigned I = 0, E = Lines.size(); I != E; ++I)
+ if (Lines[I].startswith("Features")) {
+ Lines[I].split(CPUFeatures, " ");
+ break;
+ }
+
+ for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
+ StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
+ .Case("half", "fp16")
+ .Case("neon", "neon")
+ .Case("vfpv3", "vfp3")
+ .Case("vfpv3d16", "d16")
+ .Case("vfpv4", "vfp4")
+ .Case("idiva", "hwdiv-arm")
+ .Case("idivt", "hwdiv")
+ .Default("");
+
+ if (LLVMFeatureStr != "")
+ Features.GetOrCreateValue(LLVMFeatureStr).setValue(true);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+#else
bool sys::getHostCPUFeatures(StringMap<bool> &Features){
return false;
}
+#endif
diff --git a/lib/Support/LockFileManager.cpp b/lib/Support/LockFileManager.cpp
index dc28a72421..64ec142b27 100644
--- a/lib/Support/LockFileManager.cpp
+++ b/lib/Support/LockFileManager.cpp
@@ -64,6 +64,7 @@ bool LockFileManager::processStillExecuting(StringRef Hostname, int PID) {
LockFileManager::LockFileManager(StringRef FileName)
{
+ this->FileName = FileName;
LockFileName = FileName;
LockFileName += ".lock";
@@ -175,6 +176,7 @@ void LockFileManager::waitForUnlock() {
#endif
// Don't wait more than an hour for the file to appear.
const unsigned MaxSeconds = 3600;
+ bool LockFileGone = false;
do {
// Sleep for the designated interval, to allow the owning process time to
// finish up and remove the lock file.
@@ -185,10 +187,18 @@ void LockFileManager::waitForUnlock() {
#else
nanosleep(&Interval, NULL);
#endif
- // If the file no longer exists, we're done.
+ // If the lock file no longer exists, wait for the actual file.
bool Exists = false;
- if (!sys::fs::exists(LockFileName.str(), Exists) && !Exists)
- return;
+ if (!LockFileGone) {
+ if (!sys::fs::exists(LockFileName.str(), Exists) && !Exists) {
+ LockFileGone = true;
+ Exists = false;
+ }
+ }
+ if (LockFileGone) {
+ if (!sys::fs::exists(FileName.str(), Exists) && Exists)
+ return;
+ }
if (!processStillExecuting((*Owner).first, (*Owner).second))
return;
diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp
index 79e1994991..541d160ba1 100644
--- a/lib/Support/MemoryBuffer.cpp
+++ b/lib/Support/MemoryBuffer.cpp
@@ -187,7 +187,7 @@ public:
: MemoryBufferMem(Buffer, RequiresNullTerminator) { }
~MemoryBufferMMapFile() {
- static int PageSize = sys::Process::GetPageSize();
+ static int PageSize = sys::process::get_self()->page_size();
uintptr_t Start = reinterpret_cast<uintptr_t>(getBufferStart());
size_t Size = getBufferSize();
@@ -308,7 +308,7 @@ error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
uint64_t FileSize, uint64_t MapSize,
int64_t Offset,
bool RequiresNullTerminator) {
- static int PageSize = sys::Process::GetPageSize();
+ static int PageSize = sys::process::get_self()->page_size();
// Default is to map the full file.
if (MapSize == uint64_t(-1)) {
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index c67af1b216..d0703754e0 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -15,7 +15,6 @@
#include "llvm/Config/config.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileSystem.h"
#include <cassert>
#include <cstring>
#include <ostream>
diff --git a/lib/Support/Process.cpp b/lib/Support/Process.cpp
index 88ca7c3f22..2c0d37bb32 100644
--- a/lib/Support/Process.cpp
+++ b/lib/Support/Process.cpp
@@ -11,10 +11,11 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/Process.h"
#include "llvm/Config/config.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Process.h"
-namespace llvm {
+using namespace llvm;
using namespace sys;
//===----------------------------------------------------------------------===//
@@ -22,8 +23,63 @@ using namespace sys;
//=== independent code.
//===----------------------------------------------------------------------===//
+// Empty virtual destructor to anchor the vtable for the process class.
+process::~process() {}
+
+self_process *process::get_self() {
+ // Use a function local static for thread safe initialization and allocate it
+ // as a raw pointer to ensure it is never destroyed.
+ static self_process *SP = new self_process();
+
+ return SP;
}
+#if defined(_MSC_VER)
+// Visual Studio complains that the self_process destructor never exits. This
+// doesn't make much sense, as that's the whole point of calling abort... Just
+// silence this warning.
+#pragma warning(push)
+#pragma warning(disable:4722)
+#endif
+
+// The destructor for the self_process subclass must never actually be
+// executed. There should be at most one instance of this class, and that
+// instance should live until the process terminates to avoid the potential for
+// racy accesses during shutdown.
+self_process::~self_process() {
+ llvm_unreachable("This destructor must never be executed!");
+}
+
+/// \brief A helper function to compute the elapsed wall-time since the program
+/// started.
+///
+/// Note that this routine actually computes the elapsed wall time since the
+/// first time it was called. However, we arrange to have it called during the
+/// startup of the process to get approximately correct results.
+static TimeValue getElapsedWallTime() {
+ static TimeValue &StartTime = *new TimeValue(TimeValue::now());
+ return TimeValue::now() - StartTime;
+}
+
+/// \brief A special global variable to ensure we call \c getElapsedWallTime
+/// during global initialization of the program.
+///
+/// Note that this variable is never referenced elsewhere. Doing so could
+/// create race conditions during program startup or shutdown.
+static volatile TimeValue DummyTimeValue = getElapsedWallTime();
+
+// Implement this routine by using the static helpers above. They're already
+// portable.
+TimeValue self_process::get_wall_time() const {
+ return getElapsedWallTime();
+}
+
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+
// Include the platform-specific parts of this class.
#ifdef LLVM_ON_UNIX
#include "Unix/Process.inc"
diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp
index 6580137569..fa82265f38 100644
--- a/lib/Support/SourceMgr.cpp
+++ b/lib/Support/SourceMgr.cpp
@@ -15,12 +15,16 @@
#include "llvm/Support/SourceMgr.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Locale.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
using namespace llvm;
+static const size_t TabStop = 8;
+
namespace {
struct LineNoCacheTy {
int LastQueryBufferID;
@@ -146,7 +150,8 @@ void SourceMgr::PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const {
/// prefixed to the message.
SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
const Twine &Msg,
- ArrayRef<SMRange> Ranges) const {
+ ArrayRef<SMRange> Ranges,
+ ArrayRef<SMFixIt> FixIts) const {
// First thing to do: find the current buffer containing the specified
// location to pull out the source line.
@@ -193,6 +198,7 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
R.End = SMLoc::getFromPointer(LineEnd);
// Translate from SMLoc ranges to column ranges.
+ // FIXME: Handle multibyte characters.
ColRanges.push_back(std::make_pair(R.Start.getPointer()-LineStart,
R.End.getPointer()-LineStart));
}
@@ -202,13 +208,13 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
return SMDiagnostic(*this, Loc, BufferID, LineAndCol.first,
LineAndCol.second-1, Kind, Msg.str(),
- LineStr, ColRanges);
+ LineStr, ColRanges, FixIts);
}
void SourceMgr::PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
const Twine &Msg, ArrayRef<SMRange> Ranges,
- bool ShowColors) const {
- SMDiagnostic Diagnostic = GetMessage(Loc, Kind, Msg, Ranges);
+ ArrayRef<SMFixIt> FixIts, bool ShowColors) const {
+ SMDiagnostic Diagnostic = GetMessage(Loc, Kind, Msg, Ranges, FixIts);
// Report the message with the diagnostic handler if present.
if (DiagHandler) {
@@ -231,15 +237,108 @@ void SourceMgr::PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
// SMDiagnostic Implementation
//===----------------------------------------------------------------------===//
-SMDiagnostic::SMDiagnostic(const SourceMgr &sm, SMLoc L, const std::string &FN,
+SMDiagnostic::SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN,
int Line, int Col, SourceMgr::DiagKind Kind,
- const std::string &Msg,
- const std::string &LineStr,
- ArrayRef<std::pair<unsigned,unsigned> > Ranges)
+ StringRef Msg, StringRef LineStr,
+ ArrayRef<std::pair<unsigned,unsigned> > Ranges,
+ ArrayRef<SMFixIt> Hints)
: SM(&sm), Loc(L), Filename(FN), LineNo(Line), ColumnNo(Col), Kind(Kind),
- Message(Msg), LineContents(LineStr), Ranges(Ranges.vec()) {
+ Message(Msg), LineContents(LineStr), Ranges(Ranges.vec()),
+ FixIts(Hints.begin(), Hints.end()) {
+ std::sort(FixIts.begin(), FixIts.end());
}
+void buildFixItLine(std::string &CaretLine, std::string &FixItLine,
+ ArrayRef<SMFixIt> FixIts, ArrayRef<char> SourceLine) {
+ if (FixIts.empty())
+ return;
+
+ const char *LineStart = SourceLine.begin();
+ const char *LineEnd = SourceLine.end();
+
+ size_t PrevHintEndCol = 0;
+
+ for (ArrayRef<SMFixIt>::iterator I = FixIts.begin(), E = FixIts.end();
+ I != E; ++I) {
+ // If the fixit contains a newline or tab, ignore it.
+ if (I->getText().find_first_of("\n\r\t") != StringRef::npos)
+ continue;
+
+ SMRange R = I->getRange();
+
+ // If the line doesn't contain any part of the range, then ignore it.
+ if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
+ continue;
+
+ // Translate from SMLoc to column.
+ // Ignore pieces of the range that go onto other lines.
+ // FIXME: Handle multibyte characters in the source line.
+ unsigned FirstCol;
+ if (R.Start.getPointer() < LineStart)
+ FirstCol = 0;
+ else
+ FirstCol = R.Start.getPointer() - LineStart;
+
+ // If we inserted a long previous hint, push this one forwards, and add
+ // an extra space to show that this is not part of the previous
+ // completion. This is sort of the best we can do when two hints appear
+ // to overlap.
+ //
+ // Note that if this hint is located immediately after the previous
+ // hint, no space will be added, since the location is more important.
+ unsigned HintCol = FirstCol;
+ if (HintCol < PrevHintEndCol)
+ HintCol = PrevHintEndCol + 1;
+
+ // FIXME: This assertion is intended to catch unintended use of multibyte
+ // characters in fixits. If we decide to do this, we'll have to track
+ // separate byte widths for the source and fixit lines.
+ assert((size_t)llvm::sys::locale::columnWidth(I->getText()) ==
+ I->getText().size());
+
+ // This relies on one byte per column in our fixit hints.
+ unsigned LastColumnModified = HintCol + I->getText().size();
+ if (LastColumnModified > FixItLine.size())
+ FixItLine.resize(LastColumnModified, ' ');
+
+ std::copy(I->getText().begin(), I->getText().end(),
+ FixItLine.begin() + HintCol);
+
+ PrevHintEndCol = LastColumnModified;
+
+ // For replacements, mark the removal range with '~'.
+ // FIXME: Handle multibyte characters in the source line.
+ unsigned LastCol;
+ if (R.End.getPointer() >= LineEnd)
+ LastCol = LineEnd - LineStart;
+ else
+ LastCol = R.End.getPointer() - LineStart;
+
+ std::fill(&CaretLine[FirstCol], &CaretLine[LastCol], '~');
+ }
+}
+
+static void printSourceLine(raw_ostream &S, StringRef LineContents) {
+ // Print out the source line one character at a time, so we can expand tabs.
+ for (unsigned i = 0, e = LineContents.size(), OutCol = 0; i != e; ++i) {
+ if (LineContents[i] != '\t') {
+ S << LineContents[i];
+ ++OutCol;
+ continue;
+ }
+
+ // If we have a tab, emit at least one space, then round up to 8 columns.
+ do {
+ S << ' ';
+ ++OutCol;
+ } while ((OutCol % TabStop) != 0);
+ }
+ S << '\n';
+}
+
+static bool isNonASCII(char c) {
+ return c & 0x80;
+}
void SMDiagnostic::print(const char *ProgName, raw_ostream &S,
bool ShowColors) const {
@@ -297,43 +396,48 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S,
if (LineNo == -1 || ColumnNo == -1)
return;
+ // FIXME: If there are multibyte or multi-column characters in the source, all
+ // our ranges will be wrong. To do this properly, we'll need a byte-to-column
+ // map like Clang's TextDiagnostic. For now, we'll just handle tabs by
+ // expanding them later, and bail out rather than show incorrect ranges and
+ // misaligned fixits for any other odd characters.
+ if (std::find_if(LineContents.begin(), LineContents.end(), isNonASCII) !=
+ LineContents.end()) {
+ printSourceLine(S, LineContents);
+ return;
+ }
+ size_t NumColumns = LineContents.size();
+
// Build the line with the caret and ranges.
- std::string CaretLine(LineContents.size()+1, ' ');
+ std::string CaretLine(NumColumns+1, ' ');
// Expand any ranges.
for (unsigned r = 0, e = Ranges.size(); r != e; ++r) {
std::pair<unsigned, unsigned> R = Ranges[r];
- for (unsigned i = R.first,
- e = std::min(R.second, (unsigned)LineContents.size())+1; i != e; ++i)
- CaretLine[i] = '~';
+ std::fill(&CaretLine[R.first],
+ &CaretLine[std::min((size_t)R.second, CaretLine.size())],
+ '~');
}
-
+
+ // Add any fix-its.
+ // FIXME: Find the beginning of the line properly for multibyte characters.
+ std::string FixItInsertionLine;
+ buildFixItLine(CaretLine, FixItInsertionLine, FixIts,
+ makeArrayRef(Loc.getPointer() - ColumnNo,
+ LineContents.size()));
+
// Finally, plop on the caret.
- if (unsigned(ColumnNo) <= LineContents.size())
+ if (unsigned(ColumnNo) <= NumColumns)
CaretLine[ColumnNo] = '^';
else
- CaretLine[LineContents.size()] = '^';
+ CaretLine[NumColumns] = '^';
// ... and remove trailing whitespace so the output doesn't wrap for it. We
// know that the line isn't completely empty because it has the caret in it at
// least.
CaretLine.erase(CaretLine.find_last_not_of(' ')+1);
- // Print out the source line one character at a time, so we can expand tabs.
- for (unsigned i = 0, e = LineContents.size(), OutCol = 0; i != e; ++i) {
- if (LineContents[i] != '\t') {
- S << LineContents[i];
- ++OutCol;
- continue;
- }
-
- // If we have a tab, emit at least one space, then round up to 8 columns.
- do {
- S << ' ';
- ++OutCol;
- } while (OutCol & 7);
- }
- S << '\n';
+ printSourceLine(S, LineContents);
if (ShowColors)
S.changeColor(raw_ostream::GREEN, true);
@@ -350,11 +454,36 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S,
do {
S << CaretLine[i];
++OutCol;
- } while (OutCol & 7);
+ } while ((OutCol % TabStop) != 0);
}
+ S << '\n';
if (ShowColors)
S.resetColor();
+
+ // Print out the replacement line, matching tabs in the source line.
+ if (FixItInsertionLine.empty())
+ return;
+ for (size_t i = 0, e = FixItInsertionLine.size(), OutCol = 0; i != e; ++i) {
+ if (i >= LineContents.size() || LineContents[i] != '\t') {
+ S << FixItInsertionLine[i];
+ ++OutCol;
+ continue;
+ }
+
+ // Okay, we have a tab. Insert the appropriate number of characters.
+ do {
+ S << FixItInsertionLine[i];
+ // FIXME: This is trying not to break up replacements, but then to re-sync
+ // with the tabs between replacements. This will fail, though, if two
+ // fix-it replacements are exactly adjacent, or if a fix-it contains a
+ // space. Really we should be precomputing column widths, which we'll
+ // need anyway for multibyte chars.
+ if (FixItInsertionLine[i] != ' ')
+ ++i;
+ ++OutCol;
+ } while (((OutCol % TabStop) != 0) && i != e);
+ }
S << '\n';
}
diff --git a/lib/Support/Unix/Memory.inc b/lib/Support/Unix/Memory.inc
index f4cfbc65cf..8a766f041e 100644
--- a/lib/Support/Unix/Memory.inc
+++ b/lib/Support/Unix/Memory.inc
@@ -12,11 +12,9 @@
//===----------------------------------------------------------------------===//
#include "Unix.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Process.h"
-#include "llvm/Support/Debug.h"
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
@@ -75,7 +73,7 @@ Memory::allocateMappedMemory(size_t NumBytes,
if (NumBytes == 0)
return MemoryBlock();
- static const size_t PageSize = Process::GetPageSize();
+ static const size_t PageSize = process::get_self()->page_size();
const size_t NumPages = (NumBytes+PageSize-1)/PageSize;
int fd = -1;
@@ -172,8 +170,8 @@ Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock,
std::string *ErrMsg) {
if (NumBytes == 0) return MemoryBlock();
- size_t pageSize = Process::GetPageSize();
- size_t NumPages = (NumBytes+pageSize-1)/pageSize;
+ size_t PageSize = process::get_self()->page_size();
+ size_t NumPages = (NumBytes+PageSize-1)/PageSize;
int fd = -1;
#ifdef NEED_DEV_ZERO_FOR_MMAP
@@ -197,13 +195,11 @@ Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock,
NearBlock->size() : 0;
#if defined(__APPLE__) && defined(__arm__)
- void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_EXEC,
+ void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_EXEC,
flags, fd, 0);
#else
-dbgs() << "calling mmap, start " << start << "\n";
- void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
+ void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
flags, fd, 0);
- DEBUG(dbgs() << "mmap returned " << pa<<"\n");
#endif
if (pa == MAP_FAILED) {
if (NearBlock) //Try again without a near hint
@@ -215,7 +211,7 @@ dbgs() << "calling mmap, start " << start << "\n";
#if defined(__APPLE__) && defined(__arm__)
kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)pa,
- (vm_size_t)(pageSize*NumPages), 0,
+ (vm_size_t)(PageSize*NumPages), 0,
VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY);
if (KERN_SUCCESS != kr) {
MakeErrMsg(ErrMsg, "vm_protect max RX failed");
@@ -223,7 +219,7 @@ dbgs() << "calling mmap, start " << start << "\n";
}
kr = vm_protect(mach_task_self(), (vm_address_t)pa,
- (vm_size_t)(pageSize*NumPages), 0,
+ (vm_size_t)(PageSize*NumPages), 0,
VM_PROT_READ | VM_PROT_WRITE);
if (KERN_SUCCESS != kr) {
MakeErrMsg(ErrMsg, "vm_protect RW failed");
@@ -233,7 +229,7 @@ dbgs() << "calling mmap, start " << start << "\n";
MemoryBlock result;
result.Address = pa;
- result.Size = NumPages*pageSize;
+ result.Size = NumPages*PageSize;
return result;
}
diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc
index 820041bccc..b5b76867ec 100644
--- a/lib/Support/Unix/PathV2.inc
+++ b/lib/Support/Unix/PathV2.inc
@@ -450,11 +450,12 @@ retry_random_path:
rety_open_create:
int RandomFD = ::open(RandomPath.c_str(), O_RDWR | O_CREAT | O_EXCL, mode);
if (RandomFD == -1) {
+ int SavedErrno = errno;
// If the file existed, try again, otherwise, error.
- if (errno == errc::file_exists)
+ if (SavedErrno == errc::file_exists)
goto retry_random_path;
// If path prefix doesn't exist, try to create it.
- if (errno == errc::no_such_file_or_directory &&
+ if (SavedErrno == errc::no_such_file_or_directory &&
!exists(path::parent_path(RandomPath))) {
StringRef p(RandomPath);
SmallString<64> dir_to_create;
@@ -469,13 +470,15 @@ rety_open_create:
(*i)[1] == '/' &&
(*i)[2] != '/')
return make_error_code(errc::no_such_file_or_directory);
- if (::mkdir(dir_to_create.c_str(), 0700) == -1)
+ if (::mkdir(dir_to_create.c_str(), 0700) == -1 &&
+ errno != errc::file_exists)
return error_code(errno, system_category());
}
}
goto rety_open_create;
}
- return error_code(errno, system_category());
+
+ return error_code(SavedErrno, system_category());
}
// Make the path absolute.
@@ -616,7 +619,7 @@ const char *mapped_file_region::const_data() const {
}
int mapped_file_region::alignment() {
- return Process::GetPageSize();
+ return process::get_self()->page_size();
}
error_code detail::directory_iterator_construct(detail::DirIterState &it,
diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc
index b2983b21f7..c246634321 100644
--- a/lib/Support/Unix/Process.inc
+++ b/lib/Support/Unix/Process.inc
@@ -46,9 +46,49 @@
using namespace llvm;
using namespace sys;
-unsigned
-Process::GetPageSize()
-{
+
+process::id_type self_process::get_id() {
+ return getpid();
+}
+
+static std::pair<TimeValue, TimeValue> getRUsageTimes() {
+#if defined(HAVE_GETRUSAGE)
+ struct rusage RU;
+ ::getrusage(RUSAGE_SELF, &RU);
+ return std::make_pair(
+ TimeValue(
+ static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
+ static_cast<TimeValue::NanoSecondsType>(
+ RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
+ TimeValue(
+ static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
+ static_cast<TimeValue::NanoSecondsType>(
+ RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
+#else
+#warning Cannot get usage times on this platform
+ return std::make_pair(TimeValue(), TimeValue());
+#endif
+}
+
+TimeValue self_process::get_user_time() const {
+#if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
+ // Try to get a high resolution CPU timer.
+ struct timespec TS;
+ if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
+ return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
+ static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
+#endif
+
+ // Otherwise fall back to rusage based timing.
+ return getRUsageTimes().first;
+}
+
+TimeValue self_process::get_system_time() const {
+ // We can only collect system time by inspecting the results of getrusage.
+ return getRUsageTimes().second;
+}
+
+static unsigned getPageSize() {
#if defined(__CYGWIN__)
// On Cygwin, getpagesize() returns 64k but the page size for the purposes of
// memory protection and mmap() is 4k.
@@ -65,6 +105,12 @@ Process::GetPageSize()