[PECOFF] Add a field for machine type to PECOFFLinkingContext.

So that we can determine what the target architecture is. Adding this
field does not mean that we are going to support non-i386 architectures
soon; there are many things to do to support them, and I'm focusing on
i386 now. But this is the first step toward multi architecture support.

llvm-svn: 190627
This commit is contained in:
Rui Ueyama 2013-09-12 19:46:53 +00:00
parent 9063bf462a
commit 98896ed1b5
5 changed files with 36 additions and 15 deletions

View File

@ -20,6 +20,9 @@
#include "llvm/Support/COFF.h"
#include "llvm/Support/ErrorHandling.h"
using llvm::COFF::MachineTypes;
using llvm::COFF::WindowsSubsystem;
namespace lld {
class PECOFFLinkingContext : public LinkingContext {
@ -27,8 +30,9 @@ public:
PECOFFLinkingContext()
: _baseAddress(0x400000), _stackReserve(1024 * 1024), _stackCommit(4096),
_heapReserve(1024 * 1024), _heapCommit(4096),
_subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN), _minOSVersion(6, 0),
_nxCompat(true), _largeAddressAware(false),
_subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN),
_machineType(llvm::COFF::IMAGE_FILE_MACHINE_I386),
_minOSVersion(6, 0), _nxCompat(true), _largeAddressAware(false),
_baseRelocationEnabled(true), _terminalServerAware(true),
_dynamicBaseEnabled(true), _imageType(ImageType::IMAGE_EXE) {
setDeadStripping(true);
@ -98,8 +102,11 @@ public:
uint64_t getHeapReserve() const { return _heapReserve; }
uint64_t getHeapCommit() const { return _heapCommit; }
void setSubsystem(llvm::COFF::WindowsSubsystem ss) { _subsystem = ss; }
llvm::COFF::WindowsSubsystem getSubsystem() const { return _subsystem; }
void setSubsystem(WindowsSubsystem ss) { _subsystem = ss; }
WindowsSubsystem getSubsystem() const { return _subsystem; }
void setMachineType(MachineTypes type) { _machineType = type; }
MachineTypes getMachineType() const { return _machineType; }
void setMinOSVersion(const OSVersion &version) { _minOSVersion = version; }
OSVersion getMinOSVersion() const { return _minOSVersion; }
@ -154,7 +161,8 @@ private:
uint64_t _stackCommit;
uint64_t _heapReserve;
uint64_t _heapCommit;
llvm::COFF::WindowsSubsystem _subsystem;
WindowsSubsystem _subsystem;
MachineTypes _machineType;
OSVersion _minOSVersion;
bool _nxCompat;
bool _largeAddressAware;

View File

@ -116,6 +116,15 @@ llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) {
.Default(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN);
}
llvm::COFF::MachineTypes stringToMachineType(StringRef str) {
return llvm::StringSwitch<llvm::COFF::MachineTypes>(str.lower())
.Case("arm", llvm::COFF::IMAGE_FILE_MACHINE_ARM)
.Case("ebc", llvm::COFF::IMAGE_FILE_MACHINE_EBC)
.Case("x64", llvm::COFF::IMAGE_FILE_MACHINE_AMD64)
.Case("x86", llvm::COFF::IMAGE_FILE_MACHINE_I386)
.Default(llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN);
}
// Handle /failifmatch option.
bool handleFailIfMismatchOption(StringRef option,
std::map<StringRef, StringRef> &mustMatch,
@ -308,12 +317,13 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
break;
}
case OPT_machine: {
StringRef platform = inputArg->getValue();
if (!platform.equals_lower("x64")) {
diagnostics << "error: LLD does not support non-x64 platform, "
<< "but got /machine:" << platform << "\n";
StringRef arg = inputArg->getValue();
llvm::COFF::MachineTypes type = stringToMachineType(arg);
if (type == llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
diagnostics << "error: unknown machine type: " << arg << "\n";
return true;
}
ctx.setMachineType(type);
break;
}
case OPT_subsystem: {

View File

@ -55,6 +55,12 @@ bool PECOFFLinkingContext::validateImpl(raw_ostream &diagnostics) {
return true;
}
// Architectures other than i386 is not supported yet.
if (_machineType != llvm::COFF::IMAGE_FILE_MACHINE_I386) {
diagnostics << "Machine type other than x86 is not supported.\n";
return true;
}
_reader = createReaderPECOFF(*this);
_writer = createWriterPECOFF(*this);
return false;

View File

@ -145,7 +145,7 @@ public:
std::memset(&_coffHeader, 0, sizeof(_coffHeader));
std::memset(&_peHeader, 0, sizeof(_peHeader));
_coffHeader.Machine = llvm::COFF::IMAGE_FILE_MACHINE_I386;
_coffHeader.Machine = context.getMachineType();
_coffHeader.TimeDateStamp = time(NULL);
// The size of PE header including optional data directory is always 224.

View File

@ -34,6 +34,7 @@ TEST_F(WinLinkParserTest, Basic) {
EXPECT_FALSE(parse("link.exe", "/subsystem:console", "/out:a.exe",
"-entry:start", "a.obj", "b.obj", "c.obj", nullptr));
EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _context.getSubsystem());
EXPECT_EQ(llvm::COFF::IMAGE_FILE_MACHINE_I386, _context.getMachineType());
EXPECT_EQ("a.exe", _context.outputPath());
EXPECT_EQ("_start", _context.entrySymbolName());
EXPECT_EQ(3, inputFileCount());
@ -107,11 +108,7 @@ TEST_F(WinLinkParserTest, Libpath) {
}
TEST_F(WinLinkParserTest, MachineX64) {
EXPECT_FALSE(parse("link.exe", "/machine:x64", "a.obj", nullptr));
}
TEST_F(WinLinkParserTest, MachineArm) {
EXPECT_TRUE(parse("link.exe", "/machine:arm", "a.obj", nullptr));
EXPECT_TRUE(parse("link.exe", "/machine:x64", "a.obj", nullptr));
}
TEST_F(WinLinkParserTest, MinMajorOSVersion) {