Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- BareMetal.cpp - Bare Metal ToolChain --------------------*- 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 "BareMetal.h"
10
11
#include "CommonArgs.h"
12
#include "Gnu.h"
13
#include "clang/Driver/InputInfo.h"
14
15
#include "Arch/ARM.h"
16
#include "Arch/RISCV.h"
17
#include "clang/Driver/Compilation.h"
18
#include "clang/Driver/Driver.h"
19
#include "clang/Driver/DriverDiagnostic.h"
20
#include "clang/Driver/MultilibBuilder.h"
21
#include "clang/Driver/Options.h"
22
#include "llvm/ADT/StringExtras.h"
23
#include "llvm/Option/ArgList.h"
24
#include "llvm/Support/Path.h"
25
#include "llvm/Support/VirtualFileSystem.h"
26
#include "llvm/Support/raw_ostream.h"
27
28
#include <sstream>
29
30
using namespace llvm::opt;
31
using namespace clang;
32
using namespace clang::driver;
33
using namespace clang::driver::tools;
34
using namespace clang::driver::toolchains;
35
36
static bool findRISCVMultilibs(const Driver &D,
37
                               const llvm::Triple &TargetTriple,
38
0
                               const ArgList &Args, DetectedMultilibs &Result) {
39
0
  Multilib::flags_list Flags;
40
0
  StringRef Arch = riscv::getRISCVArch(Args, TargetTriple);
41
0
  StringRef Abi = tools::riscv::getRISCVABI(Args, TargetTriple);
42
43
0
  if (TargetTriple.isRISCV64()) {
44
0
    MultilibBuilder Imac =
45
0
        MultilibBuilder().flag("-march=rv64imac").flag("-mabi=lp64");
46
0
    MultilibBuilder Imafdc = MultilibBuilder("/rv64imafdc/lp64d")
47
0
                                 .flag("-march=rv64imafdc")
48
0
                                 .flag("-mabi=lp64d");
49
50
    // Multilib reuse
51
0
    bool UseImafdc =
52
0
        (Arch == "rv64imafdc") || (Arch == "rv64gc"); // gc => imafdc
53
54
0
    addMultilibFlag((Arch == "rv64imac"), "-march=rv64imac", Flags);
55
0
    addMultilibFlag(UseImafdc, "-march=rv64imafdc", Flags);
56
0
    addMultilibFlag(Abi == "lp64", "-mabi=lp64", Flags);
57
0
    addMultilibFlag(Abi == "lp64d", "-mabi=lp64d", Flags);
58
59
0
    Result.Multilibs =
60
0
        MultilibSetBuilder().Either(Imac, Imafdc).makeMultilibSet();
61
0
    return Result.Multilibs.select(Flags, Result.SelectedMultilibs);
62
0
  }
63
0
  if (TargetTriple.isRISCV32()) {
64
0
    MultilibBuilder Imac =
65
0
        MultilibBuilder().flag("-march=rv32imac").flag("-mabi=ilp32");
66
0
    MultilibBuilder I = MultilibBuilder("/rv32i/ilp32")
67
0
                            .flag("-march=rv32i")
68
0
                            .flag("-mabi=ilp32");
69
0
    MultilibBuilder Im = MultilibBuilder("/rv32im/ilp32")
70
0
                             .flag("-march=rv32im")
71
0
                             .flag("-mabi=ilp32");
72
0
    MultilibBuilder Iac = MultilibBuilder("/rv32iac/ilp32")
73
0
                              .flag("-march=rv32iac")
74
0
                              .flag("-mabi=ilp32");
75
0
    MultilibBuilder Imafc = MultilibBuilder("/rv32imafc/ilp32f")
76
0
                                .flag("-march=rv32imafc")
77
0
                                .flag("-mabi=ilp32f");
78
79
    // Multilib reuse
80
0
    bool UseI = (Arch == "rv32i") || (Arch == "rv32ic");    // ic => i
81
0
    bool UseIm = (Arch == "rv32im") || (Arch == "rv32imc"); // imc => im
82
0
    bool UseImafc = (Arch == "rv32imafc") || (Arch == "rv32imafdc") ||
83
0
                    (Arch == "rv32gc"); // imafdc,gc => imafc
84
85
0
    addMultilibFlag(UseI, "-march=rv32i", Flags);
86
0
    addMultilibFlag(UseIm, "-march=rv32im", Flags);
87
0
    addMultilibFlag((Arch == "rv32iac"), "-march=rv32iac", Flags);
88
0
    addMultilibFlag((Arch == "rv32imac"), "-march=rv32imac", Flags);
89
0
    addMultilibFlag(UseImafc, "-march=rv32imafc", Flags);
90
0
    addMultilibFlag(Abi == "ilp32", "-mabi=ilp32", Flags);
91
0
    addMultilibFlag(Abi == "ilp32f", "-mabi=ilp32f", Flags);
92
93
0
    Result.Multilibs =
94
0
        MultilibSetBuilder().Either(I, Im, Iac, Imac, Imafc).makeMultilibSet();
95
0
    return Result.Multilibs.select(Flags, Result.SelectedMultilibs);
96
0
  }
97
0
  return false;
98
0
}
99
100
BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
101
                     const ArgList &Args)
102
0
    : ToolChain(D, Triple, Args) {
103
0
  getProgramPaths().push_back(getDriver().getInstalledDir());
104
0
  if (getDriver().getInstalledDir() != getDriver().Dir)
105
0
    getProgramPaths().push_back(getDriver().Dir);
106
107
0
  findMultilibs(D, Triple, Args);
108
0
  SmallString<128> SysRoot(computeSysRoot());
109
0
  if (!SysRoot.empty()) {
110
0
    for (const Multilib &M : getOrderedMultilibs()) {
111
0
      SmallString<128> Dir(SysRoot);
112
0
      llvm::sys::path::append(Dir, M.osSuffix(), "lib");
113
0
      getFilePaths().push_back(std::string(Dir));
114
0
      getLibraryPaths().push_back(std::string(Dir));
115
0
    }
116
0
  }
117
0
}
118
119
/// Is the triple {arm,armeb,thumb,thumbeb}-none-none-{eabi,eabihf} ?
120
0
static bool isARMBareMetal(const llvm::Triple &Triple) {
121
0
  if (Triple.getArch() != llvm::Triple::arm &&
122
0
      Triple.getArch() != llvm::Triple::thumb &&
123
0
      Triple.getArch() != llvm::Triple::armeb &&
124
0
      Triple.getArch() != llvm::Triple::thumbeb)
125
0
    return false;
126
127
0
  if (Triple.getVendor() != llvm::Triple::UnknownVendor)
128
0
    return false;
129
130
0
  if (Triple.getOS() != llvm::Triple::UnknownOS)
131
0
    return false;
132
133
0
  if (Triple.getEnvironment() != llvm::Triple::EABI &&
134
0
      Triple.getEnvironment() != llvm::Triple::EABIHF)
135
0
    return false;
136
137
0
  return true;
138
0
}
139
140
/// Is the triple {aarch64.aarch64_be}-none-elf?
141
0
static bool isAArch64BareMetal(const llvm::Triple &Triple) {
142
0
  if (Triple.getArch() != llvm::Triple::aarch64 &&
143
0
      Triple.getArch() != llvm::Triple::aarch64_be)
144
0
    return false;
145
146
0
  if (Triple.getVendor() != llvm::Triple::UnknownVendor)
147
0
    return false;
148
149
0
  if (Triple.getOS() != llvm::Triple::UnknownOS)
150
0
    return false;
151
152
0
  return Triple.getEnvironmentName() == "elf";
153
0
}
154
155
0
static bool isRISCVBareMetal(const llvm::Triple &Triple) {
156
0
  if (!Triple.isRISCV())
157
0
    return false;
158
159
0
  if (Triple.getVendor() != llvm::Triple::UnknownVendor)
160
0
    return false;
161
162
0
  if (Triple.getOS() != llvm::Triple::UnknownOS)
163
0
    return false;
164
165
0
  return Triple.getEnvironmentName() == "elf";
166
0
}
167
168
/// Is the triple powerpc[64][le]-*-none-eabi?
169
0
static bool isPPCBareMetal(const llvm::Triple &Triple) {
170
0
  return Triple.isPPC() && Triple.getOS() == llvm::Triple::UnknownOS &&
171
0
         Triple.getEnvironment() == llvm::Triple::EABI;
172
0
}
173
174
static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
175
                                  StringRef MultilibPath, const ArgList &Args,
176
0
                                  DetectedMultilibs &Result) {
177
0
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB =
178
0
      D.getVFS().getBufferForFile(MultilibPath);
179
0
  if (!MB)
180
0
    return;
181
0
  Multilib::flags_list Flags = TC.getMultilibFlags(Args);
182
0
  llvm::ErrorOr<MultilibSet> ErrorOrMultilibSet =
183
0
      MultilibSet::parseYaml(*MB.get());
184
0
  if (ErrorOrMultilibSet.getError())
185
0
    return;
186
0
  Result.Multilibs = ErrorOrMultilibSet.get();
187
0
  if (Result.Multilibs.select(Flags, Result.SelectedMultilibs))
188
0
    return;
189
0
  D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
190
0
  std::stringstream ss;
191
0
  for (const Multilib &Multilib : Result.Multilibs)
192
0
    ss << "\n" << llvm::join(Multilib.flags(), " ");
193
0
  D.Diag(clang::diag::note_drv_available_multilibs) << ss.str();
194
0
}
195
196
static constexpr llvm::StringLiteral MultilibFilename = "multilib.yaml";
197
198
// Get the sysroot, before multilib takes effect.
199
static std::string computeBaseSysRoot(const Driver &D,
200
0
                                      const llvm::Triple &Triple) {
201
0
  if (!D.SysRoot.empty())
202
0
    return D.SysRoot;
203
204
0
  SmallString<128> SysRootDir(D.Dir);
205
0
  llvm::sys::path::append(SysRootDir, "..", "lib", "clang-runtimes");
206
207
0
  SmallString<128> MultilibPath(SysRootDir);
208
0
  llvm::sys::path::append(MultilibPath, MultilibFilename);
209
210
  // New behaviour: if multilib.yaml is found then use clang-runtimes as the
211
  // sysroot.
212
0
  if (D.getVFS().exists(MultilibPath))
213
0
    return std::string(SysRootDir);
214
215
  // Otherwise fall back to the old behaviour of appending the target triple.
216
0
  llvm::sys::path::append(SysRootDir, D.getTargetTriple());
217
0
  return std::string(SysRootDir);
218
0
}
219
220
void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
221
0
                              const ArgList &Args) {
222
0
  DetectedMultilibs Result;
223
0
  if (isRISCVBareMetal(Triple)) {
224
0
    if (findRISCVMultilibs(D, Triple, Args, Result)) {
225
0
      SelectedMultilibs = Result.SelectedMultilibs;
226
0
      Multilibs = Result.Multilibs;
227
0
    }
228
0
  } else {
229
0
    llvm::SmallString<128> MultilibPath(computeBaseSysRoot(D, Triple));
230
0
    llvm::sys::path::append(MultilibPath, MultilibFilename);
231
0
    findMultilibsFromYAML(*this, D, MultilibPath, Args, Result);
232
0
    SelectedMultilibs = Result.SelectedMultilibs;
233
0
    Multilibs = Result.Multilibs;
234
0
  }
235
0
}
236
237
0
bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
238
0
  return isARMBareMetal(Triple) || isAArch64BareMetal(Triple) ||
239
0
         isRISCVBareMetal(Triple) || isPPCBareMetal(Triple);
240
0
}
241
242
0
Tool *BareMetal::buildLinker() const {
243
0
  return new tools::baremetal::Linker(*this);
244
0
}
245
246
0
Tool *BareMetal::buildStaticLibTool() const {
247
0
  return new tools::baremetal::StaticLibTool(*this);
248
0
}
249
250
0
std::string BareMetal::computeSysRoot() const {
251
0
  return computeBaseSysRoot(getDriver(), getTriple());
252
0
}
253
254
0
BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
255
  // Get multilibs in reverse order because they're ordered most-specific last.
256
0
  if (!SelectedMultilibs.empty())
257
0
    return llvm::reverse(SelectedMultilibs);
258
259
  // No multilibs selected so return a single default multilib.
260
0
  static const llvm::SmallVector<Multilib> Default = {Multilib()};
261
0
  return llvm::reverse(Default);
262
0
}
263
264
void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
265
0
                                          ArgStringList &CC1Args) const {
266
0
  if (DriverArgs.hasArg(options::OPT_nostdinc))
267
0
    return;
268
269
0
  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
270
0
    SmallString<128> Dir(getDriver().ResourceDir);
271
0
    llvm::sys::path::append(Dir, "include");
272
0
    addSystemInclude(DriverArgs, CC1Args, Dir.str());
273
0
  }
274
275
0
  if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
276
0
    const SmallString<128> SysRoot(computeSysRoot());
277
0
    if (!SysRoot.empty()) {
278
0
      for (const Multilib &M : getOrderedMultilibs()) {
279
0
        SmallString<128> Dir(SysRoot);
280
0
        llvm::sys::path::append(Dir, M.includeSuffix());
281
0
        llvm::sys::path::append(Dir, "include");
282
0
        addSystemInclude(DriverArgs, CC1Args, Dir.str());
283
0
      }
284
0
    }
285
0
  }
286
0
}
287
288
void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
289
                                      ArgStringList &CC1Args,
290
0
                                      Action::OffloadKind) const {
291
0
  CC1Args.push_back("-nostdsysteminc");
292
0
}
293
294
void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
295
0
                                             ArgStringList &CC1Args) const {
296
0
  if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
297
0
                        options::OPT_nostdincxx))
298
0
    return;
299
300
0
  const Driver &D = getDriver();
301
0
  std::string SysRoot(computeSysRoot());
302
0
  if (SysRoot.empty())
303
0
    return;
304
305
0
  for (const Multilib &M : getOrderedMultilibs()) {
306
0
    SmallString<128> Dir(SysRoot);
307
0
    llvm::sys::path::append(Dir, M.gccSuffix());
308
0
    switch (GetCXXStdlibType(DriverArgs)) {
309
0
    case ToolChain::CST_Libcxx: {
310
      // First check sysroot/usr/include/c++/v1 if it exists.
311
0
      SmallString<128> TargetDir(Dir);
312
0
      llvm::sys::path::append(TargetDir, "usr", "include", "c++", "v1");
313
0
      if (D.getVFS().exists(TargetDir)) {
314
0
        addSystemInclude(DriverArgs, CC1Args, TargetDir.str());
315
0
        break;
316
0
      }
317
      // Add generic path if nothing else succeeded so far.
318
0
      llvm::sys::path::append(Dir, "include", "c++", "v1");
319
0
      addSystemInclude(DriverArgs, CC1Args, Dir.str());
320
0
      break;
321
0
    }
322
0
    case ToolChain::CST_Libstdcxx: {
323
0
      llvm::sys::path::append(Dir, "include", "c++");
324
0
      std::error_code EC;
325
0
      Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""};
326
      // Walk the subdirs, and find the one with the newest gcc version:
327
0
      for (llvm::vfs::directory_iterator
328
0
               LI = D.getVFS().dir_begin(Dir.str(), EC),
329
0
               LE;
330
0
           !EC && LI != LE; LI = LI.increment(EC)) {
331
0
        StringRef VersionText = llvm::sys::path::filename(LI->path());
332
0
        auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
333
0
        if (CandidateVersion.Major == -1)
334
0
          continue;
335
0
        if (CandidateVersion <= Version)
336
0
          continue;
337
0
        Version = CandidateVersion;
338
0
      }
339
0
      if (Version.Major != -1) {
340
0
        llvm::sys::path::append(Dir, Version.Text);
341
0
        addSystemInclude(DriverArgs, CC1Args, Dir.str());
342
0
      }
343
0
      break;
344
0
    }
345
0
    }
346
0
  }
347
0
}
348
349
void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
350
0
                                    ArgStringList &CmdArgs) const {
351
0
  switch (GetCXXStdlibType(Args)) {
352
0
  case ToolChain::CST_Libcxx:
353
0
    CmdArgs.push_back("-lc++");
354
0
    if (Args.hasArg(options::OPT_fexperimental_library))
355
0
      CmdArgs.push_back("-lc++experimental");
356
0
    CmdArgs.push_back("-lc++abi");
357
0
    break;
358
0
  case ToolChain::CST_Libstdcxx:
359
0
    CmdArgs.push_back("-lstdc++");
360
0
    CmdArgs.push_back("-lsupc++");
361
0
    break;
362
0
  }
363
0
  CmdArgs.push_back("-lunwind");
364
0
}
365
366
void BareMetal::AddLinkRuntimeLib(const ArgList &Args,
367
0
                                  ArgStringList &CmdArgs) const {
368
0
  ToolChain::RuntimeLibType RLT = GetRuntimeLibType(Args);
369
0
  switch (RLT) {
370
0
  case ToolChain::RLT_CompilerRT: {
371
0
    const std::string FileName = getCompilerRT(Args, "builtins");
372
0
    llvm::StringRef BaseName = llvm::sys::path::filename(FileName);
373
0
    BaseName.consume_front("lib");
374
0
    BaseName.consume_back(".a");
375
0
    CmdArgs.push_back(Args.MakeArgString("-l" + BaseName));
376
0
    return;
377
0
  }
378
0
  case ToolChain::RLT_Libgcc:
379
0
    CmdArgs.push_back("-lgcc");
380
0
    return;
381
0
  }
382
0
  llvm_unreachable("Unhandled RuntimeLibType.");
383
0
}
384
385
void baremetal::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
386
                                            const InputInfo &Output,
387
                                            const InputInfoList &Inputs,
388
                                            const ArgList &Args,
389
0
                                            const char *LinkingOutput) const {
390
0
  const Driver &D = getToolChain().getDriver();
391
392
  // Silence warning for "clang -g foo.o -o foo"
393
0
  Args.ClaimAllArgs(options::OPT_g_Group);
394
  // and "clang -emit-llvm foo.o -o foo"
395
0
  Args.ClaimAllArgs(options::OPT_emit_llvm);
396
  // and for "clang -w foo.o -o foo". Other warning options are already
397
  // handled somewhere else.
398
0
  Args.ClaimAllArgs(options::OPT_w);
399
  // Silence warnings when linking C code with a C++ '-stdlib' argument.
400
0
  Args.ClaimAllArgs(options::OPT_stdlib_EQ);
401
402
  // ar tool command "llvm-ar <options> <output_file> <input_files>".
403
0
  ArgStringList CmdArgs;
404
  // Create and insert file members with a deterministic index.
405
0
  CmdArgs.push_back("rcsD");
406
0
  CmdArgs.push_back(Output.getFilename());
407
408
0
  for (const auto &II : Inputs) {
409
0
    if (II.isFilename()) {
410
0
      CmdArgs.push_back(II.getFilename());
411
0
    }
412
0
  }
413
414
  // Delete old output archive file if it already exists before generating a new
415
  // archive file.
416
0
  const char *OutputFileName = Output.getFilename();
417
0
  if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
418
0
    if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
419
0
      D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
420
0
      return;
421
0
    }
422
0
  }
423
424
0
  const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
425
0
  C.addCommand(std::make_unique<Command>(JA, *this,
426
0
                                         ResponseFileSupport::AtFileCurCP(),
427
0
                                         Exec, CmdArgs, Inputs, Output));
428
0
}
429
430
void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
431
                                     const InputInfo &Output,
432
                                     const InputInfoList &Inputs,
433
                                     const ArgList &Args,
434
0
                                     const char *LinkingOutput) const {
435
0
  ArgStringList CmdArgs;
436
437
0
  auto &TC = static_cast<const toolchains::BareMetal &>(getToolChain());
438
0
  const llvm::Triple::ArchType Arch = TC.getArch();
439
0
  const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
440
441
0
  AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
442
443
0
  CmdArgs.push_back("-Bstatic");
444
445
0
  if (Triple.isARM() || Triple.isThumb()) {
446
0
    bool IsBigEndian = arm::isARMBigEndian(Triple, Args);
447
0
    if (IsBigEndian)
448
0
      arm::appendBE8LinkFlag(Args, CmdArgs, Triple);
449
0
    CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
450
0
  } else if (Triple.isAArch64()) {
451
0
    CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL");
452
0
  }
453
454
0
  Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
455
0
                            options::OPT_s, options::OPT_t, options::OPT_r});
456
457
0
  TC.AddFilePathLibArgs(Args, CmdArgs);
458
459
0
  for (const auto &LibPath : TC.getLibraryPaths())
460
0
    CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-L", LibPath)));
461
462
0
  const std::string FileName = TC.getCompilerRT(Args, "builtins");
463
0
  llvm::SmallString<128> PathBuf{FileName};
464
0
  llvm::sys::path::remove_filename(PathBuf);
465
0
  CmdArgs.push_back(Args.MakeArgString("-L" + PathBuf));
466
467
0
  if (TC.ShouldLinkCXXStdlib(Args))
468
0
    TC.AddCXXStdlibLibArgs(Args, CmdArgs);
469
470
0
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
471
0
    CmdArgs.push_back("-lc");
472
0
    CmdArgs.push_back("-lm");
473
474
0
    TC.AddLinkRuntimeLib(Args, CmdArgs);
475
0
  }
476
477
0
  if (TC.getTriple().isRISCV())
478
0
    CmdArgs.push_back("-X");
479
480
  // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
481
  // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
482
  // arm*-*-*bsd).
483
0
  if (isARMBareMetal(TC.getTriple()))
484
0
    CmdArgs.push_back("--target2=rel");
485
486
0
  CmdArgs.push_back("-o");
487
0
  CmdArgs.push_back(Output.getFilename());
488
489
0
  C.addCommand(std::make_unique<Command>(
490
0
      JA, *this, ResponseFileSupport::AtFileCurCP(),
491
0
      Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs, Output));
492
0
}
493
494
// BareMetal toolchain allows all sanitizers where the compiler generates valid
495
// code, ignoring all runtime library support issues on the assumption that
496
// baremetal targets typically implement their own runtime support.
497
0
SanitizerMask BareMetal::getSupportedSanitizers() const {
498
0
  const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
499
0
  const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 ||
500
0
                         getTriple().getArch() == llvm::Triple::aarch64_be;
501
0
  const bool IsRISCV64 = getTriple().getArch() == llvm::Triple::riscv64;
502
0
  SanitizerMask Res = ToolChain::getSupportedSanitizers();
503
0
  Res |= SanitizerKind::Address;
504
0
  Res |= SanitizerKind::KernelAddress;
505
0
  Res |= SanitizerKind::PointerCompare;
506
0
  Res |= SanitizerKind::PointerSubtract;
507
0
  Res |= SanitizerKind::Fuzzer;
508
0
  Res |= SanitizerKind::FuzzerNoLink;
509
0
  Res |= SanitizerKind::Vptr;
510
0
  Res |= SanitizerKind::SafeStack;
511
0
  Res |= SanitizerKind::Thread;
512
0
  Res |= SanitizerKind::Scudo;
513
0
  if (IsX86_64 || IsAArch64 || IsRISCV64) {
514
0
    Res |= SanitizerKind::HWAddress;
515
0
    Res |= SanitizerKind::KernelHWAddress;
516
0
  }
517
0
  return Res;
518
0
}