Skip to content

Commit

Permalink
Remove CHECK macros from tsl/platform/default/logging.h
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 705605141
  • Loading branch information
thcmbs authored and Google-ML-Automation committed Jan 10, 2025
1 parent 092b8dd commit d811f58
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 319 deletions.
2 changes: 2 additions & 0 deletions xla/tsl/platform/default/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ cc_library(
"//xla/tsl/platform:types",
"@com_google_absl//absl/base",
"@com_google_absl//absl/base:log_severity",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/strings",
"@tsl//tsl/platform",
"@tsl//tsl/platform:mutex",
Expand Down
51 changes: 0 additions & 51 deletions xla/tsl/platform/default/logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -384,57 +384,6 @@ void LogString(const char* fname, int line, absl::LogSeverity severity,
LogMessage(fname, line, severity) << message;
}

template <>
void MakeCheckOpValueString(std::ostream* os, const char& v) {
if (v >= 32 && v <= 126) {
(*os) << "'" << v << "'";
} else {
(*os) << "char value " << static_cast<int16>(v);
}
}

template <>
void MakeCheckOpValueString(std::ostream* os, const signed char& v) {
if (v >= 32 && v <= 126) {
(*os) << "'" << v << "'";
} else {
(*os) << "signed char value " << static_cast<int16>(v);
}
}

template <>
void MakeCheckOpValueString(std::ostream* os, const unsigned char& v) {
if (v >= 32 && v <= 126) {
(*os) << "'" << v << "'";
} else {
(*os) << "unsigned char value " << static_cast<uint16>(v);
}
}

#if LANG_CXX11
template <>
void MakeCheckOpValueString(std::ostream* os, const std::nullptr_t& v) {
(*os) << "nullptr";
}
#endif

CheckOpMessageBuilder::CheckOpMessageBuilder(const char* exprtext)
: stream_(new std::ostringstream) {
*stream_ << "Check failed: " << exprtext << " (";
}

CheckOpMessageBuilder::~CheckOpMessageBuilder() { delete stream_; }

std::ostream* CheckOpMessageBuilder::ForVar2() {
*stream_ << " vs. ";
return stream_;
}

string* CheckOpMessageBuilder::NewString() {
*stream_ << ")";
return new string(stream_->str());
}

namespace {
// The following code behaves like AtomicStatsCounter::LossyAdd() for
// speed since it is fine to lose occasional updates.
Expand Down
269 changes: 1 addition & 268 deletions xla/tsl/platform/default/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ limitations under the License.
#include <vector>

#include "absl/base/log_severity.h"
#include "absl/log/check.h" // IWYU pragma: export
#include "absl/strings/string_view.h"
#include "xla/tsl/platform/macros.h"
#include "xla/tsl/platform/types.h"
Expand All @@ -51,32 +52,6 @@ limitations under the License.
#undef LOG_EVERY_N_SEC
#undef VLOG

#undef CHECK
#undef CHECK_EQ
#undef CHECK_NE
#undef CHECK_LT
#undef CHECK_LE
#undef CHECK_GT
#undef CHECK_GE

#undef DCHECK
#undef DCHECK_EQ
#undef DCHECK_NE
#undef DCHECK_LT
#undef DCHECK_LE
#undef DCHECK_GT
#undef DCHECK_GE

#undef QCHECK
#undef QCHECK_EQ
#undef QCHECK_NE
#undef QCHECK_LT
#undef QCHECK_LE
#undef QCHECK_GT
#undef QCHECK_GE

#undef PCHECK

namespace tsl {

namespace internal {
Expand Down Expand Up @@ -297,252 +272,10 @@ class LogEveryNSecState {
LOGGING_INTERNAL_STATEFUL_CONDITION(EveryNSec, true, n_seconds) \
LOG(severity)

// CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode. Therefore, it is safe to do things like:
// CHECK(fp->Write(x) == 4)
#define CHECK(condition) \
if (TF_PREDICT_FALSE(!(condition))) \
LOG(FATAL) << "Check failed: " #condition " "

// Function is overloaded for integral types to allow static const
// integrals declared in classes and not defined to be used as arguments to
// CHECK* macros. It's not encouraged though.
template <typename T>
inline const T& GetReferenceableValue(const T& t) {
return t;
}
inline char GetReferenceableValue(char t) { return t; }
inline unsigned char GetReferenceableValue(unsigned char t) { return t; }
inline signed char GetReferenceableValue(signed char t) { return t; }
inline int16 GetReferenceableValue(int16_t t) { return t; }
inline uint16 GetReferenceableValue(uint16 t) { return t; }
inline int GetReferenceableValue(int t) { return t; }
inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
inline int64_t GetReferenceableValue(int64_t t) { return t; }
inline uint64 GetReferenceableValue(uint64 t) { return t; }

// This formats a value for a failing CHECK_XX statement. Ordinarily,
// it uses the definition for operator<<, with a few special cases below.
template <typename T>
inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
(*os) << v;
}

// Overrides for char types provide readable values for unprintable
// characters.
template <>
void MakeCheckOpValueString(std::ostream* os, const char& v);
template <>
void MakeCheckOpValueString(std::ostream* os, const signed char& v);
template <>
void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);

#if LANG_CXX11
// We need an explicit specialization for std::nullptr_t.
template <>
void MakeCheckOpValueString(std::ostream* os, const std::nullptr_t& v);
#endif

// A container for a string pointer which can be evaluated to a bool -
// true iff the pointer is non-NULL.
struct CheckOpString {
explicit CheckOpString(string* str) : str_(str) {}
// No destructor: if str_ is non-NULL, we're about to LOG(FATAL),
// so there's no point in cleaning up str_.
explicit operator bool() const { return TF_PREDICT_FALSE(str_ != nullptr); }
string* str_;
};

// Build the error message string. Specify no inlining for code size.
template <typename T1, typename T2>
string* MakeCheckOpString(const T1& v1, const T2& v2,
const char* exprtext) TF_ATTRIBUTE_NOINLINE;

// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
// statement. See MakeCheckOpString for sample usage. Other
// approaches were considered: use of a template method (e.g.,
// base::BuildCheckOpString(exprtext, base::Print<T1>, &v1,
// base::Print<T2>, &v2), however this approach has complications
// related to volatile arguments and function-pointer arguments).
class CheckOpMessageBuilder {
public:
// Inserts "exprtext" and " (" to the stream.
explicit CheckOpMessageBuilder(const char* exprtext);
// Deletes "stream_".
~CheckOpMessageBuilder();
// For inserting the first variable.
std::ostream* ForVar1() { return stream_; }
// For inserting the second variable (adds an intermediate " vs. ").
std::ostream* ForVar2();
// Get the result (inserts the closing ")").
string* NewString();

private:
std::ostringstream* stream_;
};

template <typename T1, typename T2>
string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
CheckOpMessageBuilder comb(exprtext);
MakeCheckOpValueString(comb.ForVar1(), v1);
MakeCheckOpValueString(comb.ForVar2(), v2);
return comb.NewString();
}

// Helper functions for CHECK_OP macro.
// We use the full name Check_EQ, Check_NE, etc. in case the file including
// absl/log/log.h provides its own #defines for the simpler names EQ, NE, etc.
// This happens if, for example, those are used as token names in a
// yacc grammar.
// The (int, int) overload works around the issue that the compiler
// will not instantiate the template version of the function on values of
// unnamed enum type - see comment below.
#define TF_DEFINE_CHECK_OP_IMPL(name, op) \
template <typename T1, typename T2> \
inline string* name##Impl(const T1& v1, const T2& v2, \
const char* exprtext) { \
if (TF_PREDICT_TRUE(v1 op v2)) \
return NULL; \
else \
return ::tsl::internal::MakeCheckOpString(v1, v2, exprtext); \
} \
inline string* name##Impl(int v1, int v2, const char* exprtext) { \
return name##Impl<int, int>(v1, v2, exprtext); \
}

// The (size_t, int) and (int, size_t) specialization are to handle unsigned
// comparison errors while still being thorough with the comparison.

TF_DEFINE_CHECK_OP_IMPL(Check_EQ, ==)
// Compilation error with CHECK_EQ(NULL, x)?
// Use CHECK(x == NULL) instead.

inline string* Check_EQImpl(int v1, size_t v2, const char* exprtext) {
if (TF_PREDICT_FALSE(v1 < 0))
::tsl::internal::MakeCheckOpString(v1, v2, exprtext);

return Check_EQImpl(size_t(v1), v2, exprtext);
}

inline string* Check_EQImpl(size_t v1, int v2, const char* exprtext) {
return Check_EQImpl(v2, v1, exprtext);
}

TF_DEFINE_CHECK_OP_IMPL(Check_NE, !=)

inline string* Check_NEImpl(int v1, size_t v2, const char* exprtext) {
if (v1 < 0) return NULL;

return Check_NEImpl(size_t(v1), v2, exprtext);
}

inline string* Check_NEImpl(size_t v1, int v2, const char* exprtext) {
return Check_NEImpl(v2, v1, exprtext);
}

TF_DEFINE_CHECK_OP_IMPL(Check_LE, <=)

inline string* Check_LEImpl(int v1, size_t v2, const char* exprtext) {
if (v1 <= 0) return NULL;

return Check_LEImpl(size_t(v1), v2, exprtext);
}

inline string* Check_LEImpl(size_t v1, int v2, const char* exprtext) {
if (TF_PREDICT_FALSE(v2 < 0))
return ::tsl::internal::MakeCheckOpString(v1, v2, exprtext);
return Check_LEImpl(v1, size_t(v2), exprtext);
}

TF_DEFINE_CHECK_OP_IMPL(Check_LT, <)

inline string* Check_LTImpl(int v1, size_t v2, const char* exprtext) {
if (v1 < 0) return NULL;

return Check_LTImpl(size_t(v1), v2, exprtext);
}

inline string* Check_LTImpl(size_t v1, int v2, const char* exprtext) {
if (v2 < 0) return ::tsl::internal::MakeCheckOpString(v1, v2, exprtext);
return Check_LTImpl(v1, size_t(v2), exprtext);
}

// Implement GE,GT in terms of LE,LT
template <typename T1, typename T2>
inline string* Check_GEImpl(const T1& v1, const T2& v2, const char* exprtext) {
return Check_LEImpl(v2, v1, exprtext);
}

template <typename T1, typename T2>
inline string* Check_GTImpl(const T1& v1, const T2& v2, const char* exprtext) {
return Check_LTImpl(v2, v1, exprtext);
}

#undef TF_DEFINE_CHECK_OP_IMPL

// In optimized mode, use CheckOpString to hint to compiler that
// the while condition is unlikely.
#define CHECK_OP_LOG(name, op, val1, val2) \
while (::tsl::internal::CheckOpString _result{::tsl::internal::name##Impl( \
::tsl::internal::GetReferenceableValue(val1), \
::tsl::internal::GetReferenceableValue(val2), #val1 " " #op " " #val2)}) \
::tsl::internal::LogMessageFatal(__FILE__, __LINE__) << *(_result.str_)

#define CHECK_OP(name, op, val1, val2) CHECK_OP_LOG(name, op, val1, val2)

// CHECK_EQ/NE/...
#define CHECK_EQ(val1, val2) CHECK_OP(Check_EQ, ==, val1, val2)
#define CHECK_NE(val1, val2) CHECK_OP(Check_NE, !=, val1, val2)
#define CHECK_LE(val1, val2) CHECK_OP(Check_LE, <=, val1, val2)
#define CHECK_LT(val1, val2) CHECK_OP(Check_LT, <, val1, val2)
#define CHECK_GE(val1, val2) CHECK_OP(Check_GE, >=, val1, val2)
#define CHECK_GT(val1, val2) CHECK_OP(Check_GT, >, val1, val2)
#define CHECK_NOTNULL(val) \
::tsl::internal::CheckNotNull(__FILE__, __LINE__, \
"'" #val "' Must be non NULL", (val))

#ifndef NDEBUG
// DCHECK_EQ/NE/...
#define DCHECK(condition) CHECK(condition)
#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)

#else

#define DCHECK(condition) \
while (false && (condition)) LOG(FATAL)

// NDEBUG is defined, so DCHECK_EQ(x, y) and so on do nothing.
// However, we still want the compiler to parse x and y, because
// we don't want to lose potentially useful errors and warnings.
// _DCHECK_NOP is a helper, and should not be used outside of this file.
#define _TF_DCHECK_NOP(x, y) \
while (false && ((void)(x), (void)(y), 0)) LOG(FATAL)

#define DCHECK_EQ(x, y) _TF_DCHECK_NOP(x, y)
#define DCHECK_NE(x, y) _TF_DCHECK_NOP(x, y)
#define DCHECK_LE(x, y) _TF_DCHECK_NOP(x, y)
#define DCHECK_LT(x, y) _TF_DCHECK_NOP(x, y)
#define DCHECK_GE(x, y) _TF_DCHECK_NOP(x, y)
#define DCHECK_GT(x, y) _TF_DCHECK_NOP(x, y)

#endif

// These are for when you don't want a CHECK failure to print a verbose
// stack trace. The implementation of CHECK* in this file already doesn't.
#define QCHECK(condition) CHECK(condition)
#define QCHECK_EQ(x, y) CHECK_EQ(x, y)
#define QCHECK_NE(x, y) CHECK_NE(x, y)
#define QCHECK_LE(x, y) CHECK_LE(x, y)
#define QCHECK_LT(x, y) CHECK_LT(x, y)
#define QCHECK_GE(x, y) CHECK_GE(x, y)
#define QCHECK_GT(x, y) CHECK_GT(x, y)

template <typename T>
T&& CheckNotNull(const char* file, int line, const char* exprtext, T&& t) {
if (t == nullptr) {
Expand Down

0 comments on commit d811f58

Please sign in to comment.