19bb55568SKyungwoo Lee //===-- llvm-cgdata.cpp - LLVM CodeGen Data Tool --------------------------===// 29bb55568SKyungwoo Lee // 39bb55568SKyungwoo Lee // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49bb55568SKyungwoo Lee // See https://llvm.org/LICENSE.txt for license information. 59bb55568SKyungwoo Lee // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69bb55568SKyungwoo Lee // 79bb55568SKyungwoo Lee //===----------------------------------------------------------------------===// 89bb55568SKyungwoo Lee // 99bb55568SKyungwoo Lee // llvm-cgdata parses raw codegen data embedded in compiled binary files, and 109bb55568SKyungwoo Lee // merges them into a single .cgdata file. It can also inspect and maninuplate 119bb55568SKyungwoo Lee // a .cgdata file. This .cgdata can contain various codegen data like outlining 129bb55568SKyungwoo Lee // information, and it can be used to optimize the code in the subsequent build. 139bb55568SKyungwoo Lee // 149bb55568SKyungwoo Lee //===----------------------------------------------------------------------===// 159bb55568SKyungwoo Lee #include "llvm/ADT/StringRef.h" 169bb55568SKyungwoo Lee #include "llvm/CGData/CodeGenDataReader.h" 179bb55568SKyungwoo Lee #include "llvm/CGData/CodeGenDataWriter.h" 189bb55568SKyungwoo Lee #include "llvm/IR/LLVMContext.h" 199bb55568SKyungwoo Lee #include "llvm/Object/Archive.h" 209bb55568SKyungwoo Lee #include "llvm/Object/Binary.h" 219bb55568SKyungwoo Lee #include "llvm/Option/ArgList.h" 229bb55568SKyungwoo Lee #include "llvm/Option/Option.h" 239bb55568SKyungwoo Lee #include "llvm/Support/CommandLine.h" 249bb55568SKyungwoo Lee #include "llvm/Support/LLVMDriver.h" 259bb55568SKyungwoo Lee #include "llvm/Support/Path.h" 269bb55568SKyungwoo Lee #include "llvm/Support/VirtualFileSystem.h" 279bb55568SKyungwoo Lee #include "llvm/Support/WithColor.h" 289bb55568SKyungwoo Lee #include "llvm/Support/raw_ostream.h" 299bb55568SKyungwoo Lee 309bb55568SKyungwoo Lee using namespace llvm; 319bb55568SKyungwoo Lee using namespace llvm::object; 329bb55568SKyungwoo Lee 339bb55568SKyungwoo Lee enum CGDataFormat { 349bb55568SKyungwoo Lee Invalid, 359bb55568SKyungwoo Lee Text, 369bb55568SKyungwoo Lee Binary, 379bb55568SKyungwoo Lee }; 389bb55568SKyungwoo Lee 399bb55568SKyungwoo Lee enum CGDataAction { 409bb55568SKyungwoo Lee Convert, 419bb55568SKyungwoo Lee Merge, 429bb55568SKyungwoo Lee Show, 439bb55568SKyungwoo Lee }; 449bb55568SKyungwoo Lee 459bb55568SKyungwoo Lee // Command-line option boilerplate. 469bb55568SKyungwoo Lee namespace { 479bb55568SKyungwoo Lee enum ID { 489bb55568SKyungwoo Lee OPT_INVALID = 0, // This is not an option ID. 499bb55568SKyungwoo Lee #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__), 509bb55568SKyungwoo Lee #include "Opts.inc" 519bb55568SKyungwoo Lee #undef OPTION 529bb55568SKyungwoo Lee }; 539bb55568SKyungwoo Lee 54dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE 559bb55568SKyungwoo Lee #include "Opts.inc" 56dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE 57dd647e3eSChandler Carruth 58dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE 59dd647e3eSChandler Carruth #include "Opts.inc" 60dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE 619bb55568SKyungwoo Lee 629bb55568SKyungwoo Lee using namespace llvm::opt; 639bb55568SKyungwoo Lee static constexpr opt::OptTable::Info InfoTable[] = { 649bb55568SKyungwoo Lee #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), 659bb55568SKyungwoo Lee #include "Opts.inc" 669bb55568SKyungwoo Lee #undef OPTION 679bb55568SKyungwoo Lee }; 689bb55568SKyungwoo Lee 699bb55568SKyungwoo Lee class CGDataOptTable : public opt::GenericOptTable { 709bb55568SKyungwoo Lee public: 71dd647e3eSChandler Carruth CGDataOptTable() 72dd647e3eSChandler Carruth : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} 739bb55568SKyungwoo Lee }; 749bb55568SKyungwoo Lee } // end anonymous namespace 759bb55568SKyungwoo Lee 769bb55568SKyungwoo Lee // Options 779bb55568SKyungwoo Lee static StringRef ToolName; 789bb55568SKyungwoo Lee static StringRef OutputFilename = "-"; 799bb55568SKyungwoo Lee static StringRef Filename; 809bb55568SKyungwoo Lee static bool ShowCGDataVersion; 81d23c5c2dSKyungwoo Lee static bool SkipTrim; 829bb55568SKyungwoo Lee static CGDataAction Action; 839bb55568SKyungwoo Lee static std::optional<CGDataFormat> OutputFormat; 849bb55568SKyungwoo Lee static std::vector<std::string> InputFilenames; 859bb55568SKyungwoo Lee 86*9cbd705eSAmr Hesham static void exitWithError(Twine Message, StringRef Whence = "", 87*9cbd705eSAmr Hesham StringRef Hint = "") { 889bb55568SKyungwoo Lee WithColor::error(); 899bb55568SKyungwoo Lee if (!Whence.empty()) 909bb55568SKyungwoo Lee errs() << Whence << ": "; 919bb55568SKyungwoo Lee errs() << Message << "\n"; 929bb55568SKyungwoo Lee if (!Hint.empty()) 939bb55568SKyungwoo Lee WithColor::note() << Hint << "\n"; 949bb55568SKyungwoo Lee ::exit(1); 959bb55568SKyungwoo Lee } 969bb55568SKyungwoo Lee 979bb55568SKyungwoo Lee static void exitWithError(Error E, StringRef Whence = "") { 989bb55568SKyungwoo Lee if (E.isA<CGDataError>()) { 999bb55568SKyungwoo Lee handleAllErrors(std::move(E), [&](const CGDataError &IPE) { 100*9cbd705eSAmr Hesham exitWithError(IPE.message(), Whence); 1019bb55568SKyungwoo Lee }); 1029bb55568SKyungwoo Lee return; 1039bb55568SKyungwoo Lee } 1049bb55568SKyungwoo Lee 105*9cbd705eSAmr Hesham exitWithError(toString(std::move(E)), Whence); 1069bb55568SKyungwoo Lee } 1079bb55568SKyungwoo Lee 1089bb55568SKyungwoo Lee static void exitWithErrorCode(std::error_code EC, StringRef Whence = "") { 109*9cbd705eSAmr Hesham exitWithError(EC.message(), Whence); 1109bb55568SKyungwoo Lee } 1119bb55568SKyungwoo Lee 1129bb55568SKyungwoo Lee static int convert_main(int argc, const char *argv[]) { 1139bb55568SKyungwoo Lee std::error_code EC; 1149bb55568SKyungwoo Lee raw_fd_ostream OS(OutputFilename, EC, 1159bb55568SKyungwoo Lee OutputFormat == CGDataFormat::Text 1169bb55568SKyungwoo Lee ? sys::fs::OF_TextWithCRLF 1179bb55568SKyungwoo Lee : sys::fs::OF_None); 1189bb55568SKyungwoo Lee if (EC) 1199bb55568SKyungwoo Lee exitWithErrorCode(EC, OutputFilename); 1209bb55568SKyungwoo Lee 1219bb55568SKyungwoo Lee auto FS = vfs::getRealFileSystem(); 1229bb55568SKyungwoo Lee auto ReaderOrErr = CodeGenDataReader::create(Filename, *FS); 1239bb55568SKyungwoo Lee if (Error E = ReaderOrErr.takeError()) 1249bb55568SKyungwoo Lee exitWithError(std::move(E), Filename); 1259bb55568SKyungwoo Lee 1269bb55568SKyungwoo Lee CodeGenDataWriter Writer; 1279bb55568SKyungwoo Lee auto Reader = ReaderOrErr->get(); 1289bb55568SKyungwoo Lee if (Reader->hasOutlinedHashTree()) { 1299bb55568SKyungwoo Lee OutlinedHashTreeRecord Record(Reader->releaseOutlinedHashTree()); 1309bb55568SKyungwoo Lee Writer.addRecord(Record); 1319bb55568SKyungwoo Lee } 132ffcf3c86SKyungwoo Lee if (Reader->hasStableFunctionMap()) { 133ffcf3c86SKyungwoo Lee StableFunctionMapRecord Record(Reader->releaseStableFunctionMap()); 134ffcf3c86SKyungwoo Lee Writer.addRecord(Record); 135ffcf3c86SKyungwoo Lee } 1369bb55568SKyungwoo Lee 1379bb55568SKyungwoo Lee if (OutputFormat == CGDataFormat::Text) { 1389bb55568SKyungwoo Lee if (Error E = Writer.writeText(OS)) 1399bb55568SKyungwoo Lee exitWithError(std::move(E)); 1409bb55568SKyungwoo Lee } else { 1419bb55568SKyungwoo Lee if (Error E = Writer.write(OS)) 1429bb55568SKyungwoo Lee exitWithError(std::move(E)); 1439bb55568SKyungwoo Lee } 1449bb55568SKyungwoo Lee 1459bb55568SKyungwoo Lee return 0; 1469bb55568SKyungwoo Lee } 1479bb55568SKyungwoo Lee 1489bb55568SKyungwoo Lee static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer, 149ffcf3c86SKyungwoo Lee OutlinedHashTreeRecord &GlobalOutlineRecord, 150ffcf3c86SKyungwoo Lee StableFunctionMapRecord &GlobalFunctionMapRecord); 1519bb55568SKyungwoo Lee 1529bb55568SKyungwoo Lee static bool handleArchive(StringRef Filename, Archive &Arch, 153ffcf3c86SKyungwoo Lee OutlinedHashTreeRecord &GlobalOutlineRecord, 154ffcf3c86SKyungwoo Lee StableFunctionMapRecord &GlobalFunctionMapRecord) { 1559bb55568SKyungwoo Lee bool Result = true; 1569bb55568SKyungwoo Lee Error Err = Error::success(); 1579bb55568SKyungwoo Lee for (const auto &Child : Arch.children(Err)) { 1589bb55568SKyungwoo Lee auto BuffOrErr = Child.getMemoryBufferRef(); 1599bb55568SKyungwoo Lee if (Error E = BuffOrErr.takeError()) 1609bb55568SKyungwoo Lee exitWithError(std::move(E), Filename); 1619bb55568SKyungwoo Lee auto NameOrErr = Child.getName(); 1629bb55568SKyungwoo Lee if (Error E = NameOrErr.takeError()) 1639bb55568SKyungwoo Lee exitWithError(std::move(E), Filename); 1649bb55568SKyungwoo Lee std::string Name = (Filename + "(" + NameOrErr.get() + ")").str(); 165ffcf3c86SKyungwoo Lee Result &= handleBuffer(Name, BuffOrErr.get(), GlobalOutlineRecord, 166ffcf3c86SKyungwoo Lee GlobalFunctionMapRecord); 1679bb55568SKyungwoo Lee } 1689bb55568SKyungwoo Lee if (Err) 1699bb55568SKyungwoo Lee exitWithError(std::move(Err), Filename); 1709bb55568SKyungwoo Lee return Result; 1719bb55568SKyungwoo Lee } 1729bb55568SKyungwoo Lee 1739bb55568SKyungwoo Lee static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer, 174ffcf3c86SKyungwoo Lee OutlinedHashTreeRecord &GlobalOutlineRecord, 175ffcf3c86SKyungwoo Lee StableFunctionMapRecord &GlobalFunctionMapRecord) { 1769bb55568SKyungwoo Lee Expected<std::unique_ptr<object::Binary>> BinOrErr = 1779bb55568SKyungwoo Lee object::createBinary(Buffer); 1789bb55568SKyungwoo Lee if (Error E = BinOrErr.takeError()) 1799bb55568SKyungwoo Lee exitWithError(std::move(E), Filename); 1809bb55568SKyungwoo Lee 1819bb55568SKyungwoo Lee bool Result = true; 1829bb55568SKyungwoo Lee if (auto *Obj = dyn_cast<ObjectFile>(BinOrErr->get())) { 183ffcf3c86SKyungwoo Lee if (Error E = CodeGenDataReader::mergeFromObjectFile( 184ffcf3c86SKyungwoo Lee Obj, GlobalOutlineRecord, GlobalFunctionMapRecord)) 1859bb55568SKyungwoo Lee exitWithError(std::move(E), Filename); 1869bb55568SKyungwoo Lee } else if (auto *Arch = dyn_cast<Archive>(BinOrErr->get())) { 187ffcf3c86SKyungwoo Lee Result &= handleArchive(Filename, *Arch, GlobalOutlineRecord, 188ffcf3c86SKyungwoo Lee GlobalFunctionMapRecord); 1899bb55568SKyungwoo Lee } else { 1909bb55568SKyungwoo Lee // TODO: Support for the MachO universal binary format. 1919bb55568SKyungwoo Lee errs() << "Error: unsupported binary file: " << Filename << "\n"; 1929bb55568SKyungwoo Lee Result = false; 1939bb55568SKyungwoo Lee } 1949bb55568SKyungwoo Lee 1959bb55568SKyungwoo Lee return Result; 1969bb55568SKyungwoo Lee } 1979bb55568SKyungwoo Lee 1989bb55568SKyungwoo Lee static bool handleFile(StringRef Filename, 199ffcf3c86SKyungwoo Lee OutlinedHashTreeRecord &GlobalOutlineRecord, 200ffcf3c86SKyungwoo Lee StableFunctionMapRecord &GlobalFunctionMapRecord) { 2019bb55568SKyungwoo Lee ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = 2029bb55568SKyungwoo Lee MemoryBuffer::getFileOrSTDIN(Filename); 2039bb55568SKyungwoo Lee if (std::error_code EC = BuffOrErr.getError()) 2049bb55568SKyungwoo Lee exitWithErrorCode(EC, Filename); 205ffcf3c86SKyungwoo Lee return handleBuffer(Filename, *BuffOrErr.get(), GlobalOutlineRecord, 206ffcf3c86SKyungwoo Lee GlobalFunctionMapRecord); 2079bb55568SKyungwoo Lee } 2089bb55568SKyungwoo Lee 2099bb55568SKyungwoo Lee static int merge_main(int argc, const char *argv[]) { 2109bb55568SKyungwoo Lee bool Result = true; 2119bb55568SKyungwoo Lee OutlinedHashTreeRecord GlobalOutlineRecord; 212ffcf3c86SKyungwoo Lee StableFunctionMapRecord GlobalFunctionMapRecord; 2139bb55568SKyungwoo Lee for (auto &Filename : InputFilenames) 214ffcf3c86SKyungwoo Lee Result &= 215ffcf3c86SKyungwoo Lee handleFile(Filename, GlobalOutlineRecord, GlobalFunctionMapRecord); 2169bb55568SKyungwoo Lee 2179bb55568SKyungwoo Lee if (!Result) 2189bb55568SKyungwoo Lee exitWithError("failed to merge codegen data files."); 2199bb55568SKyungwoo Lee 220d23c5c2dSKyungwoo Lee GlobalFunctionMapRecord.finalize(SkipTrim); 221ffcf3c86SKyungwoo Lee 2229bb55568SKyungwoo Lee CodeGenDataWriter Writer; 2239bb55568SKyungwoo Lee if (!GlobalOutlineRecord.empty()) 2249bb55568SKyungwoo Lee Writer.addRecord(GlobalOutlineRecord); 225ffcf3c86SKyungwoo Lee if (!GlobalFunctionMapRecord.empty()) 226ffcf3c86SKyungwoo Lee Writer.addRecord(GlobalFunctionMapRecord); 2279bb55568SKyungwoo Lee 2289bb55568SKyungwoo Lee std::error_code EC; 2299bb55568SKyungwoo Lee raw_fd_ostream OS(OutputFilename, EC, 2309bb55568SKyungwoo Lee OutputFormat == CGDataFormat::Text 2319bb55568SKyungwoo Lee ? sys::fs::OF_TextWithCRLF 2329bb55568SKyungwoo Lee : sys::fs::OF_None); 2339bb55568SKyungwoo Lee if (EC) 2349bb55568SKyungwoo Lee exitWithErrorCode(EC, OutputFilename); 2359bb55568SKyungwoo Lee 2369bb55568SKyungwoo Lee if (OutputFormat == CGDataFormat::Text) { 2379bb55568SKyungwoo Lee if (Error E = Writer.writeText(OS)) 2389bb55568SKyungwoo Lee exitWithError(std::move(E)); 2399bb55568SKyungwoo Lee } else { 2409bb55568SKyungwoo Lee if (Error E = Writer.write(OS)) 2419bb55568SKyungwoo Lee exitWithError(std::move(E)); 2429bb55568SKyungwoo Lee } 2439bb55568SKyungwoo Lee 2449bb55568SKyungwoo Lee return 0; 2459bb55568SKyungwoo Lee } 2469bb55568SKyungwoo Lee 2479bb55568SKyungwoo Lee static int show_main(int argc, const char *argv[]) { 2489bb55568SKyungwoo Lee std::error_code EC; 2499bb55568SKyungwoo Lee raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF); 2509bb55568SKyungwoo Lee if (EC) 2519bb55568SKyungwoo Lee exitWithErrorCode(EC, OutputFilename); 2529bb55568SKyungwoo Lee 2539bb55568SKyungwoo Lee auto FS = vfs::getRealFileSystem(); 2549bb55568SKyungwoo Lee auto ReaderOrErr = CodeGenDataReader::create(Filename, *FS); 2559bb55568SKyungwoo Lee if (Error E = ReaderOrErr.takeError()) 2569bb55568SKyungwoo Lee exitWithError(std::move(E), Filename); 2579bb55568SKyungwoo Lee 2589bb55568SKyungwoo Lee auto Reader = ReaderOrErr->get(); 2599bb55568SKyungwoo Lee if (ShowCGDataVersion) 2609bb55568SKyungwoo Lee OS << "Version: " << Reader->getVersion() << "\n"; 2619bb55568SKyungwoo Lee 2629bb55568SKyungwoo Lee if (Reader->hasOutlinedHashTree()) { 2639bb55568SKyungwoo Lee auto Tree = Reader->releaseOutlinedHashTree(); 2649bb55568SKyungwoo Lee OS << "Outlined hash tree:\n"; 2659bb55568SKyungwoo Lee OS << " Total Node Count: " << Tree->size() << "\n"; 2669bb55568SKyungwoo Lee OS << " Terminal Node Count: " << Tree->size(/*GetTerminalCountOnly=*/true) 2679bb55568SKyungwoo Lee << "\n"; 2689bb55568SKyungwoo Lee OS << " Depth: " << Tree->depth() << "\n"; 2699bb55568SKyungwoo Lee } 270ffcf3c86SKyungwoo Lee if (Reader->hasStableFunctionMap()) { 271ffcf3c86SKyungwoo Lee auto Map = Reader->releaseStableFunctionMap(); 272ffcf3c86SKyungwoo Lee OS << "Stable function map:\n"; 273ffcf3c86SKyungwoo Lee OS << " Unique hash Count: " << Map->size() << "\n"; 274ffcf3c86SKyungwoo Lee OS << " Total function Count: " 275ffcf3c86SKyungwoo Lee << Map->size(StableFunctionMap::TotalFunctionCount) << "\n"; 276ffcf3c86SKyungwoo Lee OS << " Mergeable function Count: " 277ffcf3c86SKyungwoo Lee << Map->size(StableFunctionMap::MergeableFunctionCount) << "\n"; 278ffcf3c86SKyungwoo Lee } 2799bb55568SKyungwoo Lee 2809bb55568SKyungwoo Lee return 0; 2819bb55568SKyungwoo Lee } 2829bb55568SKyungwoo Lee 2839bb55568SKyungwoo Lee static void parseArgs(int argc, char **argv) { 2849bb55568SKyungwoo Lee CGDataOptTable Tbl; 2859bb55568SKyungwoo Lee ToolName = argv[0]; 2869bb55568SKyungwoo Lee llvm::BumpPtrAllocator A; 2879bb55568SKyungwoo Lee llvm::StringSaver Saver{A}; 2889bb55568SKyungwoo Lee llvm::opt::InputArgList Args = 2899bb55568SKyungwoo Lee Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) { 2909bb55568SKyungwoo Lee llvm::errs() << Msg << '\n'; 2919bb55568SKyungwoo Lee std::exit(1); 2929bb55568SKyungwoo Lee }); 2939bb55568SKyungwoo Lee 2949bb55568SKyungwoo Lee if (Args.hasArg(OPT_help)) { 2959bb55568SKyungwoo Lee Tbl.printHelp( 2969bb55568SKyungwoo Lee llvm::outs(), 2979bb55568SKyungwoo Lee "llvm-cgdata <action> [options] (<binary files>|<.cgdata file>)", 2989bb55568SKyungwoo Lee ToolName.str().c_str()); 2999bb55568SKyungwoo Lee std::exit(0); 3009bb55568SKyungwoo Lee } 3019bb55568SKyungwoo Lee if (Args.hasArg(OPT_version)) { 3029bb55568SKyungwoo Lee cl::PrintVersionMessage(); 3039bb55568SKyungwoo Lee std::exit(0); 3049bb55568SKyungwoo Lee } 3059bb55568SKyungwoo Lee 3069bb55568SKyungwoo Lee ShowCGDataVersion = Args.hasArg(OPT_cgdata_version); 307d23c5c2dSKyungwoo Lee SkipTrim = Args.hasArg(OPT_skip_trim); 3089bb55568SKyungwoo Lee 3099bb55568SKyungwoo Lee if (opt::Arg *A = Args.getLastArg(OPT_format)) { 3109bb55568SKyungwoo Lee StringRef OF = A->getValue(); 3119bb55568SKyungwoo Lee OutputFormat = StringSwitch<CGDataFormat>(OF) 3129bb55568SKyungwoo Lee .Case("text", CGDataFormat::Text) 3139bb55568SKyungwoo Lee .Case("binary", CGDataFormat::Binary) 3149bb55568SKyungwoo Lee .Default(CGDataFormat::Invalid); 3159bb55568SKyungwoo Lee if (OutputFormat == CGDataFormat::Invalid) 3169bb55568SKyungwoo Lee exitWithError("unsupported format '" + OF + "'"); 3179bb55568SKyungwoo Lee } 3189bb55568SKyungwoo Lee 3199bb55568SKyungwoo Lee InputFilenames = Args.getAllArgValues(OPT_INPUT); 3209bb55568SKyungwoo Lee if (InputFilenames.empty()) 3219bb55568SKyungwoo Lee exitWithError("No input file is specified."); 3229bb55568SKyungwoo Lee Filename = InputFilenames[0]; 3239bb55568SKyungwoo Lee 3249bb55568SKyungwoo Lee if (Args.hasArg(OPT_output)) { 3259bb55568SKyungwoo Lee OutputFilename = Args.getLastArgValue(OPT_output); 3269bb55568SKyungwoo Lee for (auto &Filename : InputFilenames) 3279bb55568SKyungwoo Lee if (Filename == OutputFilename) 3289bb55568SKyungwoo Lee exitWithError( 3299bb55568SKyungwoo Lee "Input file name cannot be the same as the output file name!\n"); 3309bb55568SKyungwoo Lee } 3319bb55568SKyungwoo Lee 3329bb55568SKyungwoo Lee opt::Arg *ActionArg = nullptr; 3339bb55568SKyungwoo Lee for (opt::Arg *Arg : Args.filtered(OPT_action_group)) { 3349bb55568SKyungwoo Lee if (ActionArg) 3359bb55568SKyungwoo Lee exitWithError("Only one action is allowed."); 3369bb55568SKyungwoo Lee ActionArg = Arg; 3379bb55568SKyungwoo Lee } 3389bb55568SKyungwoo Lee if (!ActionArg) 3399bb55568SKyungwoo Lee exitWithError("One action is required."); 3409bb55568SKyungwoo Lee 3419bb55568SKyungwoo Lee switch (ActionArg->getOption().getID()) { 3429bb55568SKyungwoo Lee case OPT_show: 3439bb55568SKyungwoo Lee if (InputFilenames.size() != 1) 3449bb55568SKyungwoo Lee exitWithError("only one input file is allowed."); 3459bb55568SKyungwoo Lee Action = CGDataAction::Show; 3469bb55568SKyungwoo Lee break; 3479bb55568SKyungwoo Lee case OPT_convert: 3489bb55568SKyungwoo Lee // The default output format is text for convert. 3499bb55568SKyungwoo Lee if (!OutputFormat) 3509bb55568SKyungwoo Lee OutputFormat = CGDataFormat::Text; 3519bb55568SKyungwoo Lee if (InputFilenames.size() != 1) 3529bb55568SKyungwoo Lee exitWithError("only one input file is allowed."); 3539bb55568SKyungwoo Lee Action = CGDataAction::Convert; 3549bb55568SKyungwoo Lee break; 3559bb55568SKyungwoo Lee case OPT_merge: 3569bb55568SKyungwoo Lee // The default output format is binary for merge. 3579bb55568SKyungwoo Lee if (!OutputFormat) 3589bb55568SKyungwoo Lee OutputFormat = CGDataFormat::Binary; 3599bb55568SKyungwoo Lee Action = CGDataAction::Merge; 3609bb55568SKyungwoo Lee break; 3619bb55568SKyungwoo Lee default: 3629bb55568SKyungwoo Lee llvm_unreachable("unrecognized action"); 3639bb55568SKyungwoo Lee } 3649bb55568SKyungwoo Lee } 3659bb55568SKyungwoo Lee 3669bb55568SKyungwoo Lee int llvm_cgdata_main(int argc, char **argvNonConst, const llvm::ToolContext &) { 3679bb55568SKyungwoo Lee const char **argv = const_cast<const char **>(argvNonConst); 3689bb55568SKyungwoo Lee parseArgs(argc, argvNonConst); 3699bb55568SKyungwoo Lee 3709bb55568SKyungwoo Lee switch (Action) { 3719bb55568SKyungwoo Lee case CGDataAction::Convert: 3729bb55568SKyungwoo Lee return convert_main(argc, argv); 3739bb55568SKyungwoo Lee case CGDataAction::Merge: 3749bb55568SKyungwoo Lee return merge_main(argc, argv); 3759bb55568SKyungwoo Lee case CGDataAction::Show: 3769bb55568SKyungwoo Lee return show_main(argc, argv); 3779bb55568SKyungwoo Lee } 3789bb55568SKyungwoo Lee 379723a9b87SJie Fu llvm_unreachable("unrecognized action"); 3809bb55568SKyungwoo Lee } 381