1 //===--- HostInfo.cpp - Host specific information -----------------------*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "clang/Driver/HostInfo.h"
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"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/Support/Compiler.h"
22 #include "ToolChains.h"
26 using namespace clang::driver
;
28 HostInfo::HostInfo(const Driver
&D
, const llvm::Triple
&_Triple
)
29 : TheDriver(D
), Triple(_Triple
)
34 HostInfo::~HostInfo() {
41 /// DarwinHostInfo - Darwin host information implementation.
42 class DarwinHostInfo
: public HostInfo
{
43 /// Darwin version of host.
44 unsigned DarwinVersion
[3];
46 /// GCC version to use on this host.
47 unsigned GCCVersion
[3];
49 /// Cache of tool chains we have created.
50 mutable llvm::StringMap
<ToolChain
*> ToolChains
;
53 DarwinHostInfo(const Driver
&D
, const llvm::Triple
&Triple
);
56 virtual bool useDriverDriver() const;
58 virtual types::ID
lookupTypeForExtension(const char *Ext
) const {
59 types::ID Ty
= types::lookupTypeForExtension(Ext
);
61 // Darwin always preprocesses assembly files (unless -x is used
63 if (Ty
== types::TY_PP_Asm
)
69 virtual ToolChain
*getToolChain(const ArgList
&Args
,
70 const char *ArchName
) const;
73 DarwinHostInfo::DarwinHostInfo(const Driver
&D
, const llvm::Triple
& Triple
)
74 : HostInfo(D
, Triple
) {
76 assert((getArchName() == "i386" || getArchName() == "x86_64" ||
77 getArchName() == "powerpc" || getArchName() == "powerpc64" ||
78 getArchName() == "arm") &&
79 "Unknown Darwin arch.");
81 assert(memcmp(&getOSName()[0], "darwin", 6) == 0 &&
82 "Unknown Darwin platform.");
84 if (!Driver::GetReleaseVersion(&getOSName()[6],
85 DarwinVersion
[0], DarwinVersion
[1],
86 DarwinVersion
[2], HadExtra
)) {
87 D
.Diag(clang::diag::err_drv_invalid_darwin_version
)
91 // We can only call 4.2.1 for now.
97 DarwinHostInfo::~DarwinHostInfo() {
98 for (llvm::StringMap
<ToolChain
*>::iterator
99 it
= ToolChains
.begin(), ie
= ToolChains
.end(); it
!= ie
; ++it
)
103 bool DarwinHostInfo::useDriverDriver() const {
107 ToolChain
*DarwinHostInfo::getToolChain(const ArgList
&Args
,
108 const char *ArchName
) const {
111 // If we aren't looking for a specific arch, infer the default architecture
112 // based on -arch and -m32/-m64 command line options.
113 if (Arg
*A
= Args
.getLastArg(options::OPT_arch
)) {
114 // The gcc driver behavior with multiple -arch flags wasn't consistent for
115 // things which rely on a default architecture. We just use the last -arch
116 // to find the default tool chain.
117 Arch
= A
->getValue(Args
);
119 // Normalize arch name; we shouldn't be doing this here.
121 // FIXME: This should be unnecessary once everything moves over to using
122 // the ID based Triple interface.
125 else if (Arch
== "ppc64")
128 // Otherwise default to the arch of the host.
129 Arch
= getArchName();
131 ArchName
= Arch
.c_str();
133 // Honor -m32 and -m64 when finding the default tool chain.
134 if (Arg
*A
= Args
.getLastArg(options::OPT_m32
, options::OPT_m64
)) {
135 if (Arch
== "i386" || Arch
== "x86_64") {
136 ArchName
= (A
->getOption().getId() == options::OPT_m32
) ? "i386" :
138 } else if (Arch
== "powerpc" || Arch
== "powerpc64") {
139 ArchName
= (A
->getOption().getId() == options::OPT_m32
) ? "powerpc" :
144 // Normalize arch name; we shouldn't be doing this here.
146 // FIXME: This should be unnecessary once everything moves over to using the
147 // ID based Triple interface.
148 if (strcmp(ArchName
, "ppc") == 0)
149 ArchName
= "powerpc";
150 else if (strcmp(ArchName
, "ppc64") == 0)
151 ArchName
= "powerpc64";
154 ToolChain
*&TC
= ToolChains
[ArchName
];
156 llvm::Triple
TCTriple(getTriple());
157 TCTriple
.setArchName(ArchName
);
159 if (strcmp(ArchName
, "i386") == 0 || strcmp(ArchName
, "x86_64") == 0)
160 TC
= new toolchains::Darwin_X86(*this, TCTriple
,
164 TC
= new toolchains::Darwin_GCC(*this, TCTriple
);
172 /// UnknownHostInfo - Generic host information to use for unknown
174 class UnknownHostInfo
: public HostInfo
{
175 /// Cache of tool chains we have created.
176 mutable llvm::StringMap
<ToolChain
*> ToolChains
;
179 UnknownHostInfo(const Driver
&D
, const llvm::Triple
& Triple
);
182 virtual bool useDriverDriver() const;
184 virtual types::ID
lookupTypeForExtension(const char *Ext
) const {
185 return types::lookupTypeForExtension(Ext
);
188 virtual ToolChain
*getToolChain(const ArgList
&Args
,
189 const char *ArchName
) const;
192 UnknownHostInfo::UnknownHostInfo(const Driver
&D
, const llvm::Triple
& Triple
)
193 : HostInfo(D
, Triple
) {
196 UnknownHostInfo::~UnknownHostInfo() {
197 for (llvm::StringMap
<ToolChain
*>::iterator
198 it
= ToolChains
.begin(), ie
= ToolChains
.end(); it
!= ie
; ++it
)
202 bool UnknownHostInfo::useDriverDriver() const {
206 ToolChain
*UnknownHostInfo::getToolChain(const ArgList
&Args
,
207 const char *ArchName
) const {
209 "Unexpected arch name on platform without driver driver support.");
211 // Automatically handle some instances of -m32/-m64 we know about.
212 std::string Arch
= getArchName();
213 ArchName
= Arch
.c_str();
214 if (Arg
*A
= Args
.getLastArg(options::OPT_m32
, options::OPT_m64
)) {
215 if (Triple
.getArch() == llvm::Triple::x86
||
216 Triple
.getArch() == llvm::Triple::x86_64
) {
218 (A
->getOption().getId() == options::OPT_m32
) ? "i386" : "x86_64";
219 } else if (Triple
.getArch() == llvm::Triple::ppc
||
220 Triple
.getArch() == llvm::Triple::ppc64
) {
222 (A
->getOption().getId() == options::OPT_m32
) ? "powerpc" : "powerpc64";
226 ToolChain
*&TC
= ToolChains
[ArchName
];
228 llvm::Triple
TCTriple(getTriple());
229 TCTriple
.setArchName(ArchName
);
231 TC
= new toolchains::Generic_GCC(*this, TCTriple
);
239 /// OpenBSDHostInfo - OpenBSD host information implementation.
240 class OpenBSDHostInfo
: public HostInfo
{
241 /// Cache of tool chains we have created.
242 mutable llvm::StringMap
<ToolChain
*> ToolChains
;
245 OpenBSDHostInfo(const Driver
&D
, const llvm::Triple
& Triple
)
246 : HostInfo(D
, Triple
) {}
249 virtual bool useDriverDriver() const;
251 virtual types::ID
lookupTypeForExtension(const char *Ext
) const {
252 return types::lookupTypeForExtension(Ext
);
255 virtual ToolChain
*getToolChain(const ArgList
&Args
,
256 const char *ArchName
) const;
259 OpenBSDHostInfo::~OpenBSDHostInfo() {
260 for (llvm::StringMap
<ToolChain
*>::iterator
261 it
= ToolChains
.begin(), ie
= ToolChains
.end(); it
!= ie
; ++it
)
265 bool OpenBSDHostInfo::useDriverDriver() const {
269 ToolChain
*OpenBSDHostInfo::getToolChain(const ArgList
&Args
,
270 const char *ArchName
) const {
272 "Unexpected arch name on platform without driver driver support.");
274 std::string Arch
= getArchName();
275 ArchName
= Arch
.c_str();
277 ToolChain
*&TC
= ToolChains
[ArchName
];
279 llvm::Triple
TCTriple(getTriple());
280 TCTriple
.setArchName(ArchName
);
282 TC
= new toolchains::OpenBSD(*this, TCTriple
);
290 /// FreeBSDHostInfo - FreeBSD host information implementation.
291 class FreeBSDHostInfo
: public HostInfo
{
292 /// Cache of tool chains we have created.
293 mutable llvm::StringMap
<ToolChain
*> ToolChains
;
296 FreeBSDHostInfo(const Driver
&D
, const llvm::Triple
& Triple
)
297 : HostInfo(D
, Triple
) {}
300 virtual bool useDriverDriver() const;
302 virtual types::ID
lookupTypeForExtension(const char *Ext
) const {
303 return types::lookupTypeForExtension(Ext
);
306 virtual ToolChain
*getToolChain(const ArgList
&Args
,
307 const char *ArchName
) const;
310 FreeBSDHostInfo::~FreeBSDHostInfo() {
311 for (llvm::StringMap
<ToolChain
*>::iterator
312 it
= ToolChains
.begin(), ie
= ToolChains
.end(); it
!= ie
; ++it
)
316 bool FreeBSDHostInfo::useDriverDriver() const {
320 ToolChain
*FreeBSDHostInfo::getToolChain(const ArgList
&Args
,
321 const char *ArchName
) const {
325 "Unexpected arch name on platform without driver driver support.");
327 // On x86_64 we need to be able to compile 32-bits binaries as well.
328 // Compiling 64-bit binaries on i386 is not supported. We don't have a
330 std::string Arch
= getArchName();
331 ArchName
= Arch
.c_str();
332 if (Args
.hasArg(options::OPT_m32
) && getArchName() == "x86_64") {
337 ToolChain
*&TC
= ToolChains
[ArchName
];
339 llvm::Triple
TCTriple(getTriple());
340 TCTriple
.setArchName(ArchName
);
342 TC
= new toolchains::FreeBSD(*this, TCTriple
, Lib32
);
348 // DragonFly Host Info
350 /// DragonFlyHostInfo - DragonFly host information implementation.
351 class DragonFlyHostInfo
: public HostInfo
{
352 /// Cache of tool chains we have created.
353 mutable llvm::StringMap
<ToolChain
*> ToolChains
;
356 DragonFlyHostInfo(const Driver
&D
, const llvm::Triple
& Triple
)
357 : HostInfo(D
, Triple
) {}
358 ~DragonFlyHostInfo();
360 virtual bool useDriverDriver() const;
362 virtual types::ID
lookupTypeForExtension(const char *Ext
) const {
363 return types::lookupTypeForExtension(Ext
);
366 virtual ToolChain
*getToolChain(const ArgList
&Args
,
367 const char *ArchName
) const;
370 DragonFlyHostInfo::~DragonFlyHostInfo() {
371 for (llvm::StringMap
<ToolChain
*>::iterator
372 it
= ToolChains
.begin(), ie
= ToolChains
.end(); it
!= ie
; ++it
)
376 bool DragonFlyHostInfo::useDriverDriver() const {
380 ToolChain
*DragonFlyHostInfo::getToolChain(const ArgList
&Args
,
381 const char *ArchName
) const {
383 "Unexpected arch name on platform without driver driver support.");
385 ToolChain
*&TC
= ToolChains
[getArchName()];
388 llvm::Triple
TCTriple(getTriple());
389 TCTriple
.setArchName(getArchName());
391 TC
= new toolchains::DragonFly(*this, TCTriple
);
399 /// LinuxHostInfo - Linux host information implementation.
400 class LinuxHostInfo
: public HostInfo
{
401 /// Cache of tool chains we have created.
402 mutable llvm::StringMap
<ToolChain
*> ToolChains
;
405 LinuxHostInfo(const Driver
&D
, const llvm::Triple
& Triple
)
406 : HostInfo(D
, Triple
) {}
409 virtual bool useDriverDriver() const;
411 virtual types::ID
lookupTypeForExtension(const char *Ext
) const {
412 return types::lookupTypeForExtension(Ext
);
415 virtual ToolChain
*getToolChain(const ArgList
&Args
,
416 const char *ArchName
) const;
419 LinuxHostInfo::~LinuxHostInfo() {
420 for (llvm::StringMap
<ToolChain
*>::iterator
421 it
= ToolChains
.begin(), ie
= ToolChains
.end(); it
!= ie
; ++it
)
425 bool LinuxHostInfo::useDriverDriver() const {
429 ToolChain
*LinuxHostInfo::getToolChain(const ArgList
&Args
,
430 const char *ArchName
) const {
433 "Unexpected arch name on platform without driver driver support.");
435 // Automatically handle some instances of -m32/-m64 we know about.
436 std::string Arch
= getArchName();
437 ArchName
= Arch
.c_str();
438 if (Arg
*A
= Args
.getLastArg(options::OPT_m32
, options::OPT_m64
)) {
439 if (Triple
.getArch() == llvm::Triple::x86
||
440 Triple
.getArch() == llvm::Triple::x86_64
) {
442 (A
->getOption().getId() == options::OPT_m32
) ? "i386" : "x86_64";
443 } else if (Triple
.getArch() == llvm::Triple::ppc
||
444 Triple
.getArch() == llvm::Triple::ppc64
) {
446 (A
->getOption().getId() == options::OPT_m32
) ? "powerpc" : "powerpc64";
450 ToolChain
*&TC
= ToolChains
[ArchName
];
453 llvm::Triple
TCTriple(getTriple());
454 TCTriple
.setArchName(ArchName
);
456 TC
= new toolchains::Linux(*this, TCTriple
);
465 clang::driver::createDarwinHostInfo(const Driver
&D
,
466 const llvm::Triple
& Triple
){
467 return new DarwinHostInfo(D
, Triple
);
471 clang::driver::createOpenBSDHostInfo(const Driver
&D
,
472 const llvm::Triple
& Triple
) {
473 return new OpenBSDHostInfo(D
, Triple
);
477 clang::driver::createFreeBSDHostInfo(const Driver
&D
,
478 const llvm::Triple
& Triple
) {
479 return new FreeBSDHostInfo(D
, Triple
);
483 clang::driver::createDragonFlyHostInfo(const Driver
&D
,
484 const llvm::Triple
& Triple
) {
485 return new DragonFlyHostInfo(D
, Triple
);
489 clang::driver::createLinuxHostInfo(const Driver
&D
,
490 const llvm::Triple
& Triple
) {
491 return new LinuxHostInfo(D
, Triple
);
495 clang::driver::createUnknownHostInfo(const Driver
&D
,
496 const llvm::Triple
& Triple
) {
497 return new UnknownHostInfo(D
, Triple
);