Index: llvm/trunk/include/llvm/Object/Archive.h =================================================================== --- llvm/trunk/include/llvm/Object/Archive.h +++ llvm/trunk/include/llvm/Object/Archive.h @@ -18,10 +18,11 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Object/Binary.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/TimeValue.h" namespace llvm { namespace object { Index: llvm/trunk/include/llvm/Support/CachePruning.h =================================================================== --- llvm/trunk/include/llvm/Support/CachePruning.h +++ llvm/trunk/include/llvm/Support/CachePruning.h @@ -16,6 +16,7 @@ #define LLVM_SUPPORT_CACHE_PRUNING_H #include "llvm/ADT/StringRef.h" +#include namespace llvm { @@ -29,7 +30,7 @@ /// Define the pruning interval. This is intended to be used to avoid scanning /// the directory too often. It does not impact the decision of which file to /// prune. A value of 0 forces the scan to occurs. - CachePruning &setPruningInterval(int PruningInterval) { + CachePruning &setPruningInterval(std::chrono::seconds PruningInterval) { Interval = PruningInterval; return *this; } @@ -37,7 +38,7 @@ /// Define the expiration for a file. When a file hasn't been accessed for /// \p ExpireAfter seconds, it is removed from the cache. A value of 0 disable /// the expiration-based pruning. - CachePruning &setEntryExpiration(unsigned ExpireAfter) { + CachePruning &setEntryExpiration(std::chrono::seconds ExpireAfter) { Expiration = ExpireAfter; return *this; } @@ -59,11 +60,11 @@ private: // Options that matches the setters above. std::string Path; - unsigned Expiration = 0; - unsigned Interval = 0; + std::chrono::seconds Expiration; + std::chrono::seconds Interval; unsigned PercentageOfAvailableSpace = 0; }; } // namespace llvm -#endif \ No newline at end of file +#endif Index: llvm/trunk/include/llvm/Support/FileSystem.h =================================================================== --- llvm/trunk/include/llvm/Support/FileSystem.h +++ llvm/trunk/include/llvm/Support/FileSystem.h @@ -31,10 +31,10 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Chrono.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" -#include "llvm/Support/TimeValue.h" #include #include #include @@ -209,8 +209,8 @@ // getters file_type type() const { return Type; } perms permissions() const { return Perms; } - TimeValue getLastAccessedTime() const; - TimeValue getLastModificationTime() const; + TimePoint<> getLastAccessedTime() const; + TimePoint<> getLastModificationTime() const; UniqueID getUniqueID() const; #if defined(LLVM_ON_UNIX) @@ -540,7 +540,7 @@ /// @returns errc::success if the file times were successfully set, otherwise a /// platform-specific error_code or errc::function_not_supported on /// platforms where the functionality isn't available. -std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time); +std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time); /// @brief Is status available? /// Index: llvm/trunk/include/llvm/Support/Process.h =================================================================== --- llvm/trunk/include/llvm/Support/Process.h +++ llvm/trunk/include/llvm/Support/Process.h @@ -28,8 +28,8 @@ #include "llvm/ADT/Optional.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Chrono.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/TimeValue.h" #include namespace llvm { @@ -55,13 +55,14 @@ /// This static function will set \p user_time to the amount of CPU time /// spent in user (non-kernel) mode and \p sys_time to the amount of CPU /// time spent in system (kernel) mode. If the operating system does not - /// support collection of these metrics, a zero TimeValue will be for both + /// support collection of these metrics, a zero duration will be for both /// values. - /// \param elapsed Returns the TimeValue::now() giving current time + /// \param elapsed Returns the system_clock::now() giving current time /// \param user_time Returns the current amount of user time for the process /// \param sys_time Returns the current amount of system time for the process - static void GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, - TimeValue &sys_time); + static void GetTimeUsage(TimePoint<> &elapsed, + std::chrono::nanoseconds &user_time, + std::chrono::nanoseconds &sys_time); /// This function makes the necessary calls to the operating system to /// prevent core files or any other kind of large memory dumps that can Index: llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp =================================================================== --- llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp +++ llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp @@ -836,8 +836,8 @@ } CachePruning(CacheOptions.Path) - .setPruningInterval(CacheOptions.PruningInterval) - .setEntryExpiration(CacheOptions.Expiration) + .setPruningInterval(std::chrono::seconds(CacheOptions.PruningInterval)) + .setEntryExpiration(std::chrono::seconds(CacheOptions.Expiration)) .setMaxSize(CacheOptions.MaxPercentageOfAvailableSpace) .prune(); Index: llvm/trunk/lib/Support/CachePruning.cpp =================================================================== --- llvm/trunk/lib/Support/CachePruning.cpp +++ llvm/trunk/lib/Support/CachePruning.cpp @@ -35,6 +35,8 @@ /// Prune the cache of files that haven't been accessed in a long time. bool CachePruning::prune() { + using namespace std::chrono; + if (Path.empty()) return false; @@ -45,7 +47,7 @@ if (!isPathDir) return false; - if (Expiration == 0 && PercentageOfAvailableSpace == 0) { + if (Expiration == seconds(0) && PercentageOfAvailableSpace == 0) { DEBUG(dbgs() << "No pruning settings set, exit early\n"); // Nothing will be pruned, early exit return false; @@ -55,7 +57,7 @@ SmallString<128> TimestampFile(Path); sys::path::append(TimestampFile, "llvmcache.timestamp"); sys::fs::file_status FileStatus; - sys::TimeValue CurrentTime = sys::TimeValue::now(); + const auto CurrentTime = system_clock::now(); if (auto EC = sys::fs::status(TimestampFile, FileStatus)) { if (EC == errc::no_such_file_or_directory) { // If the timestamp file wasn't there, create one now. @@ -65,14 +67,14 @@ return false; } } else { - if (Interval) { + if (Interval == seconds(0)) { // Check whether the time stamp is older than our pruning interval. // If not, do nothing. - sys::TimeValue TimeStampModTime = FileStatus.getLastModificationTime(); - auto TimeInterval = sys::TimeValue(sys::TimeValue::SecondsType(Interval)); + const auto TimeStampModTime = FileStatus.getLastModificationTime(); auto TimeStampAge = CurrentTime - TimeStampModTime; - if (TimeStampAge <= TimeInterval) { - DEBUG(dbgs() << "Timestamp file too recent (" << TimeStampAge.seconds() + if (TimeStampAge <= Interval) { + DEBUG(dbgs() << "Timestamp file too recent (" + << duration_cast(TimeStampAge).count() << "s old), do not prune.\n"); return false; } @@ -103,7 +105,6 @@ std::error_code EC; SmallString<128> CachePathNative; sys::path::native(Path, CachePathNative); - auto TimeExpiration = sys::TimeValue(sys::TimeValue::SecondsType(Expiration)); // Walk all of the files within this directory. for (sys::fs::directory_iterator File(CachePathNative, EC), FileEnd; File != FileEnd && !EC; File.increment(EC)) { @@ -119,11 +120,11 @@ } // If the file hasn't been used recently enough, delete it - sys::TimeValue FileAccessTime = FileStatus.getLastAccessedTime(); + const auto FileAccessTime = FileStatus.getLastAccessedTime(); auto FileAge = CurrentTime - FileAccessTime; - if (FileAge > TimeExpiration) { - DEBUG(dbgs() << "Remove " << File->path() << " (" << FileAge.seconds() - << "s old)\n"); + if (FileAge > Expiration) { + DEBUG(dbgs() << "Remove " << File->path() << " (" + << duration_cast(FileAge).count() << "s old)\n"); sys::fs::remove(File->path()); continue; } Index: llvm/trunk/lib/Support/Timer.cpp =================================================================== --- llvm/trunk/lib/Support/Timer.cpp +++ llvm/trunk/lib/Support/Timer.cpp @@ -116,8 +116,10 @@ } TimeRecord TimeRecord::getCurrentTime(bool Start) { + using Seconds = std::chrono::duration>; TimeRecord Result; - sys::TimeValue now(0,0), user(0,0), sys(0,0); + sys::TimePoint<> now; + std::chrono::nanoseconds user, sys; if (Start) { Result.MemUsed = getMemUsage(); @@ -127,9 +129,9 @@ Result.MemUsed = getMemUsage(); } - Result.WallTime = now.seconds() + now.microseconds() / 1000000.0; - Result.UserTime = user.seconds() + user.microseconds() / 1000000.0; - Result.SystemTime = sys.seconds() + sys.microseconds() / 1000000.0; + Result.WallTime = Seconds(now.time_since_epoch()).count(); + Result.UserTime = Seconds(user).count(); + Result.SystemTime = Seconds(sys).count(); return Result; } Index: llvm/trunk/lib/Support/Unix/Path.inc =================================================================== --- llvm/trunk/lib/Support/Unix/Path.inc +++ llvm/trunk/lib/Support/Unix/Path.inc @@ -198,16 +198,12 @@ return ""; } -TimeValue file_status::getLastAccessedTime() const { - TimeValue Ret; - Ret.fromEpochTime(fs_st_atime); - return Ret; +TimePoint<> file_status::getLastAccessedTime() const { + return toTimePoint(fs_st_atime); } -TimeValue file_status::getLastModificationTime() const { - TimeValue Ret; - Ret.fromEpochTime(fs_st_mtime); - return Ret; +TimePoint<> file_status::getLastModificationTime() const { + return toTimePoint(fs_st_mtime); } UniqueID file_status::getUniqueID() const { @@ -446,20 +442,16 @@ return fillStatus(StatRet, Status, Result); } -std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { +std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time) { #if defined(HAVE_FUTIMENS) timespec Times[2]; - Times[0].tv_sec = Time.toEpochTime(); - Times[0].tv_nsec = 0; - Times[1] = Times[0]; + Times[0] = Times[1] = sys::toTimeSpec(Time); if (::futimens(FD, Times)) return std::error_code(errno, std::generic_category()); return std::error_code(); #elif defined(HAVE_FUTIMES) timeval Times[2]; - Times[0].tv_sec = Time.toEpochTime(); - Times[0].tv_usec = 0; - Times[1] = Times[0]; + Times[0] = Times[1] = sys::toTimeVal(Time); if (::futimes(FD, Times)) return std::error_code(errno, std::generic_category()); return std::error_code(); Index: llvm/trunk/lib/Support/Unix/Process.inc =================================================================== --- llvm/trunk/lib/Support/Unix/Process.inc +++ llvm/trunk/lib/Support/Unix/Process.inc @@ -17,7 +17,6 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" -#include "llvm/Support/TimeValue.h" #if HAVE_FCNTL_H #include #endif @@ -60,22 +59,14 @@ using namespace llvm; using namespace sys; -static std::pair getRUsageTimes() { +static std::pair getRUsageTimes() { #if defined(HAVE_GETRUSAGE) struct rusage RU; ::getrusage(RUSAGE_SELF, &RU); - return std::make_pair( - TimeValue( - static_cast(RU.ru_utime.tv_sec), - static_cast( - RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)), - TimeValue( - static_cast(RU.ru_stime.tv_sec), - static_cast( - RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND))); + return { toDuration(RU.ru_utime), toDuration(RU.ru_stime) }; #else #warning Cannot get usage times on this platform - return std::make_pair(TimeValue(), TimeValue()); + return {}; #endif } @@ -121,9 +112,9 @@ #endif } -void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, - TimeValue &sys_time) { - elapsed = TimeValue::now(); +void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time, + std::chrono::nanoseconds &sys_time) { + elapsed = std::chrono::system_clock::now(); std::tie(user_time, sys_time) = getRUsageTimes(); } @@ -449,8 +440,8 @@ // Otherwise, swizzle the current time and the process ID to form a reasonable // seed. - TimeValue Now = TimeValue::now(); - return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid()); + const auto Now = std::chrono::high_resolution_clock::now(); + return hash_combine(Now.time_since_epoch().count(), ::getpid()); } #endif Index: llvm/trunk/lib/Support/Unix/Unix.h =================================================================== --- llvm/trunk/lib/Support/Unix/Unix.h +++ llvm/trunk/lib/Support/Unix/Unix.h @@ -19,7 +19,8 @@ //=== is guaranteed to work on all UNIX variants. //===----------------------------------------------------------------------===// -#include "llvm/Config/config.h" // Get autoconf configuration settings +#include "llvm/Config/config.h" // Get autoconf configuration settings +#include "llvm/Support/Chrono.h" #include "llvm/Support/Errno.h" #include #include @@ -69,4 +70,37 @@ return true; } +namespace llvm { +namespace sys { + +/// Convert a struct timeval to a duration. Note that timeval can be used both +/// as a time point and a duration. Be sure to check what the input represents. +inline std::chrono::microseconds toDuration(const struct timeval &TV) { + return std::chrono::seconds(TV.tv_sec) + + std::chrono::microseconds(TV.tv_usec); +} + +/// Convert a time point to struct timespec. +inline struct timespec toTimeSpec(TimePoint<> TP) { + using namespace std::chrono; + + struct timespec RetVal; + RetVal.tv_sec = toTimeT(TP); + RetVal.tv_nsec = (TP.time_since_epoch() % seconds(1)).count(); + return RetVal; +} + +/// Convert a time point to struct timeval. +inline struct timeval toTimeVal(TimePoint TP) { + using namespace std::chrono; + + struct timeval RetVal; + RetVal.tv_sec = toTimeT(TP); + RetVal.tv_usec = (TP.time_since_epoch() % seconds(1)).count(); + return RetVal; +} + +} // namespace sys +} // namespace llvm + #endif Index: llvm/trunk/lib/Support/Windows/Path.inc =================================================================== --- llvm/trunk/lib/Support/Windows/Path.inc +++ llvm/trunk/lib/Support/Windows/Path.inc @@ -164,24 +164,18 @@ return SpaceInfo; } -TimeValue file_status::getLastAccessedTime() const { - ULARGE_INTEGER UI; - UI.LowPart = LastAccessedTimeLow; - UI.HighPart = LastAccessedTimeHigh; - - TimeValue Ret; - Ret.fromWin32Time(UI.QuadPart); - return Ret; -} - -TimeValue file_status::getLastModificationTime() const { - ULARGE_INTEGER UI; - UI.LowPart = LastWriteTimeLow; - UI.HighPart = LastWriteTimeHigh; - - TimeValue Ret; - Ret.fromWin32Time(UI.QuadPart); - return Ret; +TimePoint<> file_status::getLastAccessedTime() const { + FILETIME Time; + Time.dwLowDateTime = LastAccessedTimeLow; + Time.dwHighDateTime = LastAccessedTimeHigh; + return toTimePoint(Time); +} + +TimePoint<> file_status::getLastModificationTime() const { + FILETIME Time; + Time.dwLowDateTime = LastWriteTimeLow; + Time.dwHighDateTime = LastWriteTimeHigh; + return toTimePoint(Time); } std::error_code current_path(SmallVectorImpl &result) { @@ -513,12 +507,8 @@ return getStatus(FileHandle, Result); } -std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { - ULARGE_INTEGER UI; - UI.QuadPart = Time.toWin32Time(); - FILETIME FT; - FT.dwLowDateTime = UI.LowPart; - FT.dwHighDateTime = UI.HighPart; +std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time) { + FILETIME FT = toFILETIME(Time); HANDLE FileHandle = reinterpret_cast(_get_osfhandle(FD)); if (!SetFileTime(FileHandle, NULL, &FT, &FT)) return mapWindowsError(::GetLastError()); Index: llvm/trunk/lib/Support/Windows/Process.inc =================================================================== --- llvm/trunk/lib/Support/Windows/Process.inc +++ llvm/trunk/lib/Support/Windows/Process.inc @@ -49,18 +49,6 @@ using namespace llvm; using namespace sys; -static TimeValue getTimeValueFromFILETIME(FILETIME Time) { - ULARGE_INTEGER TimeInteger; - TimeInteger.LowPart = Time.dwLowDateTime; - TimeInteger.HighPart = Time.dwHighDateTime; - - // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) - return TimeValue( - static_cast(TimeInteger.QuadPart / 10000000), - static_cast( - (TimeInteger.QuadPart % 10000000) * 100)); -} - // This function retrieves the page size using GetNativeSystemInfo() and is // present solely so it can be called once to initialize the self_process member // below. @@ -93,17 +81,17 @@ return size; } -void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, - TimeValue &sys_time) { - elapsed = TimeValue::now(); +void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time, + std::chrono::nanoseconds &sys_time) { + elapsed = std::chrono::system_clock::now();; FILETIME ProcCreate, ProcExit, KernelTime, UserTime; if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, &UserTime) == 0) return; - user_time = getTimeValueFromFILETIME(UserTime); - sys_time = getTimeValueFromFILETIME(KernelTime); + user_time = toDuration(UserTime); + sys_time = toDuration(KernelTime); } // Some LLVM programs such as bugpoint produce core files as a normal part of Index: llvm/trunk/lib/Support/Windows/WindowsSupport.h =================================================================== --- llvm/trunk/lib/Support/Windows/WindowsSupport.h +++ llvm/trunk/lib/Support/Windows/WindowsSupport.h @@ -39,12 +39,13 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" // Get build system configuration settings +#include "llvm/Support/Chrono.h" #include "llvm/Support/Compiler.h" -#include -#include -#include #include #include +#include +#include +#include /// Determines if the program is running on Windows 8 or newer. This /// reimplements one of the helpers in the Windows 8.1 SDK, which are intended @@ -211,6 +212,39 @@ } namespace sys { + +inline std::chrono::nanoseconds toDuration(FILETIME Time) { + ULARGE_INTEGER TimeInteger; + TimeInteger.LowPart = Time.dwLowDateTime; + TimeInteger.HighPart = Time.dwHighDateTime; + + // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) + return std::chrono::nanoseconds(100 * TimeInteger.QuadPart); +} + +inline TimePoint<> toTimePoint(FILETIME Time) { + ULARGE_INTEGER TimeInteger; + TimeInteger.LowPart = Time.dwLowDateTime; + TimeInteger.HighPart = Time.dwHighDateTime; + + // Adjust for different epoch + TimeInteger.QuadPart -= 11644473600ll * 10000000; + + // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) + return TimePoint<>(std::chrono::nanoseconds(100 * TimeInteger.QuadPart)); +} + +inline FILETIME toFILETIME(TimePoint<> TP) { + ULARGE_INTEGER TimeInteger; + TimeInteger.QuadPart = TP.time_since_epoch().count() / 100; + TimeInteger.QuadPart += 11644473600ll * 10000000; + + FILETIME Time; + Time.dwLowDateTime = TimeInteger.LowPart; + Time.dwHighDateTime = TimeInteger.HighPart; + return Time; +} + namespace path { std::error_code widenPath(const Twine &Path8, SmallVectorImpl &Path16); Index: llvm/trunk/tools/llvm-ar/llvm-ar.cpp =================================================================== --- llvm/trunk/tools/llvm-ar/llvm-ar.cpp +++ llvm/trunk/tools/llvm-ar/llvm-ar.cpp @@ -21,6 +21,7 @@ #include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Chrono.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" @@ -353,9 +354,9 @@ Expected Size = C.getSize(); failIfError(Size.takeError()); outs() << ' ' << format("%6llu", Size.get()); - Expected ModTimeOrErr = C.getLastModified(); + auto ModTimeOrErr = C.getLastModified(); failIfError(ModTimeOrErr.takeError()); - outs() << ' ' << ModTimeOrErr.get().str(); + outs() << ' ' << ModTimeOrErr.get(); outs() << ' '; } outs() << Name << "\n"; @@ -387,7 +388,7 @@ // If we're supposed to retain the original modification times, etc. do so // now. if (OriginalDates) { - Expected ModTimeOrErr = C.getLastModified(); + auto ModTimeOrErr = C.getLastModified(); failIfError(ModTimeOrErr.takeError()); failIfError( sys::fs::setLastModificationAndAccessTime(FD, ModTimeOrErr.get())); @@ -525,9 +526,9 @@ // operation. sys::fs::file_status Status; failIfError(sys::fs::status(*MI, Status), *MI); - Expected ModTimeOrErr = Member.getLastModified(); + auto ModTimeOrErr = Member.getLastModified(); failIfError(ModTimeOrErr.takeError()); - if (Status.getLastModificationTime() < ModTimeOrErr.get()) { + if (sys::TimeValue(Status.getLastModificationTime()) < ModTimeOrErr.get()) { if (PosName.empty()) return IA_AddOldMember; return IA_MoveOldMember; Index: llvm/trunk/tools/llvm-cov/CodeCoverage.cpp =================================================================== --- llvm/trunk/tools/llvm-cov/CodeCoverage.cpp +++ llvm/trunk/tools/llvm-cov/CodeCoverage.cpp @@ -30,6 +30,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" +#include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/ThreadPool.h" #include "llvm/Support/ToolOutputFile.h" #include @@ -734,7 +735,7 @@ } auto ModifiedTime = Status.getLastModificationTime(); - std::string ModifiedTimeStr = ModifiedTime.str(); + std::string ModifiedTimeStr = to_string(ModifiedTime); size_t found = ModifiedTimeStr.rfind(":"); ViewOpts.CreatedTimeStr = (found != std::string::npos) ? "Created: " + ModifiedTimeStr.substr(0, found)