[SimplifyCFG] FoldTwoEntryPHINode(): consider *total* speculation cost, not per-BB...
[llvm-complete.git] / tools / llvm-dwarfdump / Statistics.cpp
blob268ab5f79b679ac1a9d35dba177dcc4e0667fa7c
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"
9 #define DEBUG_TYPE "dwarfdump"
10 using namespace llvm;
11 using namespace object;
13 /// This represents the number of categories of debug location coverage being
14 /// calculated. The first category is the number of variables with 0% location
15 /// coverage, but the last category is the number of variables with 100%
16 /// location coverage.
17 constexpr int NumOfCoverageCategories = 12;
19 /// Holds statistics for one function (or other entity that has a PC range and
20 /// contains variables, such as a compile unit).
21 struct PerFunctionStats {
22 /// Number of inlined instances of this function.
23 unsigned NumFnInlined = 0;
24 /// Number of inlined instances that have abstract origins.
25 unsigned NumAbstractOrigins = 0;
26 /// Number of variables and parameters with location across all inlined
27 /// instances.
28 unsigned TotalVarWithLoc = 0;
29 /// Number of constants with location across all inlined instances.
30 unsigned ConstantMembers = 0;
31 /// List of all Variables and parameters in this function.
32 StringSet<> VarsInFunction;
33 /// Compile units also cover a PC range, but have this flag set to false.
34 bool IsFunction = false;
35 /// Verify function definition has PC addresses (for detecting when
36 /// a function has been inlined everywhere).
37 bool HasPCAddresses = false;
38 /// Function has source location information.
39 bool HasSourceLocation = false;
40 /// Number of function parameters.
41 unsigned NumParams = 0;
42 /// Number of function parameters with source location.
43 unsigned NumParamSourceLocations = 0;
44 /// Number of function parameters with type.
45 unsigned NumParamTypes = 0;
46 /// Number of function parameters with a DW_AT_location.
47 unsigned NumParamLocations = 0;
48 /// Number of variables.
49 unsigned NumVars = 0;
50 /// Number of variables with source location.
51 unsigned NumVarSourceLocations = 0;
52 /// Number of variables with type.
53 unsigned NumVarTypes = 0;
54 /// Number of variables with DW_AT_location.
55 unsigned NumVarLocations = 0;
58 /// Holds accumulated global statistics about DIEs.
59 struct GlobalStats {
60 /// Total number of PC range bytes covered by DW_AT_locations.
61 unsigned ScopeBytesCovered = 0;
62 /// Total number of PC range bytes in each variable's enclosing scope,
63 /// starting from the first definition of the variable.
64 unsigned ScopeBytesFromFirstDefinition = 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 /// starting from the first definition of the variable (only for parameters).
73 unsigned ParamScopeBytesFromFirstDefinition = 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 /// starting from the first definition of the variable (only for local
82 /// variables).
83 unsigned VarScopeBytesFromFirstDefinition = 0;
84 /// Total number of PC range bytes covered by DW_AT_locations with
85 /// the debug entry values (DW_OP_entry_value) (only for local variables).
86 unsigned VarScopeEntryValueBytesCovered = 0;
87 /// Total number of call site entries (DW_AT_call_file & DW_AT_call_line).
88 unsigned CallSiteEntries = 0;
89 /// Total number of call site DIEs (DW_TAG_call_site).
90 unsigned CallSiteDIEs = 0;
91 /// Total number of call site parameter DIEs (DW_TAG_call_site_parameter).
92 unsigned CallSiteParamDIEs = 0;
93 /// Total byte size of concrete functions. This byte size includes
94 /// inline functions contained in the concrete functions.
95 uint64_t FunctionSize = 0;
96 /// Total byte size of inlined functions. This is the total number of bytes
97 /// for the top inline functions within concrete functions. This can help
98 /// tune the inline settings when compiling to match user expectations.
99 uint64_t InlineFunctionSize = 0;
102 /// Holds accumulated debug location statistics about local variables and
103 /// formal parameters.
104 struct LocationStats {
105 /// Map the scope coverage decile to the number of variables in the decile.
106 /// The first element of the array (at the index zero) represents the number
107 /// of variables with the no debug location at all, but the last element
108 /// in the vector represents the number of fully covered variables within
109 /// its scope.
110 std::vector<unsigned> VarParamLocStats{
111 std::vector<unsigned>(NumOfCoverageCategories, 0)};
112 /// Map non debug entry values coverage.
113 std::vector<unsigned> VarParamNonEntryValLocStats{
114 std::vector<unsigned>(NumOfCoverageCategories, 0)};
115 /// The debug location statistics for formal parameters.
116 std::vector<unsigned> ParamLocStats{
117 std::vector<unsigned>(NumOfCoverageCategories, 0)};
118 /// Map non debug entry values coverage for formal parameters.
119 std::vector<unsigned> ParamNonEntryValLocStats{
120 std::vector<unsigned>(NumOfCoverageCategories, 0)};
121 /// The debug location statistics for local variables.
122 std::vector<unsigned> VarLocStats{
123 std::vector<unsigned>(NumOfCoverageCategories, 0)};
124 /// Map non debug entry values coverage for local variables.
125 std::vector<unsigned> VarNonEntryValLocStats{
126 std::vector<unsigned>(NumOfCoverageCategories, 0)};
127 /// Total number of local variables and function parameters processed.
128 unsigned NumVarParam = 0;
129 /// Total number of formal parameters processed.
130 unsigned NumParam = 0;
131 /// Total number of local variables processed.
132 unsigned NumVar = 0;
135 /// Extract the low pc from a Die.
136 static uint64_t getLowPC(DWARFDie Die) {
137 auto RangesOrError = Die.getAddressRanges();
138 DWARFAddressRangesVector Ranges;
139 if (RangesOrError)
140 Ranges = RangesOrError.get();
141 else
142 llvm::consumeError(RangesOrError.takeError());
143 if (Ranges.size())
144 return Ranges[0].LowPC;
145 return dwarf::toAddress(Die.find(dwarf::DW_AT_low_pc), 0);
148 /// Collect debug location statistics for one DIE.
149 static void collectLocStats(uint64_t BytesCovered, uint64_t BytesInScope,
150 std::vector<unsigned> &VarParamLocStats,
151 std::vector<unsigned> &ParamLocStats,
152 std::vector<unsigned> &VarLocStats, bool IsParam,
153 bool IsLocalVar) {
154 auto getCoverageBucket = [BytesCovered, BytesInScope]() -> unsigned {
155 unsigned LocBucket = 100 * (double)BytesCovered / BytesInScope;
156 if (LocBucket == 0) {
157 // No debug location at all for the variable.
158 return 0;
159 } else if (LocBucket == 100 || BytesCovered > BytesInScope) {
160 // Fully covered variable within its scope.
161 return NumOfCoverageCategories - 1;
162 } else {
163 // Get covered range (e.g. 20%-29%).
164 LocBucket /= 10;
165 return LocBucket + 1;
169 unsigned CoverageBucket = getCoverageBucket();
170 VarParamLocStats[CoverageBucket]++;
171 if (IsParam)
172 ParamLocStats[CoverageBucket]++;
173 else if (IsLocalVar)
174 VarLocStats[CoverageBucket]++;
177 /// Collect debug info quality metrics for one DIE.
178 static void collectStatsForDie(DWARFDie Die, uint64_t UnitLowPC, std::string FnPrefix,
179 std::string VarPrefix, uint64_t ScopeLowPC,
180 uint64_t BytesInScope, uint32_t InlineDepth,
181 StringMap<PerFunctionStats> &FnStatMap,
182 GlobalStats &GlobalStats,
183 LocationStats &LocStats) {
184 bool HasLoc = false;
185 bool HasSrcLoc = false;
186 bool HasType = false;
187 bool IsArtificial = false;
188 uint64_t BytesCovered = 0;
189 uint64_t BytesEntryValuesCovered = 0;
190 uint64_t OffsetToFirstDefinition = 0;
191 auto &FnStats = FnStatMap[FnPrefix];
192 bool IsParam = Die.getTag() == dwarf::DW_TAG_formal_parameter;
193 bool IsLocalVar = Die.getTag() == dwarf::DW_TAG_variable;
195 if (Die.getTag() == dwarf::DW_TAG_call_site ||
196 Die.getTag() == dwarf::DW_TAG_GNU_call_site) {
197 GlobalStats.CallSiteDIEs++;
198 return;
201 if (Die.getTag() == dwarf::DW_TAG_call_site_parameter ||
202 Die.getTag() == dwarf::DW_TAG_GNU_call_site_parameter) {
203 GlobalStats.CallSiteParamDIEs++;
204 return;
207 if (!IsParam && !IsLocalVar && Die.getTag() != dwarf::DW_TAG_member) {
208 // Not a variable or constant member.
209 return;
212 if (Die.findRecursively(dwarf::DW_AT_decl_file) &&
213 Die.findRecursively(dwarf::DW_AT_decl_line))
214 HasSrcLoc = true;
216 if (Die.findRecursively(dwarf::DW_AT_type))
217 HasType = true;
219 if (Die.find(dwarf::DW_AT_artificial))
220 IsArtificial = true;
222 auto IsEntryValue = [&](ArrayRef<uint8_t> D) -> bool {
223 DWARFUnit *U = Die.getDwarfUnit();
224 DataExtractor Data(toStringRef(D),
225 Die.getDwarfUnit()->getContext().isLittleEndian(), 0);
226 DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize());
227 // Consider the expression containing the DW_OP_entry_value as
228 // an entry value.
229 return llvm::any_of(Expression, [](DWARFExpression::Operation &Op) {
230 return Op.getCode() == dwarf::DW_OP_entry_value ||
231 Op.getCode() == dwarf::DW_OP_GNU_entry_value;
235 if (Die.find(dwarf::DW_AT_const_value)) {
236 // This catches constant members *and* variables.
237 HasLoc = true;
238 BytesCovered = BytesInScope;
239 } else {
240 if (Die.getTag() == dwarf::DW_TAG_member) {
241 // Non-const member.
242 return;
244 // Handle variables and function arguments.
245 auto FormValue = Die.find(dwarf::DW_AT_location);
246 HasLoc = FormValue.hasValue();
247 if (HasLoc) {
248 // Get PC coverage.
249 if (auto DebugLocOffset = FormValue->getAsSectionOffset()) {
250 auto *DebugLoc = Die.getDwarfUnit()->getContext().getDebugLoc();
251 if (auto List = DebugLoc->getLocationListAtOffset(*DebugLocOffset)) {
252 for (auto Entry : List->Entries) {
253 uint64_t BytesEntryCovered = Entry.End - Entry.Begin;
254 BytesCovered += BytesEntryCovered;
255 if (IsEntryValue(Entry.Loc))
256 BytesEntryValuesCovered += BytesEntryCovered;
258 if (List->Entries.size()) {
259 uint64_t FirstDef = List->Entries[0].Begin;
260 uint64_t UnitOfs = UnitLowPC;
261 // Ranges sometimes start before the lexical scope.
262 if (UnitOfs + FirstDef >= ScopeLowPC)
263 OffsetToFirstDefinition = UnitOfs + FirstDef - ScopeLowPC;
264 // Or even after it. Count that as a failure.
265 if (OffsetToFirstDefinition > BytesInScope)
266 OffsetToFirstDefinition = 0;
269 assert(BytesInScope);
270 } else {
271 // Assume the entire range is covered by a single location.
272 BytesCovered = BytesInScope;
277 // Calculate the debug location statistics.
278 if (BytesInScope) {
279 LocStats.NumVarParam++;
280 if (IsParam)
281 LocStats.NumParam++;
282 else if (IsLocalVar)
283 LocStats.NumVar++;
285 collectLocStats(BytesCovered, BytesInScope, LocStats.VarParamLocStats,
286 LocStats.ParamLocStats, LocStats.VarLocStats, IsParam,
287 IsLocalVar);
288 // Non debug entry values coverage statistics.
289 collectLocStats(BytesCovered - BytesEntryValuesCovered, BytesInScope,
290 LocStats.VarParamNonEntryValLocStats,
291 LocStats.ParamNonEntryValLocStats,
292 LocStats.VarNonEntryValLocStats, IsParam, IsLocalVar);
295 // Collect PC range coverage data.
296 if (DWARFDie D =
297 Die.getAttributeValueAsReferencedDie(dwarf::DW_AT_abstract_origin))
298 Die = D;
299 // By using the variable name + the path through the lexical block tree, the
300 // keys are consistent across duplicate abstract origins in different CUs.
301 std::string VarName = StringRef(Die.getName(DINameKind::ShortName));
302 FnStats.VarsInFunction.insert(VarPrefix + VarName);
303 if (BytesInScope) {
304 FnStats.TotalVarWithLoc += (unsigned)HasLoc;
305 // Adjust for the fact the variables often start their lifetime in the
306 // middle of the scope.
307 BytesInScope -= OffsetToFirstDefinition;
308 // Turns out we have a lot of ranges that extend past the lexical scope.
309 GlobalStats.ScopeBytesCovered += std::min(BytesInScope, BytesCovered);
310 GlobalStats.ScopeBytesFromFirstDefinition += BytesInScope;
311 GlobalStats.ScopeEntryValueBytesCovered += BytesEntryValuesCovered;
312 if (IsParam) {
313 GlobalStats.ParamScopeBytesCovered +=
314 std::min(BytesInScope, BytesCovered);
315 GlobalStats.ParamScopeBytesFromFirstDefinition += BytesInScope;
316 GlobalStats.ParamScopeEntryValueBytesCovered += BytesEntryValuesCovered;
317 } else if (IsLocalVar) {
318 GlobalStats.VarScopeBytesCovered += std::min(BytesInScope, BytesCovered);
319 GlobalStats.VarScopeBytesFromFirstDefinition += BytesInScope;
320 GlobalStats.VarScopeEntryValueBytesCovered += BytesEntryValuesCovered;
322 assert(GlobalStats.ScopeBytesCovered <=
323 GlobalStats.ScopeBytesFromFirstDefinition);
324 } else if (Die.getTag() == dwarf::DW_TAG_member) {
325 FnStats.ConstantMembers++;
326 } else {
327 FnStats.TotalVarWithLoc += (unsigned)HasLoc;
329 if (!IsArtificial) {
330 if (IsParam) {
331 FnStats.NumParams++;
332 if (HasType)
333 FnStats.NumParamTypes++;
334 if (HasSrcLoc)
335 FnStats.NumParamSourceLocations++;
336 if (HasLoc)
337 FnStats.NumParamLocations++;
338 } else if (IsLocalVar) {
339 FnStats.NumVars++;
340 if (HasType)
341 FnStats.NumVarTypes++;
342 if (HasSrcLoc)
343 FnStats.NumVarSourceLocations++;
344 if (HasLoc)
345 FnStats.NumVarLocations++;
350 /// Recursively collect debug info quality metrics.
351 static void collectStatsRecursive(DWARFDie Die, uint64_t UnitLowPC, std::string FnPrefix,
352 std::string VarPrefix, uint64_t ScopeLowPC,
353 uint64_t BytesInScope, uint32_t InlineDepth,
354 StringMap<PerFunctionStats> &FnStatMap,
355 GlobalStats &GlobalStats,
356 LocationStats &LocStats) {
357 // Handle any kind of lexical scope.
358 const dwarf::Tag Tag = Die.getTag();
359 const bool IsFunction = Tag == dwarf::DW_TAG_subprogram;
360 const bool IsBlock = Tag == dwarf::DW_TAG_lexical_block;
361 const bool IsInlinedFunction = Tag == dwarf::DW_TAG_inlined_subroutine;
362 if (IsFunction || IsInlinedFunction || IsBlock) {
364 // Reset VarPrefix when entering a new function.
365 if (Die.getTag() == dwarf::DW_TAG_subprogram ||
366 Die.getTag() == dwarf::DW_TAG_inlined_subroutine)
367 VarPrefix = "v";
369 // Ignore forward declarations.
370 if (Die.find(dwarf::DW_AT_declaration))
371 return;
373 // Check for call sites.
374 if (Die.find(dwarf::DW_AT_call_file) && Die.find(dwarf::DW_AT_call_line))
375 GlobalStats.CallSiteEntries++;
377 // PC Ranges.
378 auto RangesOrError = Die.getAddressRanges();
379 if (!RangesOrError) {
380 llvm::consumeError(RangesOrError.takeError());
381 return;
384 auto Ranges = RangesOrError.get();
385 uint64_t BytesInThisScope = 0;
386 for (auto Range : Ranges)
387 BytesInThisScope += Range.HighPC - Range.LowPC;
388 ScopeLowPC = getLowPC(Die);
390 // Count the function.
391 if (!IsBlock) {
392 StringRef Name = Die.getName(DINameKind::LinkageName);
393 if (Name.empty())
394 Name = Die.getName(DINameKind::ShortName);
395 FnPrefix = Name;
396 // Skip over abstract origins.
397 if (Die.find(dwarf::DW_AT_inline))
398 return;
399 // We've seen an (inlined) instance of this function.
400 auto &FnStats = FnStatMap[Name];
401 if (IsInlinedFunction) {
402 FnStats.NumFnInlined++;
403 if (Die.findRecursively(dwarf::DW_AT_abstract_origin))
404 FnStats.NumAbstractOrigins++;
406 FnStats.IsFunction = true;
407 if (BytesInThisScope && !IsInlinedFunction)
408 FnStats.HasPCAddresses = true;
409 std::string FnName = StringRef(Die.getName(DINameKind::ShortName));
410 if (Die.findRecursively(dwarf::DW_AT_decl_file) &&
411 Die.findRecursively(dwarf::DW_AT_decl_line))
412 FnStats.HasSourceLocation = true;
415 if (BytesInThisScope) {
416 BytesInScope = BytesInThisScope;
417 if (IsFunction)
418 GlobalStats.FunctionSize += BytesInThisScope;
419 else if (IsInlinedFunction && InlineDepth == 0)
420 GlobalStats.InlineFunctionSize += BytesInThisScope;
422 } else {
423 // Not a scope, visit the Die itself. It could be a variable.
424 collectStatsForDie(Die, UnitLowPC, FnPrefix, VarPrefix, ScopeLowPC, BytesInScope,
425 InlineDepth, FnStatMap, GlobalStats, LocStats);
428 // Set InlineDepth correctly for child recursion
429 if (IsFunction)
430 InlineDepth = 0;
431 else if (IsInlinedFunction)
432 ++InlineDepth;
434 // Traverse children.
435 unsigned LexicalBlockIndex = 0;
436 DWARFDie Child = Die.getFirstChild();
437 while (Child) {
438 std::string ChildVarPrefix = VarPrefix;
439 if (Child.getTag() == dwarf::DW_TAG_lexical_block)
440 ChildVarPrefix += toHex(LexicalBlockIndex++) + '.';
442 collectStatsRecursive(Child, UnitLowPC, FnPrefix, ChildVarPrefix, ScopeLowPC,
443 BytesInScope, InlineDepth, FnStatMap, GlobalStats,
444 LocStats);
445 Child = Child.getSibling();
449 /// Print machine-readable output.
450 /// The machine-readable format is single-line JSON output.
451 /// \{
452 static void printDatum(raw_ostream &OS, const char *Key, StringRef Value) {
453 OS << ",\"" << Key << "\":\"" << Value << '"';
454 LLVM_DEBUG(llvm::dbgs() << Key << ": " << Value << '\n');
456 static void printDatum(raw_ostream &OS, const char *Key, uint64_t Value) {
457 OS << ",\"" << Key << "\":" << Value;
458 LLVM_DEBUG(llvm::dbgs() << Key << ": " << Value << '\n');
460 static void printLocationStats(raw_ostream &OS,
461 const char *Key,
462 std::vector<unsigned> &LocationStats) {
463 OS << ",\"" << Key << " with 0% of its scope covered\":"
464 << LocationStats[0];
465 LLVM_DEBUG(llvm::dbgs() << Key << " with 0% of its scope covered: "
466 << LocationStats[0] << '\n');
467 OS << ",\"" << Key << " with 1-9% of its scope covered\":"
468 << LocationStats[1];
469 LLVM_DEBUG(llvm::dbgs() << Key << " with 1-9% of its scope covered: "
470 << LocationStats[1] << '\n');
471 for (unsigned i = 2; i < NumOfCoverageCategories - 1; ++i) {
472 OS << ",\"" << Key << " with " << (i - 1) * 10 << "-" << i * 10 - 1
473 << "% of its scope covered\":" << LocationStats[i];
474 LLVM_DEBUG(llvm::dbgs()
475 << Key << " with " << (i - 1) * 10 << "-" << i * 10 - 1
476 << "% of its scope covered: " << LocationStats[i]);
478 OS << ",\"" << Key << " with 100% of its scope covered\":"
479 << LocationStats[NumOfCoverageCategories - 1];
480 LLVM_DEBUG(llvm::dbgs() << Key << " with 100% of its scope covered: "
481 << LocationStats[NumOfCoverageCategories - 1]);
483 /// \}
485 /// Collect debug info quality metrics for an entire DIContext.
487 /// Do the impossible and reduce the quality of the debug info down to a few
488 /// numbers. The idea is to condense the data into numbers that can be tracked
489 /// over time to identify trends in newer compiler versions and gauge the effect
490 /// of particular optimizations. The raw numbers themselves are not particularly
491 /// useful, only the delta between compiling the same program with different
492 /// compilers is.
493 bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
494 Twine Filename, raw_ostream &OS) {
495 StringRef FormatName = Obj.getFileFormatName();
496 GlobalStats GlobalStats;
497 LocationStats LocStats;
498 StringMap<PerFunctionStats> Statistics;
499 for (const auto &CU : static_cast<DWARFContext *>(&DICtx)->compile_units())
500 if (DWARFDie CUDie = CU->getNonSkeletonUnitDIE(false))
501 collectStatsRecursive(CUDie, getLowPC(CUDie), "/", "g", 0, 0, 0,
502 Statistics, GlobalStats, LocStats);
504 /// The version number should be increased every time the algorithm is changed
505 /// (including bug fixes). New metrics may be added without increasing the
506 /// version.
507 unsigned Version = 3;
508 unsigned VarParamTotal = 0;
509 unsigned VarParamUnique = 0;
510 unsigned VarParamWithLoc = 0;
511 unsigned NumFunctions = 0;
512 unsigned NumInlinedFunctions = 0;
513 unsigned NumFuncsWithSrcLoc = 0;
514 unsigned NumAbstractOrigins = 0;
515 unsigned ParamTotal = 0;
516 unsigned ParamWithType = 0;
517 unsigned ParamWithLoc = 0;
518 unsigned ParamWithSrcLoc = 0;
519 unsigned VarTotal = 0;
520 unsigned VarWithType = 0;
521 unsigned VarWithSrcLoc = 0;
522 unsigned VarWithLoc = 0;
523 for (auto &Entry : Statistics) {
524 PerFunctionStats &Stats = Entry.getValue();
525 unsigned TotalVars = Stats.VarsInFunction.size() * Stats.NumFnInlined;
526 // Count variables in concrete out-of-line functions and in global scope.
527 if (Stats.HasPCAddresses || !Stats.IsFunction)
528 TotalVars += Stats.VarsInFunction.size();
529 unsigned Constants = Stats.ConstantMembers;
530 VarParamWithLoc += Stats.TotalVarWithLoc + Constants;
531 VarParamTotal += TotalVars;
532 VarParamUnique += Stats.VarsInFunction.size();
533 LLVM_DEBUG(for (auto &V
534 : Stats.VarsInFunction) llvm::dbgs()
535 << Entry.getKey() << ": " << V.getKey() << "\n");
536 NumFunctions += Stats.IsFunction;
537 NumFuncsWithSrcLoc += Stats.HasSourceLocation;
538 NumInlinedFunctions += Stats.IsFunction * Stats.NumFnInlined;
539 NumAbstractOrigins += Stats.IsFunction * Stats.NumAbstractOrigins;
540 ParamTotal += Stats.NumParams;
541 ParamWithType += Stats.NumParamTypes;
542 ParamWithLoc += Stats.NumParamLocations;
543 ParamWithSrcLoc += Stats.NumParamSourceLocations;
544 VarTotal += Stats.NumVars;
545 VarWithType += Stats.NumVarTypes;
546 VarWithLoc += Stats.NumVarLocations;
547 VarWithSrcLoc += Stats.NumVarSourceLocations;
550 // Print summary.
551 OS.SetBufferSize(1024);
552 OS << "{\"version\":" << Version;
553 LLVM_DEBUG(llvm::dbgs() << "Variable location quality metrics\n";
554 llvm::dbgs() << "---------------------------------\n");
555 printDatum(OS, "file", Filename.str());
556 printDatum(OS, "format", FormatName);
557 printDatum(OS, "source functions", NumFunctions);
558 printDatum(OS, "source functions with location", NumFuncsWithSrcLoc);
559 printDatum(OS, "inlined functions", NumInlinedFunctions);
560 printDatum(OS, "inlined funcs with abstract origins", NumAbstractOrigins);
561 printDatum(OS, "unique source variables", VarParamUnique);
562 printDatum(OS, "source variables", VarParamTotal);
563 printDatum(OS, "variables with location", VarParamWithLoc);
564 printDatum(OS, "call site entries", GlobalStats.CallSiteEntries);
565 printDatum(OS, "call site DIEs", GlobalStats.CallSiteDIEs);
566 printDatum(OS, "call site parameter DIEs", GlobalStats.CallSiteParamDIEs);
567 printDatum(OS, "scope bytes total",
568 GlobalStats.ScopeBytesFromFirstDefinition);
569 printDatum(OS, "scope bytes covered", GlobalStats.ScopeBytesCovered);
570 printDatum(OS, "entry value scope bytes covered",
571 GlobalStats.ScopeEntryValueBytesCovered);
572 printDatum(OS, "formal params scope bytes total",
573 GlobalStats.ParamScopeBytesFromFirstDefinition);
574 printDatum(OS, "formal params scope bytes covered",
575 GlobalStats.ParamScopeBytesCovered);
576 printDatum(OS, "formal params entry value scope bytes covered",
577 GlobalStats.ParamScopeEntryValueBytesCovered);
578 printDatum(OS, "vars scope bytes total",
579 GlobalStats.VarScopeBytesFromFirstDefinition);
580 printDatum(OS, "vars scope bytes covered", GlobalStats.VarScopeBytesCovered);
581 printDatum(OS, "vars entry value scope bytes covered",
582 GlobalStats.VarScopeEntryValueBytesCovered);
583 printDatum(OS, "total function size", GlobalStats.FunctionSize);
584 printDatum(OS, "total inlined function size", GlobalStats.InlineFunctionSize);
585 printDatum(OS, "total formal params", ParamTotal);
586 printDatum(OS, "formal params with source location", ParamWithSrcLoc);
587 printDatum(OS, "formal params with type", ParamWithType);
588 printDatum(OS, "formal params with binary location", ParamWithLoc);
589 printDatum(OS, "total vars", VarTotal);
590 printDatum(OS, "vars with source location", VarWithSrcLoc);
591 printDatum(OS, "vars with type", VarWithType);
592 printDatum(OS, "vars with binary location", VarWithLoc);
593 printDatum(OS, "total variables procesed by location statistics",
594 LocStats.NumVarParam);
595 printLocationStats(OS, "variables", LocStats.VarParamLocStats);
596 printLocationStats(OS, "variables (excluding the debug entry values)",
597 LocStats.VarParamNonEntryValLocStats);
598 printDatum(OS, "total params procesed by location statistics",
599 LocStats.NumParam);
600 printLocationStats(OS, "params", LocStats.ParamLocStats);
601 printLocationStats(OS, "params (excluding the debug entry values)",
602 LocStats.ParamNonEntryValLocStats);
603 printDatum(OS, "total vars procesed by location statistics", LocStats.NumVar);
604 printLocationStats(OS, "vars", LocStats.VarLocStats);
605 printLocationStats(OS, "vars (excluding the debug entry values)",
606 LocStats.ParamNonEntryValLocStats);
607 OS << "}\n";
608 LLVM_DEBUG(
609 llvm::dbgs() << "Total Availability: "
610 << (int)std::round((VarParamWithLoc * 100.0) / VarParamTotal)
611 << "%\n";
612 llvm::dbgs() << "PC Ranges covered: "
613 << (int)std::round((GlobalStats.ScopeBytesCovered * 100.0) /
614 GlobalStats.ScopeBytesFromFirstDefinition)
615 << "%\n");
616 return true;