blob: 8a334d9903a224f6ad43dfb6f98e9baff85bdb2d [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
87class LDDriver final : public Driver {
88public:
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
106 std::unique_ptr<llvm::opt::DerivedArgList> newArgs(
107 new llvm::opt::DerivedArgList(*_inputArgs));
108
109 if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_target)) {
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000110 newArgs->AddSeparateArg( A, _core.getOption(core::OPT_target)
111 , A->getValue());
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000112 } else {
113 assert(!_defaultTargetTriple.empty() && "Got empty target triple!");
114 newArgs->AddSeparateArg(nullptr, _core.getOption(core::OPT_target)
115 , _defaultTargetTriple);
116 }
117
118 if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_entry))
119 newArgs->AddJoinedArg(A, _core.getOption(core::OPT_entry), A->getValue());
120 else
Michael J. Spencer99b99d22012-12-09 23:56:37 +0000121 newArgs->AddJoinedArg(nullptr, _core.getOption(core::OPT_entry),
122 "_start");
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000123
124 if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_output))
125 newArgs->AddJoinedArg(A, _core.getOption(core::OPT_output),
126 A->getValue());
127 else
128 newArgs->AddJoinedArg(nullptr, _core.getOption(core::OPT_output),
129 "a.out");
130
131 if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_relocatable))
132 newArgs->AddFlagArg(A, _core.getOption(core::OPT_relocatable));
133
Michael J. Spencer38257602012-12-09 23:56:26 +0000134 if (llvm::opt::Arg *A =
135 _inputArgs->getLastArg(ld::OPT_OCTOTHORPE_OCTOTHORPE_OCTOTHORPE))
136 newArgs->AddFlagArg(A, _core.getOption(
137 core::OPT_OCTOTHORPE_OCTOTHORPE_OCTOTHORPE));
138
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000139 // Copy input args.
140 for (llvm::opt::arg_iterator it = _inputArgs->filtered_begin(ld::OPT_INPUT),
141 ie = _inputArgs->filtered_end();
142 it != ie; ++it) {
143 newArgs->AddPositionalArg(*it, _core.getOption(core::OPT_INPUT),
144 (*it)->getValue());
145 }
146
147 return std::move(newArgs);
148 }
149
150private:
151 std::unique_ptr<llvm::opt::InputArgList> _inputArgs;
152 core::CoreOptTable _core;
153 ld::LDOptTable _opt;
154};
155
156std::unique_ptr<Driver> Driver::create( Driver::Flavor flavor
157 , StringRef defaultTargetTriple) {
158 switch (flavor) {
159 case Flavor::ld:
160 return std::unique_ptr<Driver>(new LDDriver(defaultTargetTriple));
161 case Flavor::core:
162 case Flavor::ld64:
163 case Flavor::link:
164 case Flavor::invalid:
165 llvm_unreachable("Unsupported flavor");
166 }
167}
168
Michael J. Spencer18225e72013-01-05 00:46:45 +0000169std::unique_ptr<llvm::opt::ArgList>
170lld::parseCoreArgs(llvm::ArrayRef<const char *> args) {
171 core::CoreOptTable core;
172 unsigned missingIndex, missingCount;
173 std::unique_ptr<llvm::opt::ArgList> list(
174 core.ParseArgs( args.begin(), args.end(), missingIndex, missingCount));
175
176 if (missingCount) {
177 llvm::errs() << "error: missing arg value for '"
178 << list->getArgString(missingIndex)
179 << "' expected " << missingCount << " argument(s).\n";
180 return std::unique_ptr<llvm::opt::ArgList>();
181 }
182
183 return list;
184}
185
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000186LinkerOptions lld::generateOptions(const llvm::opt::ArgList &args) {
187 LinkerOptions ret;
188
189 for (llvm::opt::arg_iterator it = args.filtered_begin(ld::OPT_INPUT),
190 ie = args.filtered_end();
191 it != ie; ++it) {
192 ret._input.push_back(LinkerInput((*it)->getValue(), InputKind::Object));
193 }
194
195 ret._target = llvm::Triple::normalize(args.getLastArgValue(core::OPT_target));
196 ret._outputPath = args.getLastArgValue(core::OPT_output);
197 ret._entrySymbol = args.getLastArgValue(core::OPT_entry);
198 ret._relocatable = args.hasArg(core::OPT_relocatable);
Michael J. Spencer38257602012-12-09 23:56:26 +0000199 ret._outputCommands = args.hasArg(core::OPT_OCTOTHORPE_OCTOTHORPE_OCTOTHORPE);
Michael J. Spencer9ff4be22012-12-08 00:47:36 +0000200
201 return std::move(ret);
202}