ToolChain.cpp revision 651f13cea278ec967336033dd032faef0e9fc2ec
1//===--- ToolChain.cpp - Collections of tools for one platform ------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Tools.h"
11#include "clang/Basic/ObjCRuntime.h"
12#include "clang/Driver/Action.h"
13#include "clang/Driver/Driver.h"
14#include "clang/Driver/DriverDiagnostic.h"
15#include "clang/Driver/Options.h"
16#include "clang/Driver/SanitizerArgs.h"
17#include "clang/Driver/ToolChain.h"
18#include "llvm/ADT/StringSwitch.h"
19#include "llvm/Option/Arg.h"
20#include "llvm/Option/ArgList.h"
21#include "llvm/Option/Option.h"
22#include "llvm/Support/ErrorHandling.h"
23#include "llvm/Support/FileSystem.h"
24using namespace clang::driver;
25using namespace clang;
26using namespace llvm::opt;
27
28ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
29                     const ArgList &A)
30  : D(D), Triple(T), Args(A) {
31}
32
33ToolChain::~ToolChain() {
34}
35
36const Driver &ToolChain::getDriver() const {
37 return D;
38}
39
40bool ToolChain::useIntegratedAs() const {
41  return Args.hasFlag(options::OPT_fintegrated_as,
42                      options::OPT_fno_integrated_as,
43                      IsIntegratedAssemblerDefault());
44}
45
46const SanitizerArgs& ToolChain::getSanitizerArgs() const {
47  if (!SanitizerArguments.get())
48    SanitizerArguments.reset(new SanitizerArgs(*this, Args));
49  return *SanitizerArguments.get();
50}
51
52std::string ToolChain::getDefaultUniversalArchName() const {
53  // In universal driver terms, the arch name accepted by -arch isn't exactly
54  // the same as the ones that appear in the triple. Roughly speaking, this is
55  // an inverse of the darwin::getArchTypeForDarwinArchName() function, but the
56  // only interesting special case is powerpc.
57  switch (Triple.getArch()) {
58  case llvm::Triple::ppc:
59    return "ppc";
60  case llvm::Triple::ppc64:
61    return "ppc64";
62  case llvm::Triple::ppc64le:
63    return "ppc64le";
64  default:
65    return Triple.getArchName();
66  }
67}
68
69bool ToolChain::IsUnwindTablesDefault() const {
70  return false;
71}
72
73Tool *ToolChain::getClang() const {
74  if (!Clang)
75    Clang.reset(new tools::Clang(*this));
76  return Clang.get();
77}
78
79Tool *ToolChain::buildAssembler() const {
80  return new tools::ClangAs(*this);
81}
82
83Tool *ToolChain::buildLinker() const {
84  llvm_unreachable("Linking is not supported by this toolchain");
85}
86
87Tool *ToolChain::getAssemble() const {
88  if (!Assemble)
89    Assemble.reset(buildAssembler());
90  return Assemble.get();
91}
92
93Tool *ToolChain::getClangAs() const {
94  if (!Assemble)
95    Assemble.reset(new tools::ClangAs(*this));
96  return Assemble.get();
97}
98
99Tool *ToolChain::getLink() const {
100  if (!Link)
101    Link.reset(buildLinker());
102  return Link.get();
103}
104
105Tool *ToolChain::getTool(Action::ActionClass AC) const {
106  switch (AC) {
107  case Action::AssembleJobClass:
108    return getAssemble();
109
110  case Action::LinkJobClass:
111    return getLink();
112
113  case Action::InputClass:
114  case Action::BindArchClass:
115  case Action::LipoJobClass:
116  case Action::DsymutilJobClass:
117  case Action::VerifyDebugInfoJobClass:
118    llvm_unreachable("Invalid tool kind.");
119
120  case Action::CompileJobClass:
121  case Action::PrecompileJobClass:
122  case Action::PreprocessJobClass:
123  case Action::AnalyzeJobClass:
124  case Action::MigrateJobClass:
125  case Action::VerifyPCHJobClass:
126    return getClang();
127  }
128
129  llvm_unreachable("Invalid tool kind.");
130}
131
132Tool *ToolChain::SelectTool(const JobAction &JA) const {
133  if (getDriver().ShouldUseClangCompiler(JA))
134    return getClang();
135  Action::ActionClass AC = JA.getKind();
136  if (AC == Action::AssembleJobClass && useIntegratedAs())
137    return getClangAs();
138  return getTool(AC);
139}
140
141std::string ToolChain::GetFilePath(const char *Name) const {
142  return D.GetFilePath(Name, *this);
143
144}
145
146std::string ToolChain::GetProgramPath(const char *Name) const {
147  return D.GetProgramPath(Name, *this);
148}
149
150types::ID ToolChain::LookupTypeForExtension(const char *Ext) const {
151  return types::lookupTypeForExtension(Ext);
152}
153
154bool ToolChain::HasNativeLLVMSupport() const {
155  return false;
156}
157
158bool ToolChain::isCrossCompiling() const {
159  llvm::Triple HostTriple(LLVM_HOST_TRIPLE);
160  switch (HostTriple.getArch()) {
161  // The A32/T32/T16 instruction sets are not separate architectures in this
162  // context.
163  case llvm::Triple::arm:
164  case llvm::Triple::armeb:
165  case llvm::Triple::thumb:
166  case llvm::Triple::thumbeb:
167    return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb &&
168           getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb;
169  default:
170    return HostTriple.getArch() != getArch();
171  }
172}
173
174ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
175  return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,
176                     VersionTuple());
177}
178
179std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
180                                         types::ID InputType) const {
181  switch (getTriple().getArch()) {
182  default:
183    return getTripleString();
184
185  case llvm::Triple::x86_64: {
186    llvm::Triple Triple = getTriple();
187    if (!Triple.isOSBinFormatMachO())
188      return getTripleString();
189
190    if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
191      // x86_64h goes in the triple. Other -march options just use the
192      // vanilla triple we already have.
193      StringRef MArch = A->getValue();
194      if (MArch == "x86_64h")
195        Triple.setArchName(MArch);
196    }
197    return Triple.getTriple();
198  }
199  case llvm::Triple::arm:
200  case llvm::Triple::armeb:
201  case llvm::Triple::thumb:
202  case llvm::Triple::thumbeb: {
203    // FIXME: Factor into subclasses.
204    llvm::Triple Triple = getTriple();
205    bool IsBigEndian = getTriple().getArch() == llvm::Triple::armeb ||
206                       getTriple().getArch() == llvm::Triple::thumbeb;
207
208    // Thumb2 is the default for V7 on Darwin.
209    //
210    // FIXME: Thumb should just be another -target-feaure, not in the triple.
211    StringRef Suffix = Triple.isOSBinFormatMachO()
212      ? tools::arm::getLLVMArchSuffixForARM(tools::arm::getARMCPUForMArch(Args, Triple))
213      : tools::arm::getLLVMArchSuffixForARM(tools::arm::getARMTargetCPU(Args, Triple));
214    bool ThumbDefault = Suffix.startswith("v6m") || Suffix.startswith("v7m") ||
215      Suffix.startswith("v7em") ||
216      (Suffix.startswith("v7") && getTriple().isOSBinFormatMachO());
217    std::string ArchName;
218    if (IsBigEndian)
219      ArchName = "armeb";
220    else
221      ArchName = "arm";
222
223    // Assembly files should start in ARM mode.
224    if (InputType != types::TY_PP_Asm &&
225        Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
226    {
227      if (IsBigEndian)
228        ArchName = "thumbeb";
229      else
230        ArchName = "thumb";
231    }
232    Triple.setArchName(ArchName + Suffix.str());
233
234    return Triple.getTriple();
235  }
236  }
237}
238
239std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
240                                                   types::ID InputType) const {
241  return ComputeLLVMTriple(Args, InputType);
242}
243
244void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
245                                          ArgStringList &CC1Args) const {
246  // Each toolchain should provide the appropriate include flags.
247}
248
249void ToolChain::addClangTargetOptions(const ArgList &DriverArgs,
250                                      ArgStringList &CC1Args) const {
251}
252
253void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
254
255ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
256  const ArgList &Args) const
257{
258  if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) {
259    StringRef Value = A->getValue();
260    if (Value == "compiler-rt")
261      return ToolChain::RLT_CompilerRT;
262    if (Value == "libgcc")
263      return ToolChain::RLT_Libgcc;
264    getDriver().Diag(diag::err_drv_invalid_rtlib_name)
265      << A->getAsString(Args);
266  }
267
268  return GetDefaultRuntimeLibType();
269}
270
271ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
272  if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
273    StringRef Value = A->getValue();
274    if (Value == "libc++")
275      return ToolChain::CST_Libcxx;
276    if (Value == "libstdc++")
277      return ToolChain::CST_Libstdcxx;
278    getDriver().Diag(diag::err_drv_invalid_stdlib_name)
279      << A->getAsString(Args);
280  }
281
282  return ToolChain::CST_Libstdcxx;
283}
284
285/// \brief Utility function to add a system include directory to CC1 arguments.
286/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
287                                            ArgStringList &CC1Args,
288                                            const Twine &Path) {
289  CC1Args.push_back("-internal-isystem");
290  CC1Args.push_back(DriverArgs.MakeArgString(Path));
291}
292
293/// \brief Utility function to add a system include directory with extern "C"
294/// semantics to CC1 arguments.
295///
296/// Note that this should be used rarely, and only for directories that
297/// historically and for legacy reasons are treated as having implicit extern
298/// "C" semantics. These semantics are *ignored* by and large today, but its
299/// important to preserve the preprocessor changes resulting from the
300/// classification.
301/*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs,
302                                                   ArgStringList &CC1Args,
303                                                   const Twine &Path) {
304  CC1Args.push_back("-internal-externc-isystem");
305  CC1Args.push_back(DriverArgs.MakeArgString(Path));
306}
307
308void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
309                                                ArgStringList &CC1Args,
310                                                const Twine &Path) {
311  if (llvm::sys::fs::exists(Path))
312    addExternCSystemInclude(DriverArgs, CC1Args, Path);
313}
314
315/// \brief Utility function to add a list of system include directories to CC1.
316/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
317                                             ArgStringList &CC1Args,
318                                             ArrayRef<StringRef> Paths) {
319  for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end();
320       I != E; ++I) {
321    CC1Args.push_back("-internal-isystem");
322    CC1Args.push_back(DriverArgs.MakeArgString(*I));
323  }
324}
325
326void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
327                                             ArgStringList &CC1Args) const {
328  // Header search paths should be handled by each of the subclasses.
329  // Historically, they have not been, and instead have been handled inside of
330  // the CC1-layer frontend. As the logic is hoisted out, this generic function
331  // will slowly stop being called.
332  //
333  // While it is being called, replicate a bit of a hack to propagate the
334  // '-stdlib=' flag down to CC1 so that it can in turn customize the C++
335  // header search paths with it. Once all systems are overriding this
336  // function, the CC1 flag and this line can be removed.
337  DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
338}
339
340void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
341                                    ArgStringList &CmdArgs) const {
342  CXXStdlibType Type = GetCXXStdlibType(Args);
343
344  switch (Type) {
345  case ToolChain::CST_Libcxx:
346    CmdArgs.push_back("-lc++");
347    break;
348
349  case ToolChain::CST_Libstdcxx:
350    CmdArgs.push_back("-lstdc++");
351    break;
352  }
353}
354
355void ToolChain::AddCCKextLibArgs(const ArgList &Args,
356                                 ArgStringList &CmdArgs) const {
357  CmdArgs.push_back("-lcc_kext");
358}
359
360bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args,
361                                              ArgStringList &CmdArgs) const {
362  // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed
363  // (to keep the linker options consistent with gcc and clang itself).
364  if (!isOptimizationLevelFast(Args)) {
365    // Check if -ffast-math or -funsafe-math.
366    Arg *A =
367        Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math,
368                        options::OPT_funsafe_math_optimizations,
369                        options::OPT_fno_unsafe_math_optimizations);
370
371    if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
372        A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
373      return false;
374  }
375  // If crtfastmath.o exists add it to the arguments.
376  std::string Path = GetFilePath("crtfastmath.o");
377  if (Path == "crtfastmath.o") // Not found.
378    return false;
379
380  CmdArgs.push_back(Args.MakeArgString(Path));
381  return true;
382}
383