summaryrefslogtreecommitdiffstats
path: root/lld/lib/Driver/Drivers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/Driver/Drivers.cpp')
-rw-r--r--lld/lib/Driver/Drivers.cpp180
1 files changed, 180 insertions, 0 deletions
diff --git a/lld/lib/Driver/Drivers.cpp b/lld/lib/Driver/Drivers.cpp
new file mode 100644
index 00000000000..b664765b198
--- /dev/null
+++ b/lld/lib/Driver/Drivers.cpp
@@ -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);
+}
OpenPOWER on IntegriCloud