[llvm] cae3b83 - [llvm-nm] Switch command line parsing from llvm::cl to OptTable

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 7 13:34:42 PDT 2021


Author: Fangrui Song
Date: 2021-07-07T13:34:33-07:00
New Revision: cae3b831f4304d4487dd7c767ff88face51ea0dc

URL: https://github.com/llvm/llvm-project/commit/cae3b831f4304d4487dd7c767ff88face51ea0dc
DIFF: https://github.com/llvm/llvm-project/commit/cae3b831f4304d4487dd7c767ff88face51ea0dc.diff

LOG: [llvm-nm] 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"

Users should generally observe no difference as long as they only use intended
option forms. Behavior changes:

* `-t=d` is removed. Use `-t d` instead.
* `--demangle=0` cannot be used. Omit the option or use `--no-demangle` instead.
* `--help-list` is removed. This is a `cl::` specific option.

Note:

* `-t` diagnostic gets improved.
* This patch avoids cl::opt collision if we decide to support multiplexing for binary utilities
* One-dash long options are still supported.
* The `-s` collision (`-s segment section` for Mach-O) is unfortunate. `-s` means `--print-armap` in GNU nm.
* This patch removes the last `cl::multi_val` use case from the `llvm/lib/Support/CommandLine.cpp` library

`-M` (`--print-armap`), `-U` (`--defined-only`), and `-W` (`--no-weak`)
are now deprecated. They could conflict with future GNU nm options.
(--print-armap has an existing alias -s, so GNU will unlikely add a new one.
--no-weak (not in GNU nm) is rarely used anyway.)

`--just-symbol-name` is now deprecated in favor of
`--format=just-symbols` and `-j`.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D105330

Added: 
    llvm/tools/llvm-nm/Opts.td

Modified: 
    llvm/docs/CommandGuide/llvm-nm.rst
    llvm/docs/ReleaseNotes.rst
    llvm/test/Object/nm-universal-binary.test
    llvm/test/tools/llvm-nm/X86/radix.s
    llvm/test/tools/llvm-nm/format-bsd.test
    llvm/test/tools/llvm-nm/format-sysv-layout.test
    llvm/test/tools/llvm-nm/help.test
    llvm/test/tools/llvm-nm/just-symbols.test
    llvm/test/tools/llvm-nm/libtool-version.test
    llvm/tools/llvm-nm/CMakeLists.txt
    llvm/tools/llvm-nm/llvm-nm.cpp
    llvm/utils/gn/secondary/llvm/tools/llvm-nm/BUILD.gn
    utils/bazel/llvm-project-overlay/llvm/BUILD.bazel

Removed: 
    


################################################################################
diff  --git a/llvm/docs/CommandGuide/llvm-nm.rst b/llvm/docs/CommandGuide/llvm-nm.rst
index cdb1fd3c24928..e2d96c8220df0 100644
--- a/llvm/docs/CommandGuide/llvm-nm.rst
+++ b/llvm/docs/CommandGuide/llvm-nm.rst
@@ -130,7 +130,7 @@ OPTIONS
 
  Show all symbols, even those usually suppressed.
 
-.. option:: --defined-only, -U
+.. option:: --defined-only
 
  Print only symbols defined in this file.
 
@@ -157,11 +157,7 @@ OPTIONS
 
  Print a summary of command-line options and their meanings.
 
-.. option:: --help-list
-
- Print an uncategorized summary of command-line options and their meanings.
-
-.. option:: --just-symbol-name, -j
+.. option:: -j
 
  Print just the symbol names. Alias for `--format=just-symbols``.
 
@@ -181,7 +177,7 @@ OPTIONS
 
  Show symbols in the order encountered.
 
-.. option:: --no-weak, -W
+.. option:: --no-weak
 
  Don't print weak symbols.
 
@@ -193,7 +189,7 @@ OPTIONS
 
  Use POSIX.2 output format.  Alias for ``--format=posix``.
 
-.. option:: --print-armap, -M
+.. option:: --print-armap
 
  Print the archive symbol table, in addition to the symbols.
 
@@ -235,10 +231,6 @@ OPTIONS
  Display the version of the :program:`llvm-nm` executable, then exit. Does not
  stack with other commands.
 
-.. option:: --without-aliases
-
- Exclude aliases from the output.
-
 .. option:: @<FILE>
 
  Read command-line options from response file `<FILE>`.
@@ -267,7 +259,7 @@ MACH-O SPECIFIC OPTIONS
 
  Do not add any symbols from the dyldinfo.
 
-.. option:: -s=<segment section>
+.. option:: -s <segment> <section>
 
  Dump only symbols from this segment and section name.
 

diff  --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 3a18d36670108..3e6ecf5541a69 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -169,6 +169,13 @@ Changes to the LLVM tools
   ``--section-details`` respectively, to match llvm-readelf.
   (`D105055 <https://reviews.llvm.org/D105055>`_)
 
+* The llvm-nm short aliases ``-M`` (``--print-armap``), ``-U``
+  (``--defined-only``), and ``-W`` (``--no-weak``) are now deprecated.
+  Use the long form versions instead.
+  The alias ``--just-symbol-name`` is now deprecated in favor of
+  ``--format=just-symbols`` and ``-j``.
+  (`D105330 <https://reviews.llvm.org/D105330>`_)
+
 Changes to LLDB
 ---------------------------------
 

diff  --git a/llvm/test/Object/nm-universal-binary.test b/llvm/test/Object/nm-universal-binary.test
index f3da50d3de5c2..379f8cdc776dd 100644
--- a/llvm/test/Object/nm-universal-binary.test
+++ b/llvm/test/Object/nm-universal-binary.test
@@ -5,9 +5,9 @@ RUN:         | FileCheck %s -check-prefix CHECK-64-OBJ
 RUN: llvm-nm --arch=x86_64 %p/Inputs/macho-universal.x86_64.i386 \
 RUN:         | FileCheck %s -check-prefix CHECK-OBJ-x86_64
 RUN: not llvm-nm --arch=armv7m %p/Inputs/macho-universal.x86_64.i386 2>&1 \
-RUN:         | FileCheck %s -check-prefix CHECK-OBJ-armv7m
+RUN:         | FileCheck %s --check-prefix=CHECK-OBJ-armv7m --implicit-check-not=error:
 RUN: not llvm-nm --arch=foobar %p/Inputs/macho-universal.x86_64.i386 2>&1 \
-RUN:         | FileCheck %s -check-prefix CHECK-OBJ-foobar
+RUN:         | FileCheck %s --check-prefix=CHECK-OBJ-foobar --implicit-check-not=error:
 RUN: llvm-nm --arch=all %p/Inputs/macho-universal-archive.x86_64.i386 \
 RUN:         | FileCheck %s -check-prefix CHECK-AR
 RUN: llvm-nm --arch=all %p/Inputs/macho-universal64-archive.x86_64.i386 \
@@ -31,11 +31,9 @@ CHECK-OBJ-x86_64: 0000000100000000 T __mh_execute_header
 CHECK-OBJ-x86_64: 0000000100000f60 T _main
 CHECK-OBJ-x86_64:                  U dyld_stub_binder
 
-CHECK-OBJ-armv7m-NOT: Unknown architecture named
-CHECK-OBJ-armv7m: does not contain architecture
+CHECK-OBJ-armv7m: error: file: {{.*}} does not contain architecture
 
-CHECK-OBJ-foobar: Unknown architecture named
-CHECK-OBJ-foobar: does not contain architecture
+CHECK-OBJ-foobar: error: for the --arch option: Unknown architecture named 'foobar'
 
 CHECK-AR: macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64):
 CHECK-AR: 0000000000000068 s EH_frame0

diff  --git a/llvm/test/tools/llvm-nm/X86/radix.s b/llvm/test/tools/llvm-nm/X86/radix.s
index 1f05458ab32ec..b8de169e9ecdc 100644
--- a/llvm/test/tools/llvm-nm/X86/radix.s
+++ b/llvm/test/tools/llvm-nm/X86/radix.s
@@ -2,7 +2,8 @@
 // RUN: llvm-mc %s -filetype=obj -triple=x86_64-pc-linux -o %t.o
 // RUN: llvm-nm --radix=d %t.o | FileCheck %s
 // RUN: llvm-nm --radix=o %t.o | FileCheck --check-prefix=OCTAL %s
-// RUN: llvm-nm -t=x %t.o | FileCheck --check-prefix=HEX %s
+// RUN: llvm-nm -tx %t.o | FileCheck --check-prefix=HEX %s
+// RUN: llvm-nm -t x %t.o | FileCheck --check-prefix=HEX %s
 
 	.text
 	.file	"1.c"

diff  --git a/llvm/test/tools/llvm-nm/format-bsd.test b/llvm/test/tools/llvm-nm/format-bsd.test
index d04ecdc4b25e0..8891b59405fd2 100644
--- a/llvm/test/tools/llvm-nm/format-bsd.test
+++ b/llvm/test/tools/llvm-nm/format-bsd.test
@@ -3,7 +3,7 @@
 
 # RUN: yaml2obj %s -o %t.o
 # RUN: llvm-nm %t.o --format=bsd > %t.formatbsd.txt
-# RUN: llvm-nm %t.o -f=bsd > %t.fbsd.txt
+# RUN: llvm-nm %t.o -f bsd > %t.fbsd.txt
 # RUN: llvm-nm %t.o -B > %t.b.txt
 # RUN: llvm-nm %t.o > %t.default.txt
 

diff  --git a/llvm/test/tools/llvm-nm/format-sysv-layout.test b/llvm/test/tools/llvm-nm/format-sysv-layout.test
index 33d1b396e8bb7..c2cc5c2c477f4 100644
--- a/llvm/test/tools/llvm-nm/format-sysv-layout.test
+++ b/llvm/test/tools/llvm-nm/format-sysv-layout.test
@@ -1,6 +1,7 @@
 # RUN: yaml2obj %s -o %t.o
 # RUN: llvm-nm %t.o --debug-syms --format=sysv | FileCheck %s -DFILE=%t.o --strict-whitespace
-# RUN: llvm-nm %t.o --debug-syms -f=sysv | FileCheck %s -DFILE=%t.o --strict-whitespace
+# RUN: llvm-nm %t.o --debug-syms -fsysv | FileCheck %s -DFILE=%t.o --strict-whitespace
+# RUN: llvm-nm %t.o --debug-syms -f sysv | FileCheck %s -DFILE=%t.o --strict-whitespace
 
 !ELF
 FileHeader:

diff  --git a/llvm/test/tools/llvm-nm/help.test b/llvm/test/tools/llvm-nm/help.test
index 4e89a84b4d41c..c3693aefa4986 100644
--- a/llvm/test/tools/llvm-nm/help.test
+++ b/llvm/test/tools/llvm-nm/help.test
@@ -1,3 +1,10 @@
 RUN: llvm-nm --help 2>&1 | FileCheck --implicit-check-not="General Options:" %s
-CHECK: Generic Options:
-CHECK: llvm-nm Options:
+RUN: llvm-nm -h 2>&1 | FileCheck --implicit-check-not="General Options:" %s
+CHECK: OPTIONS:
+CHECK:   --debug-syms
+CHECK:   --demangle
+CHECK:   --format=<format>
+CHECK: llvm-nm Mach-O Specific Options:
+CHECK:   --arch=<value>
+CHECK:   -s
+CHECK: Pass @FILE {{.*}}

diff  --git a/llvm/test/tools/llvm-nm/just-symbols.test b/llvm/test/tools/llvm-nm/just-symbols.test
index 53bd2e25a62ef..24284610ea89f 100644
--- a/llvm/test/tools/llvm-nm/just-symbols.test
+++ b/llvm/test/tools/llvm-nm/just-symbols.test
@@ -7,7 +7,7 @@
 # RUN: llvm-nm --just-symbol-name %t.o | 
diff  %t.txt -
 # RUN: llvm-nm --format=just-symbols %t.o | 
diff  %t.txt -
 # RUN: llvm-nm --format=sysv -j %t.o | 
diff  %t.txt -
-# RUN: llvm-nm -j --format=posix %t.o | 
diff  %t.txt -
+# RUN: llvm-nm -j --format=posix %t.o | not 
diff  -q %t.txt %t1.txt
 
 # RUN: FileCheck %s --input-file=%t.txt --implicit-check-not={{.}} --check-prefix=COMMON
 

diff  --git a/llvm/test/tools/llvm-nm/libtool-version.test b/llvm/test/tools/llvm-nm/libtool-version.test
index ee53d0be39f35..56c974e73dff2 100644
--- a/llvm/test/tools/llvm-nm/libtool-version.test
+++ b/llvm/test/tools/llvm-nm/libtool-version.test
@@ -4,5 +4,5 @@
 
 RUN: llvm-nm -V | FileCheck %s
 RUN: llvm-nm --version | FileCheck %s
-CHECK: LLVM version
 CHECK: GNU
+CHECK: LLVM version

diff  --git a/llvm/tools/llvm-nm/CMakeLists.txt b/llvm/tools/llvm-nm/CMakeLists.txt
index 42699bf9029ed..4ad5370a2315e 100644
--- a/llvm/tools/llvm-nm/CMakeLists.txt
+++ b/llvm/tools/llvm-nm/CMakeLists.txt
@@ -6,14 +6,20 @@ set(LLVM_LINK_COMPONENTS
   Core
   Demangle
   Object
+  Option
   Support
   TextAPI
   )
 
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(NmOptsTableGen)
+
 add_llvm_tool(llvm-nm
   llvm-nm.cpp
 
   DEPENDS
+  NmOptsTableGen
   intrinsics_gen
   )
 

diff  --git a/llvm/tools/llvm-nm/Opts.td b/llvm/tools/llvm-nm/Opts.td
new file mode 100644
index 0000000000000..649fe7a9b67f6
--- /dev/null
+++ b/llvm/tools/llvm-nm/Opts.td
@@ -0,0 +1,76 @@
+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 BB<string name, string help1, string help2> {
+  def NAME: Flag<["--", "-"], name>, HelpText<help1>;
+  def no_ # NAME: Flag<["--", "-"], "no-" # name>, HelpText<help2>;
+}
+
+multiclass Eq<string name, string help> {
+  def NAME #_EQ : Joined<["--", "-"], name #"=">,
+                  HelpText<help>;
+  def : Separate<["--", "-"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+}
+
+def debug_syms : FF<"debug-syms", "Show all symbols, even debugger only">;
+def defined_only : FF<"defined-only", "Show only defined symbols">;
+defm demangle : BB<"demangle", "Demangle C++ symbol names", "Don't demangle symbol names">;
+def dynamic : FF<"dynamic", "Display dynamic symbols instead of normal symbols">;
+def extern_only : FF<"extern-only", "Show only external symbols">;
+defm format : Eq<"format", "Specify output format: bsd (default), posix, sysv, darwin, just-symbols">, MetaVarName<"<format>">;
+def help : FF<"help", "Display this help">;
+def no_llvm_bc : FF<"no-llvm-bc", "Disable LLVM bitcode reader">;
+def no_sort : FF<"no-sort", "Show symbols in order encountered">;
+def no_weak : FF<"no-weak", "Show only non-weak symbols">;
+def numeric_sort : FF<"numeric-sort", "Sort symbols by address">;
+def print_armap : FF<"print-armap", "Print the archive map">;
+def print_file_name : FF<"print-file-name", "Precede each symbol with the object file it came from">;
+def print_size : FF<"print-size", "Show symbol size as well as address">;
+def quiet : FF<"quiet", "Suppress 'no symbols' diagnostic">;
+defm radix : Eq<"radix", "Radix (o/d/x) for printing symbol Values">, MetaVarName<"<radix>">;
+def reverse_sort : FF<"reverse-sort", "Sort in reverse order">;
+def size_sort : FF<"size-sort", "Sort symbols by size">;
+def special_syms : FF<"special-syms", "Do not filter special symbols from the output">;
+def undefined_only : FF<"undefined-only", "Show only undefined symbols">;
+def version : FF<"version", "Display the version">;
+def without_aliases : FF<"without-aliases", "Exclude aliases from output">, Flags<[HelpHidden]>;
+
+// Mach-O specific options.
+def grp_mach_o : OptionGroup<"kind">, HelpText<"llvm-nm Mach-O Specific Options">;
+
+def add_dyldinfo : FF<"add-dyldinfo", "Add symbols from the dyldinfo not already in the symbol table">, Group<grp_mach_o>;
+def add_inlinedinfo : FF<"add-inlinedinfo", "Add symbols from the inlined libraries, TBD only">, Group<grp_mach_o>;
+defm arch : Eq<"arch", "architecture(s) from a Mach-O file to dump">, Group<grp_mach_o>;
+def dyldinfo_only : FF<"dyldinfo-only", "Show only symbols from the dyldinfo">, Group<grp_mach_o>;
+def no_dyldinfo : FF<"no-dyldinfo", "Don't add any symbols from the dyldinfo">, Group<grp_mach_o>;
+def s : F<"s", "Dump only symbols from this segment and section name">, Group<grp_mach_o>;
+def x : F<"x", "Print symbol entry in hex">, Group<grp_mach_o>;
+
+def : FF<"just-symbol-name", "Alias for --format=just-symbols">, Alias<format_EQ>, AliasArgs<["just-symbols"]>, Flags<[HelpHidden]>;
+def : FF<"portability", "Alias for --format=posix">, Alias<format_EQ>, AliasArgs<["posix"]>;
+
+def : F<"a", "Alias for --debug-syms">, Alias<debug_syms>;
+def : F<"A", "Alias for --print-file-name">, Alias<print_file_name>;
+def : F<"B", "Alias for --format=bsd">, Alias<format_EQ>, AliasArgs<["bsd"]>;
+def : F<"C", "Alias for --demangle">, Alias<demangle>;
+def : F<"D", "Alias for --dynamic">, Alias<dynamic>;
+def : JoinedOrSeparate<["-"], "f">, HelpText<"Alias for --format">, Alias<format_EQ>, MetaVarName<"<format>">;
+def : F<"h", "Alias for --help">, Alias<help>;
+def : F<"g", "Alias for --extern-only">, Alias<extern_only>;
+def : F<"j", "Alias for --format=just-symbols">, Alias<format_EQ>, AliasArgs<["just-symbols"]>;
+def : F<"m", "Alias for --format=darwin">, Alias<format_EQ>, AliasArgs<["darwin"]>;
+def : F<"M", "Deprecated alias for --print-armap">, Alias<print_armap>, Flags<[HelpHidden]>;
+def : F<"n", "Alias for --numeric-sort">, Alias<numeric_sort>;
+def : F<"o", "Alias for --print-file-name">, Alias<print_file_name>;
+def : F<"p", "Alias for --no-sort">, Alias<no_sort>;
+def : F<"P", "Alias for --format=posix">, Alias<format_EQ>, AliasArgs<["posix"]>;
+def : F<"r", "Alias for --reverse-sort">, Alias<reverse_sort>;
+def : F<"S", "Alias for --print-size">, Alias<print_size>;
+def : JoinedOrSeparate<["-"], "t">, HelpText<"Alias for --radix">, Alias<radix_EQ>, MetaVarName<"<radix>">;
+def : F<"u", "Alias for --undefined-only">, Alias<undefined_only>;
+def : F<"U", "Deprecated alias for --defined-only">, Alias<defined_only>, Flags<[HelpHidden]>;
+def : F<"v", "Alias for --numeric-sort">, Alias<numeric_sort>;
+def : F<"V", "Alias for --version">, Alias<version>;
+def : F<"W", "Deprecated alias for --no-weak">, Alias<no_weak>, Flags<[HelpHidden]>;

diff  --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp
index e21f18a37149f..ffb427a3f2bdf 100644
--- a/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -31,6 +31,9 @@
 #include "llvm/Object/TapiFile.h"
 #include "llvm/Object/TapiUniversal.h"
 #include "llvm/Object/Wasm.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
@@ -47,200 +50,82 @@ using namespace llvm;
 using namespace object;
 
 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
+
+static 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 NmOptTable : public opt::OptTable {
+public:
+  NmOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+};
+
 enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
+} // namespace
 
-cl::OptionCategory NMCat("llvm-nm Options");
-
-cl::opt<OutputFormatTy> OutputFormat(
-    "format", cl::desc("Specify output format"),
-    cl::values(clEnumVal(bsd, "BSD format"), clEnumVal(sysv, "System V format"),
-               clEnumVal(posix, "POSIX.2 format"),
-               clEnumVal(darwin, "Darwin -m format"),
-               cl::OptionEnumValue{"just-symbols", int(just_symbols),
-                                   "just symbol names"}),
-    cl::init(bsd), cl::cat(NMCat));
-cl::alias OutputFormat2("f", cl::desc("Alias for --format"),
-                        cl::aliasopt(OutputFormat), cl::NotHidden);
-
-cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
-                                     cl::ZeroOrMore);
-
-cl::opt<bool> UndefinedOnly("undefined-only",
-                            cl::desc("Show only undefined symbols"),
-                            cl::cat(NMCat));
-cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"),
-                         cl::aliasopt(UndefinedOnly), cl::Grouping,
-                         cl::NotHidden);
-
-cl::opt<bool> DynamicSyms("dynamic",
-                          cl::desc("Display the dynamic symbols instead "
-                                   "of normal symbols."),
-                          cl::cat(NMCat));
-cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"),
-                       cl::aliasopt(DynamicSyms), cl::Grouping, cl::NotHidden);
-
-cl::opt<bool> DefinedOnly("defined-only", cl::desc("Show only defined symbols"),
-                          cl::cat(NMCat));
-cl::alias DefinedOnly2("U", cl::desc("Alias for --defined-only"),
-                       cl::aliasopt(DefinedOnly), cl::Grouping, cl::NotHidden);
-
-cl::opt<bool> ExternalOnly("extern-only",
-                           cl::desc("Show only external symbols"),
-                           cl::ZeroOrMore, cl::cat(NMCat));
-cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"),
-                        cl::aliasopt(ExternalOnly), cl::Grouping,
-                        cl::ZeroOrMore, cl::NotHidden);
-
-cl::opt<bool> NoWeakSymbols("no-weak", cl::desc("Show only non-weak symbols"),
-                            cl::cat(NMCat));
-cl::alias NoWeakSymbols2("W", cl::desc("Alias for --no-weak"),
-                         cl::aliasopt(NoWeakSymbols), cl::Grouping,
-                         cl::NotHidden);
-
-cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"), cl::Grouping,
-                        cl::cat(NMCat));
-cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"),
-                          cl::Grouping, cl::cat(NMCat));
-cl::alias Portability("portability", cl::desc("Alias for --format=posix"),
-                      cl::aliasopt(POSIXFormat), cl::NotHidden);
-cl::opt<bool> DarwinFormat("m", cl::desc("Alias for --format=darwin"),
-                           cl::Grouping, cl::cat(NMCat), cl::NotHidden);
-
-static cl::list<std::string>
-    ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
-              cl::ZeroOrMore, cl::cat(NMCat));
-bool ArchAll = false;
-
-cl::opt<bool> PrintFileName(
-    "print-file-name",
-    cl::desc("Precede each symbol with the object file it came from"),
-    cl::cat(NMCat));
-
-cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"),
-                         cl::aliasopt(PrintFileName), cl::Grouping,
-                         cl::NotHidden);
-cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"),
-                         cl::aliasopt(PrintFileName), cl::Grouping,
-                         cl::NotHidden);
-
-cl::opt<bool> Quiet("quiet", cl::desc("Suppress 'no symbols' diagnostic"),
-                    cl::cat(NMCat));
-
-cl::opt<bool> DebugSyms("debug-syms",
-                        cl::desc("Show all symbols, even debugger only"),
-                        cl::cat(NMCat));
-cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"),
-                     cl::aliasopt(DebugSyms), cl::Grouping, cl::NotHidden);
-
-cl::opt<bool> NumericSort("numeric-sort", cl::desc("Sort symbols by address"),
-                          cl::cat(NMCat));
-cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"),
-                       cl::aliasopt(NumericSort), cl::Grouping, cl::NotHidden);
-cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"),
-                       cl::aliasopt(NumericSort), cl::Grouping, cl::NotHidden);
-
-cl::opt<bool> NoSort("no-sort", cl::desc("Show symbols in order encountered"),
-                     cl::cat(NMCat));
-cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), cl::aliasopt(NoSort),
-                  cl::Grouping, cl::NotHidden);
-
-cl::opt<bool> Demangle("demangle", cl::ZeroOrMore,
-                       cl::desc("Demangle C++ symbol names"), cl::cat(NMCat));
-cl::alias DemangleC("C", cl::desc("Alias for --demangle"),
-                    cl::aliasopt(Demangle), cl::Grouping, cl::NotHidden);
-cl::opt<bool> NoDemangle("no-demangle", cl::init(false), cl::ZeroOrMore,
-                         cl::desc("Don't demangle symbol names"),
-                         cl::cat(NMCat));
-
-cl::opt<bool> ReverseSort("reverse-sort", cl::desc("Sort in reverse order"),
-                          cl::cat(NMCat));
-cl::alias ReverseSortr("r", cl::desc("Alias for --reverse-sort"),
-                       cl::aliasopt(ReverseSort), cl::Grouping, cl::NotHidden);
-
-cl::opt<bool> PrintSize("print-size",
-                        cl::desc("Show symbol size as well as address"),
-                        cl::cat(NMCat));
-cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"),
-                     cl::aliasopt(PrintSize), cl::Grouping, cl::NotHidden);
-bool MachOPrintSizeWarning = false;
-
-cl::opt<bool> SizeSort("size-sort", cl::desc("Sort symbols by size"),
-                       cl::cat(NMCat));
-
-cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden,
-                             cl::desc("Exclude aliases from output"),
-                             cl::cat(NMCat), cl::NotHidden);
-
-cl::opt<bool> ArchiveMap("print-armap", cl::desc("Print the archive map"),
-                         cl::cat(NMCat));
-cl::alias ArchiveMaps("M", cl::desc("Alias for --print-armap"),
-                      cl::aliasopt(ArchiveMap), cl::Grouping, cl::NotHidden);
+static bool ArchiveMap;
+static bool DebugSyms;
+static bool DefinedOnly;
+static bool Demangle;
+static bool DynamicSyms;
+static bool ExternalOnly;
+static OutputFormatTy OutputFormat;
+static bool NoLLVMBitcode;
+static bool NoSort;
+static bool NoWeakSymbols;
+static bool NumericSort;
+static bool PrintFileName;
+static bool PrintSize;
+static bool Quiet;
+static bool ReverseSort;
+static bool SpecialSyms;
+static bool SizeSort;
+static bool UndefinedOnly;
+static bool WithoutAliases;
 
+namespace {
 enum Radix { d, o, x };
-cl::opt<Radix>
-    AddressRadix("radix", cl::desc("Radix (o/d/x) for printing symbol Values"),
-                 cl::values(clEnumVal(d, "decimal"), clEnumVal(o, "octal"),
-                            clEnumVal(x, "hexadecimal")),
-                 cl::init(x), cl::cat(NMCat));
-cl::alias RadixAlias("t", cl::desc("Alias for --radix"),
-                     cl::aliasopt(AddressRadix), cl::NotHidden);
-
-cl::opt<bool> JustSymbolName("just-symbol-name",
-                             cl::desc("Alias for --format=just-symbols"),
-                             cl::cat(NMCat), cl::NotHidden);
-cl::alias JustSymbolNames("j", cl::desc("Alias for --format-just-symbols"),
-                          cl::aliasopt(JustSymbolName), cl::Grouping,
-                          cl::NotHidden);
-
-cl::opt<bool>
-    SpecialSyms("special-syms",
-                cl::desc("Do not filter special symbols from the output"),
-                cl::cat(NMCat));
-
-cl::list<std::string> SegSect("s", cl::multi_val(2), cl::ZeroOrMore,
-                              cl::value_desc("segment section"), cl::Hidden,
-                              cl::desc("Dump only symbols from this segment "
-                                       "and section name, Mach-O only"),
-                              cl::cat(NMCat));
-
-cl::opt<bool> FormatMachOasHex("x",
-                               cl::desc("Print symbol entry in hex, "
-                                        "Mach-O only"),
-                               cl::Grouping, cl::cat(NMCat));
-cl::opt<bool> AddDyldInfo("add-dyldinfo",
-                          cl::desc("Add symbols from the dyldinfo not already "
-                                   "in the symbol table, Mach-O only"),
-                          cl::cat(NMCat));
-cl::opt<bool> NoDyldInfo("no-dyldinfo",
-                         cl::desc("Don't add any symbols from the dyldinfo, "
-                                  "Mach-O only"),
-                         cl::cat(NMCat));
-cl::opt<bool> DyldInfoOnly("dyldinfo-only",
-                           cl::desc("Show only symbols from the dyldinfo, "
-                                    "Mach-O only"),
-                           cl::cat(NMCat));
-
-cl::opt<bool> NoLLVMBitcode("no-llvm-bc",
-                            cl::desc("Disable LLVM bitcode reader"),
-                            cl::cat(NMCat));
-
-cl::opt<bool> AddInlinedInfo("add-inlinedinfo",
-                             cl::desc("Add symbols from the inlined libraries, "
-                                      "TBD(Mach-O) only"),
-                             cl::cat(NMCat));
-
-cl::opt<bool> Version("V", cl::desc("Print version info"), cl::cat(NMCat));
-
-cl::extrahelp HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
-
-bool PrintAddress = true;
-
-bool MultipleFiles = false;
-
-bool HadError = false;
-
-std::string ToolName;
-} // anonymous namespace
+} // namespace
+static Radix AddressRadix;
+
+// Mach-O specific options.
+static bool ArchAll = false;
+static std::vector<StringRef> ArchFlags;
+static bool AddDyldInfo;
+static bool AddInlinedInfo;
+static bool DyldInfoOnly;
+static bool FormatMachOasHex;
+static bool NoDyldInfo;
+static std::vector<StringRef> SegSect;
+static bool MachOPrintSizeWarning = false;
+
+// Miscellaneous states.
+static bool PrintAddress = true;
+static bool MultipleFiles = false;
+static bool HadError = false;
+
+static StringRef ToolName;
 
 static void error(Twine Message, Twine Path = Twine()) {
   HadError = true;
@@ -2237,23 +2122,83 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
   }
 }
 
-static void printExtraVersionInfo(raw_ostream &Outs) {
-  // This needs to contain the word "GNU", libtool looks for that string.
-  Outs << "llvm-nm, compatible with GNU nm\n";
-}
-
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
-  cl::HideUnrelatedOptions(NMCat);
-  cl::AddExtraVersionPrinter(printExtraVersionInfo);
-  cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n");
-
-  if (Version) {
+  BumpPtrAllocator A;
+  StringSaver Saver(A);
+  NmOptTable Tbl;
+  ToolName = argv[0];
+  opt::InputArgList Args =
+      Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
+        error(Msg);
+        exit(1);
+      });
+  if (Args.hasArg(OPT_help)) {
+    Tbl.printHelp(
+        outs(),
+        (Twine(ToolName) + " [options] <input object files>").str().c_str(),
+        "LLVM symbol table 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)) {
+    // This needs to contain the word "GNU", libtool looks for that string.
+    outs() << "llvm-nm, compatible with GNU nm" << '\n';
     cl::PrintVersionMessage();
-    printExtraVersionInfo(outs());
     return 0;
   }
 
+  DebugSyms = Args.hasArg(OPT_debug_syms);
+  DefinedOnly = Args.hasArg(OPT_defined_only);
+  Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
+  DynamicSyms = Args.hasArg(OPT_dynamic);
+  ExternalOnly = Args.hasArg(OPT_extern_only);
+  StringRef V = Args.getLastArgValue(OPT_format_EQ, "bsd");
+  if (V == "bsd")
+    OutputFormat = bsd;
+  else if (V == "posix")
+    OutputFormat = posix;
+  else if (V == "sysv")
+    OutputFormat = sysv;
+  else if (V == "darwin")
+    OutputFormat = darwin;
+  else if (V == "just-symbols")
+    OutputFormat = just_symbols;
+  else
+    error("--format value should be one of: bsd, posix, sysv, darwin, "
+          "just-symbols");
+  NoLLVMBitcode = Args.hasArg(OPT_no_llvm_bc);
+  NoSort = Args.hasArg(OPT_no_sort);
+  NoWeakSymbols = Args.hasArg(OPT_no_weak);
+  NumericSort = Args.hasArg(OPT_numeric_sort);
+  ArchiveMap = Args.hasArg(OPT_print_armap);
+  PrintFileName = Args.hasArg(OPT_print_file_name);
+  PrintSize = Args.hasArg(OPT_print_size);
+  ReverseSort = Args.hasArg(OPT_reverse_sort);
+  Quiet = Args.hasArg(OPT_quiet);
+  V = Args.getLastArgValue(OPT_radix_EQ, "x");
+  if (V == "o")
+    AddressRadix = Radix::o;
+  else if (V == "d")
+    AddressRadix = Radix::d;
+  else if (V == "x")
+    AddressRadix = Radix::x;
+  else
+    error("--radix value should be one of: 'o' (octal), 'd' (decimal), 'x' "
+          "(hexadecimal)");
+  SizeSort = Args.hasArg(OPT_size_sort);
+  SpecialSyms = Args.hasArg(OPT_special_syms);
+  UndefinedOnly = Args.hasArg(OPT_undefined_only);
+  WithoutAliases = Args.hasArg(OPT_without_aliases);
+
+  // Mach-O specific options.
+  FormatMachOasHex = Args.hasArg(OPT_x);
+  AddDyldInfo = Args.hasArg(OPT_add_dyldinfo);
+  AddInlinedInfo = Args.hasArg(OPT_add_inlinedinfo);
+  DyldInfoOnly = Args.hasArg(OPT_dyldinfo_only);
+  NoDyldInfo = Args.hasArg(OPT_no_dyldinfo);
+
   // llvm-nm only reads binary files.
   if (error(sys::ChangeStdinToBinary()))
     return 1;
@@ -2263,16 +2208,6 @@ int main(int argc, char **argv) {
   llvm::InitializeAllTargetMCs();
   llvm::InitializeAllAsmParsers();
 
-  ToolName = argv[0];
-  if (BSDFormat)
-    OutputFormat = bsd;
-  if (POSIXFormat)
-    OutputFormat = posix;
-  if (DarwinFormat)
-    OutputFormat = darwin;
-  if (JustSymbolName)
-    OutputFormat = just_symbols;
-
   // The relative order of these is important. If you pass --size-sort it should
   // only print out the size. However, if you pass -S --size-sort, it should
   // print out both the size and address.
@@ -2280,29 +2215,44 @@ int main(int argc, char **argv) {
     PrintAddress = false;
   if (OutputFormat == sysv || SizeSort)
     PrintSize = true;
-  if (InputFilenames.empty())
-    InputFilenames.push_back("a.out");
-  if (InputFilenames.size() > 1)
-    MultipleFiles = true;
 
-  // If both --demangle and --no-demangle are specified then pick the last one.
-  if (NoDemangle.getPosition() > Demangle.getPosition())
-    Demangle = !NoDemangle;
-
-  for (unsigned i = 0; i < ArchFlags.size(); ++i) {
-    if (ArchFlags[i] == "all") {
-      ArchAll = true;
-    } else {
-      if (!MachOObjectFile::isValidArch(ArchFlags[i]))
-        error("Unknown architecture named '" + ArchFlags[i] + "'",
+  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
+        error("Unknown architecture named '" + V + "'",
               "for the --arch option");
     }
   }
 
+  // Mach-O takes -s to accept two arguments. We emulate this by iterating over
+  // both OPT_s and OPT_INPUT.
+  std::vector<std::string> InputFilenames;
+  int SegSectArgs = 0;
+  for (opt::Arg *A : Args.filtered(OPT_s, OPT_INPUT)) {
+    if (SegSectArgs > 0) {
+      --SegSectArgs;
+      SegSect.push_back(A->getValue());
+    } else if (A->getOption().matches(OPT_s)) {
+      SegSectArgs = 2;
+    } else {
+      InputFilenames.push_back(A->getValue());
+    }
+  }
   if (!SegSect.empty() && SegSect.size() != 2)
     error("bad number of arguments (must be two arguments)",
           "for the -s option");
 
+  if (InputFilenames.empty())
+    InputFilenames.push_back("a.out");
+  if (InputFilenames.size() > 1)
+    MultipleFiles = true;
+
   if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly))
     error("--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only");
 

diff  --git a/llvm/utils/gn/secondary/llvm/tools/llvm-nm/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-nm/BUILD.gn
index 85aa339c8dda2..fd024468a830a 100644
--- a/llvm/utils/gn/secondary/llvm/tools/llvm-nm/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/tools/llvm-nm/BUILD.gn
@@ -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-nm" ]
+  args = [ "-gen-opt-parser-defs" ]
+}
+
 if (llvm_install_binutils_symlinks) {
   symlink_or_copy("nm") {
     deps = [ ":llvm-nm" ]
@@ -19,10 +25,12 @@ group("symlinks") {
 
 executable("llvm-nm") {
   deps = [
+    ":Opts",
     "//llvm/lib/Bitcode/Reader",
     "//llvm/lib/Demangle",
     "//llvm/lib/IR",
     "//llvm/lib/Object",
+    "//llvm/lib/Option",
     "//llvm/lib/Support",
     "//llvm/lib/Target:AllTargetsAsmParsers",
     "//llvm/lib/Target:AllTargetsDescs",

diff  --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
index 3516746a50277..f5d0ecebd3abf 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -3059,6 +3059,18 @@ cc_binary(
     ],
 )
 
+gentbl(
+    name = "NmOptsTableGen",
+    strip_include_prefix = "tools/llvm-nm",
+    tbl_outs = [(
+        "-gen-opt-parser-defs",
+        "tools/llvm-nm/Opts.inc",
+    )],
+    tblgen = ":llvm-tblgen",
+    td_file = "tools/llvm-nm/Opts.td",
+    td_srcs = ["include/llvm/Option/OptParser.td"],
+)
+
 cc_binary(
     name = "llvm-nm",
     srcs = glob([
@@ -3074,7 +3086,9 @@ cc_binary(
         ":BitReader",
         ":Core",
         ":Demangle",
+        ":NmOptsTableGen",
         ":Object",
+        ":Option",
         ":Support",
     ],
 )


        


More information about the llvm-commits mailing list