1 //===--- OHOS.cpp - OHOS ToolChain Implementations --------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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());
41 // -mfloat-abi=soft -mfloat-abi=softfp -mfloat-abi=hard
44 Multilib("/a7_soft", {}, {}, {"-mcpu=cortex-a7", "-mfloat-abi=soft"}));
47 Multilib("/a7_softfp_neon-vfpv4", {}, {},
48 {"-mcpu=cortex-a7", "-mfloat-abi=softfp", "-mfpu=neon-vfpv4"}));
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
;
61 static bool findOHOSMultilibs(const Driver
&D
,
63 const llvm::Triple
&TargetTriple
,
64 StringRef Path
, const ArgList
&Args
,
65 DetectedMultilibs
&Result
) {
66 Multilib::flags_list Flags
;
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
);
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
91 switch (T
.getArch()) {
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";
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
) {
126 for (const auto &S
: IL
)
127 llvm::sys::path::append(P
, S
);
128 return static_cast<std::string
>(P
.str());
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()}),
165 makePath({D
.Dir
, "..", "lib", MultiarchTriple
,
166 SelectedMultilib
.gccSuffix()}),
171 makePath({SysRootLibPath
, MultiarchTriple
, SelectedMultilib
.gccSuffix()}),
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
))
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
))
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
) {
224 llvm::sys::path::is_absolute(dir
) ? StringRef(SysRoot
) : "";
225 addExternCSystemInclude(DriverArgs
, CC1Args
, Prefix
+ dir
);
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
))
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
);
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");
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 {
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());
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
;
321 case llvm::Triple::arm
:
322 case llvm::Triple::thumb
:
326 case llvm::Triple::armeb
:
327 case llvm::Triple::thumbeb
:
332 ArchName
= Triple
.getArchName().str();
335 (tools::arm::getARMFloatABI(*this, Args
) == tools::arm::FloatABI::Hard
))
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());
347 Type
== ToolChain::FT_Object
? "" : "lib";
350 case ToolChain::FT_Object
:
353 case ToolChain::FT_Static
:
356 case ToolChain::FT_Shared
:
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");
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.
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();
412 makePath({getDriver().ResourceDir
, "lib", getMultiarchTriple(Triple
)}));
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();