diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-01-24 22:00:03 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-01-24 22:00:03 +0000 |
commit | 480093f4440d54b30b3025afeac24b48f2ba7a2e (patch) | |
tree | 162e72994062888647caf0d875428db9445491a8 /contrib/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp | |
parent | 489b1cf2ecf5b9b4a394857987014bfb09067726 (diff) | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (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.cpp | 153 |
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; } |