//===--- 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.
    const char *UseNewToolChain = ::getenv("CCC_ENABLE_NEW_DARWIN_TOOLCHAIN");
    if (UseNewToolChain || 
        Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64 ||
        Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) {
      TC = new toolchains::DarwinClang(*this, TCTriple);
    } 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);
    } 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;
}

// 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::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);
}
