summaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-dwarfdump/Statistics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-dwarfdump/Statistics.cpp')
-rw-r--r--llvm/tools/llvm-dwarfdump/Statistics.cpp407
1 files changed, 261 insertions, 146 deletions
diff --git a/llvm/tools/llvm-dwarfdump/Statistics.cpp b/llvm/tools/llvm-dwarfdump/Statistics.cpp
index 5bef4d5148ca3..18b4c40c4d751 100644
--- a/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -1,3 +1,12 @@
+//===-- Statistics.cpp - Debug Info quality metrics -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-dwarfdump.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
@@ -9,7 +18,8 @@
#define DEBUG_TYPE "dwarfdump"
using namespace llvm;
-using namespace object;
+using namespace llvm::dwarfdump;
+using namespace llvm::object;
/// This represents the number of categories of debug location coverage being
/// calculated. The first category is the number of variables with 0% location
@@ -17,11 +27,14 @@ using namespace object;
/// location coverage.
constexpr int NumOfCoverageCategories = 12;
+namespace {
/// Holds statistics for one function (or other entity that has a PC range and
/// contains variables, such as a compile unit).
struct PerFunctionStats {
/// Number of inlined instances of this function.
unsigned NumFnInlined = 0;
+ /// Number of out-of-line instances of this function.
+ unsigned NumFnOutOfLine = 0;
/// Number of inlined instances that have abstract origins.
unsigned NumAbstractOrigins = 0;
/// Number of variables and parameters with location across all inlined
@@ -29,13 +42,12 @@ struct PerFunctionStats {
unsigned TotalVarWithLoc = 0;
/// Number of constants with location across all inlined instances.
unsigned ConstantMembers = 0;
+ /// Number of arificial variables, parameters or members across all instances.
+ unsigned NumArtificial = 0;
/// List of all Variables and parameters in this function.
StringSet<> VarsInFunction;
/// Compile units also cover a PC range, but have this flag set to false.
bool IsFunction = false;
- /// Verify function definition has PC addresses (for detecting when
- /// a function has been inlined everywhere).
- bool HasPCAddresses = false;
/// Function has source location information.
bool HasSourceLocation = false;
/// Number of function parameters.
@@ -46,14 +58,14 @@ struct PerFunctionStats {
unsigned NumParamTypes = 0;
/// Number of function parameters with a DW_AT_location.
unsigned NumParamLocations = 0;
- /// Number of variables.
- unsigned NumVars = 0;
- /// Number of variables with source location.
- unsigned NumVarSourceLocations = 0;
- /// Number of variables with type.
- unsigned NumVarTypes = 0;
- /// Number of variables with DW_AT_location.
- unsigned NumVarLocations = 0;
+ /// Number of local variables.
+ unsigned NumLocalVars = 0;
+ /// Number of local variables with source location.
+ unsigned NumLocalVarSourceLocations = 0;
+ /// Number of local variables with type.
+ unsigned NumLocalVarTypes = 0;
+ /// Number of local variables with DW_AT_location.
+ unsigned NumLocalVarLocations = 0;
};
/// Holds accumulated global statistics about DIEs.
@@ -68,21 +80,19 @@ struct GlobalStats {
/// Total number of PC range bytes covered by DW_AT_locations of
/// formal parameters.
unsigned ParamScopeBytesCovered = 0;
- /// Total number of PC range bytes in each variable's enclosing scope
- /// (only for parameters).
+ /// Total number of PC range bytes in each parameter's enclosing scope.
unsigned ParamScopeBytes = 0;
/// Total number of PC range bytes covered by DW_AT_locations with
/// the debug entry values (DW_OP_entry_value) (only for parameters).
unsigned ParamScopeEntryValueBytesCovered = 0;
/// Total number of PC range bytes covered by DW_AT_locations (only for local
/// variables).
- unsigned VarScopeBytesCovered = 0;
- /// Total number of PC range bytes in each variable's enclosing scope
- /// (only for local variables).
- unsigned VarScopeBytes = 0;
+ unsigned LocalVarScopeBytesCovered = 0;
+ /// Total number of PC range bytes in each local variable's enclosing scope.
+ unsigned LocalVarScopeBytes = 0;
/// Total number of PC range bytes covered by DW_AT_locations with
/// the debug entry values (DW_OP_entry_value) (only for local variables).
- unsigned VarScopeEntryValueBytesCovered = 0;
+ unsigned LocalVarScopeEntryValueBytesCovered = 0;
/// Total number of call site entries (DW_AT_call_file & DW_AT_call_line).
unsigned CallSiteEntries = 0;
/// Total number of call site DIEs (DW_TAG_call_site).
@@ -118,10 +128,10 @@ struct LocationStats {
std::vector<unsigned> ParamNonEntryValLocStats{
std::vector<unsigned>(NumOfCoverageCategories, 0)};
/// The debug location statistics for local variables.
- std::vector<unsigned> VarLocStats{
+ std::vector<unsigned> LocalVarLocStats{
std::vector<unsigned>(NumOfCoverageCategories, 0)};
/// Map non debug entry values coverage for local variables.
- std::vector<unsigned> VarNonEntryValLocStats{
+ std::vector<unsigned> LocalVarNonEntryValLocStats{
std::vector<unsigned>(NumOfCoverageCategories, 0)};
/// Total number of local variables and function parameters processed.
unsigned NumVarParam = 0;
@@ -130,13 +140,14 @@ struct LocationStats {
/// Total number of local variables processed.
unsigned NumVar = 0;
};
+} // namespace
/// Collect debug location statistics for one DIE.
static void collectLocStats(uint64_t BytesCovered, uint64_t BytesInScope,
std::vector<unsigned> &VarParamLocStats,
std::vector<unsigned> &ParamLocStats,
- std::vector<unsigned> &VarLocStats, bool IsParam,
- bool IsLocalVar) {
+ std::vector<unsigned> &LocalVarLocStats,
+ bool IsParam, bool IsLocalVar) {
auto getCoverageBucket = [BytesCovered, BytesInScope]() -> unsigned {
// No debug location at all for the variable.
if (BytesCovered == 0)
@@ -155,7 +166,36 @@ static void collectLocStats(uint64_t BytesCovered, uint64_t BytesInScope,
if (IsParam)
ParamLocStats[CoverageBucket]++;
else if (IsLocalVar)
- VarLocStats[CoverageBucket]++;
+ LocalVarLocStats[CoverageBucket]++;
+}
+/// Construct an identifier for a given DIE from its Prefix, Name, DeclFileName
+/// and DeclLine. The identifier aims to be unique for any unique entities,
+/// but keeping the same among different instances of the same entity.
+static std::string constructDieID(DWARFDie Die,
+ StringRef Prefix = StringRef()) {
+ std::string IDStr;
+ llvm::raw_string_ostream ID(IDStr);
+ ID << Prefix
+ << Die.getName(DINameKind::LinkageName);
+
+ // Prefix + Name is enough for local variables and parameters.
+ if (!Prefix.empty() && !Prefix.equals("g"))
+ return ID.str();
+
+ auto DeclFile = Die.findRecursively(dwarf::DW_AT_decl_file);
+ std::string File;
+ if (DeclFile) {
+ DWARFUnit *U = Die.getDwarfUnit();
+ if (const auto *LT = U->getContext().getLineTableForUnit(U))
+ if (LT->getFileNameByIndex(
+ dwarf::toUnsigned(DeclFile, 0), U->getCompilationDir(),
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File))
+ File = std::string(sys::path::filename(File));
+ }
+ ID << ":" << (File.empty() ? "/" : File);
+ ID << ":"
+ << dwarf::toUnsigned(Die.findRecursively(dwarf::DW_AT_decl_line), 0);
+ return ID.str();
}
/// Collect debug info quality metrics for one DIE.
@@ -168,12 +208,13 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
bool HasLoc = false;
bool HasSrcLoc = false;
bool HasType = false;
- bool IsArtificial = false;
uint64_t BytesCovered = 0;
uint64_t BytesEntryValuesCovered = 0;
auto &FnStats = FnStatMap[FnPrefix];
bool IsParam = Die.getTag() == dwarf::DW_TAG_formal_parameter;
bool IsLocalVar = Die.getTag() == dwarf::DW_TAG_variable;
+ bool IsConstantMember = Die.getTag() == dwarf::DW_TAG_member &&
+ Die.find(dwarf::DW_AT_const_value);
if (Die.getTag() == dwarf::DW_TAG_call_site ||
Die.getTag() == dwarf::DW_TAG_GNU_call_site) {
@@ -187,11 +228,15 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
return;
}
- if (!IsParam && !IsLocalVar && Die.getTag() != dwarf::DW_TAG_member) {
+ if (!IsParam && !IsLocalVar && !IsConstantMember) {
// Not a variable or constant member.
return;
}
+ // Ignore declarations of global variables.
+ if (IsLocalVar && Die.find(dwarf::DW_AT_declaration))
+ return;
+
if (Die.findRecursively(dwarf::DW_AT_decl_file) &&
Die.findRecursively(dwarf::DW_AT_decl_line))
HasSrcLoc = true;
@@ -199,14 +244,12 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
if (Die.findRecursively(dwarf::DW_AT_type))
HasType = true;
- if (Die.find(dwarf::DW_AT_artificial))
- IsArtificial = true;
-
auto IsEntryValue = [&](ArrayRef<uint8_t> D) -> bool {
DWARFUnit *U = Die.getDwarfUnit();
DataExtractor Data(toStringRef(D),
Die.getDwarfUnit()->getContext().isLittleEndian(), 0);
- DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize());
+ DWARFExpression Expression(Data, U->getAddressByteSize(),
+ U->getFormParams().Format);
// Consider the expression containing the DW_OP_entry_value as
// an entry value.
return llvm::any_of(Expression, [](DWARFExpression::Operation &Op) {
@@ -220,10 +263,6 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
HasLoc = true;
BytesCovered = BytesInScope;
} else {
- if (Die.getTag() == dwarf::DW_TAG_member) {
- // Non-const member.
- return;
- }
// Handle variables and function arguments.
Expected<std::vector<DWARFLocationExpression>> Loc =
Die.getLocations(dwarf::DW_AT_location);
@@ -257,25 +296,24 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
LocStats.NumVar++;
collectLocStats(BytesCovered, BytesInScope, LocStats.VarParamLocStats,
- LocStats.ParamLocStats, LocStats.VarLocStats, IsParam,
+ LocStats.ParamLocStats, LocStats.LocalVarLocStats, IsParam,
IsLocalVar);
// Non debug entry values coverage statistics.
collectLocStats(BytesCovered - BytesEntryValuesCovered, BytesInScope,
LocStats.VarParamNonEntryValLocStats,
LocStats.ParamNonEntryValLocStats,
- LocStats.VarNonEntryValLocStats, IsParam, IsLocalVar);
+ LocStats.LocalVarNonEntryValLocStats, IsParam, IsLocalVar);
}
// Collect PC range coverage data.
if (DWARFDie D =
Die.getAttributeValueAsReferencedDie(dwarf::DW_AT_abstract_origin))
Die = D;
- // By using the variable name + the path through the lexical block tree, the
- // keys are consistent across duplicate abstract origins in different CUs.
- std::string VarName = StringRef(Die.getName(DINameKind::ShortName));
- FnStats.VarsInFunction.insert(VarPrefix + VarName);
+
+ std::string VarID = constructDieID(Die, VarPrefix);
+ FnStats.VarsInFunction.insert(VarID);
+
if (BytesInScope) {
- FnStats.TotalVarWithLoc += (unsigned)HasLoc;
// Turns out we have a lot of ranges that extend past the lexical scope.
GlobalStats.ScopeBytesCovered += std::min(BytesInScope, BytesCovered);
GlobalStats.ScopeBytes += BytesInScope;
@@ -286,34 +324,43 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
GlobalStats.ParamScopeBytes += BytesInScope;
GlobalStats.ParamScopeEntryValueBytesCovered += BytesEntryValuesCovered;
} else if (IsLocalVar) {
- GlobalStats.VarScopeBytesCovered += std::min(BytesInScope, BytesCovered);
- GlobalStats.VarScopeBytes += BytesInScope;
- GlobalStats.VarScopeEntryValueBytesCovered += BytesEntryValuesCovered;
+ GlobalStats.LocalVarScopeBytesCovered +=
+ std::min(BytesInScope, BytesCovered);
+ GlobalStats.LocalVarScopeBytes += BytesInScope;
+ GlobalStats.LocalVarScopeEntryValueBytesCovered +=
+ BytesEntryValuesCovered;
}
assert(GlobalStats.ScopeBytesCovered <= GlobalStats.ScopeBytes);
- } else if (Die.getTag() == dwarf::DW_TAG_member) {
+ }
+
+ if (IsConstantMember) {
FnStats.ConstantMembers++;
- } else {
- FnStats.TotalVarWithLoc += (unsigned)HasLoc;
+ return;
}
- if (!IsArtificial) {
- if (IsParam) {
- FnStats.NumParams++;
- if (HasType)
- FnStats.NumParamTypes++;
- if (HasSrcLoc)
- FnStats.NumParamSourceLocations++;
- if (HasLoc)
- FnStats.NumParamLocations++;
- } else if (IsLocalVar) {
- FnStats.NumVars++;
- if (HasType)
- FnStats.NumVarTypes++;
- if (HasSrcLoc)
- FnStats.NumVarSourceLocations++;
- if (HasLoc)
- FnStats.NumVarLocations++;
- }
+
+ FnStats.TotalVarWithLoc += (unsigned)HasLoc;
+
+ if (Die.find(dwarf::DW_AT_artificial)) {
+ FnStats.NumArtificial++;
+ return;
+ }
+
+ if (IsParam) {
+ FnStats.NumParams++;
+ if (HasType)
+ FnStats.NumParamTypes++;
+ if (HasSrcLoc)
+ FnStats.NumParamSourceLocations++;
+ if (HasLoc)
+ FnStats.NumParamLocations++;
+ } else if (IsLocalVar) {
+ FnStats.NumLocalVars++;
+ if (HasType)
+ FnStats.NumLocalVarTypes++;
+ if (HasSrcLoc)
+ FnStats.NumLocalVarSourceLocations++;
+ if (HasLoc)
+ FnStats.NumLocalVarLocations++;
}
}
@@ -324,8 +371,12 @@ static void collectStatsRecursive(DWARFDie Die, std::string FnPrefix,
StringMap<PerFunctionStats> &FnStatMap,
GlobalStats &GlobalStats,
LocationStats &LocStats) {
- // Handle any kind of lexical scope.
const dwarf::Tag Tag = Die.getTag();
+ // Skip function types.
+ if (Tag == dwarf::DW_TAG_subroutine_type)
+ return;
+
+ // Handle any kind of lexical scope.
const bool IsFunction = Tag == dwarf::DW_TAG_subprogram;
const bool IsBlock = Tag == dwarf::DW_TAG_lexical_block;
const bool IsInlinedFunction = Tag == dwarf::DW_TAG_inlined_subroutine;
@@ -358,27 +409,25 @@ static void collectStatsRecursive(DWARFDie Die, std::string FnPrefix,
// Count the function.
if (!IsBlock) {
- StringRef Name = Die.getName(DINameKind::LinkageName);
- if (Name.empty())
- Name = Die.getName(DINameKind::ShortName);
- FnPrefix = Name;
// Skip over abstract origins.
if (Die.find(dwarf::DW_AT_inline))
return;
- // We've seen an (inlined) instance of this function.
- auto &FnStats = FnStatMap[Name];
+ std::string FnID = constructDieID(Die);
+ // We've seen an instance of this function.
+ auto &FnStats = FnStatMap[FnID];
+ FnStats.IsFunction = true;
if (IsInlinedFunction) {
FnStats.NumFnInlined++;
if (Die.findRecursively(dwarf::DW_AT_abstract_origin))
FnStats.NumAbstractOrigins++;
+ } else {
+ FnStats.NumFnOutOfLine++;
}
- FnStats.IsFunction = true;
- if (BytesInThisScope && !IsInlinedFunction)
- FnStats.HasPCAddresses = true;
- std::string FnName = StringRef(Die.getName(DINameKind::ShortName));
if (Die.findRecursively(dwarf::DW_AT_decl_file) &&
Die.findRecursively(dwarf::DW_AT_decl_line))
FnStats.HasSourceLocation = true;
+ // Update function prefix.
+ FnPrefix = FnID;
}
if (BytesInThisScope) {
@@ -402,11 +451,14 @@ static void collectStatsRecursive(DWARFDie Die, std::string FnPrefix,
// Traverse children.
unsigned LexicalBlockIndex = 0;
+ unsigned FormalParameterIndex = 0;
DWARFDie Child = Die.getFirstChild();
while (Child) {
std::string ChildVarPrefix = VarPrefix;
if (Child.getTag() == dwarf::DW_TAG_lexical_block)
ChildVarPrefix += toHex(LexicalBlockIndex++) + '.';
+ if (Child.getTag() == dwarf::DW_TAG_formal_parameter)
+ ChildVarPrefix += 'p' + toHex(FormalParameterIndex++) + '.';
collectStatsRecursive(Child, FnPrefix, ChildVarPrefix, BytesInScope,
InlineDepth, FnStatMap, GlobalStats, LocStats);
@@ -421,29 +473,44 @@ static void printDatum(raw_ostream &OS, const char *Key, json::Value Value) {
OS << ",\"" << Key << "\":" << Value;
LLVM_DEBUG(llvm::dbgs() << Key << ": " << Value << '\n');
}
-static void printLocationStats(raw_ostream &OS,
- const char *Key,
+
+static void printLocationStats(raw_ostream &OS, const char *Key,
std::vector<unsigned> &LocationStats) {
- OS << ",\"" << Key << " with 0% of its scope covered\":"
+ OS << ",\"" << Key << " with 0% of parent scope covered by DW_AT_location\":"
<< LocationStats[0];
- LLVM_DEBUG(llvm::dbgs() << Key << " with 0% of its scope covered: "
- << LocationStats[0] << '\n');
- OS << ",\"" << Key << " with (0%,10%) of its scope covered\":"
+ LLVM_DEBUG(
+ llvm::dbgs() << Key
+ << " with 0% of parent scope covered by DW_AT_location: \\"
+ << LocationStats[0] << '\n');
+ OS << ",\"" << Key
+ << " with (0%,10%) of parent scope covered by DW_AT_location\":"
<< LocationStats[1];
- LLVM_DEBUG(llvm::dbgs() << Key << " with (0%,10%) of its scope covered: "
- << LocationStats[1] << '\n');
+ LLVM_DEBUG(llvm::dbgs()
+ << Key
+ << " with (0%,10%) of parent scope covered by DW_AT_location: "
+ << LocationStats[1] << '\n');
for (unsigned i = 2; i < NumOfCoverageCategories - 1; ++i) {
OS << ",\"" << Key << " with [" << (i - 1) * 10 << "%," << i * 10
- << "%) of its scope covered\":" << LocationStats[i];
+ << "%) of parent scope covered by DW_AT_location\":" << LocationStats[i];
LLVM_DEBUG(llvm::dbgs()
<< Key << " with [" << (i - 1) * 10 << "%," << i * 10
- << "%) of its scope covered: " << LocationStats[i]);
+ << "%) of parent scope covered by DW_AT_location: "
+ << LocationStats[i]);
}
- OS << ",\"" << Key << " with 100% of its scope covered\":"
+ OS << ",\"" << Key
+ << " with 100% of parent scope covered by DW_AT_location\":"
<< LocationStats[NumOfCoverageCategories - 1];
- LLVM_DEBUG(llvm::dbgs() << Key << " with 100% of its scope covered: "
- << LocationStats[NumOfCoverageCategories - 1]);
+ LLVM_DEBUG(
+ llvm::dbgs() << Key
+ << " with 100% of parent scope covered by DW_AT_location: "
+ << LocationStats[NumOfCoverageCategories - 1]);
}
+
+static void printSectionSizes(raw_ostream &OS, const SectionSizes &Sizes) {
+ for (const auto &DebugSec : Sizes.DebugSectionSizes)
+ OS << ",\"#bytes in " << DebugSec.getKey() << "\":" << DebugSec.getValue();
+}
+
/// \}
/// Collect debug info quality metrics for an entire DIContext.
@@ -454,8 +521,9 @@ static void printLocationStats(raw_ostream &OS,
/// of particular optimizations. The raw numbers themselves are not particularly
/// useful, only the delta between compiling the same program with different
/// compilers is.
-bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
- Twine Filename, raw_ostream &OS) {
+bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
+ const Twine &Filename,
+ raw_ostream &OS) {
StringRef FormatName = Obj.getFileFormatName();
GlobalStats GlobalStats;
LocationStats LocStats;
@@ -465,10 +533,14 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
collectStatsRecursive(CUDie, "/", "g", 0, 0, Statistics, GlobalStats,
LocStats);
+ /// Collect the sizes of debug sections.
+ SectionSizes Sizes;
+ calculateSectionSizes(Obj, Sizes, Filename);
+
/// The version number should be increased every time the algorithm is changed
/// (including bug fixes). New metrics may be added without increasing the
/// version.
- unsigned Version = 4;
+ unsigned Version = 5;
unsigned VarParamTotal = 0;
unsigned VarParamUnique = 0;
unsigned VarParamWithLoc = 0;
@@ -480,16 +552,18 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
unsigned ParamWithType = 0;
unsigned ParamWithLoc = 0;
unsigned ParamWithSrcLoc = 0;
- unsigned VarTotal = 0;
- unsigned VarWithType = 0;
- unsigned VarWithSrcLoc = 0;
- unsigned VarWithLoc = 0;
+ unsigned LocalVarTotal = 0;
+ unsigned LocalVarWithType = 0;
+ unsigned LocalVarWithSrcLoc = 0;
+ unsigned LocalVarWithLoc = 0;
for (auto &Entry : Statistics) {
PerFunctionStats &Stats = Entry.getValue();
- unsigned TotalVars = Stats.VarsInFunction.size() * Stats.NumFnInlined;
- // Count variables in concrete out-of-line functions and in global scope.
- if (Stats.HasPCAddresses || !Stats.IsFunction)
- TotalVars += Stats.VarsInFunction.size();
+ unsigned TotalVars = Stats.VarsInFunction.size() *
+ (Stats.NumFnInlined + Stats.NumFnOutOfLine);
+ // Count variables in global scope.
+ if (!Stats.IsFunction)
+ TotalVars =
+ Stats.NumLocalVars + Stats.ConstantMembers + Stats.NumArtificial;
unsigned Constants = Stats.ConstantMembers;
VarParamWithLoc += Stats.TotalVarWithLoc + Constants;
VarParamTotal += TotalVars;
@@ -505,10 +579,10 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
ParamWithType += Stats.NumParamTypes;
ParamWithLoc += Stats.NumParamLocations;
ParamWithSrcLoc += Stats.NumParamSourceLocations;
- VarTotal += Stats.NumVars;
- VarWithType += Stats.NumVarTypes;
- VarWithLoc += Stats.NumVarLocations;
- VarWithSrcLoc += Stats.NumVarSourceLocations;
+ LocalVarTotal += Stats.NumLocalVars;
+ LocalVarWithType += Stats.NumLocalVarTypes;
+ LocalVarWithLoc += Stats.NumLocalVarLocations;
+ LocalVarWithSrcLoc += Stats.NumLocalVarSourceLocations;
}
// Print summary.
@@ -516,56 +590,97 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
OS << "{\"version\":" << Version;
LLVM_DEBUG(llvm::dbgs() << "Variable location quality metrics\n";
llvm::dbgs() << "---------------------------------\n");
+
printDatum(OS, "file", Filename.str());
printDatum(OS, "format", FormatName);
- printDatum(OS, "source functions", NumFunctions);
- printDatum(OS, "source functions with location", NumFuncsWithSrcLoc);
- printDatum(OS, "inlined functions", NumInlinedFunctions);
- printDatum(OS, "inlined funcs with abstract origins", NumAbstractOrigins);
- printDatum(OS, "unique source variables", VarParamUnique);
- printDatum(OS, "source variables", VarParamTotal);
- printDatum(OS, "variables with location", VarParamWithLoc);
- printDatum(OS, "call site entries", GlobalStats.CallSiteEntries);
- printDatum(OS, "call site DIEs", GlobalStats.CallSiteDIEs);
- printDatum(OS, "call site parameter DIEs", GlobalStats.CallSiteParamDIEs);
- printDatum(OS, "scope bytes total", GlobalStats.ScopeBytes);
- printDatum(OS, "scope bytes covered", GlobalStats.ScopeBytesCovered);
- printDatum(OS, "entry value scope bytes covered",
+
+ printDatum(OS, "#functions", NumFunctions);
+ printDatum(OS, "#functions with location", NumFuncsWithSrcLoc);
+ printDatum(OS, "#inlined functions", NumInlinedFunctions);
+ printDatum(OS, "#inlined functions with abstract origins",
+ NumAbstractOrigins);
+
+ // This includes local variables and formal parameters.
+ printDatum(OS, "#unique source variables", VarParamUnique);
+ printDatum(OS, "#source variables", VarParamTotal);
+ printDatum(OS, "#source variables with location", VarParamWithLoc);
+
+ printDatum(OS, "#call site entries", GlobalStats.CallSiteEntries);
+ printDatum(OS, "#call site DIEs", GlobalStats.CallSiteDIEs);
+ printDatum(OS, "#call site parameter DIEs", GlobalStats.CallSiteParamDIEs);
+
+ printDatum(OS, "sum_all_variables(#bytes in parent scope)",
+ GlobalStats.ScopeBytes);
+ printDatum(OS,
+ "sum_all_variables(#bytes in parent scope covered by "
+ "DW_AT_location)",
+ GlobalStats.ScopeBytesCovered);
+ printDatum(OS,
+ "sum_all_variables(#bytes in parent scope covered by "
+ "DW_OP_entry_value)",
GlobalStats.ScopeEntryValueBytesCovered);
- printDatum(OS, "formal params scope bytes total",
+
+ printDatum(OS, "sum_all_params(#bytes in parent scope)",
GlobalStats.ParamScopeBytes);
- printDatum(OS, "formal params scope bytes covered",
- GlobalStats.ParamScopeBytesCovered);
- printDatum(OS, "formal params entry value scope bytes covered",
+ printDatum(
+ OS,
+ "sum_all_params(#bytes in parent scope covered by DW_AT_location)",
+ GlobalStats.ParamScopeBytesCovered);
+ printDatum(OS,
+ "sum_all_params(#bytes in parent scope covered by "
+ "DW_OP_entry_value)",
GlobalStats.ParamScopeEntryValueBytesCovered);
- printDatum(OS, "vars scope bytes total", GlobalStats.VarScopeBytes);
- printDatum(OS, "vars scope bytes covered", GlobalStats.VarScopeBytesCovered);
- printDatum(OS, "vars entry value scope bytes covered",
- GlobalStats.VarScopeEntryValueBytesCovered);
- printDatum(OS, "total function size", GlobalStats.FunctionSize);
- printDatum(OS, "total inlined function size", GlobalStats.InlineFunctionSize);
- printDatum(OS, "total formal params", ParamTotal);
- printDatum(OS, "formal params with source location", ParamWithSrcLoc);
- printDatum(OS, "formal params with type", ParamWithType);
- printDatum(OS, "formal params with binary location", ParamWithLoc);
- printDatum(OS, "total vars", VarTotal);
- printDatum(OS, "vars with source location", VarWithSrcLoc);
- printDatum(OS, "vars with type", VarWithType);
- printDatum(OS, "vars with binary location", VarWithLoc);
- printDatum(OS, "total variables procesed by location statistics",
+
+ printDatum(OS, "sum_all_local_vars(#bytes in parent scope)",
+ GlobalStats.LocalVarScopeBytes);
+ printDatum(OS,
+ "sum_all_local_vars(#bytes in parent scope covered by "
+ "DW_AT_location)",
+ GlobalStats.LocalVarScopeBytesCovered);
+ printDatum(OS,
+ "sum_all_local_vars(#bytes in parent scope covered by "
+ "DW_OP_entry_value)",
+ GlobalStats.LocalVarScopeEntryValueBytesCovered);
+
+ printDatum(OS, "#bytes witin functions", GlobalStats.FunctionSize);
+ printDatum(OS, "#bytes witin inlined functions",
+ GlobalStats.InlineFunctionSize);
+
+ // Print the summary for formal parameters.
+ printDatum(OS, "#params", ParamTotal);
+ printDatum(OS, "#params with source location", ParamWithSrcLoc);
+ printDatum(OS, "#params with type", ParamWithType);
+ printDatum(OS, "#params with binary location", ParamWithLoc);
+
+ // Print the summary for local variables.
+ printDatum(OS, "#local vars", LocalVarTotal);
+ printDatum(OS, "#local vars with source location", LocalVarWithSrcLoc);
+ printDatum(OS, "#local vars with type", LocalVarWithType);
+ printDatum(OS, "#local vars with binary location", LocalVarWithLoc);
+
+ // Print the debug section sizes.
+ printSectionSizes(OS, Sizes);
+
+ // Print the location statistics for variables (includes local variables
+ // and formal parameters).
+ printDatum(OS, "#variables processed by location statistics",
LocStats.NumVarParam);
- printLocationStats(OS, "variables", LocStats.VarParamLocStats);
- printLocationStats(OS, "variables (excluding the debug entry values)",
+ printLocationStats(OS, "#variables", LocStats.VarParamLocStats);
+ printLocationStats(OS, "#variables - entry values",
LocStats.VarParamNonEntryValLocStats);
- printDatum(OS, "total params procesed by location statistics",
- LocStats.NumParam);
- printLocationStats(OS, "params", LocStats.ParamLocStats);
- printLocationStats(OS, "params (excluding the debug entry values)",
+
+ // Print the location statistics for formal parameters.
+ printDatum(OS, "#params processed by location statistics", LocStats.NumParam);
+ printLocationStats(OS, "#params", LocStats.ParamLocStats);
+ printLocationStats(OS, "#params - entry values",
LocStats.ParamNonEntryValLocStats);
- printDatum(OS, "total vars procesed by location statistics", LocStats.NumVar);
- printLocationStats(OS, "vars", LocStats.VarLocStats);
- printLocationStats(OS, "vars (excluding the debug entry values)",
- LocStats.VarNonEntryValLocStats);
+
+ // Print the location statistics for local variables.
+ printDatum(OS, "#local vars processed by location statistics",
+ LocStats.NumVar);
+ printLocationStats(OS, "#local vars", LocStats.LocalVarLocStats);
+ printLocationStats(OS, "#local vars - entry values",
+ LocStats.LocalVarNonEntryValLocStats);
OS << "}\n";
LLVM_DEBUG(
llvm::dbgs() << "Total Availability: "