aboutsummaryrefslogtreecommitdiff
path: root/lib/Driver/ToolChains.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2010-09-17 15:54:40 +0000
committerDimitry Andric <dim@FreeBSD.org>2010-09-17 15:54:40 +0000
commit3d1dcd9bfdb15c49ee34d576a065079ac5c4d29f (patch)
tree0bbe07708f7571f8b5291f6d7b96c102b7c99dee /lib/Driver/ToolChains.cpp
parenta0482fa4e7fa27b01184f938097f0666b78016dd (diff)
downloadsrc-3d1dcd9bfdb15c49ee34d576a065079ac5c4d29f.tar.gz
src-3d1dcd9bfdb15c49ee34d576a065079ac5c4d29f.zip
Vendor import of clang r114020 (from the release_28 branch):vendor/clang/clang-r114020
Notes
Notes: svn path=/vendor/clang/dist/; revision=212795 svn path=/vendor/clang/clang-r114020/; revision=212796; tag=vendor/clang/clang-r114020
Diffstat (limited to 'lib/Driver/ToolChains.cpp')
-rw-r--r--lib/Driver/ToolChains.cpp265
1 files changed, 227 insertions, 38 deletions
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index a78d1536fa1e..471c47dd2b50 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -18,7 +18,9 @@
#include "clang/Driver/OptTable.h"
#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -31,13 +33,30 @@ using namespace clang::driver::toolchains;
/// Darwin - Darwin tool chain for i386 and x86_64.
-Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple,
- const unsigned (&_DarwinVersion)[3])
+Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple)
: ToolChain(Host, Triple), TargetInitialized(false)
{
+ // Compute the initial Darwin version based on the host.
+ bool HadExtra;
+ std::string OSName = Triple.getOSName();
+ if (!Driver::GetReleaseVersion(&OSName[6],
+ DarwinVersion[0], DarwinVersion[1],
+ DarwinVersion[2], HadExtra))
+ getDriver().Diag(clang::diag::err_drv_invalid_darwin_version) << OSName;
+
llvm::raw_string_ostream(MacosxVersionMin)
- << "10." << std::max(0, (int)_DarwinVersion[0] - 4) << '.'
- << _DarwinVersion[1];
+ << "10." << std::max(0, (int)DarwinVersion[0] - 4) << '.'
+ << DarwinVersion[1];
+}
+
+types::ID Darwin::LookupTypeForExtension(const char *Ext) const {
+ types::ID Ty = types::lookupTypeForExtension(Ext);
+
+ // Darwin always preprocesses assembly files (unless -x is used explicitly).
+ if (Ty == types::TY_PP_Asm)
+ return types::TY_Asm;
+
+ return Ty;
}
// FIXME: Can we tablegen this?
@@ -103,14 +122,13 @@ llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
}
}
-DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
- const unsigned (&DarwinVersion)[3],
- const unsigned (&_GCCVersion)[3])
- : Darwin(Host, Triple, DarwinVersion)
+DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple)
+ : Darwin(Host, Triple)
{
- GCCVersion[0] = _GCCVersion[0];
- GCCVersion[1] = _GCCVersion[1];
- GCCVersion[2] = _GCCVersion[2];
+ // We can only work with 4.2.1 currently.
+ GCCVersion[0] = 4;
+ GCCVersion[1] = 2;
+ GCCVersion[2] = 1;
// Set up the tool chain paths to match gcc.
ToolChainDir = "i686-apple-darwin";
@@ -174,7 +192,9 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
Path += ToolChainDir;
getProgramPaths().push_back(Path);
- getProgramPaths().push_back(getDriver().Dir);
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
}
Darwin::~Darwin() {
@@ -184,6 +204,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()))
@@ -245,7 +297,7 @@ void DarwinGCC::AddLinkSearchPathArgs(const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
"/x86_64"));
}
-
+
CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/" + ToolChainDir));
Tmp = getDriver().Dir + "/../lib/gcc/" + ToolChainDir;
@@ -314,12 +366,13 @@ void DarwinGCC::AddLinkRuntimeLibArgs(const ArgList &Args,
}
}
-DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple,
- const unsigned (&DarwinVersion)[3])
- : Darwin(Host, Triple, DarwinVersion)
+DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple)
+ : Darwin(Host, Triple)
{
// We expect 'as', 'ld', etc. to be adjacent to our install dir.
- getProgramPaths().push_back(getDriver().Dir);
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
}
void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
@@ -350,6 +403,39 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
break;
}
P.appendComponent("4.2.1");
+
+ // Determine the arch specific GCC subdirectory.
+ const char *ArchSpecificDir = 0;
+ switch (getTriple().getArch()) {
+ default:
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb: {
+ std::string Triple = ComputeLLVMTriple(Args);
+ llvm::StringRef TripleStr = Triple;
+ if (TripleStr.startswith("armv5") || TripleStr.startswith("thumbv5"))
+ ArchSpecificDir = "v5";
+ else if (TripleStr.startswith("armv6") || TripleStr.startswith("thumbv6"))
+ ArchSpecificDir = "v6";
+ else if (TripleStr.startswith("armv7") || TripleStr.startswith("thumbv7"))
+ ArchSpecificDir = "v7";
+ break;
+ }
+ case llvm::Triple::ppc64:
+ ArchSpecificDir = "ppc64";
+ break;
+ case llvm::Triple::x86_64:
+ ArchSpecificDir = "x86_64";
+ break;
+ }
+
+ if (ArchSpecificDir) {
+ P.appendComponent(ArchSpecificDir);
+ if (P.exists())
+ CmdArgs.push_back(Args.MakeArgString("-L" + P.str()));
+ P.eraseComponent();
+ }
+
if (P.exists())
CmdArgs.push_back(Args.MakeArgString("-L" + P.str()));
}
@@ -415,18 +501,9 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
}
}
-DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
- const char *BoundArch) const {
- DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
const OptTable &Opts = getDriver().getOpts();
- // FIXME: We really want to get out of the tool chain level argument
- // translation business, as it makes the driver functionality much
- // more opaque. For now, we follow gcc closely solely for the
- // purpose of easily achieving feature parity & testability. Once we
- // have something that works, we should reevaluate each translation
- // and try to push it down into tool specific logic.
-
Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
Arg *iPhoneVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ);
if (OSXVersion && iPhoneVersion) {
@@ -462,17 +539,17 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
if (OSXTarget) {
const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
- OSXVersion = DAL->MakeJoinedArg(0, O, OSXTarget);
- DAL->append(OSXVersion);
+ OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget);
+ Args.append(OSXVersion);
} else if (iPhoneOSTarget) {
const Option *O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
- iPhoneVersion = DAL->MakeJoinedArg(0, O, iPhoneOSTarget);
- DAL->append(iPhoneVersion);
+ iPhoneVersion = Args.MakeJoinedArg(0, O, iPhoneOSTarget);
+ Args.append(iPhoneVersion);
} else {
// Otherwise, assume we are targeting OS X.
const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
- OSXVersion = DAL->MakeJoinedArg(0, O, MacosxVersionMin);
- DAL->append(OSXVersion);
+ OSXVersion = Args.MakeJoinedArg(0, O, MacosxVersionMin);
+ Args.append(OSXVersion);
}
}
@@ -495,6 +572,19 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
<< iPhoneVersion->getAsString(Args);
}
setTarget(iPhoneVersion, Major, Minor, Micro);
+}
+
+DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
+ const char *BoundArch) const {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+ const OptTable &Opts = getDriver().getOpts();
+
+ // FIXME: We really want to get out of the tool chain level argument
+ // translation business, as it makes the driver functionality much
+ // more opaque. For now, we follow gcc closely solely for the
+ // purpose of easily achieving feature parity & testability. Once we
+ // have something that works, we should reevaluate each translation
+ // and try to push it down into tool specific logic.
for (ArgList::const_iterator it = Args.begin(),
ie = Args.end(); it != ie; ++it) {
@@ -673,6 +763,11 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
llvm_unreachable("invalid Darwin arch");
}
+ // Add an explicit version min argument for the deployment target. We do this
+ // after argument translation because -Xarch_ arguments may add a version min
+ // argument.
+ AddDeploymentTarget(*DAL);
+
return DAL;
}
@@ -709,13 +804,20 @@ 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.
Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
: ToolChain(Host, Triple) {
- getProgramPaths().push_back(getDriver().Dir);
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+ getProgramPaths().push_back(getDriver().Dir);
}
Generic_GCC::~Generic_GCC() {
@@ -864,8 +966,16 @@ Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
-FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32)
+FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
+
+ // Determine if we are compiling 32-bit code on an x86_64 platform.
+ bool Lib32 = false;
+ if (Triple.getArch() == llvm::Triple::x86 &&
+ llvm::Triple(getDriver().DefaultHostTriple).getArch() ==
+ llvm::Triple::x86_64)
+ Lib32 = true;
+
getProgramPaths().push_back(getDriver().Dir + "/../libexec");
getProgramPaths().push_back("/usr/libexec");
if (Lib32) {
@@ -936,7 +1046,9 @@ Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA) const {
AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
- getProgramPaths().push_back(getDriver().Dir);
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+ getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
@@ -973,7 +1085,8 @@ Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const {
Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
- getFilePaths().push_back(getDriver().Dir + "/../lib/clang/1.0/");
+ getFilePaths().push_back(getDriver().Dir +
+ "/../lib/clang/" CLANG_VERSION_STRING "/");
getFilePaths().push_back("/lib/");
getFilePaths().push_back("/usr/lib/");
@@ -994,13 +1107,35 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple)
// list), but that's messy at best.
}
+Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::AssembleJobClass:
+ T = new tools::linuxtools::Assemble(*this); break;
+ default:
+ T = &Generic_GCC::SelectTool(C, JA);
+ }
+ }
+
+ return *T;
+}
+
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
// Path mangling to find libexec
- getProgramPaths().push_back(getDriver().Dir);
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+ getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
@@ -1028,3 +1163,57 @@ Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const {
return *T;
}
+
+Windows::Windows(const HostInfo &Host, const llvm::Triple& Triple)
+ : ToolChain(Host, Triple) {
+}
+
+Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::InputClass:
+ case Action::BindArchClass:
+ case Action::LipoJobClass:
+ case Action::DsymutilJobClass:
+ assert(0 && "Invalid tool kind.");
+ case Action::PreprocessJobClass:
+ case Action::PrecompileJobClass:
+ case Action::AnalyzeJobClass:
+ case Action::CompileJobClass:
+ T = new tools::Clang(*this); break;
+ case Action::AssembleJobClass:
+ T = new tools::ClangAs(*this); break;
+ case Action::LinkJobClass:
+ T = new tools::visualstudio::Link(*this); break;
+ }
+ }
+
+ return *T;
+}
+
+bool Windows::IsIntegratedAssemblerDefault() const {
+ return true;
+}
+
+bool Windows::IsUnwindTablesDefault() const {
+ // FIXME: Gross; we should probably have some separate target
+ // definition, possibly even reusing the one in clang.
+ return getArchName() == "x86_64";
+}
+
+const char *Windows::GetDefaultRelocationModel() const {
+ return "static";
+}
+
+const char *Windows::GetForcedPicModel() const {
+ if (getArchName() == "x86_64")
+ return "pic";
+ return 0;
+}