[pkg-d-commits] [ldc] 56/74: Refactor MSVC link.exe driver into dedicated driver/linker-msvc.cpp

Matthias Klumpp mak at moszumanska.debian.org
Thu Jul 13 20:54:18 UTC 2017


This is an automated email from the git hooks/post-receive script.

mak pushed a commit to annotated tag v1.3.0-beta2
in repository ldc.

commit cb0c27c3c565aa84419b5ee1ebf68abd55318ace
Author: Martin <noone at nowhere.com>
Date:   Fri May 26 23:57:21 2017 +0200

    Refactor MSVC link.exe driver into dedicated driver/linker-msvc.cpp
---
 CMakeLists.txt         |   1 +
 driver/linker-msvc.cpp | 166 ++++++++++++++++++++++++++++++++++++++++
 driver/linker.cpp      | 200 ++++++-------------------------------------------
 3 files changed, 191 insertions(+), 176 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 51bcc8c..abef9f8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -342,6 +342,7 @@ set(DRV_SRC
     driver/tool.cpp
     driver/archiver.cpp
     driver/linker.cpp
+    driver/linker-msvc.cpp
     driver/main.cpp
     ${CMAKE_BINARY_DIR}/driver/ldc-version.cpp
 )
diff --git a/driver/linker-msvc.cpp b/driver/linker-msvc.cpp
new file mode 100644
index 0000000..e51cb8a
--- /dev/null
+++ b/driver/linker-msvc.cpp
@@ -0,0 +1,166 @@
+//===-- linker-msvc.cpp ---------------------------------------------------===//
+//
+//                         LDC � the LLVM D compiler
+//
+// This file is distributed under the BSD-style LDC license. See the LICENSE
+// file for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "errors.h"
+#include "driver/cl_options.h"
+#include "driver/tool.h"
+#include "gen/logger.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+static llvm::cl::opt<std::string> mscrtlib(
+    "mscrtlib", llvm::cl::ZeroOrMore, llvm::cl::value_desc("name"),
+    llvm::cl::desc(
+        "MS C runtime library to link against (libcmt[d] / msvcrt[d])"));
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace {
+
+void addMscrtLibs(std::vector<std::string> &args,
+                  llvm::cl::boolOrDefault fullyStaticFlag) {
+  llvm::StringRef mscrtlibName = mscrtlib;
+  if (mscrtlibName.empty()) {
+    // default to static release variant
+    mscrtlibName = fullyStaticFlag != llvm::cl::BOU_FALSE ? "libcmt" : "msvcrt";
+  }
+
+  args.push_back(("/DEFAULTLIB:" + mscrtlibName).str());
+
+  const bool isStatic = mscrtlibName.startswith_lower("libcmt");
+  const bool isDebug =
+      mscrtlibName.endswith_lower("d") || mscrtlibName.endswith_lower("d.lib");
+
+  const llvm::StringRef prefix = isStatic ? "lib" : "";
+  const llvm::StringRef suffix = isDebug ? "d" : "";
+
+  args.push_back(("/DEFAULTLIB:" + prefix + "vcruntime" + suffix).str());
+}
+
+} // anonymous namespace
+
+//////////////////////////////////////////////////////////////////////////////
+
+int linkObjToBinaryMSVC(llvm::StringRef outputPath,
+                        llvm::cl::boolOrDefault fullyStaticFlag) {
+  if (!opts::ccSwitches.empty()) {
+    error(Loc(), "-Xcc is not supported for MSVC");
+    fatal();
+  }
+
+#ifdef _WIN32
+  windows::setupMsvcEnvironment();
+#endif
+
+  const std::string tool = "link.exe";
+
+  // build arguments
+  std::vector<std::string> args;
+
+  args.push_back("/NOLOGO");
+
+  // specify that the image will contain a table of safe exception handlers
+  // and can handle addresses >2GB (32bit only)
+  if (!global.params.is64bit) {
+    args.push_back("/SAFESEH");
+    args.push_back("/LARGEADDRESSAWARE");
+  }
+
+  // output debug information
+  if (global.params.symdebug) {
+    args.push_back("/DEBUG");
+  }
+
+  // remove dead code and fold identical COMDATs
+  if (opts::disableLinkerStripDead) {
+    args.push_back("/OPT:NOREF");
+  } else {
+    args.push_back("/OPT:REF");
+    args.push_back("/OPT:ICF");
+  }
+
+  // add C runtime libs
+  addMscrtLibs(args, fullyStaticFlag);
+
+  // specify creation of DLL
+  if (global.params.dll) {
+    args.push_back("/DLL");
+  }
+
+  args.push_back(("/OUT:" + outputPath).str());
+
+  // object files
+  for (unsigned i = 0; i < global.params.objfiles->dim; i++)
+    args.push_back((*global.params.objfiles)[i]);
+
+  // .res/.def files
+  if (global.params.resfile)
+    args.push_back(global.params.resfile);
+  if (global.params.deffile)
+    args.push_back(std::string("/DEF:") + global.params.deffile);
+
+  // Link with profile-rt library when generating an instrumented binary
+  // profile-rt depends on Phobos (MD5 hashing).
+  if (global.params.genInstrProf) {
+    args.push_back("ldc-profile-rt.lib");
+    // profile-rt depends on ws2_32 for symbol `gethostname`
+    args.push_back("ws2_32.lib");
+  }
+
+  // user libs
+  for (unsigned i = 0; i < global.params.libfiles->dim; i++)
+    args.push_back((*global.params.libfiles)[i]);
+
+  // additional linker switches
+  auto addSwitch = [&](std::string str) {
+    if (str.length() > 2) {
+      // rewrite common -L and -l switches
+      if (str[0] == '-' && str[1] == 'L') {
+        str = "/LIBPATH:" + str.substr(2);
+      } else if (str[0] == '-' && str[1] == 'l') {
+        str = str.substr(2) + ".lib";
+      }
+    }
+    args.push_back(str);
+  };
+
+  for (const auto &str : opts::linkerSwitches) {
+    addSwitch(str);
+  }
+
+  for (unsigned i = 0; i < global.params.linkswitches->dim; i++) {
+    addSwitch(global.params.linkswitches->data[i]);
+  }
+
+  // default libs
+  // TODO check which libaries are necessary
+  args.push_back("kernel32.lib");
+  args.push_back("user32.lib");
+  args.push_back("gdi32.lib");
+  args.push_back("winspool.lib");
+  args.push_back("shell32.lib"); // required for dmain2.d
+  args.push_back("ole32.lib");
+  args.push_back("oleaut32.lib");
+  args.push_back("uuid.lib");
+  args.push_back("comdlg32.lib");
+  args.push_back("advapi32.lib");
+
+  Logger::println("Linking with: ");
+  Stream logstr = Logger::cout();
+  for (const auto &arg : args) {
+    if (!arg.empty()) {
+      logstr << "'" << arg << "'"
+             << " ";
+    }
+  }
+  logstr << "\n"; // FIXME where's flush ?
+
+  // try to call linker
+  return executeToolAndWait(tool, args, global.params.verbose);
+}
diff --git a/driver/linker.cpp b/driver/linker.cpp
index d9fbafb..dc08f1c 100644
--- a/driver/linker.cpp
+++ b/driver/linker.cpp
@@ -38,11 +38,6 @@ static llvm::cl::opt<bool>
                llvm::cl::desc("Create a statically linked binary, including "
                               "all system dependencies"));
 
-static llvm::cl::opt<std::string> mscrtlib(
-    "mscrtlib", llvm::cl::ZeroOrMore, llvm::cl::value_desc("name"),
-    llvm::cl::desc(
-        "MS C runtime library to link against (libcmt[d] / msvcrt[d])"));
-
 static llvm::cl::opt<std::string>
     ltoLibrary("flto-binary", llvm::cl::ZeroOrMore,
                llvm::cl::desc("Set the linker LTO plugin library file (e.g. "
@@ -51,8 +46,9 @@ static llvm::cl::opt<std::string>
 
 //////////////////////////////////////////////////////////////////////////////
 
-static std::string getOutputName(bool const sharedLib) {
+static std::string getOutputName() {
   const auto &triple = *global.params.targetTriple;
+  const bool sharedLib = global.params.dll;
 
   const char *extension = nullptr;
   if (sharedLib) {
@@ -254,32 +250,17 @@ void insertBitcodeFiles(llvm::Module &M, llvm::LLVMContext &Ctx,
 
 //////////////////////////////////////////////////////////////////////////////
 
-static void appendObjectFiles(std::vector<std::string> &args) {
-  for (unsigned i = 0; i < global.params.objfiles->dim; i++)
-    args.push_back((*global.params.objfiles)[i]);
-
-  if (global.params.targetTriple->isWindowsMSVCEnvironment()) {
-    if (global.params.resfile)
-      args.push_back(global.params.resfile);
-    if (global.params.deffile)
-      args.push_back(std::string("/DEF:") + global.params.deffile);
-  }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static std::string gExePath;
-
-static int linkObjToBinaryGcc(bool sharedLib) {
-  Logger::println("*** Linking executable ***");
-
+static int linkObjToBinaryGcc(llvm::StringRef outputPath,
+                              llvm::cl::boolOrDefault fullyStaticFlag) {
   // find gcc for linking
   const std::string tool = getGcc();
 
   // build arguments
   std::vector<std::string> args;
 
-  appendObjectFiles(args);
+  // object files
+  for (unsigned i = 0; i < global.params.objfiles->dim; i++)
+    args.push_back((*global.params.objfiles)[i]);
 
   // Link with profile-rt library when generating an instrumented binary.
   // profile-rt uses Phobos (MD5 hashing) and therefore must be passed on the
@@ -300,26 +281,16 @@ static int linkObjToBinaryGcc(bool sharedLib) {
   for (unsigned i = 0; i < global.params.libfiles->dim; i++)
     args.push_back((*global.params.libfiles)[i]);
 
-  // output filename
-  std::string output = getOutputName(sharedLib);
-
-  if (sharedLib) {
+  if (global.params.dll) {
     args.push_back("-shared");
   }
 
-  if (staticFlag) {
+  if (fullyStaticFlag == llvm::cl::BOU_TRUE) {
     args.push_back("-static");
   }
 
   args.push_back("-o");
-  args.push_back(output);
-
-  // set the global gExePath
-  gExePath = output;
-  // assert(gExePath.isValid());
-
-  // create path to exe
-  createDirectoryForFileOrFail(gExePath);
+  args.push_back(outputPath);
 
   // Pass sanitizer arguments to linker. Requires clang.
   if (opts::sanitize == opts::AddressSanitizer) {
@@ -498,155 +469,33 @@ static int linkObjToBinaryGcc(bool sharedLib) {
 
 //////////////////////////////////////////////////////////////////////////////
 
-static void addMscrtLibs(std::vector<std::string> &args) {
-  llvm::StringRef mscrtlibName = mscrtlib;
-  if (mscrtlibName.empty()) {
-    // default to static release variant
-    mscrtlibName =
-        staticFlag || staticFlag.getNumOccurrences() == 0 ? "libcmt" : "msvcrt";
-  }
-
-  args.push_back(("/DEFAULTLIB:" + mscrtlibName).str());
-
-  const bool isStatic = mscrtlibName.startswith_lower("libcmt");
-  const bool isDebug =
-      mscrtlibName.endswith_lower("d") || mscrtlibName.endswith_lower("d.lib");
+// path to the produced executable/shared library
+static std::string gExePath;
 
-  const llvm::StringRef prefix = isStatic ? "lib" : "";
-  const llvm::StringRef suffix = isDebug ? "d" : "";
+//////////////////////////////////////////////////////////////////////////////
 
-  args.push_back(("/DEFAULTLIB:" + prefix + "vcruntime" + suffix).str());
-}
+// linker-msvc.cpp
+int linkObjToBinaryMSVC(llvm::StringRef outputPath,
+                        llvm::cl::boolOrDefault fullyStaticFlag);
 
-static int linkObjToBinaryMSVC(bool sharedLib) {
+int linkObjToBinary() {
   Logger::println("*** Linking executable ***");
 
-  if (!opts::ccSwitches.empty()) {
-    error(Loc(), "-Xcc is not supported for MSVC");
-    fatal();
-  }
-
-#ifdef _WIN32
-  windows::setupMsvcEnvironment();
-#endif
-
-  const std::string tool = "link.exe";
-
-  // build arguments
-  std::vector<std::string> args;
-
-  args.push_back("/NOLOGO");
-
-  // specify that the image will contain a table of safe exception handlers
-  // and can handle addresses >2GB (32bit only)
-  if (!global.params.is64bit) {
-    args.push_back("/SAFESEH");
-    args.push_back("/LARGEADDRESSAWARE");
-  }
-
-  // output debug information
-  if (global.params.symdebug) {
-    args.push_back("/DEBUG");
-  }
-
-  // remove dead code and fold identical COMDATs
-  if (opts::disableLinkerStripDead) {
-    args.push_back("/OPT:NOREF");
-  } else {
-    args.push_back("/OPT:REF");
-    args.push_back("/OPT:ICF");
-  }
-
-  // add C runtime libs
-  addMscrtLibs(args);
-
-  // specify creation of DLL
-  if (sharedLib) {
-    args.push_back("/DLL");
-  }
+  // remember output path for later
+  gExePath = getOutputName();
 
-  // output filename
-  std::string output = getOutputName(sharedLib);
-
-  args.push_back("/OUT:" + output);
-
-  appendObjectFiles(args);
-
-  // Link with profile-rt library when generating an instrumented binary
-  // profile-rt depends on Phobos (MD5 hashing).
-  if (global.params.genInstrProf) {
-    args.push_back("ldc-profile-rt.lib");
-    // profile-rt depends on ws2_32 for symbol `gethostname`
-    args.push_back("ws2_32.lib");
-  }
-
-  // user libs
-  for (unsigned i = 0; i < global.params.libfiles->dim; i++)
-    args.push_back((*global.params.libfiles)[i]);
-
-  // set the global gExePath
-  gExePath = output;
-  // assert(gExePath.isValid());
-
-  // create path to exe
   createDirectoryForFileOrFail(gExePath);
 
-  // additional linker switches
-  auto addSwitch = [&](std::string str) {
-    if (str.length() > 2) {
-      // rewrite common -L and -l switches
-      if (str[0] == '-' && str[1] == 'L') {
-        str = "/LIBPATH:" + str.substr(2);
-      } else if (str[0] == '-' && str[1] == 'l') {
-        str = str.substr(2) + ".lib";
-      }
-    }
-    args.push_back(str);
-  };
-
-  for (const auto &str : opts::linkerSwitches) {
-    addSwitch(str);
-  }
-
-  for (unsigned i = 0; i < global.params.linkswitches->dim; i++) {
-    addSwitch(global.params.linkswitches->data[i]);
+  llvm::cl::boolOrDefault fullyStaticFlag = llvm::cl::BOU_UNSET;
+  if (staticFlag.getNumOccurrences() != 0) {
+    fullyStaticFlag = staticFlag ? llvm::cl::BOU_TRUE : llvm::cl::BOU_FALSE;
   }
 
-  // default libs
-  // TODO check which libaries are necessary
-  args.push_back("kernel32.lib");
-  args.push_back("user32.lib");
-  args.push_back("gdi32.lib");
-  args.push_back("winspool.lib");
-  args.push_back("shell32.lib"); // required for dmain2.d
-  args.push_back("ole32.lib");
-  args.push_back("oleaut32.lib");
-  args.push_back("uuid.lib");
-  args.push_back("comdlg32.lib");
-  args.push_back("advapi32.lib");
-
-  Logger::println("Linking with: ");
-  Stream logstr = Logger::cout();
-  for (const auto &arg : args) {
-    if (!arg.empty()) {
-      logstr << "'" << arg << "'"
-             << " ";
-    }
-  }
-  logstr << "\n"; // FIXME where's flush ?
-
-  // try to call linker
-  return executeToolAndWait(tool, args, global.params.verbose);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-int linkObjToBinary() {
   if (global.params.targetTriple->isWindowsMSVCEnvironment()) {
-    return linkObjToBinaryMSVC(global.params.dll);
+    return linkObjToBinaryMSVC(gExePath, fullyStaticFlag);
   }
 
-  return linkObjToBinaryGcc(global.params.dll);
+  return linkObjToBinaryGcc(gExePath, fullyStaticFlag);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -661,7 +510,6 @@ void deleteExeFile() {
 
 int runProgram() {
   assert(!gExePath.empty());
-  // assert(gExePath.isValid());
 
   // Run executable
   int status =

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-d/ldc.git



More information about the pkg-d-commits mailing list