diff options
Diffstat (limited to 'clang/lib/Driver/ToolChains/BareMetal.cpp')
| -rw-r--r-- | clang/lib/Driver/ToolChains/BareMetal.cpp | 197 | 
1 files changed, 197 insertions, 0 deletions
| diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp new file mode 100644 index 000000000000..dff0e04183ef --- /dev/null +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -0,0 +1,197 @@ +//===-- BareMetal.cpp - Bare Metal ToolChain --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "BareMetal.h" + +#include "CommonArgs.h" +#include "InputInfo.h" +#include "Gnu.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/VirtualFileSystem.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(); +} + +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, +                                      Action::OffloadKind) 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; + +  StringRef SysRoot = getDriver().SysRoot; +  if (SysRoot.empty()) +    return; + +  switch (GetCXXStdlibType(DriverArgs)) { +  case ToolChain::CST_Libcxx: { +    SmallString<128> Dir(SysRoot); +    llvm::sys::path::append(Dir, "include", "c++", "v1"); +    addSystemInclude(DriverArgs, CC1Args, Dir.str()); +    break; +  } +  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 (llvm::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->path()); +      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); +    addSystemInclude(DriverArgs, CC1Args, Dir.str()); +    break; +  } +  } +} + +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<const toolchains::BareMetal&>(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 (TC.ShouldLinkCXXStdlib(Args)) +    TC.AddCXXStdlibLibArgs(Args, CmdArgs); +  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { +    CmdArgs.push_back("-lc"); +    CmdArgs.push_back("-lm"); + +    TC.AddLinkRuntimeLib(Args, CmdArgs); +  } + +  CmdArgs.push_back("-o"); +  CmdArgs.push_back(Output.getFilename()); + +  C.addCommand(std::make_unique<Command>(JA, *this, +                                          Args.MakeArgString(TC.GetLinkerPath()), +                                          CmdArgs, Inputs)); +} | 
