clang  20.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 "CommonArgs.h"
12 #include "clang/Config/config.h"
14 #include "clang/Driver/Driver.h"
16 #include "clang/Driver/Options.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"
24 
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;
31 
34 
36  DetectedMultilibs &Result) {
37  MultilibSet Multilibs;
38  Multilibs.push_back(Multilib());
39  // -mcpu=cortex-a7
40  // -mfloat-abi=soft -mfloat-abi=softfp -mfloat-abi=hard
41  // -mfpu=neon-vfpv4
42  Multilibs.push_back(
43  Multilib("/a7_soft", {}, {}, {"-mcpu=cortex-a7", "-mfloat-abi=soft"}));
44 
45  Multilibs.push_back(
46  Multilib("/a7_softfp_neon-vfpv4", {}, {},
47  {"-mcpu=cortex-a7", "-mfloat-abi=softfp", "-mfpu=neon-vfpv4"}));
48 
49  Multilibs.push_back(
50  Multilib("/a7_hard_neon-vfpv4", {}, {},
51  {"-mcpu=cortex-a7", "-mfloat-abi=hard", "-mfpu=neon-vfpv4"}));
52 
53  if (Multilibs.select(Flags, Result.SelectedMultilibs)) {
54  Result.Multilibs = Multilibs;
55  return true;
56  }
57  return false;
58 }
59 
60 static bool findOHOSMultilibs(const Driver &D,
61  const ToolChain &TC,
62  const llvm::Triple &TargetTriple,
63  StringRef Path, const ArgList &Args,
64  DetectedMultilibs &Result) {
66  bool IsA7 = false;
67  if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
68  IsA7 = A->getValue() == StringRef("cortex-a7");
69  addMultilibFlag(IsA7, "-mcpu=cortex-a7", Flags);
70 
71  bool IsMFPU = false;
72  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
73  IsMFPU = A->getValue() == StringRef("neon-vfpv4");
74  addMultilibFlag(IsMFPU, "-mfpu=neon-vfpv4", Flags);
75 
76  tools::arm::FloatABI ARMFloatABI = getARMFloatABI(D, TargetTriple, Args);
78  "-mfloat-abi=soft", Flags);
80  "-mfloat-abi=softfp", Flags);
82  "-mfloat-abi=hard", Flags);
83 
84  return findOHOSMuslMultilibs(Flags, Result);
85 }
86 
87 std::string OHOS::getMultiarchTriple(const llvm::Triple &T) const {
88  // For most architectures, just use whatever we have rather than trying to be
89  // clever.
90  switch (T.getArch()) {
91  default:
92  break;
93 
94  // We use the existence of '/lib/<triple>' as a directory to detect some
95  // common linux triples that don't quite match the Clang triple for both
96  // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
97  // regardless of what the actual target triple is.
98  case llvm::Triple::arm:
99  case llvm::Triple::thumb:
100  return T.isOSLiteOS() ? "arm-liteos-ohos" : "arm-linux-ohos";
101  case llvm::Triple::riscv32:
102  return "riscv32-linux-ohos";
103  case llvm::Triple::riscv64:
104  return "riscv64-linux-ohos";
105  case llvm::Triple::mipsel:
106  return "mipsel-linux-ohos";
107  case llvm::Triple::x86:
108  return "i686-linux-ohos";
109  case llvm::Triple::x86_64:
110  return "x86_64-linux-ohos";
111  case llvm::Triple::aarch64:
112  return "aarch64-linux-ohos";
113  }
114  return T.str();
115 }
116 
117 std::string OHOS::getMultiarchTriple(const Driver &D,
118  const llvm::Triple &TargetTriple,
119  StringRef SysRoot) const {
120  return getMultiarchTriple(TargetTriple);
121 }
122 
123 static std::string makePath(const std::initializer_list<std::string> &IL) {
125  for (const auto &S : IL)
126  llvm::sys::path::append(P, S);
127  return static_cast<std::string>(P.str());
128 }
129 
130 /// OHOS Toolchain
131 OHOS::OHOS(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
132  : Generic_ELF(D, Triple, Args) {
133  std::string SysRoot = computeSysRoot();
134 
135  // Select the correct multilib according to the given arguments.
136  DetectedMultilibs Result;
137  findOHOSMultilibs(D, *this, Triple, "", Args, Result);
138  Multilibs = Result.Multilibs;
139  SelectedMultilibs = Result.SelectedMultilibs;
140  if (!SelectedMultilibs.empty()) {
141  SelectedMultilib = SelectedMultilibs.back();
142  }
143 
144  getFilePaths().clear();
145  for (const auto &CandidateLibPath : getArchSpecificLibPaths())
146  if (getVFS().exists(CandidateLibPath))
147  getFilePaths().push_back(CandidateLibPath);
148 
149  getLibraryPaths().clear();
150  for (auto &Path : getRuntimePaths())
151  if (getVFS().exists(Path))
152  getLibraryPaths().push_back(Path);
153 
154  // OHOS sysroots contain a library directory for each supported OS
155  // version as well as some unversioned libraries in the usual multiarch
156  // directory. Support --target=aarch64-linux-ohosX.Y.Z or
157  // --target=aarch64-linux-ohosX.Y or --target=aarch64-linux-ohosX
158  path_list &Paths = getFilePaths();
159  std::string SysRootLibPath = makePath({SysRoot, "usr", "lib"});
160  std::string MultiarchTriple = getMultiarchTriple(getTriple());
161  addPathIfExists(D, makePath({SysRootLibPath, SelectedMultilib.gccSuffix()}),
162  Paths);
164  makePath({D.Dir, "..", "lib", MultiarchTriple,
165  SelectedMultilib.gccSuffix()}),
166  Paths);
167 
169  D,
170  makePath({SysRootLibPath, MultiarchTriple, SelectedMultilib.gccSuffix()}),
171  Paths);
172 }
173 
175  const ArgList &Args) const {
176  if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) {
177  StringRef Value = A->getValue();
178  if (Value != "compiler-rt")
179  getDriver().Diag(clang::diag::err_drv_invalid_rtlib_name)
180  << A->getAsString(Args);
181  }
182 
184 }
185 
187 OHOS::GetCXXStdlibType(const ArgList &Args) const {
188  if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
189  StringRef Value = A->getValue();
190  if (Value != "libc++")
191  getDriver().Diag(diag::err_drv_invalid_stdlib_name)
192  << A->getAsString(Args);
193  }
194 
195  return ToolChain::CST_Libcxx;
196 }
197 
198 void OHOS::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
199  ArgStringList &CC1Args) const {
200  const Driver &D = getDriver();
201  const llvm::Triple &Triple = getTriple();
202  std::string SysRoot = computeSysRoot();
203 
204  if (DriverArgs.hasArg(options::OPT_nostdinc))
205  return;
206 
207  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
208  SmallString<128> P(D.ResourceDir);
209  llvm::sys::path::append(P, "include");
210  addSystemInclude(DriverArgs, CC1Args, P);
211  }
212 
213  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
214  return;
215 
216  // Check for configure-time C include directories.
217  StringRef CIncludeDirs(C_INCLUDE_DIRS);
218  if (CIncludeDirs != "") {
220  CIncludeDirs.split(dirs, ":");
221  for (StringRef dir : dirs) {
222  StringRef Prefix =
223  llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";
224  addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
225  }
226  return;
227  }
228 
229  addExternCSystemInclude(DriverArgs, CC1Args,
230  SysRoot + "/usr/include/" +
231  getMultiarchTriple(Triple));
232  addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
233  addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
234 }
235 
236 void OHOS::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
237  ArgStringList &CC1Args) const {
238  if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
239  DriverArgs.hasArg(options::OPT_nostdincxx))
240  return;
241 
242  switch (GetCXXStdlibType(DriverArgs)) {
243  case ToolChain::CST_Libcxx: {
244  std::string IncPath = makePath({getDriver().Dir, "..", "include"});
245  std::string IncTargetPath =
246  makePath({IncPath, getMultiarchTriple(getTriple()), "c++", "v1"});
247  if (getVFS().exists(IncTargetPath)) {
248  addSystemInclude(DriverArgs, CC1Args, makePath({IncPath, "c++", "v1"}));
249  addSystemInclude(DriverArgs, CC1Args, IncTargetPath);
250  }
251  break;
252  }
253 
254  default:
255  llvm_unreachable("invalid stdlib name");
256  }
257 }
258 
259 void OHOS::AddCXXStdlibLibArgs(const ArgList &Args,
260  ArgStringList &CmdArgs) const {
261  switch (GetCXXStdlibType(Args)) {
263  CmdArgs.push_back("-lc++");
264  CmdArgs.push_back("-lc++abi");
265  CmdArgs.push_back("-lunwind");
266  break;
267 
269  llvm_unreachable("invalid stdlib name");
270  }
271 }
272 
273 std::string OHOS::computeSysRoot() const {
274  std::string SysRoot =
275  !getDriver().SysRoot.empty()
276  ? getDriver().SysRoot
277  : makePath({getDriver().Dir, "..", "..", "sysroot"});
278  if (!llvm::sys::fs::exists(SysRoot))
279  return std::string();
280 
281  std::string ArchRoot = makePath({SysRoot, getMultiarchTriple(getTriple())});
282  return llvm::sys::fs::exists(ArchRoot) ? ArchRoot : SysRoot;
283 }
284 
287  path_list Paths;
288  const Driver &D = getDriver();
289  const llvm::Triple &Triple = getTriple();
290 
291  // First try the triple passed to driver as --target=<triple>.
292  P.assign(D.ResourceDir);
293  llvm::sys::path::append(P, "lib", D.getTargetTriple(), SelectedMultilib.gccSuffix());
294  Paths.push_back(P.c_str());
295 
296  // Second try the normalized triple.
297  P.assign(D.ResourceDir);
298  llvm::sys::path::append(P, "lib", Triple.str(), SelectedMultilib.gccSuffix());
299  Paths.push_back(P.c_str());
300 
301  // Third try the effective triple.
302  P.assign(D.ResourceDir);
303  std::string SysRoot = computeSysRoot();
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 
311 std::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 
340 std::string OHOS::getCompilerRT(const ArgList &Args, StringRef Component,
341  FileType Type) 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 
364 void 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("max-page-size=4096");
371  // .gnu.hash section is not compatible with the MIPS target
372  if (getArch() != llvm::Triple::mipsel)
373  CmdArgs.push_back("--hash-style=both");
374 #ifdef ENABLE_LINKER_BUILD_ID
375  CmdArgs.push_back("--build-id");
376 #endif
377  CmdArgs.push_back("--enable-new-dtags");
378 }
379 
382  Res |= SanitizerKind::Address;
383  Res |= SanitizerKind::PointerCompare;
384  Res |= SanitizerKind::PointerSubtract;
385  Res |= SanitizerKind::Fuzzer;
386  Res |= SanitizerKind::FuzzerNoLink;
387  Res |= SanitizerKind::Memory;
388  Res |= SanitizerKind::Vptr;
389  Res |= SanitizerKind::SafeStack;
390  Res |= SanitizerKind::Scudo;
391  // TODO: kASAN for liteos ??
392  // TODO: Support TSAN and HWASAN and update mask.
393  return Res;
394 }
395 
396 // TODO: Make a base class for Linux and OHOS and move this there.
397 void OHOS::addProfileRTLibs(const llvm::opt::ArgList &Args,
398  llvm::opt::ArgStringList &CmdArgs) const {
399  // Add linker option -u__llvm_profile_runtime to cause runtime
400  // initialization module to be linked in.
401  if (needsProfileRT(Args))
402  CmdArgs.push_back(Args.MakeArgString(
403  Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
404  ToolChain::addProfileRTLibs(Args, CmdArgs);
405 }
406 
408  ToolChain::path_list Paths;
409  llvm::Triple Triple = getTriple();
410  Paths.push_back(
411  makePath({getDriver().ResourceDir, "lib", getMultiarchTriple(Triple)}));
412  return Paths;
413 }
414 
415 ToolChain::UnwindLibType OHOS::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
416  if (Args.getLastArg(options::OPT_unwindlib_EQ))
417  return Generic_ELF::GetUnwindLibType(Args);
418  return GetDefaultUnwindLibType();
419 }
StringRef P
const Decl * D
IndirectLocalPath & Path
static std::string makePath(const std::initializer_list< std::string > &IL)
Definition: OHOS.cpp:123
static bool findOHOSMultilibs(const Driver &D, const ToolChain &TC, const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args, DetectedMultilibs &Result)
Definition: OHOS.cpp:60
static bool findOHOSMuslMultilibs(const Multilib::flags_list &Flags, DetectedMultilibs &Result)
Definition: OHOS.cpp:35
The base class of the type hierarchy.
Definition: Type.h:1829
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:77
std::string SysRoot
sysroot, if present
Definition: Driver.h:182
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:146
std::string ResourceDir
The path to the compiler resource directory.
Definition: Driver.h:166
std::string Dir
The path the driver executable was in, as invoked from the command line.
Definition: Driver.h:157
See also MultilibSetBuilder for combining multilibs into a set.
Definition: Multilib.h:92
bool select(const Multilib::flags_list &Flags, llvm::SmallVectorImpl< Multilib > &) const
Select compatible variants,.
Definition: Multilib.cpp:97
void push_back(const Multilib &M)
Add a completed Multilib to the set.
Definition: Multilib.cpp:95
This corresponds to a single GCC Multilib, or a segment of one controlled by a command line flag.
Definition: Multilib.h:32
const std::string & gccSuffix() const
Get the detected GCC installation path suffix for the multi-arch target variant.
Definition: Multilib.h:61
std::vector< std::string > flags_list
Definition: Multilib.h:34
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:92
const Driver & getDriver() const
Definition: ToolChain.h:269
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:1287
path_list & getFilePaths()
Definition: ToolChain.h:311
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:1302
path_list & getLibraryPaths()
Definition: ToolChain.h:308
static bool needsProfileRT(const llvm::opt::ArgList &Args)
needsProfileRT - returns true if instrumentation profile is on.
Definition: ToolChain.cpp:947
llvm::Triple::ArchType getArch() const
Definition: ToolChain.h:285
const llvm::Triple & getTriple() const
Definition: ToolChain.h:271
llvm::vfs::FileSystem & getVFS() const
Definition: ToolChain.cpp:154
virtual UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const
Definition: ToolChain.cpp:1225
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:1191
llvm::SmallVector< Multilib > SelectedMultilibs
Definition: ToolChain.h:217
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Definition: ToolChain.cpp:1478
RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override
Definition: OHOS.cpp:174
OHOS(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
OHOS Toolchain.
Definition: OHOS.cpp:131
std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, FileType Type=ToolChain::FT_Static) const override
Definition: OHOS.cpp:340
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:259
path_list getArchSpecificLibPaths() const override
Definition: OHOS.cpp:407
std::string computeSysRoot() const override
Return the sysroot, possibly searching for a default sysroot using target-specific logic.
Definition: OHOS.cpp:273
UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const override
Definition: OHOS.cpp:415
std::string getMultiarchTriple(const llvm::Triple &T) const
Definition: OHOS.cpp:87
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:397
SanitizerMask getSupportedSanitizers() const override
Return sanitizers which are available in this toolchain.
Definition: OHOS.cpp:380
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override
Definition: OHOS.cpp:187
path_list getRuntimePaths() const
Definition: OHOS.cpp:285
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:198
UnwindLibType GetDefaultUnwindLibType() const override
Definition: OHOS.h:40
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:236
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:341
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T