Clang] Fix expansion of response files in -Wp after integrated-cc1 change
[llvm-project.git] / llvm / tools / llvm-dwarfdump / Statistics.cpp
blob5bef4d5148ca3bfba51267cdc42dd81c3a9ac628
1 #include "llvm/ADT/DenseMap.h"
2 #include "llvm/ADT/StringExtras.h"
3 #include "llvm/ADT/StringSet.h"
4 #include "llvm/DebugInfo/DIContext.h"
5 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
6 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
7 #include "llvm/Object/ObjectFile.h"
8 #include "llvm/Support/JSON.h"
10 #define DEBUG_TYPE "dwarfdump"
11 using namespace llvm;
12 using namespace object;
14 /// This represents the number of categories of debug location coverage being
15 /// calculated. The first category is the number of variables with 0% location
16 /// coverage, but the last category is the number of variables with 100%
17 /// location coverage.
18 constexpr int NumOfCoverageCategories = 12;
20 /// Holds statistics for one function (or other entity that has a PC range and
21 /// contains variables, such as a compile unit).
22 struct PerFunctionStats {
23 /// Number of inlined instances of this function.
24 unsigned NumFnInlined = 0;
25 /// Number of inlined instances that have abstract origins.
26 unsigned NumAbstractOrigins = 0;
27 /// Number of variables and parameters with location across all inlined
28 /// instances.
29 unsigned TotalVarWithLoc = 0;
30 /// Number of constants with location across all inlined instances.
31 unsigned ConstantMembers = 0;
32 /// List of all Variables and parameters in this function.
33 StringSet<> VarsInFunction;
34 /// Compile units also cover a PC range, but have this flag set to false.
35 bool IsFunction = false;
36 /// Verify function definition has PC addresses (for detecting when
37 /// a function has been inlined everywhere).
38 bool HasPCAddresses = false;
39 /// Function has source location information.
40 bool HasSourceLocation = false;
41 /// Number of function parameters.
42 unsigned NumParams = 0;
43 /// Number of function parameters with source location.
44 unsigned NumParamSourceLocations = 0;
45 /// Number of function parameters with type.
46 unsigned NumParamTypes = 0;
47 /// Number of function parameters with a DW_AT_location.
48 unsigned NumParamLocations = 0;
49 /// Number of variables.
50 unsigned NumVars = 0;
51 /// Number of variables with source location.
52 unsigned NumVarSourceLocations = 0;
53 /// Number of variables with type.
54 unsigned NumVarTypes = 0;
55 /// Number of variables with DW_AT_location.
56 unsigned NumVarLocations = 0;
59 /// Holds accumulated global statistics about DIEs.
60 struct GlobalStats {
61 /// Total number of PC range bytes covered by DW_AT_locations.
62 unsigned ScopeBytesCovered = 0;
63 /// Total number of PC range bytes in each variable's enclosing scope.
64 unsigned ScopeBytes = 0;
65 /// Total number of PC range bytes covered by DW_AT_locations with
66 /// the debug entry values (DW_OP_entry_value).
67 unsigned ScopeEntryValueBytesCovered = 0;
68 /// Total number of PC range bytes covered by DW_AT_locations of
69 /// formal parameters.
70 unsigned ParamScopeBytesCovered = 0;
71 /// Total number of PC range bytes in each variable's enclosing scope
72 /// (only for parameters).
73 unsigned ParamScopeBytes = 0;
74 /// Total number of PC range bytes covered by DW_AT_locations with
75 /// the debug entry values (DW_OP_entry_value) (only for parameters).
76 unsigned ParamScopeEntryValueBytesCovered = 0;
77 /// Total number of PC range bytes covered by DW_AT_locations (only for local
78 /// variables).
79 unsigned VarScopeBytesCovered = 0;
80 /// Total number of PC range bytes in each variable's enclosing scope
81 /// (only for local variables).
82 unsigned VarScopeBytes = 0;
83 /// Total number of PC range bytes covered by DW_AT_locations with
84 /// the debug entry values (DW_OP_entry_value) (only for local variables).
85 unsigned VarScopeEntryValueBytesCovered = 0;
86 /// Total number of call site entries (DW_AT_call_file & DW_AT_call_line).
87 unsigned CallSiteEntries = 0;
88 /// Total number of call site DIEs (DW_TAG_call_site).
89 unsigned CallSiteDIEs = 0;
90 /// Total number of call site parameter DIEs (DW_TAG_call_site_parameter).
91 unsigned CallSiteParamDIEs = 0;
92 /// Total byte size of concrete functions. This byte size includes
93 /// inline functions contained in the concrete functions.
94 unsigned FunctionSize = 0;
95 /// Total byte size of inlined functions. This is the total number of bytes
96 /// for the top inline functions within concrete functions. This can help
97 /// tune the inline settings when compiling to match user expectations.
98 unsigned InlineFunctionSize = 0;
101 /// Holds accumulated debug location statistics about local variables and
102 /// formal parameters.
103 struct LocationStats {
104 /// Map the scope coverage decile to the number of variables in the decile.
105 /// The first element of the array (at the index zero) represents the number
106 /// of variables with the no debug location at all, but the last element
107 /// in the vector represents the number of fully covered variables within
108 /// its scope.
109 std::vector<unsigned> VarParamLocStats{
110 std::vector<unsigned>(NumOfCoverageCategories, 0)};
111 /// Map non debug entry values coverage.
112 std::vector<unsigned> VarParamNonEntryValLocStats{
113 std::vector<unsigned>(NumOfCoverageCategories, 0)};
114 /// The debug location statistics for formal parameters.
115 std::vector<unsigned> ParamLocStats{
116 std::vector<unsigned>(NumOfCoverageCategories, 0)};
117 /// Map non debug entry values coverage for formal parameters.
118 std::vector<unsigned> ParamNonEntryValLocStats{
119 std::vector<unsigned>(NumOfCoverageCategories, 0)};
120 /// The debug location statistics for local variables.
121 std::vector<unsigned> VarLocStats{
122 std::vector<unsigned>(NumOfCoverageCategories, 0)};
123 /// Map non debug entry values coverage for local variables.
124 std::vector<unsigned> VarNonEntryValLocStats{
125 std::vector<unsigned>(NumOfCoverageCategories, 0)};
126 /// Total number of local variables and function parameters processed.
127 unsigned NumVarParam = 0;
128 /// Total number of formal parameters processed.
129 unsigned NumParam = 0;
130 /// Total number of local variables processed.
131 unsigned NumVar = 0;
134 /// Collect debug location statistics for one DIE.
135 static void collectLocStats(uint64_t BytesCovered, uint64_t BytesInScope,
136 std::vector<unsigned> &VarParamLocStats,
137 std::vector<unsigned> &ParamLocStats,
138 std::vector<unsigned> &VarLocStats, bool IsParam,
139 bool IsLocalVar) {
140 auto getCoverageBucket = [BytesCovered, BytesInScope]() -> unsigned {
141 // No debug location at all for the variable.
142 if (BytesCovered == 0)
143 return 0;
144 // Fully covered variable within its scope.
145 if (BytesCovered >= BytesInScope)
146 return NumOfCoverageCategories - 1;
147 // Get covered range (e.g. 20%-29%).
148 unsigned LocBucket = 100 * (double)BytesCovered / BytesInScope;
149 LocBucket /= 10;
150 return LocBucket + 1;
153 unsigned CoverageBucket = getCoverageBucket();
154 VarParamLocStats[CoverageBucket]++;
155 if (IsParam)
156 ParamLocStats[CoverageBucket]++;
157 else if (IsLocalVar)
158 VarLocStats[CoverageBucket]++;
161 /// Collect debug info quality metrics for one DIE.
162 static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
163 std::string VarPrefix, uint64_t BytesInScope,
164 uint32_t InlineDepth,
165 StringMap<PerFunctionStats> &FnStatMap,
166 GlobalStats &GlobalStats,
167 LocationStats &LocStats) {
168 bool HasLoc = false;
169 bool HasSrcLoc = false;
170 bool HasType = false;
171 bool IsArtificial = false;
172 uint64_t BytesCovered = 0;
173 uint64_t BytesEntryValuesCovered = 0;
174 auto &FnStats = FnStatMap[FnPrefix];
175 bool IsParam = Die.getTag() == dwarf::DW_TAG_formal_parameter;
176 bool IsLocalVar = Die.getTag() == dwarf::DW_TAG_variable;
178 if (Die.getTag() == dwarf::DW_TAG_call_site ||
179 Die.getTag() == dwarf::DW_TAG_GNU_call_site) {
180 GlobalStats.CallSiteDIEs++;
181 return;
184 if (Die.getTag() == dwarf::DW_TAG_call_site_parameter ||
185 Die.getTag() == dwarf::DW_TAG_GNU_call_site_parameter) {
186 GlobalStats.CallSiteParamDIEs++;
187 return;
190 if (!IsParam && !IsLocalVar && Die.getTag() != dwarf::DW_TAG_member) {
191 // Not a variable or constant member.
192 return;
195 if (Die.findRecursively(dwarf::DW_AT_decl_file) &&
196 Die.findRecursively(dwarf::DW_AT_decl_line))
197 HasSrcLoc = true;
199 if (Die.findRecursively(dwarf::DW_AT_type))
200 HasType = true;
202 if (Die.find(dwarf::DW_AT_artificial))
203 IsArtificial = true;
205 auto IsEntryValue = [&](ArrayRef<uint8_t> D) -> bool {
206 DWARFUnit *U = Die.getDwarfUnit();
207 DataExtractor Data(toStringRef(D),
208 Die.getDwarfUnit()->getContext().isLittleEndian(), 0);
209 DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize());
210 // Consider the expression containing the DW_OP_entry_value as
211 // an entry value.
212 return llvm::any_of(Expression, [](DWARFExpression::Operation &Op) {
213 return Op.getCode() == dwarf::DW_OP_entry_value ||
214 Op.getCode() == dwarf::DW_OP_GNU_entry_value;
218 if (Die.find(dwarf::DW_AT_const_value)) {
219 // This catches constant members *and* variables.
220 HasLoc = true;
221 BytesCovered = BytesInScope;
222 } else {
223 if (Die.getTag() == dwarf::DW_TAG_member) {
224 // Non-const member.
225 return;
227 // Handle variables and function arguments.
228 Expected<std::vector<DWARFLocationExpression>> Loc =
229 Die.getLocations(dwarf::DW_AT_location);
230 if (!Loc) {
231 consumeError(Loc.takeError());
232 } else {
233 HasLoc = true;
234 // Get PC coverage.
235 auto Default = find_if(
236 *Loc, [](const DWARFLocationExpression &L) { return !L.Range; });
237 if (Default != Loc->end()) {
238 // Assume the entire range is covered by a single location.
239 BytesCovered = BytesInScope;
240 } else {
241 for (auto Entry : *Loc) {
242 uint64_t BytesEntryCovered = Entry.Range->HighPC - Entry.Range->LowPC;
243 BytesCovered += BytesEntryCovered;
244 if (IsEntryValue(Entry.Expr))
245 BytesEntryValuesCovered += BytesEntryCovered;
251 // Calculate the debug location statistics.
252 if (BytesInScope) {
253 LocStats.NumVarParam++;
254 if (IsParam)
255 LocStats.NumParam++;
256 else if (IsLocalVar)
257 LocStats.NumVar++;
259 collectLocStats(BytesCovered, BytesInScope, LocStats.VarParamLocStats,
260 LocStats.ParamLocStats, LocStats.VarLocStats, IsParam,
261 IsLocalVar);
262 // Non debug entry values coverage statistics.
263 collectLocStats(BytesCovered - BytesEntryValuesCovered, BytesInScope,
264 LocStats.VarParamNonEntryValLocStats,
265 LocStats.ParamNonEntryValLocStats,
266 LocStats.VarNonEntryValLocStats, IsParam, IsLocalVar);
269 // Collect PC range coverage data.
270 if (DWARFDie D =
271 Die.getAttributeValueAsReferencedDie(dwarf::DW_AT_abstract_origin))
272 Die = D;
273 // By using the variable name + the path through the lexical block tree, the
274 // keys are consistent across duplicate abstract origins in different CUs.
275 std::string VarName = StringRef(Die.getName(DINameKind::ShortName));
276 FnStats.VarsInFunction.insert(VarPrefix + VarName);
277 if (BytesInScope) {
278 FnStats.TotalVarWithLoc += (unsigned)HasLoc;
279 // Turns out we have a lot of ranges that extend past the lexical scope.
280 GlobalStats.ScopeBytesCovered += std::min(BytesInScope, BytesCovered);
281 GlobalStats.ScopeBytes += BytesInScope;
282 GlobalStats.ScopeEntryValueBytesCovered += BytesEntryValuesCovered;
283 if (IsParam) {
284 GlobalStats.ParamScopeBytesCovered +=
285 std::min(BytesInScope, BytesCovered);
286 GlobalStats.ParamScopeBytes += BytesInScope;
287 GlobalStats.ParamScopeEntryValueBytesCovered += BytesEntryValuesCovered;
288 } else if (IsLocalVar) {
289 GlobalStats.VarScopeBytesCovered += std::min(BytesInScope, BytesCovered);
290 GlobalStats.VarScopeBytes += BytesInScope;
291 GlobalStats.VarScopeEntryValueBytesCovered += BytesEntryValuesCovered;
293 assert(GlobalStats.ScopeBytesCovered <= GlobalStats.ScopeBytes);
294 } else if (Die.getTag() == dwarf::DW_TAG_member) {
295 FnStats.ConstantMembers++;
296 } else {
297 FnStats.TotalVarWithLoc += (unsigned)HasLoc;
299 if (!IsArtificial) {
300 if (IsParam) {
301 FnStats.NumParams++;
302 if (HasType)
303 FnStats.NumParamTypes++;
304 if (HasSrcLoc)
305 FnStats.NumParamSourceLocations++;
306 if (HasLoc)
307 FnStats.NumParamLocations++;
308 } else if (IsLocalVar) {
309 FnStats.NumVars++;
310 if (HasType)
311 FnStats.NumVarTypes++;
312 if (HasSrcLoc)
313 FnStats.NumVarSourceLocations++;
314 if (HasLoc)
315 FnStats.NumVarLocations++;
320 /// Recursively collect debug info quality metrics.
321 static void collectStatsRecursive(DWARFDie Die, std::string FnPrefix,
322 std::string VarPrefix, uint64_t BytesInScope,
323 uint32_t InlineDepth,
324 StringMap<PerFunctionStats> &FnStatMap,
325 GlobalStats &GlobalStats,
326 LocationStats &LocStats) {
327 // Handle any kind of lexical scope.
328 const dwarf::Tag Tag = Die.getTag();
329 const bool IsFunction = Tag == dwarf::DW_TAG_subprogram;
330 const bool IsBlock = Tag == dwarf::DW_TAG_lexical_block;
331 const bool IsInlinedFunction = Tag == dwarf::DW_TAG_inlined_subroutine;
332 if (IsFunction || IsInlinedFunction || IsBlock) {
334 // Reset VarPrefix when entering a new function.
335 if (Die.getTag() == dwarf::DW_TAG_subprogram ||
336 Die.getTag() == dwarf::DW_TAG_inlined_subroutine)
337 VarPrefix = "v";
339 // Ignore forward declarations.
340 if (Die.find(dwarf::DW_AT_declaration))
341 return;
343 // Check for call sites.
344 if (Die.find(dwarf::DW_AT_call_file) && Die.find(dwarf::DW_AT_call_line))
345 GlobalStats.CallSiteEntries++;
347 // PC Ranges.
348 auto RangesOrError = Die.getAddressRanges();
349 if (!RangesOrError) {
350 llvm::consumeError(RangesOrError.takeError());
351 return;
354 auto Ranges = RangesOrError.get();
355 uint64_t BytesInThisScope = 0;
356 for (auto Range : Ranges)
357 BytesInThisScope += Range.HighPC - Range.LowPC;
359 // Count the function.
360 if (!IsBlock) {
361 StringRef Name = Die.getName(DINameKind::LinkageName);
362 if (Name.empty())
363 Name = Die.getName(DINameKind::ShortName);
364 FnPrefix = Name;
365 // Skip over abstract origins.
366 if (Die.find(dwarf::DW_AT_inline))
367 return;
368 // We've seen an (inlined) instance of this function.
369 auto &FnStats = FnStatMap[Name];
370 if (IsInlinedFunction) {
371 FnStats.NumFnInlined++;
372 if (Die.findRecursively(dwarf::DW_AT_abstract_origin))
373 FnStats.NumAbstractOrigins++;
375 FnStats.IsFunction = true;
376 if (BytesInThisScope && !IsInlinedFunction)
377 FnStats.HasPCAddresses = true;
378 std::string FnName = StringRef(Die.getName(DINameKind::ShortName));
379 if (Die.findRecursively(dwarf::DW_AT_decl_file) &&
380 Die.findRecursively(dwarf::DW_AT_decl_line))
381 FnStats.HasSourceLocation = true;
384 if (BytesInThisScope) {
385 BytesInScope = BytesInThisScope;
386 if (IsFunction)
387 GlobalStats.FunctionSize += BytesInThisScope;
388 else if (IsInlinedFunction && InlineDepth == 0)
389 GlobalStats.InlineFunctionSize += BytesInThisScope;
391 } else {
392 // Not a scope, visit the Die itself. It could be a variable.
393 collectStatsForDie(Die, FnPrefix, VarPrefix, BytesInScope, InlineDepth,
394 FnStatMap, GlobalStats, LocStats);
397 // Set InlineDepth correctly for child recursion
398 if (IsFunction)
399 InlineDepth = 0;
400 else if (IsInlinedFunction)
401 ++InlineDepth;
403 // Traverse children.
404 unsigned LexicalBlockIndex = 0;
405 DWARFDie Child = Die.getFirstChild();
406 while (Child) {
407 std::string ChildVarPrefix = VarPrefix;
408 if (Child.getTag() == dwarf::DW_TAG_lexical_block)
409 ChildVarPrefix += toHex(LexicalBlockIndex++) + '.';
411 collectStatsRecursive(Child, FnPrefix, ChildVarPrefix, BytesInScope,
412 InlineDepth, FnStatMap, GlobalStats, LocStats);
413 Child = Child.getSibling();
417 /// Print machine-readable output.
418 /// The machine-readable format is single-line JSON output.
419 /// \{
420 static void printDatum(raw_ostream &OS, const char *Key, json::Value Value) {
421 OS << ",\"" << Key << "\":" << Value;
422 LLVM_DEBUG(llvm::dbgs() << Key << ": " << Value << '\n');
424 static void printLocationStats(raw_ostream &OS,
425 const char *Key,
426 std::vector<unsigned> &LocationStats) {
427 OS << ",\"" << Key << " with 0% of its scope covered\":"
428 << LocationStats[0];
429 LLVM_DEBUG(llvm::dbgs() << Key << " with 0% of its scope covered: "
430 << LocationStats[0] << '\n');
431 OS << ",\"" << Key << " with (0%,10%) of its scope covered\":"
432 << LocationStats[1];
433 LLVM_DEBUG(llvm::dbgs() << Key << " with (0%,10%) of its scope covered: "
434 << LocationStats[1] << '\n');
435 for (unsigned i = 2; i < NumOfCoverageCategories - 1; ++i) {
436 OS << ",\"" << Key << " with [" << (i - 1) * 10 << "%," << i * 10
437 << "%) of its scope covered\":" << LocationStats[i];
438 LLVM_DEBUG(llvm::dbgs()
439 << Key << " with [" << (i - 1) * 10 << "%," << i * 10
440 << "%) of its scope covered: " << LocationStats[i]);
442 OS << ",\"" << Key << " with 100% of its scope covered\":"
443 << LocationStats[NumOfCoverageCategories - 1];
444 LLVM_DEBUG(llvm::dbgs() << Key << " with 100% of its scope covered: "
445 << LocationStats[NumOfCoverageCategories - 1]);
447 /// \}
449 /// Collect debug info quality metrics for an entire DIContext.
451 /// Do the impossible and reduce the quality of the debug info down to a few
452 /// numbers. The idea is to condense the data into numbers that can be tracked
453 /// over time to identify trends in newer compiler versions and gauge the effect
454 /// of particular optimizations. The raw numbers themselves are not particularly
455 /// useful, only the delta between compiling the same program with different
456 /// compilers is.
457 bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
458 Twine Filename, raw_ostream &OS) {
459 StringRef FormatName = Obj.getFileFormatName();
460 GlobalStats GlobalStats;
461 LocationStats LocStats;
462 StringMap<PerFunctionStats> Statistics;
463 for (const auto &CU : static_cast<DWARFContext *>(&DICtx)->compile_units())
464 if (DWARFDie CUDie = CU->getNonSkeletonUnitDIE(false))
465 collectStatsRecursive(CUDie, "/", "g", 0, 0, Statistics, GlobalStats,
466 LocStats);
468 /// The version number should be increased every time the algorithm is changed
469 /// (including bug fixes). New metrics may be added without increasing the
470 /// version.
471 unsigned Version = 4;
472 unsigned VarParamTotal = 0;
473 unsigned VarParamUnique = 0;
474 unsigned VarParamWithLoc = 0;
475 unsigned NumFunctions = 0;
476 unsigned NumInlinedFunctions = 0;
477 unsigned NumFuncsWithSrcLoc = 0;
478 unsigned NumAbstractOrigins = 0;
479 unsigned ParamTotal = 0;
480 unsigned ParamWithType = 0;
481 unsigned ParamWithLoc = 0;
482 unsigned ParamWithSrcLoc = 0;
483 unsigned VarTotal = 0;
484 unsigned VarWithType = 0;
485 unsigned VarWithSrcLoc = 0;
486 unsigned VarWithLoc = 0;
487 for (auto &Entry : Statistics) {
488 PerFunctionStats &Stats = Entry.getValue();
489 unsigned TotalVars = Stats.VarsInFunction.size() * Stats.NumFnInlined;
490 // Count variables in concrete out-of-line functions and in global scope.
491 if (Stats.HasPCAddresses || !Stats.IsFunction)
492 TotalVars += Stats.VarsInFunction.size();
493 unsigned Constants = Stats.ConstantMembers;
494 VarParamWithLoc += Stats.TotalVarWithLoc + Constants;
495 VarParamTotal += TotalVars;
496 VarParamUnique += Stats.VarsInFunction.size();
497 LLVM_DEBUG(for (auto &V
498 : Stats.VarsInFunction) llvm::dbgs()
499 << Entry.getKey() << ": " << V.getKey() << "\n");
500 NumFunctions += Stats.IsFunction;
501 NumFuncsWithSrcLoc += Stats.HasSourceLocation;
502 NumInlinedFunctions += Stats.IsFunction * Stats.NumFnInlined;
503 NumAbstractOrigins += Stats.IsFunction * Stats.NumAbstractOrigins;
504 ParamTotal += Stats.NumParams;
505 ParamWithType += Stats.NumParamTypes;
506 ParamWithLoc += Stats.NumParamLocations;
507 ParamWithSrcLoc += Stats.NumParamSourceLocations;
508 VarTotal += Stats.NumVars;
509 VarWithType += Stats.NumVarTypes;
510 VarWithLoc += Stats.NumVarLocations;
511 VarWithSrcLoc += Stats.NumVarSourceLocations;
514 // Print summary.
515 OS.SetBufferSize(1024);
516 OS << "{\"version\":" << Version;
517 LLVM_DEBUG(llvm::dbgs() << "Variable location quality metrics\n";
518 llvm::dbgs() << "---------------------------------\n");
519 printDatum(OS, "file", Filename.str());
520 printDatum(OS, "format", FormatName);
521 printDatum(OS, "source functions", NumFunctions);
522 printDatum(OS, "source functions with location", NumFuncsWithSrcLoc);
523 printDatum(OS, "inlined functions", NumInlinedFunctions);
524 printDatum(OS, "inlined funcs with abstract origins", NumAbstractOrigins);
525 printDatum(OS, "unique source variables", VarParamUnique);
526 printDatum(OS, "source variables", VarParamTotal);
527 printDatum(OS, "variables with location", VarParamWithLoc);
528 printDatum(OS, "call site entries", GlobalStats.CallSiteEntries);
529 printDatum(OS, "call site DIEs", GlobalStats.CallSiteDIEs);
530 printDatum(OS, "call site parameter DIEs", GlobalStats.CallSiteParamDIEs);
531 printDatum(OS, "scope bytes total", GlobalStats.ScopeBytes);
532 printDatum(OS, "scope bytes covered", GlobalStats.ScopeBytesCovered);
533 printDatum(OS, "entry value scope bytes covered",
534 GlobalStats.ScopeEntryValueBytesCovered);
535 printDatum(OS, "formal params scope bytes total",
536 GlobalStats.ParamScopeBytes);
537 printDatum(OS, "formal params scope bytes covered",
538 GlobalStats.ParamScopeBytesCovered);
539 printDatum(OS, "formal params entry value scope bytes covered",
540 GlobalStats.ParamScopeEntryValueBytesCovered);
541 printDatum(OS, "vars scope bytes total", GlobalStats.VarScopeBytes);
542 printDatum(OS, "vars scope bytes covered", GlobalStats.VarScopeBytesCovered);
543 printDatum(OS, "vars entry value scope bytes covered",
544 GlobalStats.VarScopeEntryValueBytesCovered);
545 printDatum(OS, "total function size", GlobalStats.FunctionSize);
546 printDatum(OS, "total inlined function size", GlobalStats.InlineFunctionSize);
547 printDatum(OS, "total formal params", ParamTotal);
548 printDatum(OS, "formal params with source location", ParamWithSrcLoc);
549 printDatum(OS, "formal params with type", ParamWithType);
550 printDatum(OS, "formal params with binary location", ParamWithLoc);
551 printDatum(OS, "total vars", VarTotal);
552 printDatum(OS, "vars with source location", VarWithSrcLoc);
553 printDatum(OS, "vars with type", VarWithType);
554 printDatum(OS, "vars with binary location", VarWithLoc);
555 printDatum(OS, "total variables procesed by location statistics",
556 LocStats.NumVarParam);
557 printLocationStats(OS, "variables", LocStats.VarParamLocStats);
558 printLocationStats(OS, "variables (excluding the debug entry values)",
559 LocStats.VarParamNonEntryValLocStats);
560 printDatum(OS, "total params procesed by location statistics",
561 LocStats.NumParam);
562 printLocationStats(OS, "params", LocStats.ParamLocStats);
563 printLocationStats(OS, "params (excluding the debug entry values)",
564 LocStats.ParamNonEntryValLocStats);
565 printDatum(OS, "total vars procesed by location statistics", LocStats.NumVar);
566 printLocationStats(OS, "vars", LocStats.VarLocStats);
567 printLocationStats(OS, "vars (excluding the debug entry values)",
568 LocStats.VarNonEntryValLocStats);
569 OS << "}\n";
570 LLVM_DEBUG(
571 llvm::dbgs() << "Total Availability: "
572 << (int)std::round((VarParamWithLoc * 100.0) / VarParamTotal)
573 << "%\n";
574 llvm::dbgs() << "PC Ranges covered: "
575 << (int)std::round((GlobalStats.ScopeBytesCovered * 100.0) /
576 GlobalStats.ScopeBytes)
577 << "%\n");
578 return true;