| //===--- 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 { |
| /// Darwin version of host. |
| unsigned DarwinVersion[3]; |
| |
| /// GCC version to use on this host. |
| unsigned GCCVersion[3]; |
| |
| /// 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 types::ID lookupTypeForExtension(const char *Ext) const { |
| types::ID Ty = types::lookupTypeForExtension(Ext); |
| |
| // Darwin always preprocesses assembly files (unless -x is used |
| // explicitly). |
| if (Ty == types::TY_PP_Asm) |
| return types::TY_Asm; |
| |
| return Ty; |
| } |
| |
| virtual ToolChain *CreateToolChain(const ArgList &Args, |
| const char *ArchName) const; |
| }; |
| |
| DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple) |
| : HostInfo(D, Triple) { |
| |
| assert(Triple.getArch() != llvm::Triple::UnknownArch && "Invalid arch!"); |
| assert(memcmp(&getOSName()[0], "darwin", 6) == 0 && |
| "Unknown Darwin platform."); |
| bool HadExtra; |
| if (!Driver::GetReleaseVersion(&getOSName()[6], |
| DarwinVersion[0], DarwinVersion[1], |
| DarwinVersion[2], HadExtra)) |
| D.Diag(clang::diag::err_drv_invalid_darwin_version) << getOSName(); |
| |
| // We can only call 4.2.1 for now. |
| GCCVersion[0] = 4; |
| GCCVersion[1] = 2; |
| GCCVersion[2] = 1; |
| } |
| |
| 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. |
| const char *UseNewToolChain = ::getenv("CCC_ENABLE_NEW_DARWIN_TOOLCHAIN"); |
| if (UseNewToolChain || |
| Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) { |
| TC = new toolchains::DarwinClang(*this, TCTriple, DarwinVersion); |
| } else if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) { |
| // We still use the legacy DarwinGCC toolchain on X86. |
| TC = new toolchains::DarwinGCC(*this, TCTriple, DarwinVersion, |
| GCCVersion); |
| } 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 types::ID lookupTypeForExtension(const char *Ext) const { |
| types::ID Ty = types::lookupTypeForExtension(Ext); |
| |
| if (Ty == types::TY_PP_Asm) |
| return types::TY_Asm; |
| |
| return Ty; |
| } |
| |
| 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 types::ID lookupTypeForExtension(const char *Ext) const { |
| return types::lookupTypeForExtension(Ext); |
| } |
| |
| 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 types::ID lookupTypeForExtension(const char *Ext) const { |
| return types::lookupTypeForExtension(Ext); |
| } |
| |
| 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 types::ID lookupTypeForExtension(const char *Ext) const { |
| return types::lookupTypeForExtension(Ext); |
| } |
| |
| 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 types::ID lookupTypeForExtension(const char *Ext) const { |
| return types::lookupTypeForExtension(Ext); |
| } |
| |
| 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 { |
| bool Lib32 = false; |
| |
| assert(!ArchName && |
| "Unexpected arch name on platform without driver driver support."); |
| |
| // On x86_64 we need to be able to compile 32-bits binaries as well. |
| // Compiling 64-bit binaries on i386 is not supported. We don't have a |
| // lib64. |
| std::string Arch = getArchName(); |
| ArchName = Arch.c_str(); |
| if (Args.hasArg(options::OPT_m32) && getArchName() == "x86_64") { |
| ArchName = "i386"; |
| Lib32 = true; |
| } |
| |
| ToolChain *&TC = ToolChains[ArchName]; |
| if (!TC) { |
| llvm::Triple TCTriple(getTriple()); |
| TCTriple.setArchName(ArchName); |
| |
| TC = new toolchains::FreeBSD(*this, TCTriple, Lib32); |
| } |
| |
| 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 types::ID lookupTypeForExtension(const char *Ext) const { |
| return types::lookupTypeForExtension(Ext); |
| } |
| |
| 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 types::ID lookupTypeForExtension(const char *Ext) const { |
| return types::lookupTypeForExtension(Ext); |
| } |
| |
| 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; |
| } |
| |
| } |
| |
| 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::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::createUnknownHostInfo(const Driver &D, |
| const llvm::Triple& Triple) { |
| return new UnknownHostInfo(D, Triple); |
| } |