Driver: Move Clang "triple" computation routines to method on the
ToolChain. This fixes a potenial bad cast when running Clang on PPC code, since
the tool chain in effect is not a subclass of the Darwin one, but we were
treating it like it was.
- This introduces some gross code duplication, but the right fix for it is to
just move the Driver to start depending on the targets in libBasic, so I am
not planning on fixing it immediately.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111856 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index ab907c1..94c1c6b 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -10,8 +10,12 @@
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Action.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/HostInfo.h"
+#include "clang/Driver/Options.h"
using namespace clang::driver;
@@ -38,3 +42,135 @@
types::ID ToolChain::LookupTypeForExtension(const char *Ext) const {
return types::lookupTypeForExtension(Ext);
}
+
+/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting.
+//
+// FIXME: tblgen this.
+static const char *getARMTargetCPU(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ // FIXME: Warn on inconsistent use of -mcpu and -march.
+
+ // If we have -mcpu=, use that.
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ return A->getValue(Args);
+
+ llvm::StringRef MArch;
+ if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ // Otherwise, if we have -march= choose the base CPU for that arch.
+ MArch = A->getValue(Args);
+ } else {
+ // Otherwise, use the Arch from the triple.
+ MArch = Triple.getArchName();
+ }
+
+ if (MArch == "armv2" || MArch == "armv2a")
+ return "arm2";
+ if (MArch == "armv3")
+ return "arm6";
+ if (MArch == "armv3m")
+ return "arm7m";
+ if (MArch == "armv4" || MArch == "armv4t")
+ return "arm7tdmi";
+ if (MArch == "armv5" || MArch == "armv5t")
+ return "arm10tdmi";
+ if (MArch == "armv5e" || MArch == "armv5te")
+ return "arm1026ejs";
+ if (MArch == "armv5tej")
+ return "arm926ej-s";
+ if (MArch == "armv6" || MArch == "armv6k")
+ return "arm1136jf-s";
+ if (MArch == "armv6j")
+ return "arm1136j-s";
+ if (MArch == "armv6z" || MArch == "armv6zk")
+ return "arm1176jzf-s";
+ if (MArch == "armv6t2")
+ return "arm1156t2-s";
+ if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
+ return "cortex-a8";
+ if (MArch == "armv7r" || MArch == "armv7-r")
+ return "cortex-r4";
+ if (MArch == "armv7m" || MArch == "armv7-m")
+ return "cortex-m3";
+ if (MArch == "ep9312")
+ return "ep9312";
+ if (MArch == "iwmmxt")
+ return "iwmmxt";
+ if (MArch == "xscale")
+ return "xscale";
+
+ // If all else failed, return the most base CPU LLVM supports.
+ return "arm7tdmi";
+}
+
+/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
+/// CPU.
+//
+// FIXME: This is redundant with -mcpu, why does LLVM use this.
+// FIXME: tblgen this, or kill it!
+static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
+ if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" ||
+ CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" ||
+ CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" ||
+ CPU == "arm940t" || CPU == "ep9312")
+ return "v4t";
+
+ if (CPU == "arm10tdmi" || CPU == "arm1020t")
+ return "v5";
+
+ if (CPU == "arm9e" || CPU == "arm926ej-s" || CPU == "arm946e-s" ||
+ CPU == "arm966e-s" || CPU == "arm968e-s" || CPU == "arm10e" ||
+ CPU == "arm1020e" || CPU == "arm1022e" || CPU == "xscale" ||
+ CPU == "iwmmxt")
+ return "v5e";
+
+ if (CPU == "arm1136j-s" || CPU == "arm1136jf-s" || CPU == "arm1176jz-s" ||
+ CPU == "arm1176jzf-s" || CPU == "mpcorenovfp" || CPU == "mpcore")
+ return "v6";
+
+ if (CPU == "arm1156t2-s" || CPU == "arm1156t2f-s")
+ return "v6t2";
+
+ if (CPU == "cortex-a8" || CPU == "cortex-a9")
+ return "v7";
+
+ return "";
+}
+
+std::string ToolChain::ComputeLLVMTriple(const ArgList &Args) const {
+ switch (getTriple().getArch()) {
+ default:
+ return getTripleString();
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb: {
+ // FIXME: Factor into subclasses.
+ llvm::Triple Triple = getTriple();
+
+ // Thumb2 is the default for V7 on Darwin.
+ //
+ // FIXME: Thumb should just be another -target-feaure, not in the triple.
+ llvm::StringRef Suffix =
+ getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
+ bool ThumbDefault =
+ (Suffix == "v7" && getTriple().getOS() == llvm::Triple::Darwin);
+ std::string ArchName = "arm";
+ if (Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
+ ArchName = "thumb";
+ Triple.setArchName(ArchName + Suffix.str());
+
+ return Triple.getTriple();
+ }
+ }
+}
+
+std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args) const {
+ // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on
+ // non-Darwin.
+ if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ,
+ options::OPT_miphoneos_version_min_EQ))
+ getDriver().Diag(clang::diag::err_drv_clang_unsupported)
+ << A->getAsString(Args);
+
+ return ComputeLLVMTriple(Args);
+}
+
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index f1e0d4d..5be810d 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -19,6 +19,7 @@
#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -202,6 +203,38 @@
delete it->second;
}
+std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args) const {
+ llvm::Triple Triple(ComputeLLVMTriple(Args));
+
+ // If the target isn't initialized (e.g., an unknown Darwin platform, return
+ // the default triple).
+ if (!isTargetInitialized())
+ return Triple.getTriple();
+
+ unsigned Version[3];
+ getTargetVersion(Version);
+
+ // Mangle the target version into the OS triple component. For historical
+ // reasons that make little sense, the version passed here is the "darwin"
+ // version, which drops the 10 and offsets by 4. See inverse code when
+ // setting the OS version preprocessor define.
+ if (!isTargetIPhoneOS()) {
+ Version[0] = Version[1] + 4;
+ Version[1] = Version[2];
+ Version[2] = 0;
+ } else {
+ // Use the environment to communicate that we are targetting iPhoneOS.
+ Triple.setEnvironmentName("iphoneos");
+ }
+
+ llvm::SmallString<16> Str;
+ llvm::raw_svector_ostream(Str) << "darwin" << Version[0]
+ << "." << Version[1] << "." << Version[2];
+ Triple.setOSName(Str.str());
+
+ return Triple.getTriple();
+}
+
Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA) const {
Action::ActionClass Key;
if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
@@ -763,6 +796,11 @@
return !isTargetIPhoneOS();
}
+std::string
+Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args) const {
+ return ComputeLLVMTriple(Args);
+}
+
/// Generic_GCC - A tool chain using the 'gcc' command to perform
/// all subcommands; this relies on gcc translating the majority of
/// command line options.
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 742daad..d1f1556 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -73,6 +73,8 @@
Darwin(const HostInfo &Host, const llvm::Triple& Triple);
~Darwin();
+ std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
+
/// @name Darwin Specific Toolchain API
/// {
@@ -251,6 +253,8 @@
Darwin_Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {}
+ std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
+
virtual const char *GetDefaultRelocationModel() const { return "pic"; }
};
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index dfd170e..0024bc9 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -337,35 +337,6 @@
return "";
}
-/// getLLVMTriple - Get the LLVM triple to use for a particular toolchain, which
-/// may depend on command line arguments.
-static std::string getLLVMTriple(const ToolChain &TC, const ArgList &Args) {
- switch (TC.getTriple().getArch()) {
- default:
- return TC.getTripleString();
-
- case llvm::Triple::arm:
- case llvm::Triple::thumb: {
- // FIXME: Factor into subclasses.
- llvm::Triple Triple = TC.getTriple();
-
- // Thumb2 is the default for V7 on Darwin.
- //
- // FIXME: Thumb should just be another -target-feaure, not in the triple.
- llvm::StringRef Suffix =
- getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
- bool ThumbDefault =
- (Suffix == "v7" && TC.getTriple().getOS() == llvm::Triple::Darwin);
- std::string ArchName = "arm";
- if (Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
- ArchName = "thumb";
- Triple.setArchName(ArchName + Suffix.str());
-
- return Triple.getTriple();
- }
- }
-}
-
// FIXME: Move to target hook.
static bool isSignedCharDefault(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
@@ -694,55 +665,6 @@
}
}
-/// getEffectiveClangTriple - Get the "effective" target triple, which is the
-/// triple for the target but with the OS version potentially modified for
-/// Darwin's -mmacosx-version-min.
-static std::string getEffectiveClangTriple(const Driver &D,
- const ToolChain &TC,
- const ArgList &Args) {
- llvm::Triple Triple(getLLVMTriple(TC, Args));
-
- // Handle -mmacosx-version-min and -miphoneos-version-min.
- if (Triple.getOS() != llvm::Triple::Darwin) {
- // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on
- // non-Darwin.
- if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ,
- options::OPT_miphoneos_version_min_EQ))
- D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
- } else {
- const toolchains::Darwin &DarwinTC(
- reinterpret_cast<const toolchains::Darwin&>(TC));
-
- // If the target isn't initialized (e.g., an unknown Darwin platform, return
- // the default triple).
- if (!DarwinTC.isTargetInitialized())
- return Triple.getTriple();
-
- unsigned Version[3];
- DarwinTC.getTargetVersion(Version);
-
- // Mangle the target version into the OS triple component. For historical
- // reasons that make little sense, the version passed here is the "darwin"
- // version, which drops the 10 and offsets by 4. See inverse code when
- // setting the OS version preprocessor define.
- if (!DarwinTC.isTargetIPhoneOS()) {
- Version[0] = Version[1] + 4;
- Version[1] = Version[2];
- Version[2] = 0;
- } else {
- // Use the environment to communicate that we are targetting iPhoneOS.
- Triple.setEnvironmentName("iphoneos");
- }
-
- llvm::SmallString<16> Str;
- llvm::raw_svector_ostream(Str) << "darwin" << Version[0]
- << "." << Version[1] << "." << Version[2];
- Triple.setOSName(Str.str());
- }
-
- return Triple.getTriple();
-}
-
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -762,7 +684,7 @@
// Add the "effective" target triple.
CmdArgs.push_back("-triple");
- std::string TripleStr = getEffectiveClangTriple(D, getToolChain(), Args);
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
CmdArgs.push_back(Args.MakeArgString(TripleStr));
// Select the appropriate action.
@@ -1543,7 +1465,6 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
assert(Inputs.size() == 1 && "Unexpected number of inputs.");
@@ -1556,7 +1477,7 @@
// Add the "effective" target triple.
CmdArgs.push_back("-triple");
- std::string TripleStr = getEffectiveClangTriple(D, getToolChain(), Args);
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
CmdArgs.push_back(Args.MakeArgString(TripleStr));
// Set the output mode, we currently only expect to be used as a real