-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[lld][COFF][LTO] Implement /lldemit:llvm option #66964
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-lld-coff @llvm/pr-subscribers-lld-elf ChangesWith this new option, bitcode will be emited instead of object code. This is analogous to the Full diff: https://github.com/llvm/llvm-project/pull/66964.diff 8 Files Affected:
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
+}
|
1cbb665
to
696eb4f
Compare
696eb4f
to
5151c02
Compare
I think the first commit looks good to go at this point; do you want to make a separate PR for that, that we can approve right away? |
I lean on to what Martin says, I am not super excited about re-using |
I sure don't mind changing the flag to whatever is the best fit. I can wait for a second opinion from @rnk , and we can debate about the spelling all we want :) |
5151c02
to
b5e750e
Compare
I think Another option is to have an |
maybe |
b5e750e
to
4c14e86
Compare
I have updated the MR (and subsequent emitasm one) to use a standalone flag. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
4c14e86
to
7e5bb36
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the new name, thanks for the update.
My build is failing with this change. |
Can you confirm this patch would help you?
|
Yes, the above cmake fix corrected my build fail. I look forward to your merge of the above cmake fix. Thank you. |
It's done, thanks! |
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.