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) {
84 for (auto i = vec.begin(); i != vec.end();) {
85 const IR::Node *n = v.apply_visitor(*i);
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 {
128 for (auto &a : vec) v.visit(a);
129}
130template <class T>
131void IR::Vector<T>::parallel_visit_children(Visitor &v) {
132 SplitFlowVisitVector<T>(v, *this).run_visit();
133}
134template <class T>
135void IR::Vector<T>::parallel_visit_children(Visitor &v) 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 const char *sep = "";
142 Node::toJSON(json);
143 json << "," << std::endl << json.indent++ << "\"vec\" : [";
144 for (auto &k : vec) {
145 json << sep << std::endl << json.indent << k;
146 sep = ",";
147 }
148 --json.indent;
149 if (*sep) {
150 json << std::endl << json.indent;
151 }
152 json << "]";
153}
154
155std::ostream &operator<<(std::ostream &out, const IR::Vector<IR::Expression> &v);
156std::ostream &operator<<(std::ostream &out, const IR::Vector<IR::Annotation> &v);
157
158template <class T>
159void IR::IndexedVector<T>::visit_children(Visitor &v) {
160 for (auto i = begin(); i != end();) {
161 auto n = v.apply_visitor(*i);
162 if (!n && *i) {
163 i = erase(i);
164 continue;
165 }
166 CHECK_NULL(n);
167 if (n == *i) {
168 i++;
169 continue;
170 }
171 if (auto l = n->template to<Vector<T>>()) {
172 i = erase(i);
173 i = insert(i, l->begin(), l->end());
174 i += l->Vector<T>::size();
175 continue;
176 }
177 if (auto e = n->template to<T>()) {
178 i = replace(i, e);
179 continue;
180 }
181 BUG("visitor returned invalid type %s for IndexedVector<%s>", n->node_type_name(),
182 T::static_type_name());
183 }
184}
185template <class T>
186void IR::IndexedVector<T>::visit_children(Visitor &v) const {
187 for (auto &a : *this) v.visit(a);
188}
189template <class T>
190void IR::IndexedVector<T>::toJSON(JSONGenerator &json) const {
191 const char *sep = "";
192 Vector<T>::toJSON(json);
193 json << "," << std::endl << json.indent++ << "\"declarations\" : {";
194 for (const auto &k : declarations) {
195 json << sep << std::endl << json.indent << k.first << " : " << k.second;
196 sep = ",";
197 }
198 --json.indent;
199 if (*sep != 0) {
200 json << std::endl << json.indent;
201 }
202 json << "}";
203}
204IRNODE_DEFINE_APPLY_OVERLOAD(IndexedVector, template <class T>, <T>)
205
206template <class MAP>
207static inline void namemap_insert_helper(typename MAP::iterator, typename MAP::key_type k,
208 typename MAP::mapped_type v, MAP &, MAP &new_symbols) {
209 new_symbols.emplace(std::move(k), std::move(v));
210}
211
212template <class MAP, class InputIterator>
213static inline void namemap_insert_helper(typename MAP::iterator, InputIterator b, InputIterator e,
214 MAP &, MAP &new_symbols) {
215 new_symbols.insert(b, e);
216}
217
218template <class T>
219static inline void namemap_insert_helper(typename ordered_map<cstring, T>::iterator it, cstring k,
220 T v, ordered_map<cstring, T> &symbols,
221 ordered_map<cstring, T> &) {
222 symbols.emplace_hint(it, std::move(k), std::move(v));
223}
224
225template <class T, class InputIterator>
226static inline void namemap_insert_helper(typename ordered_map<cstring, T>::iterator it,
227 InputIterator b, InputIterator e,
228 ordered_map<cstring, T> &symbols,
229 ordered_map<cstring, T> &) {
230 symbols.insert(it, b, e);
231}
232
233template <class T, template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
234 class COMP /*= std::less<cstring>*/,
235 class ALLOC /*= std::allocator<std::pair<const cstring, const T*>>*/>
236void IR::NameMap<T, MAP, COMP, ALLOC>::visit_children(Visitor &v) {
237 map_t new_symbols;
238 for (auto i = symbols.begin(); i != symbols.end();) {
239 const IR::Node *n = v.apply_visitor(i->second, i->first.c_str());
240 if (!n && i->second) {
241 i = symbols.erase(i);
242 continue;
243 }
244 CHECK_NULL(n);
245 if (n == i->second) {
246 i++;
247 continue;
248 }
249 if (auto m = n->to<NameMap>()) {
250 namemap_insert_helper(i, m->symbols.begin(), m->symbols.end(), symbols, new_symbols);
251 i = symbols.erase(i);
252 continue;
253 }
254 if (auto s = n->to<T>()) {
255 if (match_name(i->first, s)) {
256 i->second = s;
257 i++;
258 } else {
259 namemap_insert_helper(i, cstring(obj_name(s)), std::move(s), symbols, new_symbols);
260 i = symbols.erase(i);
261 }
262 continue;
263 }
264 BUG("visitor returned invalid type %s for NameMap<%s>", n->node_type_name(),
265 T::static_type_name());
266 }
267 symbols.insert(new_symbols.begin(), new_symbols.end());
268}
269template <class T, template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
270 class COMP /*= std::less<cstring>*/,
271 class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
272void IR::NameMap<T, MAP, COMP, ALLOC>::visit_children(Visitor &v) const {
273 for (auto &k : symbols) {
274 v.visit(k.second, k.first.c_str());
275 }
276}
277template <class T, template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
278 class COMP /*= std::less<cstring>*/,
279 class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
280void IR::NameMap<T, MAP, COMP, ALLOC>::toJSON(JSONGenerator &json) const {
281 const char *sep = "";
282 Node::toJSON(json);
283 json << "," << std::endl << json.indent++ << "\"symbols\" : {";
284 for (auto &k : symbols) {
285 json << sep << std::endl << json.indent << k.first << " : " << k.second;
286 sep = ",";
287 }
288 --json.indent;
289 if (*sep) {
290 json << std::endl << json.indent;
291 }
292 json << "}";
293}
294
295template <class KEY, class VALUE,
296 template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
297 class COMP /*= std::less<cstring>*/,
298 class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
299void IR::NodeMap<KEY, VALUE, MAP, COMP, ALLOC>::visit_children(Visitor &v) {
300 map_t new_symbols;
301 for (auto i = symbols.begin(); i != symbols.end();) {
302 auto nk = i->first;
303 v.visit(nk);
304 if (!nk && i->first) {
305 i = symbols.erase(i);
306 } else if (nk == i->first) {
307 v.visit(i->second);
308 if (i->second) {
309 ++i;
310 } else {
311 i = symbols.erase(i);
312 }
313 } else {
314 auto nv = i->second;
315 v.visit(nv);
316 if (nv) new_symbols.emplace(nk, nv);
317 i = symbols.erase(i);
318 }
319 }
320 symbols.insert(new_symbols.begin(), new_symbols.end());
321}
322template <class KEY, class VALUE,
323 template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
324 class COMP /*= std::less<cstring>*/,
325 class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
326void IR::NodeMap<KEY, VALUE, MAP, COMP, ALLOC>::visit_children(Visitor &v) const {
327 for (auto &k : symbols) {
328 v.visit(k.first);
329 v.visit(k.second);
330 }
331}
332
333} // namespace P4
334
335#endif /* IR_IR_INLINE_H_ */
The namespace encapsulating IR node classes.
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24