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