1/* Internals of libgccjit: logging 2 Copyright (C) 2014-2022 Free Software Foundation, Inc. 3 Contributed by David Malcolm <dmalcolm@redhat.com>. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it 8under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along 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 28namespace gcc { 29 30namespace 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 37logger::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 53logger::~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 62void 63logger::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 74void 75logger::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 88void 89logger::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 104void 105logger::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 118void 119logger::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 128void 129logger::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 142log_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 150log_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 159void 160log_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