blob: 53dcf1602c9f2924e2e1c7af274abb4942269a2f [file] [log] [blame]
Duncan P. N. Exon Smith846a6272014-02-17 23:22:49 +00001//===- 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
Duncan P. N. Exon Smith846a6272014-02-17 23:22:49 +000014#include "llvm/ADT/StringRef.h"
Justin Bognerf8d79192014-03-21 17:24:48 +000015#include "llvm/ProfileData/InstrProfReader.h"
Duncan P. N. Exon Smith846a6272014-02-17 23:22:49 +000016#include "llvm/Support/CommandLine.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
23using namespace llvm;
24
Justin Bognerf8d79192014-03-21 17:24:48 +000025static void exitWithError(const Twine &Message, StringRef Whence = "") {
26 errs() << "error: ";
27 if (!Whence.empty())
28 errs() << Whence << ": ";
29 errs() << Message << "\n";
Duncan P. N. Exon Smith846a6272014-02-17 23:22:49 +000030 ::exit(1);
31}
32
Justin Bogner618bcea2014-03-19 02:20:46 +000033int merge_main(int argc, const char *argv[]) {
34 cl::opt<std::string> Filename1(cl::Positional, cl::Required,
35 cl::desc("file1"));
36 cl::opt<std::string> Filename2(cl::Positional, cl::Required,
37 cl::desc("file2"));
38
39 cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
40 cl::init("-"),
41 cl::desc("Output file"));
42 cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
43 cl::aliasopt(OutputFilename));
Justin Bognerbfee8d42014-03-12 20:14:17 +000044
Justin Bognerec49f982014-03-12 22:00:57 +000045 cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
Justin Bognerbfee8d42014-03-12 20:14:17 +000046
Justin Bognerf8d79192014-03-21 17:24:48 +000047 std::unique_ptr<InstrProfReader> Reader1, Reader2;
48 if (error_code ec = InstrProfReader::create(Filename1, Reader1))
Justin Bognerec49f982014-03-12 22:00:57 +000049 exitWithError(ec.message(), Filename1);
Justin Bognerf8d79192014-03-21 17:24:48 +000050 if (error_code ec = InstrProfReader::create(Filename2, Reader2))
Justin Bognerec49f982014-03-12 22:00:57 +000051 exitWithError(ec.message(), Filename2);
Justin Bognerbfee8d42014-03-12 20:14:17 +000052
Justin Bognerec49f982014-03-12 22:00:57 +000053 if (OutputFilename.empty())
54 OutputFilename = "-";
55
56 std::string ErrorInfo;
57 raw_fd_ostream Output(OutputFilename.data(), ErrorInfo, sys::fs::F_Text);
58 if (!ErrorInfo.empty())
59 exitWithError(ErrorInfo, OutputFilename);
60
Justin Bognerf8d79192014-03-21 17:24:48 +000061 for (InstrProfIterator I1 = Reader1->begin(), E1 = Reader1->end(),
62 I2 = Reader2->begin(), E2 = Reader2->end();
63 I1 != E1 && I2 != E2; ++I1, ++I2) {
64 if (I1->Name != I2->Name)
65 exitWithError("Function name mismatch, " + I1->Name + " != " + I2->Name);
66 if (I1->Hash != I2->Hash)
67 exitWithError("Function hash mismatch for " + I1->Name);
68 if (I1->Counts.size() != I2->Counts.size())
69 exitWithError("Function count mismatch for " + I1->Name);
70
71 Output << I1->Name << "\n" << I1->Hash << "\n" << I1->Counts.size() << "\n";
72
73 for (size_t II = 0, EE = I1->Counts.size(); II < EE; ++II) {
74 uint64_t Sum = I1->Counts[II] + I2->Counts[II];
75 if (Sum < I1->Counts[II])
76 exitWithError("Counter overflow for " + I1->Name);
77 Output << Sum << "\n";
Justin Bognerbfee8d42014-03-12 20:14:17 +000078 }
Justin Bognerf8d79192014-03-21 17:24:48 +000079 Output << "\n";
Justin Bognerbfee8d42014-03-12 20:14:17 +000080 }
Justin Bognerf8d79192014-03-21 17:24:48 +000081 if (Reader1->hasError())
82 exitWithError(Reader1->getError().message(), Filename1);
83 if (Reader2->hasError())
84 exitWithError(Reader2->getError().message(), Filename2);
85 if (!Reader1->isEOF() || !Reader2->isEOF())
86 exitWithError("Number of instrumented functions differ.");
Justin Bognerbfee8d42014-03-12 20:14:17 +000087
Justin Bognerec49f982014-03-12 22:00:57 +000088 return 0;
Justin Bognerbfee8d42014-03-12 20:14:17 +000089}
Justin Bogner618bcea2014-03-19 02:20:46 +000090
91int main(int argc, const char *argv[]) {
92 // Print a stack trace if we signal out.
93 sys::PrintStackTraceOnErrorSignal();
94 PrettyStackTraceProgram X(argc, argv);
95 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
96
97 StringRef ProgName(sys::path::filename(argv[0]));
98 if (argc > 1) {
99 int (*func)(int, const char *[]) = 0;
100
101 if (strcmp(argv[1], "merge") == 0)
102 func = merge_main;
103
104 if (func) {
105 std::string Invocation(ProgName.str() + " " + argv[1]);
106 argv[1] = Invocation.c_str();
107 return func(argc - 1, argv + 1);
108 }
109
110 if (strcmp(argv[1], "-h") == 0 ||
111 strcmp(argv[1], "-help") == 0 ||
112 strcmp(argv[1], "--help") == 0) {
113
114 errs() << "OVERVIEW: LLVM profile data tools\n\n"
115 << "USAGE: " << ProgName << " <command> [args...]\n"
116 << "USAGE: " << ProgName << " <command> -help\n\n"
117 << "Available commands: merge\n";
118 return 0;
119 }
120 }
121
122 if (argc < 2)
123 errs() << ProgName << ": No command specified!\n";
124 else
125 errs() << ProgName << ": Unknown command!\n";
126
Justin Bognerf8d79192014-03-21 17:24:48 +0000127 errs() << "USAGE: " << ProgName << " <merge> [args...]\n";
Justin Bogner618bcea2014-03-19 02:20:46 +0000128 return 1;
129}