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 (D.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 (D.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()