P4C
The P4 Compiler
Loading...
Searching...
No Matches
reachability.h
1#ifndef COMMON_COMPILER_REACHABILITY_H_
2#define COMMON_COMPILER_REACHABILITY_H_
3
4#include <list>
5#include <set>
6#include <string>
7#include <unordered_map>
8#include <unordered_set>
9#include <utility>
10#include <vector>
11
12#include "frontends/p4/callGraph.h"
13#include "ir/id.h"
14#include "ir/ir.h"
15#include "ir/node.h"
16#include "ir/visitor.h"
17#include "lib/cstring.h"
18#include "lib/null.h"
19
20namespace P4Tools {
21
22using DCGVertexType = const IR::Node;
23using DCGVertexTypeSet = std::unordered_set<const DCGVertexType *>;
24using ReachabilityHashType = std::unordered_map<cstring, std::unordered_set<const DCGVertexType *>>;
25
26template <class T>
28 friend class P4ProgramDCGCreator;
29 ReachabilityHashType hash;
30
31 public:
32 explicit ExtendedCallGraph(std::string_view name) : P4::CallGraph<T>(name) {}
33 const ReachabilityHashType &getHash() const { return hash; }
37 void addToHash(T vertex, IR::ID name) {
38 if (name.name.size() == 0) {
39 return;
40 }
41 auto i = hash.find(name.name);
42 if (i == hash.end()) {
43 std::unordered_set<const DCGVertexType *> s;
44 s.insert(vertex);
45 hash.emplace(name.name, s);
46 } else {
47 i->second.insert(vertex);
48 }
49 const auto *prev = name.name.findlast('.');
50 if (prev != nullptr) {
51 cstring newName = name.name.before(prev);
52 i = hash.find(newName);
53 if (i == hash.end()) {
54 addToHash(vertex, (newName.size() ? IR::ID(newName) : IR::ID()));
55 }
56 }
57 }
58
59 bool isReachable(T start, T element) const {
60 CHECK_NULL(start);
61 CHECK_NULL(element);
62 std::set<T> work;
63 std::set<T> visited;
64 work.emplace(start);
65 while (!work.empty()) {
66 auto *node = *work.begin();
67 if (node->equiv(*element)) {
68 return true;
69 }
70 work.erase(node);
71 if (visited.find(node) != visited.end()) {
72 continue;
73 }
74 visited.emplace(node);
75 auto edges = this->out_edges.find(node);
76 if (edges == this->out_edges.end()) {
77 continue;
78 }
79 for (auto c : *(edges->second)) {
80 work.emplace(c);
81 }
82 }
83 return false;
84 }
85};
86
87using NodesCallGraph = ExtendedCallGraph<DCGVertexType *>;
88
91 NodesCallGraph *dcg;
92 DCGVertexTypeSet prev;
93 std::unordered_set<const DCGVertexType *> visited;
94 const IR::P4Program *p4program;
95
96 public:
98
99 bool preorder(const IR::Annotation *annotation) override;
100 bool preorder(const IR::ConstructorCallExpression *callExpr) override;
101 bool preorder(const IR::MethodCallExpression *method) override;
102 bool preorder(const IR::MethodCallStatement *method) override;
103 bool preorder(const IR::P4Action *action) override;
104 bool preorder(const IR::P4Parser *parser) override;
105 bool preorder(const IR::P4Table *table) override;
106 bool preorder(const IR::ParserState *parserState) override;
107 bool preorder(const IR::P4Control *control) override;
108 bool preorder(const IR::P4Program *program) override;
109 bool preorder(const IR::P4ValueSet *valueSet) override;
110 bool preorder(const IR::SelectExpression *selectExpression) override;
111 bool preorder(const IR::IfStatement *ifStatement) override;
112 bool preorder(const IR::SwitchStatement *switchStatement) override;
113 bool preorder(const IR::StatOrDecl *statOrDecl) override;
114
115 protected:
118 void addEdge(const DCGVertexType *vertex, IR::ID vertexName = IR::ID());
119};
120
123 const DCGVertexType *prevNode = nullptr;
124 std::list<const DCGVertexType *> state;
125
126 public:
132 std::list<const DCGVertexType *> getState();
134 void setState(std::list<const DCGVertexType *>);
136 const DCGVertexType *getPrevNode();
138 void setPrevNode(const DCGVertexType *);
140 bool isEmpty();
142 void clear();
143};
144
145using ReachabilityResult = std::pair<bool, const IR::Expression *>;
146
158// Engine if corresponded <p4c node name> was reached.
160 const NodesCallGraph &dcg;
161 const ReachabilityHashType &hash;
162 std::unordered_map<const DCGVertexType *, std::list<const DCGVertexType *>> userTransitions;
163 std::unordered_map<const DCGVertexType *, const IR::Expression *> conditions;
164 std::unordered_set<const DCGVertexType *> forbiddenVertexes;
165
166 public:
171 ReachabilityEngine(const NodesCallGraph &dcg, std::string reachabilityExpression,
172 bool eliminateAnnotations = false);
178 ReachabilityResult next(ReachabilityEngineState *, const DCGVertexType *);
180 const NodesCallGraph &getDCG();
181
182 protected:
184 void annotationToStatements(const DCGVertexType *node,
185 std::unordered_set<const DCGVertexType *> &s);
187 void addTransition(const DCGVertexType *, const std::unordered_set<const DCGVertexType *> &);
189 std::unordered_set<const DCGVertexType *> getName(std::string name);
191 const IR::Expression *getCondition(const DCGVertexType *);
193 const IR::Expression *addCondition(const IR::Expression *prev,
194 const DCGVertexType *currentState);
197 static const IR::Expression *stringToNode(std::string name);
198
199 protected:
202 void addEdge(const DCGVertexType *vertex, IR::ID vertexName = IR::ID());
203};
204
205} // namespace P4Tools
206
207#endif /* COMMON_COMPILER_REACHABILITY_H_ */
Definition node.h:93
Definition visitor.h:396
Definition callGraph.h:41
Definition reachability.h:27
void addToHash(T vertex, IR::ID name)
Definition reachability.h:37
The main class for building control flow DCG.
Definition reachability.h:90
void addEdge(const DCGVertexType *vertex, IR::ID vertexName=IR::ID())
Definition common/compiler/reachability.cpp:320
Definition reachability.h:159
const IR::Expression * addCondition(const IR::Expression *prev, const DCGVertexType *currentState)
Adds user's condition the a node.
Definition common/compiler/reachability.cpp:444
void addEdge(const DCGVertexType *vertex, IR::ID vertexName=IR::ID())
static const IR::Expression * stringToNode(std::string name)
Definition common/compiler/reachability.cpp:564
std::unordered_set< const DCGVertexType * > getName(std::string name)
Translates string into the corresponding nodes.
Definition common/compiler/reachability.cpp:453
const NodesCallGraph & getDCG()
Returns current control flow graph.
Definition common/compiler/reachability.cpp:554
void annotationToStatements(const DCGVertexType *node, std::unordered_set< const DCGVertexType * > &s)
Translates current annotation into set of the parent nodes.
Definition common/compiler/reachability.cpp:406
ReachabilityResult next(ReachabilityEngineState *, const DCGVertexType *)
Definition common/compiler/reachability.cpp:486
ReachabilityEngine(const NodesCallGraph &dcg, std::string reachabilityExpression, bool eliminateAnnotations=false)
Definition common/compiler/reachability.cpp:356
const IR::Expression * getCondition(const DCGVertexType *)
Gets a user's condition from a node.
Definition common/compiler/reachability.cpp:556
void addTransition(const DCGVertexType *, const std::unordered_set< const DCGVertexType * > &)
Adds transition to engine control flow graph.
Definition common/compiler/reachability.cpp:430
The main data for reachability engine.
Definition reachability.h:122
static ReachabilityEngineState * getInitial()
Gets initial state.
Definition common/compiler/reachability.cpp:330
bool isEmpty()
Retuns true if state is empty.
Definition common/compiler/reachability.cpp:352
std::list< const DCGVertexType * > getState()
Gets current state.
Definition common/compiler/reachability.cpp:344
void setPrevNode(const DCGVertexType *)
Sets previous node.
Definition common/compiler/reachability.cpp:350
void clear()
Clears state.
Definition common/compiler/reachability.cpp:354
const DCGVertexType * getPrevNode()
Gets previous node.
Definition common/compiler/reachability.cpp:348
ReachabilityEngineState * copy()
Copies a state.
Definition common/compiler/reachability.cpp:337
void setState(std::list< const DCGVertexType * >)
Sets current state.
Definition common/compiler/reachability.cpp:346
Definition cstring.h:80
Definition common/compiler/compiler_result.cpp:3
Definition id.h:28