Index: cmake/caches/BaremetalARM.cmake =================================================================== --- /dev/null +++ cmake/caches/BaremetalARM.cmake @@ -0,0 +1,50 @@ +set(LLVM_TARGETS_TO_BUILD ARM;X86 CACHE STRING "") + +# Builtins +set(LLVM_BUILTIN_TARGETS "armv7m-none-eabi;armv6m-none-eabi;armv7em-none-eabi" CACHE STRING "Builtin Targets") + +set(BUILTINS_armv6m-none-eabi_CMAKE_SYSROOT ${BAREMETAL_ARMV6M_SYSROOT} CACHE STRING "armv6m-none-eabi Sysroot") +set(BUILTINS_armv6m-none-eabi_CMAKE_SYSTEM_NAME Generic CACHE STRING "armv6m-none-eabi System Name") +set(BUILTINS_armv6m-none-eabi_COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "armv6m-none-eabi Baremetal build") +set(BUILTINS_armv6m-none-eabi_COMPILER_RT_OS_DIR "baremetal" CACHE STRING "armv6m-none-eabi os dir") + +set(BUILTINS_armv7m-none-eabi_CMAKE_SYSROOT ${BAREMETAL_ARMV7M_SYSROOT} CACHE STRING "armv7m-none-eabi Sysroot") +set(BUILTINS_armv7m-none-eabi_CMAKE_SYSTEM_NAME Generic CACHE STRING "armv7m-none-eabi System Name") +set(BUILTINS_armv7m-none-eabi_COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "armv7m-none-eabi Baremetal build") +set(BUILTINS_armv7m-none-eabi_CMAKE_C_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7m-none-eabi C Flags") +set(BUILTINS_armv7m-none-eabi_CMAKE_ASM_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7m-none-eabi ASM Flags") +set(BUILTINS_armv7m-none-eabi_COMPILER_RT_OS_DIR "baremetal" CACHE STRING "armv7m-none-eabi os dir") + +set(BUILTINS_armv7em-none-eabi_CMAKE_SYSROOT ${BAREMETAL_ARMV7EM_SYSROOT} CACHE STRING "armv7em-none-eabi Sysroot") +set(BUILTINS_armv7em-none-eabi_CMAKE_SYSTEM_NAME Generic CACHE STRING "armv7em-none-eabi System Name") +set(BUILTINS_armv7em-none-eabi_COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "armv7em-none-eabi Baremetal build") +set(BUILTINS_armv7em-none-eabi_CMAKE_C_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7em-none-eabi C Flags") +set(BUILTINS_armv7em-none-eabi_CMAKE_ASM_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7em-none-eabi ASM Flags") +set(BUILTINS_armv7em-none-eabi_COMPILER_RT_OS_DIR "baremetal" CACHE STRING "armv7em-none-eabi os dir") + +set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "") +set(LLVM_TOOLCHAIN_TOOLS + llc + llvm-ar + llvm-cxxfilt + llvm-dwarfdump + llvm-dsymutil + llvm-nm + llvm-objdump + llvm-ranlib + llvm-readobj + llvm-size + llvm-symbolizer + opt + CACHE STRING "") + +set(LLVM_DISTRIBUTION_COMPONENTS + clang + lld + clang-headers + builtins-armv6m-none-eabi + builtins-armv7m-none-eabi + builtins-armv7em-none-eabi + runtimes + ${LLVM_TOOLCHAIN_TOOLS} + CACHE STRING "") Index: lib/Driver/CMakeLists.txt =================================================================== --- lib/Driver/CMakeLists.txt +++ lib/Driver/CMakeLists.txt @@ -30,6 +30,7 @@ ToolChains/AMDGPU.cpp ToolChains/AVR.cpp ToolChains/Bitrig.cpp + ToolChains/BareMetal.cpp ToolChains/Clang.cpp ToolChains/CloudABI.cpp ToolChains/CommonArgs.cpp Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -22,6 +22,7 @@ #include "ToolChains/FreeBSD.h" #include "ToolChains/Fuchsia.h" #include "ToolChains/Gnu.h" +#include "ToolChains/BareMetal.h" #include "ToolChains/Haiku.h" #include "ToolChains/Hexagon.h" #include "ToolChains/Lanai.h" @@ -3819,6 +3820,8 @@ if (Target.getVendor() == llvm::Triple::Myriad) TC = llvm::make_unique(*this, Target, Args); + else if (toolchains::BareMetal::handlesTarget(Target)) + TC = llvm::make_unique(*this, Target, Args); else if (Target.isOSBinFormatELF()) TC = llvm::make_unique(*this, Target, Args); else if (Target.isOSBinFormatMachO()) Index: lib/Driver/ToolChains/BareMetal.h =================================================================== --- /dev/null +++ lib/Driver/ToolChains/BareMetal.h @@ -0,0 +1,90 @@ +//===--- BareMetal.h - Bare Metal Tool and ToolChain -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_BAREMETAL_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_BAREMETAL_H + +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" + +#include + +namespace clang { +namespace driver { + +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain { +public: + BareMetal(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + ~BareMetal() override; + + static bool handlesTarget(const llvm::Triple &Triple); +protected: + Tool *buildLinker() const override; + +public: + bool useIntegratedAs() const override { return true; } + bool isCrossCompiling() const override { return true; } + bool isPICDefault() const override { return false; } + bool isPIEDefault() const override { return false; } + bool isPICDefaultForced() const override { return false; } + bool SupportsProfiling() const override { return false; } + bool SupportsObjCGC() const override { return false; } + std::string getThreadModel() const override; + bool isThreadModelSupported(const StringRef Model) const override; + + RuntimeLibType GetDefaultRuntimeLibType() const override { + return ToolChain::RLT_CompilerRT; + } + CXXStdlibType GetDefaultCXXStdlibType() const override { + return ToolChain::CST_Libcxx; + } + + const char *getDefaultLinker() const override { return "ld.lld"; } + + std::string getRuntimesDir() const; + void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + std::string findLibCxxIncludePath(ToolChain::CXXStdlibType LibType) const; + void AddClangCXXStdlibIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + void AddLinkRuntimeLib(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const; +}; + +} // namespace toolchains + +namespace tools { +namespace baremetal { + +class LLVM_LIBRARY_VISIBILITY Linker : public Tool { +public: + Linker(const ToolChain &TC) : Tool("baremetal::Linker", "ld.lld", TC) {} + bool isLinkJob() const override { return true; } + bool hasIntegratedCPP() const override { return false; } + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; + +} // namespace baremetal +} // namespace tools + +} // namespace driver +} // namespace clang + +#endif Index: lib/Driver/ToolChains/BareMetal.cpp =================================================================== --- /dev/null +++ lib/Driver/ToolChains/BareMetal.cpp @@ -0,0 +1,209 @@ +//===--- BaremMetal.cpp - Bare Metal ToolChain ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "BareMetal.h" + +#include "CommonArgs.h" +#include "InputInfo.h" +#include "Gnu.h" + +#include "clang/Basic/VirtualFileSystem.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm::opt; +using namespace clang; +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang::driver::toolchains; + +BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : ToolChain(D, Triple, Args) { + getProgramPaths().push_back(getDriver().getInstalledDir()); + if (getDriver().getInstalledDir() != getDriver().Dir) + getProgramPaths().push_back(getDriver().Dir); +} + +BareMetal::~BareMetal() {} + +/// Is the triple {arm,thumb}-none-none-{eabi,eabihf} ? +static bool isARMBareMetal(const llvm::Triple &Triple) { + if (Triple.getArch() != llvm::Triple::arm && + Triple.getArch() != llvm::Triple::thumb) + return false; + + if (Triple.getVendor() != llvm::Triple::UnknownVendor) + return false; + + if (Triple.getOS() != llvm::Triple::UnknownOS) + return false; + + if (Triple.getEnvironment() != llvm::Triple::EABI && + Triple.getEnvironment() != llvm::Triple::EABIHF) + return false; + + return true; +} + +bool BareMetal::handlesTarget(const llvm::Triple &Triple) { + return isARMBareMetal(Triple); +} + +Tool *BareMetal::buildLinker() const { + return new tools::baremetal::Linker(*this); +} + +std::string BareMetal::getThreadModel() const { + return "single"; +} + +bool BareMetal::isThreadModelSupported(const StringRef Model) const { + return Model == "single"; +} + +std::string BareMetal::getRuntimesDir() const { + SmallString<128> Dir(getDriver().ResourceDir); + llvm::sys::path::append(Dir, "lib", "baremetal"); + return Dir.str(); +} + +void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> Dir(getDriver().ResourceDir); + llvm::sys::path::append(Dir, "include"); + addSystemInclude(DriverArgs, CC1Args, Dir.str()); + } + + if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) { + SmallString<128> Dir(getDriver().SysRoot); + llvm::sys::path::append(Dir, "include"); + addSystemInclude(DriverArgs, CC1Args, Dir.str()); + } +} + +void BareMetal::addClangTargetOptions(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + CC1Args.push_back("-nostdsysteminc"); +} + +std::string BareMetal::findLibCxxIncludePath(CXXStdlibType LibType) const { + StringRef SysRoot = getDriver().SysRoot; + if (SysRoot.empty()) + return ""; + + switch (LibType) { + case ToolChain::CST_Libcxx: { + SmallString<128> Dir(SysRoot); + llvm::sys::path::append(Dir, "include", "c++", "v1"); + return Dir.str(); + } + case ToolChain::CST_Libstdcxx: { + SmallString<128> Dir(SysRoot); + llvm::sys::path::append(Dir, "include", "c++"); + std::error_code EC; + Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""}; + // Walk the subdirs, and find the one with the newest gcc version: + for (vfs::directory_iterator LI = + getDriver().getVFS().dir_begin(Dir.str(), EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->getName()); + auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText); + if (CandidateVersion.Major == -1) + continue; + if (CandidateVersion <= Version) + continue; + Version = CandidateVersion; + } + if (Version.Major == -1) + return ""; + llvm::sys::path::append(Dir, Version.Text); + return Dir.str(); + } + } +} + +void BareMetal::AddClangCXXStdlibIncludeArgs( + const ArgList &DriverArgs, ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc) || + DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + std::string Path = findLibCxxIncludePath(GetCXXStdlibType(DriverArgs)); + if (!Path.empty()) + addSystemInclude(DriverArgs, CC1Args, Path); +} + +void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + switch (GetCXXStdlibType(Args)) { + case ToolChain::CST_Libcxx: + CmdArgs.push_back("-lc++"); + CmdArgs.push_back("-lc++abi"); + break; + case ToolChain::CST_Libstdcxx: + CmdArgs.push_back("-lstdc++"); + CmdArgs.push_back("-lsupc++"); + break; + } + CmdArgs.push_back("-lunwind"); +} + +void BareMetal::AddLinkRuntimeLib(const ArgList &Args, + ArgStringList &CmdArgs) const { + CmdArgs.push_back(Args.MakeArgString("-lclang_rt.builtins-" + + getTriple().getArchName() + ".a")); +} + +void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + + auto &TC = static_cast(getToolChain()); + + AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); + + CmdArgs.push_back("-Bstatic"); + + CmdArgs.push_back(Args.MakeArgString("-L" + TC.getRuntimesDir())); + + Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, + options::OPT_e, options::OPT_s, options::OPT_t, + options::OPT_Z_Flag, options::OPT_r}); + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { + if (C.getDriver().CCCIsCXX()) + TC.AddCXXStdlibLibArgs(Args, CmdArgs); + + CmdArgs.push_back("-lc"); + CmdArgs.push_back("-lm"); + + TC.AddLinkRuntimeLib(Args, CmdArgs); + } + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + C.addCommand(llvm::make_unique(JA, *this, + Args.MakeArgString(TC.GetLinkerPath()), + CmdArgs, Inputs)); +} Index: lib/Driver/ToolChains/Gnu.cpp =================================================================== --- lib/Driver/ToolChains/Gnu.cpp +++ lib/Driver/ToolChains/Gnu.cpp @@ -1598,6 +1598,49 @@ return false; } +/// \brief Parse a GCCVersion object out of a string of text. +/// +/// This is the primary means of forming GCCVersion objects. +/*static*/ +Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) { + const GCCVersion BadVersion = {VersionText.str(), -1, -1, -1, "", "", ""}; + std::pair First = VersionText.split('.'); + std::pair Second = First.second.split('.'); + + GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""}; + if (First.first.getAsInteger(10, GoodVersion.Major) || GoodVersion.Major < 0) + return BadVersion; + GoodVersion.MajorStr = First.first.str(); + if (First.second.empty()) + return GoodVersion; + if (Second.first.getAsInteger(10, GoodVersion.Minor) || GoodVersion.Minor < 0) + return BadVersion; + GoodVersion.MinorStr = Second.first.str(); + + // First look for a number prefix and parse that if present. Otherwise just + // stash the entire patch string in the suffix, and leave the number + // unspecified. This covers versions strings such as: + // 5 (handled above) + // 4.4 + // 4.4.0 + // 4.4.x + // 4.4.2-rc4 + // 4.4.x-patched + // And retains any patch number it finds. + StringRef PatchText = GoodVersion.PatchSuffix = Second.second.str(); + if (!PatchText.empty()) { + if (size_t EndNumber = PatchText.find_first_not_of("0123456789")) { + // Try to parse the number and any suffix. + if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) || + GoodVersion.Patch < 0) + return BadVersion; + GoodVersion.PatchSuffix = PatchText.substr(EndNumber); + } + } + + return GoodVersion; +} + static llvm::StringRef getGCCToolchainDir(const ArgList &Args) { const Arg *A = Args.getLastArg(clang::driver::options::OPT_gcc_toolchain); if (A) Index: lib/Driver/ToolChains/Linux.cpp =================================================================== --- lib/Driver/ToolChains/Linux.cpp +++ lib/Driver/ToolChains/Linux.cpp @@ -372,49 +372,6 @@ addPathIfExists(D, SysRoot + "/usr/lib", Paths); } -/// \brief Parse a GCCVersion object out of a string of text. -/// -/// This is the primary means of forming GCCVersion objects. -/*static*/ -Generic_GCC::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) { - const GCCVersion BadVersion = {VersionText.str(), -1, -1, -1, "", "", ""}; - std::pair First = VersionText.split('.'); - std::pair Second = First.second.split('.'); - - GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""}; - if (First.first.getAsInteger(10, GoodVersion.Major) || GoodVersion.Major < 0) - return BadVersion; - GoodVersion.MajorStr = First.first.str(); - if (First.second.empty()) - return GoodVersion; - if (Second.first.getAsInteger(10, GoodVersion.Minor) || GoodVersion.Minor < 0) - return BadVersion; - GoodVersion.MinorStr = Second.first.str(); - - // First look for a number prefix and parse that if present. Otherwise just - // stash the entire patch string in the suffix, and leave the number - // unspecified. This covers versions strings such as: - // 5 (handled above) - // 4.4 - // 4.4.0 - // 4.4.x - // 4.4.2-rc4 - // 4.4.x-patched - // And retains any patch number it finds. - StringRef PatchText = GoodVersion.PatchSuffix = Second.second.str(); - if (!PatchText.empty()) { - if (size_t EndNumber = PatchText.find_first_not_of("0123456789")) { - // Try to parse the number and any suffix. - if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) || - GoodVersion.Patch < 0) - return BadVersion; - GoodVersion.PatchSuffix = PatchText.substr(EndNumber); - } - } - - return GoodVersion; -} - bool Linux::HasNativeLLVMSupport() const { return true; } Tool *Linux::buildLinker() const { return new tools::gnutools::Linker(*this); } Index: test/Driver/baremetal.cpp =================================================================== --- /dev/null +++ test/Driver/baremetal.cpp @@ -0,0 +1,77 @@ +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target armv6m-none-eabi \ +// RUN: -T semihosted.lds \ +// RUN: -L some/directory/user/asked/for \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-V6M-C %s +// CHECK-V6M-C: "[[PREFIX_DIR:.*]]/bin/clang" "-cc1" "-triple" "thumbv6m-none--eabi" +// CHECK-V6M-C-SAME: "-resource-dir" "[[PREFIX_DIR]]/lib/clang/[[VERSION:[^"]*]]" +// CHECK-V6M-C-SAME: "-isysroot" "[[SYSROOT:[^"]*]]" +// CHECK-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]/include/c++/v1" +// CHECk-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]/include" +// CHECK-V6M-C-SAME: "-x" "c++" "{{.*}}baremetal.cpp" +// CHECK-V6M-C-NEXT: "[[PREFIX_DIR:.*]]/bin/ld.lld" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-C-SAME: "-L[[PREFIX_DIR]]/lib/clang/[[VERSION]]/lib/baremetal" +// CHECK-V6M-C-SAME: "-T" "semihosted.lds" "-Lsome/directory/user/asked/for" +// CHECK-V6M-C-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a" +// CHECK-V6M-C-SAME: "-o" "{{.*}}.o" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target armv6m-none-eabi \ +// RUN: -nostdlibinc -nobuiltininc \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-V6M-LIBINC %s +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target armv6m-none-eabi \ +// RUN: -nostdinc \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-V6M-LIBINC %s +// CHECK-V6M-LIBINC-NOT: "-internal-isystem" + +// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target armv6m-none-eabi \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: | FileCheck --check-prefix=CHECK-V6M-DEFAULTCXX %s +// CHECK-V6M-DEFAULTCXX: "[[PREFIX_DIR:.*]]/bin/ld.lld" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-DEFAULTCXX-SAME: "-L[[PREFIX_DIR]]/lib/clang/{{.*}}/lib/baremetal" +// CHECK-V6M-DEFAULTCXX-SAME: "-lc++" "-lc++abi" "-lunwind" +// CHECK-V6M-DEFAULTCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a" +// CHECK-V6M-DEFAULTCXX-SAME: "-o" "{{.*}}.o" + +// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target armv6m-none-eabi \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: -stdlib=libc++ \ +// RUN: | FileCheck --check-prefix=CHECK-V6M-LIBCXX %s +// CHECK-V6M-LIBCXX-NOT: "-internal-isystem" "{{[^"]+}}/include/c++/{{[^v].*}}" +// CHECK-V6M-LIBCXX: "-internal-isystem" "{{[^"]+}}/include/c++/v1" +// CHECK-V6M-LIBCXX: "[[PREFIX_DIR:.*]]/bin/ld.lld" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-LIBCXX-SAME: "-L[[PREFIX_DIR]]/lib/clang/{{.*}}/lib/baremetal" +// CHECK-V6M-LIBCXX-SAME: "-lc++" "-lc++abi" "-lunwind" +// CHECK-V6M-LIBCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a" +// CHECK-V6M-LIBCXX-SAME: "-o" "{{.*}}.o" + +// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target armv6m-none-eabi \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: -stdlib=libstdc++ \ +// RUN: | FileCheck --check-prefix=CHECK-V6M-LIBSTDCXX %s +// CHECK-V6M-LIBSTDCXX-NOT: "-internal-isystem" "{{[^"]+}}/include/c++/v1" +// CHECK-V6M-LIBSTDCXX: "-internal-isystem" "{{[^"]+}}/include/c++/6.0.0" +// CHECK-V6M-LIBSTDCXX: "[[PREFIX_DIR:.*]]/bin/ld.lld" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-LIBSTDCXX-SAME: "-L[[PREFIX_DIR]]/lib/clang/{{.*}}/lib/baremetal" +// CHECK-V6M-LIBSTDCXX-SAME: "-lstdc++" "-lsupc++" "-lunwind" +// CHECK-V6M-LIBSTDCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a" +// CHECK-V6M-LIBSTDCXX-SAME: "-o" "{{.*}}.o" + +// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target armv6m-none-eabi \ +// RUN: --sysroot=%S/Inputs/baremetal_arm \ +// RUN: -nodefaultlibs \ +// RUN: | FileCheck --check-prefix=CHECK-V6M-NDL %s +// CHECK-V6M-NDL: "[[PREFIX_DIR:.*]]/bin/ld.lld" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-NDL-SAME: "-L[[PREFIX_DIR]]/lib/clang/{{.*}}/lib/baremetal" "-o" "{{.*}}.o" + +// RUN: %clangxx -target arm-none-eabi -v 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-THREAD-MODEL +// CHECK-THREAD-MODEL: Thread model: single