[lld] 964ef8e - [lld] Support --lto-emit-asm and --plugin-opt=emit-asm
Hongtao Yu via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 27 11:00:52 PDT 2020
Author: Hongtao Yu
Date: 2020-04-27T11:00:46-07:00
New Revision: 964ef8eecc98a881489c9bdd51db25dc74f301d0
URL: https://github.com/llvm/llvm-project/commit/964ef8eecc98a881489c9bdd51db25dc74f301d0
DIFF: https://github.com/llvm/llvm-project/commit/964ef8eecc98a881489c9bdd51db25dc74f301d0.diff
LOG: [lld] Support --lto-emit-asm and --plugin-opt=emit-asm
Summary: The switch --plugin-opt=emit-asm can be used with the gold linker to dump the final assembly code generated by LTO in a user-friendly way. Unfortunately it doesn't work with lld. I'm hooking it up with lld. With that switch, lld emits assembly code into the output file (specified by -o) and if there are multiple input files, each of their assembly code will be emitted into a separate file named by suffixing the output file name with a unique number, respectively. The linking then stops after generating those assembly files.
Reviewers: espindola, wenlei, tejohnson, MaskRay, grimar
Reviewed By: tejohnson, MaskRay, grimar
Subscribers: pcc, emaste, inglorion, arichardson, hiraditya, MaskRay, steven_wu, dexonsmith, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D77231
Added:
lld/test/ELF/lto/emit-asm.ll
Modified:
lld/ELF/Config.h
lld/ELF/Driver.cpp
lld/ELF/LTO.cpp
lld/ELF/Options.td
Removed:
################################################################################
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index e01a16b81023..cf2c70c4b99a 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -166,6 +166,7 @@ struct Configuration {
bool ignoreFunctionAddressEquality;
bool ltoCSProfileGenerate;
bool ltoDebugPassManager;
+ bool ltoEmitAsm;
bool ltoNewPassManager;
bool ltoUniqueBBSectionNames;
bool ltoWholeProgramVisibility;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index a5b117913356..12f704d75dfb 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -917,6 +917,7 @@ static void readConfigs(opt::InputArgList &args) {
config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate);
config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file);
config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
+ config->ltoEmitAsm = args.hasArg(OPT_lto_emit_asm);
config->ltoNewPassManager = args.hasArg(OPT_lto_new_pass_manager);
config->ltoNewPmPasses = args.getLastArgValue(OPT_lto_newpm_passes);
config->ltoWholeProgramVisibility =
@@ -1949,13 +1950,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
// 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)
- 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)
+ // Likewise, --plugin-opt=emit-llvm and --plugin-opt=emit-asm are the
+ // options to create output files in bitcode or assembly code
+ // repsectively. No object files are generated.
+ if (config->thinLTOIndexOnly || config->emitLLVM || config->ltoEmitAsm)
return;
// Apply symbol renames for -wrap.
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index d09f2a74e48c..7f3aca5e90f0 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -153,6 +153,9 @@ static lto::Config createConfig() {
};
}
+ if (config->ltoEmitAsm)
+ c.CGFileType = CGFT_AssemblyFile;
+
if (config->saveTemps)
checkError(c.addSaveTemps(config->outputFile.str() + ".",
/*UseInputModulePath*/ true));
@@ -329,6 +332,13 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o");
}
+ if (config->ltoEmitAsm) {
+ saveBuffer(buf[0], config->outputFile);
+ for (unsigned i = 1; i != maxTasks; ++i)
+ saveBuffer(buf[i], config->outputFile + Twine(i));
+ return {};
+ }
+
std::vector<InputFile *> ret;
for (unsigned i = 0; i != maxTasks; ++i)
if (!buf[i].empty())
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 799707af49fa..ad4e489f7f90 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -483,6 +483,8 @@ def lto_aa_pipeline: J<"lto-aa-pipeline=">,
HelpText<"AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes">;
def lto_debug_pass_manager: F<"lto-debug-pass-manager">,
HelpText<"Debug new pass manager">;
+def lto_emit_asm: F<"lto-emit-asm">,
+ HelpText<"Emit assembly code">;
def lto_new_pass_manager: F<"lto-new-pass-manager">,
HelpText<"Use new pass manager">;
def lto_newpm_passes: J<"lto-newpm-passes=">,
@@ -535,6 +537,8 @@ 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_asm: F<"plugin-opt=emit-asm">,
+ Alias<lto_emit_asm>, HelpText<"Alias for --lto-emit-asm">;
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">;
diff --git a/lld/test/ELF/lto/emit-asm.ll b/lld/test/ELF/lto/emit-asm.ll
new file mode 100644
index 000000000000..d0719411a5ba
--- /dev/null
+++ b/lld/test/ELF/lto/emit-asm.ll
@@ -0,0 +1,24 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld --lto-emit-asm -shared %t.o -o - | FileCheck %s
+; RUN: ld.lld --plugin-opt=emit-asm --plugin-opt=lto-partitions=2 -shared %t.o -o %t2.s
+; RUN: cat %t2.s %t2.s1 | FileCheck %s
+
+; RUN: ld.lld --lto-emit-asm --save-temps -shared %t.o -o %t3.s
+; RUN: FileCheck --input-file %t3.s %s
+; RUN: llvm-dis %t3.s.0.4.opt.bc -o - | FileCheck --check-prefix=OPT %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK-DAG: f1:
+; OPT-DAG: define void @f1()
+define void @f1() {
+ ret void
+}
+
+; CHECK-DAG: f2:
+; OPT-DAG: define void @f2()
+define void @f2() {
+ ret void
+}
More information about the llvm-commits
mailing list