blob: 73105355f821637c8aa2ba2a71b4802ec6207e3d [file] [log] [blame]
Daniel Dunbar39176082009-03-20 00:20:03 +00001//===--- ToolChains.cpp - ToolChain Implementations ---------------------*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ToolChains.h"
11
Daniel Dunbarf3cad362009-03-25 04:13:45 +000012#include "clang/Driver/Arg.h"
13#include "clang/Driver/ArgList.h"
Daniel Dunbarc50b00d2009-03-23 16:15:50 +000014#include "clang/Driver/Driver.h"
Daniel Dunbar4e7e9cf2009-03-25 06:12:34 +000015#include "clang/Driver/DriverDiagnostic.h"
Daniel Dunbarc50b00d2009-03-23 16:15:50 +000016#include "clang/Driver/HostInfo.h"
Daniel Dunbar4e7e9cf2009-03-25 06:12:34 +000017#include "clang/Driver/Option.h"
Daniel Dunbarc50b00d2009-03-23 16:15:50 +000018
19#include "llvm/ADT/StringExtras.h"
Daniel Dunbarec069ed2009-03-25 06:58:31 +000020#include "llvm/Support/raw_ostream.h"
Daniel Dunbarc50b00d2009-03-23 16:15:50 +000021#include "llvm/System/Path.h"
22
Daniel Dunbarf36a06a2009-04-10 21:00:07 +000023#include <cstdlib> // ::getenv
24
Daniel Dunbar39176082009-03-20 00:20:03 +000025using namespace clang::driver;
26using namespace clang::driver::toolchains;
27
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +000028/// Darwin_X86 - Darwin tool chain for i386 and x86_64.
29
Daniel Dunbarc50b00d2009-03-23 16:15:50 +000030Darwin_X86::Darwin_X86(const HostInfo &Host, const char *Arch,
31 const char *Platform, const char *OS,
32 const unsigned (&_DarwinVersion)[3],
33 const unsigned (&_GCCVersion)[3])
Daniel Dunbar11e1b402009-05-02 18:28:39 +000034 : ToolChain(Host, Arch, Platform, OS) {
Daniel Dunbarc50b00d2009-03-23 16:15:50 +000035 DarwinVersion[0] = _DarwinVersion[0];
36 DarwinVersion[1] = _DarwinVersion[1];
37 DarwinVersion[2] = _DarwinVersion[2];
38 GCCVersion[0] = _GCCVersion[0];
39 GCCVersion[1] = _GCCVersion[1];
40 GCCVersion[2] = _GCCVersion[2];
41
Daniel Dunbar02633b52009-03-26 16:23:12 +000042 llvm::raw_string_ostream(MacosxVersionMin)
43 << "10." << DarwinVersion[0] - 4 << '.' << DarwinVersion[1];
44
Daniel Dunbarc50b00d2009-03-23 16:15:50 +000045 ToolChainDir = "i686-apple-darwin";
46 ToolChainDir += llvm::utostr(DarwinVersion[0]);
47 ToolChainDir += "/";
48 ToolChainDir += llvm::utostr(GCCVersion[0]);
49 ToolChainDir += '.';
50 ToolChainDir += llvm::utostr(GCCVersion[1]);
51 ToolChainDir += '.';
52 ToolChainDir += llvm::utostr(GCCVersion[2]);
53
54 std::string Path;
55 if (getArchName() == "x86_64") {
56 Path = getHost().getDriver().Dir;
57 Path += "/../lib/gcc/";
58 Path += getToolChainDir();
59 Path += "/x86_64";
60 getFilePaths().push_back(Path);
61
62 Path = "/usr/lib/gcc/";
63 Path += getToolChainDir();
64 Path += "/x86_64";
65 getFilePaths().push_back(Path);
66 }
67
68 Path = getHost().getDriver().Dir;
69 Path += "/../lib/gcc/";
70 Path += getToolChainDir();
71 getFilePaths().push_back(Path);
72
73 Path = "/usr/lib/gcc/";
74 Path += getToolChainDir();
75 getFilePaths().push_back(Path);
76
77 Path = getHost().getDriver().Dir;
78 Path += "/../libexec/gcc/";
79 Path += getToolChainDir();
80 getProgramPaths().push_back(Path);
81
82 Path = "/usr/libexec/gcc/";
83 Path += getToolChainDir();
84 getProgramPaths().push_back(Path);
85
Daniel Dunbar82fa7c52009-03-24 04:07:10 +000086 Path = getHost().getDriver().Dir;
87 Path += "/../libexec";
88 getProgramPaths().push_back(Path);
89
Daniel Dunbarc50b00d2009-03-23 16:15:50 +000090 getProgramPaths().push_back(getHost().getDriver().Dir);
91}
92
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +000093Darwin_X86::~Darwin_X86() {
94 // Free tool implementations.
95 for (llvm::DenseMap<unsigned, Tool*>::iterator
96 it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
97 delete it->second;
98}
99
100Tool &Darwin_X86::SelectTool(const Compilation &C,
101 const JobAction &JA) const {
102 Action::ActionClass Key;
Daniel Dunbaraf80e1f2009-03-24 18:57:02 +0000103 if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName()))
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000104 Key = Action::AnalyzeJobClass;
105 else
106 Key = JA.getKind();
107
108 Tool *&T = Tools[Key];
109 if (!T) {
110 switch (Key) {
111 case Action::InputClass:
112 case Action::BindArchClass:
113 assert(0 && "Invalid tool kind.");
114 case Action::PreprocessJobClass:
Daniel Dunbar9120f172009-03-29 22:27:40 +0000115 T = new tools::darwin::Preprocess(*this); break;
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000116 case Action::AnalyzeJobClass:
117 T = new tools::Clang(*this); break;
Daniel Dunbar9120f172009-03-29 22:27:40 +0000118 case Action::PrecompileJobClass:
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000119 case Action::CompileJobClass:
Daniel Dunbar9120f172009-03-29 22:27:40 +0000120 T = new tools::darwin::Compile(*this); break;
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000121 case Action::AssembleJobClass:
Daniel Dunbar8cac5f72009-03-20 16:06:39 +0000122 T = new tools::darwin::Assemble(*this); break;
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000123 case Action::LinkJobClass:
Daniel Dunbar02633b52009-03-26 16:23:12 +0000124 T = new tools::darwin::Link(*this, MacosxVersionMin.c_str()); break;
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000125 case Action::LipoJobClass:
126 T = new tools::darwin::Lipo(*this); break;
127 }
128 }
129
130 return *T;
131}
132
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000133DerivedArgList *Darwin_X86::TranslateArgs(InputArgList &Args) const {
Daniel Dunbar4e7e9cf2009-03-25 06:12:34 +0000134 DerivedArgList *DAL = new DerivedArgList(Args, false);
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000135 const OptTable &Opts = getHost().getDriver().getOpts();
136
137 // FIXME: We really want to get out of the tool chain level argument
138 // translation business, as it makes the driver functionality much
139 // more opaque. For now, we follow gcc closely solely for the
140 // purpose of easily achieving feature parity & testability. Once we
141 // have something that works, we should reevaluate each translation
142 // and try to push it down into tool specific logic.
143
Daniel Dunbarff8857a2009-04-10 20:11:50 +0000144 Arg *OSXVersion =
145 Args.getLastArg(options::OPT_mmacosx_version_min_EQ, false);
146 Arg *iPhoneVersion =
147 Args.getLastArg(options::OPT_miphoneos_version_min_EQ, false);
148 if (OSXVersion && iPhoneVersion) {
149 getHost().getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with)
150 << OSXVersion->getAsString(Args)
151 << iPhoneVersion->getAsString(Args);
152 } else if (!OSXVersion && !iPhoneVersion) {
153 // Chose the default version based on the arch.
154 //
155 // FIXME: This will need to be fixed when we merge in arm support.
Daniel Dunbarf36a06a2009-04-10 21:00:07 +0000156
157 // Look for MACOSX_DEPLOYMENT_TARGET, otherwise use the version
158 // from the host.
159 const char *Version = ::getenv("MACOSX_DEPLOYMENT_TARGET");
160 if (!Version)
161 Version = MacosxVersionMin.c_str();
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000162 const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
Daniel Dunbarf36a06a2009-04-10 21:00:07 +0000163 DAL->append(DAL->MakeJoinedArg(0, O, Version));
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000164 }
Daniel Dunbar4e7e9cf2009-03-25 06:12:34 +0000165
166 for (ArgList::iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) {
167 Arg *A = *it;
168
169 if (A->getOption().matches(options::OPT_Xarch__)) {
170 // FIXME: Canonicalize name.
171 if (getArchName() != A->getValue(Args, 0))
172 continue;
173
174 // FIXME: The arg is leaked here, and we should have a nicer
175 // interface for this.
Daniel Dunbar4e7e9cf2009-03-25 06:12:34 +0000176 unsigned Prev, Index = Prev = A->getIndex() + 1;
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000177 Arg *XarchArg = Opts.ParseOneArg(Args, Index);
Daniel Dunbar4e7e9cf2009-03-25 06:12:34 +0000178
179 // If the argument parsing failed or more than one argument was
180 // consumed, the -Xarch_ argument's parameter tried to consume
181 // extra arguments. Emit an error and ignore.
182 //
183 // We also want to disallow any options which would alter the
184 // driver behavior; that isn't going to work in our model. We
185 // use isDriverOption() as an approximation, although things
186 // like -O4 are going to slip through.
187 if (!XarchArg || Index > Prev + 1 ||
188 XarchArg->getOption().isDriverOption()) {
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000189 getHost().getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument)
Daniel Dunbar4e7e9cf2009-03-25 06:12:34 +0000190 << A->getAsString(Args);
191 continue;
192 }
193
Daniel Dunbar478edc22009-03-29 22:29:05 +0000194 XarchArg->setBaseArg(A);
Daniel Dunbar4e7e9cf2009-03-25 06:12:34 +0000195 A = XarchArg;
196 }
197
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000198 // Sob. These is strictly gcc compatible for the time being. Apple
199 // gcc translates options twice, which means that self-expanding
200 // options add duplicates.
201 options::ID id = A->getOption().getId();
202 switch (id) {
203 default:
204 DAL->append(A);
205 break;
206
207 case options::OPT_mkernel:
208 case options::OPT_fapple_kext:
209 DAL->append(A);
Daniel Dunbar478edc22009-03-29 22:29:05 +0000210 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_static)));
211 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_static)));
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000212 break;
213
214 case options::OPT_dependency_file:
Daniel Dunbar478edc22009-03-29 22:29:05 +0000215 DAL->append(DAL->MakeSeparateArg(A, Opts.getOption(options::OPT_MF),
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000216 A->getValue(Args)));
217 break;
218
219 case options::OPT_gfull:
Daniel Dunbar478edc22009-03-29 22:29:05 +0000220 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_g_Flag)));
221 DAL->append(DAL->MakeFlagArg(A,
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000222 Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols)));
223 break;
224
225 case options::OPT_gused:
Daniel Dunbar478edc22009-03-29 22:29:05 +0000226 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_g_Flag)));
227 DAL->append(DAL->MakeFlagArg(A,
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000228 Opts.getOption(options::OPT_feliminate_unused_debug_symbols)));
229 break;
230
231 case options::OPT_fterminated_vtables:
232 case options::OPT_findirect_virtual_calls:
Daniel Dunbar478edc22009-03-29 22:29:05 +0000233 DAL->append(DAL->MakeFlagArg(A,
234 Opts.getOption(options::OPT_fapple_kext)));
235 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_static)));
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000236 break;
237
238 case options::OPT_shared:
Daniel Dunbar478edc22009-03-29 22:29:05 +0000239 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_dynamiclib)));
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000240 break;
241
242 case options::OPT_fconstant_cfstrings:
Daniel Dunbar478edc22009-03-29 22:29:05 +0000243 DAL->append(DAL->MakeFlagArg(A,
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000244 Opts.getOption(options::OPT_mconstant_cfstrings)));
245 break;
246
247 case options::OPT_fno_constant_cfstrings:
Daniel Dunbar478edc22009-03-29 22:29:05 +0000248 DAL->append(DAL->MakeFlagArg(A,
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000249 Opts.getOption(options::OPT_mno_constant_cfstrings)));
250 break;
251
252 case options::OPT_Wnonportable_cfstrings:
Daniel Dunbar478edc22009-03-29 22:29:05 +0000253 DAL->append(DAL->MakeFlagArg(A,
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000254 Opts.getOption(options::OPT_mwarn_nonportable_cfstrings)));
255 break;
256
257 case options::OPT_Wno_nonportable_cfstrings:
Daniel Dunbar478edc22009-03-29 22:29:05 +0000258 DAL->append(DAL->MakeFlagArg(A,
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000259 Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings)));
260 break;
261
262 case options::OPT_fpascal_strings:
Daniel Dunbar478edc22009-03-29 22:29:05 +0000263 DAL->append(DAL->MakeFlagArg(A,
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000264 Opts.getOption(options::OPT_mpascal_strings)));
265 break;
266
267 case options::OPT_fno_pascal_strings:
Daniel Dunbar478edc22009-03-29 22:29:05 +0000268 DAL->append(DAL->MakeFlagArg(A,
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000269 Opts.getOption(options::OPT_mno_pascal_strings)));
270 break;
271 }
Daniel Dunbar4e7e9cf2009-03-25 06:12:34 +0000272 }
273
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000274 // FIXME: Actually, gcc always adds this, but it is filtered for
275 // duplicates somewhere. This also changes the order of things, so
276 // look it up.
277 if (getArchName() == "x86_64")
278 if (!Args.hasArg(options::OPT_m64, false))
Daniel Dunbar478edc22009-03-29 22:29:05 +0000279 DAL->append(DAL->MakeFlagArg(0, Opts.getOption(options::OPT_m64)));
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000280
281 if (!Args.hasArg(options::OPT_mtune_EQ, false))
Daniel Dunbar478edc22009-03-29 22:29:05 +0000282 DAL->append(DAL->MakeJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ),
Daniel Dunbarec069ed2009-03-25 06:58:31 +0000283 "core2"));
284
Daniel Dunbar4e7e9cf2009-03-25 06:12:34 +0000285 return DAL;
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000286}
287
288bool Darwin_X86::IsMathErrnoDefault() const {
289 return false;
290}
291
292bool Darwin_X86::IsUnwindTablesDefault() const {
293 // FIXME: Gross; we should probably have some separate target
294 // definition, possibly even reusing the one in clang.
295 return getArchName() == "x86_64";
296}
297
298const char *Darwin_X86::GetDefaultRelocationModel() const {
299 return "pic";
300}
301
302const char *Darwin_X86::GetForcedPicModel() const {
303 if (getArchName() == "x86_64")
304 return "pic";
305 return 0;
306}
307
Daniel Dunbar39176082009-03-20 00:20:03 +0000308/// Generic_GCC - A tool chain using the 'gcc' command to perform
309/// all subcommands; this relies on gcc translating the majority of
310/// command line options.
311
Daniel Dunbarc50b00d2009-03-23 16:15:50 +0000312Generic_GCC::Generic_GCC(const HostInfo &Host, const char *Arch,
313 const char *Platform, const char *OS)
314 : ToolChain(Host, Arch, Platform, OS)
315{
Daniel Dunbar82fa7c52009-03-24 04:07:10 +0000316 std::string Path(getHost().getDriver().Dir);
317 Path += "/../libexec";
318 getProgramPaths().push_back(Path);
319
Daniel Dunbarc50b00d2009-03-23 16:15:50 +0000320 getProgramPaths().push_back(getHost().getDriver().Dir);
321}
322
Daniel Dunbar39176082009-03-20 00:20:03 +0000323Generic_GCC::~Generic_GCC() {
324 // Free tool implementations.
325 for (llvm::DenseMap<unsigned, Tool*>::iterator
326 it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
327 delete it->second;
328}
329
330Tool &Generic_GCC::SelectTool(const Compilation &C,
331 const JobAction &JA) const {
332 Action::ActionClass Key;
Daniel Dunbaraf80e1f2009-03-24 18:57:02 +0000333 if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName()))
Daniel Dunbar39176082009-03-20 00:20:03 +0000334 Key = Action::AnalyzeJobClass;
335 else
336 Key = JA.getKind();
337
338 Tool *&T = Tools[Key];
339 if (!T) {
340 switch (Key) {
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000341 case Action::InputClass:
342 case Action::BindArchClass:
Daniel Dunbar39176082009-03-20 00:20:03 +0000343 assert(0 && "Invalid tool kind.");
344 case Action::PreprocessJobClass:
345 T = new tools::gcc::Preprocess(*this); break;
346 case Action::PrecompileJobClass:
347 T = new tools::gcc::Precompile(*this); break;
348 case Action::AnalyzeJobClass:
349 T = new tools::Clang(*this); break;
350 case Action::CompileJobClass:
351 T = new tools::gcc::Compile(*this); break;
352 case Action::AssembleJobClass:
353 T = new tools::gcc::Assemble(*this); break;
354 case Action::LinkJobClass:
355 T = new tools::gcc::Link(*this); break;
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000356
357 // This is a bit ungeneric, but the only platform using a driver
358 // driver is Darwin.
359 case Action::LipoJobClass:
360 T = new tools::darwin::Lipo(*this); break;
Daniel Dunbar39176082009-03-20 00:20:03 +0000361 }
362 }
363
364 return *T;
365}
366
367bool Generic_GCC::IsMathErrnoDefault() const {
368 return true;
369}
370
371bool Generic_GCC::IsUnwindTablesDefault() const {
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000372 // FIXME: Gross; we should probably have some separate target
373 // definition, possibly even reusing the one in clang.
Daniel Dunbar39176082009-03-20 00:20:03 +0000374 return getArchName() == "x86_64";
375}
376
377const char *Generic_GCC::GetDefaultRelocationModel() const {
378 return "static";
379}
380
381const char *Generic_GCC::GetForcedPicModel() const {
382 return 0;
383}
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000384
385DerivedArgList *Generic_GCC::TranslateArgs(InputArgList &Args) const {
386 return new DerivedArgList(Args, true);
387}
Daniel Dunbar75358d22009-03-30 21:06:03 +0000388
389/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
390
391FreeBSD::FreeBSD(const HostInfo &Host, const char *Arch,
392 const char *Platform, const char *OS, bool Lib32)
393 : Generic_GCC(Host, Arch, Platform, OS) {
Daniel Dunbarbc534662009-04-02 18:30:04 +0000394 if (Lib32) {
Daniel Dunbar75358d22009-03-30 21:06:03 +0000395 getFilePaths().push_back(getHost().getDriver().Dir + "/../lib32");
Daniel Dunbarbc534662009-04-02 18:30:04 +0000396 getFilePaths().push_back("/usr/lib32");
397 } else {
Daniel Dunbar75358d22009-03-30 21:06:03 +0000398 getFilePaths().push_back(getHost().getDriver().Dir + "/../lib");
Daniel Dunbarbc534662009-04-02 18:30:04 +0000399 getFilePaths().push_back("/usr/lib");
400 }
Daniel Dunbar75358d22009-03-30 21:06:03 +0000401}
402
403Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
404 Action::ActionClass Key;
405 if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName()))
406 Key = Action::AnalyzeJobClass;
407 else
408 Key = JA.getKind();
409
410 Tool *&T = Tools[Key];
411 if (!T) {
412 switch (Key) {
Daniel Dunbar68a31d42009-03-31 17:45:15 +0000413 case Action::AssembleJobClass:
414 T = new tools::freebsd::Assemble(*this); break;
Daniel Dunbar008f54a2009-04-01 19:36:32 +0000415 case Action::LinkJobClass:
416 T = new tools::freebsd::Link(*this); break;
Daniel Dunbar75358d22009-03-30 21:06:03 +0000417 default:
418 T = &Generic_GCC::SelectTool(C, JA);
419 }
420 }
421
422 return *T;
423}
Daniel Dunbar11e1b402009-05-02 18:28:39 +0000424
425/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
426
427DragonFly::DragonFly(const HostInfo &Host, const char *Arch,
428 const char *Platform, const char *OS)
429 : Generic_GCC(Host, Arch, Platform, OS) {
430
431 // Path mangling to find libexec
432 std::string Path(getHost().getDriver().Dir);
433
434 Path += "/../libexec";
435 getProgramPaths().push_back(Path);
436 getProgramPaths().push_back(getHost().getDriver().Dir);
437
438 getFilePaths().push_back(getHost().getDriver().Dir + "/../lib");
439 getFilePaths().push_back("/usr/lib");
440 getFilePaths().push_back("/usr/lib/gcc41");
441}
442
443Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const {
444 Action::ActionClass Key;
445 if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName()))
446 Key = Action::AnalyzeJobClass;
447 else
448 Key = JA.getKind();
449
450 Tool *&T = Tools[Key];
451 if (!T) {
452 switch (Key) {
453 case Action::AssembleJobClass:
454 T = new tools::dragonfly::Assemble(*this); break;
455 case Action::LinkJobClass:
456 T = new tools::dragonfly::Link(*this); break;
457 default:
458 T = &Generic_GCC::SelectTool(C, JA);
459 }
460 }
461
462 return *T;
463}