LLVM: lib/ToolDrivers/llvm-lib/LibDriver.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

33#include

34

35using namespace llvm;

37

38namespace {

39

40#define OPTTABLE_STR_TABLE_CODE

41#include "Options.inc"

42#undef OPTTABLE_STR_TABLE_CODE

43

44enum {

45 OPT_INVALID = 0,

46#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),

47#include "Options.inc"

48#undef OPTION

49};

50

51#define OPTTABLE_PREFIXES_TABLE_CODE

52#include "Options.inc"

53#undef OPTTABLE_PREFIXES_TABLE_CODE

54

57#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),

58#include "Options.inc"

59#undef OPTION

60};

61

63public:

64 LibOptTable()

65 : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable,

67};

68}

69

73 return std::string(Val);

74}

75

78 std::vector Ret;

79

80 Ret.push_back("");

81

82

83 for (auto *Arg : Args->filtered(OPT_libpath))

85

86

88 if (!EnvOpt)

89 return Ret;

91 while (!Env.empty()) {

93 std::tie(Path, Env) = Env.split(';');

94 Ret.push_back(Path);

95 }

96 return Ret;

97}

98

99

103

104 if (std::error_code EC = MB.getError()) {

105 llvm::errs() << "cannot open file " << Path << ": " << EC.message() << "\n";

106 return nullptr;

107 }

108

109 return std::move(*MB);

110}

111

117 return std::string(Path);

118 }

119 return "";

120}

121

123 if (!E)

124 return;

126 llvm::errs() << "error opening '" << File << "': " << EIB.message() << '\n';

127 exit(1);

128 });

129}

130

132

133 std::unique_ptr B;

134 for (auto *Arg : Args.filtered(OPT_INPUT)) {

135

137 Arg->getValue(), false, false);

139

141 B = std::move(MaybeBuf.get());

142 break;

143 }

144 }

145

146

147 if (B)

148 return;

149

152 fatalOpenError(std::move(Err), B->getBufferIdentifier());

153

154 std::vector Names;

158 Names.push_back(NameOrErr.get());

159 }

162 fatalOpenError(std::move(Err), B->getBufferIdentifier());

163}

164

166 std::error_code EC;

168 if (!Obj)

169 return Obj.takeError();

170

177 "unknown machine: " + std::to_string(Machine));

178 }

179

181}

182

185 if (!TripleStr)

187

189 switch (T.getArch()) {

201 default:

203 "unknown arch in target triple: " + *TripleStr);

204 }

205}

206

209 if (LibMachine == FileMachine)

210 return true;

211

212

213 switch (LibMachine) {

220 default:

221 return false;

222 }

223}

224

225static void appendFile(std::vector &Members,

229

234 << ": not a COFF object, bitcode, archive, import library or "

235 "resource file\n";

236 exit(1);

237 }

238

239

240

241

242

247

250 if (!ChildMB) {

252 llvm::errs() << MB.getBufferIdentifier() << ": " << EIB.message()

253 << "\n";

254 });

255 exit(1);

256 }

257

258 appendFile(Members, LibMachine, LibMachineSource, *ChildMB);

259 }

260

262 return;

263 }

264

265

266

267

268

269

270

271

276 if (!MaybeFileMachine) {

279 llvm::errs() << MB.getBufferIdentifier() << ": "

280 << EIB.message() << "\n";

281 });

282 exit(1);

283 }

285

286

287

288

289

295 << " conflicts with inferred library machine type,"

296 << " use /machine:arm64ec or /machine:arm64x\n";

297 exit(1);

298 }

299 LibMachine = FileMachine;

300 LibMachineSource =

302 .str();

303 } else if (machineMatches(LibMachine, FileMachine)) {

306 << " conflicts with library machine type "

307 << machineToStr(LibMachine) << LibMachineSource << '\n';

308 exit(1);

309 }

310 }

311 }

312

313 Members.emplace_back(MB);

314}

315

319

320

323 ArgsArr = NewArgs;

324

325 LibOptTable Table;

326 unsigned MissingIndex;

327 unsigned MissingCount;

329 Table.ParseArgs(ArgsArr.slice(1), MissingIndex, MissingCount);

330 if (MissingCount) {

331 llvm::errs() << "missing arg value for \""

332 << Args.getArgString(MissingIndex) << "\", expected "

333 << MissingCount

334 << (MissingCount == 1 ? " argument.\n" : " arguments.\n");

335 return 1;

336 }

337 for (auto *Arg : Args.filtered(OPT_UNKNOWN))

339 << "\n";

340

341

342 if (Args.hasArg(OPT_help)) {

343 Table.printHelp(outs(), "llvm-lib [options] file...", "LLVM Lib");

344 return 0;

345 }

346

347

349 for (auto *Arg : Args.filtered(OPT_ignore))

351

352

353 std::string OutputPath;

354 if (auto *Arg = Args.getLastArg(OPT_out)) {

356 }

357

359 std::string LibMachineSource;

360 if (auto *Arg = Args.getLastArg(OPT_machine)) {

364 return 1;

365 }

366 LibMachineSource =

367 std::string(" (from '/machine:") + Arg->getValue() + "' flag)";

368 }

369

370

371 if (Args.hasArg(OPT_deffile)) {

372

373 if (OutputPath.empty()) {

374 llvm::errs() << "no output path given\n";

375 return 1;

376 }

377

379 llvm::errs() << "/def option requires /machine to be specified" << '\n';

380 return 1;

381 }

382

383 std::unique_ptr MB =

384 openFile(Args.getLastArg(OPT_deffile)->getValue());

385 if (!MB)

386 return 1;

387

388 if (!MB->getBufferSize()) {

389 llvm::errs() << "definition file empty\n";

390 return 1;

391 }

392

395

396 if (!Def) {

397 llvm::errs() << "error parsing definition\n"

399 return 1;

400 }

401

402 std::vector NativeExports;

403 std::string OutputFile = Def->OutputFile;

404

405 if (isArm64EC(LibMachine) && Args.hasArg(OPT_nativedeffile)) {

406 std::unique_ptr NativeMB =

407 openFile(Args.getLastArg(OPT_nativedeffile)->getValue());

408 if (!NativeMB)

409 return 1;

410

411 if (!NativeMB->getBufferSize()) {

412 llvm::errs() << "native definition file empty\n";

413 return 1;

414 }

415

418

419 if (!NativeDef) {

420 llvm::errs() << "error parsing native definition\n"

422 return 1;

423 }

424 NativeExports = std::move(NativeDef->Exports);

425 OutputFile = std::move(NativeDef->OutputFile);

426 }

427

430 false, NativeExports)) {

433 });

434 return 1;

435 }

436 return 0;

437 }

438

439

440

441 if (!Args.hasArgNoClaim(OPT_INPUT) && !Args.hasArg(OPT_llvmlibempty)) {

442 if (!IgnoredWarnings.contains("emptyoutput")) {

443 llvm::errs() << "warning: no input files, not writing output file\n";

444 llvm::errs() << " pass /llvmlibempty to write empty .lib file,\n";

445 llvm::errs() << " pass /ignore:emptyoutput to suppress warning\n";

446 if (Args.hasFlag(OPT_WX, OPT_WX_no, false)) {

447 llvm::errs() << "treating warning as error due to /WX\n";

448 return 1;

449 }

450 }

451 return 0;

452 }

453

454 if (Args.hasArg(OPT_lst)) {

456 return 0;

457 }

458

459 std::vector SearchPaths = getSearchPaths(&Args, Saver);

460

461 std::vector<std::unique_ptr> MBs;

463 std::vector Members;

464

465

466 for (auto *Arg : Args.filtered(OPT_INPUT)) {

467

469 if (Path.empty()) {

471 return 1;

472 }

473

474

475

476

477

478

479

480

481 if (!Seen.insert(Path).second)

482 continue;

483

484

486 Path, false, false);

489

490

491 appendFile(Members, LibMachine, LibMachineSource, MBRef);

492

493

494 MBs.push_back(std::move(*MOrErr));

495 }

496

497

498 if (OutputPath.empty()) {

499 if (!Members.empty()) {

501 } else {

502 llvm::errs() << "no output path given, and cannot infer with no inputs\n";

503 return 1;

504 }

505 }

506

507 bool Thin = Args.hasArg(OPT_llvmlibthin);

508 if (Thin) {

513 if (PathOrErr)

514 Member.MemberName = Saver.save(*PathOrErr);

515 }

516 }

517 }

518

519

520 std::reverse(Members.begin(), Members.end());

521

522 auto Symtab = Args.hasFlag(OPT_llvmlibindex, OPT_llvmlibindex_no,

523 true)

524 ? SymtabWritingMode::NormalSymtab

525 : SymtabWritingMode::NoSymtab;

526

528 OutputPath, Members, Symtab,

530 true, Thin, nullptr, COFF::isArm64EC(LibMachine))) {

533 });

534 return 1;

535 }

536

537 return 0;

538}

Defines the llvm::Arg class for parsed arguments.

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

COFF::MachineTypes Machine

static bool machineMatches(COFF::MachineTypes LibMachine, COFF::MachineTypes FileMachine)

static Expected< COFF::MachineTypes > getBitcodeFileMachine(MemoryBufferRef MB)

static Expected< COFF::MachineTypes > getCOFFFileMachine(MemoryBufferRef MB)

static std::string getDefaultOutputPath(const NewArchiveMember &FirstMember)

static std::string findInputFile(StringRef File, ArrayRef< StringRef > Paths)

static void doList(opt::InputArgList &Args)

static std::vector< StringRef > getSearchPaths(opt::InputArgList *Args, StringSaver &Saver)

std::unique_ptr< MemoryBuffer > openFile(const Twine &Path)

static void appendFile(std::vector< NewArchiveMember > &Members, COFF::MachineTypes &LibMachine, std::string &LibMachineSource, MemoryBufferRef MB)

static void fatalOpenError(llvm::Error E, Twine File)

Provides a library for accessing information about this process and other processes on the operating ...

StringSet - A set-like wrapper for the StringMap.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

ArrayRef< T > slice(size_t N, size_t M) const

slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.

Allocate memory in an ever growing pool, as if by bump-pointer.

Base class for error info classes.

virtual std::string message() const

Return the error message as a string.

Represents either an error or a value T.

std::error_code getError() const

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

reference get()

Returns a reference to the stored T value.

StringRef getBufferIdentifier() const

StringRef getBuffer() const

static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

std::pair< StringRef, StringRef > split(char Separator) const

Split into two substrings around the first occurrence of a separator character.

constexpr bool empty() const

empty - Check if the string is empty.

Saves strings in the provided stable storage and returns a StringRef with a stable character pointer.

StringRef save(const char *S)

StringSet - A wrapper for StringMap that provides set-like functionality.

bool contains(StringRef key) const

Check if the set contains the given key.

std::pair< typename Base::iterator, bool > insert(StringRef key)

Triple - Helper class for working with autoconf configuration names.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

iterator_range< child_iterator > children(Error &Err, bool SkipInternal=true) const

static Expected< std::unique_ptr< COFFObjectFile > > create(MemoryBufferRef Object)

A concrete instance of a particular driver option.

std::string getAsString(const ArgList &Args) const

Return a formatted version of the argument and its values, for diagnostics.

const char * getValue(unsigned N=0) const

Specialization of OptTable.

static std::optional< std::string > GetEnv(StringRef name)

@ IMAGE_FILE_MACHINE_ARM64

@ IMAGE_FILE_MACHINE_UNKNOWN

@ IMAGE_FILE_MACHINE_AMD64

@ IMAGE_FILE_MACHINE_ARM64EC

@ IMAGE_FILE_MACHINE_R4000

@ IMAGE_FILE_MACHINE_I386

@ IMAGE_FILE_MACHINE_ARM64X

@ IMAGE_FILE_MACHINE_ARMNT

bool isAnyArm64(T Machine)

bool isArm64EC(T Machine)

@ C

The default llvm calling convention, compatible with C.

bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, SmallVectorImpl< const char * > &Argv)

A convenience helper which supports the typical use case of expansion function call.

void TokenizeWindowsCommandLine(StringRef Source, StringSaver &Saver, SmallVectorImpl< const char * > &NewArgv, bool MarkEOLs=false)

Tokenizes a string of Windows command line arguments, which may contain quotes and escaped quotes.

Expected< COFFModuleDefinition > parseCOFFModuleDefinition(MemoryBufferRef MB, COFF::MachineTypes Machine, bool MingwDef=false, bool AddUnderscores=true)

Error writeImportLibrary(StringRef ImportName, StringRef Path, ArrayRef< COFFShortExport > Exports, COFF::MachineTypes Machine, bool MinGW, ArrayRef< COFFShortExport > NativeExports={})

Writes a COFF import library containing entries described by the Exports array.

bool exists(const basic_file_status &status)

Does file exist?

void replace_extension(SmallVectorImpl< char > &path, const Twine &extension, Style style=Style::native)

Replace the file extension of path with extension.

bool is_relative(const Twine &path, Style style=Style::native)

Is path relative?

void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")

Append to path.

This is an optimization pass for GlobalISel generic memory operations.

file_magic identify_magic(StringRef magic)

Identify the type of a binary file based on how magical it is.

Error writeArchive(StringRef ArcName, ArrayRef< NewArchiveMember > NewMembers, SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr< MemoryBuffer > OldArchiveBuf=nullptr, std::optional< bool > IsEC=std::nullopt, function_ref< void(Error)> Warn=warnToStderr)

int libDriverMain(ArrayRef< const char * > ARgs)

void handleAllErrors(Error E, HandlerTs &&... Handlers)

Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...

std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

raw_fd_ostream & outs()

This returns a reference to a raw_fd_ostream for standard output.

Expected< std::string > getBitcodeTargetTriple(MemoryBufferRef Buffer)

Read the header of the specified bitcode buffer and extract just the triple information.

COFF::MachineTypes getMachineType(StringRef S)

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

auto reverse(ContainerTy &&C)

StringRef machineToStr(COFF::MachineTypes MT)

raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

Expected< std::string > computeArchiveRelativePath(StringRef From, StringRef To)

Error errorCodeToError(std::error_code EC)

Helper for converting an std::error_code to a Error.

std::error_code errorToErrorCode(Error Err)

Helper for converting an ECError to a std::error_code.

std::unique_ptr< MemoryBuffer > Buf

file_magic - An "enum class" enumeration of file types based on magic (the first N bytes of the file)...

@ coff_import_library

COFF import library.

@ archive

ar style archive file

@ windows_resource

Windows compiled resource file (.res)

@ coff_object

COFF object file.

Entry for a single option instance in the option data table.