clang API Documentation

HostInfo.cpp

Go to the documentation of this file.
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 }