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 /// FreeBSDHostInfo - FreeBSD host information implementation.
240 class FreeBSDHostInfo : public HostInfo {
241 /// Cache of tool chains we have created.
242 mutable llvm::StringMap<ToolChain*> ToolChains;
245 FreeBSDHostInfo(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 FreeBSDHostInfo::~FreeBSDHostInfo() {
260 for (llvm::StringMap<ToolChain*>::iterator
261 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
265 bool FreeBSDHostInfo::useDriverDriver() const {
269 ToolChain *FreeBSDHostInfo::getToolChain(const ArgList &Args,
270 const char *ArchName) const {
274 "Unexpected arch name on platform without driver driver support.");
276 // On x86_64 we need to be able to compile 32-bits binaries as well.
277 // Compiling 64-bit binaries on i386 is not supported. We don't have a
279 std::string Arch = getArchName();
280 ArchName = Arch.c_str();
281 if (Args.hasArg(options::OPT_m32) && getArchName() == "x86_64") {
286 ToolChain *&TC = ToolChains[ArchName];
288 llvm::Triple TCTriple(getTriple());
289 TCTriple.setArchName(ArchName);
291 TC = new toolchains::FreeBSD(*this, TCTriple, Lib32);
297 // DragonFly Host Info
299 /// DragonFlyHostInfo - DragonFly host information implementation.
300 class DragonFlyHostInfo : public HostInfo {
301 /// Cache of tool chains we have created.
302 mutable llvm::StringMap<ToolChain*> ToolChains;
305 DragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple)
306 : HostInfo(D, Triple) {}
307 ~DragonFlyHostInfo();
309 virtual bool useDriverDriver() const;
311 virtual types::ID lookupTypeForExtension(const char *Ext) const {
312 return types::lookupTypeForExtension(Ext);
315 virtual ToolChain *getToolChain(const ArgList &Args,
316 const char *ArchName) const;
319 DragonFlyHostInfo::~DragonFlyHostInfo() {
320 for (llvm::StringMap<ToolChain*>::iterator
321 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
325 bool DragonFlyHostInfo::useDriverDriver() const {
329 ToolChain *DragonFlyHostInfo::getToolChain(const ArgList &Args,
330 const char *ArchName) const {
332 "Unexpected arch name on platform without driver driver support.");
334 ToolChain *&TC = ToolChains[getArchName()];
337 llvm::Triple TCTriple(getTriple());
338 TCTriple.setArchName(getArchName());
340 TC = new toolchains::DragonFly(*this, TCTriple);
348 /// LinuxHostInfo - Linux host information implementation.
349 class LinuxHostInfo : public HostInfo {
350 /// Cache of tool chains we have created.
351 mutable llvm::StringMap<ToolChain*> ToolChains;
354 LinuxHostInfo(const Driver &D, const llvm::Triple& Triple)
355 : HostInfo(D, Triple) {}
358 virtual bool useDriverDriver() const;
360 virtual types::ID lookupTypeForExtension(const char *Ext) const {
361 return types::lookupTypeForExtension(Ext);
364 virtual ToolChain *getToolChain(const ArgList &Args,
365 const char *ArchName) const;
368 LinuxHostInfo::~LinuxHostInfo() {
369 for (llvm::StringMap<ToolChain*>::iterator
370 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
374 bool LinuxHostInfo::useDriverDriver() const {
378 ToolChain *LinuxHostInfo::getToolChain(const ArgList &Args,
379 const char *ArchName) const {
382 "Unexpected arch name on platform without driver driver support.");
384 // Automatically handle some instances of -m32/-m64 we know about.
385 std::string Arch = getArchName();
386 ArchName = Arch.c_str();
387 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
388 if (Triple.getArch() == llvm::Triple::x86 ||
389 Triple.getArch() == llvm::Triple::x86_64) {
391 (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
392 } else if (Triple.getArch() == llvm::Triple::ppc ||
393 Triple.getArch() == llvm::Triple::ppc64) {
395 (A->getOption().getId() == options::OPT_m32) ? "powerpc" : "powerpc64";
399 ToolChain *&TC = ToolChains[ArchName];
402 llvm::Triple TCTriple(getTriple());
403 TCTriple.setArchName(ArchName);
405 TC = new toolchains::Linux(*this, TCTriple);
414 clang::driver::createDarwinHostInfo(const Driver &D,
415 const llvm::Triple& Triple){
416 return new DarwinHostInfo(D, Triple);
420 clang::driver::createFreeBSDHostInfo(const Driver &D,
421 const llvm::Triple& Triple) {
422 return new FreeBSDHostInfo(D, Triple);
426 clang::driver::createDragonFlyHostInfo(const Driver &D,
427 const llvm::Triple& Triple) {
428 return new DragonFlyHostInfo(D, Triple);
432 clang::driver::createLinuxHostInfo(const Driver &D,
433 const llvm::Triple& Triple) {
434 return new LinuxHostInfo(D, Triple);
438 clang::driver::createUnknownHostInfo(const Driver &D,
439 const llvm::Triple& Triple) {
440 return new UnknownHostInfo(D, Triple);