mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
2fc342d2e4
Rationale: it is a widespread practice, both in revng and in projects that depend on it, to write verification functions that check specific properties hold after different transformations on various data structures. Often, these verification function are very useful for debugging and during development, but they can be very costly and we don't want to always execute them at runtime. This patch adds a global public Logger, called VerifyLog, that can be enabled with the --debug-log=verify command line argument. This Logger is intended to be used in revng and in projects that depend on it, as a guard for costly calls to verification functions that do not need to be performed on a typical execution, but only when debugging. For now the only user is JumpTargetManager, but other uses are already envisioned.
121 lines
3.3 KiB
C++
121 lines
3.3 KiB
C++
/// \file Debug.cpp
|
|
/// \brief Implementation of the debug framework
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
// Standard includes
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
// LLVM includes
|
|
#include "llvm/ADT/Twine.h"
|
|
#include "llvm/IR/Value.h"
|
|
|
|
// Local libraries includes
|
|
#include "revng/Support/Debug.h"
|
|
#include "revng/Support/revng.h"
|
|
|
|
namespace cl = llvm::cl;
|
|
using llvm::Twine;
|
|
|
|
static cl::opt<unsigned> MaxLocationLength("debug-location-max-length",
|
|
cl::desc("emit file and line number "
|
|
"for log "
|
|
"messages of at most this "
|
|
"size."),
|
|
cl::cat(MainCategory),
|
|
cl::init(0));
|
|
|
|
size_t MaxLoggerNameLength = 0;
|
|
llvm::ManagedStatic<LoggersRegistry> Loggers;
|
|
|
|
std::ostream &dbg(std::cerr);
|
|
|
|
Logger<> PassesLog("passes");
|
|
Logger<> ReleaseLog("release");
|
|
Logger<> VerifyLog("verify");
|
|
|
|
template<bool X>
|
|
void Logger<X>::flush(const LogTerminator &LineInfo) {
|
|
if (X && Enabled) {
|
|
std::string Pad;
|
|
|
|
if (MaxLocationLength != 0) {
|
|
std::string Suffix = (Twine(":") + Twine(LineInfo.Line)).str();
|
|
revng_assert(Suffix.size() < MaxLocationLength);
|
|
std::string Location(LineInfo.File);
|
|
size_t LastSlash = Location.rfind("/");
|
|
if (LastSlash != std::string::npos)
|
|
Location.erase(0, LastSlash + 1);
|
|
|
|
if (Location.size() > MaxLocationLength - Suffix.size()) {
|
|
Location.erase(MaxLocationLength - Suffix.size(), std::string::npos);
|
|
}
|
|
|
|
Pad = std::string(MaxLocationLength - Location.size() - Suffix.size(),
|
|
' ');
|
|
dbg << "[" << Location << Suffix << "] " << Pad;
|
|
}
|
|
|
|
Pad = std::string(MaxLoggerNameLength - Name.size() + IndentLevel * 2, ' ');
|
|
dbg << "[" << Name.data() << "] " << Pad;
|
|
|
|
std::string Data = Buffer.str();
|
|
if (Data.size() > 0 and Data.back() == '\n')
|
|
Data.resize(Data.size() - 1);
|
|
|
|
std::string Delimiter = "\n";
|
|
size_t Start = 0;
|
|
size_t End = Data.find(Delimiter);
|
|
dbg << Data.substr(Start, End) << "\n";
|
|
|
|
if (End != std::string::npos) {
|
|
Pad = std::string(3 + MaxLoggerNameLength + IndentLevel * 2, ' ');
|
|
do {
|
|
Start = End + Delimiter.length();
|
|
End = Data.find(Delimiter, Start);
|
|
dbg << Pad << Data.substr(Start, End - Start) << "\n";
|
|
} while (End != std::string::npos);
|
|
}
|
|
|
|
Buffer.str("");
|
|
Buffer.clear();
|
|
}
|
|
}
|
|
|
|
static std::unique_ptr<cl::list<PlaceholderEnum>> DebugLogging;
|
|
static std::unique_ptr<cl::alias> DebugLoggingAlias;
|
|
|
|
llvm::ManagedStatic<DebugLogOptionWrapper> DebugLogOption;
|
|
|
|
template<bool X>
|
|
unsigned Logger<X>::IndentLevel;
|
|
|
|
template<bool X>
|
|
void Logger<X>::indent(unsigned Level) {
|
|
if (isEnabled())
|
|
IndentLevel += Level;
|
|
}
|
|
|
|
template<bool X>
|
|
void Logger<X>::unindent(unsigned Level) {
|
|
if (isEnabled()) {
|
|
revng_assert(IndentLevel - Level >= 0);
|
|
IndentLevel -= Level;
|
|
}
|
|
}
|
|
|
|
template<bool X>
|
|
void Logger<X>::setIndentation(unsigned Level) {
|
|
if (isEnabled())
|
|
IndentLevel = Level;
|
|
}
|
|
|
|
// Force instantiation
|
|
template class Logger<true>;
|
|
template class Logger<false>;
|