[lld] r178798 - [Driver] Fix symlinked universal driver behavior and add a test.
Michael J. Spencer
bigcheesegs at gmail.com
Thu Apr 4 15:04:16 PDT 2013
Author: mspencer
Date: Thu Apr 4 17:04:16 2013
New Revision: 178798
URL: http://llvm.org/viewvc/llvm-project?rev=178798&view=rev
Log:
[Driver] Fix symlinked universal driver behavior and add a test.
Added:
lld/trunk/unittests/CoreTests/
lld/trunk/unittests/CoreTests/CMakeLists.txt
lld/trunk/unittests/CoreTests/RangeTest.cpp
- copied, changed from r178788, lld/trunk/unittests/RangeTest.cpp
lld/trunk/unittests/DriverTests/
lld/trunk/unittests/DriverTests/CMakeLists.txt
lld/trunk/unittests/DriverTests/UniversalDriverTest.cpp
Removed:
lld/trunk/unittests/RangeTest.cpp
Modified:
lld/trunk/include/lld/Driver/Driver.h
lld/trunk/lib/Driver/UniversalDriver.cpp
lld/trunk/unittests/CMakeLists.txt
Modified: lld/trunk/include/lld/Driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/Driver.h?rev=178798&r1=178797&r2=178798&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/Driver.h (original)
+++ lld/trunk/include/lld/Driver/Driver.h Thu Apr 4 17:04:16 2013
@@ -48,21 +48,11 @@ private:
class UniversalDriver : public Driver {
public:
/// Determine flavor and pass control to Driver for that flavor.
- static bool link(int argc, const char *argv[]);
+ static bool link(int argc, const char *argv[],
+ raw_ostream &diagnostics = llvm::errs());
private:
UniversalDriver() LLVM_DELETED_FUNCTION;
-
- enum class Flavor {
- invalid,
- gnu_ld, // -flavor gnu
- win_link, // -flavor link
- darwin_ld, // -flavor darwin
- core // -flavor core OR -core
- };
-
- static Flavor selectFlavor(std::vector<const char*> &args);
- static Flavor strToFlavor(StringRef str);
};
Modified: lld/trunk/lib/Driver/UniversalDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/UniversalDriver.cpp?rev=178798&r1=178797&r2=178798&view=diff
==============================================================================
--- lld/trunk/lib/Driver/UniversalDriver.cpp (original)
+++ lld/trunk/lib/Driver/UniversalDriver.cpp Thu Apr 4 17:04:16 2013
@@ -14,96 +14,120 @@
//===----------------------------------------------------------------------===//
#include "lld/Driver/Driver.h"
-#include "lld/ReaderWriter/MachOTargetInfo.h"
-#include "llvm/ADT/ArrayRef.h"
+#include "lld/Core/LLVM.h"
+
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Signals.h"
-
-#include <memory>
-namespace lld {
+using namespace lld;
+namespace {
+enum class Flavor {
+ invalid,
+ gnu_ld, // -flavor gnu
+ win_link, // -flavor link
+ darwin_ld, // -flavor darwin
+ core // -flavor core OR -core
+};
-bool UniversalDriver::link(int argc, const char *argv[]) {
- // Convert argv[] C-array to vector.
- std::vector<const char *> args;
- args.assign(&argv[0], &argv[argc]);
-
- // Determine flavor of link based on command name or -flavor argument.
- // Note: 'args' is modified to remove -flavor option.
- Flavor flavor = selectFlavor(args);
-
- // Switch to appropriate driver.
- switch (flavor) {
- case Flavor::gnu_ld:
- return GnuLdDriver::linkELF(args.size(), &args[0]);
- case Flavor::darwin_ld:
- return DarwinLdDriver::linkMachO(args.size(), &args[0]);
- case Flavor::core:
- return CoreDriver::link(args.size(), &args[0]);
- case Flavor::win_link:
- llvm_unreachable("Unsupported flavor");
- case Flavor::invalid:
- return true;
- }
+Flavor strToFlavor(StringRef str) {
+ return llvm::StringSwitch<Flavor>(str)
+ .Case("gnu", Flavor::gnu_ld)
+ .Case("link", Flavor::win_link)
+ .Case("darwin", Flavor::darwin_ld)
+ .Case("core", Flavor::core)
+ .Case("ld", Flavor::gnu_ld) // deprecated
+ .Default(Flavor::invalid);
}
+struct ProgramNameParts {
+ StringRef _target;
+ StringRef _flavor;
+};
+
+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;
+}
-/// Pick the flavor of driver to use based on the command line and
-/// host environment.
-UniversalDriver::Flavor UniversalDriver::selectFlavor(
- std::vector<const char*> &args) {
+Flavor selectFlavor(std::vector<const char *> &args, raw_ostream &diag) {
// -core as first arg is shorthand for -flavor core.
- if (args.size() >= 1 && StringRef(args[1]) == "-core") {
+ if (args.size() > 1 && StringRef(args[1]) == "-core") {
args.erase(args.begin() + 1);
return Flavor::core;
}
// Handle -flavor as first arg.
- if (args.size() >= 2 && StringRef(args[1]) == "-flavor") {
+ if (args.size() > 2 && StringRef(args[1]) == "-flavor") {
Flavor flavor = strToFlavor(args[2]);
args.erase(args.begin() + 1);
args.erase(args.begin() + 1);
if (flavor == Flavor::invalid)
- llvm::errs() << "error: '" << args[2] << "' invalid value for -flavor.\n";
+ diag << "error: '" << args[2] << "' invalid value for -flavor.\n";
return flavor;
}
- // Check if flavor is at end of program name (e.g. "lld-gnu");
- SmallVector<StringRef, 3> components;
- llvm::SplitString(args[0], components, "-");
- Flavor flavor = strToFlavor(components.back());
-
+ Flavor flavor =
+ strToFlavor(parseProgramName(llvm::sys::path::stem(args[0]))._flavor);
+
// If flavor still undetermined, then error out.
if (flavor == Flavor::invalid)
- llvm::errs() << "error: failed to determine driver flavor from program name"
- " '" << args[0] << "'.\n";
+ diag << "error: failed to determine driver flavor from program name"
+ " '" << args[0] << "'.\n";
return flavor;
}
-
-/// Maps flavor strings to Flavor enum values.
-UniversalDriver::Flavor UniversalDriver::strToFlavor(StringRef str) {
- return llvm::StringSwitch<Flavor>(str)
- .Case("gnu", Flavor::gnu_ld)
- .Case("darwin", Flavor::darwin_ld)
- .Case("link", Flavor::win_link)
- .Case("core", Flavor::core)
- .Case("ld", Flavor::gnu_ld) // deprecated
- .Default(Flavor::invalid);
}
+namespace lld {
+bool UniversalDriver::link(int argc, const char *argv[],
+ raw_ostream &diagnostics) {
+ // Convert argv[] C-array to vector.
+ std::vector<const char *> args(argv, argv + argc);
+
+ // Determine flavor of link based on command name or -flavor argument.
+ // Note: 'args' is modified to remove -flavor option.
+ Flavor flavor = selectFlavor(args, diagnostics);
-} // namespace lld
+ // Switch to appropriate driver.
+ switch (flavor) {
+ case Flavor::gnu_ld:
+ return GnuLdDriver::linkELF(args.size(), args.data(), diagnostics);
+ case Flavor::darwin_ld:
+ return DarwinLdDriver::linkMachO(args.size(), args.data(), diagnostics);
+ case Flavor::core:
+ return CoreDriver::link(args.size(), args.data(), diagnostics);
+ case Flavor::win_link:
+ llvm_unreachable("Unsupported flavor");
+ case Flavor::invalid:
+ return true;
+ }
+}
+} // end namespace lld
Modified: lld/trunk/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/CMakeLists.txt?rev=178798&r1=178797&r2=178798&view=diff
==============================================================================
--- lld/trunk/unittests/CMakeLists.txt (original)
+++ lld/trunk/unittests/CMakeLists.txt Thu Apr 4 17:04:16 2013
@@ -7,12 +7,8 @@ set_target_properties(LLDUnitTests PROPE
# Produces a binary named 'basename(test_dirname)'.
function(add_lld_unittest test_dirname)
add_unittest(LLDUnitTests ${test_dirname} ${ARGN})
+ target_link_libraries(${test_dirname} ${LLVM_COMMON_LIBS})
endfunction()
-set(LLVM_LINK_COMPONENTS
- support
- )
-
-add_lld_unittest(CoreTests
- RangeTest.cpp
- )
+add_subdirectory(CoreTests)
+add_subdirectory(DriverTests)
Added: lld/trunk/unittests/CoreTests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/CoreTests/CMakeLists.txt?rev=178798&view=auto
==============================================================================
--- lld/trunk/unittests/CoreTests/CMakeLists.txt (added)
+++ lld/trunk/unittests/CoreTests/CMakeLists.txt Thu Apr 4 17:04:16 2013
@@ -0,0 +1,3 @@
+add_lld_unittest(CoreTests
+ RangeTest.cpp
+ )
Copied: lld/trunk/unittests/CoreTests/RangeTest.cpp (from r178788, lld/trunk/unittests/RangeTest.cpp)
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/CoreTests/RangeTest.cpp?p2=lld/trunk/unittests/CoreTests/RangeTest.cpp&p1=lld/trunk/unittests/RangeTest.cpp&r1=178788&r2=178798&rev=178798&view=diff
==============================================================================
(empty)
Added: lld/trunk/unittests/DriverTests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/CMakeLists.txt?rev=178798&view=auto
==============================================================================
--- lld/trunk/unittests/DriverTests/CMakeLists.txt (added)
+++ lld/trunk/unittests/DriverTests/CMakeLists.txt Thu Apr 4 17:04:16 2013
@@ -0,0 +1,7 @@
+add_lld_unittest(DriverTests
+ UniversalDriverTest.cpp
+ )
+
+target_link_libraries(DriverTests
+ lldDriver
+ )
Added: lld/trunk/unittests/DriverTests/UniversalDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/UniversalDriverTest.cpp?rev=178798&view=auto
==============================================================================
--- lld/trunk/unittests/DriverTests/UniversalDriverTest.cpp (added)
+++ lld/trunk/unittests/DriverTests/UniversalDriverTest.cpp Thu Apr 4 17:04:16 2013
@@ -0,0 +1,35 @@
+//===- 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" };
+
+ std::string diags;
+ raw_string_ostream os(diags);
+ UniversalDriver::link(array_lengthof(args), 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);
+}
Removed: lld/trunk/unittests/RangeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/RangeTest.cpp?rev=178797&view=auto
==============================================================================
--- lld/trunk/unittests/RangeTest.cpp (original)
+++ lld/trunk/unittests/RangeTest.cpp (removed)
@@ -1,245 +0,0 @@
-//===- lld/unittest/RangeTest.cpp -----------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief range.h unit tests.
-///
-//===----------------------------------------------------------------------===//
-
-#include "gtest/gtest.h"
-
-#include "lld/Core/range.h"
-
-#include <assert.h>
-#include <array>
-#include <deque>
-#include <forward_list>
-#include <iterator>
-#include <list>
-#include <numeric>
-#include <sstream>
-#include <vector>
-
-template <typename T, typename U> struct AssertTypesSame;
-template <typename T> struct AssertTypesSame<T, T> {};
-#define ASSERT_TYPES_SAME(T, U) AssertTypesSame<T, U>()
-
-struct no_begin {};
-struct member_begin {
- int *begin();
-};
-struct free_begin {};
-int *begin(free_begin);
-
-template <typename T>
-auto type_of_forward(T &&t) -> decltype(std::forward<T>(t)) {
- return std::forward<T>(t);
-}
-
-template <typename To> To implicit_cast(To val) { return val; }
-
-void test_traits() {
- using namespace lld::detail;
- ASSERT_TYPES_SAME(begin_result<no_begin>::type, undefined);
- // This causes clang to segfault.
-#if 0
- ASSERT_TYPES_SAME(
- begin_result<decltype(type_of_forward(member_begin()))>::type, int *);
-#endif
- ASSERT_TYPES_SAME(begin_result<free_begin>::type, int *);
-}
-
-TEST(Range, constructors) {
- std::vector<int> v(5);
- std::iota(v.begin(), v.end(), 0);
- lld::range<std::vector<int>::iterator> r = v;
- EXPECT_EQ(v.begin(), r.begin());
- EXPECT_EQ(v.end(), r.end());
-
- int arr[] = { 1, 2, 3, 4, 5 };
- std::begin(arr);
- lld::range<int *> r2 = arr;
- EXPECT_EQ(5, r2.back());
-}
-
-TEST(Range, conversion_to_pointer_range) {
- std::vector<int> v(5);
- std::iota(v.begin(), v.end(), 0);
- lld::range<int *> r = v;
- EXPECT_EQ(&*v.begin(), r.begin());
- EXPECT_EQ(2, r[2]);
-}
-
-template <typename Iter> void takes_range(lld::range<Iter> r) {
- int expected = 0;
- for (int val : r) {
- EXPECT_EQ(expected++, val);
- }
-}
-
-void takes_ptr_range(lld::range<const int *> r) {
- int expected = 0;
- for (int val : r) {
- EXPECT_EQ(expected++, val);
- }
-}
-
-TEST(Range, passing) {
- using lld::make_range;
- using lld::make_ptr_range;
- std::list<int> l(5);
- std::iota(l.begin(), l.end(), 0);
- takes_range(make_range(l));
- takes_range(make_range(implicit_cast<const std::list<int> &>(l)));
- std::deque<int> d(5);
- std::iota(d.begin(), d.end(), 0);
- takes_range(make_range(d));
- takes_range(make_range(implicit_cast<const std::deque<int> &>(d)));
- std::vector<int> v(5);
- std::iota(v.begin(), v.end(), 0);
- takes_range(make_range(v));
- takes_range(make_range(implicit_cast<const std::vector<int> &>(v)));
- // MSVC Can't compile make_ptr_range.
-#ifndef _MSC_VER
- static_assert(
- std::is_same<decltype(make_ptr_range(v)), lld::range<int *> >::value,
- "make_ptr_range should return a range of pointers");
- takes_range(make_ptr_range(v));
- takes_range(make_ptr_range(implicit_cast<const std::vector<int> &>(v)));
-#endif
- int arr[] = { 0, 1, 2, 3, 4 };
- takes_range(make_range(arr));
- const int carr[] = { 0, 1, 2, 3, 4 };
- takes_range(make_range(carr));
-
- takes_ptr_range(v);
- takes_ptr_range(implicit_cast<const std::vector<int> &>(v));
- takes_ptr_range(arr);
- takes_ptr_range(carr);
-}
-
-TEST(Range, access) {
- std::array<int, 5> a = { { 1, 2, 3, 4, 5 } };
- lld::range<decltype(a.begin())> r = a;
- EXPECT_EQ(4, r[3]);
- EXPECT_EQ(4, r[-2]);
-}
-
-template <bool b> struct CompileAssert;
-template <> struct CompileAssert<true> {};
-
-#if __has_feature(cxx_constexpr)
-constexpr int arr[] = { 1, 2, 3, 4, 5 };
-TEST(Range, constexpr) {
- constexpr lld::range<const int *> r(arr, arr + 5);
- CompileAssert<r.front() == 1>();
- CompileAssert<r.size() == 5>();
- CompileAssert<r[4] == 5>();
-}
-#endif
-
-template <typename Container> void test_slice() {
- Container cont(10);
- std::iota(cont.begin(), cont.end(), 0);
- lld::range<decltype(cont.begin())> r = cont;
-
- // One argument.
- EXPECT_EQ(10, r.slice(0).size());
- EXPECT_EQ(8, r.slice(2).size());
- EXPECT_EQ(2, r.slice(2).front());
- EXPECT_EQ(1, r.slice(-1).size());
- EXPECT_EQ(9, r.slice(-1).front());
-
- // Two positive arguments.
- EXPECT_TRUE(r.slice(5, 2).empty());
- EXPECT_EQ(next(cont.begin(), 5), r.slice(5, 2).begin());
- EXPECT_EQ(1, r.slice(1, 2).size());
- EXPECT_EQ(1, r.slice(1, 2).front());
-
- // Two negative arguments.
- EXPECT_TRUE(r.slice(-2, -5).empty());
- EXPECT_EQ(next(cont.begin(), 8), r.slice(-2, -5).begin());
- EXPECT_EQ(1, r.slice(-2, -1).size());
- EXPECT_EQ(8, r.slice(-2, -1).front());
-
- // Positive start, negative stop.
- EXPECT_EQ(1, r.slice(6, -3).size());
- EXPECT_EQ(6, r.slice(6, -3).front());
- EXPECT_TRUE(r.slice(6, -5).empty());
- EXPECT_EQ(next(cont.begin(), 6), r.slice(6, -5).begin());
-
- // Negative start, positive stop.
- EXPECT_TRUE(r.slice(-3, 6).empty());
- EXPECT_EQ(next(cont.begin(), 7), r.slice(-3, 6).begin());
- EXPECT_EQ(1, r.slice(-5, 6).size());
- EXPECT_EQ(5, r.slice(-5, 6).front());
-}
-
-TEST(Range, slice) {
- // -fsanitize=undefined complains about this, but only if optimizations are
- // enabled.
-#if 0
- test_slice<std::forward_list<int> >();
-#endif
- test_slice<std::list<int> >();
- // gcc doesn't like this.
-#if !(defined(__GNUC__) && !defined(__clang__)) || defined(_MSC_VER)
- test_slice<std::deque<int> >();
-#endif
-}
-
-// This test is flaky and I've yet to pin down why. Changing between
-// EXPECT_EQ(1, input.front()) and EXPECT_TRUE(input.front() == 1) makes it work
-// with VS 2012 in Debug mode. Clang on Linux seems to fail with -03 and -02 -g
-// -fsanitize=undefined.
-#if 0
-TEST(Range, istream_range) {
- std::istringstream stream("1 2 3 4 5");
- // MSVC interprets input as a function declaration if you don't declare start
- // and instead directly pass std::istream_iterator<int>(stream).
- auto start = std::istream_iterator<int>(stream);
- lld::range<std::istream_iterator<int> > input(
- start, std::istream_iterator<int>());
- EXPECT_TRUE(input.front() == 1);
- input.pop_front();
- EXPECT_TRUE(input.front() == 2);
- input.pop_front(2);
- EXPECT_TRUE(input.front() == 4);
- input.pop_front_upto(7);
- EXPECT_TRUE(input.empty());
-}
-#endif
-
-//! [algorithm using range]
-template <typename T> void partial_sum(T &container) {
- using lld::make_range;
- auto range = make_range(container);
- typename T::value_type sum = 0;
- // One would actually use a range-based for loop
- // in this case, but you get the idea:
- for (; !range.empty(); range.pop_front()) {
- sum += range.front();
- range.front() = sum;
- }
-}
-
-TEST(Range, user1) {
- std::vector<int> v(5, 2);
- partial_sum(v);
- EXPECT_EQ(8, v[3]);
-}
-//! [algorithm using range]
-
-//! [algorithm using ptr_range]
-void my_write(int fd, lld::range<const char *> buffer) {}
-
-TEST(Range, user2) {
- std::string s("Hello world");
- my_write(1, s);
-}
More information about the llvm-commits
mailing list