Coverage Report

Created: 2023-09-21 18:56

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