#include "clang/Driver/Action.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Path.h"
/// programs.
path_list ProgramPaths;
- mutable llvm::DenseMap<unsigned, Tool*> Tools;
+ mutable OwningPtr<Tool> Clang;
+ mutable OwningPtr<Tool> Assemble;
+ mutable OwningPtr<Tool> Link;
+ Tool *getClang() const;
+ Tool *getAssemble() const;
+ Tool *getLink() const;
+ Tool *getClangAs() const;
protected:
ToolChain(const Driver &D, const llvm::Triple &T, const ArgList &Args);
- virtual Tool *constructTool(Action::ActionClass AC) const;
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
+ virtual Tool *getTool(Action::ActionClass AC) const;
/// \name Utilities for implementing subclasses.
///@{
}
ToolChain::~ToolChain() {
- // Free tool implementations.
- for (llvm::DenseMap<unsigned, Tool*>::iterator
- it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
- delete it->second;
}
const Driver &ToolChain::getDriver() const {
return false;
}
-Tool *ToolChain::constructTool(Action::ActionClass AC) const {
+Tool *ToolChain::getClang() const {
+ if (!Clang)
+ Clang.reset(new tools::Clang(*this));
+ return Clang.get();
+}
+
+Tool *ToolChain::buildAssembler() const {
+ return new tools::ClangAs(*this);
+}
+
+Tool *ToolChain::buildLinker() const {
+ llvm_unreachable("Linking is not supported by this toolchain");
+}
+
+Tool *ToolChain::getAssemble() const {
+ if (!Assemble)
+ Assemble.reset(buildAssembler());
+ return Assemble.get();
+}
+
+Tool *ToolChain::getClangAs() const {
+ if (!Assemble)
+ Assemble.reset(new tools::ClangAs(*this));
+ return Assemble.get();
+}
+
+Tool *ToolChain::getLink() const {
+ if (!Link)
+ Link.reset(buildLinker());
+ return Link.get();
+}
+
+Tool *ToolChain::getTool(Action::ActionClass AC) const {
switch (AC) {
- case Action::InputClass:
- case Action::BindArchClass:
case Action::AssembleJobClass:
+ return getAssemble();
+
case Action::LinkJobClass:
+ return getLink();
+
+ case Action::InputClass:
+ case Action::BindArchClass:
case Action::LipoJobClass:
case Action::DsymutilJobClass:
case Action::VerifyJobClass:
case Action::PreprocessJobClass:
case Action::AnalyzeJobClass:
case Action::MigrateJobClass:
- return new tools::Clang(*this);
+ return getClang();
}
}
Tool &ToolChain::SelectTool(const JobAction &JA) const {
- Action::ActionClass Key;
if (getDriver().ShouldUseClangCompiler(JA))
- Key = Action::AnalyzeJobClass;
- else
- Key = JA.getKind();
-
- Tool *&T = Tools[Key];
- if (T)
- return *T;
-
- if (getDriver().ShouldUseClangCompiler(JA))
- T = new tools::Clang(*this);
- else if (Key == Action::AssembleJobClass && useIntegratedAs())
- T = new tools::ClangAs(*this);
- else
- T = constructTool(Key);
-
- return *T;
+ return *getClang();
+ Action::ActionClass AC = JA.getKind();
+ if (AC == Action::AssembleJobClass && useIntegratedAs())
+ return *getClangAs();
+ return *getTool(AC);
}
std::string ToolChain::GetFilePath(const char *Name) const {
void Generic_ELF::anchor() {}
-Tool *Darwin::constructTool(Action::ActionClass AC) const {
+Tool *Darwin::getTool(Action::ActionClass AC) const {
switch (AC) {
- case Action::AssembleJobClass:
- return new tools::darwin::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::darwin::Link(*this);
case Action::LipoJobClass:
- return new tools::darwin::Lipo(*this);
+ if (!Lipo)
+ Lipo.reset(new tools::darwin::Lipo(*this));
+ return Lipo.get();
case Action::DsymutilJobClass:
- return new tools::darwin::Dsymutil(*this);
+ if (!Dsymutil)
+ Dsymutil.reset(new tools::darwin::Dsymutil(*this));
+ return Dsymutil.get();
case Action::VerifyJobClass:
- return new tools::darwin::VerifyDebug(*this);
+ if (!VerifyDebug)
+ VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));
+ return VerifyDebug.get();
default:
- return ToolChain::constructTool(AC);
+ return ToolChain::getTool(AC);
}
}
+Tool *Darwin::buildLinker() const {
+ return new tools::darwin::Link(*this);
+}
+
+Tool *Darwin::buildAssembler() const {
+ return new tools::darwin::Assemble(*this);
+}
DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple,
const ArgList &Args)
Generic_GCC::~Generic_GCC() {
}
-Tool *Generic_GCC::constructTool(Action::ActionClass AC) const {
+Tool *Generic_GCC::getTool(Action::ActionClass AC) const {
switch (AC) {
case Action::PreprocessJobClass:
- return new tools::gcc::Preprocess(*this);
+ if (!Preprocess)
+ Preprocess.reset(new tools::gcc::Preprocess(*this));
+ return Preprocess.get();
case Action::PrecompileJobClass:
- return new tools::gcc::Precompile(*this);
+ if (!Precompile)
+ Precompile.reset(new tools::gcc::Precompile(*this));
+ return Precompile.get();
case Action::CompileJobClass:
- return new tools::gcc::Compile(*this);
- case Action::AssembleJobClass:
- return new tools::gcc::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::gcc::Link(*this);
+ if (!Compile)
+ Compile.reset(new tools::gcc::Compile(*this));
+ return Compile.get();
default:
- return ToolChain::constructTool(AC);
+ return ToolChain::getTool(AC);
}
}
+Tool *Generic_GCC::buildAssembler() const {
+ return new tools::gcc::Assemble(*this);
+}
+
+Tool *Generic_GCC::buildLinker() const {
+ return new tools::gcc::Link(*this);
+}
+
bool Generic_GCC::IsUnwindTablesDefault() const {
return getArch() == llvm::Triple::x86_64;
}
Hexagon_TC::~Hexagon_TC() {
}
-Tool *Hexagon_TC::constructTool(Action::ActionClass AC) const {
- switch (AC) {
- case Action::AssembleJobClass:
- return new tools::hexagon::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::hexagon::Link(*this);
- default:
- return Linux::constructTool(AC);
- }
+Tool *Hexagon_TC::buildAssembler() const {
+ return new tools::hexagon::Assemble(*this);
+}
+
+Tool *Hexagon_TC::buildLinker() const {
+ return new tools::hexagon::Link(*this);
}
void Hexagon_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
getFilePaths().push_back("/usr/lib");
}
-Tool *OpenBSD::constructTool(Action::ActionClass AC) const {
- switch (AC) {
- case Action::AssembleJobClass:
- return new tools::openbsd::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::openbsd::Link(*this);
- default:
- return Generic_GCC::constructTool(AC);
- }
+Tool *OpenBSD::buildAssembler() const {
+ return new tools::openbsd::Assemble(*this);
+}
+
+Tool *OpenBSD::buildLinker() const {
+ return new tools::openbsd::Link(*this);
}
/// Bitrig - Bitrig tool chain which can call as(1) and ld(1) directly.
getFilePaths().push_back("/usr/lib");
}
-Tool *Bitrig::constructTool(Action::ActionClass AC) const {
- switch (AC) {
- case Action::AssembleJobClass:
- return new tools::bitrig::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::bitrig::Link(*this); break;
- default:
- return Generic_GCC::constructTool(AC);
- }
+Tool *Bitrig::buildAssembler() const {
+ return new tools::bitrig::Assemble(*this);
+}
+
+Tool *Bitrig::buildLinker() const {
+ return new tools::bitrig::Link(*this);
}
void Bitrig::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
}
-Tool *FreeBSD::constructTool(Action::ActionClass AC) const {
- switch (AC) {
- case Action::AssembleJobClass:
- return new tools::freebsd::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::freebsd::Link(*this); break;
- default:
- return Generic_GCC::constructTool(AC);
- }
+Tool *FreeBSD::buildAssembler() const {
+ return new tools::freebsd::Assemble(*this);
+}
+
+Tool *FreeBSD::buildLinker() const {
+ return new tools::freebsd::Link(*this);
}
bool FreeBSD::UseSjLjExceptions() const {
}
}
-Tool *NetBSD::constructTool(Action::ActionClass AC) const {
- switch (AC) {
- case Action::AssembleJobClass:
- return new tools::netbsd::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::netbsd::Link(*this);
- default:
- return Generic_GCC::constructTool(AC);
- }
+Tool *NetBSD::buildAssembler() const {
+ return new tools::netbsd::Assemble(*this);
+}
+
+Tool *NetBSD::buildLinker() const {
+ return new tools::netbsd::Link(*this);
}
/// Minix - Minix tool chain which can call as(1) and ld(1) directly.
getFilePaths().push_back("/usr/lib");
}
-Tool *Minix::constructTool(Action::ActionClass AC) const {
- switch (AC) {
- case Action::AssembleJobClass:
- return new tools::minix::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::minix::Link(*this);
- default:
- return Generic_GCC::constructTool(AC);
- }
+Tool *Minix::buildAssembler() const {
+ return new tools::minix::Assemble(*this);
+}
+
+Tool *Minix::buildLinker() const {
+ return new tools::minix::Link(*this);
}
/// AuroraUX - AuroraUX tool chain which can call as(1) and ld(1) directly.
}
-Tool *AuroraUX::constructTool(Action::ActionClass AC) const {
- switch (AC) {
- case Action::AssembleJobClass:
- return new tools::auroraux::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::auroraux::Link(*this);
- default:
- return Generic_GCC::constructTool(AC);
- }
+Tool *AuroraUX::buildAssembler() const {
+ return new tools::auroraux::Assemble(*this);
+}
+
+Tool *AuroraUX::buildLinker() const {
+ return new tools::auroraux::Link(*this);
}
/// Solaris - Solaris tool chain which can call as(1) and ld(1) directly.
getFilePaths().push_back("/usr/lib");
}
-Tool *Solaris::constructTool(Action::ActionClass AC) const {
- switch (AC) {
- case Action::AssembleJobClass:
- return new tools::solaris::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::solaris::Link(*this);
- default:
- return Generic_GCC::constructTool(AC);
- }
+Tool *Solaris::buildAssembler() const {
+ return new tools::solaris::Assemble(*this);
+}
+
+Tool *Solaris::buildLinker() const {
+ return new tools::solaris::Link(*this);
}
/// Linux toolchain (very bare-bones at the moment).
return true;
}
-Tool *Linux::constructTool(Action::ActionClass AC) const {
- switch (AC) {
- case Action::AssembleJobClass:
- return new tools::linuxtools::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::linuxtools::Link(*this); break;
- default:
- return Generic_GCC::constructTool(AC);
- }
+Tool *Linux::buildLinker() const {
+ return new tools::linuxtools::Link(*this);
+}
+
+Tool *Linux::buildAssembler() const {
+ return new tools::linuxtools::Assemble(*this);
}
void Linux::addClangTargetOptions(const ArgList &DriverArgs,
getFilePaths().push_back("/usr/lib/gcc41");
}
-Tool *DragonFly::constructTool(Action::ActionClass AC) const {
- switch (AC) {
- case Action::AssembleJobClass:
- return new tools::dragonfly::Assemble(*this);
- case Action::LinkJobClass:
- return new tools::dragonfly::Link(*this);
- default:
- return Generic_GCC::constructTool(AC);
- }
+Tool *DragonFly::buildAssembler() const {
+ return new tools::dragonfly::Assemble(*this);
+}
+
+Tool *DragonFly::buildLinker() const {
+ return new tools::dragonfly::Link(*this);
}
Generic_GCC(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
~Generic_GCC();
- virtual Tool *constructTool(Action::ActionClass AC) const;
-
virtual bool IsUnwindTablesDefault() const;
virtual bool isPICDefault() const;
virtual bool isPICDefaultForced() const;
protected:
+ virtual Tool *getTool(Action::ActionClass AC) const;
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
+
/// \name ToolChain Implementation Helper Functions
/// @{
bool isTarget32Bit() const { return getTriple().isArch32Bit(); }
/// @}
+
+private:
+ mutable OwningPtr<tools::gcc::Preprocess> Preprocess;
+ mutable OwningPtr<tools::gcc::Precompile> Precompile;
+ mutable OwningPtr<tools::gcc::Compile> Compile;
};
/// Darwin - The base Darwin tool chain.
/// The host version.
unsigned DarwinVersion[3];
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
+ virtual Tool *getTool(Action::ActionClass AC) const;
+
private:
+ mutable OwningPtr<tools::darwin::Lipo> Lipo;
+ mutable OwningPtr<tools::darwin::Dsymutil> Dsymutil;
+ mutable OwningPtr<tools::darwin::VerifyDebug> VerifyDebug;
+
/// Whether the information on the target has been initialized.
//
// FIXME: This should be eliminated. What we want to do is make this part of
virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
const char *BoundArch) const;
- virtual Tool *constructTool(Action::ActionClass AC) const;
-
virtual bool IsBlocksDefault() const {
// Always allow blocks on Darwin; users interested in versioning are
// expected to use /usr/include/Blocks.h.
public:
AuroraUX(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
- virtual Tool *constructTool(Action::ActionClass AC) const;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_GCC {
public:
Solaris(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
- virtual Tool *constructTool(Action::ActionClass AC) const;
-
virtual bool IsIntegratedAssemblerDefault() const { return true; }
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
+
};
virtual bool IsMathErrnoDefault() const { return false; }
virtual bool IsObjCNonFragileABIDefault() const { return true; }
- virtual Tool *constructTool(Action::ActionClass AC) const;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY Bitrig : public Generic_ELF {
virtual bool IsObjCNonFragileABIDefault() const { return true; }
virtual bool IsObjCLegacyDispatchDefault() const { return false; }
- virtual Tool *constructTool(Action::ActionClass AC) const;
-
virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
virtual void AddCXXStdlibLibArgs(const ArgList &Args,
virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const {
return 1;
}
+
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
virtual bool IsMathErrnoDefault() const { return false; }
virtual bool IsObjCNonFragileABIDefault() const { return true; }
- virtual Tool *constructTool(Action::ActionClass AC) const;
virtual bool UseSjLjExceptions() const;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY NetBSD : public Generic_ELF {
virtual bool IsMathErrnoDefault() const { return false; }
virtual bool IsObjCNonFragileABIDefault() const { return true; }
- virtual Tool *constructTool(Action::ActionClass AC) const;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY Minix : public Generic_ELF {
public:
Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
- virtual Tool *constructTool(Action::ActionClass AC) const;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY DragonFly : public Generic_ELF {
virtual bool IsMathErrnoDefault() const { return false; }
- virtual Tool *constructTool(Action::ActionClass AC) const;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
virtual bool HasNativeLLVMSupport() const;
- virtual Tool *constructTool(Action::ActionClass AC) const;
-
virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
virtual void addClangTargetOptions(const ArgList &DriverArgs,
std::string Linker;
std::vector<std::string> ExtraOpts;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
+
private:
static bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
Twine TargetArchDir,
class LLVM_LIBRARY_VISIBILITY Hexagon_TC : public Linux {
protected:
GCCVersion GCCLibAndIncVersion;
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
public:
Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args);
~Hexagon_TC();
- virtual Tool *constructTool(Action::ActionClass AC) const;
-
virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
public:
Windows(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
- virtual Tool *constructTool(Action::ActionClass AC) const;
-
virtual bool IsIntegratedAssemblerDefault() const;
virtual bool IsUnwindTablesDefault() const;
virtual bool isPICDefault() const;
ArgStringList &CC1Args) const;
virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
-
+protected:
+ virtual Tool *buildLinker() const;
+ virtual Tool *buildAssembler() const;
};
} // end namespace toolchains
: ToolChain(D, Triple, Args) {
}
-Tool *Windows::constructTool(Action::ActionClass AC) const {
- switch (AC) {
- case Action::AssembleJobClass:
- if (getTriple().getEnvironment() == llvm::Triple::MachO)
- return new tools::darwin::Assemble(*this);
+Tool *Windows::buildLinker() const {
+ return new tools::visualstudio::Link(*this);
+}
+
+Tool *Windows::buildAssembler() const {
+ if (getTriple().getEnvironment() == llvm::Triple::MachO)
+ return new tools::darwin::Assemble(*this);
+ else
// There no assembler we can use on windows other than the integrated
// assembler, so we ignore -no-integrated-as.
- return new tools::ClangAs(*this);
- case Action::LinkJobClass:
- return new tools::visualstudio::Link(*this);
- default:
- return ToolChain::constructTool(AC);
- }
+ return ToolChain::buildAssembler();
}
bool Windows::IsIntegratedAssemblerDefault() const {