From 4b102c3d5c4f7232bf915a934eb3dbdd709fb471 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Tue, 1 Aug 2017 21:23:26 +0000 Subject: [PATCH] [llvm-cov] Allow specifying distinct architectures for each loaded binary The coverage tool needs to know which slice to look at when it's handed a universal binary. Some projects need to look at aggregate coverage reports for a variety of slices in different binaries: this patch adds support for these kinds of projects to llvm-cov. rdar://problem/33579007 llvm-svn: 309747 --- llvm/docs/CommandGuide/llvm-cov.rst | 11 ++++---- .../ProfileData/Coverage/CoverageMapping.h | 6 +++-- .../ProfileData/Coverage/CoverageMapping.cpp | 7 +++--- llvm/test/tools/llvm-cov/universal-binary.c | 9 +++++++ llvm/tools/llvm-cov/CodeCoverage.cpp | 25 ++++++++++++------- 5 files changed, 39 insertions(+), 19 deletions(-) diff --git a/llvm/docs/CommandGuide/llvm-cov.rst b/llvm/docs/CommandGuide/llvm-cov.rst index 47db8d04e0b2..3732b39740ff 100644 --- a/llvm/docs/CommandGuide/llvm-cov.rst +++ b/llvm/docs/CommandGuide/llvm-cov.rst @@ -222,12 +222,13 @@ OPTIONS Enable or disable color output. By default this is autodetected. -.. option:: -arch= +.. option:: -arch=[*NAMES*] - If the covered binary is a universal binary, select the architecture to use. - It is an error to specify an architecture that is not included in the - universal binary or to use an architecture that does not match a - non-universal binary. + Specify a list of architectures such that the Nth entry in the list + corresponds to the Nth specified binary. If the covered object is a universal + binary, this specifies the architecture to use. It is an error to specify an + architecture that is not included in the universal binary or to use an + architecture that does not match a non-universal binary. .. option:: -name= diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h index fa9a87aed680..980d47e7afe4 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -449,14 +449,16 @@ public: CoverageMapping(const CoverageMapping &) = delete; CoverageMapping &operator=(const CoverageMapping &) = delete; - /// \brief Load the coverage mapping using the given readers. + /// Load the coverage mapping using the given readers. static Expected> load(ArrayRef> CoverageReaders, IndexedInstrProfReader &ProfileReader); + /// Load the coverage mapping from the given object files and profile. If + /// \p Arches is non-empty, it must specify an architecture for each object. static Expected> load(ArrayRef ObjectFilenames, StringRef ProfileFilename, - StringRef Arch = StringRef()); + ArrayRef Arches = None); /// \brief The number of functions that couldn't have their profiles mapped. /// diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 8c5f136ea270..c435cb6ac849 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -260,7 +260,7 @@ Expected> CoverageMapping::load( Expected> CoverageMapping::load(ArrayRef ObjectFilenames, - StringRef ProfileFilename, StringRef Arch) { + StringRef ProfileFilename, ArrayRef Arches) { auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename); if (Error E = ProfileReaderOrErr.takeError()) return std::move(E); @@ -268,10 +268,11 @@ CoverageMapping::load(ArrayRef ObjectFilenames, SmallVector, 4> Readers; SmallVector, 4> Buffers; - for (StringRef ObjectFilename : ObjectFilenames) { - auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(ObjectFilename); + for (const auto &File : llvm::enumerate(ObjectFilenames)) { + auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(File.value()); if (std::error_code EC = CovMappingBufOrErr.getError()) return errorCodeToError(EC); + StringRef Arch = Arches.empty() ? StringRef() : Arches[File.index()]; auto CoverageReaderOrErr = BinaryCoverageReader::create(CovMappingBufOrErr.get(), Arch); if (Error E = CoverageReaderOrErr.takeError()) diff --git a/llvm/test/tools/llvm-cov/universal-binary.c b/llvm/test/tools/llvm-cov/universal-binary.c index 1b15f98cb76b..00f3e87b6014 100644 --- a/llvm/test/tools/llvm-cov/universal-binary.c +++ b/llvm/test/tools/llvm-cov/universal-binary.c @@ -7,9 +7,18 @@ int main(int argc, const char *argv[]) {} // RUN: llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -filename-equivalence %s -arch x86_64 | FileCheck %s // RUN: llvm-cov export %S/Inputs/universal-binary -instr-profile %t.profdata -arch x86_64 2>&1 | FileCheck %S/Inputs/universal-binary.json +// RUN: llvm-cov report %S/Inputs/universal-binary -arch x86_64 -object %S/Inputs/templateInstantiations.covmapping -arch i386 -instr-profile %t.profdata 2>&1 | FileCheck %s --check-prefix=COMBINED +// COMBINED: showTemplateInstantiations.cpp +// COMBINED-NEXT: universal-binary.c // RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -filename-equivalence %s -arch i386 2>&1 | FileCheck --check-prefix=WRONG-ARCH %s // WRONG-ARCH: Failed to load coverage +// RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -filename-equivalence %s -arch definitly_a_made_up_architecture 2>&1 | FileCheck --check-prefix=MADE-UP-ARCH %s +// MADE-UP-ARCH: Unknown architecture: definitly_a_made_up_architecture + +// RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -filename-equivalence %s -arch=x86_64 -arch=x86_64 2>&1 | FileCheck --check-prefix=TOO-MANY-ARCH %s +// TOO-MANY-ARCH: Number of architectures doesn't match the number of objects +// // RUN: not llvm-cov report -instr-profile %t.profdata 2>&1 | FileCheck --check-prefix=MISSING-BINARY %s // MISSING-BINARY: No filenames specified! diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp index 3cbd6591134b..073bd83e7af3 100644 --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -133,7 +133,7 @@ private: StringMap RemappedFilenames; /// The architecture the coverage mapping data targets. - std::string CoverageArch; + std::vector CoverageArches; /// A cache for demangled symbols. DemangleCache DC; @@ -329,7 +329,7 @@ std::unique_ptr CodeCoverageTool::load() { warning("profile data may be out of date - object is newer", ObjectFilename); auto CoverageOrErr = - CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArch); + CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArches); if (Error E = CoverageOrErr.takeError()) { error("Failed to load coverage: " + toString(std::move(E)), join(ObjectFilenames.begin(), ObjectFilenames.end(), ", ")); @@ -499,8 +499,8 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { cl::desc( "File with the profile data obtained after an instrumented run")); - cl::opt Arch( - "arch", cl::desc("architecture of the coverage mapping binary")); + cl::list Arches( + "arch", cl::desc("architectures of the coverage mapping binaries")); cl::opt DebugDump("dump", cl::Optional, cl::desc("Show internal debug dump")); @@ -632,12 +632,19 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { Filters.push_back(std::unique_ptr(StatFilterer)); } - if (!Arch.empty() && - Triple(Arch).getArch() == llvm::Triple::ArchType::UnknownArch) { - error("Unknown architecture: " + Arch); - return 1; + if (!Arches.empty()) { + for (const std::string &Arch : Arches) { + if (Triple(Arch).getArch() == llvm::Triple::ArchType::UnknownArch) { + error("Unknown architecture: " + Arch); + return 1; + } + CoverageArches.emplace_back(Arch); + } + if (CoverageArches.size() != ObjectFilenames.size()) { + error("Number of architectures doesn't match the number of objects"); + return 1; + } } - CoverageArch = Arch; for (const std::string &File : InputSourceFiles) collectPaths(File);