aboutsummaryrefslogtreecommitdiff
path: root/lib/Driver/Driver.cpp
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2012-01-25 11:01:57 +0000
committerChandler Carruth <chandlerc@gmail.com>2012-01-25 11:01:57 +0000
commit18d7f3af752c41a197552a1ff25ddd639224b4bb (patch)
tree73e4eba9a7a5f6eb14339db9001dcad0dba9f866 /lib/Driver/Driver.cpp
parent3366ef0783b855da9949229dfe3e9d58e13824bd (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.cpp172
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,