/// \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 #include #include #include #include // LLVM includes #include "llvm/IR/Value.h" #include "llvm/Support/raw_os_ostream.h" // Local libraries includes #include "revng/Support/CommandLine.h" #include "revng/Support/Debug.h" #include "revng/Support/revng.h" namespace cl = llvm::cl; size_t MaxLoggerNameLength = 0; LogTerminator DoLog; llvm::ManagedStatic Loggers; std::ostream &dbg(std::cerr); Logger<> PassesLog("passes"); Logger<> ReleaseLog("release"); template void Logger::emit() { if (X && Enabled) { std::string Pad = std::string(MaxLoggerNameLength - Name.size(), ' '); dbg << "[" << Name.data() << Pad << "] "; for (unsigned I = 0; I < IndentLevel; I++) dbg << " "; dbg << Buffer.str() << "\n"; Buffer.str(""); Buffer.clear(); } } /// \brief Class for dynamically registering arguments options template class DynamicValuesClass { private: struct Alternative { const char *Name; int Value; const char *Description; }; std::vector Values; public: void addOption(const char *Name, int Value, const char *Description) { Values.push_back({ Name, Value, Description }); } template void apply(Opt &O) const { for (const Alternative &A : Values) O.getParser().addLiteralOption(A.Name, A.Value, A.Description); } }; enum PlaceholderEnum {}; static std::unique_ptr> DebugLogging; static std::unique_ptr DebugLoggingAlias; void LoggersRegistry::registerArguments() const { DynamicValuesClass Values; unsigned I = 0; for (Logger *L : Loggers) Values.addOption(L->name().data(), I++, L->description().data()); auto *Opt = new cl::list("debug-log", cl::desc("enable verbose logging"), Values, cl::cat(MainCategory)); DebugLogging.reset(Opt); DebugLoggingAlias.reset(new cl::alias("d", cl::desc("Alias for -debug-log"), cl::aliasopt(*DebugLogging), cl::cat(MainCategory))); } void LoggersRegistry::activateArguments() { for (unsigned I : *DebugLogging) Loggers[I]->enable(); } template unsigned Logger::IndentLevel; // Force instantiation template class Logger; template class Logger; void dumpModule(const llvm::Module *M, const char *Path) { std::ofstream FileStream(Path); llvm::raw_os_ostream Stream(FileStream); M->print(Stream, nullptr, true); }