[lld] [lld][MachO] Add --lto-emit-llvm command line option (PR #170355)

via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 2 11:37:49 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld-macho

Author: Tarun Prabhu (tarunprabhu)

<details>
<summary>Changes</summary>

This option will cause the linker to emit LLVM bitcode instead of an object file. The implementation is similar to that of the corresponding option in the ELF backend. This only works with LLD and will not work the gold plugin.

---
Full diff: https://github.com/llvm/llvm-project/pull/170355.diff


5 Files Affected:

- (modified) lld/MachO/Config.h (+1) 
- (modified) lld/MachO/Driver.cpp (+5-4) 
- (modified) lld/MachO/LTO.cpp (+10) 
- (modified) lld/MachO/Options.td (+2) 
- (added) lld/test/MachO/lto-emit-llvm.ll (+18) 


``````````diff
diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index a2ca5770bf952..bacfaa241f69b 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -216,6 +216,7 @@ struct Configuration {
   std::vector<SectionAlign> sectionAlignments;
   std::vector<SegmentProtection> segmentProtections;
   bool ltoDebugPassManager = false;
+  bool emitLLVM = false;
   llvm::StringRef codegenDataGeneratePath;
   bool csProfileGenerate = false;
   llvm::StringRef csProfilePath;
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 28c817c54c85d..94dbbf04a56f1 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -1999,6 +1999,7 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
     config->ignoreAutoLinkOptions.insert(arg->getValue());
   config->strictAutoLink = args.hasArg(OPT_strict_auto_link);
   config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
+  config->emitLLVM = args.hasArg(OPT_lto_emit_llvm);
   config->codegenDataGeneratePath =
       args.getLastArgValue(OPT_codegen_data_generate_path);
   config->csProfileGenerate = args.hasArg(OPT_cs_profile_generate);
@@ -2344,10 +2345,10 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
 
     resolveLCLinkerOptions();
 
-    // If --thinlto-index-only is given, we should create only "index
-    // files" and not object files. Index file creation is already done
-    // in compileBitcodeFiles, so we are done if that's the case.
-    if (config->thinLTOIndexOnly)
+    // If either --thinlto-index-only or --lto-emit-llvm is given, we should
+    // not create object files. Index file creation is already done in
+    // compileBitcodeFiles, so we are done if that's the case.
+    if (config->thinLTOIndexOnly || config->emitLLVM)
       return errorCount() == 0;
 
     // LTO may emit a non-hidden (extern) object file symbol even if the
diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp
index 4695b639dcc96..2c360374ef3cc 100644
--- a/lld/MachO/LTO.cpp
+++ b/lld/MachO/LTO.cpp
@@ -64,6 +64,16 @@ static lto::Config createConfig() {
   if (config->saveTemps)
     checkError(c.addSaveTemps(config->outputFile.str() + ".",
                               /*UseInputModulePath=*/true));
+
+  if (config->emitLLVM) {
+    llvm::StringRef outputFile = config->outputFile;
+    c.PreCodeGenModuleHook = [outputFile](size_t task, const Module &m) {
+      if (std::unique_ptr<raw_fd_ostream> os = openLTOOutputFile(outputFile))
+        WriteBitcodeToFile(m, *os, false);
+      return false;
+    };
+  }
+
   return c;
 }
 
diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index be1a1cc2963d9..15491e7d42fd2 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -188,6 +188,8 @@ def lto_debug_pass_manager: Flag<["--"], "lto-debug-pass-manager">,
     HelpText<"Debug new pass manager">, Group<grp_lld>;
 def lto_newpm_passes: Joined<["--"], "lto-newpm-passes=">,
     HelpText<"Passes to run during LTO">, Group<grp_lld>;
+def lto_emit_llvm: Flag<["--"], "lto-emit-llvm">,
+    HelpText<"Emit LLVM-IR bitcode">;
 def load_pass_plugins : Separate<["--"], "load-pass-plugin">, Group<grp_lld>;
 def load_pass_plugins_eq : Joined<["--"], "load-pass-plugin=">,
     Alias<!cast<Separate>(load_pass_plugins)>,
diff --git a/lld/test/MachO/lto-emit-llvm.ll b/lld/test/MachO/lto-emit-llvm.ll
new file mode 100644
index 0000000000000..77bf700837dfb
--- /dev/null
+++ b/lld/test/MachO/lto-emit-llvm.ll
@@ -0,0 +1,18 @@
+; REQUIRES: x86
+;
+; Check that the --lto-emit-llvm option is handled correctly.
+;
+; RUN: opt %s -o %t.o
+; RUN: ld.lld --lto-emit-llvm %t.o -o %t.out.o
+; RUN: llvm-dis < %t.out.o -o - | FileCheck %s
+;
+; CHECK: define hidden void @main()
+
+target triple = "x86_64-apple-darwin"
+target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
+ at llvm.compiler.used = appending global [1 x ptr] [ptr @main], section "llvm.metadata"
+
+define hidden void @main() {
+  ret void
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/170355


More information about the llvm-commits mailing list