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