summaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
Diffstat (limited to 'lld')
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp7
-rw-r--r--lld/ELF/LTO.cpp8
-rw-r--r--lld/ELF/Options.td1
-rw-r--r--lld/test/ELF/lto/emit-llvm.ll14
5 files changed, 31 insertions, 0 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 37f713f1843..8fb760e592e 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -135,6 +135,7 @@ struct Configuration {
bool Demangle = true;
bool DisableVerify;
bool EhFrameHdr;
+ bool EmitLLVM;
bool EmitRelocs;
bool EnableNewDtags;
bool ExecuteOnly;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 37fab4c9642..a8582416732 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -776,6 +776,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->DynamicLinker = getDynamicLinker(Args);
Config->EhFrameHdr =
Args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false);
+ Config->EmitLLVM = Args.hasArg(OPT_plugin_opt_emit_llvm, false);
Config->EmitRelocs = Args.hasArg(OPT_emit_relocs);
Config->CallGraphProfileSort = Args.hasFlag(
OPT_call_graph_profile_sort, OPT_no_call_graph_profile_sort, true);
@@ -1581,6 +1582,12 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
if (Config->ThinLTOIndexOnly)
return;
+ // Likewise, --plugin-opt=emit-llvm is an option to make LTO create
+ // an output file in bitcode and exit, so that you can just get a
+ // combined bitcode file.
+ if (Config->EmitLLVM)
+ return;
+
// Apply symbol renames for -wrap.
if (!Wrapped.empty())
wrapSymbols<ELFT>(Wrapped);
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index c3e59b5b71e..ca44581780e 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -103,6 +103,14 @@ static lto::Config createConfig() {
C.DebugPassManager = Config->LTODebugPassManager;
C.DwoDir = Config->DwoDir;
+ if (Config->EmitLLVM) {
+ C.PostInternalizeModuleHook = [](size_t Task, const Module &M) {
+ if (std::unique_ptr<raw_fd_ostream> OS = openFile(Config->OutputFile))
+ WriteBitcodeToFile(M, *OS, false);
+ return false;
+ };
+ }
+
if (Config->SaveTemps)
checkError(C.addSaveTemps(Config->OutputFile.str() + ".",
/*UseInputModulePath*/ true));
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 27cbade418a..e43a21b923d 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -458,6 +458,7 @@ def: F<"plugin-opt=debug-pass-manager">,
def: F<"plugin-opt=disable-verify">, Alias<disable_verify>, HelpText<"Alias for -disable-verify">;
def plugin_opt_dwo_dir_eq: J<"plugin-opt=dwo_dir=">,
HelpText<"Directory to store .dwo files when LTO and debug fission are used">;
+def plugin_opt_emit_llvm: F<"plugin-opt=emit-llvm">;
def: J<"plugin-opt=jobs=">, Alias<thinlto_jobs>, HelpText<"Alias for -thinlto-jobs">;
def: J<"plugin-opt=lto-partitions=">, Alias<lto_partitions>, HelpText<"Alias for -lto-partitions">;
def plugin_opt_mcpu_eq: J<"plugin-opt=mcpu=">;
diff --git a/lld/test/ELF/lto/emit-llvm.ll b/lld/test/ELF/lto/emit-llvm.ll
new file mode 100644
index 00000000000..bf38c982f02
--- /dev/null
+++ b/lld/test/ELF/lto/emit-llvm.ll
@@ -0,0 +1,14 @@
+; REQUIRES: x86
+
+; RUN: opt -module-hash -module-summary %s -o %t.o
+; RUN: ld.lld --plugin-opt=emit-llvm -o %t.out.o %t.o
+; RUN: llvm-dis < %t.out.o -o - | FileCheck %s
+
+; CHECK: define internal void @main()
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @main() {
+ ret void
+}