LLVM 17.0.0git
LibDriver.cpp
Go to the documentation of this file.
1//===- LibDriver.cpp - lib.exe-compatible driver --------------------------===//
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// Defines an interface to a lib.exe-compatible driver that also understands
10// bitcode files. Used by llvm-lib and lld-link /lib.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/StringSet.h"
21#include "llvm/Object/COFF.h"
24#include "llvm/Option/Arg.h"
25#include "llvm/Option/ArgList.h"
26#include "llvm/Option/Option.h"
28#include "llvm/Support/Path.h"
32#include <optional>
33
34using namespace llvm;
35using namespace llvm::object;
36
37namespace {
38
39enum {
40 OPT_INVALID = 0,
41#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
42#include "Options.inc"
43#undef OPTION
44};
45
46#define PREFIX(NAME, VALUE) \
47 static constexpr StringLiteral NAME##_init[] = VALUE; \
48 static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
49 std::size(NAME##_init) - 1);
50#include "Options.inc"
51#undef PREFIX
52
53static constexpr opt::OptTable::Info InfoTable[] = {
54#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
55 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \
56 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
57#include "Options.inc"
58#undef OPTION
59};
60
61class LibOptTable : public opt::GenericOptTable {
62public:
63 LibOptTable() : opt::GenericOptTable(InfoTable, true) {}
64};
65} // namespace
66
67static std::string getDefaultOutputPath(const NewArchiveMember &FirstMember) {
68 SmallString<128> Val = StringRef(FirstMember.Buf->getBufferIdentifier());
70 return std::string(Val.str());
71}
72
73static std::vector<StringRef> getSearchPaths(opt::InputArgList *Args,
74 StringSaver &Saver) {
75 std::vector<StringRef> Ret;
76 // Add current directory as first item of the search path.
77 Ret.push_back("");
78
79 // Add /libpath flags.
80 for (auto *Arg : Args->filtered(OPT_libpath))
81 Ret.push_back(Arg->getValue());
82
83 // Add $LIB.
84 std::optional<std::string> EnvOpt = sys::Process::GetEnv("LIB");
85 if (!EnvOpt)
86 return Ret;
87 StringRef Env = Saver.save(*EnvOpt);
88 while (!Env.empty()) {
89 StringRef Path;
90 std::tie(Path, Env) = Env.split(';');
91 Ret.push_back(Path);
92 }
93 return Ret;
94}
95
96// Opens a file. Path has to be resolved already. (used for def file)
97std::unique_ptr<MemoryBuffer> openFile(const Twine &Path) {
99
100 if (std::error_code EC = MB.getError()) {
101 llvm::errs() << "cannot open file " << Path << ": " << EC.message() << "\n";
102 return nullptr;
103 }
104
105 return std::move(*MB);
106}
107
109 for (StringRef Dir : Paths) {
110 SmallString<128> Path = Dir;
111 sys::path::append(Path, File);
112 if (sys::fs::exists(Path))
113 return std::string(Path);
114 }
115 return "";
116}
117
118static void fatalOpenError(llvm::Error E, Twine File) {
119 if (!E)
120 return;
121 handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) {
122 llvm::errs() << "error opening '" << File << "': " << EIB.message() << '\n';
123 exit(1);
124 });
125}
126
127static void doList(opt::InputArgList &Args) {
128 // lib.exe prints the contents of the first archive file.
129 std::unique_ptr<MemoryBuffer> B;
130 for (auto *Arg : Args.filtered(OPT_INPUT)) {
131 // Create or open the archive object.
133 Arg->getValue(), /*IsText=*/false, /*RequiresNullTerminator=*/false);
134 fatalOpenError(errorCodeToError(MaybeBuf.getError()), Arg->getValue());
135
136 if (identify_magic(MaybeBuf.get()->getBuffer()) == file_magic::archive) {
137 B = std::move(MaybeBuf.get());
138 break;
139 }
140 }
141
142 // lib.exe doesn't print an error if no .lib files are passed.
143 if (!B)
144 return;
145
146 Error Err = Error::success();
147 object::Archive Archive(B.get()->getMemBufferRef(), Err);
148 fatalOpenError(std::move(Err), B->getBufferIdentifier());
149
150 std::vector<StringRef> Names;
151 for (auto &C : Archive.children(Err)) {
152 Expected<StringRef> NameOrErr = C.getName();
153 fatalOpenError(NameOrErr.takeError(), B->getBufferIdentifier());
154 Names.push_back(NameOrErr.get());
155 }
156 for (auto Name : reverse(Names))
157 llvm::outs() << Name << '\n';
158 fatalOpenError(std::move(Err), B->getBufferIdentifier());
159}
160
162 std::error_code EC;
163 auto Obj = object::COFFObjectFile::create(MB);
164 if (!Obj)
165 return Obj.takeError();
166
167 uint16_t Machine = (*Obj)->getMachine();
168 if (Machine != COFF::IMAGE_FILE_MACHINE_I386 &&
173 "unknown machine: " + std::to_string(Machine));
174 }
175
176 return static_cast<COFF::MachineTypes>(Machine);
177}
178
181 if (!TripleStr)
182 return TripleStr.takeError();
183
184 switch (Triple(*TripleStr).getArch()) {
185 case Triple::x86:
187 case Triple::x86_64:
189 case Triple::arm:
191 case Triple::aarch64:
193 default:
195 "unknown arch in target triple: " + *TripleStr);
196 }
197}
198
199static void appendFile(std::vector<NewArchiveMember> &Members,
200 COFF::MachineTypes &LibMachine,
201 std::string &LibMachineSource, MemoryBufferRef MB) {
202 file_magic Magic = identify_magic(MB.getBuffer());
203
204 if (Magic != file_magic::coff_object && Magic != file_magic::bitcode &&
208 << ": not a COFF object, bitcode, archive, import library or "
209 "resource file\n";
210 exit(1);
211 }
212
213 // If a user attempts to add an archive to another archive, llvm-lib doesn't
214 // handle the first archive file as a single file. Instead, it extracts all
215 // members from the archive and add them to the second archive. This behavior
216 // is for compatibility with Microsoft's lib command.
217 if (Magic == file_magic::archive) {
218 Error Err = Error::success();
219 object::Archive Archive(MB, Err);
220 fatalOpenError(std::move(Err), MB.getBufferIdentifier());
221
222 for (auto &C : Archive.children(Err)) {
223 Expected<MemoryBufferRef> ChildMB = C.getMemoryBufferRef();
224 if (!ChildMB) {
225 handleAllErrors(ChildMB.takeError(), [&](const ErrorInfoBase &EIB) {
226 llvm::errs() << MB.getBufferIdentifier() << ": " << EIB.message()
227 << "\n";
228 });
229 exit(1);
230 }
231
232 appendFile(Members, LibMachine, LibMachineSource, *ChildMB);
233 }
234
235 fatalOpenError(std::move(Err), MB.getBufferIdentifier());
236 return;
237 }
238
239 // Check that all input files have the same machine type.
240 // Mixing normal objects and LTO bitcode files is fine as long as they
241 // have the same machine type.
242 // Doing this here duplicates the header parsing work that writeArchive()
243 // below does, but it's not a lot of work and it's a bit awkward to do
244 // in writeArchive() which needs to support many tools, can't assume the
245 // input is COFF, and doesn't have a good way to report errors.
246 if (Magic == file_magic::coff_object || Magic == file_magic::bitcode) {
247 Expected<COFF::MachineTypes> MaybeFileMachine =
250 if (!MaybeFileMachine) {
251 handleAllErrors(MaybeFileMachine.takeError(),
252 [&](const ErrorInfoBase &EIB) {
253 llvm::errs() << MB.getBufferIdentifier() << ": "
254 << EIB.message() << "\n";
255 });
256 exit(1);
257 }
258 COFF::MachineTypes FileMachine = *MaybeFileMachine;
259
260 // FIXME: Once lld-link rejects multiple resource .obj files:
261 // Call convertResToCOFF() on .res files and add the resulting
262 // COFF file to the .lib output instead of adding the .res file, and remove
263 // this check. See PR42180.
264 if (FileMachine != COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
265 if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
266 LibMachine = FileMachine;
267 LibMachineSource =
268 (" (inferred from earlier file '" + MB.getBufferIdentifier() + "')")
269 .str();
270 } else if (LibMachine != FileMachine) {
271 llvm::errs() << MB.getBufferIdentifier() << ": file machine type "
272 << machineToStr(FileMachine)
273 << " conflicts with library machine type "
274 << machineToStr(LibMachine) << LibMachineSource << '\n';
275 exit(1);
276 }
277 }
278 }
279
280 Members.emplace_back(MB);
281}
282
284 BumpPtrAllocator Alloc;
285 StringSaver Saver(Alloc);
286
287 // Parse command line arguments.
288 SmallVector<const char *, 20> NewArgs(ArgsArr.begin(), ArgsArr.end());
290 ArgsArr = NewArgs;
291
292 LibOptTable Table;
293 unsigned MissingIndex;
294 unsigned MissingCount;
295 opt::InputArgList Args =
296 Table.ParseArgs(ArgsArr.slice(1), MissingIndex, MissingCount);
297 if (MissingCount) {
298 llvm::errs() << "missing arg value for \""
299 << Args.getArgString(MissingIndex) << "\", expected "
300 << MissingCount
301 << (MissingCount == 1 ? " argument.\n" : " arguments.\n");
302 return 1;
303 }
304 for (auto *Arg : Args.filtered(OPT_UNKNOWN))
305 llvm::errs() << "ignoring unknown argument: " << Arg->getAsString(Args)
306 << "\n";
307
308 // Handle /help
309 if (Args.hasArg(OPT_help)) {
310 Table.printHelp(outs(), "llvm-lib [options] file...", "LLVM Lib");
311 return 0;
312 }
313
314 // Parse /ignore:
315 llvm::StringSet<> IgnoredWarnings;
316 for (auto *Arg : Args.filtered(OPT_ignore))
317 IgnoredWarnings.insert(Arg->getValue());
318
319 // get output library path, if any
320 std::string OutputPath;
321 if (auto *Arg = Args.getLastArg(OPT_out)) {
322 OutputPath = Arg->getValue();
323 }
324
326 std::string LibMachineSource;
327 if (auto *Arg = Args.getLastArg(OPT_machine)) {
328 LibMachine = getMachineType(Arg->getValue());
329 if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
330 llvm::errs() << "unknown /machine: arg " << Arg->getValue() << '\n';
331 return 1;
332 }
333 LibMachineSource =
334 std::string(" (from '/machine:") + Arg->getValue() + "' flag)";
335 }
336
337 // create an import library
338 if (Args.hasArg(OPT_deffile)) {
339
340 if (OutputPath.empty()) {
341 llvm::errs() << "no output path given\n";
342 return 1;
343 }
344
345 if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
346 llvm::errs() << "/def option requires /machine to be specified" << '\n';
347 return 1;
348 }
349
350 std::unique_ptr<MemoryBuffer> MB =
351 openFile(Args.getLastArg(OPT_deffile)->getValue());
352 if (!MB)
353 return 1;
354
355 if (!MB->getBufferSize()) {
356 llvm::errs() << "definition file empty\n";
357 return 1;
358 }
359
361 parseCOFFModuleDefinition(*MB, LibMachine, true);
362
363 if (!Def) {
364 llvm::errs() << "error parsing definition\n"
365 << errorToErrorCode(Def.takeError()).message();
366 return 1;
367 }
368
369 return writeImportLibrary(Def->OutputFile, OutputPath, Def->Exports,
370 LibMachine,
371 /*MinGW=*/false)
372 ? 1
373 : 0;
374 }
375
376 // If no input files and not told otherwise, silently do nothing to match
377 // lib.exe
378 if (!Args.hasArgNoClaim(OPT_INPUT) && !Args.hasArg(OPT_llvmlibempty)) {
379 if (!IgnoredWarnings.contains("emptyoutput")) {
380 llvm::errs() << "warning: no input files, not writing output file\n";
381 llvm::errs() << " pass /llvmlibempty to write empty .lib file,\n";
382 llvm::errs() << " pass /ignore:emptyoutput to suppress warning\n";
383 if (Args.hasFlag(OPT_WX, OPT_WX_no, false)) {
384 llvm::errs() << "treating warning as error due to /WX\n";
385 return 1;
386 }
387 }
388 return 0;
389 }
390
391 if (Args.hasArg(OPT_lst)) {
392 doList(Args);
393 return 0;
394 }
395
396 std::vector<StringRef> SearchPaths = getSearchPaths(&Args, Saver);
397
398 std::vector<std::unique_ptr<MemoryBuffer>> MBs;
399 StringSet<> Seen;
400 std::vector<NewArchiveMember> Members;
401
402 // Create a NewArchiveMember for each input file.
403 for (auto *Arg : Args.filtered(OPT_INPUT)) {
404 // Find a file
405 std::string Path = findInputFile(Arg->getValue(), SearchPaths);
406 if (Path.empty()) {
407 llvm::errs() << Arg->getValue() << ": no such file or directory\n";
408 return 1;
409 }
410
411 // Input files are uniquified by pathname. If you specify the exact same
412 // path more than once, all but the first one are ignored.
413 //
414 // Note that there's a loophole in the rule; you can prepend `.\` or
415 // something like that to a path to make it look different, and they are
416 // handled as if they were different files. This behavior is compatible with
417 // Microsoft lib.exe.
418 if (!Seen.insert(Path).second)
419 continue;
420
421 // Open a file.
423 Path, /*IsText=*/false, /*RequiresNullTerminator=*/false);
425 MemoryBufferRef MBRef = (*MOrErr)->getMemBufferRef();
426
427 // Append a file.
428 appendFile(Members, LibMachine, LibMachineSource, MBRef);
429
430 // Take the ownership of the file buffer to keep the file open.
431 MBs.push_back(std::move(*MOrErr));
432 }
433
434 // Create an archive file.
435 if (OutputPath.empty()) {
436 if (!Members.empty()) {
437 OutputPath = getDefaultOutputPath(Members[0]);
438 } else {
439 llvm::errs() << "no output path given, and cannot infer with no inputs\n";
440 return 1;
441 }
442 }
443 // llvm-lib uses relative paths for both regular and thin archives, unlike
444 // standard GNU ar, which only uses relative paths for thin archives and
445 // basenames for regular archives.
446 for (NewArchiveMember &Member : Members) {
447 if (sys::path::is_relative(Member.MemberName)) {
448 Expected<std::string> PathOrErr =
449 computeArchiveRelativePath(OutputPath, Member.MemberName);
450 if (PathOrErr)
451 Member.MemberName = Saver.save(*PathOrErr);
452 }
453 }
454
455 // For compatibility with MSVC, reverse member vector after de-duplication.
456 std::reverse(Members.begin(), Members.end());
457
458 if (Error E =
459 writeArchive(OutputPath, Members,
460 /*WriteSymtab=*/true, object::Archive::K_GNU,
461 /*Deterministic*/ true, Args.hasArg(OPT_llvmlibthin))) {
462 handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
463 llvm::errs() << OutputPath << ": " << EI.message() << "\n";
464 });
465 return 1;
466 }
467
468 return 0;
469}
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
arm prera ldst opt
Defines the llvm::Arg class for parsed arguments.
basic Basic Alias true
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
std::string Name
static Expected< COFF::MachineTypes > getBitcodeFileMachine(MemoryBufferRef MB)
Definition: LibDriver.cpp:179
static Expected< COFF::MachineTypes > getCOFFFileMachine(MemoryBufferRef MB)
Definition: LibDriver.cpp:161
static std::string getDefaultOutputPath(const NewArchiveMember &FirstMember)
Definition: LibDriver.cpp:67
static std::string findInputFile(StringRef File, ArrayRef< StringRef > Paths)
Definition: LibDriver.cpp:108
static void doList(opt::InputArgList &Args)
Definition: LibDriver.cpp:127
static std::vector< StringRef > getSearchPaths(opt::InputArgList *Args, StringSaver &Saver)
Definition: LibDriver.cpp:73
std::unique_ptr< MemoryBuffer > openFile(const Twine &Path)
Definition: LibDriver.cpp:97
static void appendFile(std::vector< NewArchiveMember > &Members, COFF::MachineTypes &LibMachine, std::string &LibMachineSource, MemoryBufferRef MB)
Definition: LibDriver.cpp:199
static void fatalOpenError(llvm::Error E, Twine File)
Definition: LibDriver.cpp:118
Provides a library for accessing information about this process and other processes on the operating ...
This file contains some templates that are useful if you are working with the STL at all.
StringSet - A set-like wrapper for the StringMap.
@ Paths
Definition: TextStubV5.cpp:120
@ Names
Definition: TextStubV5.cpp:106
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
iterator end() const
Definition: ArrayRef.h:152
iterator begin() const
Definition: ArrayRef.h:151
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.
Definition: ArrayRef.h:193
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:66
Base class for error info classes.
Definition: Error.h:47
virtual std::string message() const
Return the error message as a string.
Definition: Error.h:55
Represents either an error or a value T.
Definition: ErrorOr.h:56
reference get()
Definition: ErrorOr.h:150
std::error_code getError() const
Definition: ErrorOr.h:153
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Tagged union holding either a T or a Error.
Definition: Error.h:470
Error takeError()
Take ownership of the stored error.
Definition: Error.h:597
reference get()
Returns a reference to the stored T value.
Definition: Error.h:567
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...
Definition: SmallString.h:26
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:261
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:687
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
Saves strings in the provided stable storage and returns a StringRef with a stable character pointer.
Definition: StringSaver.h:21
StringRef save(const char *S)
Definition: StringSaver.h:30
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition: StringSet.h:23
bool contains(StringRef key) const
Check if the set contains the given key.
Definition: StringSet.h:51
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition: StringSet.h:34
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition: Triple.h:356
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
iterator_range< child_iterator > children(Error &Err, bool SkipInternal=true) const
Definition: Archive.h:344
static Expected< std::unique_ptr< COFFObjectFile > > create(MemoryBufferRef Object)
Specialization of OptTable.
Definition: OptTable.h:267
static std::optional< std::string > GetEnv(StringRef name)
MachineTypes
Definition: COFF.h:92
@ IMAGE_FILE_MACHINE_ARM64
Definition: COFF.h:100
@ IMAGE_FILE_MACHINE_UNKNOWN
Definition: COFF.h:95
@ IMAGE_FILE_MACHINE_AMD64
Definition: COFF.h:97
@ IMAGE_FILE_MACHINE_I386
Definition: COFF.h:103
@ IMAGE_FILE_MACHINE_ARMNT
Definition: COFF.h:99
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
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)
Error writeImportLibrary(StringRef ImportName, StringRef Path, ArrayRef< COFFShortExport > Exports, COFF::MachineTypes Machine, bool MinGW)
bool exists(const basic_file_status &status)
Does file exist?
Definition: Path.cpp:1077
void replace_extension(SmallVectorImpl< char > &path, const Twine &extension, Style style=Style::native)
Replace the file extension of path with extension.
Definition: Path.cpp:480
bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
Definition: Path.cpp:699
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:456
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Definition: Magic.cpp:33
int libDriverMain(ArrayRef< const char * > ARgs)
Definition: LibDriver.cpp:283
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition: Error.h:966
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:79
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.
Definition: Error.h:1246
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:495
StringRef machineToStr(COFF::MachineTypes MT)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Error writeArchive(StringRef ArcName, ArrayRef< NewArchiveMember > NewMembers, bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr< MemoryBuffer > OldArchiveBuf=nullptr)
Expected< std::string > computeArchiveRelativePath(StringRef From, StringRef To)
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:92
std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
Definition: Error.cpp:98
std::unique_ptr< MemoryBuffer > Buf
Definition: ArchiveWriter.h:21
file_magic - An "enum class" enumeration of file types based on magic (the first N bytes of the file)...
Definition: Magic.h:20
@ coff_import_library
COFF import library.
Definition: Magic.h:47
@ archive
ar style archive file
Definition: Magic.h:24
@ bitcode
Bitcode file.
Definition: Magic.h:23
@ windows_resource
Windows compiled resource file (.res)
Definition: Magic.h:49
@ coff_object
COFF object file.
Definition: Magic.h:46
Entry for a single option instance in the option data table.
Definition: OptTable.h:43