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