blob: 83fb83ce383542c977f7fe49c95b41b0ff95a48a [file] [log] [blame]
Michael J. Spencer9ff4be22012-12-08 00:47:36 +00001//===- lib/Driver/Drivers.cpp - Linker Driver Emulators -------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11///
12/// Concrete instances of the Driver interface.
13///
14//===----------------------------------------------------------------------===//
15
16#include "lld/Driver/Driver.h"
17
18#include "lld/Driver/LinkerOptions.h"
19
20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/Triple.h"
23#include "llvm/Option/Arg.h"
24#include "llvm/Option/Option.h"
25#include "llvm/Support/raw_ostream.h"
26
27using namespace lld;
28
29namespace core {
30enum ID {
31 OPT_INVALID = 0,
32#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, HELP, META) \
33 OPT_##ID,
34#include "CoreOptions.inc"
35 LastOption
36#undef OPTION
37};
38
39#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
40#include "CoreOptions.inc"
41#undef PREFIX
42
43static const llvm::opt::OptTable::Info InfoTable[] = {
44#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
45 HELPTEXT, METAVAR) \
46 { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
47 PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS },
48#include "CoreOptions.inc"
49#undef OPTION
50};
51
52class CoreOptTable : public llvm::opt::OptTable {
53public:
54 CoreOptTable() : OptTable(InfoTable, llvm::array_lengthof(InfoTable)){}
55};
56}
57
58namespace ld {
59enum LDOpt {
60 OPT_INVALID = 0,
61#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, HELP, META) \
62 OPT_##ID,
63#include "LDOptions.inc"
64 LastOption
65#undef OPTION
66};
67
68#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
69#include "LDOptions.inc"
70#undef PREFIX
71
72static const llvm::opt::OptTable::Info InfoTable[] = {
73#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
74 HELPTEXT, METAVAR) \
75 { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
76 PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS },
77#include "LDOptions.inc"
78#undef OPTION
79};
80
81class LDOptTable : public llvm::opt::OptTable {
82public:
83 LDOptTable() : OptTable(InfoTable, llvm::array_lengthof(InfoTable)){}
84};
85}
86
Chandler Carruthb5f3bd92013-01-19 09:57:51 +000087class LDDriver LLVM_FINAL : public Driver {
Michael J. Spencer9ff4be22012-12-08 00:47:36 +000088public:
89 LDDriver(StringRef defaultTargetTriple) : Driver(defaultTargetTriple) {}
90
91 virtual std::unique_ptr<llvm::opt::DerivedArgList>
Andy Gibbsd02bf1d2012-12-22 09:46:10 +000092 transform(llvm::ArrayRef<const char *> args) {
Michael J. Spencer9ff4be22012-12-08 00:47:36 +000093 assert(!_inputArgs && "transform may only be called once!");
94
95 unsigned missingIndex, missingCount;
96 _inputArgs.reset(_opt.ParseArgs( args.begin(), args.end()
97 , missingIndex, missingCount));
98
99 if (missingCount) {
100 llvm::errs() << "error: missing arg value for '"
101 << _inputArgs->getArgString(missingIndex)
102 << "' expected " << missingCount << " argument(s).\n";
103 return std::unique_ptr<llvm::opt::DerivedArgList>();
104 }
105
Michael J. Spencer60471632013-01-08 22:59:27 +0000106 for (llvm::opt::arg_iterator it = _inputArgs->filtered_begin(ld::OPT_UNKNOWN),
107 ie = _inputArgs->filtered_end();
108 it != ie; ++it) {
109 llvm::errs() << "warning: ignoring unknown argument: "
110 << (*it)->getAsString(*_inputArgs) << "\n";
111 }
112
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000113 std::unique_ptr<llvm::opt::DerivedArgList> newArgs(
114 new llvm::opt::DerivedArgList(*_inputArgs));
115
116 if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_target)) {
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000117 newArgs->AddSeparateArg( A, _core.getOption(core::OPT_target)
118 , A->getValue());
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000119 } else {
120 assert(!_defaultTargetTriple.empty() && "Got empty target triple!");
121 newArgs->AddSeparateArg(nullptr, _core.getOption(core::OPT_target)
122 , _defaultTargetTriple);
123 }
124
125 if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_entry))
126 newArgs->AddJoinedArg(A, _core.getOption(core::OPT_entry), A->getValue());
127 else
Michael J. Spencer99b99d22012-12-09 23:56:37 +0000128 newArgs->AddJoinedArg(nullptr, _core.getOption(core::OPT_entry),
129 "_start");
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000130
131 if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_output))
132 newArgs->AddJoinedArg(A, _core.getOption(core::OPT_output),
133 A->getValue());
134 else
135 newArgs->AddJoinedArg(nullptr, _core.getOption(core::OPT_output),
136 "a.out");
137
138 if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_relocatable))
139 newArgs->AddFlagArg(A, _core.getOption(core::OPT_relocatable));
140
Michael J. Spencer38257602012-12-09 23:56:26 +0000141 if (llvm::opt::Arg *A =
142 _inputArgs->getLastArg(ld::OPT_OCTOTHORPE_OCTOTHORPE_OCTOTHORPE))
143 newArgs->AddFlagArg(A, _core.getOption(
144 core::OPT_OCTOTHORPE_OCTOTHORPE_OCTOTHORPE));
145
Michael J. Spencer956b0362013-01-07 08:00:25 +0000146 if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_emit_yaml))
147 newArgs->AddFlagArg(A, _core.getOption(core::OPT_emit_yaml));
148
Shankar Easwaran7381db02013-01-11 15:11:47 +0000149 if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_noinhibit_exec))
150 newArgs->AddFlagArg(A, _core.getOption(core::OPT_noinhibit_exec));
151
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000152 // Copy input args.
153 for (llvm::opt::arg_iterator it = _inputArgs->filtered_begin(ld::OPT_INPUT),
154 ie = _inputArgs->filtered_end();
155 it != ie; ++it) {
156 newArgs->AddPositionalArg(*it, _core.getOption(core::OPT_INPUT),
157 (*it)->getValue());
158 }
159
Michael J. Spencer60471632013-01-08 22:59:27 +0000160 // Copy mllvm
161 for (llvm::opt::arg_iterator it = _inputArgs->filtered_begin(ld::OPT_mllvm),
162 ie = _inputArgs->filtered_end();
163 it != ie; ++it) {
164 newArgs->AddPositionalArg(*it, _core.getOption(core::OPT_mllvm),
165 (*it)->getValue());
166 }
167
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000168 return std::move(newArgs);
169 }
170
171private:
172 std::unique_ptr<llvm::opt::InputArgList> _inputArgs;
173 core::CoreOptTable _core;
174 ld::LDOptTable _opt;
175};
176
177std::unique_ptr<Driver> Driver::create( Driver::Flavor flavor
178 , StringRef defaultTargetTriple) {
179 switch (flavor) {
180 case Flavor::ld:
181 return std::unique_ptr<Driver>(new LDDriver(defaultTargetTriple));
182 case Flavor::core:
183 case Flavor::ld64:
184 case Flavor::link:
185 case Flavor::invalid:
186 llvm_unreachable("Unsupported flavor");
187 }
188}
189
Michael J. Spencer18225e72013-01-05 00:46:45 +0000190std::unique_ptr<llvm::opt::ArgList>
191lld::parseCoreArgs(llvm::ArrayRef<const char *> args) {
192 core::CoreOptTable core;
193 unsigned missingIndex, missingCount;
194 std::unique_ptr<llvm::opt::ArgList> list(
195 core.ParseArgs( args.begin(), args.end(), missingIndex, missingCount));
196
197 if (missingCount) {
198 llvm::errs() << "error: missing arg value for '"
199 << list->getArgString(missingIndex)
200 << "' expected " << missingCount << " argument(s).\n";
201 return std::unique_ptr<llvm::opt::ArgList>();
202 }
203
Michael J. Spencer60471632013-01-08 22:59:27 +0000204 bool hasUnknown = false;
205 for (llvm::opt::arg_iterator it = list->filtered_begin(ld::OPT_UNKNOWN),
206 ie = list->filtered_end();
207 it != ie; ++it) {
208 llvm::errs() << "error: ignoring unknown argument: "
209 << (*it)->getAsString(*list) << "\n";
210 hasUnknown = true;
211 }
212 if (hasUnknown)
213 return std::unique_ptr<llvm::opt::ArgList>();
214
Michael J. Spencer18225e72013-01-05 00:46:45 +0000215 return list;
216}
217
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000218LinkerOptions lld::generateOptions(const llvm::opt::ArgList &args) {
219 LinkerOptions ret;
220
221 for (llvm::opt::arg_iterator it = args.filtered_begin(ld::OPT_INPUT),
222 ie = args.filtered_end();
223 it != ie; ++it) {
224 ret._input.push_back(LinkerInput((*it)->getValue(), InputKind::Object));
225 }
226
Michael J. Spencer60471632013-01-08 22:59:27 +0000227 ret._llvmArgs = args.getAllArgValues(core::OPT_mllvm);
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000228 ret._target = llvm::Triple::normalize(args.getLastArgValue(core::OPT_target));
229 ret._outputPath = args.getLastArgValue(core::OPT_output);
230 ret._entrySymbol = args.getLastArgValue(core::OPT_entry);
231 ret._relocatable = args.hasArg(core::OPT_relocatable);
Michael J. Spencer38257602012-12-09 23:56:26 +0000232 ret._outputCommands = args.hasArg(core::OPT_OCTOTHORPE_OCTOTHORPE_OCTOTHORPE);
Michael J. Spencer956b0362013-01-07 08:00:25 +0000233 ret._outputYAML = args.hasArg(core::OPT_emit_yaml);
Shankar Easwaran7381db02013-01-11 15:11:47 +0000234 ret._noInhibitExec = args.hasArg(core::OPT_noinhibit_exec);
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000235
236 return std::move(ret);
237}