diff options
Diffstat (limited to 'lib/Support')
-rw-r--r-- | lib/Support/APFloat.cpp | 9 | ||||
-rw-r--r-- | lib/Support/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Support/ConstantRange.cpp | 2 | ||||
-rw-r--r-- | lib/Support/Dwarf.cpp | 4 | ||||
-rw-r--r-- | lib/Support/DynamicLibrary.cpp | 2 | ||||
-rw-r--r-- | lib/Support/FoldingSet.cpp | 4 | ||||
-rw-r--r-- | lib/Support/Host.cpp | 58 | ||||
-rw-r--r-- | lib/Support/LockFileManager.cpp | 16 | ||||
-rw-r--r-- | lib/Support/MemoryBuffer.cpp | 4 | ||||
-rw-r--r-- | lib/Support/Path.cpp | 1 | ||||
-rw-r--r-- | lib/Support/Process.cpp | 60 | ||||
-rw-r--r-- | lib/Support/SourceMgr.cpp | 193 | ||||
-rw-r--r-- | lib/Support/Unix/Memory.inc | 20 | ||||
-rw-r--r-- | lib/Support/Unix/PathV2.inc | 13 | ||||
-rw-r--r-- | lib/Support/Unix/Process.inc | 102 | ||||
-rw-r--r-- | lib/Support/Unix/Program.inc | 23 | ||||
-rw-r--r-- | lib/Support/Unix/Signals.inc | 26 | ||||
-rw-r--r-- | lib/Support/Windows/Process.inc | 81 | ||||
-rw-r--r-- | lib/Support/Windows/Program.inc | 22 | ||||
-rw-r--r-- | lib/Support/Windows/Signals.inc | 4 | ||||
-rw-r--r-- | lib/Support/YAMLTraits.cpp | 827 |
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() |