[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