xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp (revision 5956d97f4b3204318ceb6aa9c77bd0bc6ea87a41)
1 //===-- Statistics.cpp - Debug Info quality metrics -----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm-dwarfdump.h"
10 #include "llvm/ADT/DenseMap.h"
11 #include "llvm/ADT/StringSet.h"
12 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
13 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
14 #include "llvm/Object/ObjectFile.h"
15 #include "llvm/Support/JSON.h"
16 
17 #define DEBUG_TYPE "dwarfdump"
18 using namespace llvm;
19 using namespace llvm::dwarfdump;
20 using namespace llvm::object;
21 
22 namespace {
23 /// This represents the number of categories of debug location coverage being
24 /// calculated. The first category is the number of variables with 0% location
25 /// coverage, but the last category is the number of variables with 100%
26 /// location coverage.
27 constexpr int NumOfCoverageCategories = 12;
28 
29 /// This is used for zero location coverage bucket.
30 constexpr unsigned ZeroCoverageBucket = 0;
31 
32 /// The UINT64_MAX is used as an indication of the overflow.
33 constexpr uint64_t OverflowValue = std::numeric_limits<uint64_t>::max();
34 
35 /// This represents variables DIE offsets.
36 using AbstractOriginVarsTy = llvm::SmallVector<uint64_t>;
37 /// This maps function DIE offset to its variables.
38 using AbstractOriginVarsTyMap = llvm::DenseMap<uint64_t, AbstractOriginVarsTy>;
39 /// This represents function DIE offsets containing an abstract_origin.
40 using FunctionsWithAbstractOriginTy = llvm::SmallVector<uint64_t>;
41 
42 /// This represents a data type for the stats and it helps us to
43 /// detect an overflow.
44 /// NOTE: This can be implemented as a template if there is an another type
45 /// needing this.
46 struct SaturatingUINT64 {
47   /// Number that represents the stats.
48   uint64_t Value;
49 
50   SaturatingUINT64(uint64_t Value_) : Value(Value_) {}
51 
52   void operator++(int) { return *this += 1; }
53   void operator+=(uint64_t Value_) {
54     if (Value != OverflowValue) {
55       if (Value < OverflowValue - Value_)
56         Value += Value_;
57       else
58         Value = OverflowValue;
59     }
60   }
61 };
62 
63 /// Utility struct to store the full location of a DIE - its CU and offset.
64 struct DIELocation {
65   DWARFUnit *DwUnit;
66   uint64_t DIEOffset;
67   DIELocation(DWARFUnit *_DwUnit, uint64_t _DIEOffset)
68       : DwUnit(_DwUnit), DIEOffset(_DIEOffset) {}
69 };
70 /// This represents DWARF locations of CrossCU referencing DIEs.
71 using CrossCUReferencingDIELocationTy = llvm::SmallVector<DIELocation>;
72 
73 /// This maps function DIE offset to its DWARF CU.
74 using FunctionDIECUTyMap = llvm::DenseMap<uint64_t, DWARFUnit *>;
75 
76 /// Holds statistics for one function (or other entity that has a PC range and
77 /// contains variables, such as a compile unit).
78 struct PerFunctionStats {
79   /// Number of inlined instances of this function.
80   uint64_t NumFnInlined = 0;
81   /// Number of out-of-line instances of this function.
82   uint64_t NumFnOutOfLine = 0;
83   /// Number of inlined instances that have abstract origins.
84   uint64_t NumAbstractOrigins = 0;
85   /// Number of variables and parameters with location across all inlined
86   /// instances.
87   uint64_t TotalVarWithLoc = 0;
88   /// Number of constants with location across all inlined instances.
89   uint64_t ConstantMembers = 0;
90   /// Number of arificial variables, parameters or members across all instances.
91   uint64_t NumArtificial = 0;
92   /// List of all Variables and parameters in this function.
93   StringSet<> VarsInFunction;
94   /// Compile units also cover a PC range, but have this flag set to false.
95   bool IsFunction = false;
96   /// Function has source location information.
97   bool HasSourceLocation = false;
98   /// Number of function parameters.
99   uint64_t NumParams = 0;
100   /// Number of function parameters with source location.
101   uint64_t NumParamSourceLocations = 0;
102   /// Number of function parameters with type.
103   uint64_t NumParamTypes = 0;
104   /// Number of function parameters with a DW_AT_location.
105   uint64_t NumParamLocations = 0;
106   /// Number of local variables.
107   uint64_t NumLocalVars = 0;
108   /// Number of local variables with source location.
109   uint64_t NumLocalVarSourceLocations = 0;
110   /// Number of local variables with type.
111   uint64_t NumLocalVarTypes = 0;
112   /// Number of local variables with DW_AT_location.
113   uint64_t NumLocalVarLocations = 0;
114 };
115 
116 /// Holds accumulated global statistics about DIEs.
117 struct GlobalStats {
118   /// Total number of PC range bytes covered by DW_AT_locations.
119   SaturatingUINT64 TotalBytesCovered = 0;
120   /// Total number of parent DIE PC range bytes covered by DW_AT_Locations.
121   SaturatingUINT64 ScopeBytesCovered = 0;
122   /// Total number of PC range bytes in each variable's enclosing scope.
123   SaturatingUINT64 ScopeBytes = 0;
124   /// Total number of PC range bytes covered by DW_AT_locations with
125   /// the debug entry values (DW_OP_entry_value).
126   SaturatingUINT64 ScopeEntryValueBytesCovered = 0;
127   /// Total number of PC range bytes covered by DW_AT_locations of
128   /// formal parameters.
129   SaturatingUINT64 ParamScopeBytesCovered = 0;
130   /// Total number of PC range bytes in each parameter's enclosing scope.
131   SaturatingUINT64 ParamScopeBytes = 0;
132   /// Total number of PC range bytes covered by DW_AT_locations with
133   /// the debug entry values (DW_OP_entry_value) (only for parameters).
134   SaturatingUINT64 ParamScopeEntryValueBytesCovered = 0;
135   /// Total number of PC range bytes covered by DW_AT_locations (only for local
136   /// variables).
137   SaturatingUINT64 LocalVarScopeBytesCovered = 0;
138   /// Total number of PC range bytes in each local variable's enclosing scope.
139   SaturatingUINT64 LocalVarScopeBytes = 0;
140   /// Total number of PC range bytes covered by DW_AT_locations with
141   /// the debug entry values (DW_OP_entry_value) (only for local variables).
142   SaturatingUINT64 LocalVarScopeEntryValueBytesCovered = 0;
143   /// Total number of call site entries (DW_AT_call_file & DW_AT_call_line).
144   SaturatingUINT64 CallSiteEntries = 0;
145   /// Total number of call site DIEs (DW_TAG_call_site).
146   SaturatingUINT64 CallSiteDIEs = 0;
147   /// Total number of call site parameter DIEs (DW_TAG_call_site_parameter).
148   SaturatingUINT64 CallSiteParamDIEs = 0;
149   /// Total byte size of concrete functions. This byte size includes
150   /// inline functions contained in the concrete functions.
151   SaturatingUINT64 FunctionSize = 0;
152   /// Total byte size of inlined functions. This is the total number of bytes
153   /// for the top inline functions within concrete functions. This can help
154   /// tune the inline settings when compiling to match user expectations.
155   SaturatingUINT64 InlineFunctionSize = 0;
156 };
157 
158 /// Holds accumulated debug location statistics about local variables and
159 /// formal parameters.
160 struct LocationStats {
161   /// Map the scope coverage decile to the number of variables in the decile.
162   /// The first element of the array (at the index zero) represents the number
163   /// of variables with the no debug location at all, but the last element
164   /// in the vector represents the number of fully covered variables within
165   /// its scope.
166   std::vector<SaturatingUINT64> VarParamLocStats{
167       std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
168   /// Map non debug entry values coverage.
169   std::vector<SaturatingUINT64> VarParamNonEntryValLocStats{
170       std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
171   /// The debug location statistics for formal parameters.
172   std::vector<SaturatingUINT64> ParamLocStats{
173       std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
174   /// Map non debug entry values coverage for formal parameters.
175   std::vector<SaturatingUINT64> ParamNonEntryValLocStats{
176       std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
177   /// The debug location statistics for local variables.
178   std::vector<SaturatingUINT64> LocalVarLocStats{
179       std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
180   /// Map non debug entry values coverage for local variables.
181   std::vector<SaturatingUINT64> LocalVarNonEntryValLocStats{
182       std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
183   /// Total number of local variables and function parameters processed.
184   SaturatingUINT64 NumVarParam = 0;
185   /// Total number of formal parameters processed.
186   SaturatingUINT64 NumParam = 0;
187   /// Total number of local variables processed.
188   SaturatingUINT64 NumVar = 0;
189 };
190 } // namespace
191 
192 /// Collect debug location statistics for one DIE.
193 static void collectLocStats(uint64_t ScopeBytesCovered, uint64_t BytesInScope,
194                             std::vector<SaturatingUINT64> &VarParamLocStats,
195                             std::vector<SaturatingUINT64> &ParamLocStats,
196                             std::vector<SaturatingUINT64> &LocalVarLocStats,
197                             bool IsParam, bool IsLocalVar) {
198   auto getCoverageBucket = [ScopeBytesCovered, BytesInScope]() -> unsigned {
199     // No debug location at all for the variable.
200     if (ScopeBytesCovered == 0)
201       return 0;
202     // Fully covered variable within its scope.
203     if (ScopeBytesCovered >= BytesInScope)
204       return NumOfCoverageCategories - 1;
205     // Get covered range (e.g. 20%-29%).
206     unsigned LocBucket = 100 * (double)ScopeBytesCovered / BytesInScope;
207     LocBucket /= 10;
208     return LocBucket + 1;
209   };
210 
211   unsigned CoverageBucket = getCoverageBucket();
212 
213   VarParamLocStats[CoverageBucket].Value++;
214   if (IsParam)
215     ParamLocStats[CoverageBucket].Value++;
216   else if (IsLocalVar)
217     LocalVarLocStats[CoverageBucket].Value++;
218 }
219 
220 /// Construct an identifier for a given DIE from its Prefix, Name, DeclFileName
221 /// and DeclLine. The identifier aims to be unique for any unique entities,
222 /// but keeping the same among different instances of the same entity.
223 static std::string constructDieID(DWARFDie Die,
224                                   StringRef Prefix = StringRef()) {
225   std::string IDStr;
226   llvm::raw_string_ostream ID(IDStr);
227   ID << Prefix
228      << Die.getName(DINameKind::LinkageName);
229 
230   // Prefix + Name is enough for local variables and parameters.
231   if (!Prefix.empty() && !Prefix.equals("g"))
232     return ID.str();
233 
234   auto DeclFile = Die.findRecursively(dwarf::DW_AT_decl_file);
235   std::string File;
236   if (DeclFile) {
237     DWARFUnit *U = Die.getDwarfUnit();
238     if (const auto *LT = U->getContext().getLineTableForUnit(U))
239       if (LT->getFileNameByIndex(
240               dwarf::toUnsigned(DeclFile, 0), U->getCompilationDir(),
241               DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File))
242         File = std::string(sys::path::filename(File));
243   }
244   ID << ":" << (File.empty() ? "/" : File);
245   ID << ":"
246      << dwarf::toUnsigned(Die.findRecursively(dwarf::DW_AT_decl_line), 0);
247   return ID.str();
248 }
249 
250 /// Return the number of bytes in the overlap of ranges A and B.
251 static uint64_t calculateOverlap(DWARFAddressRange A, DWARFAddressRange B) {
252   uint64_t Lower = std::max(A.LowPC, B.LowPC);
253   uint64_t Upper = std::min(A.HighPC, B.HighPC);
254   if (Lower >= Upper)
255     return 0;
256   return Upper - Lower;
257 }
258 
259 /// Collect debug info quality metrics for one DIE.
260 static void collectStatsForDie(DWARFDie Die, const std::string &FnPrefix,
261                                const std::string &VarPrefix,
262                                uint64_t BytesInScope, uint32_t InlineDepth,
263                                StringMap<PerFunctionStats> &FnStatMap,
264                                GlobalStats &GlobalStats,
265                                LocationStats &LocStats,
266                                AbstractOriginVarsTy *AbstractOriginVariables) {
267   const dwarf::Tag Tag = Die.getTag();
268   // Skip CU node.
269   if (Tag == dwarf::DW_TAG_compile_unit)
270     return;
271 
272   bool HasLoc = false;
273   bool HasSrcLoc = false;
274   bool HasType = false;
275   uint64_t TotalBytesCovered = 0;
276   uint64_t ScopeBytesCovered = 0;
277   uint64_t BytesEntryValuesCovered = 0;
278   auto &FnStats = FnStatMap[FnPrefix];
279   bool IsParam = Tag == dwarf::DW_TAG_formal_parameter;
280   bool IsLocalVar = Tag == dwarf::DW_TAG_variable;
281   bool IsConstantMember = Tag == dwarf::DW_TAG_member &&
282                           Die.find(dwarf::DW_AT_const_value);
283 
284   // For zero covered inlined variables the locstats will be
285   // calculated later.
286   bool DeferLocStats = false;
287 
288   if (Tag == dwarf::DW_TAG_call_site || Tag == dwarf::DW_TAG_GNU_call_site) {
289     GlobalStats.CallSiteDIEs++;
290     return;
291   }
292 
293   if (Tag == dwarf::DW_TAG_call_site_parameter ||
294       Tag == dwarf::DW_TAG_GNU_call_site_parameter) {
295     GlobalStats.CallSiteParamDIEs++;
296     return;
297   }
298 
299   if (!IsParam && !IsLocalVar && !IsConstantMember) {
300     // Not a variable or constant member.
301     return;
302   }
303 
304   // Ignore declarations of global variables.
305   if (IsLocalVar && Die.find(dwarf::DW_AT_declaration))
306     return;
307 
308   if (Die.findRecursively(dwarf::DW_AT_decl_file) &&
309       Die.findRecursively(dwarf::DW_AT_decl_line))
310     HasSrcLoc = true;
311 
312   if (Die.findRecursively(dwarf::DW_AT_type))
313     HasType = true;
314 
315   if (Die.find(dwarf::DW_AT_abstract_origin)) {
316     if (Die.find(dwarf::DW_AT_location) || Die.find(dwarf::DW_AT_const_value)) {
317       if (AbstractOriginVariables) {
318         auto Offset = Die.find(dwarf::DW_AT_abstract_origin);
319         // Do not track this variable any more, since it has location
320         // coverage.
321         llvm::erase_value(*AbstractOriginVariables, (*Offset).getRawUValue());
322       }
323     } else {
324       // The locstats will be handled at the end of
325       // the collectStatsRecursive().
326       DeferLocStats = true;
327     }
328   }
329 
330   auto IsEntryValue = [&](ArrayRef<uint8_t> D) -> bool {
331     DWARFUnit *U = Die.getDwarfUnit();
332     DataExtractor Data(toStringRef(D),
333                        Die.getDwarfUnit()->getContext().isLittleEndian(), 0);
334     DWARFExpression Expression(Data, U->getAddressByteSize(),
335                                U->getFormParams().Format);
336     // Consider the expression containing the DW_OP_entry_value as
337     // an entry value.
338     return llvm::any_of(Expression, [](const DWARFExpression::Operation &Op) {
339       return Op.getCode() == dwarf::DW_OP_entry_value ||
340              Op.getCode() == dwarf::DW_OP_GNU_entry_value;
341     });
342   };
343 
344   if (Die.find(dwarf::DW_AT_const_value)) {
345     // This catches constant members *and* variables.
346     HasLoc = true;
347     ScopeBytesCovered = BytesInScope;
348     TotalBytesCovered = BytesInScope;
349   } else {
350     // Handle variables and function arguments.
351     Expected<std::vector<DWARFLocationExpression>> Loc =
352         Die.getLocations(dwarf::DW_AT_location);
353     if (!Loc) {
354       consumeError(Loc.takeError());
355     } else {
356       HasLoc = true;
357       // Get PC coverage.
358       auto Default = find_if(
359           *Loc, [](const DWARFLocationExpression &L) { return !L.Range; });
360       if (Default != Loc->end()) {
361         // Assume the entire range is covered by a single location.
362         ScopeBytesCovered = BytesInScope;
363         TotalBytesCovered = BytesInScope;
364       } else {
365         // Caller checks this Expected result already, it cannot fail.
366         auto ScopeRanges = cantFail(Die.getParent().getAddressRanges());
367         for (auto Entry : *Loc) {
368           TotalBytesCovered += Entry.Range->HighPC - Entry.Range->LowPC;
369           uint64_t ScopeBytesCoveredByEntry = 0;
370           // Calculate how many bytes of the parent scope this entry covers.
371           // FIXME: In section 2.6.2 of the DWARFv5 spec it says that "The
372           // address ranges defined by the bounded location descriptions of a
373           // location list may overlap". So in theory a variable can have
374           // multiple simultaneous locations, which would make this calculation
375           // misleading because we will count the overlapped areas
376           // twice. However, clang does not currently emit DWARF like this.
377           for (DWARFAddressRange R : ScopeRanges) {
378             ScopeBytesCoveredByEntry += calculateOverlap(*Entry.Range, R);
379           }
380           ScopeBytesCovered += ScopeBytesCoveredByEntry;
381           if (IsEntryValue(Entry.Expr))
382             BytesEntryValuesCovered += ScopeBytesCoveredByEntry;
383         }
384       }
385     }
386   }
387 
388   // Calculate the debug location statistics.
389   if (BytesInScope && !DeferLocStats) {
390     LocStats.NumVarParam.Value++;
391     if (IsParam)
392       LocStats.NumParam.Value++;
393     else if (IsLocalVar)
394       LocStats.NumVar.Value++;
395 
396     collectLocStats(ScopeBytesCovered, BytesInScope, LocStats.VarParamLocStats,
397                     LocStats.ParamLocStats, LocStats.LocalVarLocStats, IsParam,
398                     IsLocalVar);
399     // Non debug entry values coverage statistics.
400     collectLocStats(ScopeBytesCovered - BytesEntryValuesCovered, BytesInScope,
401                     LocStats.VarParamNonEntryValLocStats,
402                     LocStats.ParamNonEntryValLocStats,
403                     LocStats.LocalVarNonEntryValLocStats, IsParam, IsLocalVar);
404   }
405 
406   // Collect PC range coverage data.
407   if (DWARFDie D =
408           Die.getAttributeValueAsReferencedDie(dwarf::DW_AT_abstract_origin))
409     Die = D;
410 
411   std::string VarID = constructDieID(Die, VarPrefix);
412   FnStats.VarsInFunction.insert(VarID);
413 
414   GlobalStats.TotalBytesCovered += TotalBytesCovered;
415   if (BytesInScope) {
416     GlobalStats.ScopeBytesCovered += ScopeBytesCovered;
417     GlobalStats.ScopeBytes += BytesInScope;
418     GlobalStats.ScopeEntryValueBytesCovered += BytesEntryValuesCovered;
419     if (IsParam) {
420       GlobalStats.ParamScopeBytesCovered += ScopeBytesCovered;
421       GlobalStats.ParamScopeBytes += BytesInScope;
422       GlobalStats.ParamScopeEntryValueBytesCovered += BytesEntryValuesCovered;
423     } else if (IsLocalVar) {
424       GlobalStats.LocalVarScopeBytesCovered += ScopeBytesCovered;
425       GlobalStats.LocalVarScopeBytes += BytesInScope;
426       GlobalStats.LocalVarScopeEntryValueBytesCovered +=
427           BytesEntryValuesCovered;
428     }
429     assert(GlobalStats.ScopeBytesCovered.Value <= GlobalStats.ScopeBytes.Value);
430   }
431 
432   if (IsConstantMember) {
433     FnStats.ConstantMembers++;
434     return;
435   }
436 
437   FnStats.TotalVarWithLoc += (unsigned)HasLoc;
438 
439   if (Die.find(dwarf::DW_AT_artificial)) {
440     FnStats.NumArtificial++;
441     return;
442   }
443 
444   if (IsParam) {
445     FnStats.NumParams++;
446     if (HasType)
447       FnStats.NumParamTypes++;
448     if (HasSrcLoc)
449       FnStats.NumParamSourceLocations++;
450     if (HasLoc)
451       FnStats.NumParamLocations++;
452   } else if (IsLocalVar) {
453     FnStats.NumLocalVars++;
454     if (HasType)
455       FnStats.NumLocalVarTypes++;
456     if (HasSrcLoc)
457       FnStats.NumLocalVarSourceLocations++;
458     if (HasLoc)
459       FnStats.NumLocalVarLocations++;
460   }
461 }
462 
463 /// Recursively collect variables from subprogram with DW_AT_inline attribute.
464 static void collectAbstractOriginFnInfo(
465     DWARFDie Die, uint64_t SPOffset,
466     AbstractOriginVarsTyMap &GlobalAbstractOriginFnInfo,
467     AbstractOriginVarsTyMap &LocalAbstractOriginFnInfo) {
468   DWARFDie Child = Die.getFirstChild();
469   while (Child) {
470     const dwarf::Tag ChildTag = Child.getTag();
471     if (ChildTag == dwarf::DW_TAG_formal_parameter ||
472         ChildTag == dwarf::DW_TAG_variable) {
473       GlobalAbstractOriginFnInfo[SPOffset].push_back(Child.getOffset());
474       LocalAbstractOriginFnInfo[SPOffset].push_back(Child.getOffset());
475     } else if (ChildTag == dwarf::DW_TAG_lexical_block)
476       collectAbstractOriginFnInfo(Child, SPOffset, GlobalAbstractOriginFnInfo,
477                                   LocalAbstractOriginFnInfo);
478     Child = Child.getSibling();
479   }
480 }
481 
482 /// Recursively collect debug info quality metrics.
483 static void collectStatsRecursive(
484     DWARFDie Die, std::string FnPrefix, std::string VarPrefix,
485     uint64_t BytesInScope, uint32_t InlineDepth,
486     StringMap<PerFunctionStats> &FnStatMap, GlobalStats &GlobalStats,
487     LocationStats &LocStats, FunctionDIECUTyMap &AbstractOriginFnCUs,
488     AbstractOriginVarsTyMap &GlobalAbstractOriginFnInfo,
489     AbstractOriginVarsTyMap &LocalAbstractOriginFnInfo,
490     FunctionsWithAbstractOriginTy &FnsWithAbstractOriginToBeProcessed,
491     AbstractOriginVarsTy *AbstractOriginVarsPtr = nullptr) {
492   // Skip NULL nodes.
493   if (Die.isNULL())
494     return;
495 
496   const dwarf::Tag Tag = Die.getTag();
497   // Skip function types.
498   if (Tag == dwarf::DW_TAG_subroutine_type)
499     return;
500 
501   // Handle any kind of lexical scope.
502   const bool HasAbstractOrigin = Die.find(dwarf::DW_AT_abstract_origin) != None;
503   const bool IsFunction = Tag == dwarf::DW_TAG_subprogram;
504   const bool IsBlock = Tag == dwarf::DW_TAG_lexical_block;
505   const bool IsInlinedFunction = Tag == dwarf::DW_TAG_inlined_subroutine;
506   // We want to know how many variables (with abstract_origin) don't have
507   // location info.
508   const bool IsCandidateForZeroLocCovTracking =
509       (IsInlinedFunction || (IsFunction && HasAbstractOrigin));
510 
511   AbstractOriginVarsTy AbstractOriginVars;
512 
513   // Get the vars of the inlined fn, so the locstats
514   // reports the missing vars (with coverage 0%).
515   if (IsCandidateForZeroLocCovTracking) {
516     auto OffsetFn = Die.find(dwarf::DW_AT_abstract_origin);
517     if (OffsetFn) {
518       uint64_t OffsetOfInlineFnCopy = (*OffsetFn).getRawUValue();
519       if (LocalAbstractOriginFnInfo.count(OffsetOfInlineFnCopy)) {
520         AbstractOriginVars = LocalAbstractOriginFnInfo[OffsetOfInlineFnCopy];
521         AbstractOriginVarsPtr = &AbstractOriginVars;
522       } else {
523         // This means that the DW_AT_inline fn copy is out of order
524         // or that the abstract_origin references another CU,
525         // so this abstract origin instance will be processed later.
526         FnsWithAbstractOriginToBeProcessed.push_back(Die.getOffset());
527         AbstractOriginVarsPtr = nullptr;
528       }
529     }
530   }
531 
532   if (IsFunction || IsInlinedFunction || IsBlock) {
533     // Reset VarPrefix when entering a new function.
534     if (IsFunction || IsInlinedFunction)
535       VarPrefix = "v";
536 
537     // Ignore forward declarations.
538     if (Die.find(dwarf::DW_AT_declaration))
539       return;
540 
541     // Check for call sites.
542     if (Die.find(dwarf::DW_AT_call_file) && Die.find(dwarf::DW_AT_call_line))
543       GlobalStats.CallSiteEntries++;
544 
545     // PC Ranges.
546     auto RangesOrError = Die.getAddressRanges();
547     if (!RangesOrError) {
548       llvm::consumeError(RangesOrError.takeError());
549       return;
550     }
551 
552     auto Ranges = RangesOrError.get();
553     uint64_t BytesInThisScope = 0;
554     for (auto Range : Ranges)
555       BytesInThisScope += Range.HighPC - Range.LowPC;
556 
557     // Count the function.
558     if (!IsBlock) {
559       // Skip over abstract origins, but collect variables
560       // from it so it can be used for location statistics
561       // for inlined instancies.
562       if (Die.find(dwarf::DW_AT_inline)) {
563         uint64_t SPOffset = Die.getOffset();
564         AbstractOriginFnCUs[SPOffset] = Die.getDwarfUnit();
565         collectAbstractOriginFnInfo(Die, SPOffset, GlobalAbstractOriginFnInfo,
566                                     LocalAbstractOriginFnInfo);
567         return;
568       }
569 
570       std::string FnID = constructDieID(Die);
571       // We've seen an instance of this function.
572       auto &FnStats = FnStatMap[FnID];
573       FnStats.IsFunction = true;
574       if (IsInlinedFunction) {
575         FnStats.NumFnInlined++;
576         if (Die.findRecursively(dwarf::DW_AT_abstract_origin))
577           FnStats.NumAbstractOrigins++;
578       } else {
579         FnStats.NumFnOutOfLine++;
580       }
581       if (Die.findRecursively(dwarf::DW_AT_decl_file) &&
582           Die.findRecursively(dwarf::DW_AT_decl_line))
583         FnStats.HasSourceLocation = true;
584       // Update function prefix.
585       FnPrefix = FnID;
586     }
587 
588     if (BytesInThisScope) {
589       BytesInScope = BytesInThisScope;
590       if (IsFunction)
591         GlobalStats.FunctionSize += BytesInThisScope;
592       else if (IsInlinedFunction && InlineDepth == 0)
593         GlobalStats.InlineFunctionSize += BytesInThisScope;
594     }
595   } else {
596     // Not a scope, visit the Die itself. It could be a variable.
597     collectStatsForDie(Die, FnPrefix, VarPrefix, BytesInScope, InlineDepth,
598                        FnStatMap, GlobalStats, LocStats, AbstractOriginVarsPtr);
599   }
600 
601   // Set InlineDepth correctly for child recursion
602   if (IsFunction)
603     InlineDepth = 0;
604   else if (IsInlinedFunction)
605     ++InlineDepth;
606 
607   // Traverse children.
608   unsigned LexicalBlockIndex = 0;
609   unsigned FormalParameterIndex = 0;
610   DWARFDie Child = Die.getFirstChild();
611   while (Child) {
612     std::string ChildVarPrefix = VarPrefix;
613     if (Child.getTag() == dwarf::DW_TAG_lexical_block)
614       ChildVarPrefix += toHex(LexicalBlockIndex++) + '.';
615     if (Child.getTag() == dwarf::DW_TAG_formal_parameter)
616       ChildVarPrefix += 'p' + toHex(FormalParameterIndex++) + '.';
617 
618     collectStatsRecursive(
619         Child, FnPrefix, ChildVarPrefix, BytesInScope, InlineDepth, FnStatMap,
620         GlobalStats, LocStats, AbstractOriginFnCUs, GlobalAbstractOriginFnInfo,
621         LocalAbstractOriginFnInfo, FnsWithAbstractOriginToBeProcessed,
622         AbstractOriginVarsPtr);
623     Child = Child.getSibling();
624   }
625 
626   if (!IsCandidateForZeroLocCovTracking)
627     return;
628 
629   // After we have processed all vars of the inlined function (or function with
630   // an abstract_origin), we want to know how many variables have no location.
631   for (auto Offset : AbstractOriginVars) {
632     LocStats.NumVarParam++;
633     LocStats.VarParamLocStats[ZeroCoverageBucket]++;
634     auto FnDie = Die.getDwarfUnit()->getDIEForOffset(Offset);
635     if (!FnDie)
636       continue;
637     auto Tag = FnDie.getTag();
638     if (Tag == dwarf::DW_TAG_formal_parameter) {
639       LocStats.NumParam++;
640       LocStats.ParamLocStats[ZeroCoverageBucket]++;
641     } else if (Tag == dwarf::DW_TAG_variable) {
642       LocStats.NumVar++;
643       LocStats.LocalVarLocStats[ZeroCoverageBucket]++;
644     }
645   }
646 }
647 
648 /// Print human-readable output.
649 /// \{
650 static void printDatum(json::OStream &J, const char *Key, json::Value Value) {
651   if (Value == OverflowValue)
652     J.attribute(Key, "overflowed");
653   else
654     J.attribute(Key, Value);
655 
656   LLVM_DEBUG(llvm::dbgs() << Key << ": " << Value << '\n');
657 }
658 
659 static void printLocationStats(json::OStream &J, const char *Key,
660                                std::vector<SaturatingUINT64> &LocationStats) {
661   if (LocationStats[0].Value == OverflowValue)
662     J.attribute((Twine(Key) +
663                  " with (0%,10%) of parent scope covered by DW_AT_location")
664                     .str(),
665                 "overflowed");
666   else
667     J.attribute(
668         (Twine(Key) + " with 0% of parent scope covered by DW_AT_location")
669             .str(),
670         LocationStats[0].Value);
671   LLVM_DEBUG(
672       llvm::dbgs() << Key
673                    << " with 0% of parent scope covered by DW_AT_location: \\"
674                    << LocationStats[0].Value << '\n');
675 
676   if (LocationStats[1].Value == OverflowValue)
677     J.attribute((Twine(Key) +
678                  " with (0%,10%) of parent scope covered by DW_AT_location")
679                     .str(),
680                 "overflowed");
681   else
682     J.attribute((Twine(Key) +
683                  " with (0%,10%) of parent scope covered by DW_AT_location")
684                     .str(),
685                 LocationStats[1].Value);
686   LLVM_DEBUG(llvm::dbgs()
687              << Key
688              << " with (0%,10%) of parent scope covered by DW_AT_location: "
689              << LocationStats[1].Value << '\n');
690 
691   for (unsigned i = 2; i < NumOfCoverageCategories - 1; ++i) {
692     if (LocationStats[i].Value == OverflowValue)
693       J.attribute((Twine(Key) + " with [" + Twine((i - 1) * 10) + "%," +
694                    Twine(i * 10) +
695                    "%) of parent scope covered by DW_AT_location")
696                       .str(),
697                   "overflowed");
698     else
699       J.attribute((Twine(Key) + " with [" + Twine((i - 1) * 10) + "%," +
700                    Twine(i * 10) +
701                    "%) of parent scope covered by DW_AT_location")
702                       .str(),
703                   LocationStats[i].Value);
704     LLVM_DEBUG(llvm::dbgs()
705                << Key << " with [" << (i - 1) * 10 << "%," << i * 10
706                << "%) of parent scope covered by DW_AT_location: "
707                << LocationStats[i].Value);
708   }
709   if (LocationStats[NumOfCoverageCategories - 1].Value == OverflowValue)
710     J.attribute(
711         (Twine(Key) + " with 100% of parent scope covered by DW_AT_location")
712             .str(),
713         "overflowed");
714   else
715     J.attribute(
716         (Twine(Key) + " with 100% of parent scope covered by DW_AT_location")
717             .str(),
718         LocationStats[NumOfCoverageCategories - 1].Value);
719   LLVM_DEBUG(
720       llvm::dbgs() << Key
721                    << " with 100% of parent scope covered by DW_AT_location: "
722                    << LocationStats[NumOfCoverageCategories - 1].Value);
723 }
724 
725 static void printSectionSizes(json::OStream &J, const SectionSizes &Sizes) {
726   for (const auto &It : Sizes.DebugSectionSizes)
727     J.attribute((Twine("#bytes in ") + It.first).str(), int64_t(It.second));
728 }
729 
730 /// Stop tracking variables that contain abstract_origin with a location.
731 /// This is used for out-of-order DW_AT_inline subprograms only.
732 static void updateVarsWithAbstractOriginLocCovInfo(
733     DWARFDie FnDieWithAbstractOrigin,
734     AbstractOriginVarsTy &AbstractOriginVars) {
735   DWARFDie Child = FnDieWithAbstractOrigin.getFirstChild();
736   while (Child) {
737     const dwarf::Tag ChildTag = Child.getTag();
738     if ((ChildTag == dwarf::DW_TAG_formal_parameter ||
739          ChildTag == dwarf::DW_TAG_variable) &&
740         (Child.find(dwarf::DW_AT_location) ||
741          Child.find(dwarf::DW_AT_const_value))) {
742       auto OffsetVar = Child.find(dwarf::DW_AT_abstract_origin);
743       if (OffsetVar)
744         llvm::erase_value(AbstractOriginVars, (*OffsetVar).getRawUValue());
745     } else if (ChildTag == dwarf::DW_TAG_lexical_block)
746       updateVarsWithAbstractOriginLocCovInfo(Child, AbstractOriginVars);
747     Child = Child.getSibling();
748   }
749 }
750 
751 /// Collect zero location coverage for inlined variables which refer to
752 /// a DW_AT_inline copy of subprogram that is out of order in the DWARF.
753 /// Also cover the variables of a concrete function (represented with
754 /// the DW_TAG_subprogram) with an abstract_origin attribute.
755 static void collectZeroLocCovForVarsWithAbstractOrigin(
756     DWARFUnit *DwUnit, GlobalStats &GlobalStats, LocationStats &LocStats,
757     AbstractOriginVarsTyMap &LocalAbstractOriginFnInfo,
758     FunctionsWithAbstractOriginTy &FnsWithAbstractOriginToBeProcessed) {
759   // The next variable is used to filter out functions that have been processed,
760   // leaving FnsWithAbstractOriginToBeProcessed with just CrossCU references.
761   FunctionsWithAbstractOriginTy ProcessedFns;
762   for (auto FnOffset : FnsWithAbstractOriginToBeProcessed) {
763     DWARFDie FnDieWithAbstractOrigin = DwUnit->getDIEForOffset(FnOffset);
764     auto FnCopy = FnDieWithAbstractOrigin.find(dwarf::DW_AT_abstract_origin);
765     AbstractOriginVarsTy AbstractOriginVars;
766     if (!FnCopy)
767       continue;
768     uint64_t FnCopyRawUValue = (*FnCopy).getRawUValue();
769     // If there is no entry within LocalAbstractOriginFnInfo for the given
770     // FnCopyRawUValue, function isn't out-of-order in DWARF. Rather, we have
771     // CrossCU referencing.
772     if (!LocalAbstractOriginFnInfo.count(FnCopyRawUValue))
773       continue;
774     AbstractOriginVars = LocalAbstractOriginFnInfo[FnCopyRawUValue];
775     updateVarsWithAbstractOriginLocCovInfo(FnDieWithAbstractOrigin,
776                                            AbstractOriginVars);
777 
778     for (auto Offset : AbstractOriginVars) {
779       LocStats.NumVarParam++;
780       LocStats.VarParamLocStats[ZeroCoverageBucket]++;
781       auto Tag = DwUnit->getDIEForOffset(Offset).getTag();
782       if (Tag == dwarf::DW_TAG_formal_parameter) {
783         LocStats.NumParam++;
784         LocStats.ParamLocStats[ZeroCoverageBucket]++;
785       } else if (Tag == dwarf::DW_TAG_variable) {
786         LocStats.NumVar++;
787         LocStats.LocalVarLocStats[ZeroCoverageBucket]++;
788       }
789     }
790     ProcessedFns.push_back(FnOffset);
791   }
792   for (auto ProcessedFn : ProcessedFns)
793     llvm::erase_value(FnsWithAbstractOriginToBeProcessed, ProcessedFn);
794 }
795 
796 /// Collect zero location coverage for inlined variables which refer to
797 /// a DW_AT_inline copy of subprogram that is in a different CU.
798 static void collectZeroLocCovForVarsWithCrossCUReferencingAbstractOrigin(
799     LocationStats &LocStats, FunctionDIECUTyMap AbstractOriginFnCUs,
800     AbstractOriginVarsTyMap &GlobalAbstractOriginFnInfo,
801     CrossCUReferencingDIELocationTy &CrossCUReferencesToBeResolved) {
802   for (const auto &CrossCUReferenceToBeResolved :
803        CrossCUReferencesToBeResolved) {
804     DWARFUnit *DwUnit = CrossCUReferenceToBeResolved.DwUnit;
805     DWARFDie FnDIEWithCrossCUReferencing =
806         DwUnit->getDIEForOffset(CrossCUReferenceToBeResolved.DIEOffset);
807     auto FnCopy =
808         FnDIEWithCrossCUReferencing.find(dwarf::DW_AT_abstract_origin);
809     if (!FnCopy)
810       continue;
811     uint64_t FnCopyRawUValue = (*FnCopy).getRawUValue();
812     AbstractOriginVarsTy AbstractOriginVars =
813         GlobalAbstractOriginFnInfo[FnCopyRawUValue];
814     updateVarsWithAbstractOriginLocCovInfo(FnDIEWithCrossCUReferencing,
815                                            AbstractOriginVars);
816     for (auto Offset : AbstractOriginVars) {
817       LocStats.NumVarParam++;
818       LocStats.VarParamLocStats[ZeroCoverageBucket]++;
819       auto Tag = (AbstractOriginFnCUs[FnCopyRawUValue])
820                      ->getDIEForOffset(Offset)
821                      .getTag();
822       if (Tag == dwarf::DW_TAG_formal_parameter) {
823         LocStats.NumParam++;
824         LocStats.ParamLocStats[ZeroCoverageBucket]++;
825       } else if (Tag == dwarf::DW_TAG_variable) {
826         LocStats.NumVar++;
827         LocStats.LocalVarLocStats[ZeroCoverageBucket]++;
828       }
829     }
830   }
831 }
832 
833 /// \}
834 
835 /// Collect debug info quality metrics for an entire DIContext.
836 ///
837 /// Do the impossible and reduce the quality of the debug info down to a few
838 /// numbers. The idea is to condense the data into numbers that can be tracked
839 /// over time to identify trends in newer compiler versions and gauge the effect
840 /// of particular optimizations. The raw numbers themselves are not particularly
841 /// useful, only the delta between compiling the same program with different
842 /// compilers is.
843 bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
844                                           const Twine &Filename,
845                                           raw_ostream &OS) {
846   StringRef FormatName = Obj.getFileFormatName();
847   GlobalStats GlobalStats;
848   LocationStats LocStats;
849   StringMap<PerFunctionStats> Statistics;
850   // This variable holds variable information for functions with
851   // abstract_origin globally, across all CUs.
852   AbstractOriginVarsTyMap GlobalAbstractOriginFnInfo;
853   // This variable holds information about the CU of a function with
854   // abstract_origin.
855   FunctionDIECUTyMap AbstractOriginFnCUs;
856   CrossCUReferencingDIELocationTy CrossCUReferencesToBeResolved;
857   for (const auto &CU : static_cast<DWARFContext *>(&DICtx)->compile_units()) {
858     if (DWARFDie CUDie = CU->getNonSkeletonUnitDIE(false)) {
859       // This variable holds variable information for functions with
860       // abstract_origin, but just for the current CU.
861       AbstractOriginVarsTyMap LocalAbstractOriginFnInfo;
862       FunctionsWithAbstractOriginTy FnsWithAbstractOriginToBeProcessed;
863 
864       collectStatsRecursive(
865           CUDie, "/", "g", 0, 0, Statistics, GlobalStats, LocStats,
866           AbstractOriginFnCUs, GlobalAbstractOriginFnInfo,
867           LocalAbstractOriginFnInfo, FnsWithAbstractOriginToBeProcessed);
868 
869       // collectZeroLocCovForVarsWithAbstractOrigin will filter out all
870       // out-of-order DWARF functions that have been processed within it,
871       // leaving FnsWithAbstractOriginToBeProcessed with only CrossCU
872       // references.
873       collectZeroLocCovForVarsWithAbstractOrigin(
874           CUDie.getDwarfUnit(), GlobalStats, LocStats,
875           LocalAbstractOriginFnInfo, FnsWithAbstractOriginToBeProcessed);
876 
877       // Collect all CrossCU references into CrossCUReferencesToBeResolved.
878       for (auto CrossCUReferencingDIEOffset :
879            FnsWithAbstractOriginToBeProcessed)
880         CrossCUReferencesToBeResolved.push_back(
881             DIELocation(CUDie.getDwarfUnit(), CrossCUReferencingDIEOffset));
882     }
883   }
884 
885   /// Resolve CrossCU references.
886   collectZeroLocCovForVarsWithCrossCUReferencingAbstractOrigin(
887       LocStats, AbstractOriginFnCUs, GlobalAbstractOriginFnInfo,
888       CrossCUReferencesToBeResolved);
889 
890   /// Collect the sizes of debug sections.
891   SectionSizes Sizes;
892   calculateSectionSizes(Obj, Sizes, Filename);
893 
894   /// The version number should be increased every time the algorithm is changed
895   /// (including bug fixes). New metrics may be added without increasing the
896   /// version.
897   unsigned Version = 9;
898   SaturatingUINT64 VarParamTotal = 0;
899   SaturatingUINT64 VarParamUnique = 0;
900   SaturatingUINT64 VarParamWithLoc = 0;
901   SaturatingUINT64 NumFunctions = 0;
902   SaturatingUINT64 NumInlinedFunctions = 0;
903   SaturatingUINT64 NumFuncsWithSrcLoc = 0;
904   SaturatingUINT64 NumAbstractOrigins = 0;
905   SaturatingUINT64 ParamTotal = 0;
906   SaturatingUINT64 ParamWithType = 0;
907   SaturatingUINT64 ParamWithLoc = 0;
908   SaturatingUINT64 ParamWithSrcLoc = 0;
909   SaturatingUINT64 LocalVarTotal = 0;
910   SaturatingUINT64 LocalVarWithType = 0;
911   SaturatingUINT64 LocalVarWithSrcLoc = 0;
912   SaturatingUINT64 LocalVarWithLoc = 0;
913   for (auto &Entry : Statistics) {
914     PerFunctionStats &Stats = Entry.getValue();
915     uint64_t TotalVars = Stats.VarsInFunction.size() *
916                          (Stats.NumFnInlined + Stats.NumFnOutOfLine);
917     // Count variables in global scope.
918     if (!Stats.IsFunction)
919       TotalVars =
920           Stats.NumLocalVars + Stats.ConstantMembers + Stats.NumArtificial;
921     uint64_t Constants = Stats.ConstantMembers;
922     VarParamWithLoc += Stats.TotalVarWithLoc + Constants;
923     VarParamTotal += TotalVars;
924     VarParamUnique += Stats.VarsInFunction.size();
925     LLVM_DEBUG(for (auto &V
926                     : Stats.VarsInFunction) llvm::dbgs()
927                << Entry.getKey() << ": " << V.getKey() << "\n");
928     NumFunctions += Stats.IsFunction;
929     NumFuncsWithSrcLoc += Stats.HasSourceLocation;
930     NumInlinedFunctions += Stats.IsFunction * Stats.NumFnInlined;
931     NumAbstractOrigins += Stats.IsFunction * Stats.NumAbstractOrigins;
932     ParamTotal += Stats.NumParams;
933     ParamWithType += Stats.NumParamTypes;
934     ParamWithLoc += Stats.NumParamLocations;
935     ParamWithSrcLoc += Stats.NumParamSourceLocations;
936     LocalVarTotal += Stats.NumLocalVars;
937     LocalVarWithType += Stats.NumLocalVarTypes;
938     LocalVarWithLoc += Stats.NumLocalVarLocations;
939     LocalVarWithSrcLoc += Stats.NumLocalVarSourceLocations;
940   }
941 
942   // Print summary.
943   OS.SetBufferSize(1024);
944   json::OStream J(OS, 2);
945   J.objectBegin();
946   J.attribute("version", Version);
947   LLVM_DEBUG(llvm::dbgs() << "Variable location quality metrics\n";
948              llvm::dbgs() << "---------------------------------\n");
949 
950   printDatum(J, "file", Filename.str());
951   printDatum(J, "format", FormatName);
952 
953   printDatum(J, "#functions", NumFunctions.Value);
954   printDatum(J, "#functions with location", NumFuncsWithSrcLoc.Value);
955   printDatum(J, "#inlined functions", NumInlinedFunctions.Value);
956   printDatum(J, "#inlined functions with abstract origins",
957              NumAbstractOrigins.Value);
958 
959   // This includes local variables and formal parameters.
960   printDatum(J, "#unique source variables", VarParamUnique.Value);
961   printDatum(J, "#source variables", VarParamTotal.Value);
962   printDatum(J, "#source variables with location", VarParamWithLoc.Value);
963 
964   printDatum(J, "#call site entries", GlobalStats.CallSiteEntries.Value);
965   printDatum(J, "#call site DIEs", GlobalStats.CallSiteDIEs.Value);
966   printDatum(J, "#call site parameter DIEs",
967              GlobalStats.CallSiteParamDIEs.Value);
968 
969   printDatum(J, "sum_all_variables(#bytes in parent scope)",
970              GlobalStats.ScopeBytes.Value);
971   printDatum(J,
972              "sum_all_variables(#bytes in any scope covered by DW_AT_location)",
973              GlobalStats.TotalBytesCovered.Value);
974   printDatum(J,
975              "sum_all_variables(#bytes in parent scope covered by "
976              "DW_AT_location)",
977              GlobalStats.ScopeBytesCovered.Value);
978   printDatum(J,
979              "sum_all_variables(#bytes in parent scope covered by "
980              "DW_OP_entry_value)",
981              GlobalStats.ScopeEntryValueBytesCovered.Value);
982 
983   printDatum(J, "sum_all_params(#bytes in parent scope)",
984              GlobalStats.ParamScopeBytes.Value);
985   printDatum(J,
986              "sum_all_params(#bytes in parent scope covered by DW_AT_location)",
987              GlobalStats.ParamScopeBytesCovered.Value);
988   printDatum(J,
989              "sum_all_params(#bytes in parent scope covered by "
990              "DW_OP_entry_value)",
991              GlobalStats.ParamScopeEntryValueBytesCovered.Value);
992 
993   printDatum(J, "sum_all_local_vars(#bytes in parent scope)",
994              GlobalStats.LocalVarScopeBytes.Value);
995   printDatum(J,
996              "sum_all_local_vars(#bytes in parent scope covered by "
997              "DW_AT_location)",
998              GlobalStats.LocalVarScopeBytesCovered.Value);
999   printDatum(J,
1000              "sum_all_local_vars(#bytes in parent scope covered by "
1001              "DW_OP_entry_value)",
1002              GlobalStats.LocalVarScopeEntryValueBytesCovered.Value);
1003 
1004   printDatum(J, "#bytes within functions", GlobalStats.FunctionSize.Value);
1005   printDatum(J, "#bytes within inlined functions",
1006              GlobalStats.InlineFunctionSize.Value);
1007 
1008   // Print the summary for formal parameters.
1009   printDatum(J, "#params", ParamTotal.Value);
1010   printDatum(J, "#params with source location", ParamWithSrcLoc.Value);
1011   printDatum(J, "#params with type", ParamWithType.Value);
1012   printDatum(J, "#params with binary location", ParamWithLoc.Value);
1013 
1014   // Print the summary for local variables.
1015   printDatum(J, "#local vars", LocalVarTotal.Value);
1016   printDatum(J, "#local vars with source location", LocalVarWithSrcLoc.Value);
1017   printDatum(J, "#local vars with type", LocalVarWithType.Value);
1018   printDatum(J, "#local vars with binary location", LocalVarWithLoc.Value);
1019 
1020   // Print the debug section sizes.
1021   printSectionSizes(J, Sizes);
1022 
1023   // Print the location statistics for variables (includes local variables
1024   // and formal parameters).
1025   printDatum(J, "#variables processed by location statistics",
1026              LocStats.NumVarParam.Value);
1027   printLocationStats(J, "#variables", LocStats.VarParamLocStats);
1028   printLocationStats(J, "#variables - entry values",
1029                      LocStats.VarParamNonEntryValLocStats);
1030 
1031   // Print the location statistics for formal parameters.
1032   printDatum(J, "#params processed by location statistics",
1033              LocStats.NumParam.Value);
1034   printLocationStats(J, "#params", LocStats.ParamLocStats);
1035   printLocationStats(J, "#params - entry values",
1036                      LocStats.ParamNonEntryValLocStats);
1037 
1038   // Print the location statistics for local variables.
1039   printDatum(J, "#local vars processed by location statistics",
1040              LocStats.NumVar.Value);
1041   printLocationStats(J, "#local vars", LocStats.LocalVarLocStats);
1042   printLocationStats(J, "#local vars - entry values",
1043                      LocStats.LocalVarNonEntryValLocStats);
1044   J.objectEnd();
1045   OS << '\n';
1046   LLVM_DEBUG(llvm::dbgs() << "Total Availability: "
1047                           << (int)std::round((VarParamWithLoc.Value * 100.0) /
1048                                              VarParamTotal.Value)
1049                           << "%\n";
1050              llvm::dbgs() << "PC Ranges covered: "
1051                           << (int)std::round(
1052                                  (GlobalStats.ScopeBytesCovered.Value * 100.0) /
1053                                  GlobalStats.ScopeBytes.Value)
1054                           << "%\n");
1055   return true;
1056 }
1057