clang API Documentation
00001 //===--- HostInfo.cpp - Host specific information -----------------------*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "clang/Driver/HostInfo.h" 00011 00012 #include "clang/Driver/Arg.h" 00013 #include "clang/Driver/ArgList.h" 00014 #include "clang/Driver/Driver.h" 00015 #include "clang/Driver/DriverDiagnostic.h" 00016 #include "clang/Driver/Option.h" 00017 #include "clang/Driver/Options.h" 00018 00019 #include "llvm/ADT/StringMap.h" 00020 #include "llvm/Support/Compiler.h" 00021 00022 #include "ToolChains.h" 00023 00024 #include <cassert> 00025 00026 using namespace clang::driver; 00027 00028 HostInfo::HostInfo(const Driver &D, const llvm::Triple &_Triple) 00029 : TheDriver(D), Triple(_Triple) { 00030 } 00031 00032 HostInfo::~HostInfo() { 00033 } 00034 00035 namespace { 00036 00037 // Darwin Host Info 00038 00039 /// DarwinHostInfo - Darwin host information implementation. 00040 class DarwinHostInfo : public HostInfo { 00041 /// Darwin version of host. 00042 unsigned DarwinVersion[3]; 00043 00044 /// GCC version to use on this host. 00045 unsigned GCCVersion[3]; 00046 00047 /// Cache of tool chains we have created. 00048 mutable llvm::DenseMap<unsigned, ToolChain*> ToolChains; 00049 00050 public: 00051 DarwinHostInfo(const Driver &D, const llvm::Triple &Triple); 00052 ~DarwinHostInfo(); 00053 00054 virtual bool useDriverDriver() const; 00055 00056 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00057 types::ID Ty = types::lookupTypeForExtension(Ext); 00058 00059 // Darwin always preprocesses assembly files (unless -x is used 00060 // explicitly). 00061 if (Ty == types::TY_PP_Asm) 00062 return types::TY_Asm; 00063 00064 return Ty; 00065 } 00066 00067 virtual ToolChain *CreateToolChain(const ArgList &Args, 00068 const char *ArchName) const; 00069 }; 00070 00071 DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple) 00072 : HostInfo(D, Triple) { 00073 00074 assert(Triple.getArch() != llvm::Triple::UnknownArch && "Invalid arch!"); 00075 assert(memcmp(&getOSName()[0], "darwin", 6) == 0 && 00076 "Unknown Darwin platform."); 00077 bool HadExtra; 00078 if (!Driver::GetReleaseVersion(&getOSName()[6], 00079 DarwinVersion[0], DarwinVersion[1], 00080 DarwinVersion[2], HadExtra)) 00081 D.Diag(clang::diag::err_drv_invalid_darwin_version) << getOSName(); 00082 00083 // We can only call 4.2.1 for now. 00084 GCCVersion[0] = 4; 00085 GCCVersion[1] = 2; 00086 GCCVersion[2] = 1; 00087 } 00088 00089 DarwinHostInfo::~DarwinHostInfo() { 00090 for (llvm::DenseMap<unsigned, ToolChain*>::iterator 00091 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00092 delete it->second; 00093 } 00094 00095 bool DarwinHostInfo::useDriverDriver() const { 00096 return true; 00097 } 00098 00099 ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args, 00100 const char *ArchName) const { 00101 llvm::Triple::ArchType Arch; 00102 00103 if (!ArchName) { 00104 // If we aren't looking for a specific arch, infer the default architecture 00105 // based on -arch and -m32/-m64 command line options. 00106 if (Arg *A = Args.getLastArg(options::OPT_arch)) { 00107 // The gcc driver behavior with multiple -arch flags wasn't consistent for 00108 // things which rely on a default architecture. We just use the last -arch 00109 // to find the default tool chain (assuming it is valid). 00110 Arch = llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args)); 00111 00112 // If it was invalid just use the host, we will reject this command line 00113 // later. 00114 if (Arch == llvm::Triple::UnknownArch) 00115 Arch = getTriple().getArch(); 00116 } else { 00117 // Otherwise default to the arch of the host. 00118 Arch = getTriple().getArch(); 00119 } 00120 00121 // Honor -m32 and -m64 when finding the default tool chain. 00122 // 00123 // FIXME: Should this information be in llvm::Triple? 00124 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { 00125 if (A->getOption().matches(options::OPT_m32)) { 00126 if (Arch == llvm::Triple::x86_64) 00127 Arch = llvm::Triple::x86; 00128 if (Arch == llvm::Triple::ppc64) 00129 Arch = llvm::Triple::ppc; 00130 } else { 00131 if (Arch == llvm::Triple::x86) 00132 Arch = llvm::Triple::x86_64; 00133 if (Arch == llvm::Triple::ppc) 00134 Arch = llvm::Triple::ppc64; 00135 } 00136 } 00137 } else 00138 Arch = llvm::Triple::getArchTypeForDarwinArchName(ArchName); 00139 00140 assert(Arch != llvm::Triple::UnknownArch && "Unexpected arch!"); 00141 ToolChain *&TC = ToolChains[Arch]; 00142 if (!TC) { 00143 llvm::Triple TCTriple(getTriple()); 00144 TCTriple.setArch(Arch); 00145 00146 // If we recognized the arch, match it to the toolchains we support. 00147 if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) { 00148 // We still use the legacy DarwinGCC toolchain on X86. 00149 TC = new toolchains::DarwinGCC(*this, TCTriple, DarwinVersion, 00150 GCCVersion); 00151 } else if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) 00152 TC = new toolchains::DarwinClang(*this, TCTriple, DarwinVersion); 00153 else 00154 TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple); 00155 } 00156 00157 return TC; 00158 } 00159 00160 // TCE Host Info 00161 00162 /// TCEHostInfo - TCE host information implementation (see http://tce.cs.tut.fi) 00163 class TCEHostInfo : public HostInfo { 00164 00165 public: 00166 TCEHostInfo(const Driver &D, const llvm::Triple &Triple); 00167 ~TCEHostInfo() {} 00168 00169 virtual bool useDriverDriver() const; 00170 00171 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00172 types::ID Ty = types::lookupTypeForExtension(Ext); 00173 00174 if (Ty == types::TY_PP_Asm) 00175 return types::TY_Asm; 00176 00177 return Ty; 00178 } 00179 00180 virtual ToolChain *CreateToolChain(const ArgList &Args, 00181 const char *ArchName) const; 00182 }; 00183 00184 TCEHostInfo::TCEHostInfo(const Driver &D, const llvm::Triple& Triple) 00185 : HostInfo(D, Triple) { 00186 } 00187 00188 bool TCEHostInfo::useDriverDriver() const { 00189 return false; 00190 } 00191 00192 ToolChain *TCEHostInfo::CreateToolChain(const ArgList &Args, 00193 const char *ArchName) const { 00194 llvm::Triple TCTriple(getTriple()); 00195 // TCTriple.setArchName(ArchName); 00196 return new toolchains::TCEToolChain(*this, TCTriple); 00197 } 00198 00199 00200 // Unknown Host Info 00201 00202 /// UnknownHostInfo - Generic host information to use for unknown hosts. 00203 class UnknownHostInfo : public HostInfo { 00204 /// Cache of tool chains we have created. 00205 mutable llvm::StringMap<ToolChain*> ToolChains; 00206 00207 public: 00208 UnknownHostInfo(const Driver &D, const llvm::Triple& Triple); 00209 ~UnknownHostInfo(); 00210 00211 virtual bool useDriverDriver() const; 00212 00213 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00214 return types::lookupTypeForExtension(Ext); 00215 } 00216 00217 virtual ToolChain *CreateToolChain(const ArgList &Args, 00218 const char *ArchName) const; 00219 }; 00220 00221 UnknownHostInfo::UnknownHostInfo(const Driver &D, const llvm::Triple& Triple) 00222 : HostInfo(D, Triple) { 00223 } 00224 00225 UnknownHostInfo::~UnknownHostInfo() { 00226 for (llvm::StringMap<ToolChain*>::iterator 00227 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00228 delete it->second; 00229 } 00230 00231 bool UnknownHostInfo::useDriverDriver() const { 00232 return false; 00233 } 00234 00235 ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args, 00236 const char *ArchName) const { 00237 assert(!ArchName && 00238 "Unexpected arch name on platform without driver driver support."); 00239 00240 // Automatically handle some instances of -m32/-m64 we know about. 00241 std::string Arch = getArchName(); 00242 ArchName = Arch.c_str(); 00243 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { 00244 if (Triple.getArch() == llvm::Triple::x86 || 00245 Triple.getArch() == llvm::Triple::x86_64) { 00246 ArchName = 00247 (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; 00248 } else if (Triple.getArch() == llvm::Triple::ppc || 00249 Triple.getArch() == llvm::Triple::ppc64) { 00250 ArchName = 00251 (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; 00252 } 00253 } 00254 00255 ToolChain *&TC = ToolChains[ArchName]; 00256 if (!TC) { 00257 llvm::Triple TCTriple(getTriple()); 00258 TCTriple.setArchName(ArchName); 00259 00260 TC = new toolchains::Generic_GCC(*this, TCTriple); 00261 } 00262 00263 return TC; 00264 } 00265 00266 // OpenBSD Host Info 00267 00268 /// OpenBSDHostInfo - OpenBSD host information implementation. 00269 class OpenBSDHostInfo : public HostInfo { 00270 /// Cache of tool chains we have created. 00271 mutable llvm::StringMap<ToolChain*> ToolChains; 00272 00273 public: 00274 OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple) 00275 : HostInfo(D, Triple) {} 00276 ~OpenBSDHostInfo(); 00277 00278 virtual bool useDriverDriver() const; 00279 00280 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00281 return types::lookupTypeForExtension(Ext); 00282 } 00283 00284 virtual ToolChain *CreateToolChain(const ArgList &Args, 00285 const char *ArchName) const; 00286 }; 00287 00288 OpenBSDHostInfo::~OpenBSDHostInfo() { 00289 for (llvm::StringMap<ToolChain*>::iterator 00290 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00291 delete it->second; 00292 } 00293 00294 bool OpenBSDHostInfo::useDriverDriver() const { 00295 return false; 00296 } 00297 00298 ToolChain *OpenBSDHostInfo::CreateToolChain(const ArgList &Args, 00299 const char *ArchName) const { 00300 assert(!ArchName && 00301 "Unexpected arch name on platform without driver driver support."); 00302 00303 std::string Arch = getArchName(); 00304 ArchName = Arch.c_str(); 00305 00306 ToolChain *&TC = ToolChains[ArchName]; 00307 if (!TC) { 00308 llvm::Triple TCTriple(getTriple()); 00309 TCTriple.setArchName(ArchName); 00310 00311 TC = new toolchains::OpenBSD(*this, TCTriple); 00312 } 00313 00314 return TC; 00315 } 00316 00317 // AuroraUX Host Info 00318 00319 /// AuroraUXHostInfo - AuroraUX host information implementation. 00320 class AuroraUXHostInfo : public HostInfo { 00321 /// Cache of tool chains we have created. 00322 mutable llvm::StringMap<ToolChain*> ToolChains; 00323 00324 public: 00325 AuroraUXHostInfo(const Driver &D, const llvm::Triple& Triple) 00326 : HostInfo(D, Triple) {} 00327 ~AuroraUXHostInfo(); 00328 00329 virtual bool useDriverDriver() const; 00330 00331 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00332 return types::lookupTypeForExtension(Ext); 00333 } 00334 00335 virtual ToolChain *CreateToolChain(const ArgList &Args, 00336 const char *ArchName) const; 00337 }; 00338 00339 AuroraUXHostInfo::~AuroraUXHostInfo() { 00340 for (llvm::StringMap<ToolChain*>::iterator 00341 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00342 delete it->second; 00343 } 00344 00345 bool AuroraUXHostInfo::useDriverDriver() const { 00346 return false; 00347 } 00348 00349 ToolChain *AuroraUXHostInfo::CreateToolChain(const ArgList &Args, 00350 const char *ArchName) const { 00351 assert(!ArchName && 00352 "Unexpected arch name on platform without driver driver support."); 00353 00354 ToolChain *&TC = ToolChains[getArchName()]; 00355 00356 if (!TC) { 00357 llvm::Triple TCTriple(getTriple()); 00358 TCTriple.setArchName(getArchName()); 00359 00360 TC = new toolchains::AuroraUX(*this, TCTriple); 00361 } 00362 00363 return TC; 00364 } 00365 00366 // FreeBSD Host Info 00367 00368 /// FreeBSDHostInfo - FreeBSD host information implementation. 00369 class FreeBSDHostInfo : public HostInfo { 00370 /// Cache of tool chains we have created. 00371 mutable llvm::StringMap<ToolChain*> ToolChains; 00372 00373 public: 00374 FreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple) 00375 : HostInfo(D, Triple) {} 00376 ~FreeBSDHostInfo(); 00377 00378 virtual bool useDriverDriver() const; 00379 00380 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00381 return types::lookupTypeForExtension(Ext); 00382 } 00383 00384 virtual ToolChain *CreateToolChain(const ArgList &Args, 00385 const char *ArchName) const; 00386 }; 00387 00388 FreeBSDHostInfo::~FreeBSDHostInfo() { 00389 for (llvm::StringMap<ToolChain*>::iterator 00390 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00391 delete it->second; 00392 } 00393 00394 bool FreeBSDHostInfo::useDriverDriver() const { 00395 return false; 00396 } 00397 00398 ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args, 00399 const char *ArchName) const { 00400 bool Lib32 = false; 00401 00402 assert(!ArchName && 00403 "Unexpected arch name on platform without driver driver support."); 00404 00405 // On x86_64 we need to be able to compile 32-bits binaries as well. 00406 // Compiling 64-bit binaries on i386 is not supported. We don't have a 00407 // lib64. 00408 std::string Arch = getArchName(); 00409 ArchName = Arch.c_str(); 00410 if (Args.hasArg(options::OPT_m32) && getArchName() == "x86_64") { 00411 ArchName = "i386"; 00412 Lib32 = true; 00413 } 00414 00415 ToolChain *&TC = ToolChains[ArchName]; 00416 if (!TC) { 00417 llvm::Triple TCTriple(getTriple()); 00418 TCTriple.setArchName(ArchName); 00419 00420 TC = new toolchains::FreeBSD(*this, TCTriple, Lib32); 00421 } 00422 00423 return TC; 00424 } 00425 00426 // DragonFly Host Info 00427 00428 /// DragonFlyHostInfo - DragonFly host information implementation. 00429 class DragonFlyHostInfo : public HostInfo { 00430 /// Cache of tool chains we have created. 00431 mutable llvm::StringMap<ToolChain*> ToolChains; 00432 00433 public: 00434 DragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple) 00435 : HostInfo(D, Triple) {} 00436 ~DragonFlyHostInfo(); 00437 00438 virtual bool useDriverDriver() const; 00439 00440 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00441 return types::lookupTypeForExtension(Ext); 00442 } 00443 00444 virtual ToolChain *CreateToolChain(const ArgList &Args, 00445 const char *ArchName) const; 00446 }; 00447 00448 DragonFlyHostInfo::~DragonFlyHostInfo() { 00449 for (llvm::StringMap<ToolChain*>::iterator 00450 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00451 delete it->second; 00452 } 00453 00454 bool DragonFlyHostInfo::useDriverDriver() const { 00455 return false; 00456 } 00457 00458 ToolChain *DragonFlyHostInfo::CreateToolChain(const ArgList &Args, 00459 const char *ArchName) const { 00460 assert(!ArchName && 00461 "Unexpected arch name on platform without driver driver support."); 00462 00463 ToolChain *&TC = ToolChains[getArchName()]; 00464 00465 if (!TC) { 00466 llvm::Triple TCTriple(getTriple()); 00467 TCTriple.setArchName(getArchName()); 00468 00469 TC = new toolchains::DragonFly(*this, TCTriple); 00470 } 00471 00472 return TC; 00473 } 00474 00475 // Linux Host Info 00476 00477 /// LinuxHostInfo - Linux host information implementation. 00478 class LinuxHostInfo : public HostInfo { 00479 /// Cache of tool chains we have created. 00480 mutable llvm::StringMap<ToolChain*> ToolChains; 00481 00482 public: 00483 LinuxHostInfo(const Driver &D, const llvm::Triple& Triple) 00484 : HostInfo(D, Triple) {} 00485 ~LinuxHostInfo(); 00486 00487 virtual bool useDriverDriver() const; 00488 00489 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00490 return types::lookupTypeForExtension(Ext); 00491 } 00492 00493 virtual ToolChain *CreateToolChain(const ArgList &Args, 00494 const char *ArchName) const; 00495 }; 00496 00497 LinuxHostInfo::~LinuxHostInfo() { 00498 for (llvm::StringMap<ToolChain*>::iterator 00499 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00500 delete it->second; 00501 } 00502 00503 bool LinuxHostInfo::useDriverDriver() const { 00504 return false; 00505 } 00506 00507 ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args, 00508 const char *ArchName) const { 00509 00510 assert(!ArchName && 00511 "Unexpected arch name on platform without driver driver support."); 00512 00513 // Automatically handle some instances of -m32/-m64 we know about. 00514 std::string Arch = getArchName(); 00515 ArchName = Arch.c_str(); 00516 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { 00517 if (Triple.getArch() == llvm::Triple::x86 || 00518 Triple.getArch() == llvm::Triple::x86_64) { 00519 ArchName = 00520 (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; 00521 } else if (Triple.getArch() == llvm::Triple::ppc || 00522 Triple.getArch() == llvm::Triple::ppc64) { 00523 ArchName = 00524 (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; 00525 } 00526 } 00527 00528 ToolChain *&TC = ToolChains[ArchName]; 00529 00530 if (!TC) { 00531 llvm::Triple TCTriple(getTriple()); 00532 TCTriple.setArchName(ArchName); 00533 00534 TC = new toolchains::Linux(*this, TCTriple); 00535 } 00536 00537 return TC; 00538 } 00539 00540 } 00541 00542 const HostInfo * 00543 clang::driver::createAuroraUXHostInfo(const Driver &D, 00544 const llvm::Triple& Triple){ 00545 return new AuroraUXHostInfo(D, Triple); 00546 } 00547 00548 const HostInfo * 00549 clang::driver::createDarwinHostInfo(const Driver &D, 00550 const llvm::Triple& Triple){ 00551 return new DarwinHostInfo(D, Triple); 00552 } 00553 00554 const HostInfo * 00555 clang::driver::createOpenBSDHostInfo(const Driver &D, 00556 const llvm::Triple& Triple) { 00557 return new OpenBSDHostInfo(D, Triple); 00558 } 00559 00560 const HostInfo * 00561 clang::driver::createFreeBSDHostInfo(const Driver &D, 00562 const llvm::Triple& Triple) { 00563 return new FreeBSDHostInfo(D, Triple); 00564 } 00565 00566 const HostInfo * 00567 clang::driver::createDragonFlyHostInfo(const Driver &D, 00568 const llvm::Triple& Triple) { 00569 return new DragonFlyHostInfo(D, Triple); 00570 } 00571 00572 const HostInfo * 00573 clang::driver::createLinuxHostInfo(const Driver &D, 00574 const llvm::Triple& Triple) { 00575 return new LinuxHostInfo(D, Triple); 00576 } 00577 00578 const HostInfo * 00579 clang::driver::createTCEHostInfo(const Driver &D, 00580 const llvm::Triple& Triple) { 00581 return new TCEHostInfo(D, Triple); 00582 } 00583 00584 const HostInfo * 00585 clang::driver::createUnknownHostInfo(const Driver &D, 00586 const llvm::Triple& Triple) { 00587 return new UnknownHostInfo(D, Triple); 00588 }