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