Index: cfe/trunk/lib/Basic/Targets.cpp =================================================================== --- cfe/trunk/lib/Basic/Targets.cpp +++ cfe/trunk/lib/Basic/Targets.cpp @@ -713,8 +713,7 @@ // RegParmMax is inherited from the underlying architecture this->LongDoubleFormat = &llvm::APFloat::IEEEdouble; if (Triple.getArch() == llvm::Triple::arm) { - this->DescriptionString = - "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128"; + // Handled in ARM's setABI(). } else if (Triple.getArch() == llvm::Triple::x86) { this->DescriptionString = "e-m:e-p:32:32-i64:64-n8:16:32-S128"; } else if (Triple.getArch() == llvm::Triple::x86_64) { @@ -3897,6 +3896,9 @@ "-a:0:32" "-n32" "-S64"; + } else if (T.isOSNaCl()) { + assert(!BigEndian && "NaCl on ARM does not support big endian"); + DescriptionString = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128"; } else { DescriptionString = BigEndian ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" Index: cfe/trunk/lib/Driver/Driver.cpp =================================================================== --- cfe/trunk/lib/Driver/Driver.cpp +++ cfe/trunk/lib/Driver/Driver.cpp @@ -2062,6 +2062,9 @@ else TC = new toolchains::Linux(*this, Target, Args); break; + case llvm::Triple::NaCl: + TC = new toolchains::NaCl_TC(*this, Target, Args); + break; case llvm::Triple::Solaris: TC = new toolchains::Solaris(*this, Target, Args); break; Index: cfe/trunk/lib/Driver/ToolChains.h =================================================================== --- cfe/trunk/lib/Driver/ToolChains.h +++ cfe/trunk/lib/Driver/ToolChains.h @@ -717,6 +717,45 @@ static StringRef GetTargetCPU(const llvm::opt::ArgList &Args); }; +class LLVM_LIBRARY_VISIBILITY NaCl_TC : public Generic_ELF { +public: + NaCl_TC(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void + AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + + CXXStdlibType + GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; + + void + AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + + bool + IsIntegratedAssemblerDefault() const override { return false; } + + // Get the path to the file containing NaCl's ARM macros. It lives in NaCl_TC + // because the AssembleARM tool needs a const char * that it can pass around + // and the toolchain outlives all the jobs. + const char *GetNaClArmMacrosPath() const { return NaClArmMacrosPath.c_str(); } + + std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args, + types::ID InputType) const override; + std::string Linker; + +protected: + Tool *buildLinker() const override; + Tool *buildAssembler() const override; + +private: + std::string NaClArmMacrosPath; +}; + /// TCEToolChain - A tool chain using the llvm bitcode tools to perform /// all subcommands. See http://tce.cs.tut.fi for our peculiar target. class LLVM_LIBRARY_VISIBILITY TCEToolChain : public ToolChain { Index: cfe/trunk/lib/Driver/ToolChains.cpp =================================================================== --- cfe/trunk/lib/Driver/ToolChains.cpp +++ cfe/trunk/lib/Driver/ToolChains.cpp @@ -2084,7 +2084,8 @@ getTriple().getArch() == llvm::Triple::aarch64_be || (getTriple().getOS() == llvm::Triple::Linux && (!V.isOlderThan(4, 7, 0) || - getTriple().getEnvironment() == llvm::Triple::Android)); + getTriple().getEnvironment() == llvm::Triple::Android)) || + getTriple().getOS() == llvm::Triple::NaCl; if (DriverArgs.hasFlag(options::OPT_fuse_init_array, options::OPT_fno_use_init_array, @@ -2307,6 +2308,159 @@ } // End Hexagon +/// NaCl Toolchain +NaCl_TC::NaCl_TC(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_ELF(D, Triple, Args) { + + // Remove paths added by Generic_GCC. NaCl Toolchain cannot use the + // default paths, and must instead only use the paths provided + // with this toolchain based on architecture. + path_list& file_paths = getFilePaths(); + path_list& prog_paths = getProgramPaths(); + + file_paths.clear(); + prog_paths.clear(); + + // Path for library files (libc.a, ...) + std::string FilePath(getDriver().Dir + "/../"); + + // Path for tools (clang, ld, etc..) + std::string ProgPath(getDriver().Dir + "/../"); + + // Path for toolchain libraries (libgcc.a, ...) + std::string ToolPath(getDriver().ResourceDir + "/lib/"); + + switch(Triple.getArch()) { + case llvm::Triple::x86: { + file_paths.push_back(FilePath + "x86_64-nacl/lib32"); + file_paths.push_back(FilePath + "x86_64-nacl/usr/lib32"); + prog_paths.push_back(ProgPath + "x86_64-nacl/bin"); + file_paths.push_back(ToolPath + "i686-nacl"); + break; + } + case llvm::Triple::x86_64: { + file_paths.push_back(FilePath + "x86_64-nacl/lib"); + file_paths.push_back(FilePath + "x86_64-nacl/usr/lib"); + prog_paths.push_back(ProgPath + "x86_64-nacl/bin"); + file_paths.push_back(ToolPath + "x86_64-nacl"); + break; + } + case llvm::Triple::arm: { + file_paths.push_back(FilePath + "arm-nacl/lib"); + file_paths.push_back(FilePath + "arm-nacl/usr/lib"); + prog_paths.push_back(ProgPath + "arm-nacl/bin"); + file_paths.push_back(ToolPath + "arm-nacl"); + break; + } + default: + break; + } + + // Use provided linker, not system linker + Linker = GetProgramPath("ld"); + NaClArmMacrosPath = GetFilePath("nacl-arm-macros.s"); +} + +void NaCl_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + const Driver &D = getDriver(); + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + SmallString<128> P(D.Dir + "/../"); + if (getTriple().getArch() == llvm::Triple::arm) { + llvm::sys::path::append(P, "arm-nacl/usr/include"); + } else if (getTriple().getArch() == llvm::Triple::x86) { + llvm::sys::path::append(P, "x86_64-nacl/usr/include"); + } else if (getTriple().getArch() == llvm::Triple::x86_64) { + llvm::sys::path::append(P, "x86_64-nacl/usr/include"); + } else { + return; + } + + addSystemInclude(DriverArgs, CC1Args, P.str()); + llvm::sys::path::remove_filename(P); + llvm::sys::path::remove_filename(P); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P.str()); +} + +void NaCl_TC::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + // Check for -stdlib= flags. We only support libc++ but this consumes the arg + // if the value is libc++, and emits an error for other values. + GetCXXStdlibType(Args); + CmdArgs.push_back("-lc++"); +} + +void NaCl_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + const Driver &D = getDriver(); + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + // Check for -stdlib= flags. We only support libc++ but this consumes the arg + // if the value is libc++, and emits an error for other values. + GetCXXStdlibType(DriverArgs); + + if (getTriple().getArch() == llvm::Triple::arm) { + SmallString<128> P(D.Dir + "/../"); + llvm::sys::path::append(P, "arm-nacl/include/c++/v1"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + } else if (getTriple().getArch() == llvm::Triple::x86) { + SmallString<128> P(D.Dir + "/../"); + llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + } else if (getTriple().getArch() == llvm::Triple::x86_64) { + SmallString<128> P(D.Dir + "/../"); + llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + } +} + +ToolChain::CXXStdlibType NaCl_TC::GetCXXStdlibType(const ArgList &Args) const { + if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { + StringRef Value = A->getValue(); + if (Value == "libc++") + return ToolChain::CST_Libcxx; + getDriver().Diag(diag::err_drv_invalid_stdlib_name) + << A->getAsString(Args); + } + + return ToolChain::CST_Libcxx; +} + +std::string NaCl_TC::ComputeEffectiveClangTriple( + const ArgList &Args, types::ID InputType) const { + llvm::Triple TheTriple(ComputeLLVMTriple(Args, InputType)); + if (TheTriple.getArch() == llvm::Triple::arm && + TheTriple.getEnvironment() == llvm::Triple::UnknownEnvironment) + TheTriple.setEnvironment(llvm::Triple::GNUEABIHF); + return TheTriple.getTriple(); +} + +Tool *NaCl_TC::buildLinker() const { + return new tools::nacltools::Link(*this); +} + +Tool *NaCl_TC::buildAssembler() const { + if (getTriple().getArch() == llvm::Triple::arm) + return new tools::nacltools::AssembleARM(*this); + return new tools::gnutools::Assemble(*this); +} +// End NaCl + /// TCEToolChain - A tool chain using the llvm bitcode tools to perform /// all subcommands. See http://tce.cs.tut.fi for our peculiar target. /// Currently does not support anything else but compilation. Index: cfe/trunk/lib/Driver/Tools.h =================================================================== --- cfe/trunk/lib/Driver/Tools.h +++ cfe/trunk/lib/Driver/Tools.h @@ -507,6 +507,33 @@ const char *LinkingOutput) const override; }; } + +namespace nacltools { + class LLVM_LIBRARY_VISIBILITY AssembleARM : public gnutools::Assemble { + public: + AssembleARM(const ToolChain &TC) : gnutools::Assemble(TC) {} + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; + }; + class LLVM_LIBRARY_VISIBILITY Link : public Tool { + public: + Link(const ToolChain &TC) : Tool("NaCl::Link", "linker", TC) {} + + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; + }; +} + /// minix -- Directly call GNU Binutils assembler and linker namespace minix { class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool { Index: cfe/trunk/lib/Driver/Tools.cpp =================================================================== --- cfe/trunk/lib/Driver/Tools.cpp +++ cfe/trunk/lib/Driver/Tools.cpp @@ -7911,6 +7911,172 @@ llvm::make_unique(JA, *this, ToolChain.Linker.c_str(), CmdArgs)); } + +// NaCl ARM assembly (inline or standalone) can be written with a set of macros +// for the various SFI requirements like register masking. The assembly tool +// inserts the file containing the macros as an input into all the assembly +// jobs. +void nacltools::AssembleARM::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const toolchains::NaCl_TC& ToolChain = + static_cast(getToolChain()); + InputInfo NaClMacros(ToolChain.GetNaClArmMacrosPath(), types::TY_PP_Asm, + "nacl-arm-macros.s"); + InputInfoList NewInputs; + NewInputs.push_back(NaClMacros); + NewInputs.append(Inputs.begin(), Inputs.end()); + gnutools::Assemble::ConstructJob(C, JA, Output, NewInputs, Args, + LinkingOutput); +} + + +// This is quite similar to gnutools::link::ConstructJob with changes that +// we use static by default, do not yet support sanitizers or LTO, and a few +// others. Eventually we can support more of that and hopefully migrate back +// to gnutools::link. +void nacltools::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + + const toolchains::NaCl_TC& ToolChain = + static_cast(getToolChain()); + const Driver &D = ToolChain.getDriver(); + const bool IsStatic = + !Args.hasArg(options::OPT_dynamic) && + !Args.hasArg(options::OPT_shared); + + ArgStringList CmdArgs; + + // Silence warning for "clang -g foo.o -o foo" + Args.ClaimAllArgs(options::OPT_g_Group); + // and "clang -emit-llvm foo.o -o foo" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and for "clang -w foo.o -o foo". Other warning options are already + // handled somewhere else. + Args.ClaimAllArgs(options::OPT_w); + + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("-export-dynamic"); + + if (Args.hasArg(options::OPT_s)) + CmdArgs.push_back("-s"); + + // NaCl_TC doesn't have ExtraOpts like Linux; the only relevant flag from + // there is --build-id, which we do want. + CmdArgs.push_back("--build-id"); + + if (!IsStatic) + CmdArgs.push_back("--eh-frame-hdr"); + + CmdArgs.push_back("-m"); + if (ToolChain.getArch() == llvm::Triple::x86) + CmdArgs.push_back("elf_i386_nacl"); + else if (ToolChain.getArch() == llvm::Triple::arm) + CmdArgs.push_back("armelf_nacl"); + else if (ToolChain.getArch() == llvm::Triple::x86_64) + CmdArgs.push_back("elf_x86_64_nacl"); + else + D.Diag(diag::err_target_unsupported_arch) << ToolChain.getArchName() << + "Native Client"; + + + if (IsStatic) + CmdArgs.push_back("-static"); + else if (Args.hasArg(options::OPT_shared)) + CmdArgs.push_back("-shared"); + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_shared)) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); + + const char *crtbegin; + if (IsStatic) + crtbegin = "crtbeginT.o"; + else if (Args.hasArg(options::OPT_shared)) + crtbegin = "crtbeginS.o"; + else + crtbegin = "crtbegin.o"; + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + Args.AddAllArgs(CmdArgs, options::OPT_u); + + const ToolChain::path_list &Paths = ToolChain.getFilePaths(); + + for (const auto &Path : Paths) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); + + if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) + CmdArgs.push_back("--no-demangle"); + + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + + if (D.CCCIsCXX() && + !Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && + !IsStatic; + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bstatic"); + ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bdynamic"); + CmdArgs.push_back("-lm"); + } + + if (!Args.hasArg(options::OPT_nostdlib)) { + if (!Args.hasArg(options::OPT_nodefaultlibs)) { + // Always use groups, since it has no effect on dynamic libraries. + CmdArgs.push_back("--start-group"); + CmdArgs.push_back("-lc"); + // NaCl's libc++ currently requires libpthread, so just always include it + // in the group for C++. + if (Args.hasArg(options::OPT_pthread) || + Args.hasArg(options::OPT_pthreads) || + D.CCCIsCXX()) { + CmdArgs.push_back("-lpthread"); + } + + CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("--as-needed"); + if (IsStatic) + CmdArgs.push_back("-lgcc_eh"); + else + CmdArgs.push_back("-lgcc_s"); + CmdArgs.push_back("--no-as-needed"); + CmdArgs.push_back("--end-group"); + } + + if (!Args.hasArg(options::OPT_nostartfiles)) { + const char *crtend; + if (Args.hasArg(options::OPT_shared)) + crtend = "crtendS.o"; + else + crtend = "crtend.o"; + + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); + } + } + + C.addCommand(llvm::make_unique(JA, *this, + ToolChain.Linker.c_str(), CmdArgs)); +} + + void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, Index: cfe/trunk/lib/Frontend/InitHeaderSearch.cpp =================================================================== --- cfe/trunk/lib/Frontend/InitHeaderSearch.cpp +++ cfe/trunk/lib/Frontend/InitHeaderSearch.cpp @@ -232,6 +232,7 @@ case llvm::Triple::NetBSD: case llvm::Triple::OpenBSD: case llvm::Triple::Bitrig: + case llvm::Triple::NaCl: break; default: // FIXME: temporary hack: hard-coded paths. @@ -352,6 +353,7 @@ switch (os) { case llvm::Triple::CloudABI: case llvm::Triple::RTEMS: + case llvm::Triple::NaCl: break; default: AddPath("/usr/include", ExternCSystem, false); Index: cfe/trunk/test/CodeGen/target-data.c =================================================================== --- cfe/trunk/test/CodeGen/target-data.c +++ cfe/trunk/test/CodeGen/target-data.c @@ -66,7 +66,7 @@ // RUN: FileCheck %s -check-prefix=X86_64-NACL // X86_64-NACL: target datalayout = "e-m:e-p:32:32-i64:64-n8:16:32:64-S128" -// RUN: %clang_cc1 -triple arm-nacl-gnueabi -o - -emit-llvm %s | \ +// RUN: %clang_cc1 -triple arm-nacl -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=ARM-NACL // ARM-NACL: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128" Index: cfe/trunk/test/Driver/nacl-direct.c =================================================================== --- cfe/trunk/test/Driver/nacl-direct.c +++ cfe/trunk/test/Driver/nacl-direct.c @@ -0,0 +1,108 @@ +// Test clang changes for NaCl Support including: +// include paths, library paths, emulation, default static +// +// RUN: %clang -### -o %t.o %s 2>&1 \ +// RUN: -target i686-unknown-nacl \ +// RUN: | FileCheck --check-prefix=CHECK-I686 %s +// CHECK-I686: {{.*}}clang{{.*}}" "-cc1" +// CHECK-I686: "-fuse-init-array" +// CHECK-I686: "-target-cpu" "pentium4" +// CHECK-I686: "-resource-dir" "{{.*}}/lib/clang/[[VER:[0-9.]+]]" +// CHECK-I686: "-internal-isystem" "{{.*}}/../lib/clang/[[VER]]/include" +// CHECK-I686: "-internal-isystem" "{{.*}}/../x86_64-nacl/usr/include" +// CHECK-I686: "-internal-isystem" "{{.*}}/../x86_64-nacl/include" +// CHECK-I686: /as" "--32" +// CHECK-I686: /ld" +// CHECK-I686: "--build-id" +// CHECK-I686: "-m" "elf_i386_nacl" +// CHECK-I686: "-static" +// CHECK-I686: "-L{{.*}}/../x86_64-nacl/lib32" +// CHECK-I686: "-L{{.*}}/../x86_64-nacl/usr/lib32" +// CHECK-I686: "-L{{.*}}/../lib/clang/[[VER]]/lib/i686-nacl" +// CHECK-I686-NOT: -lpthread +// +// RUN: %clang -### -o %t.o %s 2>&1 \ +// RUN: -target x86_64-unknown-nacl \ +// RUN: | FileCheck --check-prefix=CHECK-x86_64 %s +// CHECK-x86_64: {{.*}}clang{{.*}}" "-cc1" +// CHECK-x86_64: "-fuse-init-array" +// CHECK-x86_64: "-target-cpu" "x86-64" +// CHECK-x86_64: "-resource-dir" "{{.*}}/lib/clang/[[VER:[0-9.]+]]" +// CHECK-x86_64: "-internal-isystem" "{{.*}}/../lib/clang/[[VER]]/include" +// CHECK-x86_64: "-internal-isystem" "{{.*}}/../x86_64-nacl/usr/include" +// CHECK-x86_64: "-internal-isystem" "{{.*}}/../x86_64-nacl/include" +// CHECK-x86_64: /as" "--64" +// CHECK-x86_64: /ld" +// CHECK-x86_64: "--build-id" +// CHECK-x86_64: "-m" "elf_x86_64_nacl" +// CHECK-x86_64: "-static" +// CHECK-x86_64: "-L{{.*}}/../x86_64-nacl/lib" +// CHECK-x86_64: "-L{{.*}}/../x86_64-nacl/usr/lib" +// CHECK-x86_64: "-L{{.*}}/../lib/clang/[[VER]]/lib/x86_64-nacl" +// CHECK-X86_64-NOT: -lpthread +// +// RUN: %clang -### -o %t.o %s 2>&1 \ +// RUN: -target armv7a-unknown-nacl-gnueabihf \ +// RUN: | FileCheck --check-prefix=CHECK-ARM %s +// CHECK-ARM: {{.*}}clang{{.*}}" "-cc1" +// CHECK-ARM: "-fuse-init-array" +// CHECK-ARM: "-target-cpu" "cortex-a8" +// CHECK-ARM: "-target-abi" "aapcs-linux" +// CHECK-ARM: "-mfloat-abi" "hard" +// CHECK-ARM: "-resource-dir" "{{.*}}/lib/clang/[[VER:[0-9.]+]]" +// CHECK-ARM: "-internal-isystem" "{{.*}}/../lib/clang/[[VER]]/include" +// CHECK-ARM: "-internal-isystem" "{{.*}}/../arm-nacl/usr/include" +// CHECK-ARM: "-internal-isystem" "{{.*}}/../arm-nacl/include" +// CHECK-ARM: /as" +// CHECK-ARM: /ld" +// CHECK-ARM: "--build-id" +// CHECK-ARM: "-m" "armelf_nacl" +// CHECK-ARM: "-static" +// CHECK-ARM: "-L{{.*}}/../arm-nacl/lib" +// CHECK-ARM: "-L{{.*}}/../arm-nacl/usr/lib" +// CHECK-ARM: "-L{{.*}}/../lib/clang/[[VER]]/lib/arm-nacl" +// CHECK-ARM-NOT: -lpthread + +// Check that even when the target arch is just "arm" (as will be the case when +// it is inferred from the binary name) that we get the right ABI flags +// RUN: %clang -### -o %t.o %s 2>&1 \ +// RUN: -target arm-nacl \ +// RUN: | FileCheck --check-prefix=CHECK-ARM-NOV7 %s +// CHECK-ARM-NOV7: "-triple" "armv7--nacl-gnueabihf" +// CHECK-ARM-NOV7: "-target-abi" "aapcs-linux" +// CHECK-ARM-NOV7: "-mfloat-abi" "hard" + +// Test clang c++ include dirs and link line when using clang++ + +// RUN: %clangxx -### -o %t.o %s 2>&1 \ +// RUN: -target armv7a-unknown-nacl-gnueabihf \ +// RUN: | FileCheck --check-prefix=CHECK-ARM-CXX %s +// CHECK-ARM-CXX: {{.*}}clang{{.*}}" "-cc1" +// CHECK-ARM-CXX: "-resource-dir" "{{.*}}/lib/clang/[[VER:[0-9.]+]]" +// CHECK-ARM-CXX: "-internal-isystem" "{{.*}}/../arm-nacl/include/c++/v1" +// CHECK-ARM-CXX: "-internal-isystem" "{{.*}}/../lib/clang/[[VER]]/include" +// CHECK-ARM-CXX: "-internal-isystem" "{{.*}}/../arm-nacl/usr/include" +// CHECK-ARM-CXX: "-internal-isystem" "{{.*}}/../arm-nacl/include" +// CHECK-ARM-CXX: "-lpthread" + +// RUN: %clangxx -### -o %t.o %s 2>&1 \ +// RUN: -target i686-unknown-nacl \ +// RUN: | FileCheck --check-prefix=CHECK-I686-CXX %s +// CHECK-I686-CXX: {{.*}}clang{{.*}}" "-cc1" +// CHECK-I686-CXX: "-resource-dir" "{{.*}}/lib/clang/[[VER:[0-9.]+]]" +// CHECK-I686-CXX: "-internal-isystem" "{{.*}}/../x86_64-nacl/include/c++/v1" +// CHECK-I686-CXX: "-internal-isystem" "{{.*}}/../lib/clang/[[VER]]/include" +// CHECK-I686-CXX: "-internal-isystem" "{{.*}}/../x86_64-nacl/usr/include" +// CHECK-I686-CXX: "-internal-isystem" "{{.*}}/../x86_64-nacl/include" +// CHECK-I686-CXX: "-lpthread" + +// RUN: %clangxx -### -o %t.o %s 2>&1 \ +// RUN: -target x86_64-unknown-nacl \ +// RUN: | FileCheck --check-prefix=CHECK-x86_64-CXX %s +// CHECK-x86_64-CXX: {{.*}}clang{{.*}}" "-cc1" +// CHECK-x86_64-CXX: "-resource-dir" "{{.*}}/lib/clang/[[VER:[0-9.]+]]" +// CHECK-x86_64-CXX: "-internal-isystem" "{{.*}}/../x86_64-nacl/include/c++/v1" +// CHECK-x86_64-CXX: "-internal-isystem" "{{.*}}/../lib/clang/[[VER]]/include" +// CHECK-x86_64-CXX: "-internal-isystem" "{{.*}}/../x86_64-nacl/usr/include" +// CHECK-x86_64-CXX: "-internal-isystem" "{{.*}}/../x86_64-nacl/include" +// CHECK-x86_64-CXX: "-lpthread"