Files
revng-revng/lib/Model/SerializeModelPass.cpp
T
Pietro Fezzardi c050dcb621 Handle missing model in SerializeModelPass
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.
2021-10-21 15:02:01 +02:00

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();
}