1 /* Internals of libgccjit: logging 2 Copyright (C) 2014-2015 Free Software Foundation, Inc. 3 Contributed by David Malcolm <dmalcolm@redhat.com>. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GCC is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #ifndef JIT_LOGGING_H 22 #define JIT_LOGGING_H 23 24 #include "jit-common.h" 25 26 namespace gcc { 27 28 namespace jit { 29 30 /* A gcc::jit::logger encapsulates a logging stream: a way to send 31 lines of pertinent information to a FILE *. */ 32 33 class logger 34 { 35 public: 36 logger (FILE *f_out, int flags, int verbosity); 37 ~logger (); 38 39 void incref (const char *reason); 40 void decref (const char *reason); 41 42 void log (const char *fmt, ...) 43 GNU_PRINTF(2, 3); 44 void log_va (const char *fmt, va_list ap) 45 GNU_PRINTF(2, 0); 46 47 void enter_scope (const char *scope_name); 48 void exit_scope (const char *scope_name); 49 50 private: 51 int m_refcount; 52 FILE *m_f_out; 53 int m_indent_level; 54 bool m_log_refcount_changes; 55 }; 56 57 /* The class gcc::jit::log_scope is an RAII-style class intended to make 58 it easy to notify a logger about entering and exiting the body of a 59 given function. */ 60 61 class log_scope 62 { 63 public: 64 log_scope (logger *logger, const char *name); 65 ~log_scope (); 66 67 private: 68 logger *m_logger; 69 const char *m_name; 70 }; 71 72 /* The constructor for gcc::jit::log_scope. 73 74 The normal case is that the logger is NULL, in which case this should 75 be largely a no-op. 76 77 If we do have a logger, notify it that we're entering the given scope. 78 We also need to hold a reference on it, to avoid a use-after-free 79 when logging the cleanup of the owner of the logger. */ 80 81 inline 82 log_scope::log_scope (logger *logger, const char *name) : 83 m_logger (logger), 84 m_name (name) 85 { 86 if (m_logger) 87 { 88 m_logger->incref ("log_scope ctor"); 89 m_logger->enter_scope (m_name); 90 } 91 } 92 93 /* The destructor for gcc::jit::log_scope; essentially the opposite of 94 the constructor. */ 95 96 inline 97 log_scope::~log_scope () 98 { 99 if (m_logger) 100 { 101 m_logger->exit_scope (m_name); 102 m_logger->decref ("log_scope dtor"); 103 } 104 } 105 106 /* A gcc::jit::log_user is something that potentially uses a 107 gcc::jit::logger (which could be NULL). 108 109 It is the base class for each of: 110 111 - class gcc::jit::recording::context 112 113 - class gcc::jit::playback::context 114 115 - class gcc::jit::tempdir 116 117 - class gcc::jit::result 118 119 The log_user class keeps the reference-count of a logger up-to-date. */ 120 121 class log_user 122 { 123 public: 124 log_user (logger *logger); 125 ~log_user (); 126 127 logger * get_logger () const { return m_logger; } 128 void set_logger (logger * logger); 129 130 void log (const char *fmt, ...) const 131 GNU_PRINTF(2, 3); 132 133 void enter_scope (const char *scope_name); 134 void exit_scope (const char *scope_name); 135 136 private: 137 logger *m_logger; 138 }; 139 140 /* A shortcut for calling log from a context/result, handling the common 141 case where the underlying logger is NULL via a no-op. */ 142 143 inline void 144 log_user::log (const char *fmt, ...) const 145 { 146 if (m_logger) 147 { 148 va_list ap; 149 va_start (ap, fmt); 150 m_logger->log_va (fmt, ap); 151 va_end (ap); 152 } 153 } 154 155 /* A shortcut for recording entry into a scope from a context/result, 156 handling the common case where the underlying logger is NULL via 157 a no-op. */ 158 159 inline void 160 log_user::enter_scope (const char *scope_name) 161 { 162 if (m_logger) 163 m_logger->enter_scope (scope_name); 164 } 165 166 /* A shortcut for recording exit from a scope from a context/result, 167 handling the common case where the underlying logger is NULL via 168 a no-op. */ 169 170 inline void 171 log_user::exit_scope (const char *scope_name) 172 { 173 if (m_logger) 174 m_logger->exit_scope (scope_name); 175 } 176 177 } // namespace gcc::jit 178 179 } // namespace gcc 180 181 /* If the given logger is non-NULL, log entry/exit of this scope to 182 it, identifying it using __PRETTY_FUNCTION__. */ 183 184 #define JIT_LOG_SCOPE(LOGGER) \ 185 gcc::jit::log_scope s (LOGGER, __PRETTY_FUNCTION__) 186 187 /* If the given logger is non-NULL, log entry/exit of this scope to 188 it, identifying it using __func__. */ 189 190 #define JIT_LOG_FUNC(LOGGER) \ 191 gcc::jit::log_scope s (LOGGER, __func__) 192 193 #endif /* JIT_LOGGING_H */ 194