diff --git a/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c b/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c --- a/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c +++ b/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c @@ -1,16 +1,24 @@ // RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %s -// RUN: llvm-profdata show --debug-info=%t --detailed-summary --show-prof-sym-list | FileCheck %s +// RUN: llvm-profdata show --debug-info=%t | FileCheck %s --match-full-lines // RUN: %clang_pgogen -o %t.no.dbg -mllvm --debug-info-correlate -mllvm --disable-vp=true %s // RUN: not llvm-profdata show --debug-info=%t.no.dbg 2>&1 | FileCheck %s --check-prefix NO-DBG // NO-DBG: unable to correlate profile: could not find any profile metadata in debug info +// CHECK: - Function Name: a +// CHECK: Linkage Name: a +// CHECK: CFG Hash: 0x[[#%.1X,HASH:]] +// CHECK: Counter Offset: 0x0 +// CHECK: Num Counters: 1 +// CHECK: File: [[FILE:'.*']] +// CHECK: Line: [[@LINE+1]] void a() {} -void b() {} -int main() { return 0; } -// CHECK: a -// CHECK: b -// CHECK: main -// CHECK: Counters section size: 0x18 bytes -// CHECK: Found 3 functions +// CHECK: - Function Name: main +// CHECK: Linkage Name: main +// CHECK: CFG Hash: 0x[[#%.1X,HASH:]] +// CHECK: Counter Offset: 0x8 +// CHECK: Num Counters: 1 +// CHECK: File: [[FILE]] +// CHECK: Line: [[@LINE+1]] +int main() { return 0; } diff --git a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h --- a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h +++ b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h @@ -16,6 +16,7 @@ #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/YAMLTraits.h" #include namespace llvm { @@ -36,6 +37,9 @@ /// to their functions. virtual Error correlateProfileData() = 0; + /// Process debug info and dump the correlation data. + virtual Error dumpYaml(raw_ostream &OS) = 0; + /// Return the number of ProfileData elements. llvm::Optional getDataSize() const; @@ -69,7 +73,7 @@ /// True if target and host have different endian orders. bool ShouldSwapBytes; }; - const std::unique_ptr Ctx; + const std::unique_ptr Ctx; InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr Ctx) : Ctx(std::move(Ctx)), Kind(K) {} @@ -77,6 +81,19 @@ std::string Names; std::vector NamesVec; + struct Probe { + std::string FunctionName; + Optional LinkageName; + yaml::Hex64 CFGHash; + yaml::Hex64 CounterOffset; + uint32_t NumCounters; + Optional FilePath; + Optional LineNumber; + }; + + friend struct yaml::MappingTraits; + friend struct yaml::SequenceElementTraits; + private: static llvm::Expected> get(std::unique_ptr Buffer); @@ -109,7 +126,10 @@ std::vector> Data; Error correlateProfileData() override; - virtual void correlateProfileDataImpl() = 0; + virtual void correlateProfileDataImpl( + std::vector *Probes = nullptr) = 0; + + Error dumpYaml(raw_ostream &OS) override; void addProbe(StringRef FunctionName, uint64_t CFGHash, IntPtrT CounterOffset, IntPtrT FunctionPtr, uint32_t NumCounters); @@ -171,7 +191,8 @@ /// NULL /// NULL /// \endcode - void correlateProfileDataImpl() override; + void correlateProfileDataImpl( + std::vector *Probes = nullptr) override; }; } // end namespace llvm diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp --- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp +++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp @@ -155,6 +155,35 @@ return Result; } +template <> struct yaml::MappingTraits { + static void mapping(yaml::IO &io, InstrProfCorrelator::Probe &P) { + io.mapRequired("Function Name", P.FunctionName); + io.mapOptional("Linkage Name", P.LinkageName); + io.mapRequired("CFG Hash", P.CFGHash); + io.mapRequired("Counter Offset", P.CounterOffset); + io.mapRequired("Num Counters", P.NumCounters); + io.mapOptional("File", P.FilePath); + io.mapOptional("Line", P.LineNumber); + } +}; + +template <> struct yaml::SequenceElementTraits { + static const bool flow = false; +}; + +template +Error InstrProfCorrelatorImpl::dumpYaml(raw_ostream &OS) { + std::vector Probes; + correlateProfileDataImpl(&Probes); + if (Probes.empty()) + return make_error( + instrprof_error::unable_to_correlate_profile, + "could not find any profile metadata in debug info"); + yaml::Output YamlOS(OS); + YamlOS << Probes; + return Error::success(); +} + template void InstrProfCorrelatorImpl::addProbe(StringRef FunctionName, uint64_t CFGHash, @@ -222,15 +251,16 @@ } template -void DwarfInstrProfCorrelator::correlateProfileDataImpl() { +void DwarfInstrProfCorrelator::correlateProfileDataImpl( + std::vector *Probes) { auto maybeAddProbe = [&](DWARFDie Die) { if (!isDIEOfProbe(Die)) return; Optional FunctionName; Optional CFGHash; Optional CounterPtr = getLocation(Die); - auto FunctionPtr = - dwarf::toAddress(Die.getParent().find(dwarf::DW_AT_low_pc)); + auto FnDie = Die.getParent(); + auto FunctionPtr = dwarf::toAddress(FnDie.find(dwarf::DW_AT_low_pc)); Optional NumCounters; for (const DWARFDie &Child : Die.children()) { if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation) @@ -283,8 +313,26 @@ << "\n"); LLVM_DEBUG(Die.dump(dbgs())); } - this->addProbe(*FunctionName, *CFGHash, *CounterPtr - CountersStart, - FunctionPtr.value_or(0), *NumCounters); + IntPtrT CounterOffset = *CounterPtr - CountersStart; + if (Probes) { + InstrProfCorrelator::Probe P; + P.FunctionName = *FunctionName; + if (auto Name = FnDie.getName(DINameKind::LinkageName)) + P.LinkageName = Name; + P.CFGHash = *CFGHash; + P.CounterOffset = CounterOffset; + P.NumCounters = *NumCounters; + auto FilePath = FnDie.getDeclFile( + DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath); + if (!FilePath.empty()) + P.FilePath = FilePath; + if (auto LineNumber = FnDie.getDeclLine()) + P.LineNumber = LineNumber; + Probes->push_back(P); + } else { + this->addProbe(*FunctionName, *CFGHash, CounterOffset, + FunctionPtr.value_or(0), *NumCounters); + } }; for (auto &CU : DICtx->normal_units()) for (const auto &Entry : CU->dies()) diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -2684,29 +2684,12 @@ } static int showDebugInfoCorrelation(const std::string &Filename, - bool ShowDetailedSummary, - bool ShowProfileSymbolList, raw_fd_ostream &OS) { std::unique_ptr Correlator; if (auto Err = InstrProfCorrelator::get(Filename).moveInto(Correlator)) exitWithError(std::move(Err), Filename); - if (auto Err = Correlator->correlateProfileData()) + if (auto Err = Correlator->dumpYaml(OS)) exitWithError(std::move(Err), Filename); - - InstrProfSymtab Symtab; - if (auto Err = Symtab.create( - StringRef(Correlator->getNamesPointer(), Correlator->getNamesSize()))) - exitWithError(std::move(Err), Filename); - - if (ShowProfileSymbolList) - Symtab.dumpNames(OS); - // TODO: Read "Profile Data Type" from debug info to compute and show how many - // counters the section holds. - if (ShowDetailedSummary) - OS << "Counters section size: 0x" - << Twine::utohexstr(Correlator->getCountersSectionSize()) << " bytes\n"; - OS << "Found " << Correlator->getDataSize() << " functions\n"; - return 0; } @@ -2808,8 +2791,7 @@ WithColor::warning() << "-function argument ignored: showing all functions\n"; if (!DebugInfoFilename.empty()) - return showDebugInfoCorrelation(DebugInfoFilename, ShowDetailedSummary, - ShowProfileSymbolList, OS); + return showDebugInfoCorrelation(DebugInfoFilename, OS); if (ProfileKind == instr) return showInstrProfile(