#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include #include #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/Support/YAMLTraits.h" #include "revng/TupleTree/TupleTreeDiff.h" namespace pipeline { class Global { private: const char *ID; public: Global(const char *ID) : ID(ID) {} 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; } 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 deserialize(const llvm::MemoryBuffer &Buffer) = 0; virtual llvm::Expected deserializeDiff(const llvm::MemoryBuffer &Diff) = 0; virtual bool verify() const = 0; virtual void clear() = 0; virtual llvm::Expected> createNew(const llvm::MemoryBuffer &Buffer) const = 0; virtual std::unique_ptr clone() const = 0; virtual llvm::Error storeToDisk(llvm::StringRef Path) const; virtual llvm::Error loadFromDisk(llvm::StringRef Path); }; template class TupleTreeGlobal : public Global { private: TupleTree Value; static const char &getID() { static char ID; return ID; } public: explicit TupleTreeGlobal(TupleTree Value) : Global(&getID()), Value(std::move(Value)) {} TupleTreeGlobal() : Global(&getID()) {} 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> createNew(const llvm::MemoryBuffer &Buffer) const override { auto MaybeTree = TupleTree::deserialize(Buffer.getBuffer()); if (!MaybeTree) return llvm::errorCodeToError(MaybeTree.getError()); return std::make_unique(MaybeTree.get()); } std::unique_ptr clone() const override { auto Ptr = new TupleTreeGlobal(*this); return std::unique_ptr(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 deserialize(const llvm::MemoryBuffer &Buffer) override { auto MaybeDiff = TupleTree::deserialize(Buffer.getBuffer()); if (!MaybeDiff) return llvm::errorCodeToError(MaybeDiff.getError()); Value = *MaybeDiff; return llvm::Error::success(); } llvm::Expected deserializeDiff(const llvm::MemoryBuffer &Buffer) override { return ::deserialize>(Buffer.getBuffer()); } bool verify() const override { return Value->verify(); } GlobalTupleTreeDiff diff(const Global &Other) const override { const TupleTreeGlobal &Casted = llvm::cast(Other); auto Diff = ::diff(*Value, *Casted.Value); return GlobalTupleTreeDiff(std::move(Diff)); } llvm::Error applyDiff(const llvm::MemoryBuffer &Diff) override { auto MaybeDiff = TupleTreeDiff::deserialize(Diff.getBuffer()); if (not MaybeDiff) { return MaybeDiff.takeError(); } return MaybeDiff->apply(Value); } llvm::Error applyDiff(const TupleTreeDiff &Diff) { return Diff.apply(Value); } llvm::Error applyDiff(const GlobalTupleTreeDiff &Diff) override { return Diff.getAs()->apply(Value); } Global &operator=(const Global &Other) override { const TupleTreeGlobal &Casted = llvm::cast(Other); Value = Casted.Value; return *this; } const TupleTree &get() const { return Value; } TupleTree &get() { return Value; } }; } // namespace pipeline