llvm-project/llvm/lib/Transforms/IPO/EmbedBitcodePass.cpp
Paul Kirth 55c7d5cdad
[llvm][EmbedBitcodePass] Prevent modifying the module with ThinLTO (#139999)
Since ThinLTOBitcodeWriterPass handles many things for CFI and WPD, like
updating vtable linkage, we need to prevent those changes from
persisting in the non-LTO object code we will compile under FatLTO.

The only non-invasive way to do that is to clone the module when
serializing the module in ThinLTOBitcodeWriterPass. We may be able to
avoid cloning in the future with additional infrastructure to restore
the IR to its original state.

Fixes #139440
2025-05-29 13:42:48 -07:00

50 lines
1.8 KiB
C++

//===- EmbedBitcodePass.cpp - Pass that embeds the bitcode into a global---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/EmbedBitcodePass.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include <string>
using namespace llvm;
PreservedAnalyses EmbedBitcodePass::run(Module &M, ModuleAnalysisManager &AM) {
if (M.getGlobalVariable("llvm.embedded.module", /*AllowInternal=*/true))
reportFatalUsageError("Can only embed the module once");
Triple T(M.getTargetTriple());
if (T.getObjectFormat() != Triple::ELF)
reportFatalUsageError(
"EmbedBitcode pass currently only supports ELF object format");
std::string Data;
raw_string_ostream OS(Data);
// Clone the module with Thin LTO, since ThinLTOBitcodeWriterPass changes
// vtable linkage that would break the non-lto object code for FatLTO.
if (IsThinLTO)
ThinLTOBitcodeWriterPass(OS, /*ThinLinkOS=*/nullptr)
.run(*llvm::CloneModule(M), AM);
else
BitcodeWriterPass(OS, /*ShouldPreserveUseListOrder=*/false, EmitLTOSummary)
.run(M, AM);
embedBufferInModule(M, MemoryBufferRef(Data, "ModuleData"), ".llvm.lto");
return PreservedAnalyses::all();
}