summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/COFF/Driver.cpp5
-rw-r--r--lld/COFF/Driver.h4
-rw-r--r--lld/COFF/DriverUtils.cpp28
-rw-r--r--lld/COFF/SymbolTable.cpp1
-rw-r--r--llvm/include/llvm/ToolDrivers/llvm-lib/LibDriver.h15
-rw-r--r--llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp37
-rw-r--r--llvm/lib/ToolDrivers/llvm-lib/Options.td13
-rw-r--r--llvm/test/tools/llvm-lib/machine-mismatch.test13
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)
OpenPOWER on IntegriCloud