+void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
+ StringRef GCNOFile, StringRef GCDAFile) {
+ for (const auto &LI : LineInfo) {
+ StringRef Filename = LI.first();
+ auto AllLines = LineConsumer(Filename);
+
+ std::string CoveragePath = getCoveragePath(Filename, MainFilename);
+ std::unique_ptr<raw_ostream> CovStream = openCoveragePath(CoveragePath);
+ raw_ostream &CovOS = *CovStream;
+
+ CovOS << " -: 0:Source:" << Filename << "\n";
+ CovOS << " -: 0:Graph:" << GCNOFile << "\n";
+ CovOS << " -: 0:Data:" << GCDAFile << "\n";
+ CovOS << " -: 0:Runs:" << RunCount << "\n";
+ CovOS << " -: 0:Programs:" << ProgramCount << "\n";
+
+ const LineData &Line = LI.second;
+ GCOVCoverage FileCoverage(Filename);
+ for (uint32_t LineIndex = 0; LineIndex < Line.LastLine || !AllLines.empty();
+ ++LineIndex) {
+ if (Options.BranchInfo) {
+ FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex);
+ if (FuncsIt != Line.Functions.end())
+ printFunctionSummary(CovOS, FuncsIt->second);
+ }
+
+ BlockLines::const_iterator BlocksIt = Line.Blocks.find(LineIndex);
+ if (BlocksIt == Line.Blocks.end()) {
+ // No basic blocks are on this line. Not an executable line of code.
+ CovOS << " -:";
+ AllLines.printNext(CovOS, LineIndex + 1);
+ } else {
+ const BlockVector &Blocks = BlocksIt->second;
+
+ // Add up the block counts to form line counts.
+ DenseMap<const GCOVFunction *, bool> LineExecs;
+ uint64_t LineCount = 0;
+ for (const GCOVBlock *Block : Blocks) {
+ if (Options.AllBlocks) {
+ // Only take the highest block count for that line.
+ uint64_t BlockCount = Block->getCount();
+ LineCount = LineCount > BlockCount ? LineCount : BlockCount;
+ } else {
+ // Sum up all of the block counts.
+ LineCount += Block->getCount();
+ }
+
+ if (Options.FuncCoverage) {
+ // This is a slightly convoluted way to most accurately gather line
+ // statistics for functions. Basically what is happening is that we
+ // don't want to count a single line with multiple blocks more than
+ // once. However, we also don't simply want to give the total line
+ // count to every function that starts on the line. Thus, what is
+ // happening here are two things:
+ // 1) Ensure that the number of logical lines is only incremented
+ // once per function.
+ // 2) If there are multiple blocks on the same line, ensure that the
+ // number of lines executed is incremented as long as at least
+ // one of the blocks are executed.
+ const GCOVFunction *Function = &Block->getParent();
+ if (FuncCoverages.find(Function) == FuncCoverages.end()) {
+ std::pair<const GCOVFunction *, GCOVCoverage> KeyValue(
+ Function, GCOVCoverage(Function->getName()));
+ FuncCoverages.insert(KeyValue);
+ }
+ GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
+
+ if (LineExecs.find(Function) == LineExecs.end()) {
+ if (Block->getCount()) {
+ ++FuncCoverage.LinesExec;
+ LineExecs[Function] = true;
+ } else {
+ LineExecs[Function] = false;
+ }
+ ++FuncCoverage.LogicalLines;
+ } else if (!LineExecs[Function] && Block->getCount()) {
+ ++FuncCoverage.LinesExec;
+ LineExecs[Function] = true;
+ }
+ }
+ }
+
+ if (LineCount == 0)
+ CovOS << " #####:";
+ else {
+ CovOS << format("%9" PRIu64 ":", LineCount);
+ ++FileCoverage.LinesExec;
+ }
+ ++FileCoverage.LogicalLines;
+
+ AllLines.printNext(CovOS, LineIndex + 1);
+
+ uint32_t BlockNo = 0;
+ uint32_t EdgeNo = 0;
+ for (const GCOVBlock *Block : Blocks) {
+ // Only print block and branch information at the end of the block.
+ if (Block->getLastLine() != LineIndex + 1)
+ continue;
+ if (Options.AllBlocks)
+ printBlockInfo(CovOS, *Block, LineIndex, BlockNo);
+ if (Options.BranchInfo) {
+ size_t NumEdges = Block->getNumDstEdges();
+ if (NumEdges > 1)
+ printBranchInfo(CovOS, *Block, FileCoverage, EdgeNo);
+ else if (Options.UncondBranch && NumEdges == 1)
+ printUncondBranchInfo(CovOS, EdgeNo,
+ (*Block->dst_begin())->Count);
+ }
+ }
+ }