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