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     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 }