1 //===- llvm-profdata.cpp - LLVM profile data tool -------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // llvm-profdata merges .profdata files.
12 //===----------------------------------------------------------------------===//
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"
25 static cl::opt<std::string> Filename1(cl::Positional, cl::Required,
27 static cl::opt<std::string> Filename2(cl::Positional, cl::Required,
30 static cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
32 cl::desc("Output file"));
33 static cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
34 cl::aliasopt(OutputFilename));
36 static void exitWithError(const std::string &Message,
37 const std::string &Filename, int64_t Line = -1) {
38 errs() << "error: " << Filename;
40 errs() << ":" << Line;
41 errs() << ": " << Message << "\n";
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.
52 cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
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);
61 if (OutputFilename.empty())
64 std::string ErrorInfo;
65 raw_fd_ostream Output(OutputFilename.data(), ErrorInfo, sys::fs::F_Text);
66 if (!ErrorInfo.empty())
67 exitWithError(ErrorInfo, OutputFilename);
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) {
75 exitWithError("data mismatch", Filename2, I2.line_number());
82 exitWithError("function name mismatch", Filename2, I2.line_number());
83 Output << *I1 << "\n";
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());
92 exitWithError("function hash mismatch", Filename2, I2.line_number());
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());
102 exitWithError("function count mismatch", Filename2, I2.line_number());
103 Output << N1 << "\n";
105 State = 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;
114 exitWithError("counter overflow", Filename2, I2.line_number());
115 Output << N1 + N2 << "\n";
116 if (--NumCounters == 0)
122 exitWithError("truncated file", Filename1, I1.line_number());
124 exitWithError("truncated file", Filename2, I2.line_number());
125 if (State != ReadName)
126 exitWithError("truncated file", Filename1, I1.line_number());