xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- BareMetal.cpp - Bare Metal ToolChain --------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "BareMetal.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "CommonArgs.h"
120b57cec5SDimitry Andric #include "Gnu.h"
13fe6060f1SDimitry Andric #include "clang/Driver/InputInfo.h"
140b57cec5SDimitry Andric 
1506c3fb27SDimitry Andric #include "Arch/ARM.h"
16e8d8bef9SDimitry Andric #include "Arch/RISCV.h"
170b57cec5SDimitry Andric #include "clang/Driver/Compilation.h"
180b57cec5SDimitry Andric #include "clang/Driver/Driver.h"
190b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
2006c3fb27SDimitry Andric #include "clang/Driver/MultilibBuilder.h"
210b57cec5SDimitry Andric #include "clang/Driver/Options.h"
2206c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
230b57cec5SDimitry Andric #include "llvm/Option/ArgList.h"
240b57cec5SDimitry Andric #include "llvm/Support/Path.h"
250b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
260b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
270b57cec5SDimitry Andric 
2806c3fb27SDimitry Andric #include <sstream>
2906c3fb27SDimitry Andric 
300b57cec5SDimitry Andric using namespace llvm::opt;
310b57cec5SDimitry Andric using namespace clang;
320b57cec5SDimitry Andric using namespace clang::driver;
330b57cec5SDimitry Andric using namespace clang::driver::tools;
340b57cec5SDimitry Andric using namespace clang::driver::toolchains;
350b57cec5SDimitry Andric 
36e8d8bef9SDimitry Andric static bool findRISCVMultilibs(const Driver &D,
37e8d8bef9SDimitry Andric                                const llvm::Triple &TargetTriple,
38e8d8bef9SDimitry Andric                                const ArgList &Args, DetectedMultilibs &Result) {
39e8d8bef9SDimitry Andric   Multilib::flags_list Flags;
40*0fca6ea1SDimitry Andric   std::string Arch = riscv::getRISCVArch(Args, TargetTriple);
41e8d8bef9SDimitry Andric   StringRef Abi = tools::riscv::getRISCVABI(Args, TargetTriple);
42e8d8bef9SDimitry Andric 
43bdd1243dSDimitry Andric   if (TargetTriple.isRISCV64()) {
4406c3fb27SDimitry Andric     MultilibBuilder Imac =
4506c3fb27SDimitry Andric         MultilibBuilder().flag("-march=rv64imac").flag("-mabi=lp64");
4606c3fb27SDimitry Andric     MultilibBuilder Imafdc = MultilibBuilder("/rv64imafdc/lp64d")
4706c3fb27SDimitry Andric                                  .flag("-march=rv64imafdc")
4806c3fb27SDimitry Andric                                  .flag("-mabi=lp64d");
49e8d8bef9SDimitry Andric 
50e8d8bef9SDimitry Andric     // Multilib reuse
51e8d8bef9SDimitry Andric     bool UseImafdc =
52e8d8bef9SDimitry Andric         (Arch == "rv64imafdc") || (Arch == "rv64gc"); // gc => imafdc
53e8d8bef9SDimitry Andric 
5406c3fb27SDimitry Andric     addMultilibFlag((Arch == "rv64imac"), "-march=rv64imac", Flags);
5506c3fb27SDimitry Andric     addMultilibFlag(UseImafdc, "-march=rv64imafdc", Flags);
5606c3fb27SDimitry Andric     addMultilibFlag(Abi == "lp64", "-mabi=lp64", Flags);
5706c3fb27SDimitry Andric     addMultilibFlag(Abi == "lp64d", "-mabi=lp64d", Flags);
58e8d8bef9SDimitry Andric 
5906c3fb27SDimitry Andric     Result.Multilibs =
6006c3fb27SDimitry Andric         MultilibSetBuilder().Either(Imac, Imafdc).makeMultilibSet();
6106c3fb27SDimitry Andric     return Result.Multilibs.select(Flags, Result.SelectedMultilibs);
62e8d8bef9SDimitry Andric   }
63bdd1243dSDimitry Andric   if (TargetTriple.isRISCV32()) {
6406c3fb27SDimitry Andric     MultilibBuilder Imac =
6506c3fb27SDimitry Andric         MultilibBuilder().flag("-march=rv32imac").flag("-mabi=ilp32");
6606c3fb27SDimitry Andric     MultilibBuilder I = MultilibBuilder("/rv32i/ilp32")
6706c3fb27SDimitry Andric                             .flag("-march=rv32i")
6806c3fb27SDimitry Andric                             .flag("-mabi=ilp32");
6906c3fb27SDimitry Andric     MultilibBuilder Im = MultilibBuilder("/rv32im/ilp32")
7006c3fb27SDimitry Andric                              .flag("-march=rv32im")
7106c3fb27SDimitry Andric                              .flag("-mabi=ilp32");
7206c3fb27SDimitry Andric     MultilibBuilder Iac = MultilibBuilder("/rv32iac/ilp32")
7306c3fb27SDimitry Andric                               .flag("-march=rv32iac")
7406c3fb27SDimitry Andric                               .flag("-mabi=ilp32");
7506c3fb27SDimitry Andric     MultilibBuilder Imafc = MultilibBuilder("/rv32imafc/ilp32f")
7606c3fb27SDimitry Andric                                 .flag("-march=rv32imafc")
7706c3fb27SDimitry Andric                                 .flag("-mabi=ilp32f");
78e8d8bef9SDimitry Andric 
79e8d8bef9SDimitry Andric     // Multilib reuse
80e8d8bef9SDimitry Andric     bool UseI = (Arch == "rv32i") || (Arch == "rv32ic");    // ic => i
81e8d8bef9SDimitry Andric     bool UseIm = (Arch == "rv32im") || (Arch == "rv32imc"); // imc => im
82e8d8bef9SDimitry Andric     bool UseImafc = (Arch == "rv32imafc") || (Arch == "rv32imafdc") ||
83e8d8bef9SDimitry Andric                     (Arch == "rv32gc"); // imafdc,gc => imafc
84e8d8bef9SDimitry Andric 
8506c3fb27SDimitry Andric     addMultilibFlag(UseI, "-march=rv32i", Flags);
8606c3fb27SDimitry Andric     addMultilibFlag(UseIm, "-march=rv32im", Flags);
8706c3fb27SDimitry Andric     addMultilibFlag((Arch == "rv32iac"), "-march=rv32iac", Flags);
8806c3fb27SDimitry Andric     addMultilibFlag((Arch == "rv32imac"), "-march=rv32imac", Flags);
8906c3fb27SDimitry Andric     addMultilibFlag(UseImafc, "-march=rv32imafc", Flags);
9006c3fb27SDimitry Andric     addMultilibFlag(Abi == "ilp32", "-mabi=ilp32", Flags);
9106c3fb27SDimitry Andric     addMultilibFlag(Abi == "ilp32f", "-mabi=ilp32f", Flags);
92e8d8bef9SDimitry Andric 
9306c3fb27SDimitry Andric     Result.Multilibs =
9406c3fb27SDimitry Andric         MultilibSetBuilder().Either(I, Im, Iac, Imac, Imafc).makeMultilibSet();
9506c3fb27SDimitry Andric     return Result.Multilibs.select(Flags, Result.SelectedMultilibs);
96e8d8bef9SDimitry Andric   }
97e8d8bef9SDimitry Andric   return false;
98e8d8bef9SDimitry Andric }
99e8d8bef9SDimitry Andric 
1000b57cec5SDimitry Andric BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
1010b57cec5SDimitry Andric                      const ArgList &Args)
1020b57cec5SDimitry Andric     : ToolChain(D, Triple, Args) {
1030b57cec5SDimitry Andric   getProgramPaths().push_back(getDriver().Dir);
1040b57cec5SDimitry Andric 
105e8d8bef9SDimitry Andric   findMultilibs(D, Triple, Args);
106e8d8bef9SDimitry Andric   SmallString<128> SysRoot(computeSysRoot());
107e8d8bef9SDimitry Andric   if (!SysRoot.empty()) {
10806c3fb27SDimitry Andric     for (const Multilib &M : getOrderedMultilibs()) {
10906c3fb27SDimitry Andric       SmallString<128> Dir(SysRoot);
11006c3fb27SDimitry Andric       llvm::sys::path::append(Dir, M.osSuffix(), "lib");
11106c3fb27SDimitry Andric       getFilePaths().push_back(std::string(Dir));
11206c3fb27SDimitry Andric       getLibraryPaths().push_back(std::string(Dir));
11306c3fb27SDimitry Andric     }
114e8d8bef9SDimitry Andric   }
115e8d8bef9SDimitry Andric }
1160b57cec5SDimitry Andric 
11706c3fb27SDimitry Andric /// Is the triple {arm,armeb,thumb,thumbeb}-none-none-{eabi,eabihf} ?
1180b57cec5SDimitry Andric static bool isARMBareMetal(const llvm::Triple &Triple) {
1190b57cec5SDimitry Andric   if (Triple.getArch() != llvm::Triple::arm &&
12006c3fb27SDimitry Andric       Triple.getArch() != llvm::Triple::thumb &&
12106c3fb27SDimitry Andric       Triple.getArch() != llvm::Triple::armeb &&
12206c3fb27SDimitry Andric       Triple.getArch() != llvm::Triple::thumbeb)
1230b57cec5SDimitry Andric     return false;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   if (Triple.getVendor() != llvm::Triple::UnknownVendor)
1260b57cec5SDimitry Andric     return false;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   if (Triple.getOS() != llvm::Triple::UnknownOS)
1290b57cec5SDimitry Andric     return false;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   if (Triple.getEnvironment() != llvm::Triple::EABI &&
1320b57cec5SDimitry Andric       Triple.getEnvironment() != llvm::Triple::EABIHF)
1330b57cec5SDimitry Andric     return false;
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   return true;
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
13806c3fb27SDimitry Andric /// Is the triple {aarch64.aarch64_be}-none-elf?
139349cc55cSDimitry Andric static bool isAArch64BareMetal(const llvm::Triple &Triple) {
14006c3fb27SDimitry Andric   if (Triple.getArch() != llvm::Triple::aarch64 &&
14106c3fb27SDimitry Andric       Triple.getArch() != llvm::Triple::aarch64_be)
142349cc55cSDimitry Andric     return false;
143349cc55cSDimitry Andric 
144349cc55cSDimitry Andric   if (Triple.getVendor() != llvm::Triple::UnknownVendor)
145349cc55cSDimitry Andric     return false;
146349cc55cSDimitry Andric 
147349cc55cSDimitry Andric   if (Triple.getOS() != llvm::Triple::UnknownOS)
148349cc55cSDimitry Andric     return false;
149349cc55cSDimitry Andric 
150349cc55cSDimitry Andric   return Triple.getEnvironmentName() == "elf";
151349cc55cSDimitry Andric }
152349cc55cSDimitry Andric 
153e8d8bef9SDimitry Andric static bool isRISCVBareMetal(const llvm::Triple &Triple) {
154bdd1243dSDimitry Andric   if (!Triple.isRISCV())
155e8d8bef9SDimitry Andric     return false;
156e8d8bef9SDimitry Andric 
157e8d8bef9SDimitry Andric   if (Triple.getVendor() != llvm::Triple::UnknownVendor)
158e8d8bef9SDimitry Andric     return false;
159e8d8bef9SDimitry Andric 
160e8d8bef9SDimitry Andric   if (Triple.getOS() != llvm::Triple::UnknownOS)
161e8d8bef9SDimitry Andric     return false;
162e8d8bef9SDimitry Andric 
163e8d8bef9SDimitry Andric   return Triple.getEnvironmentName() == "elf";
164e8d8bef9SDimitry Andric }
165e8d8bef9SDimitry Andric 
16606c3fb27SDimitry Andric /// Is the triple powerpc[64][le]-*-none-eabi?
16706c3fb27SDimitry Andric static bool isPPCBareMetal(const llvm::Triple &Triple) {
16806c3fb27SDimitry Andric   return Triple.isPPC() && Triple.getOS() == llvm::Triple::UnknownOS &&
16906c3fb27SDimitry Andric          Triple.getEnvironment() == llvm::Triple::EABI;
17006c3fb27SDimitry Andric }
17106c3fb27SDimitry Andric 
17206c3fb27SDimitry Andric static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
17306c3fb27SDimitry Andric                                   StringRef MultilibPath, const ArgList &Args,
17406c3fb27SDimitry Andric                                   DetectedMultilibs &Result) {
17506c3fb27SDimitry Andric   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB =
17606c3fb27SDimitry Andric       D.getVFS().getBufferForFile(MultilibPath);
17706c3fb27SDimitry Andric   if (!MB)
17806c3fb27SDimitry Andric     return;
17906c3fb27SDimitry Andric   Multilib::flags_list Flags = TC.getMultilibFlags(Args);
18006c3fb27SDimitry Andric   llvm::ErrorOr<MultilibSet> ErrorOrMultilibSet =
18106c3fb27SDimitry Andric       MultilibSet::parseYaml(*MB.get());
18206c3fb27SDimitry Andric   if (ErrorOrMultilibSet.getError())
18306c3fb27SDimitry Andric     return;
18406c3fb27SDimitry Andric   Result.Multilibs = ErrorOrMultilibSet.get();
18506c3fb27SDimitry Andric   if (Result.Multilibs.select(Flags, Result.SelectedMultilibs))
18606c3fb27SDimitry Andric     return;
18706c3fb27SDimitry Andric   D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
18806c3fb27SDimitry Andric   std::stringstream ss;
18906c3fb27SDimitry Andric   for (const Multilib &Multilib : Result.Multilibs)
19006c3fb27SDimitry Andric     ss << "\n" << llvm::join(Multilib.flags(), " ");
19106c3fb27SDimitry Andric   D.Diag(clang::diag::note_drv_available_multilibs) << ss.str();
19206c3fb27SDimitry Andric }
19306c3fb27SDimitry Andric 
19406c3fb27SDimitry Andric static constexpr llvm::StringLiteral MultilibFilename = "multilib.yaml";
19506c3fb27SDimitry Andric 
19606c3fb27SDimitry Andric // Get the sysroot, before multilib takes effect.
19706c3fb27SDimitry Andric static std::string computeBaseSysRoot(const Driver &D,
19806c3fb27SDimitry Andric                                       const llvm::Triple &Triple) {
19906c3fb27SDimitry Andric   if (!D.SysRoot.empty())
20006c3fb27SDimitry Andric     return D.SysRoot;
20106c3fb27SDimitry Andric 
20206c3fb27SDimitry Andric   SmallString<128> SysRootDir(D.Dir);
20306c3fb27SDimitry Andric   llvm::sys::path::append(SysRootDir, "..", "lib", "clang-runtimes");
20406c3fb27SDimitry Andric 
20506c3fb27SDimitry Andric   SmallString<128> MultilibPath(SysRootDir);
20606c3fb27SDimitry Andric   llvm::sys::path::append(MultilibPath, MultilibFilename);
20706c3fb27SDimitry Andric 
20806c3fb27SDimitry Andric   // New behaviour: if multilib.yaml is found then use clang-runtimes as the
20906c3fb27SDimitry Andric   // sysroot.
21006c3fb27SDimitry Andric   if (D.getVFS().exists(MultilibPath))
21106c3fb27SDimitry Andric     return std::string(SysRootDir);
21206c3fb27SDimitry Andric 
21306c3fb27SDimitry Andric   // Otherwise fall back to the old behaviour of appending the target triple.
21406c3fb27SDimitry Andric   llvm::sys::path::append(SysRootDir, D.getTargetTriple());
21506c3fb27SDimitry Andric   return std::string(SysRootDir);
21606c3fb27SDimitry Andric }
21706c3fb27SDimitry Andric 
218e8d8bef9SDimitry Andric void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
219e8d8bef9SDimitry Andric                               const ArgList &Args) {
220e8d8bef9SDimitry Andric   DetectedMultilibs Result;
221e8d8bef9SDimitry Andric   if (isRISCVBareMetal(Triple)) {
222e8d8bef9SDimitry Andric     if (findRISCVMultilibs(D, Triple, Args, Result)) {
22306c3fb27SDimitry Andric       SelectedMultilibs = Result.SelectedMultilibs;
224e8d8bef9SDimitry Andric       Multilibs = Result.Multilibs;
225e8d8bef9SDimitry Andric     }
22606c3fb27SDimitry Andric   } else {
22706c3fb27SDimitry Andric     llvm::SmallString<128> MultilibPath(computeBaseSysRoot(D, Triple));
22806c3fb27SDimitry Andric     llvm::sys::path::append(MultilibPath, MultilibFilename);
22906c3fb27SDimitry Andric     findMultilibsFromYAML(*this, D, MultilibPath, Args, Result);
23006c3fb27SDimitry Andric     SelectedMultilibs = Result.SelectedMultilibs;
23106c3fb27SDimitry Andric     Multilibs = Result.Multilibs;
232e8d8bef9SDimitry Andric   }
233e8d8bef9SDimitry Andric }
234e8d8bef9SDimitry Andric 
2350b57cec5SDimitry Andric bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
236349cc55cSDimitry Andric   return isARMBareMetal(Triple) || isAArch64BareMetal(Triple) ||
23706c3fb27SDimitry Andric          isRISCVBareMetal(Triple) || isPPCBareMetal(Triple);
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric Tool *BareMetal::buildLinker() const {
2410b57cec5SDimitry Andric   return new tools::baremetal::Linker(*this);
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
24406c3fb27SDimitry Andric Tool *BareMetal::buildStaticLibTool() const {
24506c3fb27SDimitry Andric   return new tools::baremetal::StaticLibTool(*this);
24606c3fb27SDimitry Andric }
24706c3fb27SDimitry Andric 
248e8d8bef9SDimitry Andric std::string BareMetal::computeSysRoot() const {
24906c3fb27SDimitry Andric   return computeBaseSysRoot(getDriver(), getTriple());
25006c3fb27SDimitry Andric }
251e8d8bef9SDimitry Andric 
25206c3fb27SDimitry Andric BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
25306c3fb27SDimitry Andric   // Get multilibs in reverse order because they're ordered most-specific last.
25406c3fb27SDimitry Andric   if (!SelectedMultilibs.empty())
25506c3fb27SDimitry Andric     return llvm::reverse(SelectedMultilibs);
256e8d8bef9SDimitry Andric 
25706c3fb27SDimitry Andric   // No multilibs selected so return a single default multilib.
25806c3fb27SDimitry Andric   static const llvm::SmallVector<Multilib> Default = {Multilib()};
25906c3fb27SDimitry Andric   return llvm::reverse(Default);
260e8d8bef9SDimitry Andric }
261e8d8bef9SDimitry Andric 
2620b57cec5SDimitry Andric void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
2630b57cec5SDimitry Andric                                           ArgStringList &CC1Args) const {
2640b57cec5SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdinc))
2650b57cec5SDimitry Andric     return;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
2680b57cec5SDimitry Andric     SmallString<128> Dir(getDriver().ResourceDir);
2690b57cec5SDimitry Andric     llvm::sys::path::append(Dir, "include");
2700b57cec5SDimitry Andric     addSystemInclude(DriverArgs, CC1Args, Dir.str());
2710b57cec5SDimitry Andric   }
2720b57cec5SDimitry Andric 
273*0fca6ea1SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
274*0fca6ea1SDimitry Andric     return;
275*0fca6ea1SDimitry Andric 
276*0fca6ea1SDimitry Andric   if (std::optional<std::string> Path = getStdlibIncludePath())
277*0fca6ea1SDimitry Andric     addSystemInclude(DriverArgs, CC1Args, *Path);
278*0fca6ea1SDimitry Andric 
27906c3fb27SDimitry Andric   const SmallString<128> SysRoot(computeSysRoot());
28006c3fb27SDimitry Andric   if (!SysRoot.empty()) {
28106c3fb27SDimitry Andric     for (const Multilib &M : getOrderedMultilibs()) {
28206c3fb27SDimitry Andric       SmallString<128> Dir(SysRoot);
28306c3fb27SDimitry Andric       llvm::sys::path::append(Dir, M.includeSuffix());
2840b57cec5SDimitry Andric       llvm::sys::path::append(Dir, "include");
2850b57cec5SDimitry Andric       addSystemInclude(DriverArgs, CC1Args, Dir.str());
2860b57cec5SDimitry Andric     }
2870b57cec5SDimitry Andric   }
288e8d8bef9SDimitry Andric }
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
2910b57cec5SDimitry Andric                                       ArgStringList &CC1Args,
2920b57cec5SDimitry Andric                                       Action::OffloadKind) const {
2930b57cec5SDimitry Andric   CC1Args.push_back("-nostdsysteminc");
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
296bdd1243dSDimitry Andric void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
297bdd1243dSDimitry Andric                                              ArgStringList &CC1Args) const {
2981db9f3b2SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
2991db9f3b2SDimitry Andric                         options::OPT_nostdincxx))
3000b57cec5SDimitry Andric     return;
3010b57cec5SDimitry Andric 
302bdd1243dSDimitry Andric   const Driver &D = getDriver();
303*0fca6ea1SDimitry Andric   std::string Target = getTripleString();
304*0fca6ea1SDimitry Andric 
305*0fca6ea1SDimitry Andric   auto AddCXXIncludePath = [&](StringRef Path) {
306*0fca6ea1SDimitry Andric     std::string Version = detectLibcxxVersion(Path);
307*0fca6ea1SDimitry Andric     if (Version.empty())
308*0fca6ea1SDimitry Andric       return;
309*0fca6ea1SDimitry Andric 
310*0fca6ea1SDimitry Andric     {
311*0fca6ea1SDimitry Andric       // First the per-target include dir: include/<target>/c++/v1.
312*0fca6ea1SDimitry Andric       SmallString<128> TargetDir(Path);
313*0fca6ea1SDimitry Andric       llvm::sys::path::append(TargetDir, Target, "c++", Version);
314*0fca6ea1SDimitry Andric       addSystemInclude(DriverArgs, CC1Args, TargetDir);
315*0fca6ea1SDimitry Andric     }
316*0fca6ea1SDimitry Andric 
317*0fca6ea1SDimitry Andric     {
318*0fca6ea1SDimitry Andric       // Then the generic dir: include/c++/v1.
319*0fca6ea1SDimitry Andric       SmallString<128> Dir(Path);
320*0fca6ea1SDimitry Andric       llvm::sys::path::append(Dir, "c++", Version);
321*0fca6ea1SDimitry Andric       addSystemInclude(DriverArgs, CC1Args, Dir);
322*0fca6ea1SDimitry Andric     }
323*0fca6ea1SDimitry Andric   };
324*0fca6ea1SDimitry Andric 
325*0fca6ea1SDimitry Andric   switch (GetCXXStdlibType(DriverArgs)) {
326*0fca6ea1SDimitry Andric     case ToolChain::CST_Libcxx: {
327*0fca6ea1SDimitry Andric       SmallString<128> P(D.Dir);
328*0fca6ea1SDimitry Andric       llvm::sys::path::append(P, "..", "include");
329*0fca6ea1SDimitry Andric       AddCXXIncludePath(P);
330*0fca6ea1SDimitry Andric       break;
331*0fca6ea1SDimitry Andric     }
332*0fca6ea1SDimitry Andric     case ToolChain::CST_Libstdcxx:
333*0fca6ea1SDimitry Andric       // We only support libc++ toolchain installation.
334*0fca6ea1SDimitry Andric       break;
335*0fca6ea1SDimitry Andric   }
336*0fca6ea1SDimitry Andric 
337e8d8bef9SDimitry Andric   std::string SysRoot(computeSysRoot());
3380b57cec5SDimitry Andric   if (SysRoot.empty())
3390b57cec5SDimitry Andric     return;
3400b57cec5SDimitry Andric 
34106c3fb27SDimitry Andric   for (const Multilib &M : getOrderedMultilibs()) {
34206c3fb27SDimitry Andric     SmallString<128> Dir(SysRoot);
34306c3fb27SDimitry Andric     llvm::sys::path::append(Dir, M.gccSuffix());
3440b57cec5SDimitry Andric     switch (GetCXXStdlibType(DriverArgs)) {
3450b57cec5SDimitry Andric     case ToolChain::CST_Libcxx: {
346bdd1243dSDimitry Andric       // First check sysroot/usr/include/c++/v1 if it exists.
34706c3fb27SDimitry Andric       SmallString<128> TargetDir(Dir);
348bdd1243dSDimitry Andric       llvm::sys::path::append(TargetDir, "usr", "include", "c++", "v1");
349bdd1243dSDimitry Andric       if (D.getVFS().exists(TargetDir)) {
350bdd1243dSDimitry Andric         addSystemInclude(DriverArgs, CC1Args, TargetDir.str());
351bdd1243dSDimitry Andric         break;
352bdd1243dSDimitry Andric       }
353bdd1243dSDimitry Andric       // Add generic path if nothing else succeeded so far.
3540b57cec5SDimitry Andric       llvm::sys::path::append(Dir, "include", "c++", "v1");
3550b57cec5SDimitry Andric       addSystemInclude(DriverArgs, CC1Args, Dir.str());
3560b57cec5SDimitry Andric       break;
3570b57cec5SDimitry Andric     }
3580b57cec5SDimitry Andric     case ToolChain::CST_Libstdcxx: {
3590b57cec5SDimitry Andric       llvm::sys::path::append(Dir, "include", "c++");
3600b57cec5SDimitry Andric       std::error_code EC;
3610b57cec5SDimitry Andric       Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""};
3620b57cec5SDimitry Andric       // Walk the subdirs, and find the one with the newest gcc version:
36306c3fb27SDimitry Andric       for (llvm::vfs::directory_iterator
36406c3fb27SDimitry Andric                LI = D.getVFS().dir_begin(Dir.str(), EC),
3650b57cec5SDimitry Andric                LE;
3660b57cec5SDimitry Andric            !EC && LI != LE; LI = LI.increment(EC)) {
3670b57cec5SDimitry Andric         StringRef VersionText = llvm::sys::path::filename(LI->path());
3680b57cec5SDimitry Andric         auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
3690b57cec5SDimitry Andric         if (CandidateVersion.Major == -1)
3700b57cec5SDimitry Andric           continue;
3710b57cec5SDimitry Andric         if (CandidateVersion <= Version)
3720b57cec5SDimitry Andric           continue;
3730b57cec5SDimitry Andric         Version = CandidateVersion;
3740b57cec5SDimitry Andric       }
37506c3fb27SDimitry Andric       if (Version.Major != -1) {
3760b57cec5SDimitry Andric         llvm::sys::path::append(Dir, Version.Text);
3770b57cec5SDimitry Andric         addSystemInclude(DriverArgs, CC1Args, Dir.str());
37806c3fb27SDimitry Andric       }
3790b57cec5SDimitry Andric       break;
3800b57cec5SDimitry Andric     }
3810b57cec5SDimitry Andric     }
3820b57cec5SDimitry Andric   }
38306c3fb27SDimitry Andric }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
3860b57cec5SDimitry Andric                                     ArgStringList &CmdArgs) const {
3870b57cec5SDimitry Andric   switch (GetCXXStdlibType(Args)) {
3880b57cec5SDimitry Andric   case ToolChain::CST_Libcxx:
3890b57cec5SDimitry Andric     CmdArgs.push_back("-lc++");
390fcaf7f86SDimitry Andric     if (Args.hasArg(options::OPT_fexperimental_library))
391fcaf7f86SDimitry Andric       CmdArgs.push_back("-lc++experimental");
3920b57cec5SDimitry Andric     CmdArgs.push_back("-lc++abi");
3930b57cec5SDimitry Andric     break;
3940b57cec5SDimitry Andric   case ToolChain::CST_Libstdcxx:
3950b57cec5SDimitry Andric     CmdArgs.push_back("-lstdc++");
3960b57cec5SDimitry Andric     CmdArgs.push_back("-lsupc++");
3970b57cec5SDimitry Andric     break;
3980b57cec5SDimitry Andric   }
3990b57cec5SDimitry Andric   CmdArgs.push_back("-lunwind");
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric void BareMetal::AddLinkRuntimeLib(const ArgList &Args,
4030b57cec5SDimitry Andric                                   ArgStringList &CmdArgs) const {
404e8d8bef9SDimitry Andric   ToolChain::RuntimeLibType RLT = GetRuntimeLibType(Args);
405e8d8bef9SDimitry Andric   switch (RLT) {
406bdd1243dSDimitry Andric   case ToolChain::RLT_CompilerRT: {
407*0fca6ea1SDimitry Andric     CmdArgs.push_back(getCompilerRTArgString(Args, "builtins"));
408e8d8bef9SDimitry Andric     return;
409bdd1243dSDimitry Andric   }
410e8d8bef9SDimitry Andric   case ToolChain::RLT_Libgcc:
411e8d8bef9SDimitry Andric     CmdArgs.push_back("-lgcc");
412e8d8bef9SDimitry Andric     return;
413e8d8bef9SDimitry Andric   }
414e8d8bef9SDimitry Andric   llvm_unreachable("Unhandled RuntimeLibType.");
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric 
41706c3fb27SDimitry Andric void baremetal::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
41806c3fb27SDimitry Andric                                             const InputInfo &Output,
41906c3fb27SDimitry Andric                                             const InputInfoList &Inputs,
42006c3fb27SDimitry Andric                                             const ArgList &Args,
42106c3fb27SDimitry Andric                                             const char *LinkingOutput) const {
42206c3fb27SDimitry Andric   const Driver &D = getToolChain().getDriver();
42306c3fb27SDimitry Andric 
42406c3fb27SDimitry Andric   // Silence warning for "clang -g foo.o -o foo"
42506c3fb27SDimitry Andric   Args.ClaimAllArgs(options::OPT_g_Group);
42606c3fb27SDimitry Andric   // and "clang -emit-llvm foo.o -o foo"
42706c3fb27SDimitry Andric   Args.ClaimAllArgs(options::OPT_emit_llvm);
42806c3fb27SDimitry Andric   // and for "clang -w foo.o -o foo". Other warning options are already
42906c3fb27SDimitry Andric   // handled somewhere else.
43006c3fb27SDimitry Andric   Args.ClaimAllArgs(options::OPT_w);
43106c3fb27SDimitry Andric   // Silence warnings when linking C code with a C++ '-stdlib' argument.
43206c3fb27SDimitry Andric   Args.ClaimAllArgs(options::OPT_stdlib_EQ);
43306c3fb27SDimitry Andric 
43406c3fb27SDimitry Andric   // ar tool command "llvm-ar <options> <output_file> <input_files>".
43506c3fb27SDimitry Andric   ArgStringList CmdArgs;
43606c3fb27SDimitry Andric   // Create and insert file members with a deterministic index.
43706c3fb27SDimitry Andric   CmdArgs.push_back("rcsD");
43806c3fb27SDimitry Andric   CmdArgs.push_back(Output.getFilename());
43906c3fb27SDimitry Andric 
44006c3fb27SDimitry Andric   for (const auto &II : Inputs) {
44106c3fb27SDimitry Andric     if (II.isFilename()) {
44206c3fb27SDimitry Andric       CmdArgs.push_back(II.getFilename());
44306c3fb27SDimitry Andric     }
44406c3fb27SDimitry Andric   }
44506c3fb27SDimitry Andric 
44606c3fb27SDimitry Andric   // Delete old output archive file if it already exists before generating a new
44706c3fb27SDimitry Andric   // archive file.
44806c3fb27SDimitry Andric   const char *OutputFileName = Output.getFilename();
44906c3fb27SDimitry Andric   if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
45006c3fb27SDimitry Andric     if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
45106c3fb27SDimitry Andric       D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
45206c3fb27SDimitry Andric       return;
45306c3fb27SDimitry Andric     }
45406c3fb27SDimitry Andric   }
45506c3fb27SDimitry Andric 
45606c3fb27SDimitry Andric   const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
45706c3fb27SDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this,
45806c3fb27SDimitry Andric                                          ResponseFileSupport::AtFileCurCP(),
45906c3fb27SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
46006c3fb27SDimitry Andric }
46106c3fb27SDimitry Andric 
4620b57cec5SDimitry Andric void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
4630b57cec5SDimitry Andric                                      const InputInfo &Output,
4640b57cec5SDimitry Andric                                      const InputInfoList &Inputs,
4650b57cec5SDimitry Andric                                      const ArgList &Args,
4660b57cec5SDimitry Andric                                      const char *LinkingOutput) const {
4670b57cec5SDimitry Andric   ArgStringList CmdArgs;
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric   auto &TC = static_cast<const toolchains::BareMetal &>(getToolChain());
470*0fca6ea1SDimitry Andric   const Driver &D = getToolChain().getDriver();
47106c3fb27SDimitry Andric   const llvm::Triple::ArchType Arch = TC.getArch();
47206c3fb27SDimitry Andric   const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   CmdArgs.push_back("-Bstatic");
4770b57cec5SDimitry Andric 
478*0fca6ea1SDimitry Andric   if (TC.getTriple().isRISCV() && Args.hasArg(options::OPT_mno_relax))
479*0fca6ea1SDimitry Andric     CmdArgs.push_back("--no-relax");
480*0fca6ea1SDimitry Andric 
48106c3fb27SDimitry Andric   if (Triple.isARM() || Triple.isThumb()) {
48206c3fb27SDimitry Andric     bool IsBigEndian = arm::isARMBigEndian(Triple, Args);
48306c3fb27SDimitry Andric     if (IsBigEndian)
48406c3fb27SDimitry Andric       arm::appendBE8LinkFlag(Args, CmdArgs, Triple);
48506c3fb27SDimitry Andric     CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
48606c3fb27SDimitry Andric   } else if (Triple.isAArch64()) {
48706c3fb27SDimitry Andric     CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL");
48806c3fb27SDimitry Andric   }
48906c3fb27SDimitry Andric 
4905f757f3fSDimitry Andric   Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
4915f757f3fSDimitry Andric                             options::OPT_s, options::OPT_t, options::OPT_r});
4920b57cec5SDimitry Andric 
493fe6060f1SDimitry Andric   TC.AddFilePathLibArgs(Args, CmdArgs);
494fe6060f1SDimitry Andric 
495bdd1243dSDimitry Andric   for (const auto &LibPath : TC.getLibraryPaths())
496bdd1243dSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-L", LibPath)));
497bdd1243dSDimitry Andric 
4980b57cec5SDimitry Andric   if (TC.ShouldLinkCXXStdlib(Args))
4990b57cec5SDimitry Andric     TC.AddCXXStdlibLibArgs(Args, CmdArgs);
500bdd1243dSDimitry Andric 
5010b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
5020b57cec5SDimitry Andric     CmdArgs.push_back("-lc");
5030b57cec5SDimitry Andric     CmdArgs.push_back("-lm");
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric     TC.AddLinkRuntimeLib(Args, CmdArgs);
5060b57cec5SDimitry Andric   }
5070b57cec5SDimitry Andric 
508*0fca6ea1SDimitry Andric   if (D.isUsingLTO()) {
509*0fca6ea1SDimitry Andric     assert(!Inputs.empty() && "Must have at least one input.");
510*0fca6ea1SDimitry Andric     // Find the first filename InputInfo object.
511*0fca6ea1SDimitry Andric     auto Input = llvm::find_if(
512*0fca6ea1SDimitry Andric         Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
513*0fca6ea1SDimitry Andric     if (Input == Inputs.end())
514*0fca6ea1SDimitry Andric       // For a very rare case, all of the inputs to the linker are
515*0fca6ea1SDimitry Andric       // InputArg. If that happens, just use the first InputInfo.
516*0fca6ea1SDimitry Andric       Input = Inputs.begin();
517*0fca6ea1SDimitry Andric 
518*0fca6ea1SDimitry Andric     addLTOOptions(TC, Args, CmdArgs, Output, *Input,
519*0fca6ea1SDimitry Andric                   D.getLTOMode() == LTOK_Thin);
520*0fca6ea1SDimitry Andric   }
52106c3fb27SDimitry Andric   if (TC.getTriple().isRISCV())
52206c3fb27SDimitry Andric     CmdArgs.push_back("-X");
52306c3fb27SDimitry Andric 
52406c3fb27SDimitry Andric   // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
52506c3fb27SDimitry Andric   // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
52606c3fb27SDimitry Andric   // arm*-*-*bsd).
52706c3fb27SDimitry Andric   if (isARMBareMetal(TC.getTriple()))
52806c3fb27SDimitry Andric     CmdArgs.push_back("--target2=rel");
52906c3fb27SDimitry Andric 
5300b57cec5SDimitry Andric   CmdArgs.push_back("-o");
5310b57cec5SDimitry Andric   CmdArgs.push_back(Output.getFilename());
5320b57cec5SDimitry Andric 
53306c3fb27SDimitry Andric   C.addCommand(std::make_unique<Command>(
53406c3fb27SDimitry Andric       JA, *this, ResponseFileSupport::AtFileCurCP(),
53506c3fb27SDimitry Andric       Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs, Output));
5360b57cec5SDimitry Andric }
5375f757f3fSDimitry Andric 
5385f757f3fSDimitry Andric // BareMetal toolchain allows all sanitizers where the compiler generates valid
5395f757f3fSDimitry Andric // code, ignoring all runtime library support issues on the assumption that
5405f757f3fSDimitry Andric // baremetal targets typically implement their own runtime support.
5415f757f3fSDimitry Andric SanitizerMask BareMetal::getSupportedSanitizers() const {
5425f757f3fSDimitry Andric   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
5435f757f3fSDimitry Andric   const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 ||
5445f757f3fSDimitry Andric                          getTriple().getArch() == llvm::Triple::aarch64_be;
5455f757f3fSDimitry Andric   const bool IsRISCV64 = getTriple().getArch() == llvm::Triple::riscv64;
5465f757f3fSDimitry Andric   SanitizerMask Res = ToolChain::getSupportedSanitizers();
5475f757f3fSDimitry Andric   Res |= SanitizerKind::Address;
5485f757f3fSDimitry Andric   Res |= SanitizerKind::KernelAddress;
5495f757f3fSDimitry Andric   Res |= SanitizerKind::PointerCompare;
5505f757f3fSDimitry Andric   Res |= SanitizerKind::PointerSubtract;
5515f757f3fSDimitry Andric   Res |= SanitizerKind::Fuzzer;
5525f757f3fSDimitry Andric   Res |= SanitizerKind::FuzzerNoLink;
5535f757f3fSDimitry Andric   Res |= SanitizerKind::Vptr;
5545f757f3fSDimitry Andric   Res |= SanitizerKind::SafeStack;
5555f757f3fSDimitry Andric   Res |= SanitizerKind::Thread;
5565f757f3fSDimitry Andric   Res |= SanitizerKind::Scudo;
5575f757f3fSDimitry Andric   if (IsX86_64 || IsAArch64 || IsRISCV64) {
5585f757f3fSDimitry Andric     Res |= SanitizerKind::HWAddress;
5595f757f3fSDimitry Andric     Res |= SanitizerKind::KernelHWAddress;
5605f757f3fSDimitry Andric   }
5615f757f3fSDimitry Andric   return Res;
5625f757f3fSDimitry Andric }
563