blob: 587ee11899ba0329ef542091ed52af8d0e01e610 [file] [log] [blame]
Stephen Hines36b56882014-04-23 16:57:46 -07001//===- llvm-cov.cpp - LLVM coverage tool ----------------------------------===//
Devang Pateld02c42b2011-09-28 18:50:00 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Devang Pateld02c42b2011-09-28 18:50:00 +000010// llvm-cov is a command line tools to analyze and report coverage information.
11//
Devang Pateld02c42b2011-09-28 18:50:00 +000012//===----------------------------------------------------------------------===//
13
Stephen Hines36b56882014-04-23 16:57:46 -070014#include "llvm/ADT/SmallString.h"
Devang Pateld02c42b2011-09-28 18:50:00 +000015#include "llvm/Support/CommandLine.h"
Stephen Hines36b56882014-04-23 16:57:46 -070016#include "llvm/Support/FileSystem.h"
Devang Patel58c62002011-10-04 17:24:48 +000017#include "llvm/Support/GCOV.h"
Devang Pateld02c42b2011-09-28 18:50:00 +000018#include "llvm/Support/ManagedStatic.h"
19#include "llvm/Support/MemoryObject.h"
Stephen Hines36b56882014-04-23 16:57:46 -070020#include "llvm/Support/Path.h"
Devang Pateld02c42b2011-09-28 18:50:00 +000021#include "llvm/Support/PrettyStackTrace.h"
22#include "llvm/Support/Signals.h"
23#include "llvm/Support/system_error.h"
24using namespace llvm;
25
Stephen Hines36b56882014-04-23 16:57:46 -070026static cl::opt<std::string> SourceFile(cl::Positional, cl::Required,
27 cl::desc("SOURCEFILE"));
28
29static cl::opt<bool> AllBlocks("a", cl::init(false),
30 cl::desc("Display all basic blocks"));
31static cl::alias AllBlocksA("all-blocks", cl::aliasopt(AllBlocks));
32
33static cl::opt<bool> BranchProb("b", cl::init(false),
34 cl::desc("Display branch probabilities"));
35static cl::alias BranchProbA("branch-probabilities", cl::aliasopt(BranchProb));
36
37static cl::opt<bool> BranchCount("c", cl::init(false),
38 cl::desc("Display branch counts instead "
39 "of percentages (requires -b)"));
40static cl::alias BranchCountA("branch-counts", cl::aliasopt(BranchCount));
41
42static cl::opt<bool> FuncSummary("f", cl::init(false),
43 cl::desc("Show coverage for each function"));
44static cl::alias FuncSummaryA("function-summaries", cl::aliasopt(FuncSummary));
Devang Pateld02c42b2011-09-28 18:50:00 +000045
46static cl::opt<std::string>
Stephen Hines36b56882014-04-23 16:57:46 -070047ObjectDir("o", cl::value_desc("DIR|FILE"), cl::init(""),
48 cl::desc("Find objects in DIR or based on FILE's path"));
49static cl::alias ObjectDirA("object-directory", cl::aliasopt(ObjectDir));
50static cl::alias ObjectDirB("object-file", cl::aliasopt(ObjectDir));
Devang Pateld02c42b2011-09-28 18:50:00 +000051
Stephen Hines36b56882014-04-23 16:57:46 -070052static cl::opt<bool> PreservePaths("p", cl::init(false),
53 cl::desc("Preserve path components"));
54static cl::alias PreservePathsA("preserve-paths", cl::aliasopt(PreservePaths));
Devang Pateld02c42b2011-09-28 18:50:00 +000055
Stephen Hines36b56882014-04-23 16:57:46 -070056static cl::opt<bool> UncondBranch("u", cl::init(false),
57 cl::desc("Display unconditional branch info "
58 "(requires -b)"));
59static cl::alias UncondBranchA("unconditional-branches",
60 cl::aliasopt(UncondBranch));
Yuchen Wudaaa8b72013-11-02 00:09:17 +000061
Stephen Hines36b56882014-04-23 16:57:46 -070062static cl::OptionCategory DebugCat("Internal and debugging options");
63static cl::opt<bool> DumpGCOV("dump", cl::init(false), cl::cat(DebugCat),
64 cl::desc("Dump the gcov file to stderr"));
65static cl::opt<std::string> InputGCNO("gcno", cl::cat(DebugCat), cl::init(""),
66 cl::desc("Override inferred gcno file"));
67static cl::opt<std::string> InputGCDA("gcda", cl::cat(DebugCat), cl::init(""),
68 cl::desc("Override inferred gcda file"));
Devang Pateld02c42b2011-09-28 18:50:00 +000069
70//===----------------------------------------------------------------------===//
71int main(int argc, char **argv) {
72 // Print a stack trace if we signal out.
73 sys::PrintStackTraceOnErrorSignal();
74 PrettyStackTraceProgram X(argc, argv);
75 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
76
Stephen Hines36b56882014-04-23 16:57:46 -070077 cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
Devang Pateld02c42b2011-09-28 18:50:00 +000078
Stephen Hines36b56882014-04-23 16:57:46 -070079 SmallString<128> CoverageFileStem(ObjectDir);
80 if (CoverageFileStem.empty()) {
81 // If no directory was specified with -o, look next to the source file.
82 CoverageFileStem = sys::path::parent_path(SourceFile);
83 sys::path::append(CoverageFileStem, sys::path::stem(SourceFile));
84 } else if (sys::fs::is_directory(ObjectDir))
85 // A directory name was given. Use it and the source file name.
86 sys::path::append(CoverageFileStem, sys::path::stem(SourceFile));
87 else
88 // A file was given. Ignore the source file and look next to this file.
89 sys::path::replace_extension(CoverageFileStem, "");
90
91 if (InputGCNO.empty())
92 InputGCNO = (CoverageFileStem.str() + ".gcno").str();
93 if (InputGCDA.empty())
94 InputGCDA = (CoverageFileStem.str() + ".gcda").str();
Yuchen Wudaaa8b72013-11-02 00:09:17 +000095
Devang Pateld02c42b2011-09-28 18:50:00 +000096 GCOVFile GF;
Devang Pateld02c42b2011-09-28 18:50:00 +000097
Stephen Hines36b56882014-04-23 16:57:46 -070098 std::unique_ptr<MemoryBuffer> GCNO_Buff;
Devang Patel7a502022011-09-29 16:46:47 +000099 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputGCNO, GCNO_Buff)) {
Devang Pateld02c42b2011-09-28 18:50:00 +0000100 errs() << InputGCNO << ": " << ec.message() << "\n";
101 return 1;
102 }
Benjamin Kramerd881c1b2013-11-15 09:44:17 +0000103 GCOVBuffer GCNO_GB(GCNO_Buff.get());
Stephen Hines36b56882014-04-23 16:57:46 -0700104 if (!GF.readGCNO(GCNO_GB)) {
Devang Pateld02c42b2011-09-28 18:50:00 +0000105 errs() << "Invalid .gcno File!\n";
106 return 1;
107 }
108
Stephen Hines36b56882014-04-23 16:57:46 -0700109 std::unique_ptr<MemoryBuffer> GCDA_Buff;
110 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputGCDA, GCDA_Buff)) {
111 if (ec != errc::no_such_file_or_directory) {
Devang Pateld02c42b2011-09-28 18:50:00 +0000112 errs() << InputGCDA << ": " << ec.message() << "\n";
113 return 1;
114 }
Stephen Hines36b56882014-04-23 16:57:46 -0700115 // Clear the filename to make it clear we didn't read anything.
116 InputGCDA = "-";
117 } else {
Benjamin Kramerd881c1b2013-11-15 09:44:17 +0000118 GCOVBuffer GCDA_GB(GCDA_Buff.get());
Stephen Hines36b56882014-04-23 16:57:46 -0700119 if (!GF.readGCDA(GCDA_GB)) {
Devang Pateld02c42b2011-09-28 18:50:00 +0000120 errs() << "Invalid .gcda File!\n";
121 return 1;
122 }
123 }
124
Devang Pateld02c42b2011-09-28 18:50:00 +0000125 if (DumpGCOV)
126 GF.dump();
127
Stephen Hines36b56882014-04-23 16:57:46 -0700128 GCOVOptions Options(AllBlocks, BranchProb, BranchCount, FuncSummary,
129 PreservePaths, UncondBranch);
130 FileInfo FI(Options);
Devang Pateld02c42b2011-09-28 18:50:00 +0000131 GF.collectLineCounts(FI);
Stephen Hines36b56882014-04-23 16:57:46 -0700132 FI.print(InputGCNO, InputGCDA);
Devang Pateld02c42b2011-09-28 18:50:00 +0000133 return 0;
134}