Index: cmake/caches/BaremetalARM.cmake =================================================================== --- /dev/null +++ cmake/caches/BaremetalARM.cmake @@ -0,0 +1,33 @@ +set(LLVM_TARGETS_TO_BUILD ARM CACHE STRING "") + +# Builtins +set(LLVM_BUILTIN_TARGETS "armv6m-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 BareMetal CACHE STRING "armv6m-none-eabi System Name") +set(BUILTINS_armv6m-none-eabi_COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "Baremetal build") +set(BUILTINS_armv6m-none-eabi_CMAKE_C_FLAGS "-isysroot ${BAREMETAL_ARMV6M_SYSROOT}" CACHE STRING "armv6m-none-eabi C Flags") + +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 + 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,82 @@ +//===--- 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 true; } + bool SupportsObjCGC() const override { return false; } + + const char *getDefaultLinker() const override { return "ld.lld"; } + + std::string getRuntimesDir() const; + std::string findLibCxxIncludePath() 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; + 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; +protected: +}; + +} // 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,153 @@ +//===--- 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 "InputInfo.h" +#include "CommonArgs.h" + +#include "clang/Basic/VirtualFileSystem.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Compilation.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::getRuntimesDir() const { + SmallString<128> Dir(getDriver().ResourceDir); + llvm::sys::path::append(Dir, "lib", "baremetal"); + return Dir.str(); +} + +std::string BareMetal::findLibCxxIncludePath() const { + SmallString<128> Dir(getDriver().ResourceDir); + llvm::sys::path::append(Dir, "include", "c++", "v1"); + return Dir.str(); +} + +void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc) || + DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + SmallString<128> Dir(getDriver().ResourceDir); + llvm::sys::path::append(Dir, "include"); + addSystemInclude(DriverArgs, CC1Args, Dir.str()); +} + +void BareMetal::addClangTargetOptions(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + CC1Args.push_back("-nostdsysteminc"); +} + +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(); + addSystemInclude(DriverArgs, CC1Args, Path); +} + +void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + CmdArgs.push_back("-lc++"); + CmdArgs.push_back("-lc++abi"); + 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: test/Driver/baremetal.cpp =================================================================== --- /dev/null +++ test/Driver/baremetal.cpp @@ -0,0 +1,31 @@ +// 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: | 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: "-internal-isystem" "[[PREFIX_DIR]]/lib/clang/[[VERSION]]/include/c++/v1" +// CHECk-V6M-C-SAME: "-internal-isystem" "[[PREFIX_DIR]]/lib/clang/[[VERSION]]/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: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target armv6m-none-eabi \ +// RUN: | FileCheck --check-prefix=CHECK-V6M-CXX %s +// CHECK-V6M-CXX: "[[PREFIX_DIR:.*]]/bin/ld.lld" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-CXX-SAME: "-L[[PREFIX_DIR]]/lib/clang/{{.*}}/lib/baremetal" +// CHECK-V6M-CXX-SAME: "-lc++" "-lc++abi" "-lunwind" +// CHECK-V6M-CXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a" +// CHECK-V6M-CXX-SAME: "-o" "{{.*}}.o" + +// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target armv6m-none-eabi \ +// 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"