diff options
author | Fangrui Song <i@maskray.me> | 2021-07-09 10:26:53 -0700 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2021-07-09 10:26:53 -0700 |
commit | 47db32e542eb84ca9d4bed798bbdfd40200ac1ef (patch) | |
tree | 8517a49741d5403e3488773b40d0d0fa8269a3cc /llvm/tools/llvm-size/llvm-size.cpp | |
parent | 214f63b2729d06f8d071f0fe86a8649ba880046c (diff) | |
download | llvm-47db32e542eb84ca9d4bed798bbdfd40200ac1ef.zip llvm-47db32e542eb84ca9d4bed798bbdfd40200ac1ef.tar.gz llvm-47db32e542eb84ca9d4bed798bbdfd40200ac1ef.tar.bz2 |
[llvm-size] Switch command line parsing from llvm::cl to OptTable
Part of https://lists.llvm.org/pipermail/llvm-dev/2021-July/151622.html
"Binary utilities: switch command line parsing from llvm::cl to OptTable"
* `--totals=false` and `--totals=0` cannot be used. Omit the option.
* `--help-list` is removed. This is a `cl::` specific option.
OptTable avoids global option collision if we decide to support multiplexing for binary utilities.
Note: because the tool is simple, and its long options are uncommon, I just drop
the one-dash forms except `-arch <value>` (Darwin style).
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D105598
Diffstat (limited to 'llvm/tools/llvm-size/llvm-size.cpp')
-rw-r--r-- | llvm/tools/llvm-size/llvm-size.cpp | 189 |
1 files changed, 109 insertions, 80 deletions
diff --git a/llvm/tools/llvm-size/llvm-size.cpp b/llvm/tools/llvm-size/llvm-size.cpp index 4f98a4c..ec9a4cd 100644 --- a/llvm/tools/llvm-size/llvm-size.cpp +++ b/llvm/tools/llvm-size/llvm-size.cpp @@ -18,6 +18,9 @@ #include "llvm/Object/MachO.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -33,23 +36,56 @@ using namespace llvm; using namespace object; -cl::OptionCategory SizeCat("llvm-size Options"); +namespace { +using namespace llvm::opt; // for HelpHidden in Opts.inc +enum ID { + OPT_INVALID = 0, // This is not an option ID. +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + OPT_##ID, +#include "Opts.inc" +#undef OPTION +}; + +#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; +#include "Opts.inc" +#undef PREFIX + +const opt::OptTable::Info InfoTable[] = { +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + { \ + PREFIX, NAME, HELPTEXT, \ + METAVAR, OPT_##ID, opt::Option::KIND##Class, \ + PARAM, FLAGS, OPT_##GROUP, \ + OPT_##ALIAS, ALIASARGS, VALUES}, +#include "Opts.inc" +#undef OPTION +}; + +class SizeOptTable : public opt::OptTable { +public: + SizeOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); } +}; enum OutputFormatTy { berkeley, sysv, darwin }; -static cl::opt<OutputFormatTy> - OutputFormat("format", cl::desc("Specify output format"), - cl::values(clEnumVal(sysv, "System V format"), - clEnumVal(berkeley, "Berkeley format"), - clEnumVal(darwin, "Darwin -m format")), - cl::init(berkeley), cl::cat(SizeCat)); - -static cl::opt<OutputFormatTy> - OutputFormatShort(cl::desc("Specify output format"), - cl::values(clEnumValN(sysv, "A", "System V format"), - clEnumValN(berkeley, "B", "Berkeley format"), - clEnumValN(darwin, "m", "Darwin -m format")), - cl::init(berkeley), cl::cat(SizeCat)); +enum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 }; +} // namespace + +static bool ArchAll = false; +static std::vector<StringRef> ArchFlags; +static bool ELFCommons; +static OutputFormatTy OutputFormat; +static bool DarwinLongFormat; +static RadixTy Radix; +static bool TotalSizes; + +static std::vector<std::string> InputFilenames; + +static std::string ToolName; +// States +static bool HadError = false; static bool BerkeleyHeaderPrinted = false; static bool MoreThanOneFile = false; static uint64_t TotalObjectText = 0; @@ -57,59 +93,13 @@ static uint64_t TotalObjectData = 0; static uint64_t TotalObjectBss = 0; static uint64_t TotalObjectTotal = 0; -cl::opt<bool> - DarwinLongFormat("l", - cl::desc("When format is darwin, use long format " - "to include addresses and offsets."), - cl::cat(SizeCat)); - -cl::opt<bool> - ELFCommons("common", - cl::desc("Print common symbols in the ELF file. When using " - "Berkeley format, this is added to bss."), - cl::init(false), cl::cat(SizeCat)); - -static cl::list<std::string> - ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), - cl::ZeroOrMore, cl::cat(SizeCat)); -static bool ArchAll = false; - -enum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 }; -static cl::opt<RadixTy> Radix( - "radix", cl::desc("Print size in radix"), cl::init(decimal), - cl::values(clEnumValN(octal, "8", "Print size in octal"), - clEnumValN(decimal, "10", "Print size in decimal"), - clEnumValN(hexadecimal, "16", "Print size in hexadecimal")), - cl::cat(SizeCat)); - -static cl::opt<RadixTy> RadixShort( - cl::desc("Print size in radix:"), - cl::values(clEnumValN(octal, "o", "Print size in octal"), - clEnumValN(decimal, "d", "Print size in decimal"), - clEnumValN(hexadecimal, "x", "Print size in hexadecimal")), - cl::init(decimal), cl::cat(SizeCat)); - -static cl::opt<bool> - TotalSizes("totals", - cl::desc("Print totals of all objects - Berkeley format only"), - cl::init(false), cl::cat(SizeCat)); - -static cl::alias TotalSizesShort("t", cl::desc("Short for --totals"), - cl::aliasopt(TotalSizes)); - -static cl::list<std::string> - InputFilenames(cl::Positional, cl::desc("<input files>"), cl::ZeroOrMore); - -static cl::extrahelp - HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); - -static bool HadError = false; - -static std::string ToolName; - -static void error(const Twine &Message, StringRef File) { +static void error(const Twine &Message, StringRef File = "") { HadError = true; - WithColor::error(errs(), ToolName) << "'" << File << "': " << Message << "\n"; + if (File.empty()) + WithColor::error(errs(), ToolName) << Message << '\n'; + else + WithColor::error(errs(), ToolName) + << "'" << File << "': " << Message << '\n'; } // This version of error() prints the archive name and member name, for example: @@ -874,27 +864,66 @@ static void printBerkeleyTotals() { int main(int argc, char **argv) { InitLLVM X(argc, argv); - cl::HideUnrelatedOptions(SizeCat); - cl::ParseCommandLineOptions(argc, argv, "llvm object size dumper\n"); - + BumpPtrAllocator A; + StringSaver Saver(A); + SizeOptTable Tbl; ToolName = argv[0]; - if (OutputFormatShort.getNumOccurrences()) - OutputFormat = static_cast<OutputFormatTy>(OutputFormatShort); - if (RadixShort.getNumOccurrences()) - Radix = RadixShort.getValue(); - - for (StringRef Arch : ArchFlags) { - if (Arch == "all") { - ArchAll = true; - } else { - if (!MachOObjectFile::isValidArch(Arch)) { + opt::InputArgList Args = Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, + [&](StringRef Msg) { error(Msg); }); + if (Args.hasArg(OPT_help)) { + Tbl.printHelp( + outs(), + (Twine(ToolName) + " [options] <input object files>").str().c_str(), + "LLVM object size dumper"); + // TODO Replace this with OptTable API once it adds extrahelp support. + outs() << "\nPass @FILE as argument to read options from FILE.\n"; + return 0; + } + if (Args.hasArg(OPT_version)) { + outs() << ToolName << '\n'; + cl::PrintVersionMessage(); + return 0; + } + + ELFCommons = Args.hasArg(OPT_common); + DarwinLongFormat = Args.hasArg(OPT_l); + TotalSizes = Args.hasArg(OPT_totals); + StringRef V = Args.getLastArgValue(OPT_format_EQ, "berkeley"); + if (V == "berkeley") + OutputFormat = berkeley; + else if (V == "darwin") + OutputFormat = darwin; + else if (V == "sysv") + OutputFormat = sysv; + else + error("--format value should be one of: 'berkeley', 'darwin', 'sysv'"); + V = Args.getLastArgValue(OPT_radix_EQ, "10"); + if (V == "8") + Radix = RadixTy::octal; + else if (V == "10") + Radix = RadixTy::decimal; + else if (V == "16") + Radix = RadixTy::hexadecimal; + else + error("--radix value should be one of: 8, 10, 16 "); + + for (const auto *A : Args.filtered(OPT_arch_EQ)) { + SmallVector<StringRef, 2> Values; + llvm::SplitString(A->getValue(), Values, ","); + for (StringRef V : Values) { + if (V == "all") + ArchAll = true; + else if (MachOObjectFile::isValidArch(V)) + ArchFlags.push_back(V); + else { outs() << ToolName << ": for the -arch option: Unknown architecture " - << "named '" << Arch << "'"; + << "named '" << V << "'"; return 1; } } } + InputFilenames = Args.getAllArgValues(OPT_INPUT); if (InputFilenames.empty()) InputFilenames.push_back("a.out"); |