diff options
| -rw-r--r-- | lld/include/lld/ReaderWriter/PECOFFTargetInfo.h | 42 | ||||
| -rw-r--r-- | lld/lib/Driver/WinLinkDriver.cpp | 51 | ||||
| -rw-r--r-- | lld/lib/Driver/WinLinkOptions.td | 4 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp | 7 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp | 4 | ||||
| -rw-r--r-- | lld/unittests/DriverTests/WinLinkDriverTest.cpp | 13 | 
6 files changed, 83 insertions, 38 deletions
| diff --git a/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h b/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h index 32c7f3a0100..99b57de16c0 100644 --- a/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h +++ b/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h @@ -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,30 +43,20 @@ 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; -  } - -  virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const; -  virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const; +  void setStackCommit(uint64_t size) { _stackCommit = size; } +  uint64_t getStackCommit() const { return _stackCommit; } -  struct OSVersion { -    OSVersion(int v1, int v2) : majorVersion(v1), minorVersion(v2) {} -    int majorVersion; -    int minorVersion; -  }; +  void setSubsystem(llvm::COFF::WindowsSubsystem ss) { _subsystem = ss; } +  llvm::COFF::WindowsSubsystem getSubsystem() const { return _subsystem; } -  void setMinOSVersion(const OSVersion &version) { -    _minOSVersion = version; -  } +  void setMinOSVersion(const OSVersion &version) { _minOSVersion = version; } +  OSVersion getMinOSVersion() const { return _minOSVersion; } -  OSVersion getMinOSVersion() const { -    return _minOSVersion; -  } +  virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const; +  virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;    StringRef allocateString(const StringRef &ref) {      char *x = _extraStrings.Allocate<char>(ref.size() + 1); @@ -68,6 +66,8 @@ public:    }  private: +  uint64_t _stackReserve; +  uint64_t _stackCommit;    llvm::COFF::WindowsSubsystem _subsystem;    OSVersion _minOSVersion; diff --git a/lld/lib/Driver/WinLinkDriver.cpp b/lld/lib/Driver/WinLinkDriver.cpp index 8730a9cc22e..e67337ccdd5 100644 --- a/lld/lib/Driver/WinLinkDriver.cpp +++ b/lld/lib/Driver/WinLinkDriver.cpp @@ -66,20 +66,10 @@ int findDoubleDash(int argc, const char *argv[]) {    return -1;  } -// Returns subsystem type for the given string. -llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) { -  std::string arg(str.lower()); -  return llvm::StringSwitch<llvm::COFF::WindowsSubsystem>(arg) -      .Case("windows", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI) -      .Case("console", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI) -      .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) { +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"; @@ -88,15 +78,41 @@ bool checkOSVersion(StringRef version, const char *errorMessage,    return true;  } -bool parseMinOSVersion(PECOFFTargetInfo &info, StringRef &osVersion, +// 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()); +  return llvm::StringSwitch<llvm::COFF::WindowsSubsystem>(arg) +      .Case("windows", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI) +      .Case("console", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI) +      .Default(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN); +} + +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)) diff --git a/lld/lib/Driver/WinLinkOptions.td b/lld/lib/Driver/WinLinkOptions.td index c32ae56cbe6..850814ae6f6 100644 --- a/lld/lib/Driver/WinLinkOptions.td +++ b/lld/lib/Driver/WinLinkOptions.td @@ -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>; diff --git a/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp b/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp index 516479e65d5..a4c3e7ec4ab 100644 --- a/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp +++ b/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp @@ -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; diff --git a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp index af54e275f45..f8e4ae9f13d 100644 --- a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp @@ -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; diff --git a/lld/unittests/DriverTests/WinLinkDriverTest.cpp b/lld/unittests/DriverTests/WinLinkDriverTest.cpp index 0f85a867be4..fc05e42c924 100644 --- a/lld/unittests/DriverTests/WinLinkDriverTest.cpp +++ b/lld/unittests/DriverTests/WinLinkDriverTest.cpp @@ -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 | 

