diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 05fb137ca0575..7cb44c9ddb212 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -2604,6 +2604,15 @@ void CoverageMappingModuleGen::emit() { }; auto CovDataHeaderTy = llvm::StructType::get(Ctx, ArrayRef(CovDataHeaderTypes)); + + // By default, clang instruments the code for "region" and "branch" + // coverage, and can instrument for MCDC when `-fcoverage-mcdc` is passed. + uint32_t CovInstrLevels = CoverageCapabilities::CovInstrLevel::Region | + CoverageCapabilities::CovInstrLevel::Branch; + if (CGM.getCodeGenOpts().hasProfileClangInstr() && + CGM.getCodeGenOpts().MCDCCoverage) + CovInstrLevels |= CoverageCapabilities::CovInstrLevel::MCDC; + llvm::Constant *CovDataHeaderVals[] = { #define COVMAP_HEADER(Type, LLVMType, Name, Init) Init, #include "llvm/ProfileData/InstrProfData.inc" diff --git a/clang/test/CoverageMapping/ir.c b/clang/test/CoverageMapping/ir.c index b08734cc35113..9f5111afef695 100644 --- a/clang/test/CoverageMapping/ir.c +++ b/clang/test/CoverageMapping/ir.c @@ -17,12 +17,12 @@ int main(void) { // DARWIN: [[FuncRecord1:@__covrec_[0-9A-F]+u]] = linkonce_odr hidden constant <{ i64, i32, i64, i64, [{{.*}} x i8] }> <{ {{.*}} }>, section "__LLVM_COV,__llvm_covfun", align 8 // DARWIN: [[FuncRecord2:@__covrec_[0-9A-F]+u]] = linkonce_odr hidden constant <{ i64, i32, i64, i64, [{{.*}} x i8] }> <{ {{.*}} }>, section "__LLVM_COV,__llvm_covfun", align 8 // DARWIN: [[FuncRecord3:@__covrec_[0-9A-F]+]] = linkonce_odr hidden constant <{ i64, i32, i64, i64, [{{.*}} x i8] }> <{ {{.*}} }>, section "__LLVM_COV,__llvm_covfun", align 8 -// DARWIN: @__llvm_coverage_mapping = private constant { { i32, i32, i32, i32 }, [{{.*}} x i8] } { {{.*}} }, section "__LLVM_COV,__llvm_covmap", align 8 +// DARWIN: @__llvm_coverage_mapping = private constant { { i32, i32, i32, i32, i32 }, [{{.*}} x i8] } { {{.*}} }, section "__LLVM_COV,__llvm_covmap", align 8 // WINDOWS: [[FuncRecord1:@__covrec_[0-9A-F]+u]] = linkonce_odr hidden constant <{ i64, i32, i64, i64, [{{.*}} x i8] }> <{ {{.*}} }>, section ".lcovfun$M", comdat, align 8 // WINDOWS: [[FuncRecord2:@__covrec_[0-9A-F]+u]] = linkonce_odr hidden constant <{ i64, i32, i64, i64, [{{.*}} x i8] }> <{ {{.*}} }>, section ".lcovfun$M", comdat, align 8 // WINDOWS: [[FuncRecord3:@__covrec_[0-9A-F]+]] = linkonce_odr hidden constant <{ i64, i32, i64, i64, [{{.*}} x i8] }> <{ {{.*}} }>, section ".lcovfun$M", comdat, align 8 -// WINDOWS: @__llvm_coverage_mapping = private constant { { i32, i32, i32, i32 }, [{{.*}} x i8] } { {{.*}} }, section ".lcovmap$M", align 8 +// WINDOWS: @__llvm_coverage_mapping = private constant { { i32, i32, i32, i32, i32 }, [{{.*}} x i8] } { {{.*}} }, section ".lcovmap$M", align 8 // COMMON: @llvm.used = appending global [{{.*}}] [ // COMMON-SAME: [[FuncRecord1]] diff --git a/clang/test/Profile/def-assignop.cpp b/clang/test/Profile/def-assignop.cpp index d17654f31428b..332ea9f1046e9 100644 --- a/clang/test/Profile/def-assignop.cpp +++ b/clang/test/Profile/def-assignop.cpp @@ -23,7 +23,7 @@ struct A { // COVMAP: section "__llvm_covfun", comdat // COVMAP: section "__llvm_covfun", comdat // COVMAP: section "__llvm_covfun", comdat - // COVMAP: @__llvm_coverage_mapping = {{.*}} { { i32, i32, i32, i32 } + // COVMAP: @__llvm_coverage_mapping = {{.*}} { { i32, i32, i32, i32, i32 } B b; }; diff --git a/clang/test/Profile/def-ctors.cpp b/clang/test/Profile/def-ctors.cpp index 0179bc92dbb86..8457c13fe2f9e 100644 --- a/clang/test/Profile/def-ctors.cpp +++ b/clang/test/Profile/def-ctors.cpp @@ -28,7 +28,7 @@ struct Derived : public Base { // COVMAP: section "__llvm_covfun", comdat // COVMAP: section "__llvm_covfun", comdat // COVMAP: section "__llvm_covfun", comdat - // COVMAP: @__llvm_coverage_mapping = {{.*}} { { i32, i32, i32, i32 } + // COVMAP: @__llvm_coverage_mapping = {{.*}} { { i32, i32, i32, i32, i32 } }; Derived dd; diff --git a/clang/test/Profile/def-dtors.cpp b/clang/test/Profile/def-dtors.cpp index dc87508fe7c28..a4d6a38e9e422 100644 --- a/clang/test/Profile/def-dtors.cpp +++ b/clang/test/Profile/def-dtors.cpp @@ -23,7 +23,7 @@ struct Derived : public Base { // COVMAP: section "__llvm_covfun", comdat // COVMAP: section "__llvm_covfun", comdat // COVMAP: section "__llvm_covfun", comdat - // COVMAP: @__llvm_coverage_mapping = {{.*}} { { i32, i32, i32, i32 } + // COVMAP: @__llvm_coverage_mapping = {{.*}} { { i32, i32, i32, i32, i32 } }; int main() { diff --git a/compiler-rt/include/profile/InstrProfData.inc b/compiler-rt/include/profile/InstrProfData.inc index 0496f240dc823..a2af7cfa8cbe1 100644 --- a/compiler-rt/include/profile/InstrProfData.inc +++ b/compiler-rt/include/profile/InstrProfData.inc @@ -300,6 +300,8 @@ COVMAP_HEADER(uint32_t, Int32Ty, CoverageSize, \ llvm::ConstantInt::get(Int32Ty, CoverageMappingSize)) COVMAP_HEADER(uint32_t, Int32Ty, Version, \ llvm::ConstantInt::get(Int32Ty, CovMapVersion::CurrentVersion)) +COVMAP_HEADER(uint32_t, Int32Ty, CovInstrLevels, \ + llvm::ConstantInt::get(Int32Ty, CovInstrLevels)) #undef COVMAP_HEADER /* COVMAP_HEADER end. */ @@ -724,7 +726,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, /* Indexed profile format version (start from 1). */ #define INSTR_PROF_INDEX_VERSION 12 /* Coverage mapping format version (start from 0). */ -#define INSTR_PROF_COVMAP_VERSION 6 +#define INSTR_PROF_COVMAP_VERSION 7 /* Profile version is always of type uint64_t. Reserve the upper 32 bits in the * version for other variants of profile. We set the 8th most significant bit diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h index 7d1a85ba528fc..c6d8125ac6037 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -984,6 +984,52 @@ class CoverageData { ArrayRef getMCDCRecords() const { return MCDCRecords; } }; +/// Represents a set of available capabilities +class CoverageCapabilities { + uint32_t Capabilities; + +public: + enum CovInstrLevel { + Region = (1 << 0), + Branch = (1 << 1), + MCDC = (1 << 2), + }; + + CoverageCapabilities(uint32_t Capabilities) : Capabilities(Capabilities){}; + + static CoverageCapabilities all() { + return CoverageCapabilities(Region | Branch | MCDC); + } + + static CoverageCapabilities none() { + return CoverageCapabilities(0); + } + + bool hasCapability(CovInstrLevel Lvl) const { + return (this->Capabilities & Lvl) != 0; + } + + /// Returns true if this includes all the capabilities of Other. + bool includes(const CoverageCapabilities &Other) const { + return (this->Capabilities & Other.Capabilities) == Other.Capabilities; + } + + std::string toString() const { + std::stringstream SS; + SS << std::oct << this->Capabilities; + return SS.str(); + } + + CoverageCapabilities& operator |= (const CoverageCapabilities &Rhs) { + this->Capabilities |= Rhs.Capabilities; + return *this; + } + + CoverageCapabilities operator | (const CoverageCapabilities &Rhs) const { + return CoverageCapabilities(this->Capabilities | Rhs.Capabilities); + } +}; + /// The mapping of profile information to coverage data. /// /// This is the main interface to get coverage information, using a profile to @@ -994,6 +1040,10 @@ class CoverageMapping { DenseMap> FilenameHash2RecordIndices; std::vector> FuncHashMismatches; + /// Keep track of the coverage capabilities of the loaded object file, + /// which depends on the parameters used to compile it. + CoverageCapabilities AvailableInstrLevels = CoverageCapabilities::none(); + std::optional SingleByteCoverage; CoverageMapping() = default; @@ -1011,6 +1061,7 @@ class CoverageMapping { std::optional> &ProfileReader, CoverageMapping &Coverage, bool &DataFound, + CoverageCapabilities RequestedCapabilities, SmallVectorImpl *FoundBinaryIDs = nullptr); /// Add a function record corresponding to \p Record. @@ -1034,7 +1085,8 @@ class CoverageMapping { LLVM_ABI static Expected> load(ArrayRef> CoverageReaders, std::optional> - &ProfileReader); + &ProfileReader, + CoverageCapabilities RequestCapabilities = CoverageCapabilities::none()); /// 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. @@ -1044,7 +1096,8 @@ class CoverageMapping { std::optional ProfileFilename, vfs::FileSystem &FS, ArrayRef Arches = {}, StringRef CompilationDir = "", const object::BuildIDFetcher *BIDFetcher = nullptr, - bool CheckBinaryIDs = false); + bool CheckBinaryIDs = false, + CoverageCapabilities RequestCapabilities = CoverageCapabilities::none()); /// The number of functions that couldn't have their profiles mapped. /// @@ -1430,6 +1483,10 @@ struct CovMapHeader { template uint32_t getVersion() const { return support::endian::byte_swap(Version); } + + template uint32_t getCovInstrLevels() const { + return support::endian::byte_swap(CovInstrLevels); + } }; LLVM_PACKED_END @@ -1452,6 +1509,8 @@ enum CovMapVersion { Version6 = 5, // Branch regions extended and Decision Regions added for MC/DC. Version7 = 6, + // Covmap header tracks the instrumentation level + Version8 = 7, // The current version is Version7. CurrentVersion = INSTR_PROF_COVMAP_VERSION }; diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h index e91ba9147a745..b6e68bf13c10d 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h @@ -104,6 +104,10 @@ class CoverageMappingReader { virtual Error readNextRecord(CoverageMappingRecord &Record) = 0; CoverageMappingIterator begin() { return CoverageMappingIterator(this); } CoverageMappingIterator end() { return CoverageMappingIterator(); } + + /// Returns the instrumentation levels for which the code was originally + /// instrumented. + virtual CoverageCapabilities coverageCapabilities() const = 0; }; /// Base class for the raw coverage mapping and filenames data readers. @@ -188,6 +192,7 @@ class LLVM_ABI BinaryCoverageReader : public CoverageMappingReader { std::vector MappingRecords; std::unique_ptr ProfileNames; size_t CurrentRecord = 0; + CoverageCapabilities AvailableCapabilities; std::vector FunctionsFilenames; std::vector Expressions; std::vector MappingRegions; @@ -205,7 +210,9 @@ class LLVM_ABI BinaryCoverageReader : public CoverageMappingReader { BinaryCoverageReader(std::unique_ptr Symtab, FuncRecordsStorage &&FuncRecords, CoverageMapCopyStorage &&CoverageMapCopy) - : ProfileNames(std::move(Symtab)), FuncRecords(std::move(FuncRecords)), + : ProfileNames(std::move(Symtab)), + AvailableCapabilities(CoverageCapabilities::all()), + FuncRecords(std::move(FuncRecords)), CoverageMapCopy(std::move(CoverageMapCopy)) {} public: @@ -226,6 +233,10 @@ class LLVM_ABI BinaryCoverageReader : public CoverageMappingReader { llvm::endianness Endian, StringRef CompilationDir = ""); Error readNextRecord(CoverageMappingRecord &Record) override; + + CoverageCapabilities coverageCapabilities() const override { + return this->AvailableCapabilities; + }; }; /// Reader for the raw coverage filenames. diff --git a/llvm/include/llvm/ProfileData/InstrProfData.inc b/llvm/include/llvm/ProfileData/InstrProfData.inc index 0496f240dc823..a2af7cfa8cbe1 100644 --- a/llvm/include/llvm/ProfileData/InstrProfData.inc +++ b/llvm/include/llvm/ProfileData/InstrProfData.inc @@ -300,6 +300,8 @@ COVMAP_HEADER(uint32_t, Int32Ty, CoverageSize, \ llvm::ConstantInt::get(Int32Ty, CoverageMappingSize)) COVMAP_HEADER(uint32_t, Int32Ty, Version, \ llvm::ConstantInt::get(Int32Ty, CovMapVersion::CurrentVersion)) +COVMAP_HEADER(uint32_t, Int32Ty, CovInstrLevels, \ + llvm::ConstantInt::get(Int32Ty, CovInstrLevels)) #undef COVMAP_HEADER /* COVMAP_HEADER end. */ @@ -724,7 +726,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, /* Indexed profile format version (start from 1). */ #define INSTR_PROF_INDEX_VERSION 12 /* Coverage mapping format version (start from 0). */ -#define INSTR_PROF_COVMAP_VERSION 6 +#define INSTR_PROF_COVMAP_VERSION 7 /* Profile version is always of type uint64_t. Reserve the upper 32 bits in the * version for other variants of profile. We set the 8th most significant bit diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 429ec5c19f1f8..a7e8fb8030c04 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -978,6 +978,7 @@ Error CoverageMapping::loadFromReaders( Coverage.SingleByteCoverage = !ProfileReader || ProfileReader.value().get().hasSingleByteCoverage(); for (const auto &CoverageReader : CoverageReaders) { + Coverage.AvailableInstrLevels |= CoverageReader->coverageCapabilities(); for (auto RecordOrErr : *CoverageReader) { if (Error E = RecordOrErr.takeError()) return E; @@ -992,7 +993,7 @@ Error CoverageMapping::loadFromReaders( Expected> CoverageMapping::load( ArrayRef> CoverageReaders, std::optional> - &ProfileReader) { + &ProfileReader, CoverageCapabilities RequestedCapabilities) { auto Coverage = std::unique_ptr(new CoverageMapping()); if (Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage)) return std::move(E); @@ -1013,6 +1014,7 @@ Error CoverageMapping::loadFromFile( std::optional> &ProfileReader, CoverageMapping &Coverage, bool &DataFound, + CoverageCapabilities RequestedCapabilities, SmallVectorImpl *FoundBinaryIDs) { auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN( Filename, /*IsText=*/false, /*RequiresNullTerminator=*/false); @@ -1045,6 +1047,16 @@ Error CoverageMapping::loadFromFile( DataFound |= !Readers.empty(); if (Error E = loadFromReaders(Readers, ProfileReader, Coverage)) return createFileError(Filename, std::move(E)); + + // Check that the requested coverage capabilities are available. + if (!Coverage.AvailableInstrLevels.includes(RequestedCapabilities)) + return createFileError( + Filename, createStringError( + "lacking coverage capabilities (requested %s, got %s)", + RequestedCapabilities.toString().c_str(), + Coverage.AvailableInstrLevels.toString().c_str() + )); + return Error::success(); } @@ -1052,7 +1064,8 @@ Expected> CoverageMapping::load( ArrayRef ObjectFilenames, std::optional ProfileFilename, vfs::FileSystem &FS, ArrayRef Arches, StringRef CompilationDir, - const object::BuildIDFetcher *BIDFetcher, bool CheckBinaryIDs) { + const object::BuildIDFetcher *BIDFetcher, bool CheckBinaryIDs, + CoverageCapabilities RequestedCapabilities) { std::unique_ptr ProfileReader; if (ProfileFilename) { auto ProfileReaderOrErr = @@ -1081,7 +1094,8 @@ Expected> CoverageMapping::load( for (const auto &File : llvm::enumerate(ObjectFilenames)) { if (Error E = loadFromFile(File.value(), GetArch(File.index()), CompilationDir, ProfileReaderRef, *Coverage, - DataFound, &FoundBinaryIDs)) + DataFound, RequestedCapabilities, + &FoundBinaryIDs)) return std::move(E); } @@ -1110,7 +1124,8 @@ Expected> CoverageMapping::load( std::string Path = std::move(*PathOpt); StringRef Arch = Arches.size() == 1 ? Arches.front() : StringRef(); if (Error E = loadFromFile(Path, Arch, CompilationDir, ProfileReaderRef, - *Coverage, DataFound)) + *Coverage, DataFound, + RequestedCapabilities)) return std::move(E); } else if (CheckBinaryIDs) { return createFileError( diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index fc2577e6ada5d..8ae7a26bc1b50 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -670,7 +670,13 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { const char *CovBufEnd) override { using namespace support; - if (CovBuf + sizeof(CovMapHeader) > CovBufEnd) + // In versions before Version8, the Covmap header only has 4 uint32_t + // fields. + uint32_t HeaderSize = (Version >= CovMapVersion::Version8) + ? sizeof(CovMapHeader) + : 4 * sizeof(uint32_t); + + if (CovBuf + HeaderSize > CovBufEnd) return make_error( coveragemap_error::malformed, "coverage mapping header section is larger than buffer size"); @@ -679,7 +685,8 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { uint32_t FilenamesSize = CovHeader->getFilenamesSize(); uint32_t CoverageSize = CovHeader->getCoverageSize(); assert((CovMapVersion)CovHeader->getVersion() == Version); - CovBuf = reinterpret_cast(CovHeader + 1); + + CovBuf = reinterpret_cast(CovHeader) + HeaderSize; // Skip past the function records, saving the start and end for later. // This is a no-op in Version4 (function records are read after all headers @@ -830,6 +837,7 @@ Expected> CovMapFuncRecordReader::get( case CovMapVersion::Version5: case CovMapVersion::Version6: case CovMapVersion::Version7: + case CovMapVersion::Version8: // Decompress the name data. if (Error E = P.create(P.getNameData())) return std::move(E); @@ -851,6 +859,9 @@ Expected> CovMapFuncRecordReader::get( else if (Version == CovMapVersion::Version7) return std::make_unique>(P, R, D, F); + else if (Version == CovMapVersion::Version8) + return std::make_unique>(P, R, D, F); } llvm_unreachable("Unsupported version"); } @@ -859,7 +870,8 @@ template static Error readCoverageMappingData( InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords, std::vector &Records, - StringRef CompilationDir, std::vector &Filenames) { + StringRef CompilationDir, std::vector &Filenames, + CoverageCapabilities &AvailableCapabilities) { using namespace coverage; // Read the records in the coverage data section. @@ -871,6 +883,14 @@ static Error readCoverageMappingData( Expected> ReaderExpected = CovMapFuncRecordReader::get(Version, ProfileNames, Records, CompilationDir, Filenames); + + // Assume coverage files before Version8 have all coverage capabilities, as + // the field didn't exist before. + if (Version < CovMapVersion::Version8) + AvailableCapabilities = CoverageCapabilities::all(); + else + AvailableCapabilities = CoverageCapabilities(CovHeader->getCovInstrLevels()); + if (Error E = ReaderExpected.takeError()) return E; auto Reader = std::move(ReaderExpected.get()); @@ -915,22 +935,22 @@ BinaryCoverageReader::createCoverageReaderFromBuffer( if (BytesInAddress == 4 && Endian == llvm::endianness::little) { if (Error E = readCoverageMappingData( ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, - CompilationDir, Reader->Filenames)) + CompilationDir, Reader->Filenames, Reader->AvailableCapabilities)) return std::move(E); } else if (BytesInAddress == 4 && Endian == llvm::endianness::big) { if (Error E = readCoverageMappingData( ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, - CompilationDir, Reader->Filenames)) + CompilationDir, Reader->Filenames, Reader->AvailableCapabilities)) return std::move(E); } else if (BytesInAddress == 8 && Endian == llvm::endianness::little) { if (Error E = readCoverageMappingData( ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, - CompilationDir, Reader->Filenames)) + CompilationDir, Reader->Filenames, Reader->AvailableCapabilities)) return std::move(E); } else if (BytesInAddress == 8 && Endian == llvm::endianness::big) { if (Error E = readCoverageMappingData( ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, - CompilationDir, Reader->Filenames)) + CompilationDir, Reader->Filenames, Reader->AvailableCapabilities)) return std::move(E); } else return make_error( @@ -1003,15 +1023,28 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { return make_error(coveragemap_error::malformed, "insufficient padding"); Data = Data.substr(Pad); - if (Data.size() < sizeof(CovMapHeader)) + + // In Version8, CovMapHeader passed from 4 to 5 uint32 fields, + // So we only check the first 4 fields to get the version. + if (Data.size() < 4 * sizeof(uint32_t)) return make_error( coveragemap_error::malformed, "coverage mapping header section is larger than data size"); + auto const *CovHeader = reinterpret_cast( Data.substr(0, sizeof(CovMapHeader)).data()); auto Version = CovMapVersion(CovHeader->getVersion()); + uint16_t CovHeaderSize = (Version >= CovMapVersion::Version8) + ? sizeof(CovMapHeader) + : 4 * sizeof(uint32_t); + + if (Data.size() < CovHeaderSize) + return make_error( + coveragemap_error::malformed, + "coverage mapping header section is larger than data size"); + // In Version1, the size of CoverageMapping is calculated. if (TestingVersion == uint64_t(TestingFormatVersion::Version1)) { if (Version < CovMapVersion::Version4) { @@ -1019,7 +1052,7 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { } else { auto FilenamesSize = CovHeader->getFilenamesSize(); - CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize; + CoverageMappingSize = CovHeaderSize + FilenamesSize; } } diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp index 6c66858c4de8c..fb0bce7103ee5 100644 --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -462,9 +462,18 @@ std::unique_ptr CodeCoverageTool::load() { ObjectFilename); } auto FS = vfs::getRealFileSystem(); - auto CoverageOrErr = CoverageMapping::load( - ObjectFilenames, PGOFilename, *FS, CoverageArches, - ViewOpts.CompilationDirectory, BIDFetcher.get(), CheckBinaryIDs); + + CoverageCapabilities RequestCapabilities = + CoverageCapabilities(CoverageCapabilities::CovInstrLevel::Region); + if (ViewOpts.ShowBranches != CoverageViewOptions::BranchOutputType::Off) + RequestCapabilities |= CoverageCapabilities::CovInstrLevel::Branch; + if (ViewOpts.ShowMCDC || ViewOpts.ShowMCDCSummary) + RequestCapabilities |= CoverageCapabilities::CovInstrLevel::MCDC; + + auto CoverageOrErr = + CoverageMapping::load(ObjectFilenames, PGOFilename, *FS, CoverageArches, + ViewOpts.CompilationDirectory, BIDFetcher.get(), + CheckBinaryIDs, RequestCapabilities); if (Error E = CoverageOrErr.takeError()) { error("failed to load coverage: " + toString(std::move(E))); return nullptr; diff --git a/llvm/tools/llvm-cov/CoverageViewOptions.h b/llvm/tools/llvm-cov/CoverageViewOptions.h index 1f6ad570f86f2..46169ac9a0cfd 100644 --- a/llvm/tools/llvm-cov/CoverageViewOptions.h +++ b/llvm/tools/llvm-cov/CoverageViewOptions.h @@ -30,7 +30,7 @@ struct CoverageViewOptions { bool ShowLineNumbers; bool ShowLineStats; bool ShowRegionMarkers; - bool ShowMCDC; + bool ShowMCDC = false; bool ShowBranchCounts; bool ShowBranchPercents; bool ShowExpandedRegions; @@ -38,7 +38,7 @@ struct CoverageViewOptions { bool UnifyFunctionInstantiations; bool ShowFullFilenames; bool ShowBranchSummary; - bool ShowMCDCSummary; + bool ShowMCDCSummary = false; bool ShowRegionSummary; bool ShowInstantiationSummary; bool ShowDirectoryCoverage; diff --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/llvm/unittests/ProfileData/CoverageMappingTest.cpp index b268aa7cdd057..0eee49381cd3f 100644 --- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp +++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp @@ -106,6 +106,11 @@ struct CoverageMappingReaderMock : CoverageMappingReader { return Error::success(); } + + CoverageCapabilities coverageCapabilities() const override { + // TODO: Handle coverage capabilities in tests. + return CoverageCapabilities::all(); + } }; struct InputFunctionCoverageData {