1 //===- bolt/tools/heatmap/heatmap.cpp - Profile heatmap visualization tool ===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "bolt/Rewrite/RewriteInstance.h"
10 #include "bolt/Utils/CommandLineOpts.h"
11 #include "llvm/MC/TargetRegistry.h"
12 #include "llvm/Object/Binary.h"
13 #include "llvm/Support/CommandLine.h"
14 #include "llvm/Support/Errc.h"
15 #include "llvm/Support/Error.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/Program.h"
18 #include "llvm/Support/TargetSelect.h"
25 static cl::OptionCategory
*HeatmapCategories
[] = {&HeatmapCategory
,
28 static cl::opt
<std::string
> InputFilename(cl::Positional
,
29 cl::desc("<executable>"),
31 cl::cat(HeatmapCategory
));
35 static StringRef ToolName
;
37 static void report_error(StringRef Message
, std::error_code EC
) {
39 errs() << ToolName
<< ": '" << Message
<< "': " << EC
.message() << ".\n";
43 static void report_error(StringRef Message
, Error E
) {
45 errs() << ToolName
<< ": '" << Message
<< "': " << toString(std::move(E
))
50 static std::string
GetExecutablePath(const char *Argv0
) {
51 SmallString
<256> ExecutablePath(Argv0
);
52 // Do a PATH lookup if Argv0 isn't a valid path.
53 if (!llvm::sys::fs::exists(ExecutablePath
))
54 if (llvm::ErrorOr
<std::string
> P
=
55 llvm::sys::findProgramByName(ExecutablePath
))
57 return std::string(ExecutablePath
);
60 int main(int argc
, char **argv
) {
61 cl::HideUnrelatedOptions(ArrayRef(opts::HeatmapCategories
));
62 cl::ParseCommandLineOptions(argc
, argv
, "");
64 if (opts::PerfData
.empty()) {
65 errs() << ToolName
<< ": expected -perfdata=<filename> option.\n";
69 opts::HeatmapMode
= true;
70 opts::AggregateOnly
= true;
71 if (!sys::fs::exists(opts::InputFilename
))
72 report_error(opts::InputFilename
, errc::no_such_file_or_directory
);
74 // Output to stdout by default
75 if (opts::OutputFilename
.empty())
76 opts::OutputFilename
= "-";
78 // Initialize targets and assembly printers/parsers.
79 llvm::InitializeAllTargetInfos();
80 llvm::InitializeAllTargetMCs();
81 llvm::InitializeAllAsmParsers();
82 llvm::InitializeAllDisassemblers();
84 llvm::InitializeAllTargets();
85 llvm::InitializeAllAsmPrinters();
88 std::string ToolPath
= GetExecutablePath(argv
[0]);
89 Expected
<OwningBinary
<Binary
>> BinaryOrErr
=
90 createBinary(opts::InputFilename
);
91 if (Error E
= BinaryOrErr
.takeError())
92 report_error(opts::InputFilename
, std::move(E
));
93 Binary
&Binary
= *BinaryOrErr
.get().getBinary();
95 if (auto *e
= dyn_cast
<ELFObjectFileBase
>(&Binary
)) {
96 auto RIOrErr
= RewriteInstance::create(e
, argc
, argv
, ToolPath
);
97 if (Error E
= RIOrErr
.takeError())
98 report_error("RewriteInstance", std::move(E
));
100 RewriteInstance
&RI
= *RIOrErr
.get();
101 if (Error E
= RI
.setProfile(opts::PerfData
))
102 report_error(opts::PerfData
, std::move(E
));
104 if (Error E
= RI
.run())
105 report_error(opts::InputFilename
, std::move(E
));
107 report_error(opts::InputFilename
, object_error::invalid_file_type
);