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