Mercurial > hg > CbC > CbC_gcc
comparison gcc/coverage.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* Read and write coverage files, and associated functionality. | 1 /* Read and write coverage files, and associated functionality. |
2 Copyright (C) 1990-2017 Free Software Foundation, Inc. | 2 Copyright (C) 1990-2018 Free Software Foundation, Inc. |
3 Contributed by James E. Wilson, UC Berkeley/Cygnus Support; | 3 Contributed by James E. Wilson, UC Berkeley/Cygnus Support; |
4 based on some ideas from Dain Samples of UC Berkeley. | 4 based on some ideas from Dain Samples of UC Berkeley. |
5 Further mangling by Bob Manson, Cygnus Support. | 5 Further mangling by Bob Manson, Cygnus Support. |
6 Further mangled by Nathan Sidwell, CodeSourcery | 6 Further mangled by Nathan Sidwell, CodeSourcery |
7 | 7 |
47 #include "context.h" | 47 #include "context.h" |
48 #include "pass_manager.h" | 48 #include "pass_manager.h" |
49 #include "intl.h" | 49 #include "intl.h" |
50 #include "params.h" | 50 #include "params.h" |
51 #include "auto-profile.h" | 51 #include "auto-profile.h" |
52 #include "profile.h" | |
52 | 53 |
53 #include "gcov-io.c" | 54 #include "gcov-io.c" |
54 | 55 |
55 struct GTY((chain_next ("%h.next"))) coverage_data | 56 struct GTY((chain_next ("%h.next"))) coverage_data |
56 { | 57 { |
71 | 72 |
72 /* Store */ | 73 /* Store */ |
73 unsigned lineno_checksum; | 74 unsigned lineno_checksum; |
74 unsigned cfg_checksum; | 75 unsigned cfg_checksum; |
75 gcov_type *counts; | 76 gcov_type *counts; |
76 struct gcov_ctr_summary summary; | |
77 | 77 |
78 /* hash_table support. */ | 78 /* hash_table support. */ |
79 static inline hashval_t hash (const counts_entry *); | 79 static inline hashval_t hash (const counts_entry *); |
80 static int equal (const counts_entry *, const counts_entry *); | 80 static int equal (const counts_entry *, const counts_entry *); |
81 static void remove (counts_entry *); | 81 static void remove (counts_entry *); |
183 | 183 |
184 static void | 184 static void |
185 read_counts_file (void) | 185 read_counts_file (void) |
186 { | 186 { |
187 gcov_unsigned_t fn_ident = 0; | 187 gcov_unsigned_t fn_ident = 0; |
188 struct gcov_summary summary; | |
189 unsigned new_summary = 1; | |
190 gcov_unsigned_t tag; | 188 gcov_unsigned_t tag; |
191 int is_error = 0; | 189 int is_error = 0; |
192 unsigned lineno_checksum = 0; | 190 unsigned lineno_checksum = 0; |
193 unsigned cfg_checksum = 0; | 191 unsigned cfg_checksum = 0; |
194 | 192 |
234 lineno_checksum = gcov_read_unsigned (); | 232 lineno_checksum = gcov_read_unsigned (); |
235 cfg_checksum = gcov_read_unsigned (); | 233 cfg_checksum = gcov_read_unsigned (); |
236 } | 234 } |
237 else | 235 else |
238 fn_ident = lineno_checksum = cfg_checksum = 0; | 236 fn_ident = lineno_checksum = cfg_checksum = 0; |
239 new_summary = 1; | |
240 } | 237 } |
241 else if (tag == GCOV_TAG_PROGRAM_SUMMARY) | 238 else if (tag == GCOV_TAG_OBJECT_SUMMARY) |
242 { | 239 { |
243 struct gcov_summary sum; | 240 profile_info = XCNEW (gcov_summary); |
244 unsigned ix; | 241 profile_info->runs = gcov_read_unsigned (); |
245 | 242 profile_info->sum_max = gcov_read_unsigned (); |
246 if (new_summary) | |
247 memset (&summary, 0, sizeof (summary)); | |
248 | |
249 gcov_read_summary (&sum); | |
250 for (ix = 0; ix != GCOV_COUNTERS_SUMMABLE; ix++) | |
251 { | |
252 summary.ctrs[ix].runs += sum.ctrs[ix].runs; | |
253 summary.ctrs[ix].sum_all += sum.ctrs[ix].sum_all; | |
254 if (summary.ctrs[ix].run_max < sum.ctrs[ix].run_max) | |
255 summary.ctrs[ix].run_max = sum.ctrs[ix].run_max; | |
256 summary.ctrs[ix].sum_max += sum.ctrs[ix].sum_max; | |
257 } | |
258 if (new_summary) | |
259 memcpy (summary.ctrs[GCOV_COUNTER_ARCS].histogram, | |
260 sum.ctrs[GCOV_COUNTER_ARCS].histogram, | |
261 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); | |
262 else | |
263 gcov_histogram_merge (summary.ctrs[GCOV_COUNTER_ARCS].histogram, | |
264 sum.ctrs[GCOV_COUNTER_ARCS].histogram); | |
265 new_summary = 0; | |
266 } | 243 } |
267 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident) | 244 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident) |
268 { | 245 { |
269 counts_entry **slot, *entry, elt; | 246 counts_entry **slot, *entry, elt; |
270 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length); | 247 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length); |
280 *slot = entry = XCNEW (counts_entry); | 257 *slot = entry = XCNEW (counts_entry); |
281 entry->ident = fn_ident; | 258 entry->ident = fn_ident; |
282 entry->ctr = elt.ctr; | 259 entry->ctr = elt.ctr; |
283 entry->lineno_checksum = lineno_checksum; | 260 entry->lineno_checksum = lineno_checksum; |
284 entry->cfg_checksum = cfg_checksum; | 261 entry->cfg_checksum = cfg_checksum; |
285 if (elt.ctr < GCOV_COUNTERS_SUMMABLE) | |
286 entry->summary = summary.ctrs[elt.ctr]; | |
287 entry->summary.num = n_counts; | |
288 entry->counts = XCNEWVEC (gcov_type, n_counts); | 262 entry->counts = XCNEWVEC (gcov_type, n_counts); |
289 } | 263 } |
290 else if (entry->lineno_checksum != lineno_checksum | 264 else if (entry->lineno_checksum != lineno_checksum |
291 || entry->cfg_checksum != cfg_checksum) | 265 || entry->cfg_checksum != cfg_checksum) |
292 { | 266 { |
296 lineno_checksum, cfg_checksum); | 270 lineno_checksum, cfg_checksum); |
297 delete counts_hash; | 271 delete counts_hash; |
298 counts_hash = NULL; | 272 counts_hash = NULL; |
299 break; | 273 break; |
300 } | 274 } |
301 else if (entry->summary.num != n_counts) | |
302 { | |
303 error ("Profile data for function %u is corrupted", fn_ident); | |
304 error ("number of counters is %d instead of %d", entry->summary.num, n_counts); | |
305 delete counts_hash; | |
306 counts_hash = NULL; | |
307 break; | |
308 } | |
309 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE) | |
310 { | |
311 error ("cannot merge separate %s counters for function %u", | |
312 ctr_names[elt.ctr], fn_ident); | |
313 goto skip_merge; | |
314 } | |
315 else | |
316 { | |
317 entry->summary.runs += summary.ctrs[elt.ctr].runs; | |
318 entry->summary.sum_all += summary.ctrs[elt.ctr].sum_all; | |
319 if (entry->summary.run_max < summary.ctrs[elt.ctr].run_max) | |
320 entry->summary.run_max = summary.ctrs[elt.ctr].run_max; | |
321 entry->summary.sum_max += summary.ctrs[elt.ctr].sum_max; | |
322 } | |
323 for (ix = 0; ix != n_counts; ix++) | 275 for (ix = 0; ix != n_counts; ix++) |
324 entry->counts[ix] += gcov_read_counter (); | 276 entry->counts[ix] += gcov_read_counter (); |
325 skip_merge:; | |
326 } | 277 } |
327 gcov_sync (offset, length); | 278 gcov_sync (offset, length); |
328 if ((is_error = gcov_is_error ())) | 279 if ((is_error = gcov_is_error ())) |
329 { | 280 { |
330 error (is_error < 0 | 281 error (is_error < 0 |
341 } | 292 } |
342 | 293 |
343 /* Returns the counters for a particular tag. */ | 294 /* Returns the counters for a particular tag. */ |
344 | 295 |
345 gcov_type * | 296 gcov_type * |
346 get_coverage_counts (unsigned counter, unsigned expected, | 297 get_coverage_counts (unsigned counter, unsigned cfg_checksum, |
347 unsigned cfg_checksum, unsigned lineno_checksum, | 298 unsigned lineno_checksum) |
348 const struct gcov_ctr_summary **summary) | |
349 { | 299 { |
350 counts_entry *entry, elt; | 300 counts_entry *entry, elt; |
351 | 301 |
352 /* No hash table, no counts. */ | 302 /* No hash table, no counts. */ |
353 if (!counts_hash) | 303 if (!counts_hash) |
354 { | 304 { |
355 static int warned = 0; | 305 static int warned = 0; |
356 | 306 |
357 if (!warned++ && dump_enabled_p ()) | 307 if (!warned++) |
358 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location, | 308 { |
359 (flag_guess_branch_prob | 309 warning (OPT_Wmissing_profile, |
360 ? "file %s not found, execution counts estimated\n" | 310 "%qs profile count data file not found", |
361 : "file %s not found, execution counts assumed to " | 311 da_file_name); |
362 "be zero\n"), | 312 if (dump_enabled_p ()) |
363 da_file_name); | 313 { |
314 dump_user_location_t loc | |
315 = dump_user_location_t::from_location_t (input_location); | |
316 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, | |
317 "file %s not found, %s\n", da_file_name, | |
318 (flag_guess_branch_prob | |
319 ? "execution counts estimated" | |
320 : "execution counts assumed to be zero")); | |
321 } | |
322 } | |
364 return NULL; | 323 return NULL; |
365 } | 324 } |
366 if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID)) | 325 if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID)) |
367 elt.ident = current_function_funcdef_no + 1; | 326 elt.ident = current_function_funcdef_no + 1; |
368 else | 327 else |
370 gcc_assert (coverage_node_map_initialized_p ()); | 329 gcc_assert (coverage_node_map_initialized_p ()); |
371 elt.ident = cgraph_node::get (cfun->decl)->profile_id; | 330 elt.ident = cgraph_node::get (cfun->decl)->profile_id; |
372 } | 331 } |
373 elt.ctr = counter; | 332 elt.ctr = counter; |
374 entry = counts_hash->find (&elt); | 333 entry = counts_hash->find (&elt); |
375 if (!entry || !entry->summary.num) | 334 if (!entry) |
376 /* The function was not emitted, or is weak and not chosen in the | 335 { |
377 final executable. Silently fail, because there's nothing we | 336 if (counter == GCOV_COUNTER_ARCS) |
378 can do about it. */ | 337 warning_at (DECL_SOURCE_LOCATION (current_function_decl), |
379 return NULL; | 338 OPT_Wmissing_profile, |
380 | 339 "profile for function %qD not found in profile data", |
381 if (entry->cfg_checksum != cfg_checksum | 340 current_function_decl); |
382 || entry->summary.num != expected) | 341 /* The function was not emitted, or is weak and not chosen in the |
342 final executable. Silently fail, because there's nothing we | |
343 can do about it. */ | |
344 return NULL; | |
345 } | |
346 | |
347 if (entry->cfg_checksum != cfg_checksum) | |
383 { | 348 { |
384 static int warned = 0; | 349 static int warned = 0; |
385 bool warning_printed = false; | 350 bool warning_printed = false; |
386 tree id = DECL_ASSEMBLER_NAME (current_function_decl); | |
387 | 351 |
388 warning_printed = | 352 warning_printed = |
389 warning_at (input_location, OPT_Wcoverage_mismatch, | 353 warning_at (DECL_SOURCE_LOCATION (current_function_decl), |
390 "the control flow of function %qE does not match " | 354 OPT_Wcoverage_mismatch, |
391 "its profile data (counter %qs)", id, ctr_names[counter]); | 355 "the control flow of function %qD does not match " |
356 "its profile data (counter %qs)", current_function_decl, | |
357 ctr_names[counter]); | |
392 if (warning_printed && dump_enabled_p ()) | 358 if (warning_printed && dump_enabled_p ()) |
393 { | 359 { |
394 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location, | 360 dump_user_location_t loc |
361 = dump_user_location_t::from_location_t (input_location); | |
362 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, | |
395 "use -Wno-error=coverage-mismatch to tolerate " | 363 "use -Wno-error=coverage-mismatch to tolerate " |
396 "the mismatch but performance may drop if the " | 364 "the mismatch but performance may drop if the " |
397 "function is hot\n"); | 365 "function is hot\n"); |
398 | 366 |
399 if (!seen_error () | 367 if (!seen_error () |
400 && !warned++) | 368 && !warned++) |
401 { | 369 { |
402 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location, | 370 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, |
403 "coverage mismatch ignored\n"); | 371 "coverage mismatch ignored\n"); |
404 dump_printf (MSG_OPTIMIZED_LOCATIONS, | 372 dump_printf (MSG_MISSED_OPTIMIZATION, |
405 flag_guess_branch_prob | 373 flag_guess_branch_prob |
406 ? G_("execution counts estimated\n") | 374 ? G_("execution counts estimated\n") |
407 : G_("execution counts assumed to be zero\n")); | 375 : G_("execution counts assumed to be zero\n")); |
408 if (!flag_guess_branch_prob) | 376 if (!flag_guess_branch_prob) |
409 dump_printf (MSG_OPTIMIZED_LOCATIONS, | 377 dump_printf (MSG_MISSED_OPTIMIZATION, |
410 "this can result in poorly optimized code\n"); | 378 "this can result in poorly optimized code\n"); |
411 } | 379 } |
412 } | 380 } |
413 | 381 |
414 return NULL; | 382 return NULL; |
415 } | 383 } |
416 else if (entry->lineno_checksum != lineno_checksum) | 384 else if (entry->lineno_checksum != lineno_checksum) |
417 { | 385 { |
418 warning (OPT_Wcoverage_mismatch, | 386 warning_at (DECL_SOURCE_LOCATION (current_function_decl), |
419 "source locations for function %qE have changed," | 387 OPT_Wcoverage_mismatch, |
420 " the profile data may be out of date", | 388 "source locations for function %qD have changed," |
421 DECL_ASSEMBLER_NAME (current_function_decl)); | 389 " the profile data may be out of date", |
422 } | 390 current_function_decl); |
423 | 391 } |
424 if (summary) | |
425 *summary = &entry->summary; | |
426 | 392 |
427 return entry->counts; | 393 return entry->counts; |
428 } | 394 } |
429 | 395 |
430 /* Allocate NUM counters of type COUNTER. Returns nonzero if the | 396 /* Allocate NUM counters of type COUNTER. Returns nonzero if the |
661 | 627 |
662 gcov_write_unsigned (lineno_checksum); | 628 gcov_write_unsigned (lineno_checksum); |
663 gcov_write_unsigned (cfg_checksum); | 629 gcov_write_unsigned (cfg_checksum); |
664 gcov_write_string (IDENTIFIER_POINTER | 630 gcov_write_string (IDENTIFIER_POINTER |
665 (DECL_ASSEMBLER_NAME (current_function_decl))); | 631 (DECL_ASSEMBLER_NAME (current_function_decl))); |
632 gcov_write_unsigned (DECL_ARTIFICIAL (current_function_decl) | |
633 && !DECL_FUNCTION_VERSIONED (current_function_decl) | |
634 && !DECL_LAMBDA_FUNCTION (current_function_decl)); | |
666 gcov_write_filename (xloc.file); | 635 gcov_write_filename (xloc.file); |
667 gcov_write_unsigned (xloc.line); | 636 gcov_write_unsigned (xloc.line); |
637 gcov_write_unsigned (xloc.column); | |
638 | |
639 expanded_location endloc = expand_location (cfun->function_end_locus); | |
640 | |
641 /* Function can start in a single file and end in another one. */ | |
642 gcov_write_unsigned (endloc.file == xloc.file ? endloc.line : xloc.line); | |
668 gcov_write_length (offset); | 643 gcov_write_length (offset); |
669 | 644 |
670 return !gcov_is_error (); | 645 return !gcov_is_error (); |
671 } | 646 } |
672 | 647 |
1218 similar to the handling in finish_optimization_passes. */ | 1193 similar to the handling in finish_optimization_passes. */ |
1219 int profile_pass_num = | 1194 int profile_pass_num = |
1220 g->get_passes ()->get_pass_profile ()->static_pass_number; | 1195 g->get_passes ()->get_pass_profile ()->static_pass_number; |
1221 g->get_dumps ()->dump_start (profile_pass_num, NULL); | 1196 g->get_dumps ()->dump_start (profile_pass_num, NULL); |
1222 | 1197 |
1223 if (!profile_data_prefix && !IS_ABSOLUTE_PATH (filename)) | 1198 if (!IS_ABSOLUTE_PATH (filename)) |
1224 profile_data_prefix = getpwd (); | 1199 { |
1200 /* When a profile_data_prefix is provided, then mangle full path | |
1201 of filename in order to prevent file path clashing. */ | |
1202 if (profile_data_prefix) | |
1203 { | |
1204 #if HAVE_DOS_BASED_FILE_SYSTEM | |
1205 const char *separator = "\\"; | |
1206 #else | |
1207 const char *separator = "/"; | |
1208 #endif | |
1209 filename = concat (getpwd (), separator, filename, NULL); | |
1210 filename = mangle_path (filename); | |
1211 len = strlen (filename); | |
1212 } | |
1213 else | |
1214 profile_data_prefix = getpwd (); | |
1215 } | |
1225 | 1216 |
1226 if (profile_data_prefix) | 1217 if (profile_data_prefix) |
1227 prefix_len = strlen (profile_data_prefix); | 1218 prefix_len = strlen (profile_data_prefix); |
1228 | 1219 |
1229 /* Name of da file. */ | 1220 /* Name of da file. */ |
1260 else | 1251 else |
1261 { | 1252 { |
1262 gcov_write_unsigned (GCOV_NOTE_MAGIC); | 1253 gcov_write_unsigned (GCOV_NOTE_MAGIC); |
1263 gcov_write_unsigned (GCOV_VERSION); | 1254 gcov_write_unsigned (GCOV_VERSION); |
1264 gcov_write_unsigned (bbg_file_stamp); | 1255 gcov_write_unsigned (bbg_file_stamp); |
1256 gcov_write_string (getpwd ()); | |
1257 | |
1258 /* Do not support has_unexecuted_blocks for Ada. */ | |
1259 gcov_write_unsigned (strcmp (lang_hooks.name, "GNU Ada") != 0); | |
1265 } | 1260 } |
1266 } | 1261 } |
1267 | 1262 |
1268 g->get_dumps ()->dump_finish (profile_pass_num); | 1263 g->get_dumps ()->dump_finish (profile_pass_num); |
1269 } | 1264 } |