llvm-profdata: Update to use the naive text format with function hash
[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/LineIterator.h"
17 #include "llvm/Support/ManagedStatic.h"
18 #include "llvm/Support/MemoryBuffer.h"
19 #include "llvm/Support/PrettyStackTrace.h"
20 #include "llvm/Support/Signals.h"
21 #include "llvm/Support/raw_ostream.h"
22
23 using namespace llvm;
24
25 static cl::opt<std::string> Filename1(cl::Positional, cl::Required,
26                                       cl::desc("file1"));
27 static cl::opt<std::string> Filename2(cl::Positional, cl::Required,
28                                       cl::desc("file2"));
29
30 static cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
31                                            cl::init("-"),
32                                            cl::desc("Output file"));
33 static cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
34                                  cl::aliasopt(OutputFilename));
35
36 static void exitWithError(const std::string &Message,
37                           const std::string &Filename, int64_t Line = -1) {
38   errs() << "error: " << Filename;
39   if (Line >= 0)
40     errs() << ":" << Line;
41   errs() << ": " << Message << "\n";
42   ::exit(1);
43 }
44
45 //===----------------------------------------------------------------------===//
46 int main(int argc, char **argv) {
47   // Print a stack trace if we signal out.
48   sys::PrintStackTraceOnErrorSignal();
49   PrettyStackTraceProgram X(argc, argv);
50   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
51
52   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
53
54   std::unique_ptr<MemoryBuffer> File1;
55   std::unique_ptr<MemoryBuffer> File2;
56   if (error_code ec = MemoryBuffer::getFile(Filename1, File1))
57     exitWithError(ec.message(), Filename1);
58   if (error_code ec = MemoryBuffer::getFile(Filename2, File2))
59     exitWithError(ec.message(), Filename2);
60
61   if (OutputFilename.empty())
62     OutputFilename = "-";
63
64   std::string ErrorInfo;
65   raw_fd_ostream Output(OutputFilename.data(), ErrorInfo, sys::fs::F_Text);
66   if (!ErrorInfo.empty())
67     exitWithError(ErrorInfo, OutputFilename);
68
69   enum {ReadName, ReadHash, ReadCount, ReadCounters} State = ReadName;
70   uint64_t N1, N2, NumCounters;
71   line_iterator I1(*File1, '#'), I2(*File2, '#');
72   for (; !I1.is_at_end() && !I2.is_at_end(); ++I1, ++I2) {
73     if (I1->empty()) {
74       if (!I2->empty())
75         exitWithError("data mismatch", Filename2, I2.line_number());
76       Output << "\n";
77       continue;
78     }
79     switch (State) {
80     case ReadName:
81       if (*I1 != *I2)
82         exitWithError("function name mismatch", Filename2, I2.line_number());
83       Output << *I1 << "\n";
84       State = ReadHash;
85       break;
86     case ReadHash:
87       if (I1->getAsInteger(10, N1))
88         exitWithError("bad function hash", Filename1, I1.line_number());
89       if (I2->getAsInteger(10, N2))
90         exitWithError("bad function hash", Filename2, I2.line_number());
91       if (N1 != N2)
92         exitWithError("function hash mismatch", Filename2, I2.line_number());
93       Output << N1 << "\n";
94       State = ReadCount;
95       break;
96     case ReadCount:
97       if (I1->getAsInteger(10, N1))
98         exitWithError("bad function count", Filename1, I1.line_number());
99       if (I2->getAsInteger(10, N2))
100         exitWithError("bad function count", Filename2, I2.line_number());
101       if (N1 != N2)
102         exitWithError("function count mismatch", Filename2, I2.line_number());
103       Output << N1 << "\n";
104       NumCounters = N1;
105       State = ReadCounters;
106       break;
107     case ReadCounters:
108       if (I1->getAsInteger(10, N1))
109         exitWithError("invalid counter", Filename1, I1.line_number());
110       if (I2->getAsInteger(10, N2))
111         exitWithError("invalid counter", Filename2, I2.line_number());
112       uint64_t Sum = N1 + N2;
113       if (Sum < N1)
114         exitWithError("counter overflow", Filename2, I2.line_number());
115       Output << N1 + N2 << "\n";
116       if (--NumCounters == 0)
117         State = ReadName;
118       break;
119     }
120   }
121   if (!I1.is_at_end())
122     exitWithError("truncated file", Filename1, I1.line_number());
123   if (!I2.is_at_end())
124     exitWithError("truncated file", Filename2, I2.line_number());
125   if (State != ReadName)
126     exitWithError("truncated file", Filename1, I1.line_number());
127
128   return 0;
129 }