[PECOFF][Driver] Add -stack command line option.

llvm-svn: 183604
This commit is contained in:
Rui Ueyama 2013-06-08 03:59:00 +00:00
parent 7b5592bc0b
commit eb0cc96e4b
6 changed files with 84 additions and 39 deletions

View File

@ -23,9 +23,17 @@ namespace lld {
class PECOFFTargetInfo : public TargetInfo {
public:
PECOFFTargetInfo()
: _subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN),
: _stackReserve(1024 * 1024),
_stackCommit(4096),
_subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN),
_minOSVersion(6, 0) {}
struct OSVersion {
OSVersion(int v1, int v2) : majorVersion(v1), minorVersion(v2) {}
int majorVersion;
int minorVersion;
};
virtual error_code parseFile(
std::unique_ptr<MemoryBuffer> &mb,
std::vector<std::unique_ptr<File>> &result) const;
@ -35,31 +43,21 @@ public:
virtual void addPasses(PassManager &pm) const {}
void setSubsystem(llvm::COFF::WindowsSubsystem subsystem) {
_subsystem = subsystem;
}
void setStackReserve(uint64_t size) { _stackReserve = size; }
uint64_t getStackReserve() const { return _stackReserve; }
llvm::COFF::WindowsSubsystem getSubsystem() const {
return _subsystem;
}
void setStackCommit(uint64_t size) { _stackCommit = size; }
uint64_t getStackCommit() const { return _stackCommit; }
void setSubsystem(llvm::COFF::WindowsSubsystem ss) { _subsystem = ss; }
llvm::COFF::WindowsSubsystem getSubsystem() const { return _subsystem; }
void setMinOSVersion(const OSVersion &version) { _minOSVersion = version; }
OSVersion getMinOSVersion() const { return _minOSVersion; }
virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
struct OSVersion {
OSVersion(int v1, int v2) : majorVersion(v1), minorVersion(v2) {}
int majorVersion;
int minorVersion;
};
void setMinOSVersion(const OSVersion &version) {
_minOSVersion = version;
}
OSVersion getMinOSVersion() const {
return _minOSVersion;
}
StringRef allocateString(const StringRef &ref) {
char *x = _extraStrings.Allocate<char>(ref.size() + 1);
memcpy(x, ref.data(), ref.size());
@ -68,6 +66,8 @@ public:
}
private:
uint64_t _stackReserve;
uint64_t _stackCommit;
llvm::COFF::WindowsSubsystem _subsystem;
OSVersion _minOSVersion;

View File

@ -66,6 +66,35 @@ int findDoubleDash(int argc, const char *argv[]) {
return -1;
}
// Displays error message if the given version does not match with
// /^\d+$/.
bool checkNumber(StringRef version, const char *errorMessage,
raw_ostream &diagnostics) {
if (version.str().find_first_not_of("0123456789") != std::string::npos
|| version.empty()) {
diagnostics << "error: " << errorMessage << version << "\n";
return false;
}
return true;
}
// Parse -stack command line option. The form of the option is
// "-stack:stackReserveSize[,stackCommitSize]".
bool parseStackOption(PECOFFTargetInfo &info, const StringRef &arg,
raw_ostream &diagnostics) {
StringRef reserve, commit;
llvm::tie(reserve, commit) = arg.split(',');
if (!checkNumber(reserve, "invalid stack size: ", diagnostics))
return false;
info.setStackReserve(atoi(reserve.str().c_str()));
if (!commit.empty()) {
if (!checkNumber(commit, "invalid stack size: ", diagnostics))
return false;
info.setStackCommit(atoi(commit.str().c_str()));
}
return true;
}
// Returns subsystem type for the given string.
llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) {
std::string arg(str.lower());
@ -75,28 +104,15 @@ llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) {
.Default(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN);
}
// Displays error message if the given version does not match with
// /^\d+$/.
bool checkOSVersion(StringRef version, const char *errorMessage,
raw_ostream &diagnostics) {
if (version.str().find_first_not_of("0123456789") != std::string::npos
|| version.empty()) {
diagnostics << "error: " << errorMessage << version << "\n";
return false;
}
return true;
}
bool parseMinOSVersion(PECOFFTargetInfo &info, StringRef &osVersion,
bool parseMinOSVersion(PECOFFTargetInfo &info, const StringRef &osVersion,
raw_ostream &diagnostics) {
StringRef majorVersion, minorVersion;
llvm::tie(majorVersion, minorVersion) = osVersion.split('.');
if (minorVersion.empty())
minorVersion = "0";
if (!checkOSVersion(majorVersion, "invalid OS major version: ", diagnostics))
if (!checkNumber(majorVersion, "invalid OS major version: ", diagnostics))
return false;
if (!checkOSVersion(minorVersion, "invalid OS minor version: ", diagnostics))
if (!checkNumber(minorVersion, "invalid OS minor version: ", diagnostics))
return false;
PECOFFTargetInfo::OSVersion minOSVersion(atoi(majorVersion.str().c_str()),
atoi(minorVersion.str().c_str()));
@ -195,6 +211,11 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
info.appendLLVMOption((*it)->getValue());
}
// Handle -stack
if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_stack))
if (!parseStackOption(info, arg->getValue(), diagnostics))
return true;
// Handle -subsystem
if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_subsystem))
if (!parseSubsystemOption(info, arg->getValue(), diagnostics))

View File

@ -9,6 +9,10 @@ def out : Separate<["-", "/"], "out">,
HelpText<"Path to file to write output">;
def out_c : Joined<["-", "/"], "out:">, Alias<out>;
def stack : Separate<["-", "/"], "stack">,
HelpText<"Size of the stack">;
def stack_c: Joined<["-", "/"], "stack:">, Alias<stack>;
def subsystem : Separate<["-", "/"], "subsystem">,
HelpText<"Specify subsystem">;
def subsystem_c: Joined<["-", "/"], "subsystem:">, Alias<subsystem>;

View File

@ -23,6 +23,13 @@ error_code PECOFFTargetInfo::parseFile(
}
bool PECOFFTargetInfo::validate(raw_ostream &diagnostics) {
if (_stackReserve < _stackCommit) {
diagnostics << "Invalid stack size: reserve size must be equal to or "
<< "greater than commit size, but got "
<< _stackCommit << " and " << _stackReserve << ".\n";
return true;
}
_reader = createReaderPECOFF(*this);
_writer = createWriterPECOFF(*this);
return false;

View File

@ -155,8 +155,8 @@ public:
| llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
| llvm::COFF::IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
_peHeader.SizeOfStackReserve = 0x100000;
_peHeader.SizeOfStackCommit = 0x1000;
_peHeader.SizeOfStackReserve = targetInfo.getStackReserve();
_peHeader.SizeOfStackCommit = targetInfo.getStackCommit();
_peHeader.SizeOfHeapReserve = 0x100000;
_peHeader.SizeOfHeapCommit = 0x1000;

View File

@ -44,6 +44,8 @@ TEST_F(WinLinkParserTest, Basic) {
EXPECT_EQ("c.obj", inputFiles[2]);
EXPECT_EQ(6, info->getMinOSVersion().majorVersion);
EXPECT_EQ(0, info->getMinOSVersion().minorVersion);
EXPECT_EQ(1024 * 1024, info->getStackReserve());
EXPECT_EQ(4096, info->getStackCommit());
}
TEST_F(WinLinkParserTest, WindowsStyleOption) {
@ -83,4 +85,15 @@ TEST_F(WinLinkParserTest, MinMajorMinorOSVersion) {
EXPECT_EQ(1, info->getMinOSVersion().minorVersion);
}
TEST_F(WinLinkParserTest, StackReserve) {
parse("link.exe", "-stack", "8192", nullptr);
EXPECT_EQ(8192, info->getStackReserve());
EXPECT_EQ(4096, info->getStackCommit());
}
TEST_F(WinLinkParserTest, StackReserveAndCommit) {
parse("link.exe", "-stack", "16384,8192", nullptr);
EXPECT_EQ(16384, info->getStackReserve());
EXPECT_EQ(8192, info->getStackCommit());
}
} // end anonymous namespace