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