145
|
1 /* Hierarchical log messages for the analyzer.
|
|
2 Copyright (C) 2014-2020 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 /* Adapted from jit-logging.h. */
|
|
22
|
|
23 #ifndef ANALYZER_LOGGING_H
|
|
24 #define ANALYZER_LOGGING_H
|
|
25
|
|
26 namespace ana {
|
|
27
|
|
28 /* A logger encapsulates a logging stream: a way to send
|
|
29 lines of pertinent information to a FILE *. */
|
|
30
|
|
31 class logger
|
|
32 {
|
|
33 public:
|
|
34 logger (FILE *f_out, int flags, int verbosity, const pretty_printer &reference_pp);
|
|
35 ~logger ();
|
|
36
|
|
37 void incref (const char *reason);
|
|
38 void decref (const char *reason);
|
|
39
|
|
40 void log (const char *fmt, ...)
|
|
41 ATTRIBUTE_GCC_DIAG(2, 3);
|
|
42 void log_va (const char *fmt, va_list *ap)
|
|
43 ATTRIBUTE_GCC_DIAG(2, 0);
|
|
44 void start_log_line ();
|
|
45 void log_partial (const char *fmt, ...)
|
|
46 ATTRIBUTE_GCC_DIAG(2, 3);
|
|
47 void log_va_partial (const char *fmt, va_list *ap)
|
|
48 ATTRIBUTE_GCC_DIAG(2, 0);
|
|
49 void end_log_line ();
|
|
50
|
|
51 void enter_scope (const char *scope_name);
|
|
52 void enter_scope (const char *scope_name, const char *fmt, va_list *ap)
|
|
53 ATTRIBUTE_GCC_DIAG(3, 0);
|
|
54 void exit_scope (const char *scope_name);
|
|
55
|
|
56 pretty_printer *get_printer () const { return m_pp; }
|
|
57 FILE *get_file () const { return m_f_out; }
|
|
58
|
|
59 private:
|
|
60 DISABLE_COPY_AND_ASSIGN (logger);
|
|
61
|
|
62 int m_refcount;
|
|
63 FILE *m_f_out;
|
|
64 int m_indent_level;
|
|
65 bool m_log_refcount_changes;
|
|
66 pretty_printer *m_pp;
|
|
67 };
|
|
68
|
|
69 /* The class log_scope is an RAII-style class intended to make
|
|
70 it easy to notify a logger about entering and exiting the body of a
|
|
71 given function. */
|
|
72
|
|
73 class log_scope
|
|
74 {
|
|
75 public:
|
|
76 log_scope (logger *logger, const char *name);
|
|
77 log_scope (logger *logger, const char *name, const char *fmt, ...)
|
|
78 ATTRIBUTE_GCC_DIAG(4, 5);
|
|
79 ~log_scope ();
|
|
80
|
|
81 private:
|
|
82 DISABLE_COPY_AND_ASSIGN (log_scope);
|
|
83
|
|
84 logger *m_logger;
|
|
85 const char *m_name;
|
|
86 };
|
|
87
|
|
88 /* The constructor for log_scope.
|
|
89
|
|
90 The normal case is that the logger is NULL, in which case this should
|
|
91 be largely a no-op.
|
|
92
|
|
93 If we do have a logger, notify it that we're entering the given scope.
|
|
94 We also need to hold a reference on it, to avoid a use-after-free
|
|
95 when logging the cleanup of the owner of the logger. */
|
|
96
|
|
97 inline
|
|
98 log_scope::log_scope (logger *logger, const char *name) :
|
|
99 m_logger (logger),
|
|
100 m_name (name)
|
|
101 {
|
|
102 if (m_logger)
|
|
103 {
|
|
104 m_logger->incref ("log_scope ctor");
|
|
105 m_logger->enter_scope (m_name);
|
|
106 }
|
|
107 }
|
|
108
|
|
109 inline
|
|
110 log_scope::log_scope (logger *logger, const char *name, const char *fmt, ...):
|
|
111 m_logger (logger),
|
|
112 m_name (name)
|
|
113 {
|
|
114 if (m_logger)
|
|
115 {
|
|
116 m_logger->incref ("log_scope ctor");
|
|
117 va_list ap;
|
|
118 va_start (ap, fmt);
|
|
119 m_logger->enter_scope (m_name, fmt, &ap);
|
|
120 va_end (ap);
|
|
121 }
|
|
122 }
|
|
123
|
|
124
|
|
125 /* The destructor for log_scope; essentially the opposite of
|
|
126 the constructor. */
|
|
127
|
|
128 inline
|
|
129 log_scope::~log_scope ()
|
|
130 {
|
|
131 if (m_logger)
|
|
132 {
|
|
133 m_logger->exit_scope (m_name);
|
|
134 m_logger->decref ("log_scope dtor");
|
|
135 }
|
|
136 }
|
|
137
|
|
138 /* A log_user is something that potentially uses a logger (which could be NULL).
|
|
139
|
|
140 The log_user class keeps the reference-count of a logger up-to-date. */
|
|
141
|
|
142 class log_user
|
|
143 {
|
|
144 public:
|
|
145 log_user (logger *logger);
|
|
146 ~log_user ();
|
|
147
|
|
148 logger * get_logger () const { return m_logger; }
|
|
149 void set_logger (logger * logger);
|
|
150
|
|
151 void log (const char *fmt, ...) const
|
|
152 ATTRIBUTE_GCC_DIAG(2, 3);
|
|
153
|
|
154 void start_log_line () const;
|
|
155 void end_log_line () const;
|
|
156
|
|
157 void enter_scope (const char *scope_name);
|
|
158 void exit_scope (const char *scope_name);
|
|
159
|
|
160 pretty_printer *get_logger_pp () const
|
|
161 {
|
|
162 gcc_assert (m_logger);
|
|
163 return m_logger->get_printer ();
|
|
164 }
|
|
165
|
|
166 FILE *get_logger_file () const
|
|
167 {
|
|
168 if (m_logger == NULL)
|
|
169 return NULL;
|
|
170 return m_logger->get_file ();
|
|
171 }
|
|
172
|
|
173 private:
|
|
174 DISABLE_COPY_AND_ASSIGN (log_user);
|
|
175
|
|
176 logger *m_logger;
|
|
177 };
|
|
178
|
|
179 /* A shortcut for calling log from a log_user, handling the common
|
|
180 case where the underlying logger is NULL via a no-op. */
|
|
181
|
|
182 inline void
|
|
183 log_user::log (const char *fmt, ...) const
|
|
184 {
|
|
185 if (m_logger)
|
|
186 {
|
|
187 va_list ap;
|
|
188 va_start (ap, fmt);
|
|
189 m_logger->log_va (fmt, &ap);
|
|
190 va_end (ap);
|
|
191 }
|
|
192 }
|
|
193
|
|
194 /* A shortcut for starting a log line from a log_user,
|
|
195 handling the common case where the underlying logger is NULL via
|
|
196 a no-op. */
|
|
197
|
|
198 inline void
|
|
199 log_user::start_log_line () const
|
|
200 {
|
|
201 if (m_logger)
|
|
202 m_logger->start_log_line ();
|
|
203 }
|
|
204
|
|
205 /* A shortcut for ending a log line from a log_user,
|
|
206 handling the common case where the underlying logger is NULL via
|
|
207 a no-op. */
|
|
208
|
|
209 inline void
|
|
210 log_user::end_log_line () const
|
|
211 {
|
|
212 if (m_logger)
|
|
213 m_logger->end_log_line ();
|
|
214 }
|
|
215
|
|
216 /* A shortcut for recording entry into a scope from a log_user,
|
|
217 handling the common case where the underlying logger is NULL via
|
|
218 a no-op. */
|
|
219
|
|
220 inline void
|
|
221 log_user::enter_scope (const char *scope_name)
|
|
222 {
|
|
223 if (m_logger)
|
|
224 m_logger->enter_scope (scope_name);
|
|
225 }
|
|
226
|
|
227 /* A shortcut for recording exit from a scope from a log_user,
|
|
228 handling the common case where the underlying logger is NULL via
|
|
229 a no-op. */
|
|
230
|
|
231 inline void
|
|
232 log_user::exit_scope (const char *scope_name)
|
|
233 {
|
|
234 if (m_logger)
|
|
235 m_logger->exit_scope (scope_name);
|
|
236 }
|
|
237
|
|
238 /* If the given logger is non-NULL, log entry/exit of this scope to
|
|
239 it, identifying it using __PRETTY_FUNCTION__. */
|
|
240
|
|
241 #define LOG_SCOPE(LOGGER) \
|
|
242 log_scope s (LOGGER, __PRETTY_FUNCTION__)
|
|
243
|
|
244 /* If the given logger is non-NULL, log entry/exit of this scope to
|
|
245 it, identifying it using __func__. */
|
|
246
|
|
247 #define LOG_FUNC(LOGGER) \
|
|
248 log_scope s (LOGGER, __func__)
|
|
249
|
|
250 #define LOG_FUNC_1(LOGGER, FMT, A0) \
|
|
251 log_scope s (LOGGER, __func__, FMT, A0)
|
|
252
|
|
253 #define LOG_FUNC_2(LOGGER, FMT, A0, A1) \
|
|
254 log_scope s (LOGGER, __func__, FMT, A0, A1)
|
|
255
|
|
256 #define LOG_FUNC_3(LOGGER, FMT, A0, A1, A2) \
|
|
257 log_scope s (LOGGER, __func__, FMT, A0, A1, A2)
|
|
258
|
|
259 #define LOG_FUNC_4(LOGGER, FMT, A0, A1, A2, A3) \
|
|
260 log_scope s (LOGGER, __func__, FMT, A0, A1, A2, A3)
|
|
261
|
|
262 } // namespace ana
|
|
263
|
|
264 #endif /* ANALYZER_LOGGING_H */
|