diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-09-02 21:17:18 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-12-08 17:34:50 +0000 |
commit | 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (patch) | |
tree | 62f873df87c7c675557a179e0c4c83fe9f3087bc /contrib/llvm-project/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp | |
parent | cf037972ea8863e2bab7461d77345367d2c1e054 (diff) | |
parent | 7fa27ce4a07f19b07799a767fc29416f3b625afb (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.cpp | 154 |
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"; }); |