P4C
The P4 Compiler
Loading...
Searching...
No Matches
ir/vector.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_VECTOR_H_
9#define IR_VECTOR_H_
10
11#include "ir/node.h"
12#include "lib/enumerator.h"
13#include "lib/indent.h"
14#include "lib/null.h"
15#include "lib/safe_vector.h"
16
17namespace P4 {
18class JSONLoader;
19} // namespace P4
20
21namespace P4::IR {
22
23// Specialization of vector which
24// - only stores const IR::Node* objects inside (T should derive from Node)
25// - inherits from IR::Node itself
26class VectorBase : public Node {
27 public:
28 typedef const Node *const *iterator;
29 virtual iterator VectorBase_begin() const = 0;
30 virtual iterator VectorBase_end() const = 0;
31 virtual size_t size() const = 0;
32 virtual bool empty() const = 0;
33 iterator begin() const { return VectorBase_begin(); }
34 iterator end() const { return VectorBase_end(); }
35 VectorBase() = default;
36 VectorBase(const VectorBase &) = default;
37 VectorBase(VectorBase &&) = default;
38 VectorBase &operator=(const VectorBase &) = default;
39 VectorBase &operator=(VectorBase &&) = default;
40
41 protected:
42 explicit VectorBase(JSONLoader &json) : Node(json) {}
43
44 DECLARE_TYPEINFO_WITH_TYPEID(VectorBase, NodeKind::VectorBase, Node);
45};
46
47// This class should only be used in the IR.
48// User-level code should use regular std::vector
49template <class T>
50class Vector : public VectorBase {
52
53 public:
54 typedef const T *value_type;
55 Vector() = default;
56 Vector(const Vector &) = default;
57 Vector(Vector &&) = default;
58 explicit Vector(JSONLoader &json);
59 Vector &operator=(const Vector &) = default;
60 Vector &operator=(Vector &&) = default;
61 explicit Vector(const T *a) { vec.emplace_back(a); }
62 explicit Vector(const safe_vector<const T *> &a) { vec.insert(vec.end(), a.begin(), a.end()); }
63 Vector(std::initializer_list<const T *> a) : vec(a) {}
64 template <class InputIt>
65 Vector(InputIt first, InputIt last) : vec(first, last) {}
66 Vector(Util::Enumerator<const T *> *e) // NOLINT(runtime/explicit)
67 : vec(e->begin(), e->end()) {}
68 static Node *fromJSON(JSONLoader &json);
69
70 using iterator = typename safe_vector<const T *>::iterator;
71 using const_iterator = typename safe_vector<const T *>::const_iterator;
72
73 iterator begin() { return vec.begin(); }
74 const_iterator begin() const { return vec.begin(); }
75 VectorBase::iterator VectorBase_begin() const override {
76 /* DANGER -- works as long as IR::Node is the first ultimate base class of T */
77 return reinterpret_cast<VectorBase::iterator>(&vec[0]);
78 }
79 iterator end() { return vec.end(); }
80 const_iterator end() const { return vec.end(); }
81 VectorBase::iterator VectorBase_end() const override {
82 /* DANGER -- works as long as IR::Node is the first ultimate base class of T */
83 return reinterpret_cast<VectorBase::iterator>(&vec[0] + vec.size());
84 }
85 std::reverse_iterator<iterator> rbegin() { return vec.rbegin(); }
86 std::reverse_iterator<const_iterator> rbegin() const { return vec.rbegin(); }
87 std::reverse_iterator<iterator> rend() { return vec.rend(); }
88 std::reverse_iterator<const_iterator> rend() const { return vec.rend(); }
89 size_t size() const override { return vec.size(); }
90 void resize(size_t sz) { vec.resize(sz); }
91 bool empty() const override { return vec.empty(); }
92 const T *const &front() const { return vec.front(); }
93 const T *&front() { return vec.front(); }
94 void clear() { vec.clear(); }
95 iterator erase(iterator i) { return vec.erase(i); }
96 iterator erase(iterator s, iterator e) { return vec.erase(s, e); }
97 template <typename ForwardIter>
98 iterator insert(iterator i, ForwardIter b, ForwardIter e) {
99 return vec.insert(i, b, e);
100 }
101
102 template <typename Container>
103 iterator append(const Container &toAppend) {
104 return insert(end(), toAppend.begin(), toAppend.end());
105 }
106 template <typename Container>
107 iterator prepend(const Container &toAppend) {
108 return insert(begin(), toAppend.begin(), toAppend.end());
109 }
110
117 void pushBackOrAppend(const IR::Node *item) {
118 if (item == nullptr) return;
119 if (auto *itemAsVector = item->to<IR::Vector<T>>()) {
120 append(*itemAsVector);
121 return;
122 }
123 BUG_CHECK(item->is<T>(), "Unexpected vector element: %1%", item);
124 push_back(item->to<T>());
125 }
126
127 iterator insert(iterator i, const T *v) { return vec.insert(i, v); }
128 iterator insert(iterator i, size_t n, const T *v) { return vec.insert(i, n, v); }
129
130 const T *const &operator[](size_t idx) const { return vec[idx]; }
131 const T *&operator[](size_t idx) { return vec[idx]; }
132 const T *const &at(size_t idx) const { return vec.at(idx); }
133 const T *&at(size_t idx) { return vec.at(idx); }
134 template <class... Args>
135 void emplace_back(Args &&...args) {
136 vec.emplace_back(new T(std::forward<Args>(args)...));
137 }
138 void push_back(T *a) { vec.push_back(a); }
139 void push_back(const T *a) { vec.push_back(a); }
140 void pop_back() { vec.pop_back(); }
141 const T *const &back() const { return vec.back(); }
142 const T *&back() { return vec.back(); }
143 template <class U>
144 void push_back(U &a) {
145 vec.push_back(a);
146 }
147 void check_null() const {
148 for (auto e : vec) CHECK_NULL(e);
149 }
150
151 IRNODE_SUBCLASS(Vector)
152 IRNODE_DECLARE_APPLY_OVERLOAD(Vector)
153 bool operator==(const Node &a) const override { return a == *this; }
154 bool operator==(const Vector &a) const override { return vec == a.vec; }
155 /* DANGER -- if you get an error on the above line
156 * operator== ... marked ‘override’, but does not override
157 * that mean you're trying to create an instantiation of IR::Vector that
158 * does not appear anywhere in any .def file, which won't work.
159 * To make double-dispatch comparisons work, the IR generator must know
160 * about ALL instantiations of IR class templates, which it does by scanning
161 * all the .def files for instantiations. This could in theory be fixed by
162 * having the IR generator scan all C++ header and source files for
163 * instantiations, but that is currently not done.
164 *
165 * To avoid this problem, you need to have your code ONLY use instantiations
166 * of IR::Vector that appear somewhere in a .def file -- you can usually make
167 * it work by using an instantiation with an (abstract) base class rather
168 * than a concrete class, as most of those appear in .def files. */
169 bool equiv(const Node &a_) const override {
170 if (static_cast<const Node *>(this) == &a_) return true;
171 if (this->typeId() != a_.typeId()) return false;
172 auto &a = static_cast<const Vector<T> &>(a_);
173 if (size() != a.size()) return false;
174 auto it = a.begin();
175 for (auto *el : *this)
176 if (!el->equiv(**it++)) return false;
177 return true;
178 }
179 cstring node_type_name() const override { return "Vector<" + T::static_type_name() + ">"; }
180 static cstring static_type_name() { return "Vector<" + T::static_type_name() + ">"; }
181 void visit_children(Visitor &v, const char *name) override;
182 void visit_children(Visitor &v, const char *name) const override;
183 virtual void parallel_visit_children(Visitor &v, const char *name = nullptr);
184 virtual void parallel_visit_children(Visitor &v, const char *name = nullptr) const;
185 void toJSON(JSONGenerator &json) const override;
186 Util::Enumerator<const T *> *getEnumerator() const { return Util::enumerate(vec); }
187 template <typename S>
188 Util::Enumerator<const S *> *only() const {
189 return getEnumerator()->template as<const S *>()->where(
190 [](const T *d) { return d != nullptr; });
191 }
192 template <class Filter>
193 auto where(Filter f) const {
194 return getEnumerator()->where(std::move(f));
195 }
196
197 void dbprint(std::ostream &out) const override {
198 out << "{" << IndentCtl::indent;
199 for (auto p : *this) {
200 out << " " << p;
201 }
202 out << IndentCtl::unindent << " }";
203 }
204
205 DECLARE_TYPEINFO_WITH_DISCRIMINATOR(Vector<T>, NodeDiscriminator::VectorT, T, VectorBase);
206};
207
208template <class T, class U>
209const T *get(const IR::Vector<T> &vec, U name) {
210 for (auto el : vec)
211 if (el->name == name) return el;
212 return nullptr;
213}
214template <class T, class U>
215const T *get(const IR::Vector<T> *vec, U name) {
216 if (vec)
217 for (auto el : *vec)
218 if (el->name == name) return el;
219 return nullptr;
220}
221
222} // namespace P4::IR
223
224#endif /* IR_VECTOR_H_ */
const T & as() const
Tries to convert the class to type T. A BUG occurs if the cast fails.
Definition castable.h:33
Definition node.h:44
Definition ir/vector.h:50
void pushBackOrAppend(const IR::Node *item)
Definition ir/vector.h:117
Definition json_loader.h:32
Type-erased Enumerator interface.
Definition enumerator.h:60
Definition safe_vector.h:18
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
T * to() noexcept
Definition rtti.h:226
bool is() const noexcept
Definition rtti.h:216
virtual TypeId typeId() const noexcept=0