//===-- gen/logger.h - Codegen debug logging --------------------*- C++ -*-===// // // LDC – the LLVM D compiler // // This file is distributed under the BSD-style LDC license. See the LICENSE // file for details. // //===----------------------------------------------------------------------===// // // Defines a common interface for logging debug information during code // generation. // //===----------------------------------------------------------------------===// #ifndef LDC_GEN_LOGGER_H #define LDC_GEN_LOGGER_H #include #include namespace llvm { class Type; class Value; } #ifndef IS_PRINTF #ifdef __GNUC__ #define IS_PRINTF(FMTARG) \ __attribute((__format__(__printf__, (FMTARG), (FMTARG) + 1))) #else #define IS_PRINTF(FMTARG) #endif #endif struct Loc; class Stream { std::ostream *OS; public: Stream() : OS(nullptr) {} explicit Stream(std::ostream *S) : OS(S) {} explicit Stream(std::ostream &S) : OS(&S) {} /* Stream operator << (std::ios_base &(*Func)(std::ios_base&)) { if (OS) *OS << Func; return *this; } */ Stream operator<<(std::ostream &(*Func)(std::ostream &)) { if (OS) { Func(*OS); } return *this; } template Stream &operator<<(const Ty &Thing) { if (OS) { Writer::write(*OS, Thing); } return *this; } private: // Implementation details to treat llvm::Value, llvm::Type and their // subclasses specially (to pretty-print types). static void writeType(std::ostream &OS, const llvm::Type &Ty); static void writeValue(std::ostream &OS, const llvm::Value &Ty); template friend struct Writer; // error: function template partial specialization is not allowed // So I guess type partial specialization + member function will have to do... template struct Writer { static void write(std::ostream &OS, const Ty &Thing) { OS << Thing; } }; template struct Writer { static void write(std::ostream &OS, const llvm::Type &Thing) { Stream::writeType(OS, Thing); } static void write(std::ostream &OS, const llvm::Value &Thing) { Stream::writeValue(OS, Thing); } }; // NOT IMPLEMENTED char sfinae_bait(const llvm::Type &); char sfinae_bait(const llvm::Value &); short sfinae_bait(...); }; namespace Logger { extern bool _enabled; void indent(); void undent(); Stream cout(); void println(const char *fmt, ...) IS_PRINTF(1); void print(const char *fmt, ...) IS_PRINTF(1); inline void enable() { _enabled = true; } inline void disable() { _enabled = false; } inline bool enabled() { return _enabled; } void attention(Loc loc, const char *fmt, ...) IS_PRINTF(2); struct LoggerScope { LoggerScope() { Logger::indent(); } ~LoggerScope() { Logger::undent(); } }; } #define LOG_SCOPE Logger::LoggerScope _logscope; #define IF_LOG if (Logger::enabled()) #endif