[lld] r182988 - [WinLink][Driver] Add support for -subsystem optional OS version number.

Rui Ueyama ruiu at google.com
Thu May 30 23:30:10 PDT 2013


Author: ruiu
Date: Fri May 31 01:30:10 2013
New Revision: 182988

URL: http://llvm.org/viewvc/llvm-project?rev=182988&view=rev
Log:
[WinLink][Driver] Add support for -subsystem optional OS version number.

Modified:
    lld/trunk/include/lld/ReaderWriter/PECOFFTargetInfo.h
    lld/trunk/lib/Driver/WinLinkDriver.cpp
    lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp

Modified: lld/trunk/include/lld/ReaderWriter/PECOFFTargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFTargetInfo.h?rev=182988&r1=182987&r2=182988&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/PECOFFTargetInfo.h (original)
+++ lld/trunk/include/lld/ReaderWriter/PECOFFTargetInfo.h Fri May 31 01:30:10 2013
@@ -21,7 +21,9 @@ namespace lld {
 
 class PECOFFTargetInfo : public TargetInfo {
 public:
-  PECOFFTargetInfo() : _subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN) {}
+  PECOFFTargetInfo()
+      : _subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN),
+        _minOSVersion(6, 0) {}
 
   virtual error_code parseFile(
       std::unique_ptr<MemoryBuffer> &mb,
@@ -43,8 +45,23 @@ public:
   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;
+  }
+
 private:
   llvm::COFF::WindowsSubsystem _subsystem;
+  OSVersion _minOSVersion;
 
   mutable std::unique_ptr<Reader> _reader;
   mutable std::unique_ptr<Writer> _writer;

Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=182988&r1=182987&r2=182988&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Fri May 31 01:30:10 2013
@@ -13,6 +13,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include <cstdlib>
+
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/Option.h"
@@ -64,15 +66,66 @@ int findDoubleDash(int argc, const char
   return -1;
 }
 
-// Parses -subsystem command line option.
-llvm::COFF::WindowsSubsystem strToWinSubsystem(std::string str) {
-  std::string arg(StringRef(str).lower());
+// 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) {
+  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,
+                       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))
+    return false;
+  if (!checkOSVersion(minorVersion, "invalid OS minor version: ", diagnostics))
+    return false;
+  PECOFFTargetInfo::OSVersion minOSVersion(atoi(majorVersion.str().c_str()),
+                                           atoi(minorVersion.str().c_str()));
+  info.setMinOSVersion(minOSVersion);
+  return true;
+}
+
+// Parse -subsystem command line option. The form of -subsystem is
+// "subsystem_name[,majorOSVersion[,minorOSVersion]]".
+bool parseSubsystemOption(PECOFFTargetInfo &info, std::string arg,
+                          raw_ostream &diagnostics) {
+  StringRef subsystemStr, osVersionStr;
+  llvm::tie(subsystemStr, osVersionStr) = StringRef(arg).split(',');
+
+  // Parse optional OS version if exists.
+  if (!osVersionStr.empty())
+    if (!parseMinOSVersion(info, osVersionStr, diagnostics))
+      return false;
+
+  // Parse subsystem name.
+  llvm::COFF::WindowsSubsystem subsystem = stringToWinSubsystem(subsystemStr);
+  if (subsystem == llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN) {
+    diagnostics << "error: unknown subsystem name: " << subsystemStr << "\n";
+    return false;
+  }
+  info.setSubsystem(subsystem);
+  return true;
+}
+
 // Add ".obj" extension if the given path name has no file extension.
 std::string canonicalizeInputFileName(std::string path) {
   if (llvm::sys::path::extension(path).empty())
@@ -143,15 +196,9 @@ bool WinLinkDriver::parse(int argc, cons
   }
 
   // Handle -subsystem
-  if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_subsystem)) {
-    llvm::COFF::WindowsSubsystem subsystem = strToWinSubsystem(arg->getValue());
-    if (subsystem == llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN) {
-      diagnostics << "error: unknown subsystem name: "
-                  << arg->getValue() << "\n";
+  if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_subsystem))
+    if (!parseSubsystemOption(info, arg->getValue(), diagnostics))
       return true;
-    }
-    info.setSubsystem(subsystem);
-  }
 
   // Hanlde -out
   if (llvm::opt::Arg *outpath = parsedArgs->getLastArg(OPT_out))

Modified: lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=182988&r1=182987&r2=182988&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp Fri May 31 01:30:10 2013
@@ -41,6 +41,8 @@ TEST_F(WinLinkParserTest, Basic) {
   EXPECT_EQ("a.obj", inputFiles[0]);
   EXPECT_EQ("b.obj", inputFiles[1]);
   EXPECT_EQ("c.obj", inputFiles[2]);
+  EXPECT_EQ(6, info->getMinOSVersion().majorVersion);
+  EXPECT_EQ(0, info->getMinOSVersion().minorVersion);
 }
 
 TEST_F(WinLinkParserTest, WindowsStyleOption) {
@@ -66,4 +68,18 @@ TEST_F(WinLinkParserTest, NonStandardFil
   EXPECT_EQ("foo.o", inputFiles[0]);
 }
 
+TEST_F(WinLinkParserTest, MinMajorOSVersion) {
+  parse("link.exe", "-subsystem", "windows,3", "foo.o", nullptr);
+  EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, info->getSubsystem());
+  EXPECT_EQ(3, info->getMinOSVersion().majorVersion);
+  EXPECT_EQ(0, info->getMinOSVersion().minorVersion);
+}
+
+TEST_F(WinLinkParserTest, MinMajorMinorOSVersion) {
+  parse("link.exe", "-subsystem", "windows,3.1", "foo.o", nullptr);
+  EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, info->getSubsystem());
+  EXPECT_EQ(3, info->getMinOSVersion().majorVersion);
+  EXPECT_EQ(1, info->getMinOSVersion().minorVersion);
+}
+
 }  // end anonymous namespace





More information about the llvm-commits mailing list