mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
c050dcb621
Before this commit, SerializeModelPass and SerializeModelWrapperPass had hard dependencies on the passes that load the model from LLVM-IR. This commit makes this dependency optional. When the passes for model serialization are executed, if they see that nobody requested to load the model, they will not try to serialize it. This prevents them from crashing when running in pipelines that only contain passes that ignore the model. This is particularly beneficial because `revng opt` automatically adds `-serialize-model` at the end of each pipeline and, before this commit, this meant that `revng opt` could not be used for unit-testing simple llvm passes that do not use the model. With this commit, `revng opt` can be used for unit-tests, even on LLVM IR with missing model.
62 lines
1.6 KiB
C++
62 lines
1.6 KiB
C++
/// \file SerializeModelPass.cpp
|
|
/// \brief Implementation of the pass taking care of serializing the
|
|
/// model in the Module as Metadata.
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
// LLVM includes
|
|
#include "llvm/IR/Metadata.h"
|
|
#include "llvm/IR/Module.h"
|
|
|
|
// Local libraries includes
|
|
#include "revng/Model/SerializeModelPass.h"
|
|
|
|
using namespace llvm;
|
|
|
|
char SerializeModelWrapperPass::ID;
|
|
|
|
template<typename T>
|
|
using RP = RegisterPass<T>;
|
|
|
|
static RP<SerializeModelWrapperPass>
|
|
X("serialize-model", "Serialize the model", true, true);
|
|
|
|
void writeModel(model::Binary &Model, llvm::Module &M) {
|
|
|
|
NamedMDNode *NamedMD = M.getNamedMetadata(ModelMetadataName);
|
|
revng_check(not NamedMD, "The model has alread been serialized");
|
|
|
|
std::string Buffer;
|
|
{
|
|
llvm::raw_string_ostream Stream(Buffer);
|
|
serialize(Stream, Model);
|
|
}
|
|
|
|
LLVMContext &Context = M.getContext();
|
|
auto Tuple = MDTuple::get(Context, { MDString::get(Context, Buffer) });
|
|
|
|
NamedMD = M.getOrInsertNamedMetadata(ModelMetadataName);
|
|
NamedMD->addOperand(Tuple);
|
|
}
|
|
|
|
bool SerializeModelWrapperPass::runOnModule(Module &M) {
|
|
auto LoadPass = getAnalysisIfAvailable<LoadModelWrapperPass>();
|
|
if (not LoadPass)
|
|
return false;
|
|
|
|
writeModel(*LoadPass->get().getWriteableModel(), M);
|
|
return false;
|
|
}
|
|
|
|
llvm::PreservedAnalyses
|
|
SerializeModelPass::run(llvm::Module &M, llvm::ModuleAnalysisManager &MAM) {
|
|
auto *ModelWrapper = MAM.getCachedResult<LoadModelAnalysis>(M);
|
|
if (not ModelWrapper)
|
|
return PreservedAnalyses::all();
|
|
|
|
writeModel(*ModelWrapper->getWriteableModel(), M);
|
|
return PreservedAnalyses::all();
|
|
}
|