aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-09-02 21:17:18 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-08 17:34:50 +0000
commit06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (patch)
tree62f873df87c7c675557a179e0c4c83fe9f3087bc /contrib/llvm-project/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
parentcf037972ea8863e2bab7461d77345367d2c1e054 (diff)
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp154
1 files changed, 123 insertions, 31 deletions
diff --git a/contrib/llvm-project/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp b/contrib/llvm-project/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
index ade753ad8918..747e4c5928ea 100644
--- a/contrib/llvm-project/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
+++ b/contrib/llvm-project/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
@@ -19,6 +19,7 @@
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/COFF.h"
+#include "llvm/Object/COFFModuleDefinition.h"
#include "llvm/Object/WindowsMachineFlag.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
@@ -31,6 +32,7 @@
#include <optional>
using namespace llvm;
+using namespace llvm::object;
namespace {
@@ -60,7 +62,7 @@ class LibOptTable : public opt::GenericOptTable {
public:
LibOptTable() : opt::GenericOptTable(InfoTable, true) {}
};
-}
+} // namespace
static std::string getDefaultOutputPath(const NewArchiveMember &FirstMember) {
SmallString<128> Val = StringRef(FirstMember.Buf->getBufferIdentifier());
@@ -91,6 +93,18 @@ static std::vector<StringRef> getSearchPaths(opt::InputArgList *Args,
return Ret;
}
+// Opens a file. Path has to be resolved already. (used for def file)
+std::unique_ptr<MemoryBuffer> openFile(const Twine &Path) {
+ ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB = MemoryBuffer::getFile(Path);
+
+ if (std::error_code EC = MB.getError()) {
+ llvm::errs() << "cannot open file " << Path << ": " << EC.message() << "\n";
+ return nullptr;
+ }
+
+ return std::move(*MB);
+}
+
static std::string findInputFile(StringRef File, ArrayRef<StringRef> Paths) {
for (StringRef Dir : Paths) {
SmallString<128> Path = Dir;
@@ -110,7 +124,7 @@ static void fatalOpenError(llvm::Error E, Twine File) {
});
}
-static void doList(opt::InputArgList& Args) {
+static void doList(opt::InputArgList &Args) {
// lib.exe prints the contents of the first archive file.
std::unique_ptr<MemoryBuffer> B;
for (auto *Arg : Args.filtered(OPT_INPUT)) {
@@ -133,12 +147,14 @@ static void doList(opt::InputArgList& Args) {
object::Archive Archive(B.get()->getMemBufferRef(), Err);
fatalOpenError(std::move(Err), B->getBufferIdentifier());
+ std::vector<StringRef> Names;
for (auto &C : Archive.children(Err)) {
Expected<StringRef> NameOrErr = C.getName();
fatalOpenError(NameOrErr.takeError(), B->getBufferIdentifier());
- StringRef Name = NameOrErr.get();
- llvm::outs() << Name << '\n';
+ Names.push_back(NameOrErr.get());
}
+ for (auto Name : reverse(Names))
+ llvm::outs() << Name << '\n';
fatalOpenError(std::move(Err), B->getBufferIdentifier());
}
@@ -151,8 +167,7 @@ static Expected<COFF::MachineTypes> getCOFFFileMachine(MemoryBufferRef MB) {
uint16_t Machine = (*Obj)->getMachine();
if (Machine != COFF::IMAGE_FILE_MACHINE_I386 &&
Machine != COFF::IMAGE_FILE_MACHINE_AMD64 &&
- Machine != COFF::IMAGE_FILE_MACHINE_ARMNT &&
- Machine != COFF::IMAGE_FILE_MACHINE_ARM64) {
+ Machine != COFF::IMAGE_FILE_MACHINE_ARMNT && !COFF::isAnyArm64(Machine)) {
return createStringError(inconvertibleErrorCode(),
"unknown machine: " + std::to_string(Machine));
}
@@ -165,7 +180,8 @@ static Expected<COFF::MachineTypes> getBitcodeFileMachine(MemoryBufferRef MB) {
if (!TripleStr)
return TripleStr.takeError();
- switch (Triple(*TripleStr).getArch()) {
+ Triple T(*TripleStr);
+ switch (T.getArch()) {
case Triple::x86:
return COFF::IMAGE_FILE_MACHINE_I386;
case Triple::x86_64:
@@ -173,13 +189,32 @@ static Expected<COFF::MachineTypes> getBitcodeFileMachine(MemoryBufferRef MB) {
case Triple::arm:
return COFF::IMAGE_FILE_MACHINE_ARMNT;
case Triple::aarch64:
- return COFF::IMAGE_FILE_MACHINE_ARM64;
+ return T.isWindowsArm64EC() ? COFF::IMAGE_FILE_MACHINE_ARM64EC
+ : COFF::IMAGE_FILE_MACHINE_ARM64;
default:
return createStringError(inconvertibleErrorCode(),
"unknown arch in target triple: " + *TripleStr);
}
}
+static bool machineMatches(COFF::MachineTypes LibMachine,
+ COFF::MachineTypes FileMachine) {
+ if (LibMachine == FileMachine)
+ return true;
+ // ARM64EC mode allows both pure ARM64, ARM64EC and X64 objects to be mixed in
+ // the archive.
+ switch (LibMachine) {
+ case COFF::IMAGE_FILE_MACHINE_ARM64:
+ return FileMachine == COFF::IMAGE_FILE_MACHINE_ARM64X;
+ case COFF::IMAGE_FILE_MACHINE_ARM64EC:
+ case COFF::IMAGE_FILE_MACHINE_ARM64X:
+ return COFF::isAnyArm64(FileMachine) ||
+ FileMachine == COFF::IMAGE_FILE_MACHINE_AMD64;
+ default:
+ return false;
+ }
+}
+
static void appendFile(std::vector<NewArchiveMember> &Members,
COFF::MachineTypes &LibMachine,
std::string &LibMachineSource, MemoryBufferRef MB) {
@@ -247,11 +282,18 @@ static void appendFile(std::vector<NewArchiveMember> &Members,
// this check. See PR42180.
if (FileMachine != COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
+ if (FileMachine == COFF::IMAGE_FILE_MACHINE_ARM64EC) {
+ llvm::errs() << MB.getBufferIdentifier() << ": file machine type "
+ << machineToStr(FileMachine)
+ << " conflicts with inferred library machine type,"
+ << " use /machine:arm64ec or /machine:arm64x\n";
+ exit(1);
+ }
LibMachine = FileMachine;
LibMachineSource =
(" (inferred from earlier file '" + MB.getBufferIdentifier() + "')")
.str();
- } else if (LibMachine != FileMachine) {
+ } else if (!machineMatches(LibMachine, FileMachine)) {
llvm::errs() << MB.getBufferIdentifier() << ": file machine type "
<< machineToStr(FileMachine)
<< " conflicts with library machine type "
@@ -300,6 +342,63 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
for (auto *Arg : Args.filtered(OPT_ignore))
IgnoredWarnings.insert(Arg->getValue());
+ // get output library path, if any
+ std::string OutputPath;
+ if (auto *Arg = Args.getLastArg(OPT_out)) {
+ OutputPath = Arg->getValue();
+ }
+
+ COFF::MachineTypes LibMachine = COFF::IMAGE_FILE_MACHINE_UNKNOWN;
+ std::string LibMachineSource;
+ if (auto *Arg = Args.getLastArg(OPT_machine)) {
+ LibMachine = getMachineType(Arg->getValue());
+ if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
+ llvm::errs() << "unknown /machine: arg " << Arg->getValue() << '\n';
+ return 1;
+ }
+ LibMachineSource =
+ std::string(" (from '/machine:") + Arg->getValue() + "' flag)";
+ }
+
+ // create an import library
+ if (Args.hasArg(OPT_deffile)) {
+
+ if (OutputPath.empty()) {
+ llvm::errs() << "no output path given\n";
+ return 1;
+ }
+
+ if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
+ llvm::errs() << "/def option requires /machine to be specified" << '\n';
+ return 1;
+ }
+
+ std::unique_ptr<MemoryBuffer> MB =
+ openFile(Args.getLastArg(OPT_deffile)->getValue());
+ if (!MB)
+ return 1;
+
+ if (!MB->getBufferSize()) {
+ llvm::errs() << "definition file empty\n";
+ return 1;
+ }
+
+ Expected<COFFModuleDefinition> Def =
+ parseCOFFModuleDefinition(*MB, LibMachine, /*MingwDef=*/false);
+
+ if (!Def) {
+ llvm::errs() << "error parsing definition\n"
+ << errorToErrorCode(Def.takeError()).message();
+ return 1;
+ }
+
+ return writeImportLibrary(Def->OutputFile, OutputPath, Def->Exports,
+ LibMachine,
+ /*MinGW=*/false)
+ ? 1
+ : 0;
+ }
+
// If no input files and not told otherwise, silently do nothing to match
// lib.exe
if (!Args.hasArgNoClaim(OPT_INPUT) && !Args.hasArg(OPT_llvmlibempty)) {
@@ -322,18 +421,6 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
std::vector<StringRef> SearchPaths = getSearchPaths(&Args, Saver);
- COFF::MachineTypes LibMachine = COFF::IMAGE_FILE_MACHINE_UNKNOWN;
- std::string LibMachineSource;
- if (auto *Arg = Args.getLastArg(OPT_machine)) {
- LibMachine = getMachineType(Arg->getValue());
- if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
- llvm::errs() << "unknown /machine: arg " << Arg->getValue() << '\n';
- return 1;
- }
- LibMachineSource =
- std::string(" (from '/machine:") + Arg->getValue() + "' flag)";
- }
-
std::vector<std::unique_ptr<MemoryBuffer>> MBs;
StringSet<> Seen;
std::vector<NewArchiveMember> Members;
@@ -371,14 +458,13 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
}
// Create an archive file.
- std::string OutputPath;
- if (auto *Arg = Args.getLastArg(OPT_out)) {
- OutputPath = Arg->getValue();
- } else if (!Members.empty()) {
- OutputPath = getDefaultOutputPath(Members[0]);
- } else {
- llvm::errs() << "no output path given, and cannot infer with no inputs\n";
- return 1;
+ if (OutputPath.empty()) {
+ if (!Members.empty()) {
+ OutputPath = getDefaultOutputPath(Members[0]);
+ } else {
+ llvm::errs() << "no output path given, and cannot infer with no inputs\n";
+ return 1;
+ }
}
// llvm-lib uses relative paths for both regular and thin archives, unlike
// standard GNU ar, which only uses relative paths for thin archives and
@@ -392,10 +478,16 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
}
}
+ // For compatibility with MSVC, reverse member vector after de-duplication.
+ std::reverse(Members.begin(), Members.end());
+
+ bool Thin = Args.hasArg(OPT_llvmlibthin);
if (Error E =
writeArchive(OutputPath, Members,
- /*WriteSymtab=*/true, object::Archive::K_GNU,
- /*Deterministic*/ true, Args.hasArg(OPT_llvmlibthin))) {
+ /*WriteSymtab=*/true,
+ Thin ? object::Archive::K_GNU : object::Archive::K_COFF,
+ /*Deterministic*/ true, Thin, nullptr,
+ COFF::isArm64EC(LibMachine))) {
handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
llvm::errs() << OutputPath << ": " << EI.message() << "\n";
});