[llvm] [LTO] Fix a crash with thin LTO caching and asm output (PR #138203)

Teresa Johnson via llvm-commits llvm-commits at lists.llvm.org
Tue May 13 11:00:44 PDT 2025


================
@@ -439,27 +439,33 @@ static void codegen(const Config &Conf, TargetMachine *TM,
   std::unique_ptr<CachedFileStream> &Stream = *StreamOrErr;
   TM->Options.ObjectFilenameForDebug = Stream->ObjectPathName;
 
-  legacy::PassManager CodeGenPasses;
-  TargetLibraryInfoImpl TLII(Mod.getTargetTriple());
-  CodeGenPasses.add(new TargetLibraryInfoWrapperPass(TLII));
-  // No need to make index available if the module is empty.
-  // In theory these passes should not use the index for an empty
-  // module, however, this guards against doing any unnecessary summary-based
-  // analysis in the case of a ThinLTO build where this might be an empty
-  // regular LTO combined module, with a large combined index from ThinLTO.
-  if (!isEmptyModule(Mod))
-    CodeGenPasses.add(
-        createImmutableModuleSummaryIndexWrapperPass(&CombinedIndex));
-  if (Conf.PreCodeGenPassesHook)
-    Conf.PreCodeGenPassesHook(CodeGenPasses);
-  if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS,
-                              DwoOut ? &DwoOut->os() : nullptr,
-                              Conf.CGFileType))
-    report_fatal_error("Failed to setup codegen");
-  CodeGenPasses.run(Mod);
-
-  if (DwoOut)
-    DwoOut->keep();
+  // Create the LTO pipeline in its own scope so it gets deleted before
+  // Stream->commit() is called. The commit function of CacheFile deletes
----------------
teresajohnson wrote:

Ok I see the issue, which you described earlier but I didn't quite follow until poking around more. As you note there are 2 totally separate raw_ostream objects. The first which is owned by CacheFileStream is of derived type raw_fd_stream, and constructed when invoking the CacheStream (and base class CacheFileStream) constructor. The second is formatted_raw_ostream, which is also derived from raw_ostream but a different one, and it holds a pointer to the other raw_ostream object (via data member TheStream). The formatted_raw_ostream::write_impl calls write() on TheStream.

Presumably if CacheStream::commit was changed to invoke flush() instead, because formatted_raw_ostream has not yet been flushed (and therefore TheStream->write() hadn't been called yet on CacheStream's raw_ostream, we don't actually get the file written as expected by commit()?

This is unfortunately gnarly, and I agree that the only quick fixes are the one in this PR, reverting PR136121, or changing some APIs so that e.g. CacheStream owns the formatted_raw_ostream. My preference is to revert PR136121, as improved errors are nice but IMO not worth the introduced complexity. Most of the callers of the new commit() function still call report_fatal_error on the result, so I don't know that it has improved the situation significantly anyway?

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


More information about the llvm-commits mailing list