summaryrefslogtreecommitdiffstats
path: root/lib/Driver/HostInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/HostInfo.cpp')
-rw-r--r--lib/Driver/HostInfo.cpp408
1 files changed, 408 insertions, 0 deletions
diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp
new file mode 100644
index 0000000..603b3ab
--- /dev/null
+++ b/lib/Driver/HostInfo.cpp
@@ -0,0 +1,408 @@
+//===--- 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::StringMap<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 *getToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {
+
+ assert((getArchName() == "i386" || getArchName() == "x86_64" ||
+ getArchName() == "powerpc" || getArchName() == "powerpc64" ||
+ getArchName() == "arm") &&
+ "Unknown Darwin 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::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool DarwinHostInfo::useDriverDriver() const {
+ return true;
+}
+
+ToolChain *DarwinHostInfo::getToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ std::string Arch;
+ if (!ArchName) {
+ Arch = getArchName();
+ ArchName = Arch.c_str();
+
+ // If no arch name is specified, infer it from the host and
+ // -m32/-m64.
+ if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+ if (getArchName() == "i386" || getArchName() == "x86_64") {
+ ArchName =
+ (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
+ } else if (getArchName() == "powerpc" || getArchName() == "powerpc64") {
+ ArchName = (A->getOption().getId() == options::OPT_m32) ? "powerpc" :
+ "powerpc64";
+ }
+ }
+ } else {
+ // Normalize arch name; we shouldn't be doing this here.
+ //
+ // FIXME: This should be unnecessary once everything moves over to using the
+ // ID based Triple interface.
+ if (strcmp(ArchName, "ppc") == 0)
+ ArchName = "powerpc";
+ else if (strcmp(ArchName, "ppc64") == 0)
+ ArchName = "powerpc64";
+ }
+
+ ToolChain *&TC = ToolChains[ArchName];
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(ArchName);
+
+ if (strcmp(ArchName, "i386") == 0 || strcmp(ArchName, "x86_64") == 0)
+ TC = new toolchains::Darwin_X86(*this, TCTriple,
+ DarwinVersion,
+ GCCVersion);
+ else
+ TC = new toolchains::Darwin_GCC(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+// 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 *getToolChain(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::getToolChain(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 (getArchName() == "i386" || getArchName() == "x86_64") {
+ ArchName =
+ (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
+ } else if (getArchName() == "powerpc" || getArchName() == "powerpc64") {
+ ArchName =
+ (A->getOption().getId() == 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;
+}
+
+// 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 *getToolChain(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::getToolChain(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 *getToolChain(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::getToolChain(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 *getToolChain(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::getToolChain(const ArgList &Args,
+ const char *ArchName) const {
+
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ ArchName = getArchName().c_str();
+
+ ToolChain *&TC = ToolChains[ArchName];
+
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(getArchName());
+
+ TC = new toolchains::Linux(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+}
+
+const HostInfo *
+clang::driver::createDarwinHostInfo(const Driver &D,
+ const llvm::Triple& Triple){
+ return new DarwinHostInfo(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::createUnknownHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new UnknownHostInfo(D, Triple);
+}
OpenPOWER on IntegriCloud