[lld] r262190 - Move functionality of UniversalDriver to the entry point file.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 28 11:50:14 PST 2016


Author: ruiu
Date: Sun Feb 28 13:50:14 2016
New Revision: 262190

URL: http://llvm.org/viewvc/llvm-project?rev=262190&view=rev
Log:
Move functionality of UniversalDriver to the entry point file.

UniversalDriver was used as a dispatcher to each platform-specific driver.
It had its own Options.td file. It was not just too much to parse only a
few options (we only want to parse -core, -flavor or argv[0]),
but also interpreted arguments too early. For example, if you invoke lld as
"lld -flavor gnu ... -help", then you'd get the UniversalDriver's help
message instead of GnuDriver's. This patch eliminates the use of Options
from the dispatcher.

http://reviews.llvm.org/D17686

Removed:
    lld/trunk/lib/Driver/UniversalDriver.cpp
    lld/trunk/lib/Driver/UniversalDriverOptions.td
    lld/trunk/unittests/DriverTests/UniversalDriverTest.cpp
Modified:
    lld/trunk/ELF/CMakeLists.txt
    lld/trunk/include/lld/Driver/Driver.h
    lld/trunk/lib/Driver/CMakeLists.txt
    lld/trunk/tools/lld/lld.cpp
    lld/trunk/unittests/DriverTests/CMakeLists.txt
    lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp

Modified: lld/trunk/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=262190&r1=262189&r2=262190&view=diff
==============================================================================
--- lld/trunk/ELF/CMakeLists.txt (original)
+++ lld/trunk/ELF/CMakeLists.txt Sun Feb 28 13:50:14 2016
@@ -22,6 +22,9 @@ add_lld_library(lldELF
   Option
   MC
   Support
+
+  LINK_LIBS
+  lldConfig
   )
 
 add_dependencies(lldELF ELFOptionsTableGen)

Modified: lld/trunk/include/lld/Driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/Driver.h?rev=262190&r1=262189&r2=262190&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/Driver.h (original)
+++ lld/trunk/include/lld/Driver/Driver.h Sun Feb 28 13:50:14 2016
@@ -51,18 +51,6 @@ private:
   Driver() = delete;
 };
 
-/// Driver for "universal" lld tool which can mimic any linker command line
-/// parsing once it figures out which command line flavor to use.
-class UniversalDriver : public Driver {
-public:
-  /// Determine flavor and pass control to Driver for that flavor.
-  static bool link(llvm::MutableArrayRef<const char *> args,
-                   raw_ostream &diag = llvm::errs());
-
-private:
-  UniversalDriver() = delete;
-};
-
 /// Driver for darwin/ld64 'ld' command line options.
 class DarwinLdDriver : public Driver {
 public:

Modified: lld/trunk/lib/Driver/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/CMakeLists.txt?rev=262190&r1=262189&r2=262190&view=diff
==============================================================================
--- lld/trunk/lib/Driver/CMakeLists.txt (original)
+++ lld/trunk/lib/Driver/CMakeLists.txt Sun Feb 28 13:50:14 2016
@@ -1,5 +1,3 @@
-set(LLVM_TARGET_DEFINITIONS UniversalDriverOptions.td)
-tablegen(LLVM UniversalDriverOptions.inc -gen-opt-parser-defs)
 set(LLVM_TARGET_DEFINITIONS CoreOptions.td)
 tablegen(LLVM CoreOptions.inc -gen-opt-parser-defs)
 set(LLVM_TARGET_DEFINITIONS DarwinLdOptions.td)
@@ -10,7 +8,6 @@ add_lld_library(lldDriver
   CoreDriver.cpp
   DarwinLdDriver.cpp
   Driver.cpp
-  UniversalDriver.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${LLD_INCLUDE_DIR}/lld/Driver

Removed: lld/trunk/lib/Driver/UniversalDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/UniversalDriver.cpp?rev=262189&view=auto
==============================================================================
--- lld/trunk/lib/Driver/UniversalDriver.cpp (original)
+++ lld/trunk/lib/Driver/UniversalDriver.cpp (removed)
@@ -1,220 +0,0 @@
-//===- lib/Driver/UniversalDriver.cpp -------------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// Driver for "universal" lld tool which can mimic any linker command line
-/// parsing once it figures out which command line flavor to use.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/Driver/Driver.h"
-#include "lld/Config/Version.h"
-#include "lld/Core/LLVM.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lld;
-
-namespace {
-
-// Create enum with OPT_xxx values for each option in GnuLdOptions.td
-enum {
-  OPT_INVALID = 0,
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELP, META)                                                     \
-  OPT_##ID,
-#include "UniversalDriverOptions.inc"
-#undef OPTION
-};
-
-// Create prefix string literals used in GnuLdOptions.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#include "UniversalDriverOptions.inc"
-#undef PREFIX
-
-// Create table mapping all options defined in GnuLdOptions.td
-static const llvm::opt::OptTable::Info infoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR)                                              \
-  {                                                                            \
-    PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
-        PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS                      \
-  }                                                                            \
-  ,
-#include "UniversalDriverOptions.inc"
-#undef OPTION
-};
-
-// Create OptTable class for parsing actual command line arguments
-class UniversalDriverOptTable : public llvm::opt::OptTable {
-public:
-  UniversalDriverOptTable()
-      : OptTable(infoTable) {}
-};
-
-enum class Flavor {
-  invalid,
-  gnu_ld,     // -flavor gnu
-  win_link,   // -flavor link
-  darwin_ld,  // -flavor darwin
-  core        // -flavor core OR -core
-};
-
-struct ProgramNameParts {
-  StringRef _target;
-  StringRef _flavor;
-};
-
-} // anonymous namespace
-
-static Flavor strToFlavor(StringRef str) {
-  return llvm::StringSwitch<Flavor>(str)
-      .Case("gnu", Flavor::gnu_ld)
-      .Case("ld.lld", Flavor::gnu_ld)
-      .Case("link", Flavor::win_link)
-      .Case("lld-link", Flavor::win_link)
-      .Case("darwin", Flavor::darwin_ld)
-      .Case("core", Flavor::core)
-      .Case("ld", Flavor::gnu_ld)
-      .Default(Flavor::invalid);
-}
-
-static ProgramNameParts parseProgramName(StringRef programName) {
-  SmallVector<StringRef, 3> components;
-  llvm::SplitString(programName, components, "-");
-  ProgramNameParts ret;
-
-  using std::begin;
-  using std::end;
-
-  // Erase any lld components.
-  components.erase(std::remove(components.begin(), components.end(), "lld"),
-                   components.end());
-
-  // Find the flavor component.
-  auto flIter = std::find_if(components.begin(), components.end(),
-                             [](StringRef str) -> bool {
-    return strToFlavor(str) != Flavor::invalid;
-  });
-
-  if (flIter != components.end()) {
-    ret._flavor = *flIter;
-    components.erase(flIter);
-  }
-
-  // Any remaining component must be the target.
-  if (components.size() == 1)
-    ret._target = components[0];
-
-  return ret;
-}
-
-// Removes the argument from argv along with its value, if exists, and updates
-// argc.
-static void removeArg(llvm::opt::Arg *arg,
-                      llvm::MutableArrayRef<const char *> &args) {
-  unsigned int numToRemove = arg->getNumValues() + 1;
-  auto sub = args.slice(arg->getIndex() + 1);
-  std::rotate(sub.begin(), sub.begin() + numToRemove, sub.end());
-  args = args.drop_back(numToRemove);
-}
-
-static Flavor getFlavor(llvm::MutableArrayRef<const char *> &args,
-                        const llvm::opt::InputArgList &parsedArgs) {
-  if (llvm::opt::Arg *argCore = parsedArgs.getLastArg(OPT_core)) {
-    removeArg(argCore, args);
-    return Flavor::core;
-  }
-  if (llvm::opt::Arg *argFlavor = parsedArgs.getLastArg(OPT_flavor)) {
-    removeArg(argFlavor, args);
-    return strToFlavor(argFlavor->getValue());
-  }
-
-#if LLVM_ON_UNIX
-  if (llvm::sys::path::filename(args[0]).equals("ld")) {
-#if __APPLE__
-    // On a Darwin systems, if linker binary is named "ld", use Darwin driver.
-    return Flavor::darwin_ld;
-#endif
-    // On a ELF based systems, if linker binary is named "ld", use gnu driver.
-    return Flavor::gnu_ld;
-  }
-#endif
-
-  StringRef name = llvm::sys::path::filename(args[0]);
-  if (name.endswith_lower(".exe"))
-    name = llvm::sys::path::stem(name);
-  return strToFlavor(parseProgramName(name)._flavor);
-}
-
-namespace lld {
-
-bool UniversalDriver::link(llvm::MutableArrayRef<const char *> args,
-                           raw_ostream &diagnostics) {
-  // Parse command line options using GnuLdOptions.td
-  UniversalDriverOptTable table;
-  unsigned missingIndex;
-  unsigned missingCount;
-
-  // Program name
-  StringRef programName = llvm::sys::path::stem(args[0]);
-
-  llvm::opt::InputArgList parsedArgs =
-      table.ParseArgs(args.slice(1), missingIndex, missingCount);
-
-  if (missingCount) {
-    diagnostics << "error: missing arg value for '"
-                << parsedArgs.getArgString(missingIndex) << "' expected "
-                << missingCount << " argument(s).\n";
-    return false;
-  }
-
-  // Handle -help
-  if (parsedArgs.getLastArg(OPT_help)) {
-    table.PrintHelp(llvm::outs(), programName.data(), "LLVM Linker", false);
-    return true;
-  }
-
-  // Handle -version
-  if (parsedArgs.getLastArg(OPT_version)) {
-    diagnostics << "LLVM Linker Version: " << getLLDVersion()
-                << getLLDRepositoryVersion() << "\n";
-    return true;
-  }
-
-  Flavor flavor = getFlavor(args, parsedArgs);
-
-  // Switch to appropriate driver.
-  switch (flavor) {
-  case Flavor::gnu_ld:
-    return elf::link(args, diagnostics);
-  case Flavor::darwin_ld:
-    return DarwinLdDriver::linkMachO(args, diagnostics);
-  case Flavor::win_link:
-    coff::link(args);
-    return true;
-  case Flavor::core:
-    return CoreDriver::link(args, diagnostics);
-  case Flavor::invalid:
-    diagnostics << "Select the appropriate flavor\n";
-    table.PrintHelp(llvm::outs(), programName.data(), "LLVM Linker", false);
-    return false;
-  }
-  llvm_unreachable("Unrecognised flavor");
-}
-
-} // end namespace lld

Removed: lld/trunk/lib/Driver/UniversalDriverOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/UniversalDriverOptions.td?rev=262189&view=auto
==============================================================================
--- lld/trunk/lib/Driver/UniversalDriverOptions.td (original)
+++ lld/trunk/lib/Driver/UniversalDriverOptions.td (removed)
@@ -1,19 +0,0 @@
-include "llvm/Option/OptParser.td"
-
-// Select an optional flavor
-def flavor: Separate<["-"], "flavor">,
-     HelpText<"Flavor for linking, options are gnu/darwin/link">;
-
-// Select the core flavor
-def core : Flag<["-"], "core">,
-     HelpText<"CORE linking">;
-
-def target: Separate<["-"], "target">,
-     HelpText<"Select the target">;
-
-def version: Flag<["-"], "version">,
-     HelpText<"Display the version">;
-
-// Help message
-def help : Flag<["-"], "help">,
-     HelpText<"Display this help message">;

Modified: lld/trunk/tools/lld/lld.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld/lld.cpp?rev=262190&r1=262189&r2=262190&view=diff
==============================================================================
--- lld/trunk/tools/lld/lld.cpp (original)
+++ lld/trunk/tools/lld/lld.cpp Sun Feb 28 13:50:14 2016
@@ -6,32 +6,123 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// This is the entry point to the lld driver. This is a thin wrapper which
-/// dispatches to the given platform specific driver.
-///
+//
+// This is the entry point to the lld driver. This is a thin wrapper which
+// dispatches to the given platform specific driver.
+//
+// If there is -flavor option or -core option, it is dispatched according
+// to the arguments. If the flavor parameter is not present, then it is
+// dispatched according to argv[0].
+//
 //===----------------------------------------------------------------------===//
 
-#include "lld/Core/LLVM.h"
 #include "lld/Driver/Driver.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
 #include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Signals.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace lld;
+using namespace llvm;
+using namespace llvm::sys;
+
+enum Flavor {
+  Invalid,
+  Gnu,     // -flavor gnu
+  WinLink, // -flavor link
+  Darwin,  // -flavor darwin
+  Core     // -flavor core or -core
+};
+
+LLVM_ATTRIBUTE_NORETURN static void die(const Twine &S) {
+  errs() << S << "\n";
+  exit(1);
+}
+
+static Flavor getFlavor(StringRef S) {
+  return StringSwitch<Flavor>(S)
+      .Case("ld", Gnu)
+      .Case("ld.lld", Gnu)
+      .Case("gnu", Gnu)
+      .Case("link", WinLink)
+      .Case("darwin", Darwin)
+      .Case("core", Core)
+      .Default(Invalid);
+}
 
+static Flavor parseProgname(StringRef Progname) {
+#if __APPLE__
+  // Use Darwin driver for "ld" on Darwin.
+  if (Progname == "ld")
+    return Darwin;
+#endif
+
+#if LLVM_ON_UNIX
+  // Use GNU driver for "ld" on other Unix-like system.
+  if (Progname == "ld")
+    return Gnu;
+#endif
+
+  // Progname may be something like "lld-gnu". Parse it.
+  SmallVector<StringRef, 3> V;
+  SplitString(Progname, V, "-");
+  for (StringRef S : V)
+    if (Flavor F = getFlavor(S))
+      return F;
+  return Invalid;
+}
+
+static Flavor parseFlavor(std::vector<const char *> &V) {
+  // If the first argument is -core, then core driver.
+  if (V.size() > 1 && V[1] == StringRef("-core")) {
+    V.erase(V.begin() + 1);
+    return Core;
+  }
+
+  // Parse -flavor option.
+  if (V.size() > 1 && V[1] == StringRef("-flavor")) {
+    if (V.size() <= 2)
+      die("missing arg value for '-flavor'");
+    Flavor F = getFlavor(V[2]);
+    if (F == Invalid)
+      die("Unknown flavor: " + StringRef(V[2]));
+    V.erase(V.begin() + 1, V.begin() + 3);
+    return F;
+  }
+
+  // Deduct the flavor from argv[0].
+  StringRef Arg0 = path::filename(V[0]);
+  if (Arg0.endswith_lower(".exe"))
+    Arg0 = Arg0.drop_back(4);
+  return parseProgname(Arg0);
+}
 
 /// Universal linker main(). This linker emulates the gnu, darwin, or
-/// windows linker based on the tool name or if the first argument is
-/// -flavor.
-int main(int argc, const char *argv[]) {
+/// windows linker based on the argv[0] or -flavor option.
+int main(int Argc, const char **Argv) {
   // Standard set up, so program fails gracefully.
-  llvm::sys::PrintStackTraceOnErrorSignal();
-  llvm::PrettyStackTraceProgram stackPrinter(argc, argv);
-  llvm::llvm_shutdown_obj shutdown;
+  sys::PrintStackTraceOnErrorSignal();
+  PrettyStackTraceProgram StackPrinter(Argc, Argv);
+  llvm_shutdown_obj Shutdown;
 
-  return !UniversalDriver::link(
-             llvm::MutableArrayRef<const char *>(argv, argc));
+  std::vector<const char *> Args(Argv, Argv + Argc);
+  switch (parseFlavor(Args)) {
+  case Gnu:
+    return !elf::link(Args, errs());
+  case WinLink:
+    coff::link(Args);
+    return 0;
+  case Darwin:
+    return !DarwinLdDriver::linkMachO(Args, errs());
+  case Core:
+    return !CoreDriver::link(Args, errs());
+  default:
+    die("-flavor option is missing. Available flavors are "
+        "gnu, darwin or link.");
+  }
 }

Modified: lld/trunk/unittests/DriverTests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/CMakeLists.txt?rev=262190&r1=262189&r2=262190&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/CMakeLists.txt (original)
+++ lld/trunk/unittests/DriverTests/CMakeLists.txt Sun Feb 28 13:50:14 2016
@@ -1,5 +1,4 @@
 add_lld_unittest(DriverTests
-  UniversalDriverTest.cpp
   DarwinLdDriverTest.cpp
   )
 

Modified: lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp?rev=262190&r1=262189&r2=262190&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp Sun Feb 28 13:50:14 2016
@@ -254,12 +254,3 @@ TEST_F(DarwinLdParserTest, deadStrippabl
   EXPECT_FALSE(parse("ld", "-mark_dead_strippable_dylib", "a.o",
                      "-arch", "i386", nullptr));
 }
-
-TEST_F(DarwinLdParserTest, llvmOptions) {
-  EXPECT_TRUE(parse("ld", "-mllvm", "-enable-tbaa", "-mllvm", "-enable-misched", "a.o",
-                    "-arch", "i386", nullptr));
-  const std::vector<const char *> &options = _ctx.llvmOptions();
-  EXPECT_EQ(options.size(), 2UL);
-  EXPECT_EQ(strcmp(options[0],"-enable-tbaa"), 0);
-  EXPECT_EQ(strcmp(options[1],"-enable-misched"), 0);
-}

Removed: lld/trunk/unittests/DriverTests/UniversalDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/UniversalDriverTest.cpp?rev=262189&view=auto
==============================================================================
--- lld/trunk/unittests/DriverTests/UniversalDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/UniversalDriverTest.cpp (removed)
@@ -1,32 +0,0 @@
-//===- lld/unittest/UniversalDriverTest.cpp -------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Universal driver tests that depend on the value of argv[0].
-///
-//===----------------------------------------------------------------------===//
-
-#include "gtest/gtest.h"
-#include "lld/Driver/Driver.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-using namespace lld;
-
-TEST(UniversalDriver, flavor) {
-  const char *args[] = {"ld", "-flavor", "gnu"};
-
-  std::string diags;
-  raw_string_ostream os(diags);
-  UniversalDriver::link(args, os);
-  EXPECT_EQ(os.str().find("failed to determine driver flavor"),
-            std::string::npos);
-  EXPECT_NE(os.str().find("no input files"), std::string::npos);
-}




More information about the llvm-commits mailing list