Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
323 changes: 192 additions & 131 deletions offload/include/Shared/Debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#define OMPTARGET_SHARED_DEBUG_H

#include <atomic>
#include <cstdarg>
#include <mutex>
#include <string>

Expand Down Expand Up @@ -78,17 +79,6 @@ inline std::atomic<uint32_t> &getInfoLevelInternal() {

inline uint32_t getInfoLevel() { return getInfoLevelInternal().load(); }

inline uint32_t getDebugLevel() {
static uint32_t DebugLevel = 0;
static std::once_flag Flag{};
std::call_once(Flag, []() {
if (char *EnvStr = getenv("LIBOMPTARGET_DEBUG"))
DebugLevel = std::stoi(EnvStr);
});

return DebugLevel;
}

#undef USED
#undef GCC_VERSION

Expand Down Expand Up @@ -147,46 +137,11 @@ inline uint32_t getDebugLevel() {
fprintf(_stdDst, __VA_ARGS__); \
} while (0)

// Debugging messages
#ifdef OMPTARGET_DEBUG
#include <stdio.h>

#define DEBUGP(prefix, ...) \
{ \
fprintf(stderr, "%s --> ", prefix); \
fprintf(stderr, __VA_ARGS__); \
}

/// Emit a message for debugging
#define DP(...) \
do { \
if (getDebugLevel() > 0) { \
DEBUGP(DEBUG_PREFIX, __VA_ARGS__); \
} \
} while (false)

/// Emit a message for debugging or failure if debugging is disabled
#define REPORT(...) \
do { \
if (getDebugLevel() > 0) { \
DP(__VA_ARGS__); \
} else { \
FAILURE_MESSAGE(__VA_ARGS__); \
} \
} while (false)
#else
#define DEBUGP(prefix, ...) \
{}
#define DP(...) \
{}
#define REPORT(...) FAILURE_MESSAGE(__VA_ARGS__);
#endif // OMPTARGET_DEBUG

/// Emit a message giving the user extra information about the runtime if
#define INFO(_flags, _id, ...) \
do { \
if (getDebugLevel() > 0) { \
DEBUGP(DEBUG_PREFIX, __VA_ARGS__); \
if (::llvm::offload::debug::isDebugEnabled()) { \
DP(__VA_ARGS__); \
} else if (getInfoLevel() & _flags) { \
INFO_MESSAGE(_id, __VA_ARGS__); \
} \
Expand All @@ -203,17 +158,92 @@ inline uint32_t getDebugLevel() {

namespace llvm::offload::debug {

#ifdef OMPTARGET_DEBUG
/// A raw_ostream that tracks `\n` and print the prefix after each
/// newline. Based on raw_ldbg_ostream from Support/DebugLog.h
class LLVM_ABI odbg_ostream final : public raw_ostream {
public:
enum IfLevel : uint32_t;
enum OnlyLevel : uint32_t;

struct DebugFilter {
StringRef Type;
uint32_t Level;
};
private:
std::string Prefix;
raw_ostream &Os;
uint32_t BaseLevel;
bool ShouldPrefixNextString;
bool ShouldEmitNewLineOnDestruction;
bool NeedEndNewLine = false;

struct DebugSettings {
bool Enabled = false;
uint32_t DefaultLevel = 1;
llvm::SmallVector<DebugFilter> Filters;
/// If the stream is muted, writes to it are ignored
bool Muted = false;

/// Split the line on newlines and insert the prefix before each
/// newline. Forward everything to the underlying stream.
void write_impl(const char *Ptr, size_t Size) final {
if (Muted)
return;

NeedEndNewLine = false;
auto Str = StringRef(Ptr, Size);
auto Eol = Str.find('\n');
// Handle `\n` occurring in the string, ensure to print the prefix at the
// beginning of each line.
while (Eol != StringRef::npos) {
// Take the line up to the newline (including the newline).
StringRef Line = Str.take_front(Eol + 1);
if (!Line.empty())
writeWithPrefix(Line);
// We printed a newline, record here to print a prefix.
ShouldPrefixNextString = true;
Str = Str.drop_front(Eol + 1);
Eol = Str.find('\n');
}
if (!Str.empty()) {
writeWithPrefix(Str);
NeedEndNewLine = true;
}
}
void emitPrefix() { Os.write(Prefix.c_str(), Prefix.size()); }
void writeWithPrefix(StringRef Str) {
if (ShouldPrefixNextString) {
emitPrefix();
ShouldPrefixNextString = false;
}
Os.write(Str.data(), Str.size());
}

public:
explicit odbg_ostream(std::string Prefix, raw_ostream &Os, uint32_t BaseLevel,
bool ShouldPrefixNextString = true,
bool ShouldEmitNewLineOnDestruction = true)
: Prefix(std::move(Prefix)), Os(Os), BaseLevel(BaseLevel),
ShouldPrefixNextString(ShouldPrefixNextString),
ShouldEmitNewLineOnDestruction(ShouldEmitNewLineOnDestruction) {
SetUnbuffered();
}
~odbg_ostream() final {
if (ShouldEmitNewLineOnDestruction && NeedEndNewLine)
Os << '\n';
}
odbg_ostream(const odbg_ostream &) = delete;
odbg_ostream &operator=(const odbg_ostream &) = delete;
odbg_ostream(odbg_ostream &&other) : Os(other.Os) {
Prefix = std::move(other.Prefix);
BaseLevel = other.BaseLevel;
ShouldPrefixNextString = other.ShouldPrefixNextString;
ShouldEmitNewLineOnDestruction = other.ShouldEmitNewLineOnDestruction;
NeedEndNewLine = other.NeedEndNewLine;
Muted = other.Muted;
}

/// Forward the current_pos method to the underlying stream.
uint64_t current_pos() const final { return Os.tell(); }

/// Some of the `<<` operators expect an lvalue, so we trick the type
/// system.
odbg_ostream &asLvalue() { return *this; }

void shouldMute(const IfLevel Filter) { Muted = Filter > BaseLevel; }
void shouldMute(const OnlyLevel Filter) { Muted = BaseLevel != Filter; }
};

/// dbgs - Return a circular-buffered debug stream.
Expand All @@ -228,6 +258,19 @@ struct DebugSettings {
return thestrm.strm;
}

#ifdef OMPTARGET_DEBUG

struct DebugFilter {
StringRef Type;
uint32_t Level;
};

struct DebugSettings {
bool Enabled = false;
uint32_t DefaultLevel = 1;
llvm::SmallVector<DebugFilter> Filters;
};

[[maybe_unused]] static DebugFilter parseDebugFilter(StringRef Filter) {
size_t Pos = Filter.find(':');
if (Pos == StringRef::npos)
Expand Down Expand Up @@ -309,80 +352,6 @@ shouldPrintDebug(const char *Component, const char *Type, uint32_t &Level) {
return false;
}

/// A raw_ostream that tracks `\n` and print the prefix after each
/// newline. Based on raw_ldbg_ostream from Support/DebugLog.h
class LLVM_ABI odbg_ostream final : public raw_ostream {
public:
enum IfLevel : uint32_t;
enum OnlyLevel : uint32_t;

private:
std::string Prefix;
raw_ostream &Os;
uint32_t BaseLevel;
bool ShouldPrefixNextString;
bool ShouldEmitNewLineOnDestruction;

/// If the stream is muted, writes to it are ignored
bool Muted = false;

/// Split the line on newlines and insert the prefix before each
/// newline. Forward everything to the underlying stream.
void write_impl(const char *Ptr, size_t Size) final {
if (Muted)
return;

auto Str = StringRef(Ptr, Size);
auto Eol = Str.find('\n');
// Handle `\n` occurring in the string, ensure to print the prefix at the
// beginning of each line.
while (Eol != StringRef::npos) {
// Take the line up to the newline (including the newline).
StringRef Line = Str.take_front(Eol + 1);
if (!Line.empty())
writeWithPrefix(Line);
// We printed a newline, record here to print a prefix.
ShouldPrefixNextString = true;
Str = Str.drop_front(Eol + 1);
Eol = Str.find('\n');
}
if (!Str.empty())
writeWithPrefix(Str);
}
void emitPrefix() { Os.write(Prefix.c_str(), Prefix.size()); }
void writeWithPrefix(StringRef Str) {
if (ShouldPrefixNextString) {
emitPrefix();
ShouldPrefixNextString = false;
}
Os.write(Str.data(), Str.size());
}

public:
explicit odbg_ostream(std::string Prefix, raw_ostream &Os, uint32_t BaseLevel,
bool ShouldPrefixNextString = true,
bool ShouldEmitNewLineOnDestruction = false)
: Prefix(std::move(Prefix)), Os(Os), BaseLevel(BaseLevel),
ShouldPrefixNextString(ShouldPrefixNextString),
ShouldEmitNewLineOnDestruction(ShouldEmitNewLineOnDestruction) {
SetUnbuffered();
}
~odbg_ostream() final {
if (ShouldEmitNewLineOnDestruction)
Os << '\n';
}

/// Forward the current_pos method to the underlying stream.
uint64_t current_pos() const final { return Os.tell(); }

/// Some of the `<<` operators expect an lvalue, so we trick the type
/// system.
odbg_ostream &asLvalue() { return *this; }

void shouldMute(const IfLevel Filter) { Muted = Filter > BaseLevel; }
void shouldMute(const OnlyLevel Filter) { Muted = BaseLevel != Filter; }
};

/// Compute the prefix for the debug log in the form of:
/// "Component --> "
[[maybe_unused]] static std::string computePrefix(StringRef Component,
Expand Down Expand Up @@ -463,6 +432,8 @@ static inline raw_ostream &operator<<(raw_ostream &Os,

#else

inline bool isDebugEnabled() { return false; }

#define ODBG_NULL \
for (bool _c = false; _c; _c = false) \
::llvm::nulls()
Expand All @@ -479,4 +450,94 @@ static inline raw_ostream &operator<<(raw_ostream &Os,

} // namespace llvm::offload::debug

namespace llvm::omp::target::debug {
using namespace llvm::offload::debug;

enum OmpDebugLevel : uint32_t {
ODL_Default = 1,
ODL_Error = ODL_Default,
ODL_Detailed = 2,
ODL_Verbose = 3,
ODL_VeryVerbose = 4,
ODL_Dumping = 5
};

/* Debug types to use in libomptarget */
constexpr const char *ODT_Init = "Init";
constexpr const char *ODT_Mapping = "Mapping";
constexpr const char *ODT_Kernel = "Kernel";
constexpr const char *ODT_DataTransfer = "DataTransfer";
constexpr const char *ODT_Sync = "Sync";
constexpr const char *ODT_Deinit = "Deinit";
constexpr const char *ODT_Error = "Error";
constexpr const char *ODT_KernelArgs = "KernelArgs";
constexpr const char *ODT_MappingExists = "MappingExists";
constexpr const char *ODT_DumpTable = "DumpTable";
constexpr const char *ODT_MappingChanged = "MappingChanged";
constexpr const char *ODT_PluginKernel = "PluginKernel";
constexpr const char *ODT_EmptyMapping = "EmptyMapping";

static inline odbg_ostream reportErrorStream() {
#ifdef OMPTARGET_DEBUG
if (::llvm::offload::debug::isDebugEnabled()) {
uint32_t RealLevel = ODL_Error;
if (::llvm::offload::debug::shouldPrintDebug(GETNAME(TARGET_NAME),
(ODT_Error), RealLevel))
return odbg_ostream{
::llvm::offload::debug::computePrefix(DEBUG_PREFIX, ODT_Error),
::llvm::offload::debug::dbgs(), RealLevel};
else
return odbg_ostream{"", ::llvm::nulls(), 1};
}
#endif
return odbg_ostream{GETNAME(TARGET_NAME) " error: ",
::llvm::offload::debug::dbgs(), ODL_Error};
}

#ifdef OMPTARGET_DEBUG
// Deprecated debug print macros
[[maybe_unused]] static std::string formatToStr(const char *format, ...) {
va_list args;
va_start(args, format);
size_t len = std::vsnprintf(NULL, 0, format, args);
va_end(args);
llvm::SmallVector<char, 128> vec(len + 1);
va_start(args, format);
std::vsnprintf(&vec[0], len + 1, format, args);
va_end(args);
return &vec[0];
}

// helper macro to support old DP and REPORT macros with printf syntax
#define FORMAT_TO_STR(Format, ...) \
::llvm::omp::target::debug::formatToStr(Format __VA_OPT__(, ) __VA_ARGS__)

#define DP(...) ODBG() << FORMAT_TO_STR(__VA_ARGS__);

#define REPORT_INT_OLD(...) \
do { \
if (::llvm::offload::debug::isDebugEnabled()) { \
ODBG(::llvm::omp::target::debug::ODT_Error, \
::llvm::omp::target::debug::ODL_Error) \
<< FORMAT_TO_STR(__VA_ARGS__); \
} else { \
FAILURE_MESSAGE(__VA_ARGS__); \
} \
} while (false)

#else
#define DP(...) \
{ \
}
#define REPORT_INT_OLD(...) FAILURE_MESSAGE(__VA_ARGS__);
#endif // OMPTARGET_DEBUG

// This is used for the new style REPORT macro
#define REPORT_INT() ::llvm::omp::target::debug::reportErrorStream()

// Make REPORT compatible with old and new syntax
#define REPORT(...) REPORT_INT##__VA_OPT__(_OLD)(__VA_ARGS__)

} // namespace llvm::omp::target::debug

#endif // OMPTARGET_SHARED_DEBUG_H
Loading
Loading