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. llvm-svn: 111856
This commit is contained in:
parent
f10f9bec83
commit
82eb4ce476
|
@ -18,6 +18,7 @@
|
|||
|
||||
namespace clang {
|
||||
namespace driver {
|
||||
class ArgList;
|
||||
class Compilation;
|
||||
class DerivedArgList;
|
||||
class Driver;
|
||||
|
@ -141,6 +142,17 @@ public:
|
|||
|
||||
/// UseSjLjExceptions - Does this tool chain use SjLj exceptions.
|
||||
virtual bool UseSjLjExceptions() const { return false; }
|
||||
|
||||
/// ComputeLLVMTriple - Return the LLVM target triple to use, after taking
|
||||
/// command line arguments into account.
|
||||
virtual std::string ComputeLLVMTriple(const ArgList &Args) const;
|
||||
|
||||
/// ComputeEffectiveClangTriple - Return the Clang triple to use for this
|
||||
/// target, which may take into account the command line arguments. For
|
||||
/// example, on Darwin the -mmacosx-version-min= command line argument (which
|
||||
/// sets the deployment target) determines the version in the triple passed to
|
||||
/// Clang.
|
||||
virtual std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
|
||||
};
|
||||
|
||||
} // end namespace driver
|
||||
|
|
|
@ -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 @@ std::string ToolChain::GetProgramPath(const char *Name, bool WantFile) const {
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ Darwin::~Darwin() {
|
|||
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 @@ bool Darwin::SupportsObjCGC() const {
|
|||
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.
|
||||
|
|
|
@ -73,6 +73,8 @@ public:
|
|||
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 @@ public:
|
|||
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"; }
|
||||
};
|
||||
|
||||
|
|
|
@ -337,35 +337,6 @@ static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
|
|||
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 @@ static bool needsExceptions(const ArgList &Args, types::ID InputType,
|
|||
}
|
||||
}
|
||||
|
||||
/// 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 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
|
||||
// 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 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
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 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
|
||||
// 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
|
||||
|
|
Loading…
Reference in New Issue