summaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-01-24 22:00:03 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-01-24 22:00:03 +0000
commit480093f4440d54b30b3025afeac24b48f2ba7a2e (patch)
tree162e72994062888647caf0d875428db9445491a8 /contrib/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
parent489b1cf2ecf5b9b4a394857987014bfb09067726 (diff)
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
Notes
Diffstat (limited to 'contrib/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp')
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp153
1 files changed, 59 insertions, 94 deletions
diff --git a/contrib/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp b/contrib/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
index c29ad783a9e6..5bef4d5148ca 100644
--- a/contrib/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -60,28 +60,26 @@ struct PerFunctionStats {
struct GlobalStats {
/// Total number of PC range bytes covered by DW_AT_locations.
unsigned ScopeBytesCovered = 0;
- /// Total number of PC range bytes in each variable's enclosing scope,
- /// starting from the first definition of the variable.
- unsigned ScopeBytesFromFirstDefinition = 0;
+ /// Total number of PC range bytes in each variable's enclosing scope.
+ unsigned ScopeBytes = 0;
/// Total number of PC range bytes covered by DW_AT_locations with
/// the debug entry values (DW_OP_entry_value).
unsigned ScopeEntryValueBytesCovered = 0;
/// 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,
- /// starting from the first definition of the variable (only for parameters).
- unsigned ParamScopeBytesFromFirstDefinition = 0;
+ /// Total number of PC range bytes in each variable's enclosing scope
+ /// (only for parameters).
+ 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,
- /// starting from the first definition of the variable (only for local
- /// variables).
- unsigned VarScopeBytesFromFirstDefinition = 0;
+ /// Total number of PC range bytes in each variable's enclosing scope
+ /// (only for local variables).
+ unsigned VarScopeBytes = 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;
@@ -133,19 +131,6 @@ struct LocationStats {
unsigned NumVar = 0;
};
-/// Extract the low pc from a Die.
-static uint64_t getLowPC(DWARFDie Die) {
- auto RangesOrError = Die.getAddressRanges();
- DWARFAddressRangesVector Ranges;
- if (RangesOrError)
- Ranges = RangesOrError.get();
- else
- llvm::consumeError(RangesOrError.takeError());
- if (Ranges.size())
- return Ranges[0].LowPC;
- return dwarf::toAddress(Die.find(dwarf::DW_AT_low_pc), 0);
-}
-
/// Collect debug location statistics for one DIE.
static void collectLocStats(uint64_t BytesCovered, uint64_t BytesInScope,
std::vector<unsigned> &VarParamLocStats,
@@ -153,18 +138,16 @@ static void collectLocStats(uint64_t BytesCovered, uint64_t BytesInScope,
std::vector<unsigned> &VarLocStats, bool IsParam,
bool IsLocalVar) {
auto getCoverageBucket = [BytesCovered, BytesInScope]() -> unsigned {
- unsigned LocBucket = 100 * (double)BytesCovered / BytesInScope;
- if (LocBucket == 0) {
- // No debug location at all for the variable.
+ // No debug location at all for the variable.
+ if (BytesCovered == 0)
return 0;
- } else if (LocBucket == 100 || BytesCovered > BytesInScope) {
- // Fully covered variable within its scope.
+ // Fully covered variable within its scope.
+ if (BytesCovered >= BytesInScope)
return NumOfCoverageCategories - 1;
- } else {
- // Get covered range (e.g. 20%-29%).
- LocBucket /= 10;
- return LocBucket + 1;
- }
+ // Get covered range (e.g. 20%-29%).
+ unsigned LocBucket = 100 * (double)BytesCovered / BytesInScope;
+ LocBucket /= 10;
+ return LocBucket + 1;
};
unsigned CoverageBucket = getCoverageBucket();
@@ -176,9 +159,9 @@ static void collectLocStats(uint64_t BytesCovered, uint64_t BytesInScope,
}
/// Collect debug info quality metrics for one DIE.
-static void collectStatsForDie(DWARFDie Die, uint64_t UnitLowPC, std::string FnPrefix,
- std::string VarPrefix, uint64_t ScopeLowPC,
- uint64_t BytesInScope, uint32_t InlineDepth,
+static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
+ std::string VarPrefix, uint64_t BytesInScope,
+ uint32_t InlineDepth,
StringMap<PerFunctionStats> &FnStatMap,
GlobalStats &GlobalStats,
LocationStats &LocStats) {
@@ -188,7 +171,6 @@ static void collectStatsForDie(DWARFDie Die, uint64_t UnitLowPC, std::string FnP
bool IsArtificial = false;
uint64_t BytesCovered = 0;
uint64_t BytesEntryValuesCovered = 0;
- uint64_t OffsetToFirstDefinition = 0;
auto &FnStats = FnStatMap[FnPrefix];
bool IsParam = Die.getTag() == dwarf::DW_TAG_formal_parameter;
bool IsLocalVar = Die.getTag() == dwarf::DW_TAG_variable;
@@ -243,34 +225,25 @@ static void collectStatsForDie(DWARFDie Die, uint64_t UnitLowPC, std::string FnP
return;
}
// Handle variables and function arguments.
- auto FormValue = Die.find(dwarf::DW_AT_location);
- HasLoc = FormValue.hasValue();
- if (HasLoc) {
+ Expected<std::vector<DWARFLocationExpression>> Loc =
+ Die.getLocations(dwarf::DW_AT_location);
+ if (!Loc) {
+ consumeError(Loc.takeError());
+ } else {
+ HasLoc = true;
// Get PC coverage.
- if (auto DebugLocOffset = FormValue->getAsSectionOffset()) {
- auto *DebugLoc = Die.getDwarfUnit()->getContext().getDebugLoc();
- if (auto List = DebugLoc->getLocationListAtOffset(*DebugLocOffset)) {
- for (auto Entry : List->Entries) {
- uint64_t BytesEntryCovered = Entry.End - Entry.Begin;
- BytesCovered += BytesEntryCovered;
- if (IsEntryValue(Entry.Loc))
- BytesEntryValuesCovered += BytesEntryCovered;
- }
- if (List->Entries.size()) {
- uint64_t FirstDef = List->Entries[0].Begin;
- uint64_t UnitOfs = UnitLowPC;
- // Ranges sometimes start before the lexical scope.
- if (UnitOfs + FirstDef >= ScopeLowPC)
- OffsetToFirstDefinition = UnitOfs + FirstDef - ScopeLowPC;
- // Or even after it. Count that as a failure.
- if (OffsetToFirstDefinition > BytesInScope)
- OffsetToFirstDefinition = 0;
- }
- }
- assert(BytesInScope);
- } else {
+ auto Default = find_if(
+ *Loc, [](const DWARFLocationExpression &L) { return !L.Range; });
+ if (Default != Loc->end()) {
// Assume the entire range is covered by a single location.
BytesCovered = BytesInScope;
+ } else {
+ for (auto Entry : *Loc) {
+ uint64_t BytesEntryCovered = Entry.Range->HighPC - Entry.Range->LowPC;
+ BytesCovered += BytesEntryCovered;
+ if (IsEntryValue(Entry.Expr))
+ BytesEntryValuesCovered += BytesEntryCovered;
+ }
}
}
}
@@ -303,25 +276,21 @@ static void collectStatsForDie(DWARFDie Die, uint64_t UnitLowPC, std::string FnP
FnStats.VarsInFunction.insert(VarPrefix + VarName);
if (BytesInScope) {
FnStats.TotalVarWithLoc += (unsigned)HasLoc;
- // Adjust for the fact the variables often start their lifetime in the
- // middle of the scope.
- BytesInScope -= OffsetToFirstDefinition;
// Turns out we have a lot of ranges that extend past the lexical scope.
GlobalStats.ScopeBytesCovered += std::min(BytesInScope, BytesCovered);
- GlobalStats.ScopeBytesFromFirstDefinition += BytesInScope;
+ GlobalStats.ScopeBytes += BytesInScope;
GlobalStats.ScopeEntryValueBytesCovered += BytesEntryValuesCovered;
if (IsParam) {
GlobalStats.ParamScopeBytesCovered +=
std::min(BytesInScope, BytesCovered);
- GlobalStats.ParamScopeBytesFromFirstDefinition += BytesInScope;
+ GlobalStats.ParamScopeBytes += BytesInScope;
GlobalStats.ParamScopeEntryValueBytesCovered += BytesEntryValuesCovered;
} else if (IsLocalVar) {
GlobalStats.VarScopeBytesCovered += std::min(BytesInScope, BytesCovered);
- GlobalStats.VarScopeBytesFromFirstDefinition += BytesInScope;
+ GlobalStats.VarScopeBytes += BytesInScope;
GlobalStats.VarScopeEntryValueBytesCovered += BytesEntryValuesCovered;
}
- assert(GlobalStats.ScopeBytesCovered <=
- GlobalStats.ScopeBytesFromFirstDefinition);
+ assert(GlobalStats.ScopeBytesCovered <= GlobalStats.ScopeBytes);
} else if (Die.getTag() == dwarf::DW_TAG_member) {
FnStats.ConstantMembers++;
} else {
@@ -349,9 +318,9 @@ static void collectStatsForDie(DWARFDie Die, uint64_t UnitLowPC, std::string FnP
}
/// Recursively collect debug info quality metrics.
-static void collectStatsRecursive(DWARFDie Die, uint64_t UnitLowPC, std::string FnPrefix,
- std::string VarPrefix, uint64_t ScopeLowPC,
- uint64_t BytesInScope, uint32_t InlineDepth,
+static void collectStatsRecursive(DWARFDie Die, std::string FnPrefix,
+ std::string VarPrefix, uint64_t BytesInScope,
+ uint32_t InlineDepth,
StringMap<PerFunctionStats> &FnStatMap,
GlobalStats &GlobalStats,
LocationStats &LocStats) {
@@ -386,7 +355,6 @@ static void collectStatsRecursive(DWARFDie Die, uint64_t UnitLowPC, std::string
uint64_t BytesInThisScope = 0;
for (auto Range : Ranges)
BytesInThisScope += Range.HighPC - Range.LowPC;
- ScopeLowPC = getLowPC(Die);
// Count the function.
if (!IsBlock) {
@@ -422,8 +390,8 @@ static void collectStatsRecursive(DWARFDie Die, uint64_t UnitLowPC, std::string
}
} else {
// Not a scope, visit the Die itself. It could be a variable.
- collectStatsForDie(Die, UnitLowPC, FnPrefix, VarPrefix, ScopeLowPC, BytesInScope,
- InlineDepth, FnStatMap, GlobalStats, LocStats);
+ collectStatsForDie(Die, FnPrefix, VarPrefix, BytesInScope, InlineDepth,
+ FnStatMap, GlobalStats, LocStats);
}
// Set InlineDepth correctly for child recursion
@@ -440,9 +408,8 @@ static void collectStatsRecursive(DWARFDie Die, uint64_t UnitLowPC, std::string
if (Child.getTag() == dwarf::DW_TAG_lexical_block)
ChildVarPrefix += toHex(LexicalBlockIndex++) + '.';
- collectStatsRecursive(Child, UnitLowPC, FnPrefix, ChildVarPrefix, ScopeLowPC,
- BytesInScope, InlineDepth, FnStatMap, GlobalStats,
- LocStats);
+ collectStatsRecursive(Child, FnPrefix, ChildVarPrefix, BytesInScope,
+ InlineDepth, FnStatMap, GlobalStats, LocStats);
Child = Child.getSibling();
}
}
@@ -461,16 +428,16 @@ static void printLocationStats(raw_ostream &OS,
<< LocationStats[0];
LLVM_DEBUG(llvm::dbgs() << Key << " with 0% of its scope covered: "
<< LocationStats[0] << '\n');
- OS << ",\"" << Key << " with 1-9% of its scope covered\":"
+ OS << ",\"" << Key << " with (0%,10%) of its scope covered\":"
<< LocationStats[1];
- LLVM_DEBUG(llvm::dbgs() << Key << " with 1-9% of its scope covered: "
+ LLVM_DEBUG(llvm::dbgs() << Key << " with (0%,10%) of its scope covered: "
<< LocationStats[1] << '\n');
for (unsigned i = 2; i < NumOfCoverageCategories - 1; ++i) {
- OS << ",\"" << Key << " with " << (i - 1) * 10 << "-" << i * 10 - 1
- << "% of its scope covered\":" << LocationStats[i];
+ OS << ",\"" << Key << " with [" << (i - 1) * 10 << "%," << i * 10
+ << "%) of its scope covered\":" << LocationStats[i];
LLVM_DEBUG(llvm::dbgs()
- << Key << " with " << (i - 1) * 10 << "-" << i * 10 - 1
- << "% of its scope covered: " << LocationStats[i]);
+ << Key << " with [" << (i - 1) * 10 << "%," << i * 10
+ << "%) of its scope covered: " << LocationStats[i]);
}
OS << ",\"" << Key << " with 100% of its scope covered\":"
<< LocationStats[NumOfCoverageCategories - 1];
@@ -495,13 +462,13 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
StringMap<PerFunctionStats> Statistics;
for (const auto &CU : static_cast<DWARFContext *>(&DICtx)->compile_units())
if (DWARFDie CUDie = CU->getNonSkeletonUnitDIE(false))
- collectStatsRecursive(CUDie, getLowPC(CUDie), "/", "g", 0, 0, 0,
- Statistics, GlobalStats, LocStats);
+ collectStatsRecursive(CUDie, "/", "g", 0, 0, Statistics, GlobalStats,
+ LocStats);
/// 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 = 3;
+ unsigned Version = 4;
unsigned VarParamTotal = 0;
unsigned VarParamUnique = 0;
unsigned VarParamWithLoc = 0;
@@ -561,19 +528,17 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
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.ScopeBytesFromFirstDefinition);
+ printDatum(OS, "scope bytes total", GlobalStats.ScopeBytes);
printDatum(OS, "scope bytes covered", GlobalStats.ScopeBytesCovered);
printDatum(OS, "entry value scope bytes covered",
GlobalStats.ScopeEntryValueBytesCovered);
printDatum(OS, "formal params scope bytes total",
- GlobalStats.ParamScopeBytesFromFirstDefinition);
+ GlobalStats.ParamScopeBytes);
printDatum(OS, "formal params scope bytes covered",
GlobalStats.ParamScopeBytesCovered);
printDatum(OS, "formal params entry value scope bytes covered",
GlobalStats.ParamScopeEntryValueBytesCovered);
- printDatum(OS, "vars scope bytes total",
- GlobalStats.VarScopeBytesFromFirstDefinition);
+ 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);
@@ -608,7 +573,7 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
<< "%\n";
llvm::dbgs() << "PC Ranges covered: "
<< (int)std::round((GlobalStats.ScopeBytesCovered * 100.0) /
- GlobalStats.ScopeBytesFromFirstDefinition)
+ GlobalStats.ScopeBytes)
<< "%\n");
return true;
}