summaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2018-12-14 21:58:49 +0000
committerRui Ueyama <ruiu@google.com>2018-12-14 21:58:49 +0000
commit36c0f28ca05e9f8f7c76f5812548eef14acc78a7 (patch)
treed5083a1d78a22506cd77d6e5bf6d1ca36474f999 /lld
parentd9d4702b5936a5865be351c122344ab0ebfb3487 (diff)
Add --plugin-opt=emit-llvm option.
`--plugin-opt=emit-llvm` is an option for LTO. It makes the linker to combine all bitcode files and write the result to an output file without doing codegen. Gold LTO plugin has this option. This option is being used for some post-link code analysis tools that have to see a whole program but don't need to see them in the native machine code. Differential Revision: https://reviews.llvm.org/D55717
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
+}