<div dir="ltr">On Wed, Oct 23, 2013 at 9:23 PM, Shankar Easwaran <span dir="ltr"><<a href="mailto:shankare@codeaurora.org" target="_blank">shankare@codeaurora.org</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: shankare<br>
Date: Wed Oct 23 23:23:02 2013<br>
New Revision: 193301<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=193301&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=193301&view=rev</a><br>
Log:<br>
[Driver] Change UniversalDriver to use TD file.<br>
<br>
Easier to add new options such as -version, and easy to parse.<br>
<br>
Now displays a help message with -help<br>
<br>
Added:<br>
    lld/trunk/lib/Driver/UniversalDriverOptions.td<br>
Modified:<br>
    lld/trunk/lib/Driver/CMakeLists.txt<br>
    lld/trunk/lib/Driver/UniversalDriver.cpp<br>
<br>
Modified: lld/trunk/lib/Driver/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/CMakeLists.txt?rev=193301&r1=193300&r2=193301&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/CMakeLists.txt?rev=193301&r1=193300&r2=193301&view=diff</a><br>


==============================================================================<br>
--- lld/trunk/lib/Driver/CMakeLists.txt (original)<br>
+++ lld/trunk/lib/Driver/CMakeLists.txt Wed Oct 23 23:23:02 2013<br>
@@ -1,3 +1,5 @@<br>
+set(LLVM_TARGET_DEFINITIONS UniversalDriverOptions.td)<br>
+tablegen(LLVM UniversalDriverOptions.inc -gen-opt-parser-defs)<br>
 set(LLVM_TARGET_DEFINITIONS GnuLdOptions.td)<br>
 tablegen(LLVM GnuLdOptions.inc -gen-opt-parser-defs)<br>
 set(LLVM_TARGET_DEFINITIONS CoreOptions.td)<br>
<br>
Modified: lld/trunk/lib/Driver/UniversalDriver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/UniversalDriver.cpp?rev=193301&r1=193300&r2=193301&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/UniversalDriver.cpp?rev=193301&r1=193300&r2=193301&view=diff</a><br>


==============================================================================<br>
--- lld/trunk/lib/Driver/UniversalDriver.cpp (original)<br>
+++ lld/trunk/lib/Driver/UniversalDriver.cpp Wed Oct 23 23:23:02 2013<br>
@@ -20,6 +20,9 @@<br>
<br>
 #include "llvm/ADT/StringExtras.h"<br>
 #include "llvm/ADT/StringSwitch.h"<br>
+#include "llvm/Option/Arg.h"<br>
+#include "llvm/Option/Option.h"<br>
+#include "llvm/Support/CommandLine.h"<br>
 #include "llvm/Support/Host.h"<br>
 #include "llvm/Support/Path.h"<br>
 #include "llvm/Support/raw_ostream.h"<br>
@@ -27,6 +30,42 @@<br>
 using namespace lld;<br>
<br>
 namespace {<br>
+<br>
+// Create enum with OPT_xxx values for each option in GnuLdOptions.td<br>
+enum {<br>
+  OPT_INVALID = 0,<br>
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \<br>
+               HELP, META)                                                     \<br>
+  OPT_##ID,<br>
+#include "UniversalDriverOptions.inc"<br>
+#undef OPTION<br>
+};<br>
+<br>
+// Create prefix string literals used in GnuLdOptions.td<br>
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;<br>
+#include "UniversalDriverOptions.inc"<br>
+#undef PREFIX<br>
+<br>
+// Create table mapping all options defined in GnuLdOptions.td<br>
+static const llvm::opt::OptTable::Info infoTable[] = {<br>
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \<br>
+               HELPTEXT, METAVAR)                                              \<br>
+  {                                                                            \<br>
+    PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \<br>
+        PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS                      \<br>
+  }                                                                            \<br>
+  ,<br>
+#include "UniversalDriverOptions.inc"<br>
+#undef OPTION<br>
+};<br>
+<br>
+// Create OptTable class for parsing actual command line arguments<br>
+class UniversalDriverOptTable : public llvm::opt::OptTable {<br>
+public:<br>
+  UniversalDriverOptTable()<br>
+      : OptTable(infoTable, llvm::array_lengthof(infoTable)) {}<br>
+};<br>
+<br>
 enum class Flavor {<br>
   invalid,<br>
   gnu_ld,       // -flavor gnu<br>
@@ -80,44 +119,50 @@ ProgramNameParts parseProgramName(String<br>
   return ret;<br>
 }<br>
<br>
-Flavor selectFlavor(std::vector<const char *> &args, raw_ostream &diag) {<br>
-  // -core as first arg is shorthand for -flavor core.<br>
-  if (args.size() > 1 && StringRef(args[1]) == "-core") {<br>
-    args.erase(args.begin() + 1);<br>
-    return Flavor::core;<br>
-  }<br>
-  // Handle -flavor as first arg.<br>
-  if (args.size() > 2 && StringRef(args[1]) == "-flavor") {<br>
-    Flavor flavor = strToFlavor(args[2]);<br>
-    args.erase(args.begin() + 1);<br>
-    args.erase(args.begin() + 1);<br>
-    if (flavor == Flavor::invalid)<br>
-      diag << "error: '" << args[2] << "' invalid value for -flavor.\n";<br>
-    return flavor;<br>
-  }<br>
-<br>
-  Flavor flavor =<br>
-      strToFlavor(parseProgramName(llvm::sys::path::stem(args[0]))._flavor);<br>
-<br>
-  // If flavor still undetermined, then error out.<br>
-  if (flavor == Flavor::invalid)<br>
-    diag << "error: failed to determine driver flavor from program name"<br>
-         << " '" << args[0] << "'.\n"<br>
-         << "select a flavor with -flavor [gnu|darwin|link|core].\n";<br>
-  return flavor;<br>
-}<br>
-}<br>
+} // namespace<br>
<br>
 namespace lld {<br>
 bool UniversalDriver::link(int argc, const char *argv[],<br>
                            raw_ostream &diagnostics) {<br>
-  // Convert argv[] C-array to vector.<br>
-  std::vector<const char *> args(argv, argv + argc);<br>
+  // Parse command line options using GnuLdOptions.td<br>
+  std::unique_ptr<llvm::opt::InputArgList> parsedArgs;<br>
+  UniversalDriverOptTable table;<br>
+  unsigned missingIndex;<br>
+  unsigned missingCount;<br>
+<br>
+  // Program name<br>
+  StringRef programName = llvm::sys::path::stem(argv[0]);<br>
+<br>
+  parsedArgs.reset(<br>
+      table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));<br>
+<br>
+  if (missingCount) {<br>
+    diagnostics << "error: missing arg value for '"<br>
+                << parsedArgs->getArgString(missingIndex) << "' expected "<br>
+                << missingCount << " argument(s).\n";<br>
+    return false;<br>
+  }<br>
+<br>
+  // Handle --help<br>
+  if (parsedArgs->getLastArg(OPT_help)) {<br>
+    table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);<br>
+    return true;<br>
+  }<br>
<br>
-  // Determine flavor of link based on command name or -flavor argument.<br>
-  // Note: 'args' is modified to remove -flavor option.<br>
-  Flavor flavor = selectFlavor(args, diagnostics);<br>
+  Flavor flavor;<br>
<br>
+  if (parsedArgs->getLastArg(OPT_core)) {<br>
+    flavor = Flavor::core;<br>
+    argv++;<br>
+    argc--;<br>
+  } else if (llvm::opt::Arg *argFlavor = parsedArgs->getLastArg(OPT_flavor)) {<br>
+    flavor = strToFlavor(argFlavor->getValue());<br>
+    argv += 2;<br>
+    argc -= 2;<br>
+  } else<br>
+    flavor = strToFlavor(parseProgramName(programName)._flavor);<br>
+<br>
+  std::vector<const char *> args(argv, argv + argc);<br>
   // Switch to appropriate driver.<br>
   switch (flavor) {<br>
   case Flavor::gnu_ld:<br>
@@ -129,6 +174,8 @@ bool UniversalDriver::link(int argc, con<br>
   case Flavor::core:<br>
     return CoreDriver::link(args.size(), args.data(), diagnostics);<br>
   case Flavor::invalid:<br>
+    diagnostics << "Select the appropriate flavor\n";<br>
+    table.PrintHelp(llvm::outs(), programName.data(), "LLVM Linker", false);<br>
     return false;<br>
   }<br>
   llvm_unreachable("Unrecognised flavor");<br>
<br>
Added: lld/trunk/lib/Driver/UniversalDriverOptions.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/UniversalDriverOptions.td?rev=193301&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/UniversalDriverOptions.td?rev=193301&view=auto</a><br>


==============================================================================<br>
--- lld/trunk/lib/Driver/UniversalDriverOptions.td (added)<br>
+++ lld/trunk/lib/Driver/UniversalDriverOptions.td Wed Oct 23 23:23:02 2013<br>
@@ -0,0 +1,16 @@<br>
+include "llvm/Option/OptParser.td"<br>
+<br>
+// Select an optional flavor<br>
+def flavor: Separate<["-"], "flavor">,<br>
+     HelpText<"Flavor for linking, options are gnu/darwin/link">;<br>
+<br>
+// Select the core flavor<br>
+def core : Flag<["-"], "core">,<br>
+     HelpText<"CORE linking">;<br>
+<br>
+def target: Separate<["-"], "target">,<br>
+     HelpText<"Select the target">;<br>
+<br>
+// Help message<br>
+def help : Flag<["-"], "help">,<br>
+     HelpText<"Display this help message">;<br></blockquote><div><br></div><div>It feels inconsistent to me that the driver recognizes -core as a shorthand for "-flavor core", while there are no similar options for other flavors. Should we add options for all flavors, or should we remove -core?</div>

</div></div></div>