Index: llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -15,6 +15,8 @@ #include "llvm/Support/DataExtractor.h" namespace llvm { +struct DWARFAttribute; +class DWARFContext; class DWARFUnit; class MCRegisterInfo; class raw_ostream; @@ -132,6 +134,12 @@ assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2); } + /// Form DWARFExpression objects by parsing a DW_AT_location attribute and + /// pass them into a visitor function. + static void visitExpressionsInLocation(const DWARFAttribute &Location, + DWARFUnit &U, DWARFContext &DCtx, + function_ref F); + iterator begin() const { return iterator(this, 0); } iterator end() const { return iterator(this, Data.getData().size()); } Index: llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/BinaryFormat/Dwarf.h" @@ -202,6 +203,26 @@ return true; } +void DWARFExpression::visitExpressionsInLocation( + const DWARFAttribute &Location, DWARFUnit &U, DWARFContext &DCtx, + function_ref F) { + assert(Location.Attr == DW_AT_location && "Attribute isn't a location"); + auto Visit = [&](StringRef D) { + DataExtractor Data(D, DCtx.isLittleEndian(), 0); + F(DWARFExpression(Data, U.getVersion(), U.getAddressByteSize())); + }; + if (Optional> Expr = Location.Value.getAsBlock()) { + // Visit inlined locations. + Visit(llvm::toStringRef(*Expr)); + } else if (auto LocOffset = Location.Value.getAsSectionOffset()) { + // Visit location lists. + if (auto DebugLoc = DCtx.getDebugLoc()) + if (auto LocList = DebugLoc->getLocationListAtOffset(*LocOffset)) + for (const auto &Entry : LocList->Entries) + Visit({Entry.Loc.data(), Entry.Loc.size()}); + } +} + static bool prettyPrintRegisterOp(raw_ostream &OS, uint8_t Opcode, uint64_t Operands[2], const MCRegisterInfo *MRI, bool isEH) { Index: llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -466,27 +466,16 @@ ReportError("DIE has invalid DW_AT_stmt_list encoding:"); break; case DW_AT_location: { - auto VerifyLocationExpr = [&](StringRef D) { - DWARFUnit *U = Die.getDwarfUnit(); - DataExtractor Data(D, DCtx.isLittleEndian(), 0); - DWARFExpression Expression(Data, U->getVersion(), - U->getAddressByteSize()); + DWARFUnit *U = Die.getDwarfUnit(); + auto VerifyLocationExpr = [&](DWARFExpression Expression) { bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) { return Op.isError(); }); if (Error || !Expression.verify(U)) ReportError("DIE contains invalid DWARF expression:"); }; - if (Optional> Expr = AttrValue.Value.getAsBlock()) { - // Verify inlined location. - VerifyLocationExpr(llvm::toStringRef(*Expr)); - } else if (auto LocOffset = AttrValue.Value.getAsSectionOffset()) { - // Verify location list. - if (auto DebugLoc = DCtx.getDebugLoc()) - if (auto LocList = DebugLoc->getLocationListAtOffset(*LocOffset)) - for (const auto &Entry : LocList->Entries) - VerifyLocationExpr({Entry.Loc.data(), Entry.Loc.size()}); - } + DWARFExpression::visitExpressionsInLocation(AttrValue, *U, DCtx, + VerifyLocationExpr); break; } case DW_AT_specification: Index: llvm/tools/llvm-dwarfdump/Statistics.cpp =================================================================== --- llvm/tools/llvm-dwarfdump/Statistics.cpp +++ llvm/tools/llvm-dwarfdump/Statistics.cpp @@ -39,6 +39,9 @@ unsigned NumParamTypes = 0; /// Number of function parameters with a DW_AT_location. unsigned NumParamLocations = 0; + /// Number of function parameters with a DW_AT_location containing a + /// DW_OP_entry_value description (or the GNU equivalent). + unsigned NumParamLocationsWithEntryVal = 0; /// Number of variables. unsigned NumVars = 0; /// Number of variables with source location. @@ -86,7 +89,7 @@ std::string VarPrefix, uint64_t ScopeLowPC, uint64_t BytesInScope, uint32_t InlineDepth, StringMap &FnStatMap, - GlobalStats &GlobalStats) { + GlobalStats &GlobalStats, DWARFContext &DICtx) { bool HasLoc = false; bool HasSrcLoc = false; bool HasType = false; @@ -185,8 +188,32 @@ FnStats.NumParamTypes++; if (HasSrcLoc) FnStats.NumParamSourceLocations++; - if (HasLoc) + if (HasLoc) { FnStats.NumParamLocations++; + + bool HasEntryVal = false; + auto SearchForEntryVal = [&](DWARFExpression Expression) { + if (HasEntryVal) + return; + HasEntryVal = + llvm::any_of(Expression, [](DWARFExpression::Operation &Op) { + return Op.getCode() == dwarf::DW_OP_GNU_entry_value || + Op.getCode() == dwarf::DW_OP_entry_value; + }); + }; + + DWARFUnit &U = *Die.getDwarfUnit(); + for (const DWARFAttribute &Attr : Die.attributes()) { + if (Attr.Attr == dwarf::DW_AT_location) { + DWARFExpression::visitExpressionsInLocation(Attr, U, DICtx, + SearchForEntryVal); + if (HasEntryVal) { + FnStats.NumParamLocationsWithEntryVal++; + break; + } + } + } + } } else if (Die.getTag() == dwarf::DW_TAG_variable) { FnStats.NumVars++; if (HasType) @@ -204,7 +231,8 @@ std::string VarPrefix, uint64_t ScopeLowPC, uint64_t BytesInScope, uint32_t InlineDepth, StringMap &FnStatMap, - GlobalStats &GlobalStats) { + GlobalStats &GlobalStats, + DWARFContext &DICtx) { // Handle any kind of lexical scope. const dwarf::Tag Tag = Die.getTag(); const bool IsFunction = Tag == dwarf::DW_TAG_subprogram; @@ -273,7 +301,7 @@ } else { // Not a scope, visit the Die itself. It could be a variable. collectStatsForDie(Die, FnPrefix, VarPrefix, ScopeLowPC, BytesInScope, - InlineDepth, FnStatMap, GlobalStats); + InlineDepth, FnStatMap, GlobalStats, DICtx); } // Set InlineDepth correctly for child recursion @@ -291,7 +319,8 @@ ChildVarPrefix += toHex(LexicalBlockIndex++) + '.'; collectStatsRecursive(Child, FnPrefix, ChildVarPrefix, ScopeLowPC, - BytesInScope, InlineDepth, FnStatMap, GlobalStats); + BytesInScope, InlineDepth, FnStatMap, GlobalStats, + DICtx); Child = Child.getSibling(); } } @@ -324,7 +353,8 @@ StringMap Statistics; for (const auto &CU : static_cast(&DICtx)->compile_units()) if (DWARFDie CUDie = CU->getNonSkeletonUnitDIE(false)) - collectStatsRecursive(CUDie, "/", "g", 0, 0, 0, Statistics, GlobalStats); + collectStatsRecursive(CUDie, "/", "g", 0, 0, 0, Statistics, GlobalStats, + DICtx); /// The version number should be increased every time the algorithm is changed /// (including bug fixes). New metrics may be added without increasing the @@ -340,6 +370,7 @@ unsigned ParamTotal = 0; unsigned ParamWithType = 0; unsigned ParamWithLoc = 0; + unsigned ParamWithEntryValLoc = 0; unsigned ParamWithSrcLoc = 0; unsigned VarTotal = 0; unsigned VarWithType = 0; @@ -365,6 +396,7 @@ ParamTotal += Stats.NumParams; ParamWithType += Stats.NumParamTypes; ParamWithLoc += Stats.NumParamLocations; + ParamWithEntryValLoc += Stats.NumParamLocationsWithEntryVal; ParamWithSrcLoc += Stats.NumParamSourceLocations; VarTotal += Stats.NumVars; VarWithType += Stats.NumVarTypes; @@ -396,6 +428,8 @@ 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, "formal params with binary location containing entry value", + ParamWithEntryValLoc); printDatum(OS, "total vars", VarTotal); printDatum(OS, "vars with source location", VarWithSrcLoc); printDatum(OS, "vars with type", VarWithType);