]>
Commit | Line | Data |
---|---|---|
3072d30e | 1 | /* Debug counter for debugging support |
fbd26352 | 2 | Copyright (C) 2006-2019 Free Software Foundation, Inc. |
3072d30e | 3 | |
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify it under | |
7 | the terms of the GNU General Public License as published by the Free | |
8c4c00c1 | 8 | Software Foundation; either version 3, or (at your option) any later |
3072d30e | 9 | version. |
10 | ||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
8c4c00c1 | 17 | along with GCC; see the file COPYING3. If not see |
48e1416a | 18 | <http://www.gnu.org/licenses/>. |
3072d30e | 19 | |
20 | See dbgcnt.def for usage information. */ | |
21 | ||
22 | #include "config.h" | |
23 | #include "system.h" | |
24 | #include "coretypes.h" | |
0b205f4c | 25 | #include "diagnostic-core.h" |
b9ed1410 | 26 | #include "dumpfile.h" |
3072d30e | 27 | |
28 | #include "dbgcnt.h" | |
29 | ||
30 | struct string2counter_map { | |
31 | const char *name; | |
32 | enum debug_counter counter; | |
33 | }; | |
34 | ||
35 | #define DEBUG_COUNTER(a) { #a , a }, | |
36 | ||
37 | static struct string2counter_map map[debug_counter_number_of_counters] = | |
38 | { | |
39 | #include "dbgcnt.def" | |
40 | }; | |
41 | #undef DEBUG_COUNTER | |
42 | ||
43 | #define DEBUG_COUNTER(a) UINT_MAX, | |
795785e1 | 44 | static unsigned int limit_high[debug_counter_number_of_counters] = |
3072d30e | 45 | { |
46 | #include "dbgcnt.def" | |
47 | }; | |
48 | #undef DEBUG_COUNTER | |
49 | ||
795785e1 | 50 | static unsigned int limit_low[debug_counter_number_of_counters]; |
51 | ||
3072d30e | 52 | static unsigned int count[debug_counter_number_of_counters]; |
53 | ||
54 | bool | |
55 | dbg_cnt_is_enabled (enum debug_counter index) | |
56 | { | |
795785e1 | 57 | unsigned v = count[index]; |
58 | return v > limit_low[index] && v <= limit_high[index]; | |
3072d30e | 59 | } |
60 | ||
c6ab3411 | 61 | static void |
62 | print_limit_reach (const char *counter, int limit, bool upper_p) | |
63 | { | |
64 | char buffer[128]; | |
65 | sprintf (buffer, "***dbgcnt: %s limit %d reached for %s.***\n", | |
66 | upper_p ? "upper" : "lower", limit, counter); | |
67 | fputs (buffer, stderr); | |
68 | if (dump_file) | |
69 | fputs (buffer, dump_file); | |
70 | } | |
71 | ||
3072d30e | 72 | bool |
73 | dbg_cnt (enum debug_counter index) | |
74 | { | |
75 | count[index]++; | |
795785e1 | 76 | |
c6ab3411 | 77 | /* Do not print the info for default lower limit. */ |
78 | if (count[index] == limit_low[index] && limit_low[index] > 0) | |
79 | print_limit_reach (map[index].name, limit_low[index], false); | |
80 | else if (count[index] == limit_high[index]) | |
81 | print_limit_reach (map[index].name, limit_high[index], true); | |
bf1f8fbc | 82 | |
3072d30e | 83 | return dbg_cnt_is_enabled (index); |
84 | } | |
85 | ||
3072d30e | 86 | static void |
795785e1 | 87 | dbg_cnt_set_limit_by_index (enum debug_counter index, int low, int high) |
3072d30e | 88 | { |
795785e1 | 89 | limit_low[index] = low; |
90 | limit_high[index] = high; | |
3072d30e | 91 | |
795785e1 | 92 | fprintf (stderr, "dbg_cnt '%s' set to %d-%d\n", map[index].name, low, high); |
3072d30e | 93 | } |
94 | ||
d2153a46 | 95 | static bool |
795785e1 | 96 | dbg_cnt_set_limit_by_name (const char *name, int low, int high) |
3072d30e | 97 | { |
795785e1 | 98 | if (high < low) |
99 | { | |
2f6d557f | 100 | error ("%<-fdbg-cnt=%s:%d:%d%> has smaller upper limit than the lower", |
795785e1 | 101 | name, low, high); |
102 | return false; | |
103 | } | |
104 | ||
105 | if (low < 0) | |
106 | { | |
2f6d557f | 107 | error ("Lower limit %d of %<-fdbg-cnt=%s%> must be a non-negative " |
108 | "number", low, name); | |
795785e1 | 109 | return false; |
110 | } | |
111 | ||
112 | if (high < 0) | |
113 | { | |
2f6d557f | 114 | error ("Upper limit %d of %<-fdbg-cnt=%s%> must be a non-negative " |
115 | "number", high, name); | |
795785e1 | 116 | return false; |
117 | } | |
118 | ||
3072d30e | 119 | int i; |
120 | for (i = debug_counter_number_of_counters - 1; i >= 0; i--) | |
795785e1 | 121 | if (strcmp (map[i].name, name) == 0) |
3072d30e | 122 | break; |
123 | ||
124 | if (i < 0) | |
d2153a46 | 125 | return false; |
3072d30e | 126 | |
795785e1 | 127 | dbg_cnt_set_limit_by_index ((enum debug_counter) i, low, high); |
d2153a46 | 128 | return true; |
3072d30e | 129 | } |
130 | ||
d2153a46 | 131 | |
132 | /* Process a single "name:value" pair. | |
133 | Returns NULL if there's no valid pair is found. | |
134 | Otherwise returns a pointer to the end of the pair. */ | |
135 | ||
795785e1 | 136 | static bool |
d2153a46 | 137 | dbg_cnt_process_single_pair (const char *arg) |
3072d30e | 138 | { |
795785e1 | 139 | char *str = xstrdup (arg); |
140 | char *name = strtok (str, ":"); | |
141 | char *value1 = strtok (NULL, ":"); | |
142 | char *value2 = strtok (NULL, ":"); | |
143 | ||
144 | int high, low; | |
145 | ||
146 | if (value1 == NULL) | |
f8e5c21b | 147 | return false; |
795785e1 | 148 | |
149 | if (value2 == NULL) | |
150 | { | |
151 | low = 0; | |
152 | high = strtol (value1, NULL, 10); | |
153 | } | |
154 | else | |
155 | { | |
156 | low = strtol (value1, NULL, 10); | |
157 | high = strtol (value2, NULL, 10); | |
158 | } | |
159 | ||
c6e8124e | 160 | return dbg_cnt_set_limit_by_name (name, low, high); |
d2153a46 | 161 | } |
3072d30e | 162 | |
d2153a46 | 163 | void |
164 | dbg_cnt_process_opt (const char *arg) | |
165 | { | |
795785e1 | 166 | char *str = xstrdup (arg); |
795785e1 | 167 | unsigned int start = 0; |
168 | ||
c6e8124e | 169 | auto_vec<const char *> tokens; |
170 | for (const char *next = strtok (str, ","); next != NULL; | |
171 | next = strtok (NULL, ",")) | |
172 | tokens.safe_push (next); | |
173 | ||
174 | unsigned i; | |
175 | for (i = 0; i < tokens.length (); i++) | |
176 | { | |
177 | if (!dbg_cnt_process_single_pair (tokens[i])) | |
d2153a46 | 178 | break; |
c6e8124e | 179 | start += strlen (tokens[i]) + 1; |
180 | } | |
d2153a46 | 181 | |
c6e8124e | 182 | if (i != tokens.length ()) |
3072d30e | 183 | { |
795785e1 | 184 | char *buffer = XALLOCAVEC (char, start + 2); |
185 | sprintf (buffer, "%*c", start + 1, '^'); | |
bf776685 | 186 | error ("cannot find a valid counter:value pair:"); |
c6e8124e | 187 | error ("%<-fdbg-cnt=%s%>", arg); |
188 | error (" %s", buffer); | |
3072d30e | 189 | } |
190 | } | |
d2153a46 | 191 | |
192 | /* Print name, limit and count of all counters. */ | |
193 | ||
48e1416a | 194 | void |
bf1f8fbc | 195 | dbg_cnt_list_all_counters (void) |
d2153a46 | 196 | { |
197 | int i; | |
795785e1 | 198 | printf (" %-32s %-11s %-12s\n", "counter name", "low limit", |
199 | "high limit"); | |
200 | printf ("-----------------------------------------------------------------\n"); | |
d2153a46 | 201 | for (i = 0; i < debug_counter_number_of_counters; i++) |
795785e1 | 202 | printf (" %-30s %11u %12u\n", |
203 | map[i].name, limit_low[map[i].counter], limit_high[map[i].counter]); | |
d2153a46 | 204 | printf ("\n"); |
205 | } |