P4C
The P4 Compiler
Loading...
Searching...
No Matches
ir-inline.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef IR_IR_INLINE_H_
18#define IR_IR_INLINE_H_
19
20#include "ir/id.h"
21#include "ir/indexed_vector.h"
22#include "ir/json_generator.h"
23#include "ir/namemap.h"
24#include "ir/nodemap.h"
25#include "ir/visitor.h"
26#include "lib/ordered_map.h"
27
28namespace P4 {
29
30#define DEFINE_APPLY_FUNCTIONS(CLASS, TEMPLATE, TT, INLINE) \
31 TEMPLATE INLINE bool IR::CLASS TT::apply_visitor_preorder(Modifier &v) { \
32 Node::traceVisit("Mod pre"); \
33 return v.preorder(this); \
34 } \
35 TEMPLATE INLINE void IR::CLASS TT::apply_visitor_postorder(Modifier &v) { \
36 Node::traceVisit("Mod post"); \
37 v.postorder(this); \
38 } \
39 TEMPLATE INLINE void IR::CLASS TT::apply_visitor_revisit(Modifier &v, const Node *n) const { \
40 Node::traceVisit("Mod revisit"); \
41 v.revisit(this, n); \
42 } \
43 TEMPLATE INLINE void IR::CLASS TT::apply_visitor_loop_revisit(Modifier &v) const { \
44 Node::traceVisit("Mod loop_revisit"); \
45 v.loop_revisit(this); \
46 } \
47 TEMPLATE INLINE bool IR::CLASS TT::apply_visitor_preorder(Inspector &v) const { \
48 Node::traceVisit("Insp pre"); \
49 return v.preorder(this); \
50 } \
51 TEMPLATE INLINE void IR::CLASS TT::apply_visitor_postorder(Inspector &v) const { \
52 Node::traceVisit("Insp post"); \
53 v.postorder(this); \
54 } \
55 TEMPLATE INLINE void IR::CLASS TT::apply_visitor_revisit(Inspector &v) const { \
56 Node::traceVisit("Insp revisit"); \
57 v.revisit(this); \
58 } \
59 TEMPLATE INLINE void IR::CLASS TT::apply_visitor_loop_revisit(Inspector &v) const { \
60 Node::traceVisit("Insp loop_revisit"); \
61 v.loop_revisit(this); \
62 } \
63 TEMPLATE INLINE const IR::Node *IR::CLASS TT::apply_visitor_preorder(Transform &v) { \
64 Node::traceVisit("Trans pre"); \
65 return v.preorder(this); \
66 } \
67 TEMPLATE INLINE const IR::Node *IR::CLASS TT::apply_visitor_postorder(Transform &v) { \
68 Node::traceVisit("Trans post"); \
69 return v.postorder(this); \
70 } \
71 TEMPLATE INLINE void IR::CLASS TT::apply_visitor_revisit(Transform &v, const Node *n) const { \
72 Node::traceVisit("Trans revisit"); \
73 v.revisit(this, n); \
74 } \
75 TEMPLATE INLINE void IR::CLASS TT::apply_visitor_loop_revisit(Transform &v) const { \
76 Node::traceVisit("Trans loop_revisit"); \
77 v.loop_revisit(this); \
78 }
79
80IRNODE_ALL_TEMPLATES(DEFINE_APPLY_FUNCTIONS, inline)
81
82template <class T>
83void IR::Vector<T>::visit_children(Visitor &v, const char *name) {
84 for (auto i = vec.begin(); i != vec.end();) {
85 const IR::Node *n = v.apply_visitor(*i, name);
86 if (!n && *i) {
87 i = erase(i);
88 continue;
89 }
90 CHECK_NULL(n);
91 if (n == *i) {
92 i++;
93 continue;
94 }
95 if (auto l = n->to<Vector<T>>()) {
96 i = erase(i);
97 i = insert(i, l->vec.begin(), l->vec.end());
98 i += l->vec.size();
99 continue;
100 }
101 if (const auto *v = n->to<VectorBase>()) {
102 if (v->empty()) {
103 i = erase(i);
104 } else {
105 i = insert(i, v->size() - 1, nullptr);
106 for (const auto *el : *v) {
107 CHECK_NULL(el);
108 if (auto e = el->template to<T>()) {
109 *i++ = e;
110 } else {
111 BUG("visitor returned invalid type %s for Vector<%s>", el->node_type_name(),
112 T::static_type_name());
113 }
114 }
115 }
116 continue;
117 }
118 if (auto e = n->to<T>()) {
119 *i++ = e;
120 continue;
121 }
122 BUG("visitor returned invalid type %s for Vector<%s>", n->node_type_name(),
123 T::static_type_name());
124 }
125}
126template <class T>
127void IR::Vector<T>::visit_children(Visitor &v, const char *name) const {
128 for (auto &a : vec) v.visit(a, name);
129}
130template <class T>
131void IR::Vector<T>::parallel_visit_children(Visitor &v, const char *) {
132 SplitFlowVisitVector<T>(v, *this).run_visit();
133}
134template <class T>
135void IR::Vector<T>::parallel_visit_children(Visitor &v, const char *) const {
136 SplitFlowVisitVector<T>(v, *this).run_visit();
137}
138IRNODE_DEFINE_APPLY_OVERLOAD(Vector, template <class T>, <T>)
139template <class T>
140void IR::Vector<T>::toJSON(JSONGenerator &json) const {
141 Node::toJSON(json);
142 json.emit_tag("vec");
143 auto state = json.begin_vector();
144 for (auto &k : vec) json.emit(k);
145 json.end_vector(state);
146}
147
148std::ostream &operator<<(std::ostream &out, const IR::Vector<IR::Expression> &v);
149std::ostream &operator<<(std::ostream &out, const IR::Vector<IR::Annotation> &v);
150
151template <class T>
152void IR::IndexedVector<T>::visit_children(Visitor &v, const char *name) {
153 for (auto i = begin(); i != end();) {
154 auto n = v.apply_visitor(*i, name);
155 if (!n && *i) {
156 i = erase(i);
157 continue;
158 }
159 CHECK_NULL(n);
160 if (n == *i) {
161 i++;
162 continue;
163 }
164 if (auto l = n->template to<Vector<T>>()) {
165 i = erase(i);
166 i = insert(i, l->begin(), l->end());
167 i += l->Vector<T>::size();
168 continue;
169 }
170 if (auto e = n->template to<T>()) {
171 i = replace(i, e);
172 continue;
173 }
174 BUG("visitor returned invalid type %s for IndexedVector<%s>", n->node_type_name(),
175 T::static_type_name());
176 }
177}
178template <class T>
179void IR::IndexedVector<T>::visit_children(Visitor &v, const char *name) const {
180 for (auto &a : *this) v.visit(a, name);
181}
182template <class T>
183void IR::IndexedVector<T>::toJSON(JSONGenerator &json) const {
184 Vector<T>::toJSON(json);
185 json.emit_tag("declarations");
186 auto state = json.begin_object();
187 for (auto &k : declarations) json.emit(k.first, k.second);
188 json.end_object(state);
189}
190IRNODE_DEFINE_APPLY_OVERLOAD(IndexedVector, template <class T>, <T>)
191
192template <class MAP>
193static inline void namemap_insert_helper(typename MAP::iterator, typename MAP::key_type k,
194 typename MAP::mapped_type v, MAP &, MAP &new_symbols) {
195 new_symbols.emplace(std::move(k), std::move(v));
196}
197
198template <class MAP, class InputIterator>
199static inline void namemap_insert_helper(typename MAP::iterator, InputIterator b, InputIterator e,
200 MAP &, MAP &new_symbols) {
201 new_symbols.insert(b, e);
202}
203
204template <class T>
205static inline void namemap_insert_helper(typename ordered_map<cstring, T>::iterator it, cstring k,
206 T v, ordered_map<cstring, T> &symbols,
207 ordered_map<cstring, T> &) {
208 symbols.emplace_hint(it, std::move(k), std::move(v));
209}
210
211template <class T, class InputIterator>
212static inline void namemap_insert_helper(typename ordered_map<cstring, T>::iterator it,
213 InputIterator b, InputIterator e,
214 ordered_map<cstring, T> &symbols,
215 ordered_map<cstring, T> &) {
216 symbols.insert(it, b, e);
217}
218
219template <class T, template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
220 class COMP /*= std::less<cstring>*/,
221 class ALLOC /*= std::allocator<std::pair<const cstring, const T*>>*/>
222void IR::NameMap<T, MAP, COMP, ALLOC>::visit_children(Visitor &v, const char *) {
223 map_t new_symbols;
224 for (auto i = symbols.begin(); i != symbols.end();) {
225 const IR::Node *n = v.apply_visitor(i->second, i->first.c_str());
226 if (!n && i->second) {
227 i = symbols.erase(i);
228 continue;
229 }
230 CHECK_NULL(n);
231 if (n == i->second) {
232 i++;
233 continue;
234 }
235 if (auto m = n->to<NameMap>()) {
236 namemap_insert_helper(i, m->symbols.begin(), m->symbols.end(), symbols, new_symbols);
237 i = symbols.erase(i);
238 continue;
239 }
240 if (auto s = n->to<T>()) {
241 if (match_name(i->first, s)) {
242 i->second = s;
243 i++;
244 } else {
245 namemap_insert_helper(i, cstring(obj_name(s)), std::move(s), symbols, new_symbols);
246 i = symbols.erase(i);
247 }
248 continue;
249 }
250 BUG("visitor returned invalid type %s for NameMap<%s>", n->node_type_name(),
251 T::static_type_name());
252 }
253 symbols.insert(new_symbols.begin(), new_symbols.end());
254}
255template <class T, template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
256 class COMP /*= std::less<cstring>*/,
257 class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
258void IR::NameMap<T, MAP, COMP, ALLOC>::visit_children(Visitor &v, const char *) const {
259 for (auto &k : symbols) {
260 v.visit(k.second, k.first.c_str());
261 }
262}
263template <class T, template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
264 class COMP /*= std::less<cstring>*/,
265 class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
266void IR::NameMap<T, MAP, COMP, ALLOC>::toJSON(JSONGenerator &json) const {
267 Node::toJSON(json);
268 json.emit_tag("symbols");
269 auto state = json.begin_object();
270 for (auto &k : symbols) json.emit(k.first, k.second);
271 json.end_object(state);
272}
273
274template <class KEY, class VALUE,
275 template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
276 class COMP /*= std::less<cstring>*/,
277 class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
278void IR::NodeMap<KEY, VALUE, MAP, COMP, ALLOC>::visit_children(Visitor &v, const char *name) {
279 map_t new_symbols;
280 for (auto i = symbols.begin(); i != symbols.end();) {
281 auto nk = i->first;
282 v.visit(nk, name);
283 if (!nk && i->first) {
284 i = symbols.erase(i);
285 } else if (nk == i->first) {
286 v.visit(i->second);
287 if (i->second) {
288 ++i;
289 } else {
290 i = symbols.erase(i);
291 }
292 } else {
293 auto nv = i->second;
294 v.visit(nv, name);
295 if (nv) new_symbols.emplace(nk, nv);
296 i = symbols.erase(i);
297 }
298 }
299 symbols.insert(new_symbols.begin(), new_symbols.end());
300}
301template <class KEY, class VALUE,
302 template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
303 class COMP /*= std::less<cstring>*/,
304 class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
305void IR::NodeMap<KEY, VALUE, MAP, COMP, ALLOC>::visit_children(Visitor &v, const char *name) const {
306 for (auto &k : symbols) {
307 v.visit(k.first, name);
308 v.visit(k.second, name);
309 }
310}
311
312} // namespace P4
313
314#endif /* IR_IR_INLINE_H_ */
Definition visitor.h:75
The namespace encapsulating IR node classes.
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24