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
11#include "frontends/common/resolveReferences/resolveReferences.h"
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 P4::P4Tools {
21
22using DCGVertexType = const IR::Node *;
23using DCGVertexTypeSet = std::unordered_set<DCGVertexType>;
24using ReachabilityHashType = std::unordered_map<cstring, DCGVertexTypeSet>;
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, const 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<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.isNullOrEmpty() ? 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<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 *call) 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(DCGVertexType vertex, const IR::ID &vertexName = IR::ID());
119};
120
123 DCGVertexType prevNode = nullptr;
124 std::list<DCGVertexType> state;
125
126 public:
132 std::list<DCGVertexType> getState();
134 void setState(const std::list<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<DCGVertexType, std::list<DCGVertexType>> userTransitions;
163 std::unordered_map<DCGVertexType, const IR::Expression *> conditions;
164 std::unordered_set<DCGVertexType> forbiddenVertexes;
165
166 public:
171 ReachabilityEngine(const NodesCallGraph &dcg, std::string reachabilityExpression,
172 bool eliminateAnnotations = false);
178 ReachabilityResult next(ReachabilityEngineState *, DCGVertexType);
180 const NodesCallGraph &getDCG();
181
182 protected:
184 void annotationToStatements(DCGVertexType node, std::unordered_set<DCGVertexType> &s);
186 void addTransition(DCGVertexType, const std::unordered_set<DCGVertexType> &);
188 std::unordered_set<DCGVertexType> getName(std::string name);
190 const IR::Expression *getCondition(DCGVertexType);
192 const IR::Expression *addCondition(const IR::Expression *prev, DCGVertexType currentState);
195 static const IR::Expression *stringToNode(std::string name);
196
197 protected:
200 void addEdge(DCGVertexType vertex, IR::ID vertexName = IR::ID());
201};
202
203} // namespace P4::P4Tools
204
205#endif /* COMMON_COMPILER_REACHABILITY_H_ */
Definition callGraph.h:41
Definition node.h:94
Definition visitor.h:400
Definition reachability.h:27
void addToHash(T vertex, const IR::ID &name)
Definition reachability.h:37
The main class for building control flow DCG.
Definition reachability.h:90
void addEdge(DCGVertexType vertex, const IR::ID &vertexName=IR::ID())
Definition common/compiler/reachability.cpp:354
Definition reachability.h:159
static const IR::Expression * stringToNode(std::string name)
Definition common/compiler/reachability.cpp:597
const IR::Expression * addCondition(const IR::Expression *prev, DCGVertexType currentState)
Adds user's condition the a node.
Definition common/compiler/reachability.cpp:478
void annotationToStatements(DCGVertexType node, std::unordered_set< DCGVertexType > &s)
Translates current annotation into set of the parent nodes.
Definition common/compiler/reachability.cpp:440
const NodesCallGraph & getDCG()
Returns current control flow graph.
Definition common/compiler/reachability.cpp:587
const IR::Expression * getCondition(DCGVertexType)
Gets a user's condition from a node.
Definition common/compiler/reachability.cpp:589
void addEdge(DCGVertexType vertex, IR::ID vertexName=IR::ID())
ReachabilityResult next(ReachabilityEngineState *, DCGVertexType)
Definition common/compiler/reachability.cpp:520
void addTransition(DCGVertexType, const std::unordered_set< DCGVertexType > &)
Adds transition to engine control flow graph.
Definition common/compiler/reachability.cpp:464
ReachabilityEngine(const NodesCallGraph &dcg, std::string reachabilityExpression, bool eliminateAnnotations=false)
Definition common/compiler/reachability.cpp:390
std::unordered_set< DCGVertexType > getName(std::string name)
Translates string into the corresponding nodes.
Definition common/compiler/reachability.cpp:487
The main data for reachability engine.
Definition reachability.h:122
void clear()
Clears state.
Definition common/compiler/reachability.cpp:388
std::list< DCGVertexType > getState()
Gets current state.
Definition common/compiler/reachability.cpp:378
ReachabilityEngineState * copy()
Copies a state.
Definition common/compiler/reachability.cpp:371
void setState(const std::list< DCGVertexType > &)
Sets current state.
Definition common/compiler/reachability.cpp:380
void setPrevNode(DCGVertexType)
Sets previous node.
Definition common/compiler/reachability.cpp:384
static ReachabilityEngineState * getInitial()
Gets initial state.
Definition common/compiler/reachability.cpp:364
DCGVertexType getPrevNode()
Gets previous node.
Definition common/compiler/reachability.cpp:382
bool isEmpty()
Retuns true if state is empty.
Definition common/compiler/reachability.cpp:386
Visitor mixin for looking up names in enclosing scopes from the Visitor::Context.
Definition resolveReferences.h:35
Definition cstring.h:85
Definition common/compiler/compiler_result.cpp:3
Definition id.h:28