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