Files
revng-revng/lib/Pipes/GlobalsAnalyses.cpp
Alessandro Di Federico 5820908675 Remove and ban \file
2025-12-16 17:41:55 +01:00

113 lines
3.7 KiB
C++

//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "llvm/Support/Error.h"
#include "revng/Pipeline/Context.h"
#include "revng/Pipeline/RegisterAnalysis.h"
#include "revng/Pipes/GlobalsAnalyses.h"
#include "revng/Pipes/ModelGlobal.h"
#include "revng/Support/YAMLTraits.h"
#include "revng/TupleTree/TupleTreeDiff.h"
namespace revng::pipes {
template<bool commit>
static llvm::Error applyDiffImpl(pipeline::ExecutionContext &EC,
std::string DiffGlobalName,
std::string DiffContent) {
if (DiffGlobalName.empty()) {
return revng::createError("global-name must be set");
}
std::unique_ptr<llvm::MemoryBuffer>
Buffer = llvm::MemoryBuffer::getMemBuffer(DiffContent);
auto GlobalOrError = EC.getContext().getGlobals().get(DiffGlobalName);
if (not GlobalOrError)
return GlobalOrError.takeError();
auto &Global = GlobalOrError.get();
auto MaybeDiff = Global->diffFromString(Buffer->getBuffer());
if (not MaybeDiff)
return MaybeDiff.takeError();
auto &Diff = MaybeDiff.get();
auto GlobalClone = Global->clone();
if (auto ApplyError = GlobalClone->applyDiff(Diff); ApplyError)
return ApplyError;
if (not GlobalClone->verify()) {
return revng::createError("could not verify %s", DiffGlobalName.c_str());
}
if constexpr (commit) {
*Global = *GlobalClone;
}
return llvm::Error::success();
}
llvm::Error ApplyDiffAnalysis::run(pipeline::ExecutionContext &EC,
std::string DiffGlobalName,
std::string DiffContent) {
return applyDiffImpl<true>(EC, DiffGlobalName, DiffContent);
}
llvm::Error VerifyDiffAnalysis::run(pipeline::ExecutionContext &EC,
std::string DiffGlobalName,
std::string DiffContent) {
return applyDiffImpl<false>(EC, DiffGlobalName, DiffContent);
}
template<bool commit>
inline llvm::Error setGlobalImpl(pipeline::ExecutionContext &EC,
std::string SetGlobalName,
std::string GlobalContent) {
if (SetGlobalName.empty()) {
return revng::createError("global-name must be set");
}
std::unique_ptr<llvm::MemoryBuffer>
Buffer = llvm::MemoryBuffer::getMemBuffer(GlobalContent);
auto MaybeNewGlobal = EC.getContext().getGlobals().createNew(SetGlobalName,
*Buffer);
if (not MaybeNewGlobal)
return MaybeNewGlobal.takeError();
if (not MaybeNewGlobal->get()->verify()) {
return revng::createError("could not verify %s", SetGlobalName.c_str());
}
if constexpr (commit) {
auto GlobalOrError = EC.getContext().getGlobals().get(SetGlobalName);
if (not GlobalOrError)
return GlobalOrError.takeError();
*GlobalOrError.get() = *MaybeNewGlobal.get();
}
return llvm::Error::success();
}
llvm::Error SetGlobalAnalysis::run(pipeline::ExecutionContext &EC,
std::string SetGlobalName,
std::string GlobalContent) {
return setGlobalImpl<true>(EC, SetGlobalName, GlobalContent);
}
llvm::Error VerifyGlobalAnalysis::run(pipeline::ExecutionContext &EC,
std::string SetGlobalName,
std::string GlobalContent) {
return setGlobalImpl<false>(EC, SetGlobalName, GlobalContent);
}
static pipeline::RegisterAnalysis<ApplyDiffAnalysis> X1;
static pipeline::RegisterAnalysis<VerifyDiffAnalysis> X2;
static pipeline::RegisterAnalysis<SetGlobalAnalysis> X3;
static pipeline::RegisterAnalysis<VerifyGlobalAnalysis> X4;
} // namespace revng::pipes