--- /dev/null
+include "llvm/Option/OptParser.td"
+
+class F<string letter, string help> : Flag<["-"], letter>, HelpText<help>;
+class FF<string name, string help> : Flag<["--"], name>, HelpText<help>;
+
+multiclass Eq<string name, string help> {
+ def NAME #_EQ : Joined<["--"], name #"=">,
+ HelpText<help>;
+ def : Separate<["--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+}
+
+def common : FF<"common", "Print common symbols in the ELF file. When using Berkeley format, this is added to bss">;
+defm format : Eq<"format", "Specify output format">;
+def help : FF<"help", "Display this help">;
+defm radix : Eq<"radix", "Print size in radix">;
+def totals : FF<"totals", "Print totals of all objects - Berkeley format only">;
+def version : FF<"version", "Display the version">;
+
+// Mach-O specific options.
+def grp_mach_o : OptionGroup<"kind">, HelpText<"OPTIONS (Mach-O specific)">;
+def arch_EQ : Joined<["--"], "arch=">, HelpText<"architecture(s) from a Mach-O file to dump">, Group<grp_mach_o>;
+def : Separate<["--", "-"], "arch">, Alias<arch_EQ>;
+def l : F<"l", "When format is darwin, use long format to include addresses and offsets">, Group<grp_mach_o>;
+
+def : F<"A", "Alias for --format">, Alias<format_EQ>, AliasArgs<["sysv"]>;
+def : F<"B", "Alias for --format">, Alias<format_EQ>, AliasArgs<["berkeley"]>;
+def : F<"d", "Alias for --radix=10">, Alias<radix_EQ>, AliasArgs<["10"]>;
+def : F<"h", "Alias for --help">, Alias<help>;
+def : F<"m", "Alias for --format">, Alias<format_EQ>, AliasArgs<["darwin"]>;
+def : F<"o", "Alias for --radix=8">, Alias<radix_EQ>, AliasArgs<["8"]>;
+def : F<"t", "Alias for --totals">, Alias<totals>;
+def : F<"x", "Alias for --radix=16">, Alias<radix_EQ>, AliasArgs<["16"]>;
#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"
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;
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:
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");