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"
37 const llvm::Triple &TargetTriple,
43 if (TargetTriple.isRISCV64()) {
47 .
flag(
"-march=rv64imafdc")
52 (Arch ==
"rv64imafdc") || (Arch ==
"rv64gc");
61 return Result.Multilibs.select(
D, Flags, Result.SelectedMultilibs);
63 if (TargetTriple.isRISCV32()) {
70 .
flag(
"-march=rv32im")
73 .
flag(
"-march=rv32iac")
76 .
flag(
"-march=rv32imafc")
77 .
flag(
"-mabi=ilp32f");
80 bool UseI = (Arch ==
"rv32i") || (Arch ==
"rv32ic");
81 bool UseIm = (Arch ==
"rv32im") || (Arch ==
"rv32imc");
82 bool UseImafc = (Arch ==
"rv32imafc") || (Arch ==
"rv32imafdc") ||
95 return Result.Multilibs.select(
D, Flags, Result.SelectedMultilibs);
101 if (!
D.SysRoot.empty())
105 llvm::sys::path::append(SysRootDir,
"..",
"lib",
"clang-runtimes");
108 llvm::sys::path::append(SysRootDir,
D.getTargetTriple());
110 return std::string(SysRootDir);
121 if (!SysRoot.empty()) {
122 for (
const Multilib &M : getOrderedMultilibs()) {
124 llvm::sys::path::append(Dir, M.osSuffix(),
"lib");
133 if (Triple.getArch() != llvm::Triple::aarch64 &&
134 Triple.getArch() != llvm::Triple::aarch64_be)
137 if (Triple.getVendor() != llvm::Triple::UnknownVendor)
140 if (Triple.getOS() != llvm::Triple::UnknownOS)
143 return Triple.getEnvironmentName() ==
"elf";
147 if (!Triple.isRISCV())
150 if (Triple.getVendor() != llvm::Triple::UnknownVendor)
153 if (Triple.getOS() != llvm::Triple::UnknownOS)
156 return Triple.getEnvironmentName() ==
"elf";
161 return Triple.isPPC() && Triple.getOS() == llvm::Triple::UnknownOS &&
162 Triple.getEnvironment() == llvm::Triple::EABI;
166 StringRef MultilibPath,
const ArgList &Args,
168 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB =
169 D.getVFS().getBufferForFile(MultilibPath);
173 llvm::ErrorOr<MultilibSet> ErrorOrMultilibSet =
175 if (ErrorOrMultilibSet.getError())
177 Result.Multilibs = ErrorOrMultilibSet.get();
178 if (
Result.Multilibs.select(
D, Flags,
Result.SelectedMultilibs))
180 D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags,
" ");
181 std::stringstream ss;
188 D.Diag(clang::diag::note_drv_available_multilibs) << ss.str();
197 D.Diag(clang::diag::err_drv_multilib_custom_error)
202 Result.SelectedMultilibs.clear();
207static std::optional<llvm::SmallString<128>>
209 const ArgList &Args) {
211 if (Arg *ConfigFileArg = Args.getLastArg(options::OPT_multi_lib_config)) {
212 MultilibPath = ConfigFileArg->getValue();
213 if (!
D.getVFS().exists(MultilibPath)) {
214 D.Diag(clang::diag::err_drv_no_such_file) << MultilibPath.str();
225 const ArgList &Args) {
229 std::optional<llvm::SmallString<128>> MultilibPath =
233 if (
D.getVFS().exists(*MultilibPath)) {
263BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs()
const {
274 ArgStringList &CC1Args)
const {
275 if (DriverArgs.hasArg(options::OPT_nostdinc))
278 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
280 llvm::sys::path::append(Dir,
"include");
284 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
291 if (!SysRoot.empty()) {
292 for (
const Multilib &M : getOrderedMultilibs()) {
294 llvm::sys::path::append(Dir, M.includeSuffix());
295 llvm::sys::path::append(Dir,
"include");
302 ArgStringList &CC1Args,
304 CC1Args.push_back(
"-nostdsysteminc");
308 ArgStringList &CC1Args)
const {
309 if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
310 options::OPT_nostdincxx))
316 auto AddCXXIncludePath = [&](StringRef
Path) {
324 llvm::sys::path::append(TargetDir,
Target,
"c++", Version);
331 llvm::sys::path::append(Dir,
"c++", Version);
339 llvm::sys::path::append(
P,
"..",
"include");
340 AddCXXIncludePath(
P);
352 for (
const Multilib &M : getOrderedMultilibs()) {
354 llvm::sys::path::append(Dir, M.gccSuffix());
359 llvm::sys::path::append(TargetDir,
"usr",
"include",
"c++",
"v1");
360 if (
D.getVFS().exists(TargetDir)) {
365 llvm::sys::path::append(Dir,
"include",
"c++",
"v1");
370 llvm::sys::path::append(Dir,
"include",
"c++");
374 for (llvm::vfs::directory_iterator
375 LI =
D.getVFS().dir_begin(Dir.str(), EC),
377 !EC && LI != LE; LI = LI.increment(EC)) {
378 StringRef VersionText = llvm::sys::path::filename(LI->path());
380 if (CandidateVersion.Major == -1)
382 if (CandidateVersion <= Version)
384 Version = CandidateVersion;
386 if (Version.
Major != -1) {
387 llvm::sys::path::append(Dir, Version.
Text);
400 const char *LinkingOutput)
const {
401 const Driver &
D = getToolChain().getDriver();
404 Args.ClaimAllArgs(options::OPT_g_Group);
406 Args.ClaimAllArgs(options::OPT_emit_llvm);
409 Args.ClaimAllArgs(options::OPT_w);
411 Args.ClaimAllArgs(options::OPT_stdlib_EQ);
414 ArgStringList CmdArgs;
416 CmdArgs.push_back(
"rcsD");
419 for (
const auto &II : Inputs) {
420 if (II.isFilename()) {
421 CmdArgs.push_back(II.getFilename());
428 if (Output.
isFilename() && llvm::sys::fs::exists(OutputFileName)) {
429 if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
430 D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
435 const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
436 C.addCommand(std::make_unique<Command>(JA, *
this,
438 Exec, CmdArgs, Inputs, Output));
445 const char *LinkingOutput)
const {
446 ArgStringList CmdArgs;
449 const Driver &
D = getToolChain().getDriver();
450 const llvm::Triple::ArchType Arch = TC.getArch();
451 const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
455 CmdArgs.push_back(
"-Bstatic");
457 if (TC.getTriple().isRISCV() && Args.hasArg(options::OPT_mno_relax))
458 CmdArgs.push_back(
"--no-relax");
460 if (Triple.isARM() || Triple.isThumb()) {
464 CmdArgs.push_back(IsBigEndian ?
"-EB" :
"-EL");
465 }
else if (Triple.isAArch64()) {
466 CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ?
"-EB" :
"-EL");
469 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
471 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(
"crt0.o")));
474 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
475 options::OPT_s, options::OPT_t, options::OPT_r});
477 TC.AddFilePathLibArgs(Args, CmdArgs);
479 for (
const auto &LibPath : TC.getLibraryPaths())
480 CmdArgs.push_back(Args.MakeArgString(llvm::Twine(
"-L", LibPath)));
482 if (TC.ShouldLinkCXXStdlib(Args)) {
483 bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
484 !Args.hasArg(options::OPT_static);
485 if (OnlyLibstdcxxStatic)
486 CmdArgs.push_back(
"-Bstatic");
487 TC.AddCXXStdlibLibArgs(Args, CmdArgs);
488 if (OnlyLibstdcxxStatic)
489 CmdArgs.push_back(
"-Bdynamic");
490 CmdArgs.push_back(
"-lm");
493 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
496 CmdArgs.push_back(
"-lc");
499 if (
D.isUsingLTO()) {
500 assert(!Inputs.empty() &&
"Must have at least one input.");
502 auto Input = llvm::find_if(
504 if (Input == Inputs.end())
507 Input = Inputs.begin();
512 if (TC.getTriple().isRISCV())
513 CmdArgs.push_back(
"-X");
519 CmdArgs.push_back(
"--target2=rel");
521 CmdArgs.push_back(
"-o");
524 C.addCommand(std::make_unique<Command>(
526 Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs, Output));
533 const bool IsX86_64 =
getTriple().getArch() == llvm::Triple::x86_64;
534 const bool IsAArch64 =
getTriple().getArch() == llvm::Triple::aarch64 ||
535 getTriple().getArch() == llvm::Triple::aarch64_be;
536 const bool IsRISCV64 =
getTriple().getArch() == llvm::Triple::riscv64;
538 Res |= SanitizerKind::Address;
539 Res |= SanitizerKind::KernelAddress;
540 Res |= SanitizerKind::PointerCompare;
541 Res |= SanitizerKind::PointerSubtract;
542 Res |= SanitizerKind::Fuzzer;
543 Res |= SanitizerKind::FuzzerNoLink;
544 Res |= SanitizerKind::Vptr;
545 Res |= SanitizerKind::SafeStack;
546 Res |= SanitizerKind::Thread;
547 Res |= SanitizerKind::Scudo;
548 if (IsX86_64 || IsAArch64 || IsRISCV64) {
549 Res |= SanitizerKind::HWAddress;
550 Res |= SanitizerKind::KernelHWAddress;
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...
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()