xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChains/OHOS.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric //===--- OHOS.cpp - OHOS ToolChain Implementations --------*- C++ -*-===//
2*06c3fb27SDimitry Andric //
3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06c3fb27SDimitry Andric //
7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
8*06c3fb27SDimitry Andric 
9*06c3fb27SDimitry Andric #include "OHOS.h"
10*06c3fb27SDimitry Andric #include "Arch/ARM.h"
11*06c3fb27SDimitry Andric #include "CommonArgs.h"
12*06c3fb27SDimitry Andric #include "clang/Config/config.h"
13*06c3fb27SDimitry Andric #include "clang/Driver/Compilation.h"
14*06c3fb27SDimitry Andric #include "clang/Driver/Driver.h"
15*06c3fb27SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
16*06c3fb27SDimitry Andric #include "clang/Driver/Options.h"
17*06c3fb27SDimitry Andric #include "clang/Driver/SanitizerArgs.h"
18*06c3fb27SDimitry Andric #include "llvm/Option/ArgList.h"
19*06c3fb27SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
20*06c3fb27SDimitry Andric #include "llvm/Support/FileSystem.h"
21*06c3fb27SDimitry Andric #include "llvm/Support/Path.h"
22*06c3fb27SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
23*06c3fb27SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
24*06c3fb27SDimitry Andric 
25*06c3fb27SDimitry Andric using namespace clang::driver;
26*06c3fb27SDimitry Andric using namespace clang::driver::toolchains;
27*06c3fb27SDimitry Andric using namespace clang::driver::tools;
28*06c3fb27SDimitry Andric using namespace clang;
29*06c3fb27SDimitry Andric using namespace llvm::opt;
30*06c3fb27SDimitry Andric using namespace clang::driver::tools::arm;
31*06c3fb27SDimitry Andric 
32*06c3fb27SDimitry Andric using tools::addMultilibFlag;
33*06c3fb27SDimitry Andric using tools::addPathIfExists;
34*06c3fb27SDimitry Andric 
35*06c3fb27SDimitry Andric static bool findOHOSMuslMultilibs(const Multilib::flags_list &Flags,
36*06c3fb27SDimitry Andric                                   DetectedMultilibs &Result) {
37*06c3fb27SDimitry Andric   MultilibSet Multilibs;
38*06c3fb27SDimitry Andric   Multilibs.push_back(Multilib());
39*06c3fb27SDimitry Andric   // -mcpu=cortex-a7
40*06c3fb27SDimitry Andric   // -mfloat-abi=soft -mfloat-abi=softfp -mfloat-abi=hard
41*06c3fb27SDimitry Andric   // -mfpu=neon-vfpv4
42*06c3fb27SDimitry Andric   Multilibs.push_back(
43*06c3fb27SDimitry Andric       Multilib("/a7_soft", {}, {}, {"-mcpu=cortex-a7", "-mfloat-abi=soft"}));
44*06c3fb27SDimitry Andric 
45*06c3fb27SDimitry Andric   Multilibs.push_back(
46*06c3fb27SDimitry Andric       Multilib("/a7_softfp_neon-vfpv4", {}, {},
47*06c3fb27SDimitry Andric                {"-mcpu=cortex-a7", "-mfloat-abi=softfp", "-mfpu=neon-vfpv4"}));
48*06c3fb27SDimitry Andric 
49*06c3fb27SDimitry Andric   Multilibs.push_back(
50*06c3fb27SDimitry Andric       Multilib("/a7_hard_neon-vfpv4", {}, {},
51*06c3fb27SDimitry Andric                {"-mcpu=cortex-a7", "-mfloat-abi=hard", "-mfpu=neon-vfpv4"}));
52*06c3fb27SDimitry Andric 
53*06c3fb27SDimitry Andric   if (Multilibs.select(Flags, Result.SelectedMultilibs)) {
54*06c3fb27SDimitry Andric     Result.Multilibs = Multilibs;
55*06c3fb27SDimitry Andric     return true;
56*06c3fb27SDimitry Andric   }
57*06c3fb27SDimitry Andric   return false;
58*06c3fb27SDimitry Andric }
59*06c3fb27SDimitry Andric 
60*06c3fb27SDimitry Andric static bool findOHOSMultilibs(const Driver &D,
61*06c3fb27SDimitry Andric                                       const ToolChain &TC,
62*06c3fb27SDimitry Andric                                       const llvm::Triple &TargetTriple,
63*06c3fb27SDimitry Andric                                       StringRef Path, const ArgList &Args,
64*06c3fb27SDimitry Andric                                       DetectedMultilibs &Result) {
65*06c3fb27SDimitry Andric   Multilib::flags_list Flags;
66*06c3fb27SDimitry Andric   bool IsA7 = false;
67*06c3fb27SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
68*06c3fb27SDimitry Andric     IsA7 = A->getValue() == StringRef("cortex-a7");
69*06c3fb27SDimitry Andric   addMultilibFlag(IsA7, "-mcpu=cortex-a7", Flags);
70*06c3fb27SDimitry Andric 
71*06c3fb27SDimitry Andric   bool IsMFPU = false;
72*06c3fb27SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
73*06c3fb27SDimitry Andric     IsMFPU = A->getValue() == StringRef("neon-vfpv4");
74*06c3fb27SDimitry Andric   addMultilibFlag(IsMFPU, "-mfpu=neon-vfpv4", Flags);
75*06c3fb27SDimitry Andric 
76*06c3fb27SDimitry Andric   tools::arm::FloatABI ARMFloatABI = getARMFloatABI(D, TargetTriple, Args);
77*06c3fb27SDimitry Andric   addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Soft),
78*06c3fb27SDimitry Andric                   "-mfloat-abi=soft", Flags);
79*06c3fb27SDimitry Andric   addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::SoftFP),
80*06c3fb27SDimitry Andric                   "-mfloat-abi=softfp", Flags);
81*06c3fb27SDimitry Andric   addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Hard),
82*06c3fb27SDimitry Andric                   "-mfloat-abi=hard", Flags);
83*06c3fb27SDimitry Andric 
84*06c3fb27SDimitry Andric   return findOHOSMuslMultilibs(Flags, Result);
85*06c3fb27SDimitry Andric }
86*06c3fb27SDimitry Andric 
87*06c3fb27SDimitry Andric std::string OHOS::getMultiarchTriple(const llvm::Triple &T) const {
88*06c3fb27SDimitry Andric   // For most architectures, just use whatever we have rather than trying to be
89*06c3fb27SDimitry Andric   // clever.
90*06c3fb27SDimitry Andric   switch (T.getArch()) {
91*06c3fb27SDimitry Andric   default:
92*06c3fb27SDimitry Andric     break;
93*06c3fb27SDimitry Andric 
94*06c3fb27SDimitry Andric   // We use the existence of '/lib/<triple>' as a directory to detect some
95*06c3fb27SDimitry Andric   // common linux triples that don't quite match the Clang triple for both
96*06c3fb27SDimitry Andric   // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
97*06c3fb27SDimitry Andric   // regardless of what the actual target triple is.
98*06c3fb27SDimitry Andric   case llvm::Triple::arm:
99*06c3fb27SDimitry Andric   case llvm::Triple::thumb:
100*06c3fb27SDimitry Andric     return T.isOSLiteOS() ? "arm-liteos-ohos" : "arm-linux-ohos";
101*06c3fb27SDimitry Andric   case llvm::Triple::riscv32:
102*06c3fb27SDimitry Andric     return "riscv32-linux-ohos";
103*06c3fb27SDimitry Andric   case llvm::Triple::riscv64:
104*06c3fb27SDimitry Andric     return "riscv64-linux-ohos";
105*06c3fb27SDimitry Andric   case llvm::Triple::mipsel:
106*06c3fb27SDimitry Andric     return "mipsel-linux-ohos";
107*06c3fb27SDimitry Andric   case llvm::Triple::x86:
108*06c3fb27SDimitry Andric     return "i686-linux-ohos";
109*06c3fb27SDimitry Andric   case llvm::Triple::x86_64:
110*06c3fb27SDimitry Andric     return "x86_64-linux-ohos";
111*06c3fb27SDimitry Andric   case llvm::Triple::aarch64:
112*06c3fb27SDimitry Andric     return "aarch64-linux-ohos";
113*06c3fb27SDimitry Andric   }
114*06c3fb27SDimitry Andric   return T.str();
115*06c3fb27SDimitry Andric }
116*06c3fb27SDimitry Andric 
117*06c3fb27SDimitry Andric std::string OHOS::getMultiarchTriple(const Driver &D,
118*06c3fb27SDimitry Andric                                      const llvm::Triple &TargetTriple,
119*06c3fb27SDimitry Andric                                      StringRef SysRoot) const {
120*06c3fb27SDimitry Andric   return getMultiarchTriple(TargetTriple);
121*06c3fb27SDimitry Andric }
122*06c3fb27SDimitry Andric 
123*06c3fb27SDimitry Andric static std::string makePath(const std::initializer_list<std::string> &IL) {
124*06c3fb27SDimitry Andric   SmallString<128> P;
125*06c3fb27SDimitry Andric   for (const auto &S : IL)
126*06c3fb27SDimitry Andric     llvm::sys::path::append(P, S);
127*06c3fb27SDimitry Andric   return static_cast<std::string>(P.str());
128*06c3fb27SDimitry Andric }
129*06c3fb27SDimitry Andric 
130*06c3fb27SDimitry Andric /// OHOS Toolchain
131*06c3fb27SDimitry Andric OHOS::OHOS(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
132*06c3fb27SDimitry Andric     : Generic_ELF(D, Triple, Args) {
133*06c3fb27SDimitry Andric   std::string SysRoot = computeSysRoot();
134*06c3fb27SDimitry Andric 
135*06c3fb27SDimitry Andric   // Select the correct multilib according to the given arguments.
136*06c3fb27SDimitry Andric   DetectedMultilibs Result;
137*06c3fb27SDimitry Andric   findOHOSMultilibs(D, *this, Triple, "", Args, Result);
138*06c3fb27SDimitry Andric   Multilibs = Result.Multilibs;
139*06c3fb27SDimitry Andric   SelectedMultilibs = Result.SelectedMultilibs;
140*06c3fb27SDimitry Andric   if (!SelectedMultilibs.empty()) {
141*06c3fb27SDimitry Andric     SelectedMultilib = SelectedMultilibs.back();
142*06c3fb27SDimitry Andric   }
143*06c3fb27SDimitry Andric 
144*06c3fb27SDimitry Andric   getFilePaths().clear();
145*06c3fb27SDimitry Andric   for (const auto &CandidateLibPath : getArchSpecificLibPaths())
146*06c3fb27SDimitry Andric     if (getVFS().exists(CandidateLibPath))
147*06c3fb27SDimitry Andric       getFilePaths().push_back(CandidateLibPath);
148*06c3fb27SDimitry Andric 
149*06c3fb27SDimitry Andric   getLibraryPaths().clear();
150*06c3fb27SDimitry Andric   for (auto &Path : getRuntimePaths())
151*06c3fb27SDimitry Andric     if (getVFS().exists(Path))
152*06c3fb27SDimitry Andric       getLibraryPaths().push_back(Path);
153*06c3fb27SDimitry Andric 
154*06c3fb27SDimitry Andric   // OHOS sysroots contain a library directory for each supported OS
155*06c3fb27SDimitry Andric   // version as well as some unversioned libraries in the usual multiarch
156*06c3fb27SDimitry Andric   // directory. Support --target=aarch64-linux-ohosX.Y.Z or
157*06c3fb27SDimitry Andric   // --target=aarch64-linux-ohosX.Y or --target=aarch64-linux-ohosX
158*06c3fb27SDimitry Andric   path_list &Paths = getFilePaths();
159*06c3fb27SDimitry Andric   std::string SysRootLibPath = makePath({SysRoot, "usr", "lib"});
160*06c3fb27SDimitry Andric   std::string MultiarchTriple = getMultiarchTriple(getTriple());
161*06c3fb27SDimitry Andric   addPathIfExists(D, makePath({SysRootLibPath, SelectedMultilib.gccSuffix()}),
162*06c3fb27SDimitry Andric                   Paths);
163*06c3fb27SDimitry Andric   addPathIfExists(D,
164*06c3fb27SDimitry Andric                   makePath({D.Dir, "..", "lib", MultiarchTriple,
165*06c3fb27SDimitry Andric                             SelectedMultilib.gccSuffix()}),
166*06c3fb27SDimitry Andric                   Paths);
167*06c3fb27SDimitry Andric 
168*06c3fb27SDimitry Andric   addPathIfExists(
169*06c3fb27SDimitry Andric       D,
170*06c3fb27SDimitry Andric       makePath({SysRootLibPath, MultiarchTriple, SelectedMultilib.gccSuffix()}),
171*06c3fb27SDimitry Andric       Paths);
172*06c3fb27SDimitry Andric }
173*06c3fb27SDimitry Andric 
174*06c3fb27SDimitry Andric ToolChain::RuntimeLibType OHOS::GetRuntimeLibType(
175*06c3fb27SDimitry Andric     const ArgList &Args) const {
176*06c3fb27SDimitry Andric   if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) {
177*06c3fb27SDimitry Andric     StringRef Value = A->getValue();
178*06c3fb27SDimitry Andric     if (Value != "compiler-rt")
179*06c3fb27SDimitry Andric       getDriver().Diag(clang::diag::err_drv_invalid_rtlib_name)
180*06c3fb27SDimitry Andric           << A->getAsString(Args);
181*06c3fb27SDimitry Andric   }
182*06c3fb27SDimitry Andric 
183*06c3fb27SDimitry Andric   return ToolChain::RLT_CompilerRT;
184*06c3fb27SDimitry Andric }
185*06c3fb27SDimitry Andric 
186*06c3fb27SDimitry Andric ToolChain::CXXStdlibType
187*06c3fb27SDimitry Andric OHOS::GetCXXStdlibType(const ArgList &Args) const {
188*06c3fb27SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
189*06c3fb27SDimitry Andric     StringRef Value = A->getValue();
190*06c3fb27SDimitry Andric     if (Value != "libc++")
191*06c3fb27SDimitry Andric       getDriver().Diag(diag::err_drv_invalid_stdlib_name)
192*06c3fb27SDimitry Andric         << A->getAsString(Args);
193*06c3fb27SDimitry Andric   }
194*06c3fb27SDimitry Andric 
195*06c3fb27SDimitry Andric   return ToolChain::CST_Libcxx;
196*06c3fb27SDimitry Andric }
197*06c3fb27SDimitry Andric 
198*06c3fb27SDimitry Andric void OHOS::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
199*06c3fb27SDimitry Andric                                         ArgStringList &CC1Args) const {
200*06c3fb27SDimitry Andric   const Driver &D = getDriver();
201*06c3fb27SDimitry Andric   const llvm::Triple &Triple = getTriple();
202*06c3fb27SDimitry Andric   std::string SysRoot = computeSysRoot();
203*06c3fb27SDimitry Andric 
204*06c3fb27SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdinc))
205*06c3fb27SDimitry Andric     return;
206*06c3fb27SDimitry Andric 
207*06c3fb27SDimitry Andric   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
208*06c3fb27SDimitry Andric     SmallString<128> P(D.ResourceDir);
209*06c3fb27SDimitry Andric     llvm::sys::path::append(P, "include");
210*06c3fb27SDimitry Andric     addSystemInclude(DriverArgs, CC1Args, P);
211*06c3fb27SDimitry Andric   }
212*06c3fb27SDimitry Andric 
213*06c3fb27SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
214*06c3fb27SDimitry Andric     return;
215*06c3fb27SDimitry Andric 
216*06c3fb27SDimitry Andric   // Check for configure-time C include directories.
217*06c3fb27SDimitry Andric   StringRef CIncludeDirs(C_INCLUDE_DIRS);
218*06c3fb27SDimitry Andric   if (CIncludeDirs != "") {
219*06c3fb27SDimitry Andric     SmallVector<StringRef, 5> dirs;
220*06c3fb27SDimitry Andric     CIncludeDirs.split(dirs, ":");
221*06c3fb27SDimitry Andric     for (StringRef dir : dirs) {
222*06c3fb27SDimitry Andric       StringRef Prefix =
223*06c3fb27SDimitry Andric           llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";
224*06c3fb27SDimitry Andric       addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
225*06c3fb27SDimitry Andric     }
226*06c3fb27SDimitry Andric     return;
227*06c3fb27SDimitry Andric   }
228*06c3fb27SDimitry Andric 
229*06c3fb27SDimitry Andric   addExternCSystemInclude(DriverArgs, CC1Args,
230*06c3fb27SDimitry Andric                           SysRoot + "/usr/include/" +
231*06c3fb27SDimitry Andric                               getMultiarchTriple(Triple));
232*06c3fb27SDimitry Andric   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
233*06c3fb27SDimitry Andric   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
234*06c3fb27SDimitry Andric }
235*06c3fb27SDimitry Andric 
236*06c3fb27SDimitry Andric void OHOS::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
237*06c3fb27SDimitry Andric                                         ArgStringList &CC1Args) const {
238*06c3fb27SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
239*06c3fb27SDimitry Andric       DriverArgs.hasArg(options::OPT_nostdincxx))
240*06c3fb27SDimitry Andric     return;
241*06c3fb27SDimitry Andric 
242*06c3fb27SDimitry Andric   switch (GetCXXStdlibType(DriverArgs)) {
243*06c3fb27SDimitry Andric   case ToolChain::CST_Libcxx: {
244*06c3fb27SDimitry Andric     std::string IncPath = makePath({getDriver().Dir, "..", "include"});
245*06c3fb27SDimitry Andric     std::string IncTargetPath =
246*06c3fb27SDimitry Andric         makePath({IncPath, getMultiarchTriple(getTriple()), "c++", "v1"});
247*06c3fb27SDimitry Andric     if (getVFS().exists(IncTargetPath)) {
248*06c3fb27SDimitry Andric       addSystemInclude(DriverArgs, CC1Args, makePath({IncPath, "c++", "v1"}));
249*06c3fb27SDimitry Andric       addSystemInclude(DriverArgs, CC1Args, IncTargetPath);
250*06c3fb27SDimitry Andric     }
251*06c3fb27SDimitry Andric     break;
252*06c3fb27SDimitry Andric   }
253*06c3fb27SDimitry Andric 
254*06c3fb27SDimitry Andric   default:
255*06c3fb27SDimitry Andric     llvm_unreachable("invalid stdlib name");
256*06c3fb27SDimitry Andric   }
257*06c3fb27SDimitry Andric }
258*06c3fb27SDimitry Andric 
259*06c3fb27SDimitry Andric void OHOS::AddCXXStdlibLibArgs(const ArgList &Args,
260*06c3fb27SDimitry Andric                                   ArgStringList &CmdArgs) const {
261*06c3fb27SDimitry Andric   switch (GetCXXStdlibType(Args)) {
262*06c3fb27SDimitry Andric   case ToolChain::CST_Libcxx:
263*06c3fb27SDimitry Andric     CmdArgs.push_back("-lc++");
264*06c3fb27SDimitry Andric     CmdArgs.push_back("-lc++abi");
265*06c3fb27SDimitry Andric     CmdArgs.push_back("-lunwind");
266*06c3fb27SDimitry Andric     break;
267*06c3fb27SDimitry Andric 
268*06c3fb27SDimitry Andric   case ToolChain::CST_Libstdcxx:
269*06c3fb27SDimitry Andric     llvm_unreachable("invalid stdlib name");
270*06c3fb27SDimitry Andric   }
271*06c3fb27SDimitry Andric }
272*06c3fb27SDimitry Andric 
273*06c3fb27SDimitry Andric std::string OHOS::computeSysRoot() const {
274*06c3fb27SDimitry Andric   std::string SysRoot =
275*06c3fb27SDimitry Andric       !getDriver().SysRoot.empty()
276*06c3fb27SDimitry Andric           ? getDriver().SysRoot
277*06c3fb27SDimitry Andric           : makePath({getDriver().getInstalledDir(), "..", "..", "sysroot"});
278*06c3fb27SDimitry Andric   if (!llvm::sys::fs::exists(SysRoot))
279*06c3fb27SDimitry Andric     return std::string();
280*06c3fb27SDimitry Andric 
281*06c3fb27SDimitry Andric   std::string ArchRoot = makePath({SysRoot, getMultiarchTriple(getTriple())});
282*06c3fb27SDimitry Andric   return llvm::sys::fs::exists(ArchRoot) ? ArchRoot : SysRoot;
283*06c3fb27SDimitry Andric }
284*06c3fb27SDimitry Andric 
285*06c3fb27SDimitry Andric ToolChain::path_list OHOS::getRuntimePaths() const {
286*06c3fb27SDimitry Andric   SmallString<128> P;
287*06c3fb27SDimitry Andric   path_list Paths;
288*06c3fb27SDimitry Andric   const Driver &D = getDriver();
289*06c3fb27SDimitry Andric   const llvm::Triple &Triple = getTriple();
290*06c3fb27SDimitry Andric 
291*06c3fb27SDimitry Andric   // First try the triple passed to driver as --target=<triple>.
292*06c3fb27SDimitry Andric   P.assign(D.ResourceDir);
293*06c3fb27SDimitry Andric   llvm::sys::path::append(P, "lib", D.getTargetTriple(), SelectedMultilib.gccSuffix());
294*06c3fb27SDimitry Andric   Paths.push_back(P.c_str());
295*06c3fb27SDimitry Andric 
296*06c3fb27SDimitry Andric   // Second try the normalized triple.
297*06c3fb27SDimitry Andric   P.assign(D.ResourceDir);
298*06c3fb27SDimitry Andric   llvm::sys::path::append(P, "lib", Triple.str(), SelectedMultilib.gccSuffix());
299*06c3fb27SDimitry Andric   Paths.push_back(P.c_str());
300*06c3fb27SDimitry Andric 
301*06c3fb27SDimitry Andric   // Third try the effective triple.
302*06c3fb27SDimitry Andric   P.assign(D.ResourceDir);
303*06c3fb27SDimitry Andric   std::string SysRoot = computeSysRoot();
304*06c3fb27SDimitry Andric   llvm::sys::path::append(P, "lib", getMultiarchTriple(Triple),
305*06c3fb27SDimitry Andric                           SelectedMultilib.gccSuffix());
306*06c3fb27SDimitry Andric   Paths.push_back(P.c_str());
307*06c3fb27SDimitry Andric 
308*06c3fb27SDimitry Andric   return Paths;
309*06c3fb27SDimitry Andric }
310*06c3fb27SDimitry Andric 
311*06c3fb27SDimitry Andric std::string OHOS::getDynamicLinker(const ArgList &Args) const {
312*06c3fb27SDimitry Andric   const llvm::Triple &Triple = getTriple();
313*06c3fb27SDimitry Andric   const llvm::Triple::ArchType Arch = getArch();
314*06c3fb27SDimitry Andric 
315*06c3fb27SDimitry Andric   assert(Triple.isMusl());
316*06c3fb27SDimitry Andric   std::string ArchName;
317*06c3fb27SDimitry Andric   bool IsArm = false;
318*06c3fb27SDimitry Andric 
319*06c3fb27SDimitry Andric   switch (Arch) {
320*06c3fb27SDimitry Andric   case llvm::Triple::arm:
321*06c3fb27SDimitry Andric   case llvm::Triple::thumb:
322*06c3fb27SDimitry Andric     ArchName = "arm";
323*06c3fb27SDimitry Andric     IsArm = true;
324*06c3fb27SDimitry Andric     break;
325*06c3fb27SDimitry Andric   case llvm::Triple::armeb:
326*06c3fb27SDimitry Andric   case llvm::Triple::thumbeb:
327*06c3fb27SDimitry Andric     ArchName = "armeb";
328*06c3fb27SDimitry Andric     IsArm = true;
329*06c3fb27SDimitry Andric     break;
330*06c3fb27SDimitry Andric   default:
331*06c3fb27SDimitry Andric     ArchName = Triple.getArchName().str();
332*06c3fb27SDimitry Andric   }
333*06c3fb27SDimitry Andric   if (IsArm &&
334*06c3fb27SDimitry Andric       (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard))
335*06c3fb27SDimitry Andric     ArchName += "hf";
336*06c3fb27SDimitry Andric 
337*06c3fb27SDimitry Andric   return "/lib/ld-musl-" + ArchName + ".so.1";
338*06c3fb27SDimitry Andric }
339*06c3fb27SDimitry Andric 
340*06c3fb27SDimitry Andric std::string OHOS::getCompilerRT(const ArgList &Args, StringRef Component,
341*06c3fb27SDimitry Andric                                 FileType Type) const {
342*06c3fb27SDimitry Andric   SmallString<128> Path(getDriver().ResourceDir);
343*06c3fb27SDimitry Andric   llvm::sys::path::append(Path, "lib", getMultiarchTriple(getTriple()),
344*06c3fb27SDimitry Andric                           SelectedMultilib.gccSuffix());
345*06c3fb27SDimitry Andric   const char *Prefix =
346*06c3fb27SDimitry Andric       Type == ToolChain::FT_Object ? "" : "lib";
347*06c3fb27SDimitry Andric   const char *Suffix;
348*06c3fb27SDimitry Andric   switch (Type) {
349*06c3fb27SDimitry Andric   case ToolChain::FT_Object:
350*06c3fb27SDimitry Andric     Suffix = ".o";
351*06c3fb27SDimitry Andric     break;
352*06c3fb27SDimitry Andric   case ToolChain::FT_Static:
353*06c3fb27SDimitry Andric     Suffix = ".a";
354*06c3fb27SDimitry Andric     break;
355*06c3fb27SDimitry Andric   case ToolChain::FT_Shared:
356*06c3fb27SDimitry Andric     Suffix = ".so";
357*06c3fb27SDimitry Andric     break;
358*06c3fb27SDimitry Andric   }
359*06c3fb27SDimitry Andric   llvm::sys::path::append(
360*06c3fb27SDimitry Andric       Path, Prefix + Twine("clang_rt.") + Component + Suffix);
361*06c3fb27SDimitry Andric   return static_cast<std::string>(Path.str());
362*06c3fb27SDimitry Andric }
363*06c3fb27SDimitry Andric 
364*06c3fb27SDimitry Andric void OHOS::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
365*06c3fb27SDimitry Andric   CmdArgs.push_back("-z");
366*06c3fb27SDimitry Andric   CmdArgs.push_back("now");
367*06c3fb27SDimitry Andric   CmdArgs.push_back("-z");
368*06c3fb27SDimitry Andric   CmdArgs.push_back("relro");
369*06c3fb27SDimitry Andric   CmdArgs.push_back("-z");
370*06c3fb27SDimitry Andric   CmdArgs.push_back("max-page-size=4096");
371*06c3fb27SDimitry Andric   // .gnu.hash section is not compatible with the MIPS target
372*06c3fb27SDimitry Andric   if (getArch() != llvm::Triple::mipsel)
373*06c3fb27SDimitry Andric     CmdArgs.push_back("--hash-style=both");
374*06c3fb27SDimitry Andric #ifdef ENABLE_LINKER_BUILD_ID
375*06c3fb27SDimitry Andric   CmdArgs.push_back("--build-id");
376*06c3fb27SDimitry Andric #endif
377*06c3fb27SDimitry Andric   CmdArgs.push_back("--enable-new-dtags");
378*06c3fb27SDimitry Andric }
379*06c3fb27SDimitry Andric 
380*06c3fb27SDimitry Andric SanitizerMask OHOS::getSupportedSanitizers() const {
381*06c3fb27SDimitry Andric   SanitizerMask Res = ToolChain::getSupportedSanitizers();
382*06c3fb27SDimitry Andric   Res |= SanitizerKind::Address;
383*06c3fb27SDimitry Andric   Res |= SanitizerKind::PointerCompare;
384*06c3fb27SDimitry Andric   Res |= SanitizerKind::PointerSubtract;
385*06c3fb27SDimitry Andric   Res |= SanitizerKind::Fuzzer;
386*06c3fb27SDimitry Andric   Res |= SanitizerKind::FuzzerNoLink;
387*06c3fb27SDimitry Andric   Res |= SanitizerKind::Memory;
388*06c3fb27SDimitry Andric   Res |= SanitizerKind::Vptr;
389*06c3fb27SDimitry Andric   Res |= SanitizerKind::SafeStack;
390*06c3fb27SDimitry Andric   Res |= SanitizerKind::Scudo;
391*06c3fb27SDimitry Andric   // TODO: kASAN for liteos ??
392*06c3fb27SDimitry Andric   // TODO: Support TSAN and HWASAN and update mask.
393*06c3fb27SDimitry Andric   return Res;
394*06c3fb27SDimitry Andric }
395*06c3fb27SDimitry Andric 
396*06c3fb27SDimitry Andric // TODO: Make a base class for Linux and OHOS and move this there.
397*06c3fb27SDimitry Andric void OHOS::addProfileRTLibs(const llvm::opt::ArgList &Args,
398*06c3fb27SDimitry Andric                              llvm::opt::ArgStringList &CmdArgs) const {
399*06c3fb27SDimitry Andric   // Add linker option -u__llvm_profile_runtime to cause runtime
400*06c3fb27SDimitry Andric   // initialization module to be linked in.
401*06c3fb27SDimitry Andric   if (needsProfileRT(Args))
402*06c3fb27SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(
403*06c3fb27SDimitry Andric         Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
404*06c3fb27SDimitry Andric   ToolChain::addProfileRTLibs(Args, CmdArgs);
405*06c3fb27SDimitry Andric }
406*06c3fb27SDimitry Andric 
407*06c3fb27SDimitry Andric ToolChain::path_list OHOS::getArchSpecificLibPaths() const {
408*06c3fb27SDimitry Andric   ToolChain::path_list Paths;
409*06c3fb27SDimitry Andric   llvm::Triple Triple = getTriple();
410*06c3fb27SDimitry Andric   Paths.push_back(
411*06c3fb27SDimitry Andric       makePath({getDriver().ResourceDir, "lib", getMultiarchTriple(Triple)}));
412*06c3fb27SDimitry Andric   return Paths;
413*06c3fb27SDimitry Andric }
414*06c3fb27SDimitry Andric 
415*06c3fb27SDimitry Andric ToolChain::UnwindLibType OHOS::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
416*06c3fb27SDimitry Andric   if (Args.getLastArg(options::OPT_unwindlib_EQ))
417*06c3fb27SDimitry Andric     return Generic_ELF::GetUnwindLibType(Args);
418*06c3fb27SDimitry Andric   return GetDefaultUnwindLibType();
419*06c3fb27SDimitry Andric }
420