xref: /openbsd-src/gnu/llvm/clang/lib/Driver/ToolChains/NaCl.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===--- NaCl.cpp - Native Client ToolChain Implementations -----*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick 
9e5dd7070Spatrick #include "NaCl.h"
10e5dd7070Spatrick #include "CommonArgs.h"
11e5dd7070Spatrick #include "clang/Driver/Compilation.h"
12e5dd7070Spatrick #include "clang/Driver/Driver.h"
13e5dd7070Spatrick #include "clang/Driver/DriverDiagnostic.h"
14a9ac8606Spatrick #include "clang/Driver/InputInfo.h"
15e5dd7070Spatrick #include "clang/Driver/Options.h"
16e5dd7070Spatrick #include "llvm/Option/ArgList.h"
17e5dd7070Spatrick #include "llvm/Support/Path.h"
18e5dd7070Spatrick 
19e5dd7070Spatrick using namespace clang::driver;
20e5dd7070Spatrick using namespace clang::driver::tools;
21e5dd7070Spatrick using namespace clang::driver::toolchains;
22e5dd7070Spatrick using namespace clang;
23e5dd7070Spatrick using namespace llvm::opt;
24e5dd7070Spatrick 
25e5dd7070Spatrick // NaCl ARM assembly (inline or standalone) can be written with a set of macros
26e5dd7070Spatrick // for the various SFI requirements like register masking. The assembly tool
27e5dd7070Spatrick // inserts the file containing the macros as an input into all the assembly
28e5dd7070Spatrick // jobs.
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const29e5dd7070Spatrick void nacltools::AssemblerARM::ConstructJob(Compilation &C, const JobAction &JA,
30e5dd7070Spatrick                                            const InputInfo &Output,
31e5dd7070Spatrick                                            const InputInfoList &Inputs,
32e5dd7070Spatrick                                            const ArgList &Args,
33e5dd7070Spatrick                                            const char *LinkingOutput) const {
34e5dd7070Spatrick   const toolchains::NaClToolChain &ToolChain =
35e5dd7070Spatrick       static_cast<const toolchains::NaClToolChain &>(getToolChain());
36e5dd7070Spatrick   InputInfo NaClMacros(types::TY_PP_Asm, ToolChain.GetNaClArmMacrosPath(),
37e5dd7070Spatrick                        "nacl-arm-macros.s");
38e5dd7070Spatrick   InputInfoList NewInputs;
39e5dd7070Spatrick   NewInputs.push_back(NaClMacros);
40e5dd7070Spatrick   NewInputs.append(Inputs.begin(), Inputs.end());
41e5dd7070Spatrick   gnutools::Assembler::ConstructJob(C, JA, Output, NewInputs, Args,
42e5dd7070Spatrick                                     LinkingOutput);
43e5dd7070Spatrick }
44e5dd7070Spatrick 
45e5dd7070Spatrick // This is quite similar to gnutools::Linker::ConstructJob with changes that
46e5dd7070Spatrick // we use static by default, do not yet support sanitizers or LTO, and a few
47e5dd7070Spatrick // others. Eventually we can support more of that and hopefully migrate back
48e5dd7070Spatrick // to gnutools::Linker.
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const49e5dd7070Spatrick void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
50e5dd7070Spatrick                                      const InputInfo &Output,
51e5dd7070Spatrick                                      const InputInfoList &Inputs,
52e5dd7070Spatrick                                      const ArgList &Args,
53e5dd7070Spatrick                                      const char *LinkingOutput) const {
54e5dd7070Spatrick 
55e5dd7070Spatrick   const toolchains::NaClToolChain &ToolChain =
56e5dd7070Spatrick       static_cast<const toolchains::NaClToolChain &>(getToolChain());
57e5dd7070Spatrick   const Driver &D = ToolChain.getDriver();
58e5dd7070Spatrick   const llvm::Triple::ArchType Arch = ToolChain.getArch();
59e5dd7070Spatrick   const bool IsStatic =
60e5dd7070Spatrick       !Args.hasArg(options::OPT_dynamic) && !Args.hasArg(options::OPT_shared);
61e5dd7070Spatrick 
62e5dd7070Spatrick   ArgStringList CmdArgs;
63e5dd7070Spatrick 
64e5dd7070Spatrick   // Silence warning for "clang -g foo.o -o foo"
65e5dd7070Spatrick   Args.ClaimAllArgs(options::OPT_g_Group);
66e5dd7070Spatrick   // and "clang -emit-llvm foo.o -o foo"
67e5dd7070Spatrick   Args.ClaimAllArgs(options::OPT_emit_llvm);
68e5dd7070Spatrick   // and for "clang -w foo.o -o foo". Other warning options are already
69e5dd7070Spatrick   // handled somewhere else.
70e5dd7070Spatrick   Args.ClaimAllArgs(options::OPT_w);
71e5dd7070Spatrick 
72e5dd7070Spatrick   if (!D.SysRoot.empty())
73e5dd7070Spatrick     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
74e5dd7070Spatrick 
75e5dd7070Spatrick   if (Args.hasArg(options::OPT_rdynamic))
76e5dd7070Spatrick     CmdArgs.push_back("-export-dynamic");
77e5dd7070Spatrick 
78e5dd7070Spatrick   if (Args.hasArg(options::OPT_s))
79e5dd7070Spatrick     CmdArgs.push_back("-s");
80e5dd7070Spatrick 
81e5dd7070Spatrick   // NaClToolChain doesn't have ExtraOpts like Linux; the only relevant flag
82e5dd7070Spatrick   // from there is --build-id, which we do want.
83e5dd7070Spatrick   CmdArgs.push_back("--build-id");
84e5dd7070Spatrick 
85e5dd7070Spatrick   if (!IsStatic)
86e5dd7070Spatrick     CmdArgs.push_back("--eh-frame-hdr");
87e5dd7070Spatrick 
88e5dd7070Spatrick   CmdArgs.push_back("-m");
89e5dd7070Spatrick   if (Arch == llvm::Triple::x86)
90e5dd7070Spatrick     CmdArgs.push_back("elf_i386_nacl");
91e5dd7070Spatrick   else if (Arch == llvm::Triple::arm)
92e5dd7070Spatrick     CmdArgs.push_back("armelf_nacl");
93e5dd7070Spatrick   else if (Arch == llvm::Triple::x86_64)
94e5dd7070Spatrick     CmdArgs.push_back("elf_x86_64_nacl");
95e5dd7070Spatrick   else if (Arch == llvm::Triple::mipsel)
96e5dd7070Spatrick     CmdArgs.push_back("mipselelf_nacl");
97e5dd7070Spatrick   else
98e5dd7070Spatrick     D.Diag(diag::err_target_unsupported_arch) << ToolChain.getArchName()
99e5dd7070Spatrick                                               << "Native Client";
100e5dd7070Spatrick 
101e5dd7070Spatrick   if (IsStatic)
102e5dd7070Spatrick     CmdArgs.push_back("-static");
103e5dd7070Spatrick   else if (Args.hasArg(options::OPT_shared))
104e5dd7070Spatrick     CmdArgs.push_back("-shared");
105e5dd7070Spatrick 
106e5dd7070Spatrick   CmdArgs.push_back("-o");
107e5dd7070Spatrick   CmdArgs.push_back(Output.getFilename());
108e5dd7070Spatrick   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
109e5dd7070Spatrick     if (!Args.hasArg(options::OPT_shared))
110e5dd7070Spatrick       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));
111e5dd7070Spatrick     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
112e5dd7070Spatrick 
113e5dd7070Spatrick     const char *crtbegin;
114e5dd7070Spatrick     if (IsStatic)
115e5dd7070Spatrick       crtbegin = "crtbeginT.o";
116e5dd7070Spatrick     else if (Args.hasArg(options::OPT_shared))
117e5dd7070Spatrick       crtbegin = "crtbeginS.o";
118e5dd7070Spatrick     else
119e5dd7070Spatrick       crtbegin = "crtbegin.o";
120e5dd7070Spatrick     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
121e5dd7070Spatrick   }
122e5dd7070Spatrick 
123e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_L);
124e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_u);
125e5dd7070Spatrick 
126e5dd7070Spatrick   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
127e5dd7070Spatrick 
128e5dd7070Spatrick   if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
129e5dd7070Spatrick     CmdArgs.push_back("--no-demangle");
130e5dd7070Spatrick 
131e5dd7070Spatrick   AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
132e5dd7070Spatrick 
133e5dd7070Spatrick   if (D.CCCIsCXX() &&
134e5dd7070Spatrick       !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
135e5dd7070Spatrick     if (ToolChain.ShouldLinkCXXStdlib(Args)) {
136e5dd7070Spatrick       bool OnlyLibstdcxxStatic =
137e5dd7070Spatrick           Args.hasArg(options::OPT_static_libstdcxx) && !IsStatic;
138e5dd7070Spatrick       if (OnlyLibstdcxxStatic)
139e5dd7070Spatrick         CmdArgs.push_back("-Bstatic");
140e5dd7070Spatrick       ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
141e5dd7070Spatrick       if (OnlyLibstdcxxStatic)
142e5dd7070Spatrick         CmdArgs.push_back("-Bdynamic");
143e5dd7070Spatrick     }
144e5dd7070Spatrick     CmdArgs.push_back("-lm");
145e5dd7070Spatrick   }
146e5dd7070Spatrick 
147e5dd7070Spatrick   if (!Args.hasArg(options::OPT_nostdlib)) {
148e5dd7070Spatrick     if (!Args.hasArg(options::OPT_nodefaultlibs)) {
149e5dd7070Spatrick       // Always use groups, since it has no effect on dynamic libraries.
150e5dd7070Spatrick       CmdArgs.push_back("--start-group");
151e5dd7070Spatrick       CmdArgs.push_back("-lc");
152e5dd7070Spatrick       // NaCl's libc++ currently requires libpthread, so just always include it
153e5dd7070Spatrick       // in the group for C++.
154e5dd7070Spatrick       if (Args.hasArg(options::OPT_pthread) ||
155e5dd7070Spatrick           Args.hasArg(options::OPT_pthreads) || D.CCCIsCXX()) {
156e5dd7070Spatrick         // Gold, used by Mips, handles nested groups differently than ld, and
157e5dd7070Spatrick         // without '-lnacl' it prefers symbols from libpthread.a over libnacl.a,
158e5dd7070Spatrick         // which is not a desired behaviour here.
159e5dd7070Spatrick         // See https://sourceware.org/ml/binutils/2015-03/msg00034.html
160e5dd7070Spatrick         if (getToolChain().getArch() == llvm::Triple::mipsel)
161e5dd7070Spatrick           CmdArgs.push_back("-lnacl");
162e5dd7070Spatrick 
163e5dd7070Spatrick         CmdArgs.push_back("-lpthread");
164e5dd7070Spatrick       }
165e5dd7070Spatrick 
166e5dd7070Spatrick       CmdArgs.push_back("-lgcc");
167e5dd7070Spatrick       CmdArgs.push_back("--as-needed");
168e5dd7070Spatrick       if (IsStatic)
169e5dd7070Spatrick         CmdArgs.push_back("-lgcc_eh");
170e5dd7070Spatrick       else
171e5dd7070Spatrick         CmdArgs.push_back("-lgcc_s");
172e5dd7070Spatrick       CmdArgs.push_back("--no-as-needed");
173e5dd7070Spatrick 
174e5dd7070Spatrick       // Mips needs to create and use pnacl_legacy library that contains
175e5dd7070Spatrick       // definitions from bitcode/pnaclmm.c and definitions for
176e5dd7070Spatrick       // __nacl_tp_tls_offset() and __nacl_tp_tdb_offset().
177e5dd7070Spatrick       if (getToolChain().getArch() == llvm::Triple::mipsel)
178e5dd7070Spatrick         CmdArgs.push_back("-lpnacl_legacy");
179e5dd7070Spatrick 
180e5dd7070Spatrick       CmdArgs.push_back("--end-group");
181e5dd7070Spatrick     }
182e5dd7070Spatrick 
183e5dd7070Spatrick     if (!Args.hasArg(options::OPT_nostartfiles)) {
184e5dd7070Spatrick       const char *crtend;
185e5dd7070Spatrick       if (Args.hasArg(options::OPT_shared))
186e5dd7070Spatrick         crtend = "crtendS.o";
187e5dd7070Spatrick       else
188e5dd7070Spatrick         crtend = "crtend.o";
189e5dd7070Spatrick 
190e5dd7070Spatrick       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
191e5dd7070Spatrick       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
192e5dd7070Spatrick     }
193e5dd7070Spatrick   }
194e5dd7070Spatrick 
195e5dd7070Spatrick   const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
196a9ac8606Spatrick   C.addCommand(std::make_unique<Command>(JA, *this,
197a9ac8606Spatrick                                          ResponseFileSupport::AtFileCurCP(),
198a9ac8606Spatrick                                          Exec, CmdArgs, Inputs, Output));
199e5dd7070Spatrick }
200e5dd7070Spatrick 
201e5dd7070Spatrick /// NaCl Toolchain
NaClToolChain(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)202e5dd7070Spatrick NaClToolChain::NaClToolChain(const Driver &D, const llvm::Triple &Triple,
203e5dd7070Spatrick                              const ArgList &Args)
204e5dd7070Spatrick     : Generic_ELF(D, Triple, Args) {
205e5dd7070Spatrick 
206e5dd7070Spatrick   // Remove paths added by Generic_GCC. NaCl Toolchain cannot use the
207e5dd7070Spatrick   // default paths, and must instead only use the paths provided
208e5dd7070Spatrick   // with this toolchain based on architecture.
209e5dd7070Spatrick   path_list &file_paths = getFilePaths();
210e5dd7070Spatrick   path_list &prog_paths = getProgramPaths();
211e5dd7070Spatrick 
212e5dd7070Spatrick   file_paths.clear();
213e5dd7070Spatrick   prog_paths.clear();
214e5dd7070Spatrick 
215e5dd7070Spatrick   // Path for library files (libc.a, ...)
216e5dd7070Spatrick   std::string FilePath(getDriver().Dir + "/../");
217e5dd7070Spatrick 
218e5dd7070Spatrick   // Path for tools (clang, ld, etc..)
219e5dd7070Spatrick   std::string ProgPath(getDriver().Dir + "/../");
220e5dd7070Spatrick 
221e5dd7070Spatrick   // Path for toolchain libraries (libgcc.a, ...)
222e5dd7070Spatrick   std::string ToolPath(getDriver().ResourceDir + "/lib/");
223e5dd7070Spatrick 
224e5dd7070Spatrick   switch (Triple.getArch()) {
225e5dd7070Spatrick   case llvm::Triple::x86:
226e5dd7070Spatrick     file_paths.push_back(FilePath + "x86_64-nacl/lib32");
227e5dd7070Spatrick     file_paths.push_back(FilePath + "i686-nacl/usr/lib");
228e5dd7070Spatrick     prog_paths.push_back(ProgPath + "x86_64-nacl/bin");
229e5dd7070Spatrick     file_paths.push_back(ToolPath + "i686-nacl");
230e5dd7070Spatrick     break;
231e5dd7070Spatrick   case llvm::Triple::x86_64:
232e5dd7070Spatrick     file_paths.push_back(FilePath + "x86_64-nacl/lib");
233e5dd7070Spatrick     file_paths.push_back(FilePath + "x86_64-nacl/usr/lib");
234e5dd7070Spatrick     prog_paths.push_back(ProgPath + "x86_64-nacl/bin");
235e5dd7070Spatrick     file_paths.push_back(ToolPath + "x86_64-nacl");
236e5dd7070Spatrick     break;
237e5dd7070Spatrick   case llvm::Triple::arm:
238e5dd7070Spatrick     file_paths.push_back(FilePath + "arm-nacl/lib");
239e5dd7070Spatrick     file_paths.push_back(FilePath + "arm-nacl/usr/lib");
240e5dd7070Spatrick     prog_paths.push_back(ProgPath + "arm-nacl/bin");
241e5dd7070Spatrick     file_paths.push_back(ToolPath + "arm-nacl");
242e5dd7070Spatrick     break;
243e5dd7070Spatrick   case llvm::Triple::mipsel:
244e5dd7070Spatrick     file_paths.push_back(FilePath + "mipsel-nacl/lib");
245e5dd7070Spatrick     file_paths.push_back(FilePath + "mipsel-nacl/usr/lib");
246e5dd7070Spatrick     prog_paths.push_back(ProgPath + "bin");
247e5dd7070Spatrick     file_paths.push_back(ToolPath + "mipsel-nacl");
248e5dd7070Spatrick     break;
249e5dd7070Spatrick   default:
250e5dd7070Spatrick     break;
251e5dd7070Spatrick   }
252e5dd7070Spatrick 
253e5dd7070Spatrick   NaClArmMacrosPath = GetFilePath("nacl-arm-macros.s");
254e5dd7070Spatrick }
255e5dd7070Spatrick 
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const256e5dd7070Spatrick void NaClToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
257e5dd7070Spatrick                                               ArgStringList &CC1Args) const {
258e5dd7070Spatrick   const Driver &D = getDriver();
259e5dd7070Spatrick   if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
260e5dd7070Spatrick     return;
261e5dd7070Spatrick 
262e5dd7070Spatrick   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
263e5dd7070Spatrick     SmallString<128> P(D.ResourceDir);
264e5dd7070Spatrick     llvm::sys::path::append(P, "include");
265e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args, P.str());
266e5dd7070Spatrick   }
267e5dd7070Spatrick 
268e5dd7070Spatrick   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
269e5dd7070Spatrick     return;
270e5dd7070Spatrick 
271e5dd7070Spatrick   SmallString<128> P(D.Dir + "/../");
272e5dd7070Spatrick   switch (getTriple().getArch()) {
273e5dd7070Spatrick   case llvm::Triple::x86:
274e5dd7070Spatrick     // x86 is special because multilib style uses x86_64-nacl/include for libc
275e5dd7070Spatrick     // headers but the SDK wants i686-nacl/usr/include. The other architectures
276e5dd7070Spatrick     // have the same substring.
277e5dd7070Spatrick     llvm::sys::path::append(P, "i686-nacl/usr/include");
278e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args, P.str());
279e5dd7070Spatrick     llvm::sys::path::remove_filename(P);
280e5dd7070Spatrick     llvm::sys::path::remove_filename(P);
281e5dd7070Spatrick     llvm::sys::path::remove_filename(P);
282e5dd7070Spatrick     llvm::sys::path::append(P, "x86_64-nacl/include");
283e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args, P.str());
284e5dd7070Spatrick     return;
285e5dd7070Spatrick   case llvm::Triple::arm:
286e5dd7070Spatrick     llvm::sys::path::append(P, "arm-nacl/usr/include");
287e5dd7070Spatrick     break;
288e5dd7070Spatrick   case llvm::Triple::x86_64:
289e5dd7070Spatrick     llvm::sys::path::append(P, "x86_64-nacl/usr/include");
290e5dd7070Spatrick     break;
291e5dd7070Spatrick   case llvm::Triple::mipsel:
292e5dd7070Spatrick     llvm::sys::path::append(P, "mipsel-nacl/usr/include");
293e5dd7070Spatrick     break;
294e5dd7070Spatrick   default:
295e5dd7070Spatrick     return;
296e5dd7070Spatrick   }
297e5dd7070Spatrick 
298e5dd7070Spatrick   addSystemInclude(DriverArgs, CC1Args, P.str());
299e5dd7070Spatrick   llvm::sys::path::remove_filename(P);
300e5dd7070Spatrick   llvm::sys::path::remove_filename(P);
301e5dd7070Spatrick   llvm::sys::path::append(P, "include");
302e5dd7070Spatrick   addSystemInclude(DriverArgs, CC1Args, P.str());
303e5dd7070Spatrick }
304e5dd7070Spatrick 
AddCXXStdlibLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const305e5dd7070Spatrick void NaClToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
306e5dd7070Spatrick                                         ArgStringList &CmdArgs) const {
307e5dd7070Spatrick   // Check for -stdlib= flags. We only support libc++ but this consumes the arg
308e5dd7070Spatrick   // if the value is libc++, and emits an error for other values.
309e5dd7070Spatrick   GetCXXStdlibType(Args);
310e5dd7070Spatrick   CmdArgs.push_back("-lc++");
311*12c85518Srobert   if (Args.hasArg(options::OPT_fexperimental_library))
312*12c85518Srobert     CmdArgs.push_back("-lc++experimental");
313e5dd7070Spatrick }
314e5dd7070Spatrick 
addLibCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const315e5dd7070Spatrick void NaClToolChain::addLibCxxIncludePaths(
316e5dd7070Spatrick     const llvm::opt::ArgList &DriverArgs,
317e5dd7070Spatrick     llvm::opt::ArgStringList &CC1Args) const {
318e5dd7070Spatrick   const Driver &D = getDriver();
319e5dd7070Spatrick 
320e5dd7070Spatrick   SmallString<128> P(D.Dir + "/../");
321e5dd7070Spatrick   switch (getTriple().getArch()) {
322e5dd7070Spatrick   default:
323e5dd7070Spatrick     break;
324e5dd7070Spatrick   case llvm::Triple::arm:
325e5dd7070Spatrick     llvm::sys::path::append(P, "arm-nacl/include/c++/v1");
326e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args, P.str());
327e5dd7070Spatrick     break;
328e5dd7070Spatrick   case llvm::Triple::x86:
329e5dd7070Spatrick     llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1");
330e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args, P.str());
331e5dd7070Spatrick     break;
332e5dd7070Spatrick   case llvm::Triple::x86_64:
333e5dd7070Spatrick     llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1");
334e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args, P.str());
335e5dd7070Spatrick     break;
336e5dd7070Spatrick   case llvm::Triple::mipsel:
337e5dd7070Spatrick     llvm::sys::path::append(P, "mipsel-nacl/include/c++/v1");
338e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args, P.str());
339e5dd7070Spatrick     break;
340e5dd7070Spatrick   }
341e5dd7070Spatrick }
342e5dd7070Spatrick 
343e5dd7070Spatrick ToolChain::CXXStdlibType
GetCXXStdlibType(const ArgList & Args) const344e5dd7070Spatrick NaClToolChain::GetCXXStdlibType(const ArgList &Args) const {
345e5dd7070Spatrick   if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
346e5dd7070Spatrick     StringRef Value = A->getValue();
347e5dd7070Spatrick     if (Value == "libc++")
348e5dd7070Spatrick       return ToolChain::CST_Libcxx;
349e5dd7070Spatrick     getDriver().Diag(clang::diag::err_drv_invalid_stdlib_name)
350e5dd7070Spatrick         << A->getAsString(Args);
351e5dd7070Spatrick   }
352e5dd7070Spatrick 
353e5dd7070Spatrick   return ToolChain::CST_Libcxx;
354e5dd7070Spatrick }
355e5dd7070Spatrick 
356e5dd7070Spatrick std::string
ComputeEffectiveClangTriple(const ArgList & Args,types::ID InputType) const357e5dd7070Spatrick NaClToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
358e5dd7070Spatrick                                            types::ID InputType) const {
359e5dd7070Spatrick   llvm::Triple TheTriple(ComputeLLVMTriple(Args, InputType));
360e5dd7070Spatrick   if (TheTriple.getArch() == llvm::Triple::arm &&
361e5dd7070Spatrick       TheTriple.getEnvironment() == llvm::Triple::UnknownEnvironment)
362e5dd7070Spatrick     TheTriple.setEnvironment(llvm::Triple::GNUEABIHF);
363e5dd7070Spatrick   return TheTriple.getTriple();
364e5dd7070Spatrick }
365e5dd7070Spatrick 
buildLinker() const366e5dd7070Spatrick Tool *NaClToolChain::buildLinker() const {
367e5dd7070Spatrick   return new tools::nacltools::Linker(*this);
368e5dd7070Spatrick }
369e5dd7070Spatrick 
buildAssembler() const370e5dd7070Spatrick Tool *NaClToolChain::buildAssembler() const {
371e5dd7070Spatrick   if (getTriple().getArch() == llvm::Triple::arm)
372e5dd7070Spatrick     return new tools::nacltools::AssemblerARM(*this);
373e5dd7070Spatrick   return new tools::gnutools::Assembler(*this);
374e5dd7070Spatrick }
375