]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/libgcov-interface.c
tree-optimization/95495 - use SLP_TREE_REPRESENTATIVE in assertion
[thirdparty/gcc.git] / libgcc / libgcov-interface.c
CommitLineData
d6d3f033
RX
1/* Routines required for instrumenting a program. */
2/* Compile this one with gcc. */
8d9254fc 3/* Copyright (C) 1989-2020 Free Software Foundation, Inc.
d6d3f033
RX
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
25
40d6b753 26#include "libgcov.h"
d6d3f033
RX
27#include "gthr.h"
28
d6d3f033
RX
29#if defined(inhibit_libc)
30
d6d3f033
RX
31#ifdef L_gcov_reset
32void __gcov_reset (void) {}
33#endif
34
35#ifdef L_gcov_dump
36void __gcov_dump (void) {}
37#endif
38
39#else
40
811b7636 41extern __gthread_mutex_t __gcov_mx ATTRIBUTE_HIDDEN;
d6d3f033 42
d39f7dc8 43#ifdef L_gcov_lock_unlock
d6d3f033 44#ifdef __GTHREAD_MUTEX_INIT
811b7636 45__gthread_mutex_t __gcov_mx = __GTHREAD_MUTEX_INIT;
d6d3f033
RX
46#define init_mx_once()
47#else
811b7636 48__gthread_mutex_t __gcov_mx;
d6d3f033
RX
49
50static void
51init_mx (void)
52{
811b7636 53 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_mx);
d6d3f033 54}
b98a872b 55
d6d3f033
RX
56static void
57init_mx_once (void)
58{
59 static __gthread_once_t once = __GTHREAD_ONCE_INIT;
60 __gthread_once (&once, init_mx);
61}
62#endif
63
d39f7dc8
ML
64/* Lock critical section for __gcov_dump and __gcov_reset functions. */
65
66void
67__gcov_lock (void)
68{
69 init_mx_once ();
811b7636 70 __gthread_mutex_lock (&__gcov_mx);
d39f7dc8
ML
71}
72
73/* Unlock critical section for __gcov_dump and __gcov_reset functions. */
74
75void
76__gcov_unlock (void)
77{
811b7636 78 __gthread_mutex_unlock (&__gcov_mx);
d39f7dc8
ML
79}
80#endif
81
d6d3f033
RX
82#ifdef L_gcov_reset
83
4303c581
NS
84/* Reset all counters to zero. */
85
86static void
87gcov_clear (const struct gcov_info *list)
88{
89 const struct gcov_info *gi_ptr;
90
91 for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
92 {
93 unsigned f_ix;
94
95 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
96 {
97 unsigned t_ix;
98 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
99
100 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
101 continue;
102 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
103 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
104 {
105 if (!gi_ptr->merge[t_ix])
106 continue;
107
108 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
109 ci_ptr++;
110 }
111 }
112 }
113}
114
d6d3f033
RX
115/* Function that can be called from application to reset counters to zero,
116 in order to collect profile in region of interest. */
117
118void
b20ee094 119__gcov_reset_int (void)
d6d3f033 120{
cadb2b96
NS
121 struct gcov_root *root;
122
123 /* If we're compatible with the master, iterate over everything,
124 otherise just do us. */
125 for (root = __gcov_master.version == GCOV_VERSION
126 ? __gcov_master.root : &__gcov_root; root; root = root->next)
127 {
128 gcov_clear (root->list);
129 root->dumped = 0;
130 }
d6d3f033
RX
131}
132
d39f7dc8
ML
133/* Exported function __gcov_reset. */
134
135void
136__gcov_reset (void)
137{
138 __gcov_lock ();
139
140 __gcov_reset_int ();
141
142 __gcov_unlock ();
143}
b20ee094 144
d6d3f033
RX
145#endif /* L_gcov_reset */
146
147#ifdef L_gcov_dump
d6d3f033
RX
148/* Function that can be called from application to write profile collected
149 so far, in order to collect profile in region of interest. */
150
151void
cadb2b96 152__gcov_dump_int (void)
d6d3f033 153{
cadb2b96
NS
154 struct gcov_root *root;
155
156 /* If we're compatible with the master, iterate over everything,
157 otherise just do us. */
158 for (root = __gcov_master.version == GCOV_VERSION
159 ? __gcov_master.root : &__gcov_root; root; root = root->next)
160 __gcov_dump_one (root);
d6d3f033
RX
161}
162
d39f7dc8
ML
163/* Exported function __gcov_dump. */
164
165void
166__gcov_dump (void)
167{
168 __gcov_lock ();
169
170 __gcov_dump_int ();
171
172 __gcov_unlock ();
173}
cadb2b96 174
d6d3f033
RX
175#endif /* L_gcov_dump */
176
d6d3f033 177#ifdef L_gcov_fork
c0532db4
ML
178/* A wrapper for the fork function. We reset counters in the child
179 so that they are not counted twice. */
d6d3f033
RX
180
181pid_t
182__gcov_fork (void)
183{
184 pid_t pid;
d6d3f033
RX
185 pid = fork ();
186 if (pid == 0)
c0532db4 187 {
811b7636 188 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_mx);
c0532db4
ML
189 /* We do not need locking as we are the only thread in the child. */
190 __gcov_reset_int ();
191 }
d6d3f033
RX
192 return pid;
193}
194#endif
195
196#ifdef L_gcov_execl
cadb2b96
NS
197/* A wrapper for the execl function. Flushes the accumulated
198 profiling data, so that they are not lost. */
d6d3f033
RX
199
200int
201__gcov_execl (const char *path, char *arg, ...)
202{
203 va_list ap, aq;
204 unsigned i, length;
205 char **args;
206
c0532db4
ML
207 /* Dump counters only, they will be lost after exec. */
208 __gcov_dump ();
d6d3f033
RX
209
210 va_start (ap, arg);
211 va_copy (aq, ap);
212
213 length = 2;
214 while (va_arg (ap, char *))
215 length++;
216 va_end (ap);
217
218 args = (char **) alloca (length * sizeof (void *));
219 args[0] = arg;
220 for (i = 1; i < length; i++)
221 args[i] = va_arg (aq, char *);
222 va_end (aq);
223
c0532db4
ML
224 int ret = execv (path, args);
225 /* We reach this code only when execv fails, reset counter then here. */
226 __gcov_reset ();
227 return ret;
d6d3f033
RX
228}
229#endif
230
231#ifdef L_gcov_execlp
b98a872b
NS
232/* A wrapper for the execlp function. Flushes the accumulated
233 profiling data, so that they are not lost. */
d6d3f033
RX
234
235int
236__gcov_execlp (const char *path, char *arg, ...)
237{
238 va_list ap, aq;
239 unsigned i, length;
240 char **args;
241
c0532db4
ML
242 /* Dump counters only, they will be lost after exec. */
243 __gcov_dump ();
d6d3f033
RX
244
245 va_start (ap, arg);
246 va_copy (aq, ap);
247
248 length = 2;
249 while (va_arg (ap, char *))
250 length++;
251 va_end (ap);
252
253 args = (char **) alloca (length * sizeof (void *));
254 args[0] = arg;
255 for (i = 1; i < length; i++)
256 args[i] = va_arg (aq, char *);
257 va_end (aq);
258
c0532db4
ML
259 int ret = execvp (path, args);
260 /* We reach this code only when execv fails, reset counter then here. */
261 __gcov_reset ();
262 return ret;
d6d3f033
RX
263}
264#endif
265
266#ifdef L_gcov_execle
b98a872b
NS
267/* A wrapper for the execle function. Flushes the accumulated
268 profiling data, so that they are not lost. */
d6d3f033
RX
269
270int
271__gcov_execle (const char *path, char *arg, ...)
272{
273 va_list ap, aq;
274 unsigned i, length;
275 char **args;
276 char **envp;
277
c0532db4
ML
278 /* Dump counters only, they will be lost after exec. */
279 __gcov_dump ();
d6d3f033
RX
280
281 va_start (ap, arg);
282 va_copy (aq, ap);
283
284 length = 2;
285 while (va_arg (ap, char *))
286 length++;
287 va_end (ap);
288
289 args = (char **) alloca (length * sizeof (void *));
290 args[0] = arg;
291 for (i = 1; i < length; i++)
292 args[i] = va_arg (aq, char *);
293 envp = va_arg (aq, char **);
294 va_end (aq);
295
c0532db4
ML
296 int ret = execve (path, args, envp);
297 /* We reach this code only when execv fails, reset counter then here. */
298 __gcov_reset ();
299 return ret;
d6d3f033
RX
300}
301#endif
302
303#ifdef L_gcov_execv
b98a872b
NS
304/* A wrapper for the execv function. Flushes the accumulated
305 profiling data, so that they are not lost. */
d6d3f033
RX
306
307int
308__gcov_execv (const char *path, char *const argv[])
309{
c0532db4
ML
310 /* Dump counters only, they will be lost after exec. */
311 __gcov_dump ();
312 int ret = execv (path, argv);
313 /* We reach this code only when execv fails, reset counter then here. */
314 __gcov_reset ();
315 return ret;
d6d3f033
RX
316}
317#endif
318
319#ifdef L_gcov_execvp
b98a872b
NS
320/* A wrapper for the execvp function. Flushes the accumulated
321 profiling data, so that they are not lost. */
d6d3f033
RX
322
323int
324__gcov_execvp (const char *path, char *const argv[])
325{
c0532db4
ML
326 /* Dump counters only, they will be lost after exec. */
327 __gcov_dump ();
328 int ret = execvp (path, argv);
329 /* We reach this code only when execv fails, reset counter then here. */
330 __gcov_reset ();
331 return ret;
d6d3f033
RX
332}
333#endif
334
335#ifdef L_gcov_execve
b98a872b
NS
336/* A wrapper for the execve function. Flushes the accumulated
337 profiling data, so that they are not lost. */
d6d3f033
RX
338
339int
340__gcov_execve (const char *path, char *const argv[], char *const envp[])
341{
c0532db4
ML
342 /* Dump counters only, they will be lost after exec. */
343 __gcov_dump ();
344 int ret = execve (path, argv, envp);
345 /* We reach this code only when execv fails, reset counter then here. */
346 __gcov_reset ();
347 return ret;
d6d3f033
RX
348}
349#endif
350#endif /* inhibit_libc */