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(const std::initializer_list<const T *> &a) : vec(a) {}
73 static Vector<T> *fromJSON(JSONLoader &json);
74 typedef typename safe_vector<const T *>::iterator iterator;
75 typedef typename safe_vector<const T *>::const_iterator const_iterator;
76 iterator begin() { return vec.begin(); }
77 const_iterator begin() const { return vec.begin(); }
78 VectorBase::iterator VectorBase_begin() const override {
79 /* DANGER -- works as long as IR::Node is the first ultimate base class of T */
80 return reinterpret_cast<VectorBase::iterator>(&vec[0]);
81 }
82 iterator end() { return vec.end(); }
83 const_iterator end() const { return vec.end(); }
84 VectorBase::iterator VectorBase_end() const override {
85 /* DANGER -- works as long as IR::Node is the first ultimate base class of T */
86 return reinterpret_cast<VectorBase::iterator>(&vec[0] + vec.size());
87 }
88 std::reverse_iterator<iterator> rbegin() { return vec.rbegin(); }
89 std::reverse_iterator<const_iterator> rbegin() const { return vec.rbegin(); }
90 std::reverse_iterator<iterator> rend() { return vec.rend(); }
91 std::reverse_iterator<const_iterator> rend() const { return vec.rend(); }
92 size_t size() const override { return vec.size(); }
93 void resize(size_t sz) { vec.resize(sz); }
94 bool empty() const override { return vec.empty(); }
95 const T *const &front() const { return vec.front(); }
96 const T *&front() { return vec.front(); }
97 void clear() { vec.clear(); }
98 iterator erase(iterator i) { return vec.erase(i); }
99 iterator erase(iterator s, iterator e) { return vec.erase(s, e); }
100 template <typename ForwardIter>
101 iterator insert(iterator i, ForwardIter b, ForwardIter e) {
102 /* FIXME -- GCC prior to 4.9 is broken and the insert routine returns void
103 * FIXME -- rather than an iterator. So we recalculate it from an index */
104 int index = i - vec.begin();
105 vec.insert(i, b, e);
106 return vec.begin() + index;
107 }
108
109 template <typename Container>
110 iterator append(const Container &toAppend) {
111 return insert(end(), toAppend.begin(), toAppend.end());
112 }
113 template <typename Container>
114 iterator prepend(const Container &toAppend) {
115 return insert(begin(), toAppend.begin(), toAppend.end());
116 }
117
124 void pushBackOrAppend(const IR::Node *item) {
125 if (item == nullptr) return;
126 if (auto *itemAsVector = item->to<IR::Vector<T>>()) {
127 append(*itemAsVector);
128 return;
129 }
130 BUG_CHECK(item->is<T>(), "Unexpected vector element: %1%", item);
131 push_back(item->to<T>());
132 }
133
134 iterator insert(iterator i, const T *v) {
135 /* FIXME -- GCC prior to 4.9 is broken and the insert routine returns void
136 * FIXME -- rather than an iterator. So we recalculate it from an index */
137 int index = i - vec.begin();
138 vec.insert(i, v);
139 return vec.begin() + index;
140 }
141 iterator insert(iterator i, size_t n, const T *v) {
142 /* FIXME -- GCC prior to 4.9 is broken and the insert routine returns void
143 * FIXME -- rather than an iterator. So we recalculate it from an index */
144 int index = i - vec.begin();
145 vec.insert(i, n, v);
146 return vec.begin() + index;
147 }
148
149 const T *const &operator[](size_t idx) const { return vec[idx]; }
150 const T *&operator[](size_t idx) { return vec[idx]; }
151 const T *const &at(size_t idx) const { return vec.at(idx); }
152 const T *&at(size_t idx) { return vec.at(idx); }
153 template <class... Args>
154 void emplace_back(Args &&...args) {
155 vec.emplace_back(new T(std::forward<Args>(args)...));
156 }
157 void push_back(T *a) { vec.push_back(a); }
158 void push_back(const T *a) { vec.push_back(a); }
159 void pop_back() { vec.pop_back(); }
160 const T *const &back() const { return vec.back(); }
161 const T *&back() { return vec.back(); }
162 template <class U>
163 void push_back(U &a) {
164 vec.push_back(a);
165 }
166 void check_null() const {
167 for (auto e : vec) CHECK_NULL(e);
168 }
169
170 IRNODE_SUBCLASS(Vector)
171 IRNODE_DECLARE_APPLY_OVERLOAD(Vector)
172 bool operator==(const Node &a) const override { return a == *this; }
173 bool operator==(const Vector &a) const override { return vec == a.vec; }
174 /* DANGER -- if you get an error on the above line
175 * operator== ... marked ‘override’, but does not override
176 * that mean you're trying to create an instantiation of IR::Vector that
177 * does not appear anywhere in any .def file, which won't work.
178 * To make double-dispatch comparisons work, the IR generator must know
179 * about ALL instantiations of IR class templates, which it does by scanning
180 * all the .def files for instantiations. This could in theory be fixed by
181 * having the IR generator scan all C++ header and source files for
182 * instantiations, but that is currently not done.
183 *
184 * To avoid this problem, you need to have your code ONLY use instantiations
185 * of IR::Vector that appear somewhere in a .def file -- you can usually make
186 * it work by using an instantiation with an (abstract) base class rather
187 * than a concrete class, as most of those appear in .def files. */
188 bool equiv(const Node &a_) const override {
189 if (static_cast<const Node *>(this) == &a_) return true;
190 if (this->typeId() != a_.typeId()) return false;
191 auto &a = static_cast<const Vector<T> &>(a_);
192 if (size() != a.size()) return false;
193 auto it = a.begin();
194 for (auto *el : *this)
195 if (!el->equiv(**it++)) return false;
196 return true;
197 }
198 cstring node_type_name() const override { return "Vector<" + T::static_type_name() + ">"; }
199 static cstring static_type_name() { return "Vector<" + T::static_type_name() + ">"; }
200 void visit_children(Visitor &v) override;
201 void visit_children(Visitor &v) const override;
202 virtual void parallel_visit_children(Visitor &v);
203 virtual void parallel_visit_children(Visitor &v) const;
204 void toJSON(JSONGenerator &json) const override;
205 Util::Enumerator<const T *> *getEnumerator() const { return Util::enumerate(vec); }
206 template <typename S>
207 Util::Enumerator<const S *> *only() const {
208 return getEnumerator()->template as<const S *>()->where(
209 [](const T *d) { return d != nullptr; });
210 }
211
212 void dbprint(std::ostream &out) const override {
213 out << "{" << IndentCtl::indent;
214 for (auto p : *this) {
215 out << " " << p;
216 }
217 out << IndentCtl::unindent << " }";
218 }
219
220 DECLARE_TYPEINFO_WITH_DISCRIMINATOR(Vector<T>, NodeDiscriminator::VectorT, T, VectorBase);
221};
222
223} // namespace P4::IR
224
225// XXX(seth): We use this namespace to hide our get() overloads from ADL. GCC
226// 4.8 has a bug which causes these overloads to be considered when get() is
227// called on a type in the global namespace, even if the number of arguments
228// doesn't match up, which can trigger template instantiations that cause
229// errors.
230namespace P4 {
231namespace GetImpl {
232
233template <class T, class U>
234const T *get(const IR::Vector<T> &vec, U name) {
235 for (auto el : vec)
236 if (el->name == name) return el;
237 return nullptr;
238}
239template <class T, class U>
240const T *get(const IR::Vector<T> *vec, U name) {
241 if (vec)
242 for (auto el : *vec)
243 if (el->name == name) return el;
244 return nullptr;
245}
246
247} // namespace GetImpl
248using namespace GetImpl; // NOLINT(build/namespaces)
249
250} // namespace P4
251
252#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:95
Definition vector.h:35
Definition vector.h:59
void pushBackOrAppend(const IR::Node *item)
Definition vector.h:124
Definition json_loader.h:38
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