comparison gcc/dbgcnt.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
1 /* Debug counter for debugging support 1 /* Debug counter for debugging support
2 Copyright (C) 2006-2018 Free Software Foundation, Inc. 2 Copyright (C) 2006-2020 Free Software Foundation, Inc.
3 3
4 This file is part of GCC. 4 This file is part of GCC.
5 5
6 GCC is free software; you can redistribute it and/or modify it under 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 7 the terms of the GNU General Public License as published by the Free
22 #include "config.h" 22 #include "config.h"
23 #include "system.h" 23 #include "system.h"
24 #include "coretypes.h" 24 #include "coretypes.h"
25 #include "diagnostic-core.h" 25 #include "diagnostic-core.h"
26 #include "dumpfile.h" 26 #include "dumpfile.h"
27 #include "selftest.h"
28 #include "intl.h"
27 29
28 #include "dbgcnt.h" 30 #include "dbgcnt.h"
29 31
30 struct string2counter_map { 32 struct string2counter_map {
31 const char *name; 33 const char *name;
38 { 40 {
39 #include "dbgcnt.def" 41 #include "dbgcnt.def"
40 }; 42 };
41 #undef DEBUG_COUNTER 43 #undef DEBUG_COUNTER
42 44
43 #define DEBUG_COUNTER(a) UINT_MAX, 45 typedef std::pair<unsigned int, unsigned int> limit_tuple;
44 static unsigned int limit_high[debug_counter_number_of_counters] = 46
45 { 47 static vec<limit_tuple> limits[debug_counter_number_of_counters];
46 #include "dbgcnt.def"
47 };
48 #undef DEBUG_COUNTER
49
50 static unsigned int limit_low[debug_counter_number_of_counters];
51 48
52 static unsigned int count[debug_counter_number_of_counters]; 49 static unsigned int count[debug_counter_number_of_counters];
53 50
54 bool 51 static void
55 dbg_cnt_is_enabled (enum debug_counter index) 52 print_limit_reach (const char *counter, int limit, bool upper_p)
56 { 53 {
57 unsigned v = count[index]; 54 char buffer[128];
58 return v > limit_low[index] && v <= limit_high[index]; 55 sprintf (buffer, "***dbgcnt: %s limit %d reached for %s.***\n",
56 upper_p ? "upper" : "lower", limit, counter);
57 fputs (buffer, stderr);
58 if (dump_file)
59 fputs (buffer, dump_file);
59 } 60 }
60 61
61 bool 62 bool
62 dbg_cnt (enum debug_counter index) 63 dbg_cnt (enum debug_counter index)
63 { 64 {
64 count[index]++; 65 unsigned v = ++count[index];
65 66
66 if (dump_file) 67 if (!limits[index].exists ())
67 { 68 return true;
68 /* Do not print the info for default lower limit. */ 69 else if (limits[index].is_empty ())
69 if (count[index] == limit_low[index] && limit_low[index] > 0) 70 return false;
70 fprintf (dump_file, "***dbgcnt: lower limit %d reached for %s.***\n", 71
71 limit_low[index], map[index].name); 72 unsigned last = limits[index].length () - 1;
72 else if (count[index] == limit_high[index]) 73 unsigned int min = limits[index][last].first;
73 fprintf (dump_file, "***dbgcnt: upper limit %d reached for %s.***\n", 74 unsigned int max = limits[index][last].second;
74 limit_high[index], map[index].name); 75
75 } 76 if (v < min)
76 77 return false;
77 return dbg_cnt_is_enabled (index); 78 else if (v == min)
78 } 79 {
79 80 print_limit_reach (map[index].name, v, false);
80 static void 81 if (min == max)
81 dbg_cnt_set_limit_by_index (enum debug_counter index, int low, int high) 82 limits[index].pop ();
82 { 83 return true;
83 limit_low[index] = low; 84 }
84 limit_high[index] = high; 85 else if (v < max)
85 86 return true;
86 fprintf (stderr, "dbg_cnt '%s' set to %d-%d\n", map[index].name, low, high); 87 else if (v == max)
88 {
89 print_limit_reach (map[index].name, v, true);
90 limits[index].pop ();
91 return true;
92 }
93 else
94 return false;
95 }
96
97 /* Compare limit_tuple intervals by first item in descending order. */
98
99 static int
100 cmp_tuples (const void *ptr1, const void *ptr2)
101 {
102 const limit_tuple *p1 = (const limit_tuple *)ptr1;
103 const limit_tuple *p2 = (const limit_tuple *)ptr2;
104
105 if (p1->first < p2->first)
106 return 1;
107 else if (p1->first > p2->first)
108 return -1;
109 return 0;
87 } 110 }
88 111
89 static bool 112 static bool
90 dbg_cnt_set_limit_by_name (const char *name, int low, int high) 113 dbg_cnt_set_limit_by_index (enum debug_counter index, const char *name,
114 unsigned int low, unsigned int high)
115 {
116 if (!limits[index].exists ())
117 limits[index].create (1);
118
119 limits[index].safe_push (limit_tuple (low, high));
120 limits[index].qsort (cmp_tuples);
121
122 for (unsigned i = 0; i < limits[index].length () - 1; i++)
123 {
124 limit_tuple t1 = limits[index][i];
125 limit_tuple t2 = limits[index][i + 1];
126 if (t1.first <= t2.second)
127 {
128 error ("Interval overlap of %<-fdbg-cnt=%s%>: [%u, %u] and "
129 "[%u, %u]\n", name, t2.first, t2.second, t1.first, t1.second);
130 return false;
131 }
132 }
133
134 return true;
135 }
136
137 static bool
138 dbg_cnt_set_limit_by_name (const char *name, unsigned int low,
139 unsigned int high)
91 { 140 {
92 if (high < low) 141 if (high < low)
93 { 142 {
94 error ("-fdbg-cnt=%s:%d:%d has smaller upper limit than the lower", 143 error ("%<-fdbg-cnt=%s:%d-%d%> has smaller upper limit than the lower",
95 name, low, high); 144 name, low, high);
96 return false;
97 }
98
99 if (low < 0)
100 {
101 error ("Lower limit %d of -fdbg-cnt=%s must be a non-negative number", low,
102 name);
103 return false;
104 }
105
106 if (high < 0)
107 {
108 error ("Upper limit %d of -fdbg-cnt=%s must be a non-negative number", high,
109 name);
110 return false; 145 return false;
111 } 146 }
112 147
113 int i; 148 int i;
114 for (i = debug_counter_number_of_counters - 1; i >= 0; i--) 149 for (i = debug_counter_number_of_counters - 1; i >= 0; i--)
115 if (strcmp (map[i].name, name) == 0) 150 if (strcmp (map[i].name, name) == 0)
116 break; 151 break;
117 152
118 if (i < 0) 153 if (i < 0)
119 return false; 154 {
120 155 error ("cannot find a valid counter name %qs of %<-fdbg-cnt=%> option",
121 dbg_cnt_set_limit_by_index ((enum debug_counter) i, low, high); 156 name);
122 return true; 157 return false;
123 } 158 }
124 159
125 160 return dbg_cnt_set_limit_by_index ((enum debug_counter) i, name, low, high);
126 /* Process a single "name:value" pair. 161 }
162
163 /* Process a single "low:high" pair.
127 Returns NULL if there's no valid pair is found. 164 Returns NULL if there's no valid pair is found.
128 Otherwise returns a pointer to the end of the pair. */ 165 Otherwise returns a pointer to the end of the pair. */
129 166
130 static bool 167 static bool
131 dbg_cnt_process_single_pair (const char *arg) 168 dbg_cnt_process_single_pair (char *name, char *str)
132 { 169 {
133 char *str = xstrdup (arg); 170 char *value1 = strtok (str, "-");
134 char *name = strtok (str, ":"); 171 char *value2 = strtok (NULL, "-");
135 char *value1 = strtok (NULL, ":"); 172
136 char *value2 = strtok (NULL, ":"); 173 unsigned int high, low;
137
138 int high, low;
139 174
140 if (value1 == NULL) 175 if (value1 == NULL)
141 return false; 176 return false;
142 177
143 if (value2 == NULL) 178 if (value2 == NULL)
144 { 179 {
145 low = 0;
146 high = strtol (value1, NULL, 10); 180 high = strtol (value1, NULL, 10);
181 /* Let's allow 0:0. */
182 low = high == 0 ? 0 : 1;
147 } 183 }
148 else 184 else
149 { 185 {
150 low = strtol (value1, NULL, 10); 186 low = strtol (value1, NULL, 10);
151 high = strtol (value2, NULL, 10); 187 high = strtol (value2, NULL, 10);
152 } 188 }
153 189
154 return dbg_cnt_set_limit_by_name (name, low, high); 190 return dbg_cnt_set_limit_by_name (name, low, high);
155 } 191 }
156 192
157 void 193 void
158 dbg_cnt_process_opt (const char *arg) 194 dbg_cnt_process_opt (const char *arg)
159 { 195 {
160 char *str = xstrdup (arg); 196 char *str = xstrdup (arg);
161 const char *next = strtok (str, ",");
162 unsigned int start = 0; 197 unsigned int start = 0;
163 198
164 do { 199 auto_vec<char *> tokens;
165 if (!dbg_cnt_process_single_pair (arg)) 200 for (char *next = strtok (str, ","); next != NULL; next = strtok (NULL, ","))
166 break; 201 tokens.safe_push (next);
167 start += strlen (arg) + 1; 202
168 next = strtok (NULL, ","); 203 unsigned i;
169 } while (next != NULL); 204 for (i = 0; i < tokens.length (); i++)
170 205 {
171 if (next != NULL) 206 auto_vec<char *> ranges;
172 { 207 char *name = strtok (tokens[i], ":");
173 char *buffer = XALLOCAVEC (char, start + 2); 208 for (char *part = strtok (NULL, ":"); part; part = strtok (NULL, ":"))
174 sprintf (buffer, "%*c", start + 1, '^'); 209 ranges.safe_push (part);
175 error ("cannot find a valid counter:value pair:"); 210
176 error ("-fdbg-cnt=%s", next); 211 for (unsigned j = 0; j < ranges.length (); j++)
177 error (" %s", buffer); 212 {
178 } 213 if (!dbg_cnt_process_single_pair (name, ranges[j]))
214 break;
215 }
216 start += strlen (tokens[i]) + 1;
217 }
179 } 218 }
180 219
181 /* Print name, limit and count of all counters. */ 220 /* Print name, limit and count of all counters. */
182 221
183 void 222 void
184 dbg_cnt_list_all_counters (void) 223 dbg_cnt_list_all_counters (void)
185 { 224 {
186 int i; 225 int i;
187 printf (" %-32s %-11s %-12s\n", "counter name", "low limit", 226 printf (" %-30s %s\n", G_("counter name"), G_("closed intervals"));
188 "high limit");
189 printf ("-----------------------------------------------------------------\n"); 227 printf ("-----------------------------------------------------------------\n");
190 for (i = 0; i < debug_counter_number_of_counters; i++) 228 for (i = 0; i < debug_counter_number_of_counters; i++)
191 printf (" %-30s %11u %12u\n", 229 {
192 map[i].name, limit_low[map[i].counter], limit_high[map[i].counter]); 230 printf (" %-30s ", map[i].name);
231 if (limits[i].exists ())
232 {
233 for (int j = limits[i].length () - 1; j >= 0; j--)
234 {
235 printf ("[%u, %u]", limits[i][j].first, limits[i][j].second);
236 if (j > 0)
237 printf (", ");
238 }
239 putchar ('\n');
240 }
241 else
242 printf ("unset\n");
243 }
193 printf ("\n"); 244 printf ("\n");
194 } 245 }
246
247 #if CHECKING_P
248
249 namespace selftest {
250
251 /* Selftests. */
252
253 static void
254 test_sorted_dbg_counters ()
255 {
256 for (unsigned i = 0; i < debug_counter_number_of_counters - 1; i++)
257 ASSERT_LT (strcmp (map[i].name, map[i + 1].name), 0);
258 }
259
260 void
261 dbgcnt_c_tests ()
262 {
263 test_sorted_dbg_counters ();
264 }
265
266 } // namespace selftest
267
268 #endif /* #if CHECKING_P */