1 /* Internals of libgccjit: logging 2 Copyright (C) 2014-2019 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 #include "config.h" 22 #include "system.h" 23 #include "coretypes.h" 24 #include "toplev.h" /* for print_version */ 25 26 #include "jit-logging.h" 27 28 namespace gcc { 29 30 namespace jit { 31 32 /* Implementation of class gcc::jit::logger. */ 33 34 /* The constructor for gcc::jit::logger, used by 35 gcc_jit_context_set_logfile. */ 36 37 logger::logger (FILE *f_out, 38 int, /* flags */ 39 int /* verbosity */) : 40 m_refcount (0), 41 m_f_out (f_out), 42 m_indent_level (0), 43 m_log_refcount_changes (false) 44 { 45 /* Begin the log by writing the GCC version. */ 46 print_version (f_out, "JIT:", false); 47 } 48 49 /* The destructor for gcc::jit::logger, invoked via 50 the decref method when the refcount hits zero. 51 Note that we do not close the underlying FILE * (m_f_out). */ 52 53 logger::~logger () 54 { 55 /* This should be the last message emitted. */ 56 log ("%s", __PRETTY_FUNCTION__); 57 gcc_assert (m_refcount == 0); 58 } 59 60 /* Increment the reference count of the gcc::jit::logger. */ 61 62 void 63 logger::incref (const char *reason) 64 { 65 m_refcount++; 66 if (m_log_refcount_changes) 67 log ("%s: reason: %s refcount now %i ", 68 __PRETTY_FUNCTION__, reason, m_refcount); 69 } 70 71 /* Decrement the reference count of the gcc::jit::logger, 72 deleting it if nothing is referring to it. */ 73 74 void 75 logger::decref (const char *reason) 76 { 77 gcc_assert (m_refcount > 0); 78 --m_refcount; 79 if (m_log_refcount_changes) 80 log ("%s: reason: %s refcount now %i", 81 __PRETTY_FUNCTION__, reason, m_refcount); 82 if (m_refcount == 0) 83 delete this; 84 } 85 86 /* Write a formatted message to the log, by calling the log_va method. */ 87 88 void 89 logger::log (const char *fmt, ...) 90 { 91 va_list ap; 92 va_start (ap, fmt); 93 log_va (fmt, ap); 94 va_end (ap); 95 } 96 97 /* Write an indented line to the log file. 98 99 We explicitly flush after each line: if something crashes the process, 100 we want the logfile/stream to contain the most up-to-date hint about the 101 last thing that was happening, without it being hidden in an in-process 102 buffer. */ 103 104 void 105 logger::log_va (const char *fmt, va_list ap) 106 { 107 fprintf (m_f_out, "JIT: "); 108 for (int i = 0; i < m_indent_level; i++) 109 fputc (' ', m_f_out); 110 vfprintf (m_f_out, fmt, ap); 111 fprintf (m_f_out, "\n"); 112 fflush (m_f_out); 113 } 114 115 /* Record the entry within a particular scope, indenting subsequent 116 log lines accordingly. */ 117 118 void 119 logger::enter_scope (const char *scope_name) 120 { 121 log ("entering: %s", scope_name); 122 m_indent_level += 1; 123 } 124 125 /* Record the exit from a particular scope, restoring the indent level to 126 before the scope was entered. */ 127 128 void 129 logger::exit_scope (const char *scope_name) 130 { 131 if (m_indent_level) 132 m_indent_level -= 1; 133 else 134 log ("(mismatching indentation)"); 135 log ("exiting: %s", scope_name); 136 } 137 138 /* Implementation of class gcc::jit::log_user. */ 139 140 /* The constructor for gcc::jit::log_user. */ 141 142 log_user::log_user (logger *logger) : m_logger (logger) 143 { 144 if (m_logger) 145 m_logger->incref("log_user ctor"); 146 } 147 148 /* The destructor for gcc::jit::log_user. */ 149 150 log_user::~log_user () 151 { 152 if (m_logger) 153 m_logger->decref("log_user dtor"); 154 } 155 156 /* Set the logger for a gcc::jit::log_user, managing the reference counts 157 of the old and new logger (either of which might be NULL). */ 158 159 void 160 log_user::set_logger (logger *logger) 161 { 162 if (logger) 163 logger->incref ("log_user::set_logger"); 164 if (m_logger) 165 m_logger->decref ("log_user::set_logger"); 166 m_logger = logger; 167 } 168 169 } // namespace gcc::jit 170 171 } // namespace gcc 172