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 const char *UseNewToolChain = ::getenv("CCC_ENABLE_NEW_DARWIN_TOOLCHAIN"); 00148 if (UseNewToolChain || 00149 Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) { 00150 TC = new toolchains::DarwinClang(*this, TCTriple, DarwinVersion); 00151 } else if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) { 00152 // We still use the legacy DarwinGCC toolchain on X86. 00153 TC = new toolchains::DarwinGCC(*this, TCTriple, DarwinVersion, 00154 GCCVersion); 00155 } else 00156 TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple); 00157 } 00158 00159 return TC; 00160 } 00161 00162 // TCE Host Info 00163 00164 /// TCEHostInfo - TCE host information implementation (see http://tce.cs.tut.fi) 00165 class TCEHostInfo : public HostInfo { 00166 00167 public: 00168 TCEHostInfo(const Driver &D, const llvm::Triple &Triple); 00169 ~TCEHostInfo() {} 00170 00171 virtual bool useDriverDriver() const; 00172 00173 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00174 types::ID Ty = types::lookupTypeForExtension(Ext); 00175 00176 if (Ty == types::TY_PP_Asm) 00177 return types::TY_Asm; 00178 00179 return Ty; 00180 } 00181 00182 virtual ToolChain *CreateToolChain(const ArgList &Args, 00183 const char *ArchName) const; 00184 }; 00185 00186 TCEHostInfo::TCEHostInfo(const Driver &D, const llvm::Triple& Triple) 00187 : HostInfo(D, Triple) { 00188 } 00189 00190 bool TCEHostInfo::useDriverDriver() const { 00191 return false; 00192 } 00193 00194 ToolChain *TCEHostInfo::CreateToolChain(const ArgList &Args, 00195 const char *ArchName) const { 00196 llvm::Triple TCTriple(getTriple()); 00197 // TCTriple.setArchName(ArchName); 00198 return new toolchains::TCEToolChain(*this, TCTriple); 00199 } 00200 00201 00202 // Unknown Host Info 00203 00204 /// UnknownHostInfo - Generic host information to use for unknown hosts. 00205 class UnknownHostInfo : public HostInfo { 00206 /// Cache of tool chains we have created. 00207 mutable llvm::StringMap<ToolChain*> ToolChains; 00208 00209 public: 00210 UnknownHostInfo(const Driver &D, const llvm::Triple& Triple); 00211 ~UnknownHostInfo(); 00212 00213 virtual bool useDriverDriver() const; 00214 00215 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00216 return types::lookupTypeForExtension(Ext); 00217 } 00218 00219 virtual ToolChain *CreateToolChain(const ArgList &Args, 00220 const char *ArchName) const; 00221 }; 00222 00223 UnknownHostInfo::UnknownHostInfo(const Driver &D, const llvm::Triple& Triple) 00224 : HostInfo(D, Triple) { 00225 } 00226 00227 UnknownHostInfo::~UnknownHostInfo() { 00228 for (llvm::StringMap<ToolChain*>::iterator 00229 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00230 delete it->second; 00231 } 00232 00233 bool UnknownHostInfo::useDriverDriver() const { 00234 return false; 00235 } 00236 00237 ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args, 00238 const char *ArchName) const { 00239 assert(!ArchName && 00240 "Unexpected arch name on platform without driver driver support."); 00241 00242 // Automatically handle some instances of -m32/-m64 we know about. 00243 std::string Arch = getArchName(); 00244 ArchName = Arch.c_str(); 00245 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { 00246 if (Triple.getArch() == llvm::Triple::x86 || 00247 Triple.getArch() == llvm::Triple::x86_64) { 00248 ArchName = 00249 (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; 00250 } else if (Triple.getArch() == llvm::Triple::ppc || 00251 Triple.getArch() == llvm::Triple::ppc64) { 00252 ArchName = 00253 (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; 00254 } 00255 } 00256 00257 ToolChain *&TC = ToolChains[ArchName]; 00258 if (!TC) { 00259 llvm::Triple TCTriple(getTriple()); 00260 TCTriple.setArchName(ArchName); 00261 00262 TC = new toolchains::Generic_GCC(*this, TCTriple); 00263 } 00264 00265 return TC; 00266 } 00267 00268 // OpenBSD Host Info 00269 00270 /// OpenBSDHostInfo - OpenBSD host information implementation. 00271 class OpenBSDHostInfo : public HostInfo { 00272 /// Cache of tool chains we have created. 00273 mutable llvm::StringMap<ToolChain*> ToolChains; 00274 00275 public: 00276 OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple) 00277 : HostInfo(D, Triple) {} 00278 ~OpenBSDHostInfo(); 00279 00280 virtual bool useDriverDriver() const; 00281 00282 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00283 return types::lookupTypeForExtension(Ext); 00284 } 00285 00286 virtual ToolChain *CreateToolChain(const ArgList &Args, 00287 const char *ArchName) const; 00288 }; 00289 00290 OpenBSDHostInfo::~OpenBSDHostInfo() { 00291 for (llvm::StringMap<ToolChain*>::iterator 00292 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00293 delete it->second; 00294 } 00295 00296 bool OpenBSDHostInfo::useDriverDriver() const { 00297 return false; 00298 } 00299 00300 ToolChain *OpenBSDHostInfo::CreateToolChain(const ArgList &Args, 00301 const char *ArchName) const { 00302 assert(!ArchName && 00303 "Unexpected arch name on platform without driver driver support."); 00304 00305 std::string Arch = getArchName(); 00306 ArchName = Arch.c_str(); 00307 00308 ToolChain *&TC = ToolChains[ArchName]; 00309 if (!TC) { 00310 llvm::Triple TCTriple(getTriple()); 00311 TCTriple.setArchName(ArchName); 00312 00313 TC = new toolchains::OpenBSD(*this, TCTriple); 00314 } 00315 00316 return TC; 00317 } 00318 00319 // AuroraUX Host Info 00320 00321 /// AuroraUXHostInfo - AuroraUX host information implementation. 00322 class AuroraUXHostInfo : public HostInfo { 00323 /// Cache of tool chains we have created. 00324 mutable llvm::StringMap<ToolChain*> ToolChains; 00325 00326 public: 00327 AuroraUXHostInfo(const Driver &D, const llvm::Triple& Triple) 00328 : HostInfo(D, Triple) {} 00329 ~AuroraUXHostInfo(); 00330 00331 virtual bool useDriverDriver() const; 00332 00333 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00334 return types::lookupTypeForExtension(Ext); 00335 } 00336 00337 virtual ToolChain *CreateToolChain(const ArgList &Args, 00338 const char *ArchName) const; 00339 }; 00340 00341 AuroraUXHostInfo::~AuroraUXHostInfo() { 00342 for (llvm::StringMap<ToolChain*>::iterator 00343 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00344 delete it->second; 00345 } 00346 00347 bool AuroraUXHostInfo::useDriverDriver() const { 00348 return false; 00349 } 00350 00351 ToolChain *AuroraUXHostInfo::CreateToolChain(const ArgList &Args, 00352 const char *ArchName) const { 00353 assert(!ArchName && 00354 "Unexpected arch name on platform without driver driver support."); 00355 00356 ToolChain *&TC = ToolChains[getArchName()]; 00357 00358 if (!TC) { 00359 llvm::Triple TCTriple(getTriple()); 00360 TCTriple.setArchName(getArchName()); 00361 00362 TC = new toolchains::AuroraUX(*this, TCTriple); 00363 } 00364 00365 return TC; 00366 } 00367 00368 // FreeBSD Host Info 00369 00370 /// FreeBSDHostInfo - FreeBSD host information implementation. 00371 class FreeBSDHostInfo : public HostInfo { 00372 /// Cache of tool chains we have created. 00373 mutable llvm::StringMap<ToolChain*> ToolChains; 00374 00375 public: 00376 FreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple) 00377 : HostInfo(D, Triple) {} 00378 ~FreeBSDHostInfo(); 00379 00380 virtual bool useDriverDriver() const; 00381 00382 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00383 return types::lookupTypeForExtension(Ext); 00384 } 00385 00386 virtual ToolChain *CreateToolChain(const ArgList &Args, 00387 const char *ArchName) const; 00388 }; 00389 00390 FreeBSDHostInfo::~FreeBSDHostInfo() { 00391 for (llvm::StringMap<ToolChain*>::iterator 00392 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00393 delete it->second; 00394 } 00395 00396 bool FreeBSDHostInfo::useDriverDriver() const { 00397 return false; 00398 } 00399 00400 ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args, 00401 const char *ArchName) const { 00402 bool Lib32 = false; 00403 00404 assert(!ArchName && 00405 "Unexpected arch name on platform without driver driver support."); 00406 00407 // On x86_64 we need to be able to compile 32-bits binaries as well. 00408 // Compiling 64-bit binaries on i386 is not supported. We don't have a 00409 // lib64. 00410 std::string Arch = getArchName(); 00411 ArchName = Arch.c_str(); 00412 if (Args.hasArg(options::OPT_m32) && getArchName() == "x86_64") { 00413 ArchName = "i386"; 00414 Lib32 = true; 00415 } 00416 00417 ToolChain *&TC = ToolChains[ArchName]; 00418 if (!TC) { 00419 llvm::Triple TCTriple(getTriple()); 00420 TCTriple.setArchName(ArchName); 00421 00422 TC = new toolchains::FreeBSD(*this, TCTriple, Lib32); 00423 } 00424 00425 return TC; 00426 } 00427 00428 // DragonFly Host Info 00429 00430 /// DragonFlyHostInfo - DragonFly host information implementation. 00431 class DragonFlyHostInfo : public HostInfo { 00432 /// Cache of tool chains we have created. 00433 mutable llvm::StringMap<ToolChain*> ToolChains; 00434 00435 public: 00436 DragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple) 00437 : HostInfo(D, Triple) {} 00438 ~DragonFlyHostInfo(); 00439 00440 virtual bool useDriverDriver() const; 00441 00442 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00443 return types::lookupTypeForExtension(Ext); 00444 } 00445 00446 virtual ToolChain *CreateToolChain(const ArgList &Args, 00447 const char *ArchName) const; 00448 }; 00449 00450 DragonFlyHostInfo::~DragonFlyHostInfo() { 00451 for (llvm::StringMap<ToolChain*>::iterator 00452 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00453 delete it->second; 00454 } 00455 00456 bool DragonFlyHostInfo::useDriverDriver() const { 00457 return false; 00458 } 00459 00460 ToolChain *DragonFlyHostInfo::CreateToolChain(const ArgList &Args, 00461 const char *ArchName) const { 00462 assert(!ArchName && 00463 "Unexpected arch name on platform without driver driver support."); 00464 00465 ToolChain *&TC = ToolChains[getArchName()]; 00466 00467 if (!TC) { 00468 llvm::Triple TCTriple(getTriple()); 00469 TCTriple.setArchName(getArchName()); 00470 00471 TC = new toolchains::DragonFly(*this, TCTriple); 00472 } 00473 00474 return TC; 00475 } 00476 00477 // Linux Host Info 00478 00479 /// LinuxHostInfo - Linux host information implementation. 00480 class LinuxHostInfo : public HostInfo { 00481 /// Cache of tool chains we have created. 00482 mutable llvm::StringMap<ToolChain*> ToolChains; 00483 00484 public: 00485 LinuxHostInfo(const Driver &D, const llvm::Triple& Triple) 00486 : HostInfo(D, Triple) {} 00487 ~LinuxHostInfo(); 00488 00489 virtual bool useDriverDriver() const; 00490 00491 virtual types::ID lookupTypeForExtension(const char *Ext) const { 00492 return types::lookupTypeForExtension(Ext); 00493 } 00494 00495 virtual ToolChain *CreateToolChain(const ArgList &Args, 00496 const char *ArchName) const; 00497 }; 00498 00499 LinuxHostInfo::~LinuxHostInfo() { 00500 for (llvm::StringMap<ToolChain*>::iterator 00501 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) 00502 delete it->second; 00503 } 00504 00505 bool LinuxHostInfo::useDriverDriver() const { 00506 return false; 00507 } 00508 00509 ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args, 00510 const char *ArchName) const { 00511 00512 assert(!ArchName && 00513 "Unexpected arch name on platform without driver driver support."); 00514 00515 // Automatically handle some instances of -m32/-m64 we know about. 00516 std::string Arch = getArchName(); 00517 ArchName = Arch.c_str(); 00518 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { 00519 if (Triple.getArch() == llvm::Triple::x86 || 00520 Triple.getArch() == llvm::Triple::x86_64) { 00521 ArchName = 00522 (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; 00523 } else if (Triple.getArch() == llvm::Triple::ppc || 00524 Triple.getArch() == llvm::Triple::ppc64) { 00525 ArchName = 00526 (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; 00527 } 00528 } 00529 00530 ToolChain *&TC = ToolChains[ArchName]; 00531 00532 if (!TC) { 00533 llvm::Triple TCTriple(getTriple()); 00534 TCTriple.setArchName(ArchName); 00535 00536 TC = new toolchains::Linux(*this, TCTriple); 00537 } 00538 00539 return TC; 00540 } 00541 00542 } 00543 00544 const HostInfo * 00545 clang::driver::createAuroraUXHostInfo(const Driver &D, 00546 const llvm::Triple& Triple){ 00547 return new AuroraUXHostInfo(D, Triple); 00548 } 00549 00550 const HostInfo * 00551 clang::driver::createDarwinHostInfo(const Driver &D, 00552 const llvm::Triple& Triple){ 00553 return new DarwinHostInfo(D, Triple); 00554 } 00555 00556 const HostInfo * 00557 clang::driver::createOpenBSDHostInfo(const Driver &D, 00558 const llvm::Triple& Triple) { 00559 return new OpenBSDHostInfo(D, Triple); 00560 } 00561 00562 const HostInfo * 00563 clang::driver::createFreeBSDHostInfo(const Driver &D, 00564 const llvm::Triple& Triple) { 00565 return new FreeBSDHostInfo(D, Triple); 00566 } 00567 00568 const HostInfo * 00569 clang::driver::createDragonFlyHostInfo(const Driver &D, 00570 const llvm::Triple& Triple) { 00571 return new DragonFlyHostInfo(D, Triple); 00572 } 00573 00574 const HostInfo * 00575 clang::driver::createLinuxHostInfo(const Driver &D, 00576 const llvm::Triple& Triple) { 00577 return new LinuxHostInfo(D, Triple); 00578 } 00579 00580 const HostInfo * 00581 clang::driver::createTCEHostInfo(const Driver &D, 00582 const llvm::Triple& Triple) { 00583 return new TCEHostInfo(D, Triple); 00584 } 00585 00586 const HostInfo * 00587 clang::driver::createUnknownHostInfo(const Driver &D, 00588 const llvm::Triple& Triple) { 00589 return new UnknownHostInfo(D, Triple); 00590 }