Replace OwningPtr<T> with std::unique_ptr<T>.
[oota-llvm.git] / tools / llvm-profdata / llvm-profdata.cpp
1 //===- llvm-profdata.cpp - LLVM profile data tool -------------------------===//
2 //
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 //
10 // llvm-profdata merges .profdata files.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Support/CommandLine.h"
16 #include "llvm/Support/ManagedStatic.h"
17 #include "llvm/Support/MemoryBuffer.h"
18 #include "llvm/Support/PrettyStackTrace.h"
19 #include "llvm/Support/Signals.h"
20 #include "llvm/Support/raw_ostream.h"
21
22 using namespace llvm;
23
24 static cl::opt<std::string> Filename1(cl::Positional, cl::Required,
25                                       cl::desc("file1"));
26 static cl::opt<std::string> Filename2(cl::Positional, cl::Required,
27                                       cl::desc("file2"));
28
29 static cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
30                                            cl::init("-"),
31                                            cl::desc("Output file"));
32 static cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
33                                  cl::aliasopt(OutputFilename));
34
35 static bool readLine(const char *&Start, const char *End, StringRef &S) {
36   if (Start == End)
37     return false;
38
39   for (const char *I = Start; I != End; ++I) {
40     assert(*I && "unexpected binary data");
41     if (*I == '\n') {
42       S = StringRef(Start, I - Start);
43       Start = I + 1;
44       return true;
45     }
46   }
47
48   S = StringRef(Start, End - Start);
49   Start = End;
50   return true;
51 }
52
53 static StringRef getWord(const char *&Start, const char *End) {
54   for (const char *I = Start; I != End; ++I)
55     if (*I == ' ') {
56       StringRef S(Start, I - Start);
57       Start = I + 1;
58       return S;
59     }
60   StringRef S(Start, End - Start);
61   Start = End;
62   return S;
63 }
64
65 static size_t splitWords(const StringRef &Line, std::vector<StringRef> &Words) {
66   const char *Start = Line.data();
67   const char *End = Line.data() + Line.size();
68   Words.clear();
69   while (Start != End)
70     Words.push_back(getWord(Start, End));
71   return Words.size();
72 }
73
74 static bool getNumber(const StringRef &S, uint64_t &N) {
75   N = 0;
76   for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I)
77     if (*I >= '0' && *I <= '9')
78       N = N * 10 + (*I - '0');
79     else
80       return false;
81
82   return true;
83 }
84
85 static void exitWithError(const std::string &Message,
86                           const std::string &Filename, int64_t Line = -1) {
87   errs() << "error: " << Filename;
88   if (Line >= 0)
89     errs() << ":" << Line;
90   errs() << ": " << Message << "\n";
91   ::exit(1);
92 }
93
94 //===----------------------------------------------------------------------===//
95 int main(int argc, char **argv) {
96   // Print a stack trace if we signal out.
97   sys::PrintStackTraceOnErrorSignal();
98   PrettyStackTraceProgram X(argc, argv);
99   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
100
101   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
102
103   std::unique_ptr<MemoryBuffer> File1;
104   std::unique_ptr<MemoryBuffer> File2;
105   if (error_code ec = MemoryBuffer::getFile(Filename1, File1))
106     exitWithError(ec.message(), Filename1);
107   if (error_code ec = MemoryBuffer::getFile(Filename2, File2))
108     exitWithError(ec.message(), Filename2);
109
110   if (OutputFilename.empty())
111     OutputFilename = "-";
112
113   std::string ErrorInfo;
114   raw_fd_ostream Output(OutputFilename.data(), ErrorInfo, sys::fs::F_Text);
115   if (!ErrorInfo.empty())
116     exitWithError(ErrorInfo, OutputFilename);
117
118   const char *Start1 = File1->getBufferStart();
119   const char *Start2 = File2->getBufferStart();
120   const char *End1 = File1->getBufferEnd();
121   const char *End2 = File2->getBufferEnd();
122   const char *P1 = Start1;
123   const char *P2 = Start2;
124
125   StringRef Line1, Line2;
126   int64_t Num = 0;
127   while (readLine(P1, End1, Line1)) {
128     ++Num;
129     if (!readLine(P2, End2, Line2))
130       exitWithError("truncated file", Filename2, Num);
131
132     std::vector<StringRef> Words1, Words2;
133     if (splitWords(Line1, Words1) != splitWords(Line2, Words2))
134       exitWithError("data mismatch", Filename2, Num);
135
136     if (Words1.size() > 2)
137       exitWithError("invalid data", Filename1, Num);
138
139     if (Words1.empty()) {
140       Output << "\n";
141       continue;
142     }
143
144     if (Words1.size() == 2) {
145       if (Words1[0] != Words2[0])
146         exitWithError("function name mismatch", Filename2, Num);
147
148       uint64_t N1, N2;
149       if (!getNumber(Words1[1], N1))
150         exitWithError("bad function count", Filename1, Num);
151       if (!getNumber(Words2[1], N2))
152         exitWithError("bad function count", Filename2, Num);
153
154       if (N1 != N2)
155         exitWithError("function count mismatch", Filename2, Num);
156
157       Output << Line1 << "\n";
158       continue;
159     }
160
161     uint64_t N1, N2;
162     if (!getNumber(Words1[0], N1))
163       exitWithError("invalid counter", Filename1, Num);
164     if (!getNumber(Words2[0], N2))
165       exitWithError("invalid counter", Filename2, Num);
166
167     uint64_t Sum = N1 + N2;
168     if (Sum < N1)
169       exitWithError("counter overflow", Filename2, Num);
170
171     Output << N1 + N2 << "\n";
172   }
173   if (readLine(P2, End2, Line2))
174     exitWithError("truncated file", Filename1, Num + 1);
175
176   return 0;
177 }