mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
115 lines
3.7 KiB
C++
115 lines
3.7 KiB
C++
/// \file GlobalsAnalyses.cpp
|
|
|
|
//
|
|
// 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
|