diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h index 15445b59963..617afd4df28 100644 --- a/include/llvm/ProfileData/CoverageMapping.h +++ b/include/llvm/ProfileData/CoverageMapping.h @@ -228,9 +228,13 @@ struct FunctionRecord { std::vector Filenames; /// \brief Regions in the function along with their counts. std::vector CountedRegions; + /// \brief The number of times this function was executed. + uint64_t ExecutionCount; - FunctionRecord(StringRef Name, ArrayRef Filenames) - : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} + FunctionRecord(StringRef Name, ArrayRef Filenames, + uint64_t ExecutionCount) + : Name(Name), Filenames(Filenames.begin(), Filenames.end()), + ExecutionCount(ExecutionCount) {} }; /// \brief Coverage information for a macro expansion or #included file. diff --git a/lib/ProfileData/CoverageMapping.cpp b/lib/ProfileData/CoverageMapping.cpp index 06a950c2e40..115256358ed 100644 --- a/lib/ProfileData/CoverageMapping.cpp +++ b/lib/ProfileData/CoverageMapping.cpp @@ -167,7 +167,9 @@ CoverageMapping::load(ObjectFileCoverageMappingReader &CoverageReader, continue; } - FunctionRecord Function(Record.FunctionName, Record.Filenames); + assert(Counts.size() != 0 && "Function's counts are empty"); + FunctionRecord Function(Record.FunctionName, Record.Filenames, + Counts.front()); CounterMappingContext Ctx(Record.Expressions, Counts); for (const auto &Region : Record.MappingRegions) { ErrorOr ExecutionCount = Ctx.evaluate(Region.Count); diff --git a/test/tools/llvm-cov/Inputs/report.covmapping b/test/tools/llvm-cov/Inputs/report.covmapping new file mode 100644 index 00000000000..32d84bc7273 Binary files /dev/null and b/test/tools/llvm-cov/Inputs/report.covmapping differ diff --git a/test/tools/llvm-cov/Inputs/report.profdata b/test/tools/llvm-cov/Inputs/report.profdata new file mode 100644 index 00000000000..aa47be05afa Binary files /dev/null and b/test/tools/llvm-cov/Inputs/report.profdata differ diff --git a/test/tools/llvm-cov/report.cpp b/test/tools/llvm-cov/report.cpp new file mode 100644 index 00000000000..297322a775d --- /dev/null +++ b/test/tools/llvm-cov/report.cpp @@ -0,0 +1,24 @@ +// RUN: llvm-cov report %S/Inputs/report.covmapping -instr-profile %S/Inputs/report.profdata -no-colors 2>&1 | FileCheck %s + +// CHECK: Filename Regions Miss Cover Functions Executed +// CHECK: TOTAL 5 2 60.00% 4 75.00% + +void foo(bool cond) { + if (cond) { + } +} + +void bar() { +} + +void func() { +} + +int main() { + foo(false); + bar(); + return 0; +} + +// llvm-cov doesn't work on big endian yet +// XFAIL: powerpc64-, s390x, mips-, mips64-, sparc diff --git a/tools/llvm-cov/CoverageReport.cpp b/tools/llvm-cov/CoverageReport.cpp index 2efa8e00798..94071b7367e 100644 --- a/tools/llvm-cov/CoverageReport.cpp +++ b/tools/llvm-cov/CoverageReport.cpp @@ -85,7 +85,7 @@ static Column column(StringRef Str, unsigned Width, const T &Value) { return Column(Str, Width).set(Value); } -static const unsigned FileReportColumns[] = {25, 10, 8, 8, 10, 8}; +static const unsigned FileReportColumns[] = {25, 10, 8, 8, 10, 10}; static const unsigned FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8}; /// \brief Prints a horizontal divider which spans across the given columns. @@ -178,8 +178,8 @@ void CoverageReport::renderFunctionReports(raw_ostream &OS) { render(Function, OS); renderDivider(FunctionReportColumns, OS); OS << "\n"; - render(FunctionCoverageSummary("TOTAL", File.RegionCoverage, - File.LineCoverage), + render(FunctionCoverageSummary("TOTAL", /*ExecutionCount=*/0, + File.RegionCoverage, File.LineCoverage), OS); } } @@ -190,7 +190,8 @@ void CoverageReport::renderFileReports(raw_ostream &OS) { << column("Miss", FileReportColumns[2], Column::RightAlignment) << column("Cover", FileReportColumns[3], Column::RightAlignment) << column("Functions", FileReportColumns[4], Column::RightAlignment) - << column("Cover", FileReportColumns[5], Column::RightAlignment) << "\n"; + << column("Executed", FileReportColumns[5], Column::RightAlignment) + << "\n"; renderDivider(FileReportColumns, OS); OS << "\n"; for (const auto &File : Summary.getFileSummaries()) diff --git a/tools/llvm-cov/CoverageSummary.cpp b/tools/llvm-cov/CoverageSummary.cpp index 8df3bebbacf..785e9024ba7 100644 --- a/tools/llvm-cov/CoverageSummary.cpp +++ b/tools/llvm-cov/CoverageSummary.cpp @@ -72,7 +72,7 @@ CoverageSummary::createSummaries(ArrayRef Functions) { FileCoverageSummary CoverageSummary::getCombinedFileSummaries() { size_t NumRegions = 0, CoveredRegions = 0; size_t NumLines = 0, NonCodeLines = 0, CoveredLines = 0; - size_t NumFunctionsCovered = 0, NumFunctions = 0; + size_t NumFunctionsExecuted = 0, NumFunctions = 0; for (const auto &File : FileSummaries) { NumRegions += File.RegionCoverage.NumRegions; CoveredRegions += File.RegionCoverage.Covered; @@ -81,12 +81,12 @@ FileCoverageSummary CoverageSummary::getCombinedFileSummaries() { NonCodeLines += File.LineCoverage.NonCodeLines; CoveredLines += File.LineCoverage.Covered; - NumFunctionsCovered += File.FunctionCoverage.FullyCovered; + NumFunctionsExecuted += File.FunctionCoverage.Executed; NumFunctions += File.FunctionCoverage.NumFunctions; } return FileCoverageSummary( "TOTAL", RegionCoverageInfo(CoveredRegions, NumRegions), LineCoverageInfo(CoveredLines, NonCodeLines, NumLines), - FunctionCoverageInfo(NumFunctionsCovered, NumFunctions), + FunctionCoverageInfo(NumFunctionsExecuted, NumFunctions), None); } diff --git a/tools/llvm-cov/CoverageSummaryInfo.cpp b/tools/llvm-cov/CoverageSummaryInfo.cpp index 334bc73e0d9..dd78ace8605 100644 --- a/tools/llvm-cov/CoverageSummaryInfo.cpp +++ b/tools/llvm-cov/CoverageSummaryInfo.cpp @@ -65,7 +65,8 @@ FunctionCoverageSummary::get(const coverage::FunctionRecord &Function) { NumLines += LineCount; } return FunctionCoverageSummary( - Function.Name, RegionCoverageInfo(CoveredRegions, NumCodeRegions), + Function.Name, Function.ExecutionCount, + RegionCoverageInfo(CoveredRegions, NumCodeRegions), LineCoverageInfo(CoveredLines, 0, NumLines)); } @@ -74,7 +75,7 @@ FileCoverageSummary::get(StringRef Name, ArrayRef FunctionSummaries) { size_t NumRegions = 0, CoveredRegions = 0; size_t NumLines = 0, NonCodeLines = 0, CoveredLines = 0; - size_t NumFunctionsCovered = 0; + size_t NumFunctionsExecuted = 0; for (const auto &Func : FunctionSummaries) { CoveredRegions += Func.RegionCoverage.Covered; NumRegions += Func.RegionCoverage.NumRegions; @@ -83,13 +84,13 @@ FileCoverageSummary::get(StringRef Name, NonCodeLines += Func.LineCoverage.NonCodeLines; NumLines += Func.LineCoverage.NumLines; - if (Func.RegionCoverage.isFullyCovered()) - ++NumFunctionsCovered; + if (Func.ExecutionCount != 0) + ++NumFunctionsExecuted; } return FileCoverageSummary( Name, RegionCoverageInfo(CoveredRegions, NumRegions), LineCoverageInfo(CoveredLines, NonCodeLines, NumLines), - FunctionCoverageInfo(NumFunctionsCovered, FunctionSummaries.size()), + FunctionCoverageInfo(NumFunctionsExecuted, FunctionSummaries.size()), FunctionSummaries); } diff --git a/tools/llvm-cov/CoverageSummaryInfo.h b/tools/llvm-cov/CoverageSummaryInfo.h index 18b270433cd..0036032ab39 100644 --- a/tools/llvm-cov/CoverageSummaryInfo.h +++ b/tools/llvm-cov/CoverageSummaryInfo.h @@ -69,33 +69,34 @@ struct LineCoverageInfo { /// \brief Provides information about function coverage for a file. struct FunctionCoverageInfo { - /// \brief The number of functions that have full - /// region coverage. - size_t FullyCovered; + /// \brief The number of functions that were executed. + size_t Executed; /// \brief The total number of functions in this file. size_t NumFunctions; - FunctionCoverageInfo(size_t FullyCovered, size_t NumFunctions) - : FullyCovered(FullyCovered), NumFunctions(NumFunctions) {} + FunctionCoverageInfo(size_t Executed, size_t NumFunctions) + : Executed(Executed), NumFunctions(NumFunctions) {} - bool isFullyCovered() const { return FullyCovered == NumFunctions; } + bool isFullyCovered() const { return Executed == NumFunctions; } double getPercentCovered() const { - return double(FullyCovered) / double(NumFunctions) * 100.0; + return double(Executed) / double(NumFunctions) * 100.0; } }; /// \brief A summary of function's code coverage. struct FunctionCoverageSummary { StringRef Name; + uint64_t ExecutionCount; RegionCoverageInfo RegionCoverage; LineCoverageInfo LineCoverage; - FunctionCoverageSummary(StringRef Name, + FunctionCoverageSummary(StringRef Name, uint64_t ExecutionCount, const RegionCoverageInfo &RegionCoverage, const LineCoverageInfo &LineCoverage) - : Name(Name), RegionCoverage(RegionCoverage), LineCoverage(LineCoverage) { + : Name(Name), ExecutionCount(ExecutionCount), + RegionCoverage(RegionCoverage), LineCoverage(LineCoverage) { } /// \brief Compute the code coverage summary for the given function coverage