diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2012-01-25 11:01:57 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2012-01-25 11:01:57 +0000 |
commit | 18d7f3af752c41a197552a1ff25ddd639224b4bb (patch) | |
tree | 73e4eba9a7a5f6eb14339db9001dcad0dba9f866 /lib/Driver/Driver.cpp | |
parent | 3366ef0783b855da9949229dfe3e9d58e13824bd (diff) |
Delete the driver's HostInfo class. This abstraction just never really
did anything. The two big pieces of functionality it tried to provide
was to cache the ToolChain objects for each target, and to figure out
the exact target based on the flag set coming in to an invocation.
However, it had a lot of flaws even with those goals:
- Neither of these have anything to do with the host, or its info.
- The HostInfo class was setup as a full blown class *hierarchy* with
a separate implementation for each "host" OS. This required
dispatching just to create the objects in the first place.
- The hierarchy claimed to represent the host, when in fact it was
based on the target OS.
- Each leaf in the hierarchy was responsible for implementing the flag
processing and caching, resulting in a *lot* of copy-paste code and
quite a few bugs.
- The caching was consistently done based on architecture alone, even
though *any* aspect of the targeted triple might change the behavior
of the configured toolchain.
- Flag processing was already being done in the Driver proper,
separating the flag handling even more than it already is.
Instead of this, we can simply have the dispatch logic in the Driver
which previously created a HostInfo object create the ToolChain objects.
Adding caching in the Driver layer is a tiny amount of code. Finally,
pulling the flag processing into the Driver puts it where it belongs and
consolidates it in one location.
The result is that two functions, and maybe 100 lines of new code
replace over 10 classes and 800 lines of code. Woot.
This also paves the way to introduce more detailed ToolChain objects for
various OSes without threading through a new HostInfo type as well, and
the accompanying boiler plate. That, of course, was the yak I started to
shave that began this entire refactoring escapade. Wheee!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148950 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Driver/Driver.cpp')
-rw-r--r-- | lib/Driver/Driver.cpp | 172 |
1 files changed, 119 insertions, 53 deletions
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index f44fe279b0..69dba47be2 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -18,7 +18,6 @@ #include "clang/Driver/ArgList.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/HostInfo.h" #include "clang/Driver/Job.h" #include "clang/Driver/OptTable.h" #include "clang/Driver/Option.h" @@ -40,6 +39,7 @@ #include "llvm/Support/Program.h" #include "InputInfo.h" +#include "ToolChains.h" #include <map> @@ -91,7 +91,11 @@ Driver::Driver(StringRef ClangExecutable, Driver::~Driver() { delete Opts; - delete Host; + + for (llvm::StringMap<ToolChain *>::iterator I = ToolChains.begin(), + E = ToolChains.end(); + I != E; ++I) + delete I->second; } InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { @@ -236,18 +240,6 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { return DAL; } -/// \brief Compute target triple from args. -/// -/// This routine provides the logic to compute a target triple from various -/// args passed to the driver and the default triple string. -static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, - const ArgList &Args) { - if (const Arg *A = Args.getLastArg(options::OPT_target)) - DefaultTargetTriple = A->getValue(Args); - - return llvm::Triple(llvm::Triple::normalize(DefaultTargetTriple)); -} - Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { llvm::PrettyStackTraceString CrashInfo("Compilation construction"); @@ -329,15 +321,11 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { if (Args->hasArg(options::OPT_nostdlib)) UseStdLib = false; - // Compute the target triple based on the args, and build a Host out of it. - // FIXME: Yes, this makes no sense. HostInfo has little to do with the host. - Host = GetHostInfo(computeTargetTriple(DefaultTargetTriple, *Args)); - // Perform the default argument translations. DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args); // Owned by the host. - const ToolChain &TC = *Host->CreateToolChain(*Args); + const ToolChain &TC = getToolChain(*Args); // The compilation takes ownership of Args. Compilation *C = new Compilation(*this, TC, Args, TranslatedArgs); @@ -1328,9 +1316,8 @@ void Driver::BuildJobsForAction(Compilation &C, if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) { const ToolChain *TC = &C.getDefaultToolChain(); - std::string Arch; if (BAA->getArchName()) - TC = Host->CreateToolChain(C.getArgs(), BAA->getArchName()); + TC = &getToolChain(C.getArgs(), BAA->getArchName()); BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(), AtTopLevel, LinkingOutput, Result); @@ -1584,39 +1571,118 @@ std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix) return P.str(); } -const HostInfo *Driver::GetHostInfo(const llvm::Triple &Triple) const { - llvm::PrettyStackTraceString CrashInfo("Constructing host"); - - // TCE is an osless target - if (Triple.getArchName() == "tce") - return createTCEHostInfo(*this, Triple); - - switch (Triple.getOS()) { - case llvm::Triple::AuroraUX: - return createAuroraUXHostInfo(*this, Triple); - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - return createDarwinHostInfo(*this, Triple); - case llvm::Triple::DragonFly: - return createDragonFlyHostInfo(*this, Triple); - case llvm::Triple::OpenBSD: - return createOpenBSDHostInfo(*this, Triple); - case llvm::Triple::NetBSD: - return createNetBSDHostInfo(*this, Triple); - case llvm::Triple::FreeBSD: - return createFreeBSDHostInfo(*this, Triple); - case llvm::Triple::Minix: - return createMinixHostInfo(*this, Triple); - case llvm::Triple::Linux: - return createLinuxHostInfo(*this, Triple); - case llvm::Triple::Win32: - return createWindowsHostInfo(*this, Triple); - case llvm::Triple::MinGW32: - return createMinGWHostInfo(*this, Triple); - default: - return createUnknownHostInfo(*this, Triple); +/// \brief Compute target triple from args. +/// +/// This routine provides the logic to compute a target triple from various +/// args passed to the driver and the default triple string. +static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, + const ArgList &Args, + StringRef DarwinArchName) { + if (const Arg *A = Args.getLastArg(options::OPT_target)) + DefaultTargetTriple = A->getValue(Args); + + llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple)); + + // Handle Darwin-specific options available here. + if (Target.isOSDarwin()) { + // If an explict Darwin arch name is given, that trumps all. + if (!DarwinArchName.empty()) { + Target.setArch( + llvm::Triple::getArchTypeForDarwinArchName(DarwinArchName)); + return Target; + } + + // Handle the Darwin '-arch' flag. + if (Arg *A = Args.getLastArg(options::OPT_arch)) { + llvm::Triple::ArchType DarwinArch + = llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args)); + if (DarwinArch != llvm::Triple::UnknownArch) + Target.setArch(DarwinArch); + } + } + + // Skip further flag support on OSes which don't support '-m32' or '-m64'. + if (Target.getArchName() == "tce" || + Target.getOS() == llvm::Triple::AuroraUX || + Target.getOS() == llvm::Triple::Minix) + return Target; + + // Handle pseudo-target flags '-m32' and '-m64'. + // 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 (Target.getArch() == llvm::Triple::x86_64) + Target.setArch(llvm::Triple::x86); + if (Target.getArch() == llvm::Triple::ppc64) + Target.setArch(llvm::Triple::ppc); + } else { + if (Target.getArch() == llvm::Triple::x86) + Target.setArch(llvm::Triple::x86_64); + if (Target.getArch() == llvm::Triple::ppc) + Target.setArch(llvm::Triple::ppc64); + } + } + + return Target; +} + +const ToolChain &Driver::getToolChain(const ArgList &Args, + StringRef DarwinArchName) const { + llvm::Triple Target = computeTargetTriple(DefaultTargetTriple, Args, + DarwinArchName); + + ToolChain *&TC = ToolChains[Target.str()]; + if (!TC) { + switch (Target.getOS()) { + case llvm::Triple::AuroraUX: + TC = new toolchains::AuroraUX(*this, Target); + break; + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: + if (Target.getArch() == llvm::Triple::x86 || + Target.getArch() == llvm::Triple::x86_64 || + Target.getArch() == llvm::Triple::arm || + Target.getArch() == llvm::Triple::thumb) + TC = new toolchains::DarwinClang(*this, Target); + else + TC = new toolchains::Darwin_Generic_GCC(*this, Target); + break; + case llvm::Triple::DragonFly: + TC = new toolchains::DragonFly(*this, Target); + break; + case llvm::Triple::OpenBSD: + TC = new toolchains::OpenBSD(*this, Target); + break; + case llvm::Triple::NetBSD: + TC = new toolchains::NetBSD(*this, Target, Target); + break; + case llvm::Triple::FreeBSD: + TC = new toolchains::FreeBSD(*this, Target); + break; + case llvm::Triple::Minix: + TC = new toolchains::Minix(*this, Target); + break; + case llvm::Triple::Linux: + TC = new toolchains::Linux(*this, Target); + break; + case llvm::Triple::Win32: + TC = new toolchains::Windows(*this, Target); + break; + case llvm::Triple::MinGW32: + // FIXME: We need a MinGW toolchain. Fallthrough for now. + default: + // TCE is an OSless target + if (Target.getArchName() == "tce") { + TC = new toolchains::TCEToolChain(*this, Target); + break; + } + + TC = new toolchains::Generic_GCC(*this, Target); + break; + } } + return *TC; } bool Driver::ShouldUseClangCompiler(const Compilation &C, const JobAction &JA, |