Branch data Line data Source code
1 : : /* Debugging code for logging what the diagnostics subsystem is doing.
2 : : Copyright (C) 2025 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 under
8 : : the terms of the GNU General Public License as published by the Free
9 : : Software Foundation; either version 3, or (at your option) any later
10 : : version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : : 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 GCC_DIAGNOSTICS_LOGGING_H
22 : : #define GCC_DIAGNOSTICS_LOGGING_H
23 : :
24 : : #include "diagnostics/output-file.h"
25 : : #include "diagnostics/option-id.h"
26 : : #include "diagnostics/kinds.h"
27 : :
28 : : namespace diagnostics {
29 : :
30 : : namespace logging {
31 : :
32 : : /* A class for emitting a temporal log of what the diagnostics subsystem
33 : : is doing, for debugging.
34 : : We can't use pretty_printer here as we could potentially be debugging
35 : : pretty-printing itself. */
36 : :
37 : 0 : class logger
38 : : {
39 : : public:
40 : : logger (output_file outfile);
41 : :
42 : : /* High-level functions that emit a line of text. */
43 : : void log_printf (const char *fmt, ...)
44 : : __attribute__ ((__format__ (printf, 2, 3)));
45 : : void log_bool_return (const char *function_name, bool retval);
46 : :
47 : : /* Lower-level functions for building up a line of text. */
48 : : void emit_indent () const;
49 : : void emit_newline () const;
50 : :
51 : 0 : FILE *get_stream () const
52 : : {
53 : 0 : return m_outfile.get_open_file ();
54 : : }
55 : :
56 : 0 : int get_indent () const { return m_log_depth * 2; }
57 : :
58 : 0 : void inc_depth () { m_log_depth++; }
59 : 0 : void dec_depth () { m_log_depth--; }
60 : :
61 : : private:
62 : : output_file m_outfile;
63 : : int m_log_depth;
64 : : };
65 : :
66 : : /* RAII class for pushing/popping depth within a logger. */
67 : :
68 : : class auto_inc_depth
69 : : {
70 : : public:
71 : 200964294 : auto_inc_depth (logger *log)
72 : 200964294 : : m_logger (log)
73 : : {
74 : 200964294 : if (m_logger)
75 : 0 : m_logger->inc_depth ();
76 : : }
77 : 300308715 : ~auto_inc_depth ()
78 : : {
79 : 300308715 : if (m_logger)
80 : 0 : m_logger->dec_depth ();
81 : : }
82 : :
83 : : private:
84 : : logger *m_logger;
85 : : };
86 : :
87 : : /* Class for debugging function call parameters. */
88 : :
89 : : class log_function_params
90 : : {
91 : : public:
92 : 198089739 : log_function_params (logger *logger_, const char *name)
93 : 198089739 : : m_logger (logger_),
94 : 198089739 : m_first_param (true)
95 : : {
96 : 198089739 : if (m_logger)
97 : : {
98 : 0 : m_logger->emit_indent ();
99 : 0 : fprintf (m_logger->get_stream (), "%s (", name);
100 : : }
101 : 198089739 : }
102 : 198089739 : ~log_function_params ()
103 : : {
104 : 198089739 : if (m_logger)
105 : : {
106 : 0 : fprintf (m_logger->get_stream (), ")");
107 : 0 : m_logger->emit_newline ();
108 : : }
109 : 198089739 : }
110 : :
111 : : log_function_params &
112 : 185514798 : log_param_string (const char *name, const char *value)
113 : : {
114 : 185514798 : if (m_logger)
115 : : {
116 : 0 : add_any_comma ();
117 : 0 : fprintf (m_logger->get_stream (), "%s: \"%s\"", name, value);
118 : : }
119 : 185514798 : return *this;
120 : : }
121 : :
122 : : log_function_params &
123 : 17896932 : log_param_location_t (const char *name, location_t value)
124 : : {
125 : 17896932 : if (m_logger)
126 : : {
127 : 0 : add_any_comma ();
128 : 0 : fprintf (m_logger->get_stream (),
129 : : "%s: " HOST_SIZE_T_PRINT_HEX,
130 : : name, (fmt_size_t)value);
131 : : }
132 : 17896932 : return *this;
133 : : }
134 : :
135 : : log_function_params &
136 : 34469 : log_param_rich_location (const char *name, const rich_location *richloc)
137 : : {
138 : 34469 : if (m_logger)
139 : : {
140 : 0 : add_any_comma ();
141 : 0 : fprintf (m_logger->get_stream (),
142 : : "%s: %p",
143 : : name, const_cast<void *> ((const void *)richloc));
144 : : }
145 : 34469 : return *this;
146 : : }
147 : :
148 : : log_function_params &
149 : 189909860 : log_param_option_id (const char *name, diagnostics::option_id value)
150 : : {
151 : 189909860 : if (m_logger)
152 : : {
153 : 0 : add_any_comma ();
154 : 0 : fprintf (m_logger->get_stream (), "%s: %i", name, value.m_idx);
155 : : }
156 : 189909860 : return *this;
157 : : }
158 : :
159 : : log_function_params &
160 : 97389613 : log_param_kind (const char *name, enum diagnostics::kind value)
161 : : {
162 : 97389613 : if (m_logger)
163 : : {
164 : 0 : add_any_comma ();
165 : 0 : fprintf (m_logger->get_stream (), "%s: %s",
166 : : name, get_debug_string_for_kind (value));
167 : : }
168 : 97389613 : return *this;
169 : : }
170 : :
171 : : log_function_params &
172 : 23842 : log_param_uhwi (const char *name, unsigned HOST_WIDE_INT value)
173 : : {
174 : 23842 : if (m_logger)
175 : : {
176 : 0 : add_any_comma ();
177 : 0 : fprintf (m_logger->get_stream (),
178 : : "%s: " HOST_WIDE_INT_PRINT_DEC,
179 : : name, value);
180 : : }
181 : 23842 : return *this;
182 : : }
183 : :
184 : : log_function_params &
185 : 23842 : log_params_n_gmsgids (unsigned HOST_WIDE_INT n,
186 : : const char *singular_gmsgid,
187 : : const char *plural_gmsgid)
188 : : {
189 : 23842 : return log_param_uhwi ("n", n)
190 : 23842 : .log_param_string ("singular_gmsgid", singular_gmsgid)
191 : 23842 : .log_param_string ("plural_gmsgid", plural_gmsgid);
192 : : }
193 : :
194 : : private:
195 : : void
196 : 0 : add_any_comma ()
197 : : {
198 : 0 : gcc_assert (m_logger);
199 : 0 : if (m_first_param)
200 : 0 : m_first_param = false;
201 : : else
202 : 0 : fprintf (m_logger->get_stream (), ", ");
203 : 0 : }
204 : :
205 : : logger *m_logger;
206 : : bool m_first_param;
207 : : };
208 : :
209 : : } // namespace logging
210 : : } // namespace diagnostics
211 : :
212 : : /* Various macros for logging a formatted line, and indenting
213 : : further log messages within a scope. */
214 : :
215 : : #define DIAGNOSTICS_LOG_SCOPE_PRINTF0(LOGGER, FMT) \
216 : : if (LOGGER) \
217 : : (LOGGER)->log_printf ((FMT)); \
218 : : diagnostics::logging::auto_inc_depth depth_sentinel (LOGGER);
219 : :
220 : : #define DIAGNOSTICS_LOG_SCOPE_PRINTF1(LOGGER, FMT, ARG0) \
221 : : if (LOGGER) \
222 : : (LOGGER)->log_printf ((FMT), (ARG0)); \
223 : : diagnostics::logging::auto_inc_depth depth_sentinel (LOGGER);
224 : :
225 : : #define DIAGNOSTICS_LOG_SCOPE_PRINTF2(LOGGER, FMT, ARG0, ARG1) \
226 : : if (LOGGER) \
227 : : (LOGGER)->log_printf ((FMT), (ARG0), (ARG1)); \
228 : : diagnostics::logging::auto_inc_depth depth_sentinel (LOGGER);
229 : :
230 : : #endif /* ! GCC_DIAGNOSTICS_LOGGING_H */
|