| 1 |
#ifndef _llvmd_gen_logger_h_ |
|---|
| 2 |
#define _llvmd_gen_logger_h_ |
|---|
| 3 |
|
|---|
| 4 |
#include <iosfwd> |
|---|
| 5 |
|
|---|
| 6 |
namespace llvm { |
|---|
| 7 |
class Type; |
|---|
| 8 |
class Value; |
|---|
| 9 |
} |
|---|
| 10 |
|
|---|
| 11 |
#ifndef IS_PRINTF |
|---|
| 12 |
# ifdef __GNUC__ |
|---|
| 13 |
# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) )) |
|---|
| 14 |
# else |
|---|
| 15 |
# define IS_PRINTF(FMTARG) |
|---|
| 16 |
# endif |
|---|
| 17 |
#endif |
|---|
| 18 |
|
|---|
| 19 |
struct Loc; |
|---|
| 20 |
|
|---|
| 21 |
class Stream { |
|---|
| 22 |
std::ostream* OS; |
|---|
| 23 |
|
|---|
| 24 |
public: |
|---|
| 25 |
Stream() : OS(0) {} |
|---|
| 26 |
Stream(std::ostream* S) : OS(S) {} |
|---|
| 27 |
Stream(std::ostream& S) : OS(&S) {} |
|---|
| 28 |
|
|---|
| 29 |
/* |
|---|
| 30 |
Stream operator << (std::ios_base &(*Func)(std::ios_base&)) { |
|---|
| 31 |
if (OS) *OS << Func; |
|---|
| 32 |
return *this; |
|---|
| 33 |
} |
|---|
| 34 |
*/ |
|---|
| 35 |
|
|---|
| 36 |
Stream operator << (std::ostream &(*Func)(std::ostream&)) { |
|---|
| 37 |
if (OS) Func(*OS); |
|---|
| 38 |
return *this; |
|---|
| 39 |
} |
|---|
| 40 |
|
|---|
| 41 |
template<typename Ty> |
|---|
| 42 |
Stream& operator << (const Ty& Thing) { |
|---|
| 43 |
if (OS) |
|---|
| 44 |
Writer<Ty, sizeof(sfinae_bait(Thing))>::write(*OS, Thing); |
|---|
| 45 |
return *this; |
|---|
| 46 |
} |
|---|
| 47 |
|
|---|
| 48 |
private: |
|---|
| 49 |
// Implementation details to treat llvm::Value, llvm::Type and their |
|---|
| 50 |
// subclasses specially (to pretty-print types). |
|---|
| 51 |
|
|---|
| 52 |
static void writeType(std::ostream& OS, const llvm::Type& Ty); |
|---|
| 53 |
static void writeValue(std::ostream& OS, const llvm::Value& Ty); |
|---|
| 54 |
|
|---|
| 55 |
template<typename Ty, int N> friend struct Writer; |
|---|
| 56 |
// error: function template partial specialization is not allowed |
|---|
| 57 |
// So I guess type partial specialization + member function will have to do... |
|---|
| 58 |
template<typename Ty, int N> |
|---|
| 59 |
struct Writer { |
|---|
| 60 |
static void write(std::ostream& OS, const Ty& Thing) { |
|---|
| 61 |
OS << Thing; |
|---|
| 62 |
} |
|---|
| 63 |
}; |
|---|
| 64 |
|
|---|
| 65 |
template<typename Ty> |
|---|
| 66 |
struct Writer<Ty, 1> { |
|---|
| 67 |
static void write(std::ostream& OS, const llvm::Type& Thing) { |
|---|
| 68 |
Stream::writeType(OS, Thing); |
|---|
| 69 |
} |
|---|
| 70 |
static void write(std::ostream& OS, const llvm::Value& Thing) { |
|---|
| 71 |
Stream::writeValue(OS, Thing); |
|---|
| 72 |
} |
|---|
| 73 |
}; |
|---|
| 74 |
|
|---|
| 75 |
// NOT IMPLEMENTED |
|---|
| 76 |
char sfinae_bait(const llvm::Type&); |
|---|
| 77 |
char sfinae_bait(const llvm::Value&); |
|---|
| 78 |
short sfinae_bait(...); |
|---|
| 79 |
}; |
|---|
| 80 |
|
|---|
| 81 |
namespace Logger |
|---|
| 82 |
{ |
|---|
| 83 |
void indent(); |
|---|
| 84 |
void undent(); |
|---|
| 85 |
Stream cout(); |
|---|
| 86 |
void println(const char* fmt, ...) IS_PRINTF(1); |
|---|
| 87 |
void print(const char* fmt, ...) IS_PRINTF(1); |
|---|
| 88 |
void enable(); |
|---|
| 89 |
void disable(); |
|---|
| 90 |
bool enabled(); |
|---|
| 91 |
|
|---|
| 92 |
void attention(Loc loc, const char* fmt, ...) IS_PRINTF(2); |
|---|
| 93 |
|
|---|
| 94 |
struct LoggerScope |
|---|
| 95 |
{ |
|---|
| 96 |
LoggerScope() |
|---|
| 97 |
{ |
|---|
| 98 |
Logger::indent(); |
|---|
| 99 |
} |
|---|
| 100 |
~LoggerScope() |
|---|
| 101 |
{ |
|---|
| 102 |
Logger::undent(); |
|---|
| 103 |
} |
|---|
| 104 |
}; |
|---|
| 105 |
} |
|---|
| 106 |
|
|---|
| 107 |
#define LOG_SCOPE Logger::LoggerScope _logscope; |
|---|
| 108 |
|
|---|
| 109 |
#define IF_LOG if (Logger::enabled()) |
|---|
| 110 |
|
|---|
| 111 |
#endif |
|---|