1//===--- llvm-ctxprof-util - utilities for ctxprof --------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10///
11/// Utilities for manipulating contextual profiles
12///
13//===----------------------------------------------------------------------===//
14
15#include "llvm/IR/GlobalValue.h"
16#include "llvm/ProfileData/PGOCtxProfReader.h"
17#include "llvm/ProfileData/PGOCtxProfWriter.h"
18#include "llvm/Support/CommandLine.h"
19#include "llvm/Support/Error.h"
20#include "llvm/Support/ErrorHandling.h"
21#include "llvm/Support/MemoryBuffer.h"
22#include "llvm/Support/raw_ostream.h"
23
24using namespace llvm;
25
26static cl::SubCommand FromYAML("fromYAML", "Convert from yaml");
27static cl::SubCommand ToYAML("toYAML", "Convert to yaml");
28
29static cl::opt<std::string> InputFilename(
30 "input", cl::value_desc("input"), cl::init(Val: "-"),
31 cl::desc(
32 "Input file. The format is an array of contexts.\n"
33 "Each context is a dictionary with the following keys:\n"
34 "'Guid', mandatory. The value is a 64-bit integer.\n"
35 "'Counters', mandatory. An array of 32-bit ints. These are the "
36 "counter values.\n"
37 "'Contexts', optional. An array containing arrays of contexts. The "
38 "context array at a position 'i' is the set of callees at that "
39 "callsite index. Use an empty array to indicate no callees."),
40 cl::sub(FromYAML), cl::sub(ToYAML));
41
42static cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
43 cl::init(Val: "-"),
44 cl::desc("Output file"),
45 cl::sub(FromYAML), cl::sub(ToYAML));
46
47namespace {
48// Save the bitstream profile from the JSON representation.
49Error convertFromYaml() {
50 auto BufOrError =
51 MemoryBuffer::getFileOrSTDIN(Filename: InputFilename, /*IsText=*/true);
52 if (!BufOrError)
53 return createFileError(F: InputFilename, EC: BufOrError.getError());
54
55 std::error_code EC;
56 // Using a fd_ostream instead of a fd_stream. The latter would be more
57 // efficient as the bitstream writer supports incremental flush to it, but the
58 // json scenario is for test, and file size scalability doesn't really concern
59 // us.
60 raw_fd_ostream Out(OutputFilename, EC);
61 if (EC)
62 return createStringError(EC, S: "failed to open output");
63
64 return llvm::createCtxProfFromYAML(Profile: BufOrError.get()->getBuffer(), Out);
65}
66
67Error convertToYaml() {
68 auto BufOrError = MemoryBuffer::getFileOrSTDIN(Filename: InputFilename);
69 if (!BufOrError)
70 return createFileError(F: InputFilename, EC: BufOrError.getError());
71
72 std::error_code EC;
73 raw_fd_ostream Out(OutputFilename, EC);
74 if (EC)
75 return createStringError(EC, S: "failed to open output");
76 PGOCtxProfileReader Reader(BufOrError.get()->getBuffer());
77 auto Prof = Reader.loadProfiles();
78 if (!Prof)
79 return Prof.takeError();
80 llvm::convertCtxProfToYaml(OS&: Out, Profile: *Prof);
81 Out << "\n";
82 return Error::success();
83}
84} // namespace
85
86int main(int argc, const char **argv) {
87 cl::ParseCommandLineOptions(argc, argv, Overview: "LLVM Contextual Profile Utils\n");
88 ExitOnError ExitOnErr("llvm-ctxprof-util: ");
89 auto HandleErr = [&](Error E) -> int {
90 if (E) {
91 handleAllErrors(E: std::move(E), Handlers: [&](const ErrorInfoBase &E) {
92 E.log(OS&: errs());
93 errs() << "\n";
94 });
95 return 1;
96 }
97 return 0;
98 };
99
100 if (FromYAML)
101 return HandleErr(convertFromYaml());
102
103 if (ToYAML)
104 return HandleErr(convertToYaml());
105
106 cl::PrintHelpMessage();
107 return 1;
108}
109