clang 22.0.0git
OHOS.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
8
9#include "OHOS.h"
10#include "Arch/ARM.h"
11#include "clang/Config/config.h"
14#include "clang/Driver/Driver.h"
17#include "llvm/Option/ArgList.h"
18#include "llvm/ProfileData/InstrProf.h"
19#include "llvm/Support/FileSystem.h"
20#include "llvm/Support/Path.h"
21#include "llvm/Support/VirtualFileSystem.h"
22
23using namespace clang::driver;
24using namespace clang::driver::toolchains;
25using namespace clang::driver::tools;
26using namespace clang;
27using namespace llvm::opt;
28using namespace clang::driver::tools::arm;
29
32
33static bool findOHOSMuslMultilibs(const Driver &D,
34 const Multilib::flags_list &Flags,
35 DetectedMultilibs &Result) {
36 MultilibSet Multilibs;
37 Multilibs.push_back(Multilib());
38 // -mcpu=cortex-a7
39 // -mfloat-abi=soft -mfloat-abi=softfp -mfloat-abi=hard
40 // -mfpu=neon-vfpv4
41 Multilibs.push_back(
42 Multilib("/a7_soft", {}, {}, {"-mcpu=cortex-a7", "-mfloat-abi=soft"}));
43
44 Multilibs.push_back(
45 Multilib("/a7_softfp_neon-vfpv4", {}, {},
46 {"-mcpu=cortex-a7", "-mfloat-abi=softfp", "-mfpu=neon-vfpv4"}));
47
48 Multilibs.push_back(
49 Multilib("/a7_hard_neon-vfpv4", {}, {},
50 {"-mcpu=cortex-a7", "-mfloat-abi=hard", "-mfpu=neon-vfpv4"}));
51
52 if (Multilibs.select(D, Flags, Result.SelectedMultilibs)) {
53 Result.Multilibs = Multilibs;
54 return true;
55 }
56 return false;
57}
58
59static bool findOHOSMultilibs(const Driver &D,
60 const ToolChain &TC,
61 const llvm::Triple &TargetTriple,
62 StringRef Path, const ArgList &Args,
63 DetectedMultilibs &Result) {
65 bool IsA7 = false;
66 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
67 IsA7 = A->getValue() == StringRef("cortex-a7");
68 addMultilibFlag(IsA7, "-mcpu=cortex-a7", Flags);
69
70 bool IsMFPU = false;
71 if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
72 IsMFPU = A->getValue() == StringRef("neon-vfpv4");
73 addMultilibFlag(IsMFPU, "-mfpu=neon-vfpv4", Flags);
74
75 tools::arm::FloatABI ARMFloatABI = getARMFloatABI(D, TargetTriple, Args);
76 addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Soft),
77 "-mfloat-abi=soft", Flags);
78 addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::SoftFP),
79 "-mfloat-abi=softfp", Flags);
80 addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Hard),
81 "-mfloat-abi=hard", Flags);
82
83 return findOHOSMuslMultilibs(D, Flags, Result);
84}
85
86std::string OHOS::getMultiarchTriple(const llvm::Triple &T) const {
87 // For most architectures, just use whatever we have rather than trying to be
88 // clever.
89 switch (T.getArch()) {
90 default:
91 break;
92
93 // We use the existence of '/lib/<triple>' as a directory to detect some
94 // common linux triples that don't quite match the Clang triple for both
95 // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
96 // regardless of what the actual target triple is.
97 case llvm::Triple::arm:
98 case llvm::Triple::thumb:
99 return T.isOSLiteOS() ? "arm-liteos-ohos" : "arm-linux-ohos";
100 case llvm::Triple::riscv32:
101 return "riscv32-linux-ohos";
102 case llvm::Triple::riscv64:
103 return "riscv64-linux-ohos";
104 case llvm::Triple::mipsel:
105 return "mipsel-linux-ohos";
106 case llvm::Triple::x86:
107 return "i686-linux-ohos";
108 case llvm::Triple::x86_64:
109 return "x86_64-linux-ohos";
110 case llvm::Triple::aarch64:
111 return "aarch64-linux-ohos";
112 case llvm::Triple::loongarch64:
113 return "loongarch64-linux-ohos";
114 }
115 return T.str();
116}
117
119 const llvm::Triple &TargetTriple,
120 StringRef SysRoot) const {
121 return getMultiarchTriple(TargetTriple);
122}
123
124static std::string makePath(const std::initializer_list<std::string> &IL) {
126 for (const auto &S : IL)
127 llvm::sys::path::append(P, S);
128 return static_cast<std::string>(P.str());
129}
130
131/// OHOS Toolchain
132OHOS::OHOS(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
133 : Generic_ELF(D, Triple, Args) {
134 std::string SysRoot = computeSysRoot();
135
136 // Select the correct multilib according to the given arguments.
138 findOHOSMultilibs(D, *this, Triple, "", Args, Result);
139 Multilibs = Result.Multilibs;
140 SelectedMultilibs = Result.SelectedMultilibs;
141 if (!SelectedMultilibs.empty()) {
142 SelectedMultilib = SelectedMultilibs.back();
143 }
144
145 getFilePaths().clear();
146 for (const auto &CandidateLibPath : getArchSpecificLibPaths())
147 if (getVFS().exists(CandidateLibPath))
148 getFilePaths().push_back(CandidateLibPath);
149
150 getLibraryPaths().clear();
151 for (auto &Path : getRuntimePaths())
152 if (getVFS().exists(Path))
153 getLibraryPaths().push_back(Path);
154
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);
165 makePath({D.Dir, "..", "lib", MultiarchTriple,
166 SelectedMultilib.gccSuffix()}),
167 Paths);
168
170 D,
171 makePath({SysRootLibPath, MultiarchTriple, SelectedMultilib.gccSuffix()}),
172 Paths);
173}
174
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);
182 }
183
185}
186
188OHOS::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);
194 }
195
197}
198
199void 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();
204
205 if (DriverArgs.hasArg(options::OPT_nostdinc))
206 return;
207
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);
212 }
213
214 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
215 return;
216
217 // Check for configure-time C include directories.
218 StringRef CIncludeDirs(C_INCLUDE_DIRS);
219 if (CIncludeDirs != "") {
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);
226 }
227 return;
228 }
229
230 addExternCSystemInclude(DriverArgs, CC1Args,
231 SysRoot + "/usr/include/" +
232 getMultiarchTriple(Triple));
233 addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
234 addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
235}
236
237void OHOS::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
238 ArgStringList &CC1Args) const {
239 if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
240 DriverArgs.hasArg(options::OPT_nostdincxx))
241 return;
242
243 switch (GetCXXStdlibType(DriverArgs)) {
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);
251 }
252 break;
253 }
254
255 default:
256 llvm_unreachable("invalid stdlib name");
257 }
258}
259
260void OHOS::AddCXXStdlibLibArgs(const ArgList &Args,
261 ArgStringList &CmdArgs) const {
262 switch (GetCXXStdlibType(Args)) {
264 CmdArgs.push_back("-lc++");
265 CmdArgs.push_back("-lc++abi");
266 CmdArgs.push_back("-lunwind");
267 break;
268
270 llvm_unreachable("invalid stdlib name");
271 }
272}
273
274std::string OHOS::computeSysRoot() const {
275 std::string SysRoot =
276 !getDriver().SysRoot.empty()
278 : makePath({getDriver().Dir, "..", "..", "sysroot"});
279 if (!llvm::sys::fs::exists(SysRoot))
280 return std::string();
281
282 std::string ArchRoot = makePath({SysRoot, getMultiarchTriple(getTriple())});
283 return llvm::sys::fs::exists(ArchRoot) ? ArchRoot : SysRoot;
284}
285
288 path_list Paths;
289 const Driver &D = getDriver();
290 const llvm::Triple &Triple = getTriple();
291
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());
296
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());
301
302 // Third try the effective triple.
303 P.assign(D.ResourceDir);
304 llvm::sys::path::append(P, "lib", getMultiarchTriple(Triple),
305 SelectedMultilib.gccSuffix());
306 Paths.push_back(P.c_str());
307
308 return Paths;
309}
310
311std::string OHOS::getDynamicLinker(const ArgList &Args) const {
312 const llvm::Triple &Triple = getTriple();
313 const llvm::Triple::ArchType Arch = getArch();
314
315 assert(Triple.isMusl());
316 std::string ArchName;
317 bool IsArm = false;
318
319 switch (Arch) {
320 case llvm::Triple::arm:
321 case llvm::Triple::thumb:
322 ArchName = "arm";
323 IsArm = true;
324 break;
325 case llvm::Triple::armeb:
326 case llvm::Triple::thumbeb:
327 ArchName = "armeb";
328 IsArm = true;
329 break;
330 default:
331 ArchName = Triple.getArchName().str();
332 }
333 if (IsArm &&
335 ArchName += "hf";
336
337 return "/lib/ld-musl-" + ArchName + ".so.1";
338}
339
340std::string OHOS::getCompilerRT(const ArgList &Args, StringRef Component,
341 FileType Type, bool IsFortran) const {
342 SmallString<128> Path(getDriver().ResourceDir);
343 llvm::sys::path::append(Path, "lib", getMultiarchTriple(getTriple()),
344 SelectedMultilib.gccSuffix());
345 const char *Prefix =
346 Type == ToolChain::FT_Object ? "" : "lib";
347 const char *Suffix;
348 switch (Type) {
350 Suffix = ".o";
351 break;
353 Suffix = ".a";
354 break;
356 Suffix = ".so";
357 break;
358 }
359 llvm::sys::path::append(
360 Path, Prefix + Twine("clang_rt.") + Component + Suffix);
361 return static_cast<std::string>(Path.str());
362}
363
364void OHOS::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
365 CmdArgs.push_back("-z");
366 CmdArgs.push_back("now");
367 CmdArgs.push_back("-z");
368 CmdArgs.push_back("relro");
369 CmdArgs.push_back("-z");
370 CmdArgs.push_back(getArch() == llvm::Triple::loongarch64
371 ? "max-page-size=16384"
372 : "max-page-size=4096");
373 // .gnu.hash section is not compatible with the MIPS target
374 if (getArch() != llvm::Triple::mipsel)
375 CmdArgs.push_back("--hash-style=both");
376#ifdef ENABLE_LINKER_BUILD_ID
377 CmdArgs.push_back("--build-id");
378#endif
379 CmdArgs.push_back("--enable-new-dtags");
380}
381
384 Res |= SanitizerKind::Address;
385 Res |= SanitizerKind::PointerCompare;
386 Res |= SanitizerKind::PointerSubtract;
387 Res |= SanitizerKind::Fuzzer;
388 Res |= SanitizerKind::FuzzerNoLink;
389 Res |= SanitizerKind::Memory;
390 Res |= SanitizerKind::Vptr;
391 Res |= SanitizerKind::SafeStack;
392 Res |= SanitizerKind::Scudo;
393 // TODO: kASAN for liteos ??
394 // TODO: Support TSAN and HWASAN and update mask.
395 return Res;
396}
397
398// TODO: Make a base class for Linux and OHOS and move this there.
399void OHOS::addProfileRTLibs(const llvm::opt::ArgList &Args,
400 llvm::opt::ArgStringList &CmdArgs) const {
401 // Add linker option -u__llvm_profile_runtime to cause runtime
402 // initialization module to be linked in.
403 if (needsProfileRT(Args))
404 CmdArgs.push_back(Args.MakeArgString(
405 Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
406 ToolChain::addProfileRTLibs(Args, CmdArgs);
407}
408
411 llvm::Triple Triple = getTriple();
412 Paths.push_back(
413 makePath({getDriver().ResourceDir, "lib", getMultiarchTriple(Triple)}));
414 return Paths;
415}
416
417ToolChain::UnwindLibType OHOS::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
418 if (Args.getLastArg(options::OPT_unwindlib_EQ))
421}
StringRef P
const Decl * D
IndirectLocalPath & Path
static bool findOHOSMuslMultilibs(const Driver &D, const Multilib::flags_list &Flags, DetectedMultilibs &Result)
Definition: OHOS.cpp:33
static std::string makePath(const std::initializer_list< std::string > &IL)
Definition: OHOS.cpp:124
static bool findOHOSMultilibs(const Driver &D, const ToolChain &TC, const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args, DetectedMultilibs &Result)
Definition: OHOS.cpp:59
OffloadArch Arch
Definition: OffloadArch.cpp:10
const char * ArchName
Definition: OffloadArch.cpp:11
The base class of the type hierarchy.
Definition: TypeBase.h:1833
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:99
std::string SysRoot
sysroot, if present
Definition: Driver.h:205
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:169
std::string ResourceDir
The path to the compiler resource directory.
Definition: Driver.h:189
std::string Dir
The path the driver executable was in, as invoked from the command line.
Definition: Driver.h:180
See also MultilibSetBuilder for combining multilibs into a set.
Definition: Multilib.h:129
bool select(const Driver &D, const Multilib::flags_list &Flags, llvm::SmallVectorImpl< Multilib > &, llvm::SmallVector< StringRef > *=nullptr) const
Select compatible variants,.
Definition: Multilib.cpp:216
void push_back(const Multilib &M)
Add a completed Multilib to the set.
Definition: Multilib.cpp:91
This corresponds to a single GCC Multilib, or a segment of one controlled by a command line flag.
Definition: Multilib.h:35
const std::string & gccSuffix() const
Get the detected GCC installation path suffix for the multi-arch target variant.
Definition: Multilib.h:70
std::vector< std::string > flags_list
Definition: Multilib.h:37
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:92
static void addSystemInclude(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, const Twine &Path)
Utility function to add a system include directory to CC1 arguments.
Definition: ToolChain.cpp:1436
static void addExternCSystemInclude(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, const Twine &Path)
Utility function to add a system include directory with extern "C" semantics to CC1 arguments.
Definition: ToolChain.cpp:1421
path_list & getFilePaths()
Definition: ToolChain.h:295
static bool needsProfileRT(const llvm::opt::ArgList &Args)
needsProfileRT - returns true if instrumentation profile is on.
Definition: ToolChain.cpp:1059
llvm::Triple::ArchType getArch() const
Definition: ToolChain.h:269
const Driver & getDriver() const
Definition: ToolChain.h:253
llvm::vfs::FileSystem & getVFS() const
Definition: ToolChain.cpp:115
const llvm::Triple & getTriple() const
Definition: ToolChain.h:255
virtual UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const
Definition: ToolChain.cpp:1344
virtual void addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const
addProfileRTLibs - When -fprofile-instr-profile is specified, try to pass a suitable profile runtime ...
Definition: ToolChain.cpp:1310
llvm::SmallVector< Multilib > SelectedMultilibs
Definition: ToolChain.h:200
path_list & getLibraryPaths()
Definition: ToolChain.h:292
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Definition: ToolChain.cpp:1614
RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override
Definition: OHOS.cpp:175
OHOS(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
OHOS Toolchain.
Definition: OHOS.cpp:132
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override
AddCXXStdlibLibArgs - Add the system specific linker arguments to use for the given C++ standard libr...
Definition: OHOS.cpp:260
path_list getArchSpecificLibPaths() const override
Definition: OHOS.cpp:409
std::string computeSysRoot() const override
Return the sysroot, possibly searching for a default sysroot using target-specific logic.
Definition: OHOS.cpp:274
UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const override
Definition: OHOS.cpp:417
std::string getMultiarchTriple(const llvm::Triple &T) const
Definition: OHOS.cpp:86
void addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override
addProfileRTLibs - When -fprofile-instr-profile is specified, try to pass a suitable profile runtime ...
Definition: OHOS.cpp:399
SanitizerMask getSupportedSanitizers() const override
Return sanitizers which are available in this toolchain.
Definition: OHOS.cpp:382
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override
Definition: OHOS.cpp:188
path_list getRuntimePaths() const
Definition: OHOS.cpp:286
void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override
Add the clang cc1 arguments for system include paths.
Definition: OHOS.cpp:199
UnwindLibType GetDefaultUnwindLibType() const override
Definition: OHOS.h:40
std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, FileType Type=ToolChain::FT_Static, bool IsFortran=false) const override
Definition: OHOS.cpp:340
void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override
AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set the include paths to use for...
Definition: OHOS.cpp:237
void addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const override
Definition: OHOS.cpp:364
std::string getDynamicLinker(const llvm::opt::ArgList &Args) const override
Definition: OHOS.cpp:311
FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args)
void addMultilibFlag(bool Enabled, const StringRef Flag, Multilib::flags_list &Flags)
Flag must be a flag accepted by the driver.
void addPathIfExists(const Driver &D, const Twine &Path, ToolChain::path_list &Paths)
Definition: CommonArgs.cpp:354
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
const FunctionProtoType * T