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