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