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