[llvm-commits] [lld] r169659 - in /lld/trunk: include/lld/Core/ErrorOr.h include/lld/Driver/ include/lld/Driver/Driver.h include/lld/Driver/LinkerInvocation.h include/lld/Driver/LinkerOptions.h include/lld/Driver/Target.h lib/CMakeLists.txt lib/Driver/ lib/Driver/CMakeLists.txt lib/Driver/CoreOptions.td lib/Driver/Driver.cpp lib/Driver/Drivers.cpp lib/Driver/LDOptions.td lib/Driver/LinkerInvocation.cpp lib/Driver/Target.cpp lib/Driver/Targets.cpp tools/lld/CMakeLists.txt tools/lld/lld.cpp

Michael Spencer bigcheesegs at gmail.com
Fri Dec 7 17:26:42 PST 2012


On Fri, Dec 7, 2012 at 4:58 PM, Nick Kledzik <kledzik at apple.com> wrote:
> Michael,
>
> Is there some documentation on how to use the new options infrastructure?

Not yet.

>
> Do you plan to switch all of lld (e.g. readFile() and friends) to start using ErrorOr?

Yes. I will eventually try to switch parts of llvm over too.

- Michael Spencer

>
> -Nick
>
>
> On Dec 7, 2012, at 4:47 PM, Michael J. Spencer wrote:
>> Author: mspencer
>> Date: Fri Dec  7 18:47:36 2012
>> New Revision: 169659
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=169659&view=rev
>> Log:
>> Add the core architecture for the lld driver.
>>
>> This includes selecting which driver to emulate, option parsing, invocation
>> building, and running the link. This currently only supports a very basic
>> subset of ld for x86_64-linux.
>>
>> lld -flavor ld obj.o -o obj
>>
>> or symlink lld as (ld , link, ld64, core) to get the desired behavior without
>> -flavor.
>>
>> Added:
>>    lld/trunk/include/lld/Core/ErrorOr.h
>>    lld/trunk/include/lld/Driver/
>>    lld/trunk/include/lld/Driver/Driver.h
>>    lld/trunk/include/lld/Driver/LinkerInvocation.h
>>    lld/trunk/include/lld/Driver/LinkerOptions.h
>>    lld/trunk/include/lld/Driver/Target.h
>>    lld/trunk/lib/Driver/
>>    lld/trunk/lib/Driver/CMakeLists.txt
>>    lld/trunk/lib/Driver/CoreOptions.td
>>    lld/trunk/lib/Driver/Driver.cpp
>>    lld/trunk/lib/Driver/Drivers.cpp
>>    lld/trunk/lib/Driver/LDOptions.td
>>    lld/trunk/lib/Driver/LinkerInvocation.cpp
>>    lld/trunk/lib/Driver/Target.cpp
>>    lld/trunk/lib/Driver/Targets.cpp
>> Modified:
>>    lld/trunk/lib/CMakeLists.txt
>>    lld/trunk/tools/lld/CMakeLists.txt
>>    lld/trunk/tools/lld/lld.cpp
>>
>> Added: lld/trunk/include/lld/Core/ErrorOr.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/ErrorOr.h?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/include/lld/Core/ErrorOr.h (added)
>> +++ lld/trunk/include/lld/Core/ErrorOr.h Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,213 @@
>> +//===- lld/Core/ErrorOr.h - Error Smart Pointer ---------------------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +///
>> +/// \file
>> +///
>> +/// Provides ErrorOr<T> smart pointer.
>> +///
>> +/// This should be moved to LLVMSupport when someone has time to make it c++03.
>> +///
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLD_CORE_ERROR_OR_H
>> +#define LLD_CORE_ERROR_OR_H
>> +
>> +#include "llvm/Support/AlignOf.h"
>> +#include "llvm/Support/system_error.h"
>> +
>> +#include <cassert>
>> +#include <type_traits>
>> +
>> +namespace lld {
>> +template<class T>
>> +class ErrorOrBase {
>> +  static const bool isRef = std::is_reference<T>::value;
>> +  typedef std::reference_wrapper<typename std::remove_reference<T>::type> wrap;
>> +
>> +public:
>> +  typedef typename
>> +    std::conditional< isRef
>> +                    , wrap
>> +                    , T
>> +                    >::type storage_type;
>> +
>> +private:
>> +  typedef T &reference;
>> +  typedef typename std::remove_reference<T>::type *pointer;
>> +
>> +  ErrorOrBase(const ErrorOrBase&) LLVM_DELETED_FUNCTION;
>> +  ErrorOrBase &operator =(const ErrorOrBase&) LLVM_DELETED_FUNCTION;
>> +  ErrorOrBase(ErrorOrBase &&other) LLVM_DELETED_FUNCTION;
>> +  ErrorOrBase &operator =(ErrorOrBase &&other) LLVM_DELETED_FUNCTION;
>> +
>> +public:
>> +  ErrorOrBase() : _error(llvm::make_error_code(llvm::errc::invalid_argument)) {}
>> +
>> +  ErrorOrBase(llvm::error_code ec) {
>> +    if (!_error)
>> +      get()->~storage_type();
>> +    _error = ec;
>> +  }
>> +
>> +  ErrorOrBase(T t) : _error(llvm::error_code::success()) {
>> +    new (get()) storage_type(t);
>> +  }
>> +
>> +  ~ErrorOrBase() {
>> +    if (!_error)
>> +      get()->~storage_type();
>> +  }
>> +
>> +  /// \brief Return false if there is an error.
>> +  operator bool() {
>> +    return !_error;
>> +  }
>> +
>> +  operator llvm::error_code() {
>> +    return _error;
>> +  }
>> +
>> +  operator reference() {
>> +    return *get();
>> +  }
>> +
>> +  pointer operator ->() {
>> +    return toPointer(get());
>> +  }
>> +
>> +  reference operator *() {
>> +    return *get();
>> +  }
>> +
>> +private:
>> +  pointer toPointer(pointer t) {
>> +    return t;
>> +  }
>> +
>> +  pointer toPointer(wrap *t) {
>> +    return &t->get();
>> +  }
>> +
>> +protected:
>> +  storage_type *get() {
>> +    assert(!_error && "T not valid!");
>> +    return reinterpret_cast<storage_type*>(_t.buffer);
>> +  }
>> +
>> +  llvm::error_code _error;
>> +  llvm::AlignedCharArrayUnion<storage_type> _t;
>> +};
>> +
>> +/// \brief Represents either an error or a value T.
>> +///
>> +/// ErrorOr<T> is a pointer-like class that represents the result of an
>> +/// operation. The result is either an error, or a value of type T. This is
>> +/// designed to emulate the usage of returning a pointer where nullptr indicates
>> +/// failure. However instead of just knowing that the operation failed, we also
>> +/// have an error_code that describes why it failed.
>> +///
>> +/// It is used like the following.
>> +/// \code
>> +///   ErrorOr<Buffer> getBuffer();
>> +///   void handleError(error_code ec);
>> +///
>> +///   auto buffer = getBuffer();
>> +///   if (!buffer)
>> +///     handleError(buffer);
>> +///   buffer->write("adena");
>> +/// \endcode
>> +///
>> +/// An implicit conversion to bool provides a way to check if there was an
>> +/// error. The unary * and -> operators provide pointer like access to the
>> +/// value. Accessing the value when there is an error has undefined behavior.
>> +///
>> +/// When T is a reference type the behaivor is slightly different. The reference
>> +/// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and
>> +/// there is special handling to make operator -> work as if T was not a
>> +/// reference.
>> +///
>> +/// T cannot be a rvalue reference.
>> +template<class T,
>> +  bool isMoveable =
>> +    std::is_move_constructible<typename ErrorOrBase<T>::storage_type>::value>
>> +class ErrorOr;
>> +
>> +template<class T>
>> +class ErrorOr<T, true> : public ErrorOrBase<T> {
>> +  ErrorOr(const ErrorOr &other) LLVM_DELETED_FUNCTION;
>> +  ErrorOr &operator =(const ErrorOr &other) LLVM_DELETED_FUNCTION;
>> +public:
>> +  ErrorOr(llvm::error_code ec) : ErrorOrBase<T>(ec) {}
>> +  ErrorOr(T t) : ErrorOrBase<T>(t) {}
>> +  ErrorOr(ErrorOr &&other) : ErrorOrBase<T>() {
>> +    // Get the other value.
>> +    if (!other._error)
>> +      new (this->get())
>> +        typename ErrorOrBase<T>::storage_type(std::move(*other.get()));
>> +
>> +    // Get the other error.
>> +    this->_error = other._error;
>> +
>> +    // Make sure other doesn't try to delete its storage.
>> +    other._error = llvm::make_error_code(llvm::errc::invalid_argument);
>> +  }
>> +
>> +  ErrorOr &operator =(ErrorOr &&other) {
>> +    // Delete any existing value.
>> +    if (!this->_error)
>> +      this->get()->~storage_type();
>> +
>> +    // Get the other value.
>> +    if (!other._error)
>> +      new (this->get())
>> +        typename ErrorOrBase<T>::storage_type(std::move(*other.get()));
>> +
>> +    // Get the other error.
>> +    this->_error = other._error;
>> +
>> +    // Make sure other doesn't try to delete its storage.
>> +    other._error = llvm::make_error_code(llvm::errc::invalid_argument);
>> +  }
>> +};
>> +
>> +template<class T>
>> +class ErrorOr<T, false> : public ErrorOrBase<T> {
>> +  static_assert(std::is_copy_constructible<T>::value,
>> +                "T must be copy or move constructible!");
>> +
>> +  ErrorOr(ErrorOr &&other) LLVM_DELETED_FUNCTION;
>> +  ErrorOr &operator =(ErrorOr &&other) LLVM_DELETED_FUNCTION;
>> +public:
>> +  ErrorOr(llvm::error_code ec) : ErrorOrBase<T>(ec) {}
>> +  ErrorOr(T t) : ErrorOrBase<T>(t) {}
>> +  ErrorOr(const ErrorOr &other) : ErrorOrBase<T>() {
>> +    // Get the other value.
>> +    if (!other._error)
>> +      new (this->get()) typename ErrorOrBase<T>::storage_type(*other.get());
>> +
>> +    // Get the other error.
>> +    this->_error = other._error;
>> +  }
>> +
>> +  ErrorOr &operator =(const ErrorOr &other) {
>> +    // Delete any existing value.
>> +    if (!this->_error)
>> +      this->get()->~storage_type();
>> +
>> +    // Get the other value.
>> +    if (!other._error)
>> +      new (this->get()) typename ErrorOrBase<T>::storage_type(*other.get());
>> +
>> +    // Get the other error.
>> +    this->_error = other._error;
>> +  }
>> +};
>> +}
>> +
>> +#endif
>>
>> Added: lld/trunk/include/lld/Driver/Driver.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/Driver.h?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/include/lld/Driver/Driver.h (added)
>> +++ lld/trunk/include/lld/Driver/Driver.h Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,64 @@
>> +//===- lld/Driver/Driver.h - Linker Driver Emulator -----------------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +///
>> +/// \file
>> +///
>> +/// Interface and factory for creating a specific driver emulator. A Driver is
>> +/// used to transform command line arguments into command line arguments for
>> +/// core. Core arguments are used to generate a LinkerOptions object.
>> +///
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLD_DRIVER_DRIVER_H
>> +#define LLD_DRIVER_DRIVER_H
>> +
>> +#include "lld/Core/LLVM.h"
>> +
>> +#include "llvm/Option/ArgList.h"
>> +
>> +#include <memory>
>> +#include <string>
>> +
>> +namespace lld {
>> +struct LinkerOptions;
>> +
>> +/// \brief Base class for all Drivers.
>> +class Driver {
>> +protected:
>> +  Driver(StringRef defaultTargetTriple)
>> +    : _defaultTargetTriple(defaultTargetTriple) {}
>> +
>> +  std::string _defaultTargetTriple;
>> +
>> +public:
>> +  enum class Flavor {
>> +    invalid,
>> +    ld,
>> +    link,
>> +    ld64,
>> +    core
>> +  };
>> +
>> +  virtual ~Driver();
>> +
>> +  virtual std::unique_ptr<llvm::opt::DerivedArgList>
>> +    transform(llvm::ArrayRef<const char *const> args) = 0;
>> +
>> +  /// \param flavor driver flavor to create.
>> +  /// \param defaultTargetTriple target triple as determined by the program name
>> +  ///        or host. May be overridden by -target.
>> +  /// \returns the created driver.
>> +  static std::unique_ptr<Driver> create(Flavor flavor,
>> +                                        StringRef defaultTargetTriple);
>> +};
>> +
>> +LinkerOptions generateOptions(const llvm::opt::ArgList &args);
>> +} // end namespace lld
>> +
>> +#endif
>>
>> Added: lld/trunk/include/lld/Driver/LinkerInvocation.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/LinkerInvocation.h?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/include/lld/Driver/LinkerInvocation.h (added)
>> +++ lld/trunk/include/lld/Driver/LinkerInvocation.h Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,34 @@
>> +//===- lld/Driver/LinkerInvocation.h - Linker Invocation ------------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +///
>> +/// \file
>> +///
>> +/// Drives the actual link.
>> +///
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLD_DRIVER_LINKER_INVOCATION_H
>> +#define LLD_DRIVER_LINKER_INVOCATION_H
>> +
>> +#include "lld/Driver/LinkerOptions.h"
>> +
>> +namespace lld {
>> +class LinkerInvocation {
>> +public:
>> +  LinkerInvocation(const LinkerOptions &lo) : _options(lo) {}
>> +
>> +  /// \brief Perform the link.
>> +  void operator()();
>> +
>> +private:
>> +  const LinkerOptions &_options;
>> +};
>> +}
>> +
>> +#endif
>>
>> Added: lld/trunk/include/lld/Driver/LinkerOptions.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/LinkerOptions.h?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/include/lld/Driver/LinkerOptions.h (added)
>> +++ lld/trunk/include/lld/Driver/LinkerOptions.h Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,126 @@
>> +//===- lld/Driver/LinkerOptions.h - Linker Options ------------------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +///
>> +/// \file
>> +///
>> +/// All linker options to be provided to a LinkerInvocation.
>> +///
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLD_DRIVER_LINKER_OPTIONS_H
>> +#define LLD_DRIVER_LINKER_OPTIONS_H
>> +
>> +#include "lld/Core/ErrorOr.h"
>> +#include "lld/Core/LLVM.h"
>> +
>> +#include "llvm/ADT/StringRef.h"
>> +#include "llvm/ADT/StringSwitch.h"
>> +#include "llvm/Support/Compiler.h"
>> +#include "llvm/Support/FileSystem.h"
>> +#include "llvm/Support/MemoryBuffer.h"
>> +
>> +#include <memory>
>> +
>> +namespace lld {
>> +enum class InputKind {
>> +  Unknown,
>> +  YAML,
>> +  Native,
>> +  Object,
>> +  LLVM,
>> +  Script
>> +};
>> +
>> +class LinkerInput {
>> +  LinkerInput(const LinkerInput &) LLVM_DELETED_FUNCTION;
>> +
>> +public:
>> +  LinkerInput(StringRef file, InputKind kind = InputKind::Unknown)
>> +    : _file(file)
>> +    , _kind(kind) {}
>> +
>> +  LinkerInput(llvm::MemoryBuffer *buffer, InputKind kind = InputKind::Unknown)
>> +    : _buffer(buffer)
>> +    , _file(_buffer->getBufferIdentifier())
>> +    , _kind(kind) {}
>> +
>> +  LinkerInput(LinkerInput &&other)
>> +    : _buffer(std::move(other._buffer))
>> +    , _file(std::move(other._file))
>> +    , _kind(other._kind) {}
>> +
>> +  ErrorOr<llvm::MemoryBuffer&> getBuffer() const {
>> +    if (!_buffer) {
>> +      llvm::OwningPtr<llvm::MemoryBuffer> buf;
>> +      if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(_file, buf))
>> +        return ec;
>> +      _buffer.reset(buf.take());
>> +    }
>> +
>> +    return *_buffer;
>> +  }
>> +
>> +  ErrorOr<InputKind> getKind() const {
>> +    if (_kind == InputKind::Unknown) {
>> +      _kind = llvm::StringSwitch<InputKind>(getPath())
>> +        .EndsWith(".objtxt", InputKind::YAML)
>> +        .EndsWith(".yaml", InputKind::YAML)
>> +        .Default(InputKind::Unknown);
>> +
>> +      if (_kind != InputKind::Unknown)
>> +        return _kind;
>> +
>> +      auto buf = getBuffer();
>> +      if (!buf)
>> +        return error_code(buf);
>> +
>> +      llvm::sys::fs::file_magic magic =
>> +        llvm::sys::fs::identify_magic(buf->getBuffer());
>> +
>> +      switch (magic) {
>> +      case llvm::sys::fs::file_magic::elf_relocatable:
>> +        _kind = InputKind::Object;
>> +        break;
>> +      }
>> +    }
>> +
>> +    return _kind;
>> +  }
>> +
>> +  StringRef getPath() const {
>> +    return _file;
>> +  }
>> +
>> +private:
>> +  mutable std::unique_ptr<llvm::MemoryBuffer> _buffer;
>> +  std::string _file;
>> +  mutable InputKind _kind;
>> +};
>> +
>> +struct LinkerOptions {
>> +  LinkerOptions() {}
>> +  LinkerOptions(LinkerOptions &&other)
>> +    : _input(std::move(other._input))
>> +    , _target(std::move(other._target))
>> +    , _outputPath(std::move(other._outputPath))
>> +    , _entrySymbol(std::move(other._entrySymbol))
>> +    , _relocatable(other._relocatable) {}
>> +
>> +  std::vector<LinkerInput> _input;
>> +  std::string _target;
>> +  std::string _outputPath;
>> +  std::string _entrySymbol;
>> +  unsigned _relocatable : 1;
>> +
>> +private:
>> +  LinkerOptions(const LinkerOptions&) LLVM_DELETED_FUNCTION;
>> +};
>> +}
>> +
>> +#endif
>>
>> Added: lld/trunk/include/lld/Driver/Target.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/Target.h?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/include/lld/Driver/Target.h (added)
>> +++ lld/trunk/include/lld/Driver/Target.h Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,46 @@
>> +//===- lld/Driver/Target.h - Linker Target Abstraction --------------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +///
>> +/// \file
>> +///
>> +/// Interface and factory for creating a specific Target. A Target is used to
>> +/// encapsulate all of the target specific configurations for the linker.
>> +///
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLD_DRIVER_TARGET_H
>> +#define LLD_DRIVER_TARGET_H
>> +
>> +#include "lld/ReaderWriter/Reader.h"
>> +#include "lld/ReaderWriter/Writer.h"
>> +#include "lld/Driver/LinkerOptions.h"
>> +
>> +namespace lld {
>> +/// \brief Represents a specific target.
>> +class Target {
>> +public:
>> +  Target(const LinkerOptions &lo) : _options(lo) {}
>> +  virtual ~Target();
>> +
>> +  /// \brief Get a reference to a Reader for the given input.
>> +  ///
>> +  /// Will always return the same object for the same input.
>> +  virtual ErrorOr<lld::Reader&> getReader(const LinkerInput &input) = 0;
>> +
>> +  /// \brief Get the writer.
>> +  virtual ErrorOr<lld::Writer&> getWriter() = 0;
>> +
>> +  static std::unique_ptr<Target> create(const LinkerOptions&);
>> +
>> +protected:
>> +  const LinkerOptions &_options;
>> +};
>> +}
>> +
>> +#endif
>>
>> Modified: lld/trunk/lib/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/CMakeLists.txt?rev=169659&r1=169658&r2=169659&view=diff
>> ==============================================================================
>> --- lld/trunk/lib/CMakeLists.txt (original)
>> +++ lld/trunk/lib/CMakeLists.txt Fri Dec  7 18:47:36 2012
>> @@ -1,3 +1,4 @@
>> add_subdirectory(Core)
>> +add_subdirectory(Driver)
>> add_subdirectory(Passes)
>> add_subdirectory(ReaderWriter)
>>
>> Added: lld/trunk/lib/Driver/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/CMakeLists.txt?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/lib/Driver/CMakeLists.txt (added)
>> +++ lld/trunk/lib/Driver/CMakeLists.txt Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,29 @@
>> +set(LLVM_TARGET_DEFINITIONS LDOptions.td)
>> +tablegen(LLVM LDOptions.inc -gen-opt-parser-defs)
>> +set(LLVM_TARGET_DEFINITIONS CoreOptions.td)
>> +tablegen(LLVM CoreOptions.inc -gen-opt-parser-defs)
>> +add_public_tablegen_target(DriverOptionsTableGen)
>> +
>> +add_lld_library(lldDriver
>> +  Driver.cpp
>> +  Drivers.cpp
>> +  LinkerInvocation.cpp
>> +  Target.cpp
>> +  Targets.cpp
>> +  )
>> +
>> +add_dependencies(lldDriver DriverOptionsTableGen)
>> +
>> +target_link_libraries(lldDriver
>> +  lldPasses
>> +  lldMachO
>> +  lldPECOFF
>> +  lldELF
>> +  lldNative
>> +  lldReaderWriter
>> +  lldYAML
>> +  lldCore
>> +  LLVMObject
>> +  LLVMOption
>> +  LLVMSupport
>> +  )
>>
>> Added: lld/trunk/lib/Driver/CoreOptions.td
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/CoreOptions.td?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/lib/Driver/CoreOptions.td (added)
>> +++ lld/trunk/lib/Driver/CoreOptions.td Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,7 @@
>> +include "llvm/Option/OptParser.td"
>> +
>> +def target : Separate<["-"], "target">, HelpText<"Target triple to link for">;
>> +
>> +def output : Joined<["-"], "output=">;
>> +def entry : Joined<["-"], "entry=">;
>> +def relocatable : Flag<["-"], "relocatable">;
>>
>> Added: lld/trunk/lib/Driver/Driver.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Driver.cpp?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/lib/Driver/Driver.cpp (added)
>> +++ lld/trunk/lib/Driver/Driver.cpp Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,14 @@
>> +//===- lib/Driver/Driver.cpp - Linker Driver Emulator ---------------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "lld/Driver/Driver.h"
>> +
>> +using namespace lld;
>> +
>> +Driver::~Driver() {}
>>
>> Added: lld/trunk/lib/Driver/Drivers.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Drivers.cpp?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/lib/Driver/Drivers.cpp (added)
>> +++ lld/trunk/lib/Driver/Drivers.cpp Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,180 @@
>> +//===- lib/Driver/Drivers.cpp - Linker Driver Emulators -------------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +///
>> +/// \file
>> +///
>> +/// Concrete instances of the Driver interface.
>> +///
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "lld/Driver/Driver.h"
>> +
>> +#include "lld/Driver/LinkerOptions.h"
>> +
>> +#include "llvm/ADT/ArrayRef.h"
>> +#include "llvm/ADT/STLExtras.h"
>> +#include "llvm/ADT/Triple.h"
>> +#include "llvm/Option/Arg.h"
>> +#include "llvm/Option/Option.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +
>> +using namespace lld;
>> +
>> +namespace core {
>> +enum ID {
>> +  OPT_INVALID = 0,
>> +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, HELP, META) \
>> +          OPT_##ID,
>> +#include "CoreOptions.inc"
>> +  LastOption
>> +#undef OPTION
>> +};
>> +
>> +#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
>> +#include "CoreOptions.inc"
>> +#undef PREFIX
>> +
>> +static const llvm::opt::OptTable::Info InfoTable[] = {
>> +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
>> +               HELPTEXT, METAVAR)   \
>> +  { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
>> +    PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS },
>> +#include "CoreOptions.inc"
>> +#undef OPTION
>> +};
>> +
>> +class CoreOptTable : public llvm::opt::OptTable {
>> +public:
>> +  CoreOptTable() : OptTable(InfoTable, llvm::array_lengthof(InfoTable)){}
>> +};
>> +}
>> +
>> +namespace ld {
>> +enum LDOpt {
>> +  OPT_INVALID = 0,
>> +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, HELP, META) \
>> +          OPT_##ID,
>> +#include "LDOptions.inc"
>> +  LastOption
>> +#undef OPTION
>> +};
>> +
>> +#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
>> +#include "LDOptions.inc"
>> +#undef PREFIX
>> +
>> +static const llvm::opt::OptTable::Info InfoTable[] = {
>> +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
>> +               HELPTEXT, METAVAR)   \
>> +  { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
>> +    PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS },
>> +#include "LDOptions.inc"
>> +#undef OPTION
>> +};
>> +
>> +class LDOptTable : public llvm::opt::OptTable {
>> +public:
>> +  LDOptTable() : OptTable(InfoTable, llvm::array_lengthof(InfoTable)){}
>> +};
>> +}
>> +
>> +class LDDriver final : public Driver {
>> +public:
>> +  LDDriver(StringRef defaultTargetTriple) : Driver(defaultTargetTriple) {}
>> +
>> +  virtual std::unique_ptr<llvm::opt::DerivedArgList>
>> +  transform(llvm::ArrayRef<const char *const> args) {
>> +    assert(!_inputArgs && "transform may only be called once!");
>> +
>> +    unsigned missingIndex, missingCount;
>> +    _inputArgs.reset(_opt.ParseArgs( args.begin(), args.end()
>> +                                   , missingIndex, missingCount));
>> +
>> +    if (missingCount) {
>> +      llvm::errs() << "error: missing arg value for '"
>> +                   << _inputArgs->getArgString(missingIndex)
>> +                   << "' expected " << missingCount << " argument(s).\n";
>> +      return std::unique_ptr<llvm::opt::DerivedArgList>();
>> +    }
>> +
>> +    std::unique_ptr<llvm::opt::DerivedArgList> newArgs(
>> +      new llvm::opt::DerivedArgList(*_inputArgs));
>> +
>> +    if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_target)) {
>> +      llvm::errs() << A->getValue() << "\n";
>> +      newArgs->AddSeparateArg( A, _core.getOption(core::OPT_target)
>> +                             , A->getValue());
>> +      llvm::errs() << A->getValue() << "\n";
>> +    } else {
>> +      assert(!_defaultTargetTriple.empty() && "Got empty target triple!");
>> +      newArgs->AddSeparateArg(nullptr, _core.getOption(core::OPT_target)
>> +                             , _defaultTargetTriple);
>> +    }
>> +
>> +    if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_entry))
>> +      newArgs->AddJoinedArg(A, _core.getOption(core::OPT_entry), A->getValue());
>> +    else
>> +      newArgs->AddJoinedArg(nullptr, _core.getOption(core::OPT_entry), "start");
>> +
>> +    if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_output))
>> +      newArgs->AddJoinedArg(A, _core.getOption(core::OPT_output),
>> +                            A->getValue());
>> +    else
>> +      newArgs->AddJoinedArg(nullptr, _core.getOption(core::OPT_output),
>> +                            "a.out");
>> +
>> +    if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_relocatable))
>> +      newArgs->AddFlagArg(A, _core.getOption(core::OPT_relocatable));
>> +
>> +    // Copy input args.
>> +    for (llvm::opt::arg_iterator it = _inputArgs->filtered_begin(ld::OPT_INPUT),
>> +                                 ie = _inputArgs->filtered_end();
>> +                                 it != ie; ++it) {
>> +      newArgs->AddPositionalArg(*it, _core.getOption(core::OPT_INPUT),
>> +                                (*it)->getValue());
>> +    }
>> +
>> +    return std::move(newArgs);
>> +  }
>> +
>> +private:
>> +  std::unique_ptr<llvm::opt::InputArgList> _inputArgs;
>> +  core::CoreOptTable _core;
>> +  ld::LDOptTable _opt;
>> +};
>> +
>> +std::unique_ptr<Driver> Driver::create( Driver::Flavor flavor
>> +                                      , StringRef defaultTargetTriple) {
>> +  switch (flavor) {
>> +  case Flavor::ld:
>> +    return std::unique_ptr<Driver>(new LDDriver(defaultTargetTriple));
>> +  case Flavor::core:
>> +  case Flavor::ld64:
>> +  case Flavor::link:
>> +  case Flavor::invalid:
>> +    llvm_unreachable("Unsupported flavor");
>> +  }
>> +}
>> +
>> +LinkerOptions lld::generateOptions(const llvm::opt::ArgList &args) {
>> +  LinkerOptions ret;
>> +
>> +  for (llvm::opt::arg_iterator it = args.filtered_begin(ld::OPT_INPUT),
>> +                               ie = args.filtered_end();
>> +                               it != ie; ++it) {
>> +    ret._input.push_back(LinkerInput((*it)->getValue(), InputKind::Object));
>> +  }
>> +
>> +  ret._target = llvm::Triple::normalize(args.getLastArgValue(core::OPT_target));
>> +  ret._outputPath = args.getLastArgValue(core::OPT_output);
>> +  ret._entrySymbol = args.getLastArgValue(core::OPT_entry);
>> +  ret._relocatable = args.hasArg(core::OPT_relocatable);
>> +
>> +  return std::move(ret);
>> +}
>>
>> Added: lld/trunk/lib/Driver/LDOptions.td
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/LDOptions.td?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/lib/Driver/LDOptions.td (added)
>> +++ lld/trunk/lib/Driver/LDOptions.td Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,13 @@
>> +include "llvm/Option/OptParser.td"
>> +
>> +def flavor : Separate<["-"], "flavor">;
>> +def target : Separate<["-"], "target">, HelpText<"Target triple to link for">;
>> +
>> +def entry : Joined<["--"], "entry=">;
>> +def entry_e : Separate<["-"], "e">, Alias<entry>;
>> +
>> +def output : Joined<["--"], "output=">;
>> +def output_e : Separate<["-"], "o">, Alias<output>;
>> +
>> +def relocatable : Flag<["--"], "relocatable">;
>> +def relocatable_r : Flag<["-"], "r">, Alias<relocatable>;
>>
>> Added: lld/trunk/lib/Driver/LinkerInvocation.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/LinkerInvocation.cpp?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/lib/Driver/LinkerInvocation.cpp (added)
>> +++ lld/trunk/lib/Driver/LinkerInvocation.cpp Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,70 @@
>> +//===- lib/Driver/LinkerInvocation.cpp - Linker Invocation ----------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "lld/Driver/LinkerInvocation.h"
>> +
>> +#include "lld/Core/InputFiles.h"
>> +#include "lld/Core/Resolver.h"
>> +#include "lld/Driver/Target.h"
>> +
>> +#include "llvm/Support/raw_ostream.h"
>> +
>> +using namespace lld;
>> +
>> +void LinkerInvocation::operator()() {
>> +    // Create target.
>> +    std::unique_ptr<Target> target(Target::create(_options));
>> +
>> +    if (!target) {
>> +      llvm::errs() << "Failed to create target for " << _options._target
>> +                   << "\n";
>> +      return;
>> +    }
>> +
>> +    // Read inputs
>> +    InputFiles inputs;
>> +    for (const auto &input : _options._input) {
>> +      auto reader = target->getReader(input);
>> +      if (error_code ec = reader) {
>> +        llvm::errs() << "Failed to get reader for: " << input.getPath() << ": "
>> +                     << ec.message() << "\n";
>> +        return;
>> +      }
>> +
>> +      auto buffer = input.getBuffer();
>> +      if (error_code ec = buffer) {
>> +        llvm::errs() << "Failed to read file: " << input.getPath() << ": "
>> +                     << ec.message() << "\n";
>> +        return;
>> +      }
>> +
>> +      std::vector<std::unique_ptr<File>> files;
>> +      if (llvm::error_code ec = reader->readFile(
>> +            buffer->getBufferIdentifier(), files)) {
>> +        llvm::errs() << "Failed to read file: " << input.getPath() << ": "
>> +                     << ec.message() << "\n";
>> +        return;
>> +      }
>> +      inputs.appendFiles(files);
>> +    }
>> +
>> +    ResolverOptions ro;
>> +    Resolver resolver(ro, inputs);
>> +    resolver.resolve();
>> +    File &merged = resolver.resultFile();
>> +
>> +    auto writer = target->getWriter();
>> +    if (error_code ec = writer) {
>> +      llvm::errs() << "Failed to get writer: " << ec.message() << ".\n";
>> +      return;
>> +    }
>> +
>> +    if (error_code ec = writer->writeFile(merged, _options._outputPath))
>> +      llvm::errs() << "Failed to write file: " << ec.message() << "\n";
>> +  }
>>
>> Added: lld/trunk/lib/Driver/Target.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Target.cpp?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/lib/Driver/Target.cpp (added)
>> +++ lld/trunk/lib/Driver/Target.cpp Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,14 @@
>> +//===- lib/Driver/Target.cpp - Linker Target Abstraction ------------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "lld/Driver/Target.h"
>> +
>> +using namespace lld;
>> +
>> +Target::~Target() {}
>>
>> Added: lld/trunk/lib/Driver/Targets.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Targets.cpp?rev=169659&view=auto
>> ==============================================================================
>> --- lld/trunk/lib/Driver/Targets.cpp (added)
>> +++ lld/trunk/lib/Driver/Targets.cpp Fri Dec  7 18:47:36 2012
>> @@ -0,0 +1,75 @@
>> +//===- lib/Driver/Targets.cpp - Linker Targets ----------------------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +///
>> +/// \file
>> +///
>> +/// Concrete instances of the Target interface.
>> +///
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "lld/Driver/Target.h"
>> +
>> +#include "lld/ReaderWriter/ReaderArchive.h"
>> +#include "lld/ReaderWriter/ReaderELF.h"
>> +#include "lld/ReaderWriter/ReaderYAML.h"
>> +#include "lld/ReaderWriter/WriterELF.h"
>> +
>> +#include "llvm/ADT/Triple.h"
>> +
>> +using namespace lld;
>> +
>> +class X86LinuxTarget final : public Target {
>> +public:
>> +  X86LinuxTarget(const LinkerOptions &lo) : Target(lo) {
>> +    _readerELF.reset(createReaderELF(_roe, _roa));
>> +    _readerYAML.reset(createReaderYAML(_roy));
>> +    _writer.reset(createWriterELF(_woe));
>> +  }
>> +
>> +  virtual ErrorOr<lld::Reader&> getReader(const LinkerInput &input) {
>> +    auto kind = input.getKind();
>> +    if (!kind)
>> +      return error_code(kind);
>> +
>> +    if (*kind == InputKind::YAML)
>> +      return *_readerYAML;
>> +
>> +    if (*kind == InputKind::Object)
>> +      return *_readerELF;
>> +
>> +    return llvm::make_error_code(llvm::errc::invalid_argument);
>> +  }
>> +
>> +  virtual ErrorOr<lld::Writer&> getWriter() {
>> +    return *_writer;
>> +  }
>> +
>> +private:
>> +  lld::ReaderOptionsELF _roe;
>> +  lld::ReaderOptionsArchive _roa;
>> +  struct : lld::ReaderOptionsYAML {
>> +    virtual Reference::Kind kindFromString(StringRef kindName) const {
>> +      int k;
>> +      if (kindName.getAsInteger(0, k))
>> +        k = 0;
>> +      return k;
>> +    }
>> +  } _roy;
>> +  lld::WriterOptionsELF _woe;
>> +
>> +  std::unique_ptr<lld::Reader> _readerELF, _readerYAML;
>> +  std::unique_ptr<lld::Writer> _writer;
>> +};
>> +
>> +std::unique_ptr<Target> Target::create(const LinkerOptions &lo) {
>> +  llvm::Triple t(lo._target);
>> +  if (t.getOS() == llvm::Triple::Linux && t.getArch() == llvm::Triple::x86_64)
>> +    return std::unique_ptr<Target>(new X86LinuxTarget(lo));
>> +  return std::unique_ptr<Target>();
>> +}
>>
>> Modified: lld/trunk/tools/lld/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld/CMakeLists.txt?rev=169659&r1=169658&r2=169659&view=diff
>> ==============================================================================
>> --- lld/trunk/tools/lld/CMakeLists.txt (original)
>> +++ lld/trunk/tools/lld/CMakeLists.txt Fri Dec  7 18:47:36 2012
>> @@ -2,5 +2,9 @@
>>   lld.cpp
>>   )
>>
>> +target_link_libraries(lld
>> +  lldDriver
>> +  )
>> +
>> install(TARGETS lld
>>   RUNTIME DESTINATION bin)
>>
>> Modified: lld/trunk/tools/lld/lld.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld/lld.cpp?rev=169659&r1=169658&r2=169659&view=diff
>> ==============================================================================
>> --- lld/trunk/tools/lld/lld.cpp (original)
>> +++ lld/trunk/tools/lld/lld.cpp Fri Dec  7 18:47:36 2012
>> @@ -1,4 +1,4 @@
>> -//===- tools/lld/lld.cpp - Linker Driver Dispatcher ---------------------===//
>> +//===- tools/lld/lld.cpp - Linker Driver Dispatcher -----------------------===//
>> //
>> //                             The LLVM Linker
>> //
>> @@ -6,12 +6,137 @@
>> // License. See LICENSE.TXT for details.
>> //
>> //===----------------------------------------------------------------------===//
>> -//
>> -// This is the entry point to the lld driver. This is a thin wrapper which
>> -// dispatches to the given platform specific driver.
>> -//
>> +///
>> +/// \file
>> +///
>> +/// This is the entry point to the lld driver. This is a thin wrapper which
>> +/// dispatches to the given platform specific driver.
>> +///
>> //===----------------------------------------------------------------------===//
>>
>> +#include "lld/Core/LLVM.h"
>> +#include "lld/Driver/Driver.h"
>> +#include "lld/Driver/LinkerInvocation.h"
>> +
>> +#include "llvm/ADT/ArrayRef.h"
>> +#include "llvm/ADT/SmallVector.h"
>> +#include "llvm/ADT/StringExtras.h"
>> +#include "llvm/ADT/StringRef.h"
>> +#include "llvm/ADT/StringSwitch.h"
>> +#include "llvm/Option/Arg.h"
>> +#include "llvm/Support/FileSystem.h"
>> +#include "llvm/Support/Host.h"
>> +#include "llvm/Support/ManagedStatic.h"
>> +#include "llvm/Support/PrettyStackTrace.h"
>> +#include "llvm/Support/Path.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +#include "llvm/Support/Signals.h"
>> +
>> +using namespace lld;
>> +
>> +Driver::Flavor strToFlavor(StringRef str) {
>> +  return llvm::StringSwitch<Driver::Flavor>(str)
>> +           .Case("ld", Driver::Flavor::ld)
>> +           .Case("link", Driver::Flavor::link)
>> +           .Case("ld64", Driver::Flavor::ld64)
>> +           .Case("core", Driver::Flavor::core)
>> +           .Default(Driver::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) != Driver::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;
>> +}
>> +
>> +/// \brief Pick the flavor of driver to use based on the command line and
>> +///        host environment.
>> +Driver::Flavor selectFlavor(int argc, const char * const * const argv) {
>> +  if (argc >= 2 && StringRef(argv[1]) == "-core")
>> +    return Driver::Flavor::core;
>> +  if (argc >= 3 && StringRef(argv[1]) == "-flavor") {
>> +    Driver::Flavor flavor = strToFlavor(argv[2]);
>> +    if (flavor == Driver::Flavor::invalid)
>> +      llvm::errs() << "error: '" << argv[2] << "' invalid value for -flavor.\n";
>> +    return flavor;
>> +  }
>> +
>> +  Driver::Flavor flavor = strToFlavor(
>> +    parseProgramName(llvm::sys::path::stem(argv[0]))._flavor);
>> +
>> +  if (flavor == Driver::Flavor::invalid)
>> +    llvm::errs() << "error: failed to determine driver flavor from program name"
>> +                    " '" << argv[0] << "'.\n";
>> +  return flavor;
>> +}
>> +
>> +/// \brief Get the default target triple based on either the program name or
>> +///        the primary target llvm was configured for.
>> +std::string getDefaultTarget(int argc, const char *const *const argv) {
>> +  std::string ret = parseProgramName(llvm::sys::path::stem(argv[0]))._target;
>> +  if (ret.empty())
>> +    ret = llvm::sys::getDefaultTargetTriple();
>> +  return ret;
>> +}
>> +
>> int main(int argc, char **argv) {
>> +  llvm::sys::PrintStackTraceOnErrorSignal();
>> +  llvm::PrettyStackTraceProgram X(argc, argv);
>> +  llvm::llvm_shutdown_obj Y;
>> +
>> +  Driver::Flavor iHazAFlavor = selectFlavor(argc, argv);
>> +  if (iHazAFlavor == Driver::Flavor::invalid)
>> +    return 1;
>> +
>> +  std::unique_ptr<llvm::opt::ArgList> coreArgs;
>> +  std::unique_ptr<Driver> driver;
>> +  if (iHazAFlavor != Driver::Flavor::core) {
>> +    // Transform to core arguments.
>> +    driver = Driver::create(iHazAFlavor, getDefaultTarget(argc, argv));
>> +    coreArgs = driver->transform(
>> +      llvm::ArrayRef<const char *const>(argv + 1, argv + argc));
>> +  }
>> +
>> +  if (!coreArgs)
>> +    return 1;
>> +
>> +  for (auto arg : *coreArgs) {
>> +    llvm::outs() << arg->getAsString(*coreArgs) << " ";
>> +  }
>> +  llvm::outs() << "\n";
>> +
>> +  LinkerOptions lo(generateOptions(*coreArgs));
>> +  LinkerInvocation invocation(lo);
>> +  invocation();
>> +
>>   return 0;
>> }
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>



More information about the llvm-commits mailing list