[lld] [lld][COFF][LTO] Implement /opt:emitllvm option (PR #66964)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 20 17:27:51 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld-elf

<details>
<summary>Changes</summary>

With this new option, bitcode will be emited instead of object code. This is analogous to the `--plugin-opt=emit-llvm` option in the ELF linker.

---
Full diff: https://github.com/llvm/llvm-project/pull/66964.diff


8 Files Affected:

- (modified) lld/COFF/Config.h (+1) 
- (modified) lld/COFF/Driver.cpp (+5-2) 
- (modified) lld/COFF/LTO.cpp (+10-12) 
- (modified) lld/Common/Filesystem.cpp (+27-1) 
- (modified) lld/ELF/LTO.cpp (+1-26) 
- (modified) lld/MachO/LTO.cpp (+1-13) 
- (modified) lld/include/lld/Common/Filesystem.h (+4) 
- (added) lld/test/COFF/lto-emit-llvm.ll (+14) 


``````````diff
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 4ade2c953c73e40..ee6829c3d225017 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -311,6 +311,7 @@ struct Configuration {
   bool pseudoRelocs = false;
   bool stdcallFixup = false;
   bool writeCheckSum = false;
+  bool emitLLVM = false;
 };
 
 } // namespace lld::coff
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index d7476e91e03e384..8b3bfb4bed3cdb8 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -1822,6 +1822,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
         ltoDebugPM = true;
       } else if (s == "noltodebugpassmanager") {
         ltoDebugPM = false;
+      } else if (s == "emitllvm") {
+        config->emitLLVM = true;
       } else if (s.consume_front("lldlto=")) {
         if (s.getAsInteger(10, config->ltoo) || config->ltoo > 3)
           error("/opt:lldlto: invalid optimization level: " + s);
@@ -2101,7 +2103,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // Handle /RELEASE
   if (args.hasArg(OPT_release))
     config->writeCheckSum = true;
-  
+
   // Handle /safeseh, x86 only, on by default, except for mingw.
   if (config->machine == I386) {
     config->safeSEH = args.hasFlag(OPT_safeseh, OPT_safeseh_no, !config->mingw);
@@ -2393,7 +2395,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // If -thinlto-index-only is given, we should create only "index
   // files" and not object files. Index file creation is already done
   // in addCombinedLTOObject, so we are done if that's the case.
-  if (config->thinLTOIndexOnly)
+  // Likewise, for /emitllvm we only emit bitcode.
+  if (config->emitLLVM || config->thinLTOIndexOnly)
     return;
 
   // If we generated native object files from bitcode files, this resolves
diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp
index c185da5370fa3dd..ee9cae0852d5345 100644
--- a/lld/COFF/LTO.cpp
+++ b/lld/COFF/LTO.cpp
@@ -13,6 +13,7 @@
 #include "Symbols.h"
 #include "lld/Common/Args.h"
 #include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/Filesystem.h"
 #include "lld/Common/Strings.h"
 #include "lld/Common/TargetOptionsCommandFlags.h"
 #include "llvm/ADT/STLExtras.h"
@@ -42,18 +43,6 @@ using namespace llvm::object;
 using namespace lld;
 using namespace lld::coff;
 
-// Creates an empty file to and returns a raw_fd_ostream to write to it.
-static std::unique_ptr<raw_fd_ostream> openFile(StringRef file) {
-  std::error_code ec;
-  auto ret =
-      std::make_unique<raw_fd_ostream>(file, ec, sys::fs::OpenFlags::OF_None);
-  if (ec) {
-    error("cannot open " + file + ": " + ec.message());
-    return nullptr;
-  }
-  return ret;
-}
-
 std::string BitcodeCompiler::getThinLTOOutputFile(StringRef path) {
   return lto::getThinLTOOutputFile(path, ctx.config.thinLTOPrefixReplaceOld,
                                    ctx.config.thinLTOPrefixReplaceNew);
@@ -98,6 +87,15 @@ lto::Config BitcodeCompiler::createConfig() {
   c.RunCSIRInstr = ctx.config.ltoCSProfileGenerate;
   c.PGOWarnMismatch = ctx.config.ltoPGOWarnMismatch;
 
+  if (ctx.config.emitLLVM) {
+    c.PostInternalizeModuleHook = [this](size_t task, const Module &m) {
+      if (std::unique_ptr<raw_fd_ostream> os =
+              openLTOOutputFile(ctx.config.outputFile))
+        WriteBitcodeToFile(m, *os, false);
+      return false;
+    };
+  }
+
   if (ctx.config.saveTemps)
     checkError(c.addSaveTemps(std::string(ctx.config.outputFile) + ".",
                               /*UseInputModulePath*/ true));
diff --git a/lld/Common/Filesystem.cpp b/lld/Common/Filesystem.cpp
index 671b352a3f6bc8f..1fc19ef02788603 100644
--- a/lld/Common/Filesystem.cpp
+++ b/lld/Common/Filesystem.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lld/Common/Filesystem.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/FileSystem.h"
@@ -57,7 +58,7 @@ void lld::unlinkAsync(StringRef path) {
   //
   // The code here allows LLD to work on all versions of Windows.
   // However, at Windows 10 1903 it seems that the behavior of
-  // Windows has changed, so that we could simply delete the output 
+  // Windows has changed, so that we could simply delete the output
   // file. This code should be simplified once support for older
   // versions of Windows is dropped.
   //
@@ -127,3 +128,28 @@ std::error_code lld::tryCreateFile(StringRef path) {
     return std::error_code();
   return errorToErrorCode(FileOutputBuffer::create(path, 1).takeError());
 }
+
+// Creates an empty file to and returns a raw_fd_ostream to write to it.
+std::unique_ptr<raw_fd_ostream> lld::openFile(StringRef file) {
+  std::error_code ec;
+  auto ret =
+      std::make_unique<raw_fd_ostream>(file, ec, sys::fs::OpenFlags::OF_None);
+  if (ec) {
+    error("cannot open " + file + ": " + ec.message());
+    return nullptr;
+  }
+  return ret;
+}
+
+// The merged bitcode after LTO is large. Try opening a file stream that
+// supports reading, seeking and writing. Such a file allows BitcodeWriter to
+// flush buffered data to reduce memory consumption. If this fails, open a file
+// stream that supports only write.
+std::unique_ptr<raw_fd_ostream> lld::openLTOOutputFile(StringRef file) {
+  std::error_code ec;
+  std::unique_ptr<raw_fd_ostream> fs =
+      std::make_unique<raw_fd_stream>(file, ec);
+  if (!ec)
+    return fs;
+  return openFile(file);
+}
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index eb8f8d7f829a6f0..0f6a9aa8af1d050 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -13,6 +13,7 @@
 #include "Symbols.h"
 #include "lld/Common/Args.h"
 #include "lld/Common/ErrorHandler.h"
+#include "lld/Common/FileSystem.h"
 #include "lld/Common/Strings.h"
 #include "lld/Common/TargetOptionsCommandFlags.h"
 #include "llvm/ADT/SmallString.h"
@@ -40,32 +41,6 @@ using namespace llvm::ELF;
 using namespace lld;
 using namespace lld::elf;
 
-// Creates an empty file to store a list of object files for final
-// linking of distributed ThinLTO.
-static std::unique_ptr<raw_fd_ostream> openFile(StringRef file) {
-  std::error_code ec;
-  auto ret =
-      std::make_unique<raw_fd_ostream>(file, ec, sys::fs::OpenFlags::OF_None);
-  if (ec) {
-    error("cannot open " + file + ": " + ec.message());
-    return nullptr;
-  }
-  return ret;
-}
-
-// The merged bitcode after LTO is large. Try opening a file stream that
-// supports reading, seeking and writing. Such a file allows BitcodeWriter to
-// flush buffered data to reduce memory consumption. If this fails, open a file
-// stream that supports only write.
-static std::unique_ptr<raw_fd_ostream> openLTOOutputFile(StringRef file) {
-  std::error_code ec;
-  std::unique_ptr<raw_fd_ostream> fs =
-      std::make_unique<raw_fd_stream>(file, ec);
-  if (!ec)
-    return fs;
-  return openFile(file);
-}
-
 static std::string getThinLTOOutputFile(StringRef modulePath) {
   return lto::getThinLTOOutputFile(modulePath, config->thinLTOPrefixReplaceOld,
                                    config->thinLTOPrefixReplaceNew);
diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp
index a5b0f4d3d2a746d..3077bd4a5dcec8f 100644
--- a/lld/MachO/LTO.cpp
+++ b/lld/MachO/LTO.cpp
@@ -15,6 +15,7 @@
 
 #include "lld/Common/Args.h"
 #include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/FileSystem.h"
 #include "lld/Common/Strings.h"
 #include "lld/Common/TargetOptionsCommandFlags.h"
 #include "llvm/Bitcode/BitcodeWriter.h"
@@ -32,19 +33,6 @@ using namespace llvm;
 using namespace llvm::MachO;
 using namespace llvm::sys;
 
-// Creates an empty file to store a list of object files for final
-// linking of distributed ThinLTO.
-static std::unique_ptr<raw_fd_ostream> openFile(StringRef file) {
-  std::error_code ec;
-  auto ret =
-      std::make_unique<raw_fd_ostream>(file, ec, sys::fs::OpenFlags::OF_None);
-  if (ec) {
-    error("cannot open " + file + ": " + ec.message());
-    return nullptr;
-  }
-  return ret;
-}
-
 static std::string getThinLTOOutputFile(StringRef modulePath) {
   return lto::getThinLTOOutputFile(modulePath, config->thinLTOPrefixReplaceOld,
                                    config->thinLTOPrefixReplaceNew);
diff --git a/lld/include/lld/Common/Filesystem.h b/lld/include/lld/Common/Filesystem.h
index 63a0f554a06c57f..61b32eec2ee7d7d 100644
--- a/lld/include/lld/Common/Filesystem.h
+++ b/lld/include/lld/Common/Filesystem.h
@@ -10,11 +10,15 @@
 #define LLD_FILESYSTEM_H
 
 #include "lld/Common/LLVM.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
 #include <system_error>
 
 namespace lld {
 void unlinkAsync(StringRef path);
 std::error_code tryCreateFile(StringRef path);
+std::unique_ptr<llvm::raw_fd_ostream> openFile(StringRef file);
+std::unique_ptr<llvm::raw_fd_ostream> openLTOOutputFile(StringRef file);
 } // namespace lld
 
 #endif
diff --git a/lld/test/COFF/lto-emit-llvm.ll b/lld/test/COFF/lto-emit-llvm.ll
new file mode 100644
index 000000000000000..d7ab61d043a0099
--- /dev/null
+++ b/lld/test/COFF/lto-emit-llvm.ll
@@ -0,0 +1,14 @@
+; REQUIRES: x86
+; RUN: llvm-as -o %T/lto.obj %s
+
+; RUN: lld-link /opt:emitllvm /out:%T/lto.bc /entry:main /subsystem:console %T/lto.obj
+; RUN: llvm-dis %T/lto.bc -o - | FileCheck %s
+
+; CHECK: define void @main()
+
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define void @main() {
+  ret void
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/66964


More information about the llvm-commits mailing list