mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 07:31:28 +00:00
[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
This commit is contained in:
parent
214f63b272
commit
47db32e542
@ -125,10 +125,6 @@ OPTIONS
|
||||
|
||||
Display a summary of command line options.
|
||||
|
||||
.. option:: --help-list
|
||||
|
||||
Display an uncategorized summary of command line options.
|
||||
|
||||
.. option:: -m
|
||||
|
||||
Equivalent to :option:`--format` with a value of ``darwin``.
|
||||
|
@ -1,15 +1,10 @@
|
||||
## Show that help text is printed correctly when requested.
|
||||
|
||||
RUN: llvm-size -h | FileCheck %s --check-prefixes=CHECK,CATEG
|
||||
RUN: llvm-size --help | FileCheck %s --check-prefixes=CHECK,CATEG
|
||||
RUN: llvm-size --help-list \
|
||||
RUN: | FileCheck %s --check-prefixes=CHECK,LIST
|
||||
RUN: llvm-size -h | FileCheck %s
|
||||
RUN: llvm-size --help | FileCheck %s
|
||||
|
||||
CHECK: OVERVIEW: llvm object size dumper
|
||||
CHECK: USAGE: llvm-size{{(.exe)?}} [options] <input files>{{$}}
|
||||
CHECK: OVERVIEW: LLVM object size dumper
|
||||
CHECK: USAGE: {{.*}}llvm-size{{(.exe)?}} [options] <input object files>{{$}}
|
||||
CHECK: OPTIONS:
|
||||
CATEG: Generic Options:
|
||||
LIST-NOT: Generic Options:
|
||||
CATEG: llvm-size Options:
|
||||
LIST-NOT: llvm-size Options:
|
||||
CHECK: OPTIONS (Mach-O specific):
|
||||
CHECK: @FILE
|
||||
|
@ -121,7 +121,7 @@
|
||||
# RUN: not llvm-size %t1.o --radix=bad 2>&1 \
|
||||
# RUN: | FileCheck %s --check-prefix=BAD-VAL -DNUM=bad
|
||||
|
||||
# BAD-VAL: {{.*}}llvm-size{{.*}}: for the --radix option: Cannot find option named '[[NUM]]'!
|
||||
# BAD-VAL: {{.*}}llvm-size{{.*}}: error: --radix value should be one of: 8, 10, 16
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
|
@ -1,4 +1,4 @@
|
||||
## Show that the an error is emitted if an unknown value is passed to --format.
|
||||
|
||||
# RUN: not llvm-size --format=unknown 2>&1 | FileCheck %s
|
||||
# CHECK: {{.*}}llvm-size{{.*}}: for the --format option: Cannot find option named 'unknown'!
|
||||
# CHECK: {{.*}}llvm-size{{.*}}: error: --format value should be one of: 'berkeley', 'darwin', 'sysv'
|
||||
|
@ -1,10 +1,17 @@
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
Object
|
||||
Option
|
||||
Support
|
||||
)
|
||||
|
||||
set(LLVM_TARGET_DEFINITIONS Opts.td)
|
||||
tablegen(LLVM Opts.inc -gen-opt-parser-defs)
|
||||
add_public_tablegen_target(SizeOptsTableGen)
|
||||
|
||||
add_llvm_tool(llvm-size
|
||||
llvm-size.cpp
|
||||
DEPENDS
|
||||
SizeOptsTableGen
|
||||
)
|
||||
|
||||
if(LLVM_INSTALL_BINUTILS_SYMLINKS)
|
||||
|
32
llvm/tools/llvm-size/Opts.td
Normal file
32
llvm/tools/llvm-size/Opts.td
Normal file
@ -0,0 +1,32 @@
|
||||
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"]>;
|
@ -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));
|
||||
enum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 };
|
||||
} // namespace
|
||||
|
||||
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));
|
||||
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();
|
||||
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;
|
||||
}
|
||||
|
||||
for (StringRef Arch : ArchFlags) {
|
||||
if (Arch == "all") {
|
||||
ArchAll = true;
|
||||
} else {
|
||||
if (!MachOObjectFile::isValidArch(Arch)) {
|
||||
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");
|
||||
|
||||
|
@ -1,6 +1,12 @@
|
||||
import("//llvm/tools/binutils_symlinks.gni")
|
||||
import("//llvm/utils/TableGen/tablegen.gni")
|
||||
import("//llvm/utils/gn/build/symlink_or_copy.gni")
|
||||
|
||||
tablegen("Opts") {
|
||||
visibility = [ ":llvm-size" ]
|
||||
args = [ "-gen-opt-parser-defs" ]
|
||||
}
|
||||
|
||||
if (llvm_install_binutils_symlinks) {
|
||||
symlink_or_copy("size") {
|
||||
deps = [ ":llvm-size" ]
|
||||
@ -19,7 +25,9 @@ group("symlinks") {
|
||||
|
||||
executable("llvm-size") {
|
||||
deps = [
|
||||
":Opts",
|
||||
"//llvm/lib/Object",
|
||||
"//llvm/lib/Option",
|
||||
"//llvm/lib/Support",
|
||||
]
|
||||
sources = [ "llvm-size.cpp" ]
|
||||
|
@ -3448,6 +3448,18 @@ cc_binary(
|
||||
],
|
||||
)
|
||||
|
||||
gentbl(
|
||||
name = "SizeOptsTableGen",
|
||||
strip_include_prefix = "tools/llvm-size",
|
||||
tbl_outs = [(
|
||||
"-gen-opt-parser-defs",
|
||||
"tools/llvm-size/Opts.inc",
|
||||
)],
|
||||
tblgen = ":llvm-tblgen",
|
||||
td_file = "tools/llvm-size/Opts.td",
|
||||
td_srcs = ["include/llvm/Option/OptParser.td"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "llvm-size",
|
||||
srcs = glob([
|
||||
@ -3458,6 +3470,8 @@ cc_binary(
|
||||
stamp = 0,
|
||||
deps = [
|
||||
":Object",
|
||||
":Option",
|
||||
":SizeOptsTableGen",
|
||||
":Support",
|
||||
],
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user