mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
tmp
This commit is contained in:
@@ -264,6 +264,8 @@ public:
|
||||
static const bool is_bidirectional_node = true;
|
||||
|
||||
public:
|
||||
using NodeData = Node;
|
||||
using EdgeLabelData = EdgeLabel;
|
||||
using Base = ForwardNode<Node,
|
||||
EdgeLabel,
|
||||
HasParent,
|
||||
|
||||
@@ -7,86 +7,138 @@
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
|
||||
#include "revng/ADT/GenericGraph.h"
|
||||
#include "revng/ADT/KeyedObjectTraits.h"
|
||||
#include "revng/ADT/SortedVector.h"
|
||||
#include "revng/Model/TupleTree.h"
|
||||
|
||||
template<typename NodeType>
|
||||
template<typename NodeType, typename EdgeLabel>
|
||||
struct SerializableEdge {
|
||||
using KKeyType = decltype(
|
||||
KeyedObjectTraits<NodeType>::key(*((NodeType *) NULL)));
|
||||
SerializableEdge(KKeyType Neighbor) : Neighbor(Neighbor) {}
|
||||
SerializableEdge(KKeyType Neighbor, const EdgeLabel &Label) :
|
||||
Neighbor(Neighbor), Label(Label) {}
|
||||
KKeyType Neighbor;
|
||||
EdgeLabel Label;
|
||||
|
||||
bool operator==(const SerializableEdge &Other) const = default;
|
||||
bool operator<(const SerializableEdge &Other) const = default;
|
||||
};
|
||||
|
||||
template<typename NodeType, typename EdgeLabel>
|
||||
struct llvm::yaml::MappingTraits<SerializableEdge<NodeType, EdgeLabel>>
|
||||
: public TupleLikeMappingTraits<SerializableEdge<NodeType, EdgeLabel>> {};
|
||||
|
||||
template<typename NodeType, typename EdgeLabel>
|
||||
struct SerializableNode {
|
||||
using BDir = BidirectionalNode<NodeType>;
|
||||
using KKeyType = decltype(KeyedObjectTraits<BDir>::key(*((BDir *) NULL)));
|
||||
NodeType N;
|
||||
SortedVector<KKeyType> Successors;
|
||||
using KKeyType = decltype(
|
||||
KeyedObjectTraits<NodeType>::key(*((NodeType *) NULL)));
|
||||
NodeType Node;
|
||||
SortedVector<SerializableEdge<NodeType, EdgeLabel>> Successors;
|
||||
|
||||
bool operator!=(const SerializableNode<NodeType> &O) const {
|
||||
return N != O.N;
|
||||
bool operator==(const SerializableNode &O) const = default;
|
||||
};
|
||||
|
||||
template<typename NodeType, typename EdgeLabel>
|
||||
struct llvm::yaml::MappingTraits<SerializableNode<NodeType, EdgeLabel>>
|
||||
: public TupleLikeMappingTraits<SerializableNode<NodeType, EdgeLabel>> {};
|
||||
|
||||
template<typename NodeType, typename EdgeLabel>
|
||||
struct KeyedObjectTraits<SerializableNode<NodeType, EdgeLabel>> {
|
||||
using KKeyType = decltype(
|
||||
KeyedObjectTraits<NodeType>::key(*((NodeType *) NULL)));
|
||||
|
||||
static KKeyType key(const SerializableNode<NodeType, EdgeLabel> &Node) {
|
||||
return KeyedObjectTraits<NodeType>::key(NodeType(Node.Node));
|
||||
}
|
||||
|
||||
static SerializableNode<NodeType, EdgeLabel> fromKey(const KKeyType &Key) {
|
||||
return SerializableNode<NodeType, EdgeLabel>({ Key, {} });
|
||||
}
|
||||
};
|
||||
|
||||
template<typename NodeType>
|
||||
struct KeyedObjectTraits<SerializableNode<NodeType>> {
|
||||
using BDir = BidirectionalNode<NodeType>;
|
||||
using KKeyType = decltype(KeyedObjectTraits<BDir>::key(*((BDir *) NULL)));
|
||||
template<typename NodeType, typename EdgeLabel>
|
||||
struct KeyedObjectTraits<SerializableEdge<NodeType, EdgeLabel>> {
|
||||
using KKeyType = decltype(
|
||||
KeyedObjectTraits<NodeType>::key(*((NodeType *) NULL)));
|
||||
|
||||
static KKeyType key(const SerializableNode<NodeType> &FD) {
|
||||
return KeyedObjectTraits<BDir>::key(BDir(FD.N));
|
||||
static KKeyType key(const SerializableEdge<NodeType, EdgeLabel> &Node) {
|
||||
return KeyedObjectTraits<NodeType>::key(NodeType(Node.Neighbor));
|
||||
}
|
||||
static SerializableNode<NodeType> fromKey(KKeyType Key) {
|
||||
return SerializableNode<NodeType>({ Key, {} });
|
||||
|
||||
static SerializableEdge<NodeType, EdgeLabel> fromKey(const KKeyType &Key) {
|
||||
return SerializableEdge<NodeType, EdgeLabel>({ Key, {} });
|
||||
}
|
||||
};
|
||||
|
||||
template<typename NodeType>
|
||||
template<typename NodeType, typename EdgeLabel>
|
||||
struct SerializableGraph {
|
||||
using BDir = BidirectionalNode<NodeType>;
|
||||
using SNode = SerializableNode<NodeType>;
|
||||
using KKeyType = decltype(KeyedObjectTraits<BDir>::key(*((BDir *) NULL)));
|
||||
using KKeyType = decltype(
|
||||
KeyedObjectTraits<NodeType>::key(*((NodeType *) NULL)));
|
||||
|
||||
SortedVector<SNode> Nodes;
|
||||
SortedVector<SerializableNode<NodeType, EdgeLabel>> Nodes;
|
||||
KKeyType EntryNode;
|
||||
|
||||
bool operator!=(const SerializableGraph<NodeType> &O) const {
|
||||
return Nodes != O.Nodes;
|
||||
}
|
||||
bool operator==(const SerializableGraph &O) const = default;
|
||||
|
||||
static SerializableGraph toSerializable(const GenericGraph<BDir> &G) {
|
||||
SerializableGraph Out;
|
||||
{
|
||||
auto Inserter = Out.Nodes.batch_insert();
|
||||
for (const auto &N : G.nodes())
|
||||
Inserter.insert(SNode{ getKey(*N), {} });
|
||||
}
|
||||
template<typename GenericGraphNodeType>
|
||||
GenericGraph<GenericGraphNodeType> toGenericGraph() const {
|
||||
GenericGraph<GenericGraphNodeType> Ret;
|
||||
|
||||
for (const auto &N : G.nodes()) {
|
||||
auto Inserter = Out.Nodes.at(getKey(*N)).Successors.batch_insert();
|
||||
for (const auto &J : N->successors())
|
||||
Inserter.insert(getKey(*J));
|
||||
}
|
||||
|
||||
if constexpr (GenericGraph<BDir>::hasEntryNode) {
|
||||
if (G.getEntryNode() != nullptr)
|
||||
Out.EntryNode = getKey(*G.getEntryNode());
|
||||
}
|
||||
return Out;
|
||||
};
|
||||
|
||||
GenericGraph<BDir> fromSerializable() const {
|
||||
GenericGraph<BDir> Ret;
|
||||
|
||||
std::map<KKeyType, BDir *> Map;
|
||||
std::map<KKeyType, GenericGraphNodeType *> Map;
|
||||
|
||||
for (const auto &N : Nodes)
|
||||
Map[getKey(N.N)] = Ret.addNode(N.N);
|
||||
Map[KeyedObjectTraits<NodeType>::key(N.Node)] = Ret.addNode(N.Node);
|
||||
|
||||
for (const auto &N : Nodes)
|
||||
for (const auto &S : N.Successors)
|
||||
Map[getKey(N.N)]->addSuccessor(Map[S]);
|
||||
Map[KeyedObjectTraits<NodeType>::key(N.Node)]->addSuccessor(Map[S.Neighbor], S.Label);
|
||||
|
||||
if constexpr (GenericGraph<BDir>::hasEntryNode) {
|
||||
if constexpr (GenericGraph<NodeType>::hasEntryNode) {
|
||||
Ret.setEntryNode(Map[EntryNode]);
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
private:
|
||||
static KKeyType getKey(const NodeType &N) {
|
||||
return KeyedObjectTraits<BDir>::key(BDir(N));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename NodeType, typename EdgeLabel>
|
||||
struct llvm::yaml::MappingTraits<SerializableGraph<NodeType, EdgeLabel>>
|
||||
: public TupleLikeMappingTraits<SerializableGraph<NodeType, EdgeLabel>> {};
|
||||
|
||||
template<typename G>
|
||||
SerializableGraph<typename G::Node::NodeData, typename G::Node::EdgeLabelData>
|
||||
toSerializable(const G &Graph) {
|
||||
using Node = typename G::Node::NodeData;
|
||||
using EdgeLabelData = typename G::Node::EdgeLabelData;
|
||||
SerializableGraph<Node, EdgeLabelData> Result;
|
||||
|
||||
{
|
||||
auto Inserter = Result.Nodes.batch_insert();
|
||||
for (const auto &N : Graph.nodes())
|
||||
Inserter.insert({ KeyedObjectTraits<Node>::key(*N), {} });
|
||||
}
|
||||
|
||||
for (const auto &N : Graph.nodes()) {
|
||||
auto Inserter = Result.Nodes.at(KeyedObjectTraits<Node>::key(*N))
|
||||
.Successors.batch_insert();
|
||||
for (const auto &J : N->successor_edges())
|
||||
Inserter.insert({ KeyedObjectTraits<Node>::key(*J.Neighbor), J });
|
||||
}
|
||||
|
||||
if constexpr (GenericGraph<Node>::hasEntryNode) {
|
||||
if (Graph.getEntryNode() != nullptr)
|
||||
Result.EntryNode = KeyedObjectTraits<Node>::key(*Graph.getEntryNode());
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
template<typename T> struct argument_type;
|
||||
template<typename T, typename U> struct argument_type<T(U)> { using type = U; };
|
||||
#define TYPE(A) argument_type<void(A)>::type
|
||||
|
||||
#define SERIALIZABLEGRAPH_INTROSPECTION(A, B) \
|
||||
INTROSPECTION(TYPE((SerializableGraph<A, B>)), Nodes, EntryNode); \
|
||||
INTROSPECTION(TYPE((SerializableNode<A, B>)), Node, Successors); \
|
||||
INTROSPECTION(TYPE((SerializableEdge<A, B>)), Neighbor, Label)
|
||||
|
||||
@@ -19,6 +19,7 @@ bool init_unit_test();
|
||||
|
||||
#include "revng/ADT/FilteredGraphTraits.h"
|
||||
#include "revng/ADT/GenericGraph.h"
|
||||
#include "revng/ADT/SerializableGraph.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@@ -112,18 +113,48 @@ BOOST_AUTO_TEST_CASE(TestCompile) {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Define TestEdgeLabel
|
||||
//
|
||||
struct TestEdgeLabel {
|
||||
bool operator==(const TestEdgeLabel &) const = default;
|
||||
unsigned Weight;
|
||||
};
|
||||
|
||||
INTROSPECTION(TestEdgeLabel, Weight);
|
||||
|
||||
template<>
|
||||
struct llvm::yaml::MappingTraits<TestEdgeLabel>
|
||||
: public TupleLikeMappingTraits<TestEdgeLabel> {};
|
||||
|
||||
//
|
||||
// Define TestNodeData
|
||||
//
|
||||
struct TestNodeData {
|
||||
TestNodeData(unsigned Rank) : Rank(Rank) {}
|
||||
bool operator==(const TestNodeData &) const = default;
|
||||
unsigned Rank;
|
||||
};
|
||||
|
||||
INTROSPECTION(TestNodeData, Rank);
|
||||
|
||||
template<>
|
||||
struct llvm::yaml::MappingTraits<TestNodeData>
|
||||
: public TupleLikeMappingTraits<TestNodeData> {};
|
||||
|
||||
|
||||
template<>
|
||||
struct KeyedObjectTraits<TestNodeData> {
|
||||
static unsigned key(const TestNodeData &Node) { return Node.Rank; }
|
||||
|
||||
static TestNodeData fromKey(const unsigned &Key) { return { Key }; }
|
||||
};
|
||||
|
||||
using TestNode = BidirectionalNode<TestNodeData, TestEdgeLabel>;
|
||||
using TestGraph = GenericGraph<TestNode>;
|
||||
|
||||
SERIALIZABLEGRAPH_INTROSPECTION(TestNodeData, TestEdgeLabel);
|
||||
|
||||
static bool
|
||||
shouldKeepNodePair(TestNode *const &Source, TestNode *const &Destination) {
|
||||
return Source->Rank + Destination->Rank <= 2;
|
||||
@@ -148,7 +179,7 @@ static DiamondGraph createGraph() {
|
||||
// Create nodes
|
||||
DG.Root = Graph.addNode(0);
|
||||
DG.Then = Graph.addNode(1);
|
||||
DG.Else = Graph.addNode(1);
|
||||
DG.Else = Graph.addNode(3);
|
||||
DG.Final = Graph.addNode(2);
|
||||
|
||||
// Set entry node
|
||||
@@ -228,7 +259,7 @@ BOOST_AUTO_TEST_CASE(TestFilterGraphTraits) {
|
||||
FGT>;
|
||||
auto Begin = fdf_iterator::begin(Root);
|
||||
auto End = fdf_iterator::end(Root);
|
||||
revng_check(3 == std::distance(Begin, End));
|
||||
revng_check(2 == std::distance(Begin, End));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -248,3 +279,30 @@ BOOST_AUTO_TEST_CASE(TestWriteGraph) {
|
||||
llvm::raw_null_ostream NullOutput;
|
||||
llvm::WriteGraph(NullOutput, &DG.Graph, "lol");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestSerializableGraph) {
|
||||
DiamondGraph DG = createGraph();
|
||||
auto Serializable = toSerializable(DG.Graph);
|
||||
auto Reserializable = toSerializable(Serializable.toGenericGraph<TestNode>());
|
||||
revng_check(Reserializable == Serializable);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestSerializeGraph) {
|
||||
DiamondGraph DG = createGraph();
|
||||
auto Serializable = toSerializable(DG.Graph);
|
||||
|
||||
std::string Buffer;
|
||||
{
|
||||
llvm::raw_string_ostream Stream(Buffer);
|
||||
yaml::Output YAMLOutput(Stream);
|
||||
YAMLOutput << Serializable;
|
||||
}
|
||||
|
||||
dbg << Buffer << "\n";
|
||||
|
||||
decltype(Serializable) Deserialized;
|
||||
llvm::yaml::Input YAMLInput(Buffer);
|
||||
YAMLInput >> Deserialized;
|
||||
|
||||
revng_check(Deserialized == Serializable);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user