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 }