diff options
| -rw-r--r-- | lld/COFF/Driver.cpp | 5 | ||||
| -rw-r--r-- | lld/COFF/Driver.h | 4 | ||||
| -rw-r--r-- | lld/COFF/DriverUtils.cpp | 28 | ||||
| -rw-r--r-- | lld/COFF/SymbolTable.cpp | 1 | ||||
| -rw-r--r-- | llvm/include/llvm/ToolDrivers/llvm-lib/LibDriver.h | 15 | ||||
| -rw-r--r-- | llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp | 37 | ||||
| -rw-r--r-- | llvm/lib/ToolDrivers/llvm-lib/Options.td | 13 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-lib/machine-mismatch.test | 13 |
8 files changed, 70 insertions, 46 deletions
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 45befa6a99a..4ec250d35e2 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1205,8 +1205,11 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { Args.hasFlag(OPT_appcontainer, OPT_appcontainer_no, false); // Handle /machine - if (auto *Arg = Args.getLastArg(OPT_machine)) + if (auto *Arg = Args.getLastArg(OPT_machine)) { Config->Machine = getMachineType(Arg->getValue()); + if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) + fatal(Twine("unknown /machine argument: ") + Arg->getValue()); + } // Handle /nodefaultlib:<filename> for (auto *Arg : Args.filtered(OPT_nodefaultlib)) diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index 6b4266a85e1..1e9353118a6 100644 --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -138,10 +138,6 @@ private: void printHelp(const char *Argv0); -// For /machine option. -MachineTypes getMachineType(StringRef Arg); -StringRef machineToStr(MachineTypes MT); - // Parses a string in the form of "<integer>[,<integer>]". void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size = nullptr); diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index c59027e809e..34cfa2ff014 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -72,34 +72,6 @@ private: } // anonymous namespace -// Returns /machine's value. -MachineTypes getMachineType(StringRef S) { - MachineTypes MT = StringSwitch<MachineTypes>(S.lower()) - .Cases("x64", "amd64", AMD64) - .Cases("x86", "i386", I386) - .Case("arm", ARMNT) - .Case("arm64", ARM64) - .Default(IMAGE_FILE_MACHINE_UNKNOWN); - if (MT != IMAGE_FILE_MACHINE_UNKNOWN) - return MT; - fatal("unknown /machine argument: " + S); -} - -StringRef machineToStr(MachineTypes MT) { - switch (MT) { - case ARMNT: - return "arm"; - case ARM64: - return "arm64"; - case AMD64: - return "x64"; - case I386: - return "x86"; - default: - llvm_unreachable("unknown machine type"); - } -} - // Parses a string in the form of "<integer>[,<integer>]". void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) { StringRef S1, S2; diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 5180559a86e..dd2fe293605 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/ToolDrivers/llvm-lib/LibDriver.h" #include <utility> using namespace llvm; diff --git a/llvm/include/llvm/ToolDrivers/llvm-lib/LibDriver.h b/llvm/include/llvm/ToolDrivers/llvm-lib/LibDriver.h index 7d0735f1e3a..9fdcdd808e2 100644 --- a/llvm/include/llvm/ToolDrivers/llvm-lib/LibDriver.h +++ b/llvm/include/llvm/ToolDrivers/llvm-lib/LibDriver.h @@ -18,6 +18,21 @@ namespace llvm { template <typename T> class ArrayRef; int libDriverMain(ArrayRef<const char *> ARgs); + + +class StringRef; +namespace COFF { +enum MachineTypes : unsigned; +} + +// Returns a user-readable string for ARMNT, ARM64, AMD64, I386. +// Other MachineTypes values must not be pased in. +StringRef machineToStr(COFF::MachineTypes MT); + +// Maps /machine: arguments to a MachineTypes value. +// Only returns ARMNT, ARM64, AMD64, I386, or IMAGE_FILE_MACHINE_UNKNOWN. +COFF::MachineTypes getMachineType(StringRef S); + } #endif diff --git a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp index 0b58c540928..852a977e795 100644 --- a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp +++ b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp @@ -140,7 +140,17 @@ static void doList(opt::InputArgList& Args) { fatalOpenError(std::move(Err), B->getBufferIdentifier()); } -static StringRef machineToStr(COFF::MachineTypes MT) { +// Returns /machine's value. +COFF::MachineTypes llvm::getMachineType(StringRef S) { + return StringSwitch<COFF::MachineTypes>(S.lower()) + .Cases("x64", "amd64", COFF::IMAGE_FILE_MACHINE_AMD64) + .Cases("x86", "i386", COFF::IMAGE_FILE_MACHINE_I386) + .Case("arm", COFF::IMAGE_FILE_MACHINE_ARMNT) + .Case("arm64", COFF::IMAGE_FILE_MACHINE_ARM64) + .Default(COFF::IMAGE_FILE_MACHINE_UNKNOWN); +} + +StringRef llvm::machineToStr(COFF::MachineTypes MT) { switch (MT) { case COFF::IMAGE_FILE_MACHINE_ARMNT: return "arm"; @@ -196,9 +206,20 @@ 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)"; + } + // Create a NewArchiveMember for each input file. std::vector<NewArchiveMember> Members; - COFF::MachineTypes LibMachine = COFF::IMAGE_FILE_MACHINE_UNKNOWN; for (auto *Arg : Args.filtered(OPT_INPUT)) { std::string Path = findInputFile(Arg->getValue(), SearchPaths); if (Path.empty()) { @@ -276,14 +297,20 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) { } } + // FIXME: Once lld-link rejects multiple resource .obj files: + // Call convertResToCOFF() on .res files and add the resulting + // COFF file to the .lib output instead of adding the .res file, and remove + // this check. See PR42180. if (FileMachine != COFF::IMAGE_FILE_MACHINE_UNKNOWN) { - if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) + if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) { LibMachine = FileMachine; - else if (LibMachine != FileMachine) { + LibMachineSource = std::string(" (inferred from earlier file '") + + Arg->getValue() + "')"; + } else if (LibMachine != FileMachine) { llvm::errs() << Arg->getValue() << ": file machine type " << machineToStr(FileMachine) << " conflicts with library machine type " - << machineToStr(LibMachine) << '\n'; + << machineToStr(LibMachine) << LibMachineSource << '\n'; return 1; } } diff --git a/llvm/lib/ToolDrivers/llvm-lib/Options.td b/llvm/lib/ToolDrivers/llvm-lib/Options.td index 4c297f749ed..7863196126a 100644 --- a/llvm/lib/ToolDrivers/llvm-lib/Options.td +++ b/llvm/lib/ToolDrivers/llvm-lib/Options.td @@ -3,11 +3,11 @@ include "llvm/Option/OptParser.td" // lib.exe accepts options starting with either a dash or a slash. // Flag that takes no arguments. -class F<string name> : Flag<["/", "-", "-?"], name>; +class F<string name> : Flag<["/", "-", "/?", "-?"], name>; // Flag that takes one argument after ":". class P<string name, string help> : - Joined<["/", "-", "-?"], name#":">, HelpText<help>; + Joined<["/", "-", "/?", "-?"], name#":">, HelpText<help>; def libpath: P<"libpath", "Object file search path">; @@ -18,15 +18,18 @@ def out : P<"out", "Path to file to write output">; def llvmlibthin : F<"llvmlibthin">, HelpText<"Make .lib point to .obj files instead of copying their contents">; +def machine: P<"machine", "Specify target platform">; + def help : F<"help">; -def help_q : Flag<["/?", "-?"], "">, Alias<help>; + +// /?? and -?? must be before /? and -? to not confuse lib/Options. +def help_q : Flag<["/??", "-??", "/?", "-?"], "">, Alias<help>; //============================================================================== // The flags below do nothing. They are defined only for lib.exe compatibility. //============================================================================== -class QF<string name> : Joined<["/", "-", "-?"], name#":">; +class QF<string name> : Joined<["/", "-", "/?", "-?"], name#":">; def ignore : QF<"ignore">; -def machine: QF<"machine">; def nologo : F<"nologo">; diff --git a/llvm/test/tools/llvm-lib/machine-mismatch.test b/llvm/test/tools/llvm-lib/machine-mismatch.test index 7031b4dfbb3..43a0f7ae75f 100644 --- a/llvm/test/tools/llvm-lib/machine-mismatch.test +++ b/llvm/test/tools/llvm-lib/machine-mismatch.test @@ -24,15 +24,22 @@ Mixing object files with different machine type is not ok: RUN: not llvm-lib %t/x86_64.obj %t/i386.obj 2>&1 | \ RUN: FileCheck --check-prefix=OBJ32 %s -OBJ32: i386.obj: file machine type x86 conflicts with library machine type x64 +OBJ32: i386.obj: file machine type x86 conflicts with library machine type x64 (inferred from earlier file '{{.*}}x86_64.obj') Neither is mixing object and bitcode files with different machine type: RUN: not llvm-lib %t/x86_64.obj %t/i386.bc 2>&1 | \ RUN: FileCheck --check-prefix=BC32 %s -BC32: i386.bc: file machine type x86 conflicts with library machine type x64 +BC32: i386.bc: file machine type x86 conflicts with library machine type x64 (inferred from earlier file '{{.*}}x86_64.obj') RUN: not llvm-lib %t/arm64.bc %t/x86_64.bc 2>&1 | \ RUN: FileCheck --check-prefix=BC64 %s -BC64: x86_64.bc: file machine type x64 conflicts with library machine type arm64 +BC64: x86_64.bc: file machine type x64 conflicts with library machine type arm64 (inferred from earlier file '{{.*}}arm64.bc') + + +If /machine: is passed, its value is authoritative. + +RUN: not llvm-lib /machine:X86 %t/x86_64.obj %t/i386.obj 2>&1 | \ +RUN: FileCheck --check-prefix=OBJ64 %s +OBJ64: x86_64.obj: file machine type x64 conflicts with library machine type x86 (from '/machine:X86' flag) |

