mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
210 lines
6.4 KiB
C++
210 lines
6.4 KiB
C++
#pragma once
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include <any>
|
|
#include <memory>
|
|
#include <type_traits>
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/Error.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "revng/Pipeline/GlobalTupleTreeDiff.h"
|
|
#include "revng/Pipeline/PathTargetBimap.h"
|
|
#include "revng/Storage/Path.h"
|
|
#include "revng/Support/Error.h"
|
|
#include "revng/Support/YAMLTraits.h"
|
|
#include "revng/TupleTree/Tracking.h"
|
|
#include "revng/TupleTree/TupleTreeDiff.h"
|
|
|
|
namespace pipeline {
|
|
|
|
class Global {
|
|
private:
|
|
const char *ID;
|
|
std::string Name;
|
|
|
|
public:
|
|
Global(const char *ID, llvm::StringRef Name) : ID(ID), Name(Name.str()) {}
|
|
virtual ~Global() {}
|
|
virtual Global &operator=(const Global &NewGlobal) = 0;
|
|
|
|
public:
|
|
Global(const Global &) = default;
|
|
Global(Global &&) = default;
|
|
Global &operator=(Global &&) = default;
|
|
|
|
public:
|
|
const char *getID() const { return ID; }
|
|
llvm::StringRef getName() const { return Name; }
|
|
|
|
public:
|
|
virtual GlobalTupleTreeDiff diff(const Global &Other) const = 0;
|
|
virtual llvm::Error applyDiff(const llvm::MemoryBuffer &Diff) = 0;
|
|
virtual llvm::Error applyDiff(const GlobalTupleTreeDiff &Diff) = 0;
|
|
|
|
virtual llvm::Error serialize(llvm::raw_ostream &OS) const = 0;
|
|
virtual llvm::Error fromString(llvm::StringRef String) = 0;
|
|
virtual llvm::Expected<GlobalTupleTreeDiff>
|
|
diffFromString(llvm::StringRef String) = 0;
|
|
|
|
virtual bool verify() const = 0;
|
|
virtual void clear() = 0;
|
|
|
|
virtual llvm::Expected<std::unique_ptr<Global>>
|
|
createNew(llvm::StringRef Name, const llvm::MemoryBuffer &Buffer) const = 0;
|
|
|
|
virtual std::unique_ptr<Global> clone() const = 0;
|
|
|
|
virtual llvm::Error store(const revng::FilePath &Path) const;
|
|
virtual llvm::Error load(const revng::FilePath &Path);
|
|
|
|
virtual std::optional<TupleTreePath>
|
|
deserializePath(llvm::StringRef Serialized) const = 0;
|
|
|
|
virtual std::optional<std::string>
|
|
serializePath(const TupleTreePath &Path) const = 0;
|
|
|
|
virtual void collectReadFields(const TargetInContainer &Target,
|
|
PathTargetBimap &Out) = 0;
|
|
virtual void clearAndResume() const = 0;
|
|
virtual void pushReadFields() const = 0;
|
|
virtual void popReadFields() const = 0;
|
|
virtual void stopTracking() const = 0;
|
|
};
|
|
|
|
template<TupleTreeCompatibleAndVerifiable Object>
|
|
class TupleTreeGlobal : public Global {
|
|
private:
|
|
TupleTree<Object> Value;
|
|
|
|
static const char &getID() {
|
|
static char ID;
|
|
return ID;
|
|
}
|
|
|
|
public:
|
|
explicit TupleTreeGlobal(llvm::StringRef Name, TupleTree<Object> Value) :
|
|
Global(&getID(), Name), Value(std::move(Value)) {}
|
|
|
|
explicit TupleTreeGlobal(llvm::StringRef Name) : Global(&getID(), Name) {}
|
|
TupleTreeGlobal(const TupleTreeGlobal &Other) = default;
|
|
TupleTreeGlobal(TupleTreeGlobal &&Other) = default;
|
|
TupleTreeGlobal &operator=(const TupleTreeGlobal &Other) = default;
|
|
TupleTreeGlobal &operator=(TupleTreeGlobal &&Other) = default;
|
|
virtual ~TupleTreeGlobal() override = default;
|
|
|
|
static bool classof(const Global *T) { return T->getID() == &getID(); }
|
|
|
|
public:
|
|
llvm::Expected<std::unique_ptr<Global>>
|
|
createNew(llvm::StringRef Name,
|
|
const llvm::MemoryBuffer &Buffer) const override {
|
|
auto MaybeTree = TupleTree<Object>::fromString(Buffer.getBuffer());
|
|
if (!MaybeTree)
|
|
return MaybeTree.takeError();
|
|
return std::make_unique<TupleTreeGlobal>(Name, MaybeTree.get());
|
|
}
|
|
|
|
std::unique_ptr<Global> clone() const override {
|
|
auto Ptr = new TupleTreeGlobal(*this);
|
|
return std::unique_ptr<Global>(Ptr);
|
|
}
|
|
|
|
void clear() override {
|
|
Value.evictCachedReferences();
|
|
*Value = Object();
|
|
}
|
|
|
|
llvm::Error serialize(llvm::raw_ostream &OS) const override {
|
|
Value.serialize(OS);
|
|
return llvm::Error::success();
|
|
}
|
|
|
|
llvm::Error fromString(llvm::StringRef String) override {
|
|
auto MaybeTupleTree = TupleTree<Object>::fromString(String);
|
|
if (!MaybeTupleTree)
|
|
return MaybeTupleTree.takeError();
|
|
|
|
if (not(*MaybeTupleTree)->verify()) {
|
|
return revng::createError("Verify failed on " + getName());
|
|
}
|
|
|
|
Value = *MaybeTupleTree;
|
|
return llvm::Error::success();
|
|
}
|
|
|
|
llvm::Expected<GlobalTupleTreeDiff>
|
|
diffFromString(llvm::StringRef String) override {
|
|
auto MaybeDiff = ::fromString<TupleTreeDiff<Object>>(String);
|
|
if (not MaybeDiff)
|
|
return MaybeDiff.takeError();
|
|
return GlobalTupleTreeDiff(std::move(*MaybeDiff), getName());
|
|
}
|
|
|
|
bool verify() const override { return Value->verify(); }
|
|
|
|
GlobalTupleTreeDiff diff(const Global &Other) const override {
|
|
const TupleTreeGlobal &Casted = llvm::cast<TupleTreeGlobal>(Other);
|
|
auto Diff = ::diff(*Value, *Casted.Value);
|
|
return GlobalTupleTreeDiff(std::move(Diff), getName());
|
|
}
|
|
|
|
llvm::Error applyDiff(const llvm::MemoryBuffer &Diff) override {
|
|
auto MaybeDiff = TupleTreeDiff<Object>::fromString(Diff.getBuffer());
|
|
if (not MaybeDiff) {
|
|
return MaybeDiff.takeError();
|
|
}
|
|
return MaybeDiff->apply(Value);
|
|
}
|
|
|
|
llvm::Error applyDiff(const TupleTreeDiff<Object> &Diff) {
|
|
return Diff.apply(Value);
|
|
}
|
|
|
|
llvm::Error applyDiff(const GlobalTupleTreeDiff &Diff) override {
|
|
return Diff.getAs<Object>()->apply(Value);
|
|
}
|
|
|
|
Global &operator=(const Global &Other) override {
|
|
const TupleTreeGlobal &Casted = llvm::cast<TupleTreeGlobal>(Other);
|
|
Value = Casted.Value;
|
|
return *this;
|
|
}
|
|
|
|
const TupleTree<Object> &get() const { return Value; }
|
|
TupleTree<Object> &get() { return Value; }
|
|
|
|
std::optional<TupleTreePath>
|
|
deserializePath(llvm::StringRef Serialized) const override {
|
|
return stringAsPath<Object>(Serialized);
|
|
}
|
|
|
|
std::optional<std::string>
|
|
serializePath(const TupleTreePath &Path) const override {
|
|
return pathAsString<Object>(Path);
|
|
}
|
|
|
|
void collectReadFields(const TargetInContainer &Target,
|
|
PathTargetBimap &Out) override {
|
|
const TupleTree<Object> &AsConst = Value;
|
|
ReadFields Results = revng::Tracking::collect(*AsConst);
|
|
for (const TupleTreePath &Result : Results.Read)
|
|
Out.insert(Target, Result);
|
|
for (const TupleTreePath &Result : Results.ExactVectors)
|
|
Out.insert(Target, Result);
|
|
}
|
|
|
|
void clearAndResume() const override {
|
|
revng::Tracking::clearAndResume(*Value);
|
|
}
|
|
void pushReadFields() const override { revng::Tracking::push(*Value); }
|
|
void popReadFields() const override { revng::Tracking::pop(*Value); }
|
|
void stopTracking() const override { revng::Tracking::stop(*Value); }
|
|
};
|
|
|
|
} // namespace pipeline
|