[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