blob: b24d1a93a8e43743d7c2f8c870f51388dcf7f65c [file] [log] [blame]
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -07001//===- Main.cpp -----------------------------------------------------------===//
2//
3// The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include <mcld/Environment.h>
10#include <mcld/IRBuilder.h>
11#include <mcld/Linker.h>
12#include <mcld/LinkerConfig.h>
13#include <mcld/LinkerScript.h>
14#include <mcld/Module.h>
15#include <mcld/ADT/StringEntry.h>
16#include <mcld/MC/InputAction.h>
17#include <mcld/MC/CommandAction.h>
18#include <mcld/MC/FileAction.h>
19#include <mcld/MC/ZOption.h>
20#include <mcld/Support/raw_ostream.h>
21#include <mcld/Support/MsgHandling.h>
22#include <mcld/Support/Path.h>
23#include <mcld/Support/SystemUtils.h>
24#include <mcld/Support/TargetRegistry.h>
25
26#include <llvm/ADT/ArrayRef.h>
27#include <llvm/ADT/SmallVector.h>
28#include <llvm/ADT/STLExtras.h>
29#include <llvm/ADT/StringRef.h>
30#include <llvm/ADT/StringSwitch.h>
31#include <llvm/Option/Arg.h>
32#include <llvm/Option/ArgList.h>
33#include <llvm/Option/OptTable.h>
34#include <llvm/Option/Option.h>
35#include <llvm/Support/ManagedStatic.h>
36#include <llvm/Support/Process.h>
37#include <llvm/Support/Signals.h>
38
39#include <cassert>
40#include <cstdlib>
41#include <string>
42
43#if defined(HAVE_UNISTD_H)
44#include <unistd.h>
45#endif
46
47#if defined(_MSC_VER) || defined(__MINGW32__)
48#include <io.h>
49#ifndef STDIN_FILENO
50#define STDIN_FILENO 0
51#endif
52#ifndef STDOUT_FILENO
53#define STDOUT_FILENO 1
54#endif
55#ifndef STDERR_FILENO
56#define STDERR_FILENO 2
57#endif
58#endif
59
60namespace {
61
62class Driver {
63 private:
64 enum Option {
65 // This is not an option.
66 kOpt_INVALID = 0,
67#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
68 HELPTEXT, METAVAR) \
69 kOpt_ ## ID,
70#include "Options.inc" // NOLINT
71#undef OPTION
72 kOpt_LastOption
73 };
74
75 class OptTable : public llvm::opt::OptTable {
76 private:
77#define PREFIX(NAME, VALUE) \
78 static const char* const NAME[];
79#include "Options.inc" // NOLINT
80#undef PREFIX
81 static const llvm::opt::OptTable::Info InfoTable[];
82
83 public:
84 OptTable();
85 };
86
87 private:
Stephen Hinescfcb2242016-03-08 00:18:09 -080088 explicit Driver(const char* prog_name)
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -070089 : prog_name_(prog_name),
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -070090 module_(script_),
91 ir_builder_(module_, config_) {
92 return;
93 }
94
95 public:
96 static std::unique_ptr<Driver> Create(llvm::ArrayRef<const char*> argv);
97
98 bool Run();
99
100 private:
Stephen Hinescfcb2242016-03-08 00:18:09 -0800101 bool TranslateArguments(llvm::opt::InputArgList& args);
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700102
103 private:
104 const char* prog_name_;
105
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700106 mcld::LinkerScript script_;
107
108 mcld::LinkerConfig config_;
109
110 mcld::Module module_;
111
112 mcld::IRBuilder ir_builder_;
113
114 mcld::Linker linker_;
115
116 private:
117 DISALLOW_COPY_AND_ASSIGN(Driver);
118};
119
120#define PREFIX(NAME, VALUE) \
121 const char* const Driver::OptTable::NAME[] = VALUE;
122#include "Options.inc" // NOLINT
123#undef PREFIX
124
125const llvm::opt::OptTable::Info Driver::OptTable::InfoTable[] = {
126#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
127 HELPTEXT, METAVAR) \
128 { PREFIX, NAME, HELPTEXT, METAVAR, kOpt_ ## ID, \
129 llvm::opt::Option::KIND ## Class, PARAM, FLAGS, kOpt_ ## GROUP, \
130 kOpt_ ## ALIAS, ALIASARGS },
Stephen Hinescfcb2242016-03-08 00:18:09 -0800131#include "Options.inc" // NOLINT
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700132#undef OPTION
133};
134
135Driver::OptTable::OptTable()
Stephen Hinescfcb2242016-03-08 00:18:09 -0800136 : llvm::opt::OptTable(InfoTable) { }
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700137
138inline bool ShouldColorize() {
139 const char* term = getenv("TERM");
140 return term && (0 != strcmp(term, "dumb"));
141}
142
143/// ParseProgName - Parse program name
144/// This function simplifies cross-compiling by reading triple from the program
145/// name. For example, if the program name is `arm-linux-eabi-ld.mcld', we can
146/// get the triple is arm-linux-eabi by the program name.
147inline std::string ParseProgName(const char* prog_name) {
148 static const char* suffixes[] = {"ld", "ld.mcld"};
149
150 std::string name(mcld::sys::fs::Path(prog_name).stem().native());
151
152 for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
153 if (name == suffixes[i])
154 return std::string();
155 }
156
157 llvm::StringRef prog_name_ref(prog_name);
158 llvm::StringRef prefix;
159
160 for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
161 if (!prog_name_ref.endswith(suffixes[i]))
162 continue;
163
164 llvm::StringRef::size_type last_component =
165 prog_name_ref.rfind('-', prog_name_ref.size() - strlen(suffixes[i]));
166 if (last_component == llvm::StringRef::npos)
167 continue;
168 llvm::StringRef prefix = prog_name_ref.slice(0, last_component);
169 std::string ignored_error;
170 if (!mcld::TargetRegistry::lookupTarget(prefix, ignored_error))
171 continue;
172 return prefix.str();
173 }
174 return std::string();
175}
176
177inline void ParseEmulation(llvm::Triple& triple, const char* emulation) {
178 llvm::Triple emu_triple =
179 llvm::StringSwitch<llvm::Triple>(emulation)
180 .Case("aarch64linux", llvm::Triple("aarch64", "", "linux", "gnu"))
181 .Case("armelf_linux_eabi", llvm::Triple("arm", "", "linux", "gnu"))
182 .Case("elf_i386", llvm::Triple("i386", "", "", "gnu"))
183 .Case("elf_x86_64", llvm::Triple("x86_64", "", "", "gnu"))
184 .Case("elf32_x86_64", llvm::Triple("x86_64", "", "", "gnux32"))
185 .Case("elf_i386_fbsd", llvm::Triple("i386", "", "freebsd", "gnu"))
186 .Case("elf_x86_64_fbsd", llvm::Triple("x86_64", "", "freebsd", "gnu"))
187 .Case("elf32ltsmip", llvm::Triple("mipsel", "", "", "gnu"))
188 .Case("elf64ltsmip", llvm::Triple("mips64el", "", "", "gnu"))
189 .Default(llvm::Triple());
190
191 if (emu_triple.getArch() == llvm::Triple::UnknownArch &&
192 emu_triple.getOS() == llvm::Triple::UnknownOS &&
193 emu_triple.getEnvironment() == llvm::Triple::UnknownEnvironment)
194 mcld::error(mcld::diag::err_invalid_emulation) << emulation << "\n";
195
196 if (emu_triple.getArch() != llvm::Triple::UnknownArch)
197 triple.setArch(emu_triple.getArch());
198
199 if (emu_triple.getOS() != llvm::Triple::UnknownOS)
200 triple.setOS(emu_triple.getOS());
201
202 if (emu_triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
203 triple.setEnvironment(emu_triple.getEnvironment());
204}
205
206/// Configure the output filename.
207inline bool ConfigureOutputName(llvm::StringRef output_name,
208 mcld::Module& module,
209 mcld::LinkerConfig& config) {
210 std::string output(output_name.str());
211 if (output.empty()) {
212 if (config.targets().triple().getOS() == llvm::Triple::Win32) {
213 output.assign("_out");
214 switch (config.codeGenType()) {
215 case mcld::LinkerConfig::Object: {
216 output += ".obj";
217 break;
218 }
219 case mcld::LinkerConfig::DynObj: {
220 output += ".dll";
221 break;
222 }
223 case mcld::LinkerConfig::Exec: {
224 output += ".exe";
225 break;
226 }
227 case mcld::LinkerConfig::External:
228 break;
229 default: {
230 return false;
231 break;
232 }
233 } // switch (config.codeGenType())
234 } else {
235 output.assign("a.out");
236 }
237 } // if (output.empty())
238
239 module.setName(output);
240 return true;
241}
242
243bool InitializeInputs(mcld::IRBuilder& ir_builder,
244 std::vector<std::unique_ptr<mcld::InputAction>>& input_actions) {
245 for (auto& action : input_actions) {
246 assert(action != nullptr);
247 action->activate(ir_builder.getInputBuilder());
248 }
249
250 if (ir_builder.getInputBuilder().isInGroup()) {
251 mcld::fatal(mcld::diag::fatal_forbid_nest_group);
252 return false;
253 }
254
255 return true;
256}
257
Stephen Hinescfcb2242016-03-08 00:18:09 -0800258bool Driver::TranslateArguments(llvm::opt::InputArgList& args) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700259 //===--------------------------------------------------------------------===//
260 // Preference
261 //===--------------------------------------------------------------------===//
262
263 // --color=mode
Stephen Hinescfcb2242016-03-08 00:18:09 -0800264 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Color)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700265 bool res = llvm::StringSwitch<bool>(arg->getValue())
266 .Case("never", false)
267 .Case("always", true)
268 .Case("auto", ShouldColorize() &&
269 llvm::sys::Process::FileDescriptorIsDisplayed(
270 STDOUT_FILENO))
271 .Default(false);
272 config_.options().setColor(res);
273 mcld::outs().setColor(res);
274 mcld::errs().setColor(res);
275 }
276
277 // --trace
Stephen Hinescfcb2242016-03-08 00:18:09 -0800278 config_.options().setTrace(args.hasArg(kOpt_Trace));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700279
280 // --verbose=level
Stephen Hinescfcb2242016-03-08 00:18:09 -0800281 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Verbose)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700282 llvm::StringRef value = arg->getValue();
283 int level;
284 if (value.getAsInteger(0, level)) {
285 mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
286 << ": " << arg->getValue();
287 return false;
288 }
289 config_.options().setVerbose(level);
290 }
291
292 // --error-limit NUMBER
Stephen Hinescfcb2242016-03-08 00:18:09 -0800293 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_ErrorLimit)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700294 llvm::StringRef value = arg->getValue();
295 int num;
296 if (value.getAsInteger(0, num) || (num < 0)) {
297 mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
298 << ": " << arg->getValue();
299 return false;
300 }
301 config_.options().setMaxErrorNum(num);
302 }
303
304 // --warning-limit NUMBER
Stephen Hinescfcb2242016-03-08 00:18:09 -0800305 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_WarningLimit)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700306 llvm::StringRef value = arg->getValue();
307 int num;
308 if (value.getAsInteger(0, num) || (num < 0)) {
309 mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
310 << ": " << arg->getValue();
311 return false;
312 }
313 config_.options().setMaxWarnNum(num);
314 }
315
316 // --warn-shared-textrel
Stephen Hinescfcb2242016-03-08 00:18:09 -0800317 config_.options().setWarnSharedTextrel(args.hasArg(kOpt_WarnSharedTextrel));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700318
319 //===--------------------------------------------------------------------===//
320 // Target
321 //===--------------------------------------------------------------------===//
322 llvm::Triple triple;
Stephen Hinescfcb2242016-03-08 00:18:09 -0800323 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Triple)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700324 // 1. Use the triple from command.
325 // -mtriple=value
326 triple.setTriple(arg->getValue());
327 } else {
328 std::string prog_triple = ParseProgName(prog_name_);
329 if (!prog_triple.empty()) {
330 // 2. Use the triple from the program name prefix.
331 triple.setTriple(prog_triple);
332 } else {
333 // 3. Use the default target triple.
334 triple.setTriple(mcld::sys::getDefaultTargetTriple());
335 }
336 }
337
338 // If a specific emulation was requested, apply it now.
Stephen Hinescfcb2242016-03-08 00:18:09 -0800339 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Emulation)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700340 // -m emulation
341 ParseEmulation(triple, arg->getValue());
Stephen Hinescfcb2242016-03-08 00:18:09 -0800342 } else if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Arch)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700343 // -march=value
344 config_.targets().setArch(arg->getValue());
345 }
346
Stephen Hinescfcb2242016-03-08 00:18:09 -0800347 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_CPU)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700348 config_.targets().setTargetCPU(arg->getValue());
349 }
350
351 config_.targets().setTriple(triple);
352
353 // --gpsize=value
Stephen Hinescfcb2242016-03-08 00:18:09 -0800354 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_GPSize)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700355 llvm::StringRef value = arg->getValue();
356 int size;
357 if (value.getAsInteger(0, size) || (size< 0)) {
358 mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
359 << ": " << arg->getValue() << "\n";
360 return false;
361 }
Stephen Hinescfcb2242016-03-08 00:18:09 -0800362 config_.targets().setGPSize(size);
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700363 }
364
Stephen Hinescfcb2242016-03-08 00:18:09 -0800365 // --stub-group-size=value
366 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_StubGroupSize)) {
367 llvm::StringRef value = arg->getValue();
368 int size;
369 if (value.getAsInteger(0, size) || (size< 0)) {
370 mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
371 << ": " << arg->getValue() << "\n";
372 return false;
373 }
374 config_.targets().setStubGroupSize(size);
375 }
376
377 // --fix-cortex-a53-835769
378 config_.targets().setFixCA53Erratum835769(
379 args.hasArg(kOpt_FixCA53Erratum835769));
380
381 // --fix-cortex-a53-843419
382 config_.targets().setFixCA53Erratum843419(
383 args.hasArg(kOpt_FixCA53Erratum843419));
384
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700385 //===--------------------------------------------------------------------===//
386 // Dynamic
387 //===--------------------------------------------------------------------===//
388
389 // --entry=entry
Stephen Hinescfcb2242016-03-08 00:18:09 -0800390 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Entry)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700391 script_.setEntry(arg->getValue());
392 }
393
394 // -Bsymbolic
Stephen Hinescfcb2242016-03-08 00:18:09 -0800395 config_.options().setBsymbolic(args.hasArg(kOpt_Bsymbolic));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700396
397 // -Bgroup
Stephen Hinescfcb2242016-03-08 00:18:09 -0800398 config_.options().setBgroup(args.hasArg(kOpt_Bgroup));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700399
400 // -soname=name
Stephen Hinescfcb2242016-03-08 00:18:09 -0800401 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_SOName)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700402 config_.options().setSOName(arg->getValue());
403 }
404
405 // --no-undefined
Stephen Hinescfcb2242016-03-08 00:18:09 -0800406 if (args.hasArg(kOpt_NoUndef)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700407 config_.options().setNoUndefined(true);
408 }
409
410 // --allow-multiple-definition
Stephen Hinescfcb2242016-03-08 00:18:09 -0800411 if (args.hasArg(kOpt_AllowMulDefs)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700412 config_.options().setMulDefs(true);
413 }
414
415 // -z options
Stephen Hinescfcb2242016-03-08 00:18:09 -0800416 for (llvm::opt::Arg* arg : args.filtered(kOpt_Z)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700417 llvm::StringRef value = arg->getValue();
418 mcld::ZOption z_opt =
419 llvm::StringSwitch<mcld::ZOption>(value)
420 .Case("combreloc", mcld::ZOption(mcld::ZOption::CombReloc))
421 .Case("nocombreloc", mcld::ZOption(mcld::ZOption::NoCombReloc))
422 .Case("defs", mcld::ZOption(mcld::ZOption::Defs))
423 .Case("execstack", mcld::ZOption(mcld::ZOption::ExecStack))
424 .Case("noexecstack", mcld::ZOption(mcld::ZOption::NoExecStack))
425 .Case("initfirst", mcld::ZOption(mcld::ZOption::InitFirst))
426 .Case("interpose", mcld::ZOption(mcld::ZOption::InterPose))
427 .Case("loadfltr", mcld::ZOption(mcld::ZOption::LoadFltr))
428 .Case("muldefs", mcld::ZOption(mcld::ZOption::MulDefs))
429 .Case("nocopyreloc", mcld::ZOption(mcld::ZOption::NoCopyReloc))
430 .Case("nodefaultlib", mcld::ZOption(mcld::ZOption::NoDefaultLib))
431 .Case("nodelete", mcld::ZOption(mcld::ZOption::NoDelete))
432 .Case("nodlopen", mcld::ZOption(mcld::ZOption::NoDLOpen))
433 .Case("nodump", mcld::ZOption(mcld::ZOption::NoDump))
434 .Case("relro", mcld::ZOption(mcld::ZOption::Relro))
435 .Case("norelro", mcld::ZOption(mcld::ZOption::NoRelro))
436 .Case("lazy", mcld::ZOption(mcld::ZOption::Lazy))
437 .Case("now", mcld::ZOption(mcld::ZOption::Now))
438 .Case("origin", mcld::ZOption(mcld::ZOption::Origin))
439 .Default(mcld::ZOption());
440
441 if (z_opt.kind() == mcld::ZOption::Unknown) {
442 if (value.startswith("common-page-size=")) {
443 // -z common-page-size=value
444 z_opt.setKind(mcld::ZOption::CommPageSize);
445 long long unsigned size = 0;
446 value.drop_front(17).getAsInteger(0, size);
447 z_opt.setPageSize(static_cast<uint64_t>(size));
448 } else if (value.startswith("max-page-size=")) {
449 // -z max-page-size=value
450 z_opt.setKind(mcld::ZOption::MaxPageSize);
451 long long unsigned size = 0;
452 value.drop_front(14).getAsInteger(0, size);
453 z_opt.setPageSize(static_cast<uint64_t>(size));
454 }
455 }
456 config_.options().addZOption(z_opt);
457 }
458
459 // --dynamic-linker=file
Stephen Hinescfcb2242016-03-08 00:18:09 -0800460 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Dyld)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700461 config_.options().setDyld(arg->getValue());
462 }
463
464 // --enable-new-dtags
Stephen Hinescfcb2242016-03-08 00:18:09 -0800465 config_.options().setNewDTags(args.hasArg(kOpt_EnableNewDTags));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700466
467 // --spare-dyanmic-tags COUNT
Stephen Hinescfcb2242016-03-08 00:18:09 -0800468 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_SpareDTags)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700469 llvm::StringRef value = arg->getValue();
470 int num;
471 if (value.getAsInteger(0, num) || (num < 0)) {
472 mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
473 << ": " << arg->getValue() << "\n";
474 return false;
475 }
476 config_.options().setNumSpareDTags(num);
477 }
478
479 //===--------------------------------------------------------------------===//
480 // Output
481 //===--------------------------------------------------------------------===//
482
483 // Setup the codegen type.
Stephen Hinescfcb2242016-03-08 00:18:09 -0800484 if (args.hasArg(kOpt_Shared) || args.hasArg(kOpt_PIE)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700485 // -shared, -pie
486 config_.setCodeGenType(mcld::LinkerConfig::DynObj);
Stephen Hinescfcb2242016-03-08 00:18:09 -0800487 } else if (args.hasArg(kOpt_Relocatable)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700488 // -r
489 config_.setCodeGenType(mcld::LinkerConfig::Object);
Stephen Hinescfcb2242016-03-08 00:18:09 -0800490 } else if (llvm::opt::Arg* arg = args.getLastArg(kOpt_OutputFormat)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700491 // --oformat=value
492 llvm::StringRef value = arg->getValue();
493 if (value.equals("binary")) {
494 config_.setCodeGenType(mcld::LinkerConfig::Binary);
495 }
496 } else {
497 config_.setCodeGenType(mcld::LinkerConfig::Exec);
498 }
499
500 // Setup the output filename.
501 llvm::StringRef output_name;
Stephen Hinescfcb2242016-03-08 00:18:09 -0800502 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Output)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700503 output_name = arg->getValue();
504 }
505 if (!ConfigureOutputName(output_name, module_, config_)) {
506 mcld::unreachable(mcld::diag::unrecognized_output_file) << module_.name();
507 return false;
508 } else {
Stephen Hinescfcb2242016-03-08 00:18:09 -0800509 if (!args.hasArg(kOpt_SOName)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700510 config_.options().setSOName(module_.name());
511 }
512 }
513
514 // --format=value
Stephen Hinescfcb2242016-03-08 00:18:09 -0800515 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_InputFormat)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700516 llvm::StringRef value = arg->getValue();
517 if (value.equals("binary")) {
518 config_.options().setBinaryInput();
519 }
520 }
521
522 // Setup debug info stripping.
Stephen Hinescfcb2242016-03-08 00:18:09 -0800523 config_.options().setStripDebug(args.hasArg(kOpt_StripDebug) ||
524 args.hasArg(kOpt_StripAll));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700525
526 // Setup symbol stripping mode.
Stephen Hinescfcb2242016-03-08 00:18:09 -0800527 if (args.hasArg(kOpt_StripAll)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700528 config_.options().setStripSymbols(
529 mcld::GeneralOptions::StripSymbolMode::StripAllSymbols);
Stephen Hinescfcb2242016-03-08 00:18:09 -0800530 } else if (args.hasArg(kOpt_DiscardAll)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700531 config_.options().setStripSymbols(
532 mcld::GeneralOptions::StripSymbolMode::StripLocals);
Stephen Hinescfcb2242016-03-08 00:18:09 -0800533 } else if (args.hasArg(kOpt_DiscardLocals)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700534 config_.options().setStripSymbols(
535 mcld::GeneralOptions::StripSymbolMode::StripTemporaries);
536 } else {
537 config_.options().setStripSymbols(
538 mcld::GeneralOptions::StripSymbolMode::KeepAllSymbols);
539 }
540
541 // --eh-frame-hdr
Stephen Hinescfcb2242016-03-08 00:18:09 -0800542 config_.options().setEhFrameHdr(args.hasArg(kOpt_EHFrameHdr));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700543
544 // -pie
Stephen Hinescfcb2242016-03-08 00:18:09 -0800545 config_.options().setPIE(args.hasArg(kOpt_PIE));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700546
547 // --nmagic
Stephen Hinescfcb2242016-03-08 00:18:09 -0800548 config_.options().setNMagic(args.hasArg(kOpt_NMagic));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700549
550 // --omagic
Stephen Hinescfcb2242016-03-08 00:18:09 -0800551 config_.options().setOMagic(args.hasArg(kOpt_OMagic));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700552
553 // --hash-style=style
Stephen Hinescfcb2242016-03-08 00:18:09 -0800554 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_HashStyle)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700555 mcld::GeneralOptions::HashStyle style =
556 llvm::StringSwitch<mcld::GeneralOptions::HashStyle>(arg->getValue())
557 .Case("sysv", mcld::GeneralOptions::HashStyle::SystemV)
558 .Case("gnu", mcld::GeneralOptions::HashStyle::GNU)
559 .Case("both", mcld::GeneralOptions::HashStyle::Both)
560 .Default(mcld::GeneralOptions::HashStyle::Unknown);
561 if (style != mcld::GeneralOptions::HashStyle::Unknown) {
562 config_.options().setHashStyle(style);
563 }
564 }
565
566 // --[no]-export-dynamic
Stephen Hinescfcb2242016-03-08 00:18:09 -0800567 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_ExportDynamic,
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700568 kOpt_NoExportDynamic)) {
569 if (arg->getOption().matches(kOpt_ExportDynamic)) {
570 config_.options().setExportDynamic(true);
571 } else {
572 config_.options().setExportDynamic(false);
573 }
574 }
575
576 // --no-warn-mismatch
Stephen Hinescfcb2242016-03-08 00:18:09 -0800577 config_.options().setWarnMismatch(!args.hasArg(kOpt_NoWarnMismatch));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700578
579 // --exclude-libs
Stephen Hinescfcb2242016-03-08 00:18:09 -0800580 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_ExcludeLibs)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700581 llvm::StringRef value = arg->getValue();
582 do {
583 std::pair<llvm::StringRef, llvm::StringRef> res = value.split(',');
584 config_.options().excludeLIBS().insert(res.first.str());
585 value = res.second;
586 } while (!value.empty());
587 }
588
589 //===--------------------------------------------------------------------===//
590 // Search Path
591 //===--------------------------------------------------------------------===//
592
593 // --sysroot
Stephen Hinescfcb2242016-03-08 00:18:09 -0800594 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Sysroot)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700595 mcld::sys::fs::Path path(arg->getValue());
596 if (mcld::sys::fs::exists(path) && mcld::sys::fs::is_directory(path)) {
597 script_.setSysroot(path);
598 }
599 }
600
601 // -L searchdir
Stephen Hinescfcb2242016-03-08 00:18:09 -0800602 for (llvm::opt::Arg* arg : args.filtered(kOpt_LibraryPath)) {
603 if (!script_.directories().insert(arg->getValue()))
604 mcld::warning(mcld::diag::warn_cannot_open_search_dir) << arg->getValue();
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700605 }
606
607 // -nostdlib
Stephen Hinescfcb2242016-03-08 00:18:09 -0800608 config_.options().setNoStdlib(args.hasArg(kOpt_NoStdlib));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700609
610 // -rpath=path
Stephen Hinescfcb2242016-03-08 00:18:09 -0800611 for (llvm::opt::Arg* arg : args.filtered(kOpt_RPath)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700612 config_.options().getRpathList().push_back(arg->getValue());
613 }
614
615 //===--------------------------------------------------------------------===//
616 // Symbol
617 //===--------------------------------------------------------------------===//
618
619 // -d/-dc/-dp
Stephen Hinescfcb2242016-03-08 00:18:09 -0800620 config_.options().setDefineCommon(args.hasArg(kOpt_DefineCommon));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700621
622 // -u symbol
Stephen Hinescfcb2242016-03-08 00:18:09 -0800623 for (llvm::opt::Arg* arg : args.filtered(kOpt_Undefined)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700624 config_.options().getUndefSymList().push_back(arg->getValue());
625 }
626
627 //===--------------------------------------------------------------------===//
628 // Script
629 //===--------------------------------------------------------------------===//
630
631 // --wrap=symbol
Stephen Hinescfcb2242016-03-08 00:18:09 -0800632 for (llvm::opt::Arg* arg : args.filtered(kOpt_Wrap)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700633 bool exist = false;
634 const char* symbol = arg->getValue();
635 // symbol -> __wrap_symbol
636 mcld::StringEntry<llvm::StringRef>* to_wrap =
637 script_.renameMap().insert(symbol, exist);
638
639 std::string to_wrap_str;
640 to_wrap_str.append("__wrap_")
641 .append(symbol);
642 to_wrap->setValue(to_wrap_str);
643
644 if (exist)
645 mcld::warning(mcld::diag::rewrap) << symbol << to_wrap_str;
646
647 // __real_symbol -> symbol
648 std::string from_real_str;
649 to_wrap_str.append("__real_")
650 .append(symbol);
651 mcld::StringEntry<llvm::StringRef>* from_real =
652 script_.renameMap().insert(from_real_str, exist);
653 from_real->setValue(symbol);
654
655 if (exist)
656 mcld::warning(mcld::diag::rewrap) << symbol << from_real_str;
657 }
658
659 // --portalbe=symbol
Stephen Hinescfcb2242016-03-08 00:18:09 -0800660 for (llvm::opt::Arg* arg : args.filtered(kOpt_Portable)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700661 bool exist = false;
662 const char* symbol = arg->getValue();
663 // symbol -> symbol_portable
664 mcld::StringEntry<llvm::StringRef>* to_wrap =
665 script_.renameMap().insert(symbol, exist);
666
667 std::string to_wrap_str;
668 to_wrap_str.append(symbol)
669 .append("_portable");
670 to_wrap->setValue(to_wrap_str);
671
672 if (exist)
673 mcld::warning(mcld::diag::rewrap) << symbol << to_wrap_str;
674
675 // __real_symbol -> symbol
676 std::string from_real_str;
677 to_wrap_str.append("__real_")
678 .append(symbol);
679 mcld::StringEntry<llvm::StringRef>* from_real =
680 script_.renameMap().insert(from_real_str, exist);
681 from_real->setValue(symbol);
682
683 if (exist)
684 mcld::warning(mcld::diag::rewrap) << symbol << from_real_str;
685 }
686
687 // --section-start=section=addr
Stephen Hinescfcb2242016-03-08 00:18:09 -0800688 for (llvm::opt::Arg* arg : args.filtered(kOpt_SectionStart)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700689 llvm::StringRef value = arg->getValue();
690 const size_t pos = value.find('=');
691 uint64_t addr = 0;
692 value.substr(pos + 1).getAsInteger(0, addr);
693 bool exist = false;
694 mcld::StringEntry<uint64_t>* mapping =
695 script_.addressMap().insert(value.substr(0, pos), exist);
696 mapping->setValue(addr);
697 }
698
699 // -Tbss=value
Stephen Hinescfcb2242016-03-08 00:18:09 -0800700 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Tbss)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700701 llvm::StringRef value = arg->getValue();
702 uint64_t addr = 0;
703 if (value.getAsInteger(0, addr)) {
704 mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
705 << ": " << arg->getValue() << "\n";
706 return false;
707 }
708 bool exist = false;
709 mcld::StringEntry<uint64_t>* mapping =
710 script_.addressMap().insert(".bss", exist);
711 mapping->setValue(addr);
712 }
713
714 // -Tdata=value
Stephen Hinescfcb2242016-03-08 00:18:09 -0800715 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Tdata)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700716 llvm::StringRef value = arg->getValue();
717 uint64_t addr = 0;
718 if (value.getAsInteger(0, addr)) {
719 mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
720 << ": " << arg->getValue() << "\n";
721 return false;
722 }
723 bool exist = false;
724 mcld::StringEntry<uint64_t>* mapping =
725 script_.addressMap().insert(".data", exist);
726 mapping->setValue(addr);
727 }
728
729 // -Ttext=value
Stephen Hinescfcb2242016-03-08 00:18:09 -0800730 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_Ttext)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700731 llvm::StringRef value = arg->getValue();
732 uint64_t addr = 0;
733 if (value.getAsInteger(0, addr)) {
734 mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
735 << ": " << arg->getValue() << "\n";
736 return false;
737 }
738 bool exist = false;
739 mcld::StringEntry<uint64_t>* mapping =
740 script_.addressMap().insert(".text", exist);
741 mapping->setValue(addr);
742 }
743
744 //===--------------------------------------------------------------------===//
745 // Optimization
746 //===--------------------------------------------------------------------===//
747
748 // --[no-]gc-sections
Stephen Hinescfcb2242016-03-08 00:18:09 -0800749 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_GCSections,
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700750 kOpt_NoGCSections)) {
751 if (arg->getOption().matches(kOpt_GCSections)) {
752 config_.options().setGCSections(true);
753 } else {
754 config_.options().setGCSections(false);
755 }
756 }
757
758 // --[no-]print-gc-sections
Stephen Hinescfcb2242016-03-08 00:18:09 -0800759 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_PrintGCSections,
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700760 kOpt_NoPrintGCSections)) {
761 if (arg->getOption().matches(kOpt_PrintGCSections)) {
762 config_.options().setPrintGCSections(true);
763 } else {
764 config_.options().setPrintGCSections(false);
765 }
766 }
767
768 // --[no-]ld-generated-unwind-info
Stephen Hinescfcb2242016-03-08 00:18:09 -0800769 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_LDGeneratedUnwindInfo,
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700770 kOpt_NoLDGeneratedUnwindInfo)) {
771 if (arg->getOption().matches(kOpt_LDGeneratedUnwindInfo)) {
772 config_.options().setGenUnwindInfo(true);
773 } else {
774 config_.options().setGenUnwindInfo(false);
775 }
776 }
777
778 // --icf=mode
Stephen Hinescfcb2242016-03-08 00:18:09 -0800779 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_ICF)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700780 mcld::GeneralOptions::ICF mode =
781 llvm::StringSwitch<mcld::GeneralOptions::ICF>(arg->getValue())
782 .Case("none", mcld::GeneralOptions::ICF::None)
783 .Case("all", mcld::GeneralOptions::ICF::All)
784 .Case("safe", mcld::GeneralOptions::ICF::Safe)
785 .Default(mcld::GeneralOptions::ICF::Unknown);
786 if (mode == mcld::GeneralOptions::ICF::Unknown) {
787 mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
788 << ": " << arg->getValue() << "\n";
789 return false;
790 }
791 config_.options().setICFMode(mode);
792 }
793
794 // --icf-iterations
Stephen Hinescfcb2242016-03-08 00:18:09 -0800795 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_ICFIters)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700796 llvm::StringRef value = arg->getValue();
797 int num;
798 if (value.getAsInteger(0, num) || (num < 0)) {
799 mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
800 << ": " << arg->getValue() << "\n";
801 return false;
802 }
803 config_.options().setICFIterations(num);
804 }
805
806 // --[no-]print-icf-sections
Stephen Hinescfcb2242016-03-08 00:18:09 -0800807 if (llvm::opt::Arg* arg = args.getLastArg(kOpt_PrintICFSections,
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700808 kOpt_NoPrintICFSections)) {
809 if (arg->getOption().matches(kOpt_PrintICFSections)) {
810 config_.options().setPrintICFSections(true);
811 } else {
812 config_.options().setPrintICFSections(false);
813 }
814 }
815
816 //===--------------------------------------------------------------------===//
817 // Positional
818 //===--------------------------------------------------------------------===//
819
820 // # of regular objects, script, and namespec.
821 size_t input_num = 0;
822 typedef std::unique_ptr<mcld::InputAction> Action;
823
824 std::vector<Action> actions;
825 Action action;
826 actions.reserve(32);
827
Stephen Hinescfcb2242016-03-08 00:18:09 -0800828 for (llvm::opt::Arg* arg : args) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700829 const unsigned index = arg->getIndex();
830
831 switch (arg->getOption().getID()) {
832 // -T script
833 case kOpt_Script: {
834 const char* value = arg->getValue();
835 config_.options().getScriptList().push_back(value);
836
837 // FIXME: Let index of script file be 0.
838 action.reset(new mcld::ScriptAction(
839 0x0, value, mcld::ScriptFile::LDScript, script_.directories()));
840 actions.push_back(std::move(action));
841
842 action.reset(new mcld::ContextAction(0x0));
843 actions.push_back(std::move(action));
844
845 action.reset(new mcld::MemoryAreaAction(0x0,
846 mcld::FileHandle::ReadOnly));
847 actions.push_back(std::move(action));
848
849 ++input_num;
850 break;
851 }
852
853 // --defsym=symbol=expr
854 case kOpt_DefSym: {
855 std::string expr;
856 expr.append(arg->getValue())
857 .append(";");
858 script_.defsyms().push_back(std::move(expr));
859 action.reset(new mcld::DefSymAction(index, script_.defsyms().back()));
860 actions.push_back(std::move(action));
861 break;
862 }
863
864 // -l namespec
865 case kOpt_Namespec: {
866 action.reset(new mcld::NamespecAction(
867 index, arg->getValue(), script_.directories()));
868 actions.push_back(std::move(action));
869
870 action.reset(new mcld::ContextAction(index));
871 actions.push_back(std::move(action));
872
873 action.reset(new mcld::MemoryAreaAction(index,
874 mcld::FileHandle::ReadOnly));
875 actions.push_back(std::move(action));
876
877 ++input_num;
878 break;
879 }
880
881 // --whole-archive
882 case kOpt_WholeArchive: {
883 action.reset(new mcld::WholeArchiveAction(index));
884 actions.push_back(std::move(action));
885 break;
886 }
887
888 // --no-whole-archive
889 case kOpt_NoWholeArchive: {
890 action.reset(new mcld::NoWholeArchiveAction(index));
891 actions.push_back(std::move(action));
892 break;
893 }
894
895 // --as-needed
896 case kOpt_AsNeeded: {
897 action.reset(new mcld::AsNeededAction(index));
898 actions.push_back(std::move(action));
899 break;
900 }
901
902 // --no-as-needed
903 case kOpt_NoAsNeeded: {
904 action.reset(new mcld::NoAsNeededAction(index));
905 actions.push_back(std::move(action));
906 break;
907 }
908
909 // --add-needed
910 // FIXME: This is deprecated. Should be --copy-dt-needed-entries.
911 case kOpt_AddNeeded:
912 case kOpt_CopyDTNeeded: {
913 action.reset(new mcld::AddNeededAction(index));
914 actions.push_back(std::move(action));
915 break;
916 }
917
918 // --no-add-needed
919 // FIXME: This is deprecated. Should be --no-copy-dt-needed-entries.
920 case kOpt_NoAddNeeded:
921 case kOpt_NoCopyDTNeeded: {
922 action.reset(new mcld::AddNeededAction(index));
923 actions.push_back(std::move(action));
924 break;
925 }
926
927 // -Bdynamic
928 case kOpt_Bdynamic: {
929 action.reset(new mcld::BDynamicAction(index));
930 actions.push_back(std::move(action));
931 break;
932 }
933
934 // -Bstatic
935 case kOpt_Bstatic: {
936 action.reset(new mcld::BStaticAction(index));
937 actions.push_back(std::move(action));
938 break;
939 }
940
941 // --start-group
942 case kOpt_StartGroup: {
943 action.reset(new mcld::StartGroupAction(index));
944 actions.push_back(std::move(action));
945 break;
946 }
947
948 // --end-group
949 case kOpt_EndGroup: {
950 action.reset(new mcld::EndGroupAction(index));
951 actions.push_back(std::move(action));
952 break;
953 }
954
955 case kOpt_INPUT: {
956 action.reset(new mcld::InputFileAction(index, arg->getValue()));
957 actions.push_back(std::move(action));
958
959 action.reset(new mcld::ContextAction(index));
960 actions.push_back(std::move(action));
961
962 action.reset(new mcld::MemoryAreaAction(index,
963 mcld::FileHandle::ReadOnly));
964 actions.push_back(std::move(action));
965
966 ++input_num;
967 break;
968 }
969
970 default:
971 break;
972 }
973 }
974
975 if (input_num == 0) {
976 mcld::fatal(mcld::diag::err_no_inputs);
977 return false;
978 }
979
980 // Stable sort
981 std::stable_sort(actions.begin(),
982 actions.end(),
983 [] (const Action& X, const Action& Y) {
984 return X->position() < Y->position();
985 });
986
987 if (!InitializeInputs(ir_builder_, actions)) {
988 mcld::errs() << "Failed to initialize input tree!\n";
989 return false;
990 }
991
Stephen Hinescfcb2242016-03-08 00:18:09 -0800992
993 //===--------------------------------------------------------------------===//
994 // Unknown
995 //===--------------------------------------------------------------------===//
996 std::vector<std::string> unknown_args = args.getAllArgValues(kOpt_UNKNOWN);
997 for (std::string arg : unknown_args)
998 mcld::warning(mcld::diag::warn_unsupported_option) << arg;
999
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -07001000 return true;
1001}
1002
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -07001003std::unique_ptr<Driver> Driver::Create(llvm::ArrayRef<const char*> argv) {
1004 // Parse command line options.
1005 OptTable opt_table;
Stephen Hinescfcb2242016-03-08 00:18:09 -08001006 unsigned missing_arg_idx;
1007 unsigned missing_arg_count;
1008 llvm::opt::InputArgList args =
1009 opt_table.ParseArgs(argv.slice(1), missing_arg_idx, missing_arg_count);
1010 if (missing_arg_count > 0) {
1011 mcld::errs() << "Argument to '" << args.getArgString(missing_arg_idx)
1012 << "' is missing (expected " << missing_arg_count
1013 << ((missing_arg_count > 1) ? " values" : " value") << ")\n";
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -07001014 return nullptr;
1015 }
1016
Stephen Hinescfcb2242016-03-08 00:18:09 -08001017 std::unique_ptr<Driver> result(new Driver(argv[0]));
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -07001018
1019 // Return quickly if -help is specified.
Stephen Hinescfcb2242016-03-08 00:18:09 -08001020 if (args.hasArg(kOpt_Help)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -07001021 opt_table.PrintHelp(mcld::outs(), argv[0], "MCLinker",
1022 /* FlagsToInclude */0, /* FlagsToExclude */0);
1023 return nullptr;
1024 }
1025
1026 // Print version information if requested.
Stephen Hinescfcb2242016-03-08 00:18:09 -08001027 if (args.hasArg(kOpt_Version)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -07001028 mcld::outs() << result->config_.options().getVersionString() << "\n";
1029 }
1030
1031 // Setup instance from arguments.
Stephen Hinescfcb2242016-03-08 00:18:09 -08001032 if (!result->TranslateArguments(args)) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -07001033 return nullptr;
1034 }
1035
1036 return result;
1037}
1038
1039bool Driver::Run() {
1040 mcld::Initialize();
1041
1042 if (!linker_.emulate(script_, config_)) {
1043 mcld::errs() << "Failed to emulate target!\n";
1044 return false;
1045 }
1046
1047 if (!linker_.link(module_, ir_builder_)) {
1048 mcld::errs() << "Failed to link objects!\n";
1049 return false;
1050 }
1051
1052 if (!linker_.emit(module_, module_.name())) {
1053 mcld::errs() << "Failed to emit output!\n";
1054 return false;
1055 }
1056
1057 mcld::Finalize();
1058 return true;
1059}
1060
1061} // anonymous namespace
1062
1063int main(int argc, char** argv) {
1064 std::unique_ptr<Driver> driver =
1065 Driver::Create(llvm::makeArrayRef(argv, argc));
1066
1067 if ((driver == nullptr) || !driver->Run()) {
1068 return EXIT_FAILURE;
1069 } else {
1070 return EXIT_SUCCESS;
1071 }
1072}