//===--- HostInfo.cpp - Host specific information -------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "clang/Driver/HostInfo.h" #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Option.h" #include "clang/Driver/Options.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Compiler.h" #include "ToolChains.h" #include <cassert> using namespace clang::driver; HostInfo::HostInfo(const Driver &D, const llvm::Triple &_Triple) : TheDriver(D), Triple(_Triple) { } HostInfo::~HostInfo() { } namespace { // Darwin Host Info /// DarwinHostInfo - Darwin host information implementation. class DarwinHostInfo : public HostInfo { /// Cache of tool chains we have created. mutable llvm::DenseMap<unsigned, ToolChain*> ToolChains; public: DarwinHostInfo(const Driver &D, const llvm::Triple &Triple); ~DarwinHostInfo(); virtual bool useDriverDriver() const; virtual ToolChain *CreateToolChain(const ArgList &Args, const char *ArchName) const; }; DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple) : HostInfo(D, Triple) { } DarwinHostInfo::~DarwinHostInfo() { for (llvm::DenseMap<unsigned, ToolChain*>::iterator it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) delete it->second; } bool DarwinHostInfo::useDriverDriver() const { return true; } ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { llvm::Triple::ArchType Arch; if (!ArchName) { // If we aren't looking for a specific arch, infer the default architecture // based on -arch and -m32/-m64 command line options. if (Arg *A = Args.getLastArg(options::OPT_arch)) { // The gcc driver behavior with multiple -arch flags wasn't consistent for // things which rely on a default architecture. We just use the last -arch // to find the default tool chain (assuming it is valid). Arch = llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args)); // If it was invalid just use the host, we will reject this command line // later. if (Arch == llvm::Triple::UnknownArch) Arch = getTriple().getArch(); } else { // Otherwise default to the arch of the host. Arch = getTriple().getArch(); } // Honor -m32 and -m64 when finding the default tool chain. // // FIXME: Should this information be in llvm::Triple? if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { if (A->getOption().matches(options::OPT_m32)) { if (Arch == llvm::Triple::x86_64) Arch = llvm::Triple::x86; if (Arch == llvm::Triple::ppc64) Arch = llvm::Triple::ppc; } else { if (Arch == llvm::Triple::x86) Arch = llvm::Triple::x86_64; if (Arch == llvm::Triple::ppc) Arch = llvm::Triple::ppc64; } } } else Arch = llvm::Triple::getArchTypeForDarwinArchName(ArchName); assert(Arch != llvm::Triple::UnknownArch && "Unexpected arch!"); ToolChain *&TC = ToolChains[Arch]; if (!TC) { llvm::Triple TCTriple(getTriple()); TCTriple.setArch(Arch); // If we recognized the arch, match it to the toolchains we support. if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) { TC = new toolchains::DarwinClang(*this, TCTriple); } else TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple); } return TC; } // TCE Host Info /// TCEHostInfo - TCE host information implementation (see http://tce.cs.tut.fi) class TCEHostInfo : public HostInfo { public: TCEHostInfo(const Driver &D, const llvm::Triple &Triple); ~TCEHostInfo() {} virtual bool useDriverDriver() const; virtual ToolChain *CreateToolChain(const ArgList &Args, const char *ArchName) const; }; TCEHostInfo::TCEHostInfo(const Driver &D, const llvm::Triple& Triple) : HostInfo(D, Triple) { } bool TCEHostInfo::useDriverDriver() const { return false; } ToolChain *TCEHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { llvm::Triple TCTriple(getTriple()); // TCTriple.setArchName(ArchName); return new toolchains::TCEToolChain(*this, TCTriple); } // Unknown Host Info /// UnknownHostInfo - Generic host information to use for unknown hosts. class UnknownHostInfo : public HostInfo { /// Cache of tool chains we have created. mutable llvm::StringMap<ToolChain*> ToolChains; public: UnknownHostInfo(const Driver &D, const llvm::Triple& Triple); ~UnknownHostInfo(); virtual bool useDriverDriver() const; virtual ToolChain *CreateToolChain(const ArgList &Args, const char *ArchName) const; }; UnknownHostInfo::UnknownHostInfo(const Driver &D, const llvm::Triple& Triple) : HostInfo(D, Triple) { } UnknownHostInfo::~UnknownHostInfo() { for (llvm::StringMap<ToolChain*>::iterator it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) delete it->second; } bool UnknownHostInfo::useDriverDriver() const { return false; } ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { assert(!ArchName && "Unexpected arch name on platform without driver driver support."); // Automatically handle some instances of -m32/-m64 we know about. std::string Arch = getArchName(); ArchName = Arch.c_str(); if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { if (Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::x86_64) { ArchName = (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; } else if (Triple.getArch() == llvm::Triple::ppc || Triple.getArch() == llvm::Triple::ppc64) { ArchName = (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; } } ToolChain *&TC = ToolChains[ArchName]; if (!TC) { llvm::Triple TCTriple(getTriple()); TCTriple.setArchName(ArchName); TC = new toolchains::Generic_GCC(*this, TCTriple); } return TC; } // OpenBSD Host Info /// OpenBSDHostInfo - OpenBSD host information implementation. class OpenBSDHostInfo : public HostInfo { /// Cache of tool chains we have created. mutable llvm::StringMap<ToolChain*> ToolChains; public: OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple) : HostInfo(D, Triple) {} ~OpenBSDHostInfo(); virtual bool useDriverDriver() const; virtual ToolChain *CreateToolChain(const ArgList &Args, const char *ArchName) const; }; OpenBSDHostInfo::~OpenBSDHostInfo() { for (llvm::StringMap<ToolChain*>::iterator it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) delete it->second; } bool OpenBSDHostInfo::useDriverDriver() const { return false; } ToolChain *OpenBSDHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { assert(!ArchName && "Unexpected arch name on platform without driver driver support."); std::string Arch = getArchName(); ArchName = Arch.c_str(); ToolChain *&TC = ToolChains[ArchName]; if (!TC) { llvm::Triple TCTriple(getTriple()); TCTriple.setArchName(ArchName); TC = new toolchains::OpenBSD(*this, TCTriple); } return TC; } // AuroraUX Host Info /// AuroraUXHostInfo - AuroraUX host information implementation. class AuroraUXHostInfo : public HostInfo { /// Cache of tool chains we have created. mutable llvm::StringMap<ToolChain*> ToolChains; public: AuroraUXHostInfo(const Driver &D, const llvm::Triple& Triple) : HostInfo(D, Triple) {} ~AuroraUXHostInfo(); virtual bool useDriverDriver() const; virtual ToolChain *CreateToolChain(const ArgList &Args, const char *ArchName) const; }; AuroraUXHostInfo::~AuroraUXHostInfo() { for (llvm::StringMap<ToolChain*>::iterator it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) delete it->second; } bool AuroraUXHostInfo::useDriverDriver() const { return false; } ToolChain *AuroraUXHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { assert(!ArchName && "Unexpected arch name on platform without driver driver support."); ToolChain *&TC = ToolChains[getArchName()]; if (!TC) { llvm::Triple TCTriple(getTriple()); TCTriple.setArchName(getArchName()); TC = new toolchains::AuroraUX(*this, TCTriple); } return TC; } // FreeBSD Host Info /// FreeBSDHostInfo - FreeBSD host information implementation. class FreeBSDHostInfo : public HostInfo { /// Cache of tool chains we have created. mutable llvm::StringMap<ToolChain*> ToolChains; public: FreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple) : HostInfo(D, Triple) {} ~FreeBSDHostInfo(); virtual bool useDriverDriver() const; virtual ToolChain *CreateToolChain(const ArgList &Args, const char *ArchName) const; }; FreeBSDHostInfo::~FreeBSDHostInfo() { for (llvm::StringMap<ToolChain*>::iterator it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) delete it->second; } bool FreeBSDHostInfo::useDriverDriver() const { return false; } ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { assert(!ArchName && "Unexpected arch name on platform without driver driver support."); // Automatically handle some instances of -m32/-m64 we know about. std::string Arch = getArchName(); ArchName = Arch.c_str(); if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { if (Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::x86_64) { ArchName = (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; } else if (Triple.getArch() == llvm::Triple::ppc || Triple.getArch() == llvm::Triple::ppc64) { ArchName = (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; } } ToolChain *&TC = ToolChains[ArchName]; if (!TC) { llvm::Triple TCTriple(getTriple()); TCTriple.setArchName(ArchName); TC = new toolchains::FreeBSD(*this, TCTriple); } return TC; } // NetBSD Host Info /// NetBSDHostInfo - NetBSD host information implementation. class NetBSDHostInfo : public HostInfo { /// Cache of tool chains we have created. mutable llvm::StringMap<ToolChain*> ToolChains; public: NetBSDHostInfo(const Driver &D, const llvm::Triple& Triple) : HostInfo(D, Triple) {} ~NetBSDHostInfo(); virtual bool useDriverDriver() const; virtual ToolChain *CreateToolChain(const ArgList &Args, const char *ArchName) const; }; NetBSDHostInfo::~NetBSDHostInfo() { for (llvm::StringMap<ToolChain*>::iterator it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) delete it->second; } bool NetBSDHostInfo::useDriverDriver() const { return false; } ToolChain *NetBSDHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { assert(!ArchName && "Unexpected arch name on platform without driver driver support."); // Automatically handle some instances of -m32/-m64 we know about. std::string Arch = getArchName(); ArchName = Arch.c_str(); if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { if (Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::x86_64) { ArchName = (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; } else if (Triple.getArch() == llvm::Triple::ppc || Triple.getArch() == llvm::Triple::ppc64) { ArchName = (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; } } llvm::Triple TargetTriple(getTriple()); TargetTriple.setArchName(ArchName); ToolChain *TC; // XXX Cache toolchain even if -m32 is used if (Arch == ArchName) { TC = ToolChains[ArchName]; if (TC) return TC; } TC = new toolchains::NetBSD(*this, TargetTriple, getTriple()); return TC; } // Minix Host Info /// MinixHostInfo - Minix host information implementation. class MinixHostInfo : public HostInfo { /// Cache of tool chains we have created. mutable llvm::StringMap<ToolChain*> ToolChains; public: MinixHostInfo(const Driver &D, const llvm::Triple& Triple) : HostInfo(D, Triple) {} ~MinixHostInfo(); virtual bool useDriverDriver() const; virtual ToolChain *CreateToolChain(const ArgList &Args, const char *ArchName) const; }; MinixHostInfo::~MinixHostInfo() { for (llvm::StringMap<ToolChain*>::iterator it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it){ delete it->second; } } bool MinixHostInfo::useDriverDriver() const { return false; } ToolChain *MinixHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { assert(!ArchName && "Unexpected arch name on platform without driver driver support."); std::string Arch = getArchName(); ArchName = Arch.c_str(); ToolChain *&TC = ToolChains[ArchName]; if (!TC) { llvm::Triple TCTriple(getTriple()); TCTriple.setArchName(ArchName); TC = new toolchains::Minix(*this, TCTriple); } return TC; } // DragonFly Host Info /// DragonFlyHostInfo - DragonFly host information implementation. class DragonFlyHostInfo : public HostInfo { /// Cache of tool chains we have created. mutable llvm::StringMap<ToolChain*> ToolChains; public: DragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple) : HostInfo(D, Triple) {} ~DragonFlyHostInfo(); virtual bool useDriverDriver() const; virtual ToolChain *CreateToolChain(const ArgList &Args, const char *ArchName) const; }; DragonFlyHostInfo::~DragonFlyHostInfo() { for (llvm::StringMap<ToolChain*>::iterator it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) delete it->second; } bool DragonFlyHostInfo::useDriverDriver() const { return false; } ToolChain *DragonFlyHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { assert(!ArchName && "Unexpected arch name on platform without driver driver support."); ToolChain *&TC = ToolChains[getArchName()]; if (!TC) { llvm::Triple TCTriple(getTriple()); TCTriple.setArchName(getArchName()); TC = new toolchains::DragonFly(*this, TCTriple); } return TC; } // Linux Host Info /// LinuxHostInfo - Linux host information implementation. class LinuxHostInfo : public HostInfo { /// Cache of tool chains we have created. mutable llvm::StringMap<ToolChain*> ToolChains; public: LinuxHostInfo(const Driver &D, const llvm::Triple& Triple) : HostInfo(D, Triple) {} ~LinuxHostInfo(); virtual bool useDriverDriver() const; virtual ToolChain *CreateToolChain(const ArgList &Args, const char *ArchName) const; }; LinuxHostInfo::~LinuxHostInfo() { for (llvm::StringMap<ToolChain*>::iterator it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) delete it->second; } bool LinuxHostInfo::useDriverDriver() const { return false; } ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { assert(!ArchName && "Unexpected arch name on platform without driver driver support."); // Automatically handle some instances of -m32/-m64 we know about. std::string Arch = getArchName(); ArchName = Arch.c_str(); if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { if (Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::x86_64) { ArchName = (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; } else if (Triple.getArch() == llvm::Triple::ppc || Triple.getArch() == llvm::Triple::ppc64) { ArchName = (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; } } ToolChain *&TC = ToolChains[ArchName]; if (!TC) { llvm::Triple TCTriple(getTriple()); TCTriple.setArchName(ArchName); TC = new toolchains::Linux(*this, TCTriple); } return TC; } // Windows Host Info /// WindowsHostInfo - Host information to use on Microsoft Windows. class WindowsHostInfo : public HostInfo { /// Cache of tool chains we have created. mutable llvm::StringMap<ToolChain*> ToolChains; public: WindowsHostInfo(const Driver &D, const llvm::Triple& Triple); ~WindowsHostInfo(); virtual bool useDriverDriver() const; virtual types::ID lookupTypeForExtension(const char *Ext) const { return types::lookupTypeForExtension(Ext); } virtual ToolChain *CreateToolChain(const ArgList &Args, const char *ArchName) const; }; WindowsHostInfo::WindowsHostInfo(const Driver &D, const llvm::Triple& Triple) : HostInfo(D, Triple) { } WindowsHostInfo::~WindowsHostInfo() { for (llvm::StringMap<ToolChain*>::iterator it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) delete it->second; } bool WindowsHostInfo::useDriverDriver() const { return false; } ToolChain *WindowsHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { assert(!ArchName && "Unexpected arch name on platform without driver driver support."); // Automatically handle some instances of -m32/-m64 we know about. std::string Arch = getArchName(); ArchName = Arch.c_str(); if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { if (Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::x86_64) { ArchName = (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; } } ToolChain *&TC = ToolChains[ArchName]; if (!TC) { llvm::Triple TCTriple(getTriple()); TCTriple.setArchName(ArchName); TC = new toolchains::Windows(*this, TCTriple); } return TC; } // FIXME: This is a placeholder. class MinGWHostInfo : public UnknownHostInfo { public: MinGWHostInfo(const Driver &D, const llvm::Triple& Triple); }; MinGWHostInfo::MinGWHostInfo(const Driver &D, const llvm::Triple& Triple) : UnknownHostInfo(D, Triple) {} } // end anon namespace const HostInfo * clang::driver::createAuroraUXHostInfo(const Driver &D, const llvm::Triple& Triple){ return new AuroraUXHostInfo(D, Triple); } const HostInfo * clang::driver::createDarwinHostInfo(const Driver &D, const llvm::Triple& Triple){ return new DarwinHostInfo(D, Triple); } const HostInfo * clang::driver::createOpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple) { return new OpenBSDHostInfo(D, Triple); } const HostInfo * clang::driver::createFreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple) { return new FreeBSDHostInfo(D, Triple); } const HostInfo * clang::driver::createNetBSDHostInfo(const Driver &D, const llvm::Triple& Triple) { return new NetBSDHostInfo(D, Triple); } const HostInfo * clang::driver::createMinixHostInfo(const Driver &D, const llvm::Triple& Triple) { return new MinixHostInfo(D, Triple); } const HostInfo * clang::driver::createDragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple) { return new DragonFlyHostInfo(D, Triple); } const HostInfo * clang::driver::createLinuxHostInfo(const Driver &D, const llvm::Triple& Triple) { return new LinuxHostInfo(D, Triple); } const HostInfo * clang::driver::createTCEHostInfo(const Driver &D, const llvm::Triple& Triple) { return new TCEHostInfo(D, Triple); } const HostInfo * clang::driver::createWindowsHostInfo(const Driver &D, const llvm::Triple& Triple) { return new WindowsHostInfo(D, Triple); } const HostInfo * clang::driver::createMinGWHostInfo(const Driver &D, const llvm::Triple& Triple) { return new MinGWHostInfo(D, Triple); } const HostInfo * clang::driver::createUnknownHostInfo(const Driver &D, const llvm::Triple& Triple) { return new UnknownHostInfo(D, Triple); }