blob: 18bb78659305e71181ff867bc1b44a1cf069fee7 [file] [log] [blame]
Shih-wei Liaof8fd82b2010-02-10 11:10:31 -08001//===--- HostInfo.cpp - Host specific information -----------------------*-===//
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 "clang/Driver/HostInfo.h"
11
12#include "clang/Driver/Arg.h"
13#include "clang/Driver/ArgList.h"
14#include "clang/Driver/Driver.h"
15#include "clang/Driver/DriverDiagnostic.h"
16#include "clang/Driver/Option.h"
17#include "clang/Driver/Options.h"
18
19#include "llvm/ADT/StringMap.h"
20#include "llvm/Support/Compiler.h"
21
22#include "ToolChains.h"
23
24#include <cassert>
25
26using namespace clang::driver;
27
28HostInfo::HostInfo(const Driver &D, const llvm::Triple &_Triple)
29 : TheDriver(D), Triple(_Triple) {
30}
31
32HostInfo::~HostInfo() {
33}
34
35namespace {
36
37// Darwin Host Info
38
39/// DarwinHostInfo - Darwin host information implementation.
40class DarwinHostInfo : public HostInfo {
41 /// Darwin version of host.
42 unsigned DarwinVersion[3];
43
44 /// GCC version to use on this host.
45 unsigned GCCVersion[3];
46
47 /// Cache of tool chains we have created.
48 mutable llvm::DenseMap<unsigned, ToolChain*> ToolChains;
49
50public:
51 DarwinHostInfo(const Driver &D, const llvm::Triple &Triple);
52 ~DarwinHostInfo();
53
54 virtual bool useDriverDriver() const;
55
56 virtual types::ID lookupTypeForExtension(const char *Ext) const {
57 types::ID Ty = types::lookupTypeForExtension(Ext);
58
59 // Darwin always preprocesses assembly files (unless -x is used
60 // explicitly).
61 if (Ty == types::TY_PP_Asm)
62 return types::TY_Asm;
63
64 return Ty;
65 }
66
67 virtual ToolChain *CreateToolChain(const ArgList &Args,
68 const char *ArchName) const;
69};
70
71DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple)
72 : HostInfo(D, Triple) {
73
74 assert(Triple.getArch() != llvm::Triple::UnknownArch && "Invalid arch!");
75 assert(memcmp(&getOSName()[0], "darwin", 6) == 0 &&
76 "Unknown Darwin platform.");
77 bool HadExtra;
78 if (!Driver::GetReleaseVersion(&getOSName()[6],
79 DarwinVersion[0], DarwinVersion[1],
80 DarwinVersion[2], HadExtra))
81 D.Diag(clang::diag::err_drv_invalid_darwin_version) << getOSName();
82
83 // We can only call 4.2.1 for now.
84 GCCVersion[0] = 4;
85 GCCVersion[1] = 2;
86 GCCVersion[2] = 1;
87}
88
89DarwinHostInfo::~DarwinHostInfo() {
90 for (llvm::DenseMap<unsigned, ToolChain*>::iterator
91 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
92 delete it->second;
93}
94
95bool DarwinHostInfo::useDriverDriver() const {
96 return true;
97}
98
99ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args,
100 const char *ArchName) const {
101 llvm::Triple::ArchType Arch;
102
103 if (!ArchName) {
104 // If we aren't looking for a specific arch, infer the default architecture
105 // based on -arch and -m32/-m64 command line options.
106 if (Arg *A = Args.getLastArg(options::OPT_arch)) {
107 // The gcc driver behavior with multiple -arch flags wasn't consistent for
108 // things which rely on a default architecture. We just use the last -arch
109 // to find the default tool chain (assuming it is valid).
110 Arch = llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args));
111
112 // If it was invalid just use the host, we will reject this command line
113 // later.
114 if (Arch == llvm::Triple::UnknownArch)
115 Arch = getTriple().getArch();
116 } else {
117 // Otherwise default to the arch of the host.
118 Arch = getTriple().getArch();
119 }
120
121 // Honor -m32 and -m64 when finding the default tool chain.
122 //
123 // FIXME: Should this information be in llvm::Triple?
124 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
125 if (A->getOption().matches(options::OPT_m32)) {
126 if (Arch == llvm::Triple::x86_64)
127 Arch = llvm::Triple::x86;
128 if (Arch == llvm::Triple::ppc64)
129 Arch = llvm::Triple::ppc;
130 } else {
131 if (Arch == llvm::Triple::x86)
132 Arch = llvm::Triple::x86_64;
133 if (Arch == llvm::Triple::ppc)
134 Arch = llvm::Triple::ppc64;
135 }
136 }
137 } else
138 Arch = llvm::Triple::getArchTypeForDarwinArchName(ArchName);
139
140 assert(Arch != llvm::Triple::UnknownArch && "Unexpected arch!");
141 ToolChain *&TC = ToolChains[Arch];
142 if (!TC) {
143 llvm::Triple TCTriple(getTriple());
144 TCTriple.setArch(Arch);
145
146 // If we recognized the arch, match it to the toolchains we support.
147 if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
148 // We still use the legacy DarwinGCC toolchain on X86.
149 TC = new toolchains::DarwinGCC(*this, TCTriple, DarwinVersion,
150 GCCVersion);
151 } else if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)
152 TC = new toolchains::DarwinClang(*this, TCTriple, DarwinVersion);
153 else
154 TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple);
155 }
156
157 return TC;
158}
159
160// Unknown Host Info
161
162/// UnknownHostInfo - Generic host information to use for unknown hosts.
163class UnknownHostInfo : public HostInfo {
164 /// Cache of tool chains we have created.
165 mutable llvm::StringMap<ToolChain*> ToolChains;
166
167public:
168 UnknownHostInfo(const Driver &D, const llvm::Triple& Triple);
169 ~UnknownHostInfo();
170
171 virtual bool useDriverDriver() const;
172
173 virtual types::ID lookupTypeForExtension(const char *Ext) const {
174 return types::lookupTypeForExtension(Ext);
175 }
176
177 virtual ToolChain *CreateToolChain(const ArgList &Args,
178 const char *ArchName) const;
179};
180
181UnknownHostInfo::UnknownHostInfo(const Driver &D, const llvm::Triple& Triple)
182 : HostInfo(D, Triple) {
183}
184
185UnknownHostInfo::~UnknownHostInfo() {
186 for (llvm::StringMap<ToolChain*>::iterator
187 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
188 delete it->second;
189}
190
191bool UnknownHostInfo::useDriverDriver() const {
192 return false;
193}
194
195ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args,
196 const char *ArchName) const {
197 assert(!ArchName &&
198 "Unexpected arch name on platform without driver driver support.");
199
200 // Automatically handle some instances of -m32/-m64 we know about.
201 std::string Arch = getArchName();
202 ArchName = Arch.c_str();
203 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
204 if (Triple.getArch() == llvm::Triple::x86 ||
205 Triple.getArch() == llvm::Triple::x86_64) {
206 ArchName =
207 (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
208 } else if (Triple.getArch() == llvm::Triple::ppc ||
209 Triple.getArch() == llvm::Triple::ppc64) {
210 ArchName =
211 (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64";
212 }
213 }
214
215 ToolChain *&TC = ToolChains[ArchName];
216 if (!TC) {
217 llvm::Triple TCTriple(getTriple());
218 TCTriple.setArchName(ArchName);
219
220 TC = new toolchains::Generic_GCC(*this, TCTriple);
221 }
222
223 return TC;
224}
225
226// OpenBSD Host Info
227
228/// OpenBSDHostInfo - OpenBSD host information implementation.
229class OpenBSDHostInfo : public HostInfo {
230 /// Cache of tool chains we have created.
231 mutable llvm::StringMap<ToolChain*> ToolChains;
232
233public:
234 OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
235 : HostInfo(D, Triple) {}
236 ~OpenBSDHostInfo();
237
238 virtual bool useDriverDriver() const;
239
240 virtual types::ID lookupTypeForExtension(const char *Ext) const {
241 return types::lookupTypeForExtension(Ext);
242 }
243
244 virtual ToolChain *CreateToolChain(const ArgList &Args,
245 const char *ArchName) const;
246};
247
248OpenBSDHostInfo::~OpenBSDHostInfo() {
249 for (llvm::StringMap<ToolChain*>::iterator
250 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
251 delete it->second;
252}
253
254bool OpenBSDHostInfo::useDriverDriver() const {
255 return false;
256}
257
258ToolChain *OpenBSDHostInfo::CreateToolChain(const ArgList &Args,
259 const char *ArchName) const {
260 assert(!ArchName &&
261 "Unexpected arch name on platform without driver driver support.");
262
263 std::string Arch = getArchName();
264 ArchName = Arch.c_str();
265
266 ToolChain *&TC = ToolChains[ArchName];
267 if (!TC) {
268 llvm::Triple TCTriple(getTriple());
269 TCTriple.setArchName(ArchName);
270
271 TC = new toolchains::OpenBSD(*this, TCTriple);
272 }
273
274 return TC;
275}
276
277// AuroraUX Host Info
278
279/// AuroraUXHostInfo - AuroraUX host information implementation.
280class AuroraUXHostInfo : public HostInfo {
281 /// Cache of tool chains we have created.
282 mutable llvm::StringMap<ToolChain*> ToolChains;
283
284public:
285 AuroraUXHostInfo(const Driver &D, const llvm::Triple& Triple)
286 : HostInfo(D, Triple) {}
287 ~AuroraUXHostInfo();
288
289 virtual bool useDriverDriver() const;
290
291 virtual types::ID lookupTypeForExtension(const char *Ext) const {
292 return types::lookupTypeForExtension(Ext);
293 }
294
295 virtual ToolChain *CreateToolChain(const ArgList &Args,
296 const char *ArchName) const;
297};
298
299AuroraUXHostInfo::~AuroraUXHostInfo() {
300 for (llvm::StringMap<ToolChain*>::iterator
301 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
302 delete it->second;
303}
304
305bool AuroraUXHostInfo::useDriverDriver() const {
306 return false;
307}
308
309ToolChain *AuroraUXHostInfo::CreateToolChain(const ArgList &Args,
310 const char *ArchName) const {
311 assert(!ArchName &&
312 "Unexpected arch name on platform without driver driver support.");
313
314 ToolChain *&TC = ToolChains[getArchName()];
315
316 if (!TC) {
317 llvm::Triple TCTriple(getTriple());
318 TCTriple.setArchName(getArchName());
319
320 TC = new toolchains::AuroraUX(*this, TCTriple);
321 }
322
323 return TC;
324}
325
326// FreeBSD Host Info
327
328/// FreeBSDHostInfo - FreeBSD host information implementation.
329class FreeBSDHostInfo : public HostInfo {
330 /// Cache of tool chains we have created.
331 mutable llvm::StringMap<ToolChain*> ToolChains;
332
333public:
334 FreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
335 : HostInfo(D, Triple) {}
336 ~FreeBSDHostInfo();
337
338 virtual bool useDriverDriver() const;
339
340 virtual types::ID lookupTypeForExtension(const char *Ext) const {
341 return types::lookupTypeForExtension(Ext);
342 }
343
344 virtual ToolChain *CreateToolChain(const ArgList &Args,
345 const char *ArchName) const;
346};
347
348FreeBSDHostInfo::~FreeBSDHostInfo() {
349 for (llvm::StringMap<ToolChain*>::iterator
350 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
351 delete it->second;
352}
353
354bool FreeBSDHostInfo::useDriverDriver() const {
355 return false;
356}
357
358ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args,
359 const char *ArchName) const {
360 bool Lib32 = false;
361
362 assert(!ArchName &&
363 "Unexpected arch name on platform without driver driver support.");
364
365 // On x86_64 we need to be able to compile 32-bits binaries as well.
366 // Compiling 64-bit binaries on i386 is not supported. We don't have a
367 // lib64.
368 std::string Arch = getArchName();
369 ArchName = Arch.c_str();
370 if (Args.hasArg(options::OPT_m32) && getArchName() == "x86_64") {
371 ArchName = "i386";
372 Lib32 = true;
373 }
374
375 ToolChain *&TC = ToolChains[ArchName];
376 if (!TC) {
377 llvm::Triple TCTriple(getTriple());
378 TCTriple.setArchName(ArchName);
379
380 TC = new toolchains::FreeBSD(*this, TCTriple, Lib32);
381 }
382
383 return TC;
384}
385
386// DragonFly Host Info
387
388/// DragonFlyHostInfo - DragonFly host information implementation.
389class DragonFlyHostInfo : public HostInfo {
390 /// Cache of tool chains we have created.
391 mutable llvm::StringMap<ToolChain*> ToolChains;
392
393public:
394 DragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple)
395 : HostInfo(D, Triple) {}
396 ~DragonFlyHostInfo();
397
398 virtual bool useDriverDriver() const;
399
400 virtual types::ID lookupTypeForExtension(const char *Ext) const {
401 return types::lookupTypeForExtension(Ext);
402 }
403
404 virtual ToolChain *CreateToolChain(const ArgList &Args,
405 const char *ArchName) const;
406};
407
408DragonFlyHostInfo::~DragonFlyHostInfo() {
409 for (llvm::StringMap<ToolChain*>::iterator
410 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
411 delete it->second;
412}
413
414bool DragonFlyHostInfo::useDriverDriver() const {
415 return false;
416}
417
418ToolChain *DragonFlyHostInfo::CreateToolChain(const ArgList &Args,
419 const char *ArchName) const {
420 assert(!ArchName &&
421 "Unexpected arch name on platform without driver driver support.");
422
423 ToolChain *&TC = ToolChains[getArchName()];
424
425 if (!TC) {
426 llvm::Triple TCTriple(getTriple());
427 TCTriple.setArchName(getArchName());
428
429 TC = new toolchains::DragonFly(*this, TCTriple);
430 }
431
432 return TC;
433}
434
435// Linux Host Info
436
437/// LinuxHostInfo - Linux host information implementation.
438class LinuxHostInfo : public HostInfo {
439 /// Cache of tool chains we have created.
440 mutable llvm::StringMap<ToolChain*> ToolChains;
441
442public:
443 LinuxHostInfo(const Driver &D, const llvm::Triple& Triple)
444 : HostInfo(D, Triple) {}
445 ~LinuxHostInfo();
446
447 virtual bool useDriverDriver() const;
448
449 virtual types::ID lookupTypeForExtension(const char *Ext) const {
450 return types::lookupTypeForExtension(Ext);
451 }
452
453 virtual ToolChain *CreateToolChain(const ArgList &Args,
454 const char *ArchName) const;
455};
456
457LinuxHostInfo::~LinuxHostInfo() {
458 for (llvm::StringMap<ToolChain*>::iterator
459 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
460 delete it->second;
461}
462
463bool LinuxHostInfo::useDriverDriver() const {
464 return false;
465}
466
467ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args,
468 const char *ArchName) const {
469
470 assert(!ArchName &&
471 "Unexpected arch name on platform without driver driver support.");
472
473 // Automatically handle some instances of -m32/-m64 we know about.
474 std::string Arch = getArchName();
475 ArchName = Arch.c_str();
476 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
477 if (Triple.getArch() == llvm::Triple::x86 ||
478 Triple.getArch() == llvm::Triple::x86_64) {
479 ArchName =
480 (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
481 } else if (Triple.getArch() == llvm::Triple::ppc ||
482 Triple.getArch() == llvm::Triple::ppc64) {
483 ArchName =
484 (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64";
485 }
486 }
487
488 ToolChain *&TC = ToolChains[ArchName];
489
490 if (!TC) {
491 llvm::Triple TCTriple(getTriple());
492 TCTriple.setArchName(ArchName);
493
494 TC = new toolchains::Linux(*this, TCTriple);
495 }
496
497 return TC;
498}
499
500}
501
502const HostInfo *
503clang::driver::createAuroraUXHostInfo(const Driver &D,
504 const llvm::Triple& Triple){
505 return new AuroraUXHostInfo(D, Triple);
506}
507
508const HostInfo *
509clang::driver::createDarwinHostInfo(const Driver &D,
510 const llvm::Triple& Triple){
511 return new DarwinHostInfo(D, Triple);
512}
513
514const HostInfo *
515clang::driver::createOpenBSDHostInfo(const Driver &D,
516 const llvm::Triple& Triple) {
517 return new OpenBSDHostInfo(D, Triple);
518}
519
520const HostInfo *
521clang::driver::createFreeBSDHostInfo(const Driver &D,
522 const llvm::Triple& Triple) {
523 return new FreeBSDHostInfo(D, Triple);
524}
525
526const HostInfo *
527clang::driver::createDragonFlyHostInfo(const Driver &D,
528 const llvm::Triple& Triple) {
529 return new DragonFlyHostInfo(D, Triple);
530}
531
532const HostInfo *
533clang::driver::createLinuxHostInfo(const Driver &D,
534 const llvm::Triple& Triple) {
535 return new LinuxHostInfo(D, Triple);
536}
537
538const HostInfo *
539clang::driver::createUnknownHostInfo(const Driver &D,
540 const llvm::Triple& Triple) {
541 return new UnknownHostInfo(D, Triple);
542}