chromium/third_party/angle/src/common/log_utils.h

//
// Copyright 2024 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// log_utils.h: Logging and assert utilities. A lot of the logging code is adapted from Chromium's
// base/logging.h.

#ifndef COMMON_LOG_UTILS_H_
#define COMMON_LOG_UTILS_H_

#include <assert.h>
#include <stdio.h>

#include <iomanip>
#include <ios>
#include <mutex>
#include <sstream>
#include <string>

#include "common/angleutils.h"
#include "common/entry_points_enum_autogen.h"
#include "common/platform.h"

namespace gl
{
class Context;

LogSeverity;
// Note: the log severities are used to index into the array of names,
// see g_logSeverityNames.
constexpr LogSeverity LOG_EVENT          =;
constexpr LogSeverity LOG_INFO           =;
constexpr LogSeverity LOG_WARN           =;
constexpr LogSeverity LOG_ERR            =;
constexpr LogSeverity LOG_FATAL          =;
constexpr LogSeverity LOG_NUM_SEVERITIES =;

void Trace(LogSeverity severity, const char *message);

// This class more or less represents a particular log message.  You
// create an instance of LogMessage and then stream stuff to it.
// When you finish streaming to it, ~LogMessage is called and the
// full message gets streamed to the appropriate destination.
//
// You shouldn't actually use LogMessage's constructor to log things,
// though.  You should use the ERR() and WARN() macros.
class LogMessage : angle::NonCopyable
{};

bool ShouldBeginScopedEvent(const gl::Context *context);

namespace priv
{
// This class is used to explicitly ignore values in the conditional logging macros. This avoids
// compiler warnings like "value computed is not used" and "statement has no effect".
class LogMessageVoidify
{};

extern std::ostream *gSwallowStream;

// Used by ANGLE_LOG_IS_ON to lazy-evaluate stream arguments.
bool ShouldCreatePlatformLogMessage(LogSeverity severity);

// N is the width of the output to the stream. The output is padded with zeros
// if value is less than N characters.
// S is the stream type, either ostream for ANSI or wostream for wide character.
// T is the type of the value to output to the stream.
// C is the type of characters - either char for ANSI or wchar_t for wide char.
template <int N, typename S, typename T, typename C>
S &FmtHex(S &stream, T value, const C *zeroX, C zero)
{}

template <typename S, typename T, typename C>
S &FmtHexAutoSized(S &stream, T value, const C *prefix, const C *zeroX, C zero)
{}

template <typename T, typename C>
class FmtHexHelper
{};

}  // namespace priv

template <typename T, typename C = char>
priv::FmtHexHelper<T, C> FmtHex(T value)
{}

#if defined(ANGLE_PLATFORM_WINDOWS)
priv::FmtHexHelper<HRESULT, char> FmtHR(HRESULT value);
priv::FmtHexHelper<DWORD, char> FmtErr(DWORD value);
#endif  // defined(ANGLE_PLATFORM_WINDOWS)

template <typename T>
std::ostream &FmtHex(std::ostream &os, T value)
{}

// A few definitions of macros that don't generate much code. These are used
// by ANGLE_LOG(). Since these are used all over our code, it's
// better to have compact code for these operations.
#define COMPACT_ANGLE_LOG_EX_EVENT(ClassName, ...)
#define COMPACT_ANGLE_LOG_EX_INFO(ClassName, ...)
#define COMPACT_ANGLE_LOG_EX_WARN(ClassName, ...)
#define COMPACT_ANGLE_LOG_EX_ERR(ClassName, ...)
#define COMPACT_ANGLE_LOG_EX_FATAL(ClassName, ...)

#define COMPACT_ANGLE_LOG_EVENT
#define COMPACT_ANGLE_LOG_INFO
#define COMPACT_ANGLE_LOG_WARN
#define COMPACT_ANGLE_LOG_ERR
#define COMPACT_ANGLE_LOG_FATAL

#define ANGLE_LOG_IS_ON(severity)

// Helper macro which avoids evaluating the arguments to a stream if the condition doesn't hold.
// Condition is evaluated once and only once.
#define ANGLE_LAZY_STREAM(stream, condition)

// We use the preprocessor's merging operator, "##", so that, e.g.,
// ANGLE_LOG(EVENT) becomes the token COMPACT_ANGLE_LOG_EVENT.  There's some funny
// subtle difference between ostream member streaming functions (e.g.,
// ostream::operator<<(int) and ostream non-member streaming functions
// (e.g., ::operator<<(ostream&, string&): it turns out that it's
// impossible to stream something like a string directly to an unnamed
// ostream. We employ a neat hack by calling the stream() member
// function of LogMessage which seems to avoid the problem.
#define ANGLE_LOG_STREAM(severity)

#define ANGLE_LOG(severity)

}  // namespace gl

#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define ANGLE_TRACE_ENABLED
#endif

#if !defined(NDEBUG) || defined(ANGLE_ASSERT_ALWAYS_ON)
#define ANGLE_ENABLE_ASSERTS
#endif

#define INFO()
#define WARN()
#define ERR()
#define FATAL()

// A macro to log a performance event around a scope.
#if defined(ANGLE_TRACE_ENABLED)
#    if defined(_MSC_VER)
#define EVENT
#    else
#define EVENT
#    endif  // _MSC_VER
#else
#define EVENT(message, ...)
#endif

// Note that gSwallowStream is used instead of an arbitrary LOG() stream to avoid the creation of an
// object with a non-trivial destructor (LogMessage). On MSVC x86 (checked on 2015 Update 3), this
// causes a few additional pointless instructions to be emitted even at full optimization level,
// even though the : arm of the ternary operator is clearly never executed. Using a simpler object
// to be &'d with Voidify() avoids these extra instructions. Using a simpler POD object with a
// templated operator<< also works to avoid these instructions. However, this causes warnings on
// statically defined implementations of operator<<(std::ostream, ...) in some .cpp files, because
// they become defined-but-unreferenced functions. A reinterpret_cast of 0 to an ostream* also is
// not suitable, because some compilers warn of undefined behavior.
#define ANGLE_EAT_STREAM_PARAMETERS

// A macro asserting a condition and outputting failures to the debug log
#if defined(ANGLE_ENABLE_ASSERTS)
#define ASSERT(expression)
#else
#define ASSERT
#endif  // defined(ANGLE_ENABLE_ASSERTS)

// A macro to indicate unimplemented functionality
#ifndef NOASSERT_UNIMPLEMENTED
#define NOASSERT_UNIMPLEMENTED
#endif

#if defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
#define UNIMPLEMENTED()

// A macro for code which is not expected to be reached under valid assumptions
#define UNREACHABLE()
#else
#define UNIMPLEMENTED

// A macro for code which is not expected to be reached under valid assumptions
#define UNREACHABLE
#endif  // defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)

#if defined(ANGLE_PLATFORM_WINDOWS)
#define ANGLE_FUNCTION
#else
#define ANGLE_FUNCTION
#endif

#endif  // COMMON_LOG_UTILS_H_