clang: lib/Driver/ToolChains/BareMetal.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
10
14
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
29
31using namespace clang;
35
37 const llvm::Triple &TargetTriple,
42
43 if (TargetTriple.isRISCV64()) {
47 .flag("-march=rv64imafdc")
48 .flag("-mabi=lp64d");
49
50
51 bool UseImafdc =
52 (Arch == "rv64imafdc") || (Arch == "rv64gc");
53
54 addMultilibFlag((Arch == "rv64imac"), "-march=rv64imac", Flags);
58
59 Result.Multilibs =
61 return Result.Multilibs.select(D, Flags, Result.SelectedMultilibs);
62 }
63 if (TargetTriple.isRISCV32()) {
67 .flag("-march=rv32i")
68 .flag("-mabi=ilp32");
70 .flag("-march=rv32im")
71 .flag("-mabi=ilp32");
73 .flag("-march=rv32iac")
74 .flag("-mabi=ilp32");
76 .flag("-march=rv32imafc")
77 .flag("-mabi=ilp32f");
78
79
80 bool UseI = (Arch == "rv32i") || (Arch == "rv32ic");
81 bool UseIm = (Arch == "rv32im") || (Arch == "rv32imc");
82 bool UseImafc = (Arch == "rv32imafc") || (Arch == "rv32imafdc") ||
83 (Arch == "rv32gc");
84
87 addMultilibFlag((Arch == "rv32iac"), "-march=rv32iac", Flags);
88 addMultilibFlag((Arch == "rv32imac"), "-march=rv32imac", Flags);
92
93 Result.Multilibs =
95 return Result.Multilibs.select(D, Flags, Result.SelectedMultilibs);
96 }
97 return false;
98}
99
101 if (.SysRoot.empty())
102 return D.SysRoot;
103
105 llvm::sys::path::append(SysRootDir, "..", "lib", "clang-runtimes");
106
107 if (IncludeTriple)
108 llvm::sys::path::append(SysRootDir, D.getTargetTriple());
109
110 return std::string(SysRootDir);
111}
112
114 const ArgList &Args)
118
121 if (!SysRoot.empty()) {
122 for (const Multilib &M : getOrderedMultilibs()) {
124 llvm::sys::path::append(Dir, M.osSuffix(), "lib");
127 }
128 }
129}
130
131
133 if (Triple.getArch() != llvm::Triple::aarch64 &&
134 Triple.getArch() != llvm::Triple::aarch64_be)
135 return false;
136
137 if (Triple.getVendor() != llvm::Triple::UnknownVendor)
138 return false;
139
140 if (Triple.getOS() != llvm::Triple::UnknownOS)
141 return false;
142
143 return Triple.getEnvironmentName() == "elf";
144}
145
147 if (!Triple.isRISCV())
148 return false;
149
150 if (Triple.getVendor() != llvm::Triple::UnknownVendor)
151 return false;
152
153 if (Triple.getOS() != llvm::Triple::UnknownOS)
154 return false;
155
156 return Triple.getEnvironmentName() == "elf";
157}
158
159
161 return Triple.isPPC() && Triple.getOS() == llvm::Triple::UnknownOS &&
162 Triple.getEnvironment() == llvm::Triple::EABI;
163}
164
165static void
167 StringRef MultilibPath, const ArgList &Args,
170 llvm::ErrorOr<std::unique_ptrllvm::MemoryBuffer> MB =
171 D.getVFS().getBufferForFile(MultilibPath);
172 if (!MB)
173 return;
175 llvm::ErrorOr ErrorOrMultilibSet =
177 if (ErrorOrMultilibSet.getError())
178 return;
179 Result.Multilibs = ErrorOrMultilibSet.get();
180 if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs,
181 &CustomFlagsMacroDefines))
182 return;
183 D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
184 std::stringstream ss;
185
186
187
191 D.Diag(clang::diag::note_drv_available_multilibs) << ss.str();
192
193
194
195
196
197
200 D.Diag(clang::diag::err_drv_multilib_custom_error)
202
203
204
205 Result.SelectedMultilibs.clear();
206}
207
209
210static std::optional<llvm::SmallString<128>>
212 const ArgList &Args) {
214 if (Arg *ConfigFileArg = Args.getLastArg(options::OPT_multi_lib_config)) {
215 MultilibPath = ConfigFileArg->getValue();
216 if (.getVFS().exists(MultilibPath)) {
217 D.Diag(clang::diag::err_drv_no_such_file) << MultilibPath.str();
218 return {};
219 }
220 } else {
223 }
224 return MultilibPath;
225}
226
228 const ArgList &Args) {
230
231
232 std::optional<llvm::SmallString<128>> MultilibPath =
234 if (!MultilibPath)
235 return;
236 if (D.getVFS().exists(*MultilibPath)) {
237
238
242 CustomFlagMacroDefines);
245 MultilibMacroDefines.append(CustomFlagMacroDefines.begin(),
246 CustomFlagMacroDefines.end());
251 }
252 }
253}
254
258}
259
262}
263
266}
267
269
270BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
271
274
275
277 return llvm::reverse(Default);
278}
279
281 ArgStringList &CC1Args) const {
282 if (DriverArgs.hasArg(options::OPT_nostdinc))
283 return;
284
285 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
287 llvm::sys::path::append(Dir, "include");
289 }
290
291 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
292 return;
293
296
298 if (!SysRoot.empty()) {
299 for (const Multilib &M : getOrderedMultilibs()) {
301 llvm::sys::path::append(Dir, M.includeSuffix());
302 llvm::sys::path::append(Dir, "include");
304 }
305 }
306}
307
309 ArgStringList &CC1Args,
311 CC1Args.push_back("-nostdsysteminc");
312}
313
315 ArgStringList &CC1Args) const {
316 if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
317 options::OPT_nostdincxx))
318 return;
319
322
323 auto AddCXXIncludePath = [&](StringRef Path) {
325 if (Version.empty())
326 return;
327
328 {
329
331 llvm::sys::path::append(TargetDir, Target, "c++", Version);
333 }
334
335 {
336
338 llvm::sys::path::append(Dir, "c++", Version);
340 }
341 };
342
346 llvm::sys::path::append(P, "..", "include");
347 AddCXXIncludePath(P);
348 break;
349 }
351
352 break;
353 }
354
356 if (SysRoot.empty())
357 return;
358
359 for (const Multilib &M : getOrderedMultilibs()) {
361 llvm::sys::path::append(Dir, M.gccSuffix());
364
366 llvm::sys::path::append(TargetDir, "usr", "include", "c++", "v1");
367 if (D.getVFS().exists(TargetDir)) {
369 break;
370 }
371
372 llvm::sys::path::append(Dir, "include", "c++", "v1");
374 break;
375 }
377 llvm::sys::path::append(Dir, "include", "c++");
378 std::error_code EC;
380
381 for (llvm::vfs::directory_iterator
382 LI = D.getVFS().dir_begin(Dir.str(), EC),
383 LE;
384 !EC && LI != LE; LI = LI.increment(EC)) {
385 StringRef VersionText = llvm::sys::path::filename(LI->path());
387 if (CandidateVersion.Major == -1)
388 continue;
389 if (CandidateVersion <= Version)
390 continue;
391 Version = CandidateVersion;
392 }
393 if (Version.Major != -1) {
394 llvm::sys::path::append(Dir, Version.Text);
396 }
397 break;
398 }
399 }
400 }
401}
402
406 const ArgList &Args,
407 const char *LinkingOutput) const {
408 const Driver &D = getToolChain().getDriver();
409
410
411 Args.ClaimAllArgs(options::OPT_g_Group);
412
413 Args.ClaimAllArgs(options::OPT_emit_llvm);
414
415
416 Args.ClaimAllArgs(options::OPT_w);
417
418 Args.ClaimAllArgs(options::OPT_stdlib_EQ);
419
420
421 ArgStringList CmdArgs;
422
423 CmdArgs.push_back("rcsD");
425
426 for (const auto &II : Inputs) {
427 if (II.isFilename()) {
428 CmdArgs.push_back(II.getFilename());
429 }
430 }
431
432
433
434 const char *OutputFileName = Output.getFilename();
435 if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
436 if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
437 D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
438 return;
439 }
440 }
441
442 const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
443 C.addCommand(std::make_unique(JA, *this,
445 Exec, CmdArgs, Inputs, Output));
446}
447
451 const ArgList &Args,
452 const char *LinkingOutput) const {
453 ArgStringList CmdArgs;
454
456 const Driver &D = getToolChain().getDriver();
457 const llvm::Triple::ArchType Arch = TC.getArch();
458 const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
459
461
462 CmdArgs.push_back("-Bstatic");
463
464 if (TC.getTriple().isRISCV() && Args.hasArg(options::OPT_mno_relax))
465 CmdArgs.push_back("--no-relax");
466
467 if (Triple.isARM() || Triple.isThumb()) {
469 if (IsBigEndian)
471 CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
472 } else if (Triple.isAArch64()) {
473 CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL");
474 }
475
476 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
477 options::OPT_r)) {
478 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt0.o")));
479 }
480
481 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
482 options::OPT_s, options::OPT_t, options::OPT_r});
483
484 TC.AddFilePathLibArgs(Args, CmdArgs);
485
486 for (const auto &LibPath : TC.getLibraryPaths())
487 CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-L", LibPath)));
488
489 if (TC.ShouldLinkCXXStdlib(Args)) {
490 bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
491 !Args.hasArg(options::OPT_static);
492 if (OnlyLibstdcxxStatic)
493 CmdArgs.push_back("-Bstatic");
494 TC.AddCXXStdlibLibArgs(Args, CmdArgs);
495 if (OnlyLibstdcxxStatic)
496 CmdArgs.push_back("-Bdynamic");
497 CmdArgs.push_back("-lm");
498 }
499
500 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
502
503 CmdArgs.push_back("-lc");
504 }
505
506 if (D.isUsingLTO()) {
507 assert(!Inputs.empty() && "Must have at least one input.");
508
509 auto Input = llvm::find_if(
511 if (Input == Inputs.end())
512
513
514 Input = Inputs.begin();
515
518 }
519 if (TC.getTriple().isRISCV())
520 CmdArgs.push_back("-X");
521
522
523
524
526 CmdArgs.push_back("--target2=rel");
527
528 CmdArgs.push_back("-o");
530
531 C.addCommand(std::make_unique(
533 Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs, Output));
534}
535
536
537
538
540 const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
541 const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 ||
542 getTriple().getArch() == llvm::Triple::aarch64_be;
543 const bool IsRISCV64 = getTriple().getArch() == llvm::Triple::riscv64;
545 Res |= SanitizerKind::Address;
546 Res |= SanitizerKind::KernelAddress;
547 Res |= SanitizerKind::PointerCompare;
548 Res |= SanitizerKind::PointerSubtract;
549 Res |= SanitizerKind::Fuzzer;
550 Res |= SanitizerKind::FuzzerNoLink;
551 Res |= SanitizerKind::Vptr;
552 Res |= SanitizerKind::SafeStack;
553 Res |= SanitizerKind::Thread;
554 Res |= SanitizerKind::Scudo;
555 if (IsX86_64 || IsAArch64 || IsRISCV64) {
556 Res |= SanitizerKind::HWAddress;
557 Res |= SanitizerKind::KernelHWAddress;
558 }
559 return Res;
560}
561
564 return MultilibMacroDefines;
565}
llvm::MachO::Target Target
Compilation - A set of tasks to perform for a single driver invocation.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
InputInfo - Wrapper for information about an input source.
const char * getFilename() const
This corresponds to a single GCC multilib, or a segment of one controlled by a command line flag.
MultilibBuilder & flag(StringRef Flag, bool Disallow=false)
Add a flag to the flags list Flag must be a flag accepted by the driver.
This class can be used to create a MultilibSet, and contains helper functions to add combinations of ...
MultilibSetBuilder & Either(const MultilibBuilder &M1, const MultilibBuilder &M2)
Add a set of mutually incompatible Multilib segments.
MultilibSet makeMultilibSet() const
static llvm::ErrorOr< MultilibSet > parseYaml(llvm::MemoryBufferRef, llvm::SourceMgr::DiagHandlerTy=nullptr, void *DiagHandlerCtxt=nullptr)
This corresponds to a single GCC Multilib, or a segment of one controlled by a command line flag.
const std::string & getErrorMessage() const
const flags_list & flags() const
Get the flags that indicate or contraindicate this multilib's use All elements begin with either '-' ...
std::vector< std::string > flags_list
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
static constexpr ResponseFileSupport AtFileCurCP()