Index: include/llvm/Support/Chrono.h =================================================================== --- /dev/null +++ include/llvm/Support/Chrono.h @@ -0,0 +1,47 @@ +//===- llvm/Support/Chrono.h - Utilities for Timing Manipulation-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CHRONO_H +#define LLVM_SUPPORT_CHRONO_H + +#include +#include + +namespace llvm { + +class raw_ostream; + +namespace sys { + +/// A time point on the system clock. The only way this differs from +/// std::chrono::system_clock::time_point is that we explicitly specify the +/// duration to be nanoseconds (default duration of system_clock is +/// implementation-defined). +using TimePoint = std::chrono::time_point; + +/// Convert a TimePoint to std::time_t +inline std::time_t toTimeT(TimePoint TP) { + using namespace std::chrono; + return system_clock::to_time_t( + time_point_cast(TP)); +} + +/// Convert a std::time_t to a TimePoint +inline TimePoint toTimePoint(std::time_t T) { + return std::chrono::system_clock::from_time_t(T); +} + +} // namespace sys + +raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint TP); + +} // namespace llvm + +#endif // LLVM_SUPPORT_CHRONO_H Index: include/llvm/Support/TimeValue.h =================================================================== --- include/llvm/Support/TimeValue.h +++ include/llvm/Support/TimeValue.h @@ -14,6 +14,7 @@ #ifndef LLVM_SUPPORT_TIMEVALUE_H #define LLVM_SUPPORT_TIMEVALUE_H +#include "llvm/Support/Chrono.h" #include "llvm/Support/DataTypes.h" #include @@ -112,6 +113,10 @@ this->normalize(); } + TimeValue(TimePoint TP) + : seconds_(sys::toTimeT(TP) + PosixZeroTimeSeconds), + nanos_((TP.time_since_epoch() % std::chrono::seconds(1)).count()) {} + /// This is a static constructor that returns a TimeValue that represents /// the current time. /// @brief Creates a TimeValue with the current time (UTC). @@ -121,6 +126,11 @@ /// @name Operators /// @{ public: + operator TimePoint() const { + return toTimePoint(seconds_ - PosixZeroTimeSeconds) + + std::chrono::nanoseconds(nanos_); + } + /// Add \p that to \p this. /// @returns this /// @brief Incrementing assignment operator. Index: lib/Support/CMakeLists.txt =================================================================== --- lib/Support/CMakeLists.txt +++ lib/Support/CMakeLists.txt @@ -37,6 +37,7 @@ BranchProbability.cpp CachePruning.cpp circular_raw_ostream.cpp + Chrono.cpp COM.cpp CommandLine.cpp Compression.cpp Index: lib/Support/Chrono.cpp =================================================================== --- /dev/null +++ lib/Support/Chrono.cpp @@ -0,0 +1,20 @@ +//===- lib/Chrono.h --- Utilities for Timing Manipulation -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Chrono.h" +#include "llvm/Config/config.h" +#include "llvm/Support/raw_ostream.h" + +/// Include the platform-specific portion +#ifdef LLVM_ON_UNIX +#include "Unix/Chrono.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/Chrono.inc" +#endif Index: lib/Support/TimeValue.cpp =================================================================== --- lib/Support/TimeValue.cpp +++ lib/Support/TimeValue.cpp @@ -12,7 +12,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/TimeValue.h" -#include "llvm/Config/config.h" +#include "llvm/Support/Chrono.h" +#include "llvm/Support/ScopedPrinter.h" namespace llvm { @@ -45,12 +46,10 @@ } } -} // namespace llvm +std::string TimeValue::str() const { return to_string(TimePoint(*this)); } + +TimeValue TimeValue::now() { + return TimePoint(std::chrono::system_clock::now()); +} -/// Include the platform-specific portion of TimeValue class -#ifdef LLVM_ON_UNIX -#include "Unix/TimeValue.inc" -#endif -#ifdef LLVM_ON_WIN32 -#include "Windows/TimeValue.inc" -#endif +} // namespace llvm Index: lib/Support/Unix/Chrono.inc =================================================================== --- /dev/null +++ lib/Support/Unix/Chrono.inc @@ -0,0 +1,34 @@ +//===- Unix/Chrono.inc - Utilities for Timing Manipulation-------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Format.h" + +namespace llvm { + +using namespace sys; + +raw_ostream &operator<<(raw_ostream &OS, TimePoint TP) { + std::time_t OurTime = toTimeT(TP); + struct tm Storage; + struct tm *LT = ::localtime_r(&OurTime, &Storage); + assert(LT); + char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")]; + strftime(Buffer, sizeof(Buffer), "%Y-%m-%d %H:%M:%S", LT); + return OS << Buffer << '.' + << format("%.9lu", + long((TP.time_since_epoch() % std::chrono::seconds(1)) + .count())); +} + +} // namespace llvm Index: lib/Support/Unix/TimeValue.inc =================================================================== --- lib/Support/Unix/TimeValue.inc +++ /dev/null @@ -1,54 +0,0 @@ -//===- Unix/TimeValue.cpp - Unix TimeValue Implementation -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the Unix specific portion of the TimeValue class. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -//=== WARNING: Implementation here must contain only generic UNIX code that -//=== is guaranteed to work on *all* UNIX variants. -//===----------------------------------------------------------------------===// - -#include "Unix.h" - -namespace llvm { - using namespace sys; - -std::string TimeValue::str() const { - time_t OurTime = time_t(this->toEpochTime()); - struct tm Storage; - struct tm *LT = ::localtime_r(&OurTime, &Storage); - assert(LT); - char Buffer1[sizeof("YYYY-MM-DD HH:MM:SS")]; - strftime(Buffer1, sizeof(Buffer1), "%Y-%m-%d %H:%M:%S", LT); - char Buffer2[sizeof("YYYY-MM-DD HH:MM:SS.MMMUUUNNN")]; - snprintf(Buffer2, sizeof(Buffer2), "%s.%.9u", Buffer1, this->nanoseconds()); - return std::string(Buffer2); -} - -TimeValue TimeValue::now() { - struct timeval the_time; - timerclear(&the_time); - if (0 != ::gettimeofday(&the_time,nullptr)) { - // This is *really* unlikely to occur because the only gettimeofday - // errors concern the timezone parameter which we're passing in as 0. - // In the unlikely case it does happen, just return MinTime, no error - // message needed. - return MinTime(); - } - - return TimeValue( - static_cast( the_time.tv_sec + - PosixZeroTimeSeconds ), - static_cast( the_time.tv_usec * - NANOSECONDS_PER_MICROSECOND ) ); -} - -} Index: lib/Support/Windows/Chrono.inc =================================================================== --- /dev/null +++ lib/Support/Windows/Chrono.inc @@ -0,0 +1,40 @@ +//===- Windows/Chrono.inc - Utilities for Timing Manipulation ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code. +//===----------------------------------------------------------------------===// + +#include "WindowsSupport.h" +#include "llvm/Support/Format.h" +#include +#include + +namespace llvm { + +using namespace sys; + +raw_ostream &operator<<(raw_ostream &OS, TimePoint TP) { + struct tm *LT; + struct tm Storage; + __time64_t OurTime = toTimeT(TP); + int Error = ::_localtime64_s(&Storage, &OurTime); + assert(!Error); + (void)Error; + LT = &Storage; + + char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")]; + strftime(Buffer, sizeof(Buffer), "%Y-%m-%d %H:%M:%S", LT); + return OS << Buffer << '.' + << format("%.9lu", + long((TP.time_since_epoch() % std::chrono::seconds(1)) + .count())); +} + +} // namespace llvm Index: lib/Support/Windows/TimeValue.inc =================================================================== --- lib/Support/Windows/TimeValue.inc +++ /dev/null @@ -1,61 +0,0 @@ -//===- Win32/TimeValue.cpp - Win32 TimeValue Implementation -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides the Win32 implementation of the TimeValue class. -// -//===----------------------------------------------------------------------===// - -#include "WindowsSupport.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include -#include - -using namespace llvm; -using namespace llvm::sys; - -//===----------------------------------------------------------------------===// -//=== WARNING: Implementation here must contain only Win32 specific code. -//===----------------------------------------------------------------------===// - -TimeValue TimeValue::now() { - uint64_t ft; - GetSystemTimeAsFileTime(reinterpret_cast(&ft)); - - TimeValue t(0, 0); - t.fromWin32Time(ft); - return t; -} - -std::string TimeValue::str() const { - std::string S; - struct tm *LT; -#ifdef __MINGW32__ - // Old versions of mingw don't have _localtime64_s. Remove this once we drop support - // for them. - time_t OurTime = time_t(this->toEpochTime()); - LT = ::localtime(&OurTime); - assert(LT); -#else - struct tm Storage; - __time64_t OurTime = this->toEpochTime(); - int Error = ::_localtime64_s(&Storage, &OurTime); - assert(!Error); - (void)Error; - LT = &Storage; -#endif - - char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")]; - strftime(Buffer, sizeof(Buffer), "%Y-%m-%d %H:%M:%S", LT); - raw_string_ostream OS(S); - OS << format("%s.%.9u", static_cast(Buffer), - this->nanoseconds()); - OS.flush(); - return S; -} Index: unittests/Support/CMakeLists.txt =================================================================== --- unittests/Support/CMakeLists.txt +++ unittests/Support/CMakeLists.txt @@ -9,6 +9,7 @@ BlockFrequencyTest.cpp BranchProbabilityTest.cpp Casting.cpp + Chrono.cpp CommandLineTest.cpp CompressionTest.cpp ConvertUTFTest.cpp Index: unittests/Support/Chrono.cpp =================================================================== --- /dev/null +++ unittests/Support/Chrono.cpp @@ -0,0 +1,62 @@ +//===- llvm/unittest/Support/Chrono.cpp - Time utilities tests ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Chrono.h" +#include "llvm/ADT/SmallVector.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::sys; +using namespace std::chrono; + +namespace { + +TEST(Chrono, TimeTConversion) { + EXPECT_EQ(time_t(0), toTimeT(toTimePoint(time_t(0)))); + EXPECT_EQ(time_t(1), toTimeT(toTimePoint(time_t(1)))); + EXPECT_EQ(time_t(47), toTimeT(toTimePoint(time_t(47)))); + + TimePoint TP; + EXPECT_EQ(TP, toTimePoint(toTimeT(TP))); + TP += seconds(1); + EXPECT_EQ(TP, toTimePoint(toTimeT(TP))); + TP += hours(47); + EXPECT_EQ(TP, toTimePoint(toTimeT(TP))); +} + +TEST(Chrono, StringConversion) { + std::string S; + raw_string_ostream OS(S); + OS << system_clock::now(); + + // Do a basic sanity check on the output. + // The format we expect is YYYY-MM-DD HH:MM:SS.MMMUUUNNN + StringRef Date, Time; + std::tie(Date, Time) = StringRef(OS.str()).split(' '); + + SmallVector Components; + Date.split(Components, '-'); + ASSERT_EQ(3u, Components.size()); + EXPECT_EQ(4u, Components[0].size()); + EXPECT_EQ(2u, Components[1].size()); + EXPECT_EQ(2u, Components[2].size()); + + StringRef Sec, Nano; + std::tie(Sec, Nano) = Time.split('.'); + + Components.clear(); + Sec.split(Components, ':'); + ASSERT_EQ(3u, Components.size()); + EXPECT_EQ(2u, Components[0].size()); + EXPECT_EQ(2u, Components[1].size()); + EXPECT_EQ(2u, Components[2].size()); + EXPECT_EQ(9u, Nano.size()); +} + +} // anonymous namespace Index: unittests/Support/TimeValueTest.cpp =================================================================== --- unittests/Support/TimeValueTest.cpp +++ unittests/Support/TimeValueTest.cpp @@ -37,4 +37,14 @@ EXPECT_EQ(ft1970, epoch.toWin32Time()); } +TEST(TimeValue, Chrono) { + sys::TimeValue TV; + TV.fromEpochTime(0); + sys::TimePoint TP = TV; + EXPECT_EQ(0u, sys::toTimeT(TP)); + + TP += std::chrono::seconds(47); + TV = TP; + EXPECT_EQ(47u, TV.toEpochTime()); +} }