P4C
The P4 Compiler
Loading...
Searching...
No Matches
indexed_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_INDEXED_VECTOR_H_
18#define IR_INDEXED_VECTOR_H_
19
20#include "ir/declaration.h"
21#include "ir/vector.h"
22#include "lib/enumerator.h"
23#include "lib/error.h"
24#include "lib/map.h"
25#include "lib/null.h"
26#include "lib/safe_vector.h"
27#include "lib/string_map.h"
28
29namespace P4 {
30class JSONLoader;
31} // namespace P4
32
33namespace P4::IR {
34
39template <class T>
40class IndexedVector : public Vector<T> {
42 bool invalid = false; // set when an error occurs; then we don't
43 // expect the validity check to succeed.
44
45 void insertInMap(const T *a) {
46 if (a == nullptr || !a->template is<IDeclaration>()) return;
47 auto decl = a->template to<IDeclaration>();
48 auto name = decl->getName().name;
49 auto [it, inserted] = declarations.emplace(name, decl);
50 if (!inserted) {
51 invalid = true;
52 ::P4::error(ErrorType::ERR_DUPLICATE, "%1%: Duplicates declaration %2%", a, it->second);
53 }
54 }
55 void removeFromMap(const T *a) {
56 if (a == nullptr) return;
57 auto decl = a->template to<IDeclaration>();
58 if (decl == nullptr) return;
59 cstring name = decl->getName().name;
60 auto it = declarations.find(name);
61 if (it == declarations.end()) BUG("%1% does not exist", a);
62 declarations.erase(it);
63 }
64
65 public:
66 using Vector<T>::begin;
67 using Vector<T>::end;
68
69 IndexedVector() = default;
70 IndexedVector(const IndexedVector &) = default;
71 IndexedVector(IndexedVector &&) = default;
72 IndexedVector(std::initializer_list<const T *> a) : Vector<T>(a) {
73 for (auto el : *this) insertInMap(el);
74 }
75 IndexedVector &operator=(const IndexedVector &) = default;
76 IndexedVector &operator=(IndexedVector &&) = default;
77 explicit IndexedVector(const T *a) { push_back(a); }
78 explicit IndexedVector(const safe_vector<const T *> &a) {
79 insert(Vector<T>::end(), a.begin(), a.end());
80 }
81 explicit IndexedVector(const Vector<T> &a) { insert(Vector<T>::end(), a.begin(), a.end()); }
82 template <typename It>
83 explicit IndexedVector(It start, It end) {
84 insert(Vector<T>::end(), start, end);
85 }
86 explicit IndexedVector(JSONLoader &json);
87
88 void clear() {
89 IR::Vector<T>::clear();
90 declarations.clear();
91 }
92 // TODO: Although this is not a const_iterator, it should NOT
93 // be used to modify the vector directly. I don't know
94 // how to enforce this property, though.
95 using iterator = typename Vector<T>::iterator;
96 using const_iterator = typename Vector<T>::const_iterator;
97
98 const IDeclaration *getDeclaration(cstring name) const {
99 auto it = declarations.find(name);
100 if (it == declarations.end()) return nullptr;
101 return it->second;
102 }
103 const IDeclaration *getDeclaration(std::string_view name) const {
104 auto it = declarations.find(name);
105 if (it == declarations.end()) return nullptr;
106 return it->second;
107 }
108 template <class U>
109 const U *getDeclaration(cstring name) const {
110 auto it = declarations.find(name);
111 if (it == declarations.end()) return nullptr;
112 return it->second->template to<U>();
113 }
114 template <class U>
115 const U *getDeclaration(std::string_view name) const {
116 auto it = declarations.find(name);
117 if (it == declarations.end()) return nullptr;
118 return it->second->template to<U>();
119 }
120 Util::Enumerator<const IDeclaration *> *getDeclarations() const {
121 return Util::enumerate(Values(declarations));
122 }
123 iterator erase(iterator from, iterator to) {
124 for (auto it = from; it != to; ++it) {
125 removeFromMap(*it);
126 }
127 return Vector<T>::erase(from, to);
128 }
129 iterator erase(iterator i) {
130 removeFromMap(*i);
131 return Vector<T>::erase(i);
132 }
133 template <typename ForwardIter>
134 iterator insert(iterator i, ForwardIter b, ForwardIter e) {
135 for (auto it = b; it != e; ++it) insertInMap(*it);
136 return Vector<T>::insert(i, b, e);
137 }
138 iterator replace(iterator i, const T *v) {
139 removeFromMap(*i);
140 *i = v;
141 insertInMap(v);
142 return ++i;
143 }
144 template <typename Container>
145 iterator append(const Container &toAppend) {
146 return insert(Vector<T>::end(), toAppend.begin(), toAppend.end());
147 }
148 template <typename Container>
149 iterator prepend(const Container &toAppend) {
150 return insert(Vector<T>::begin(), toAppend.begin(), toAppend.end());
151 }
152 iterator insert(iterator i, const T *v) {
153 insertInMap(v);
154 return Vector<T>::insert(i, v);
155 }
156 template <class... Args>
157 void emplace_back(Args &&...args) {
158 auto el = new T(std::forward<Args>(args)...);
159 push_back(el);
160 }
161 bool removeByName(cstring name) {
162 for (auto it = begin(); it != end(); ++it) {
163 auto decl = (*it)->template to<IDeclaration>();
164 if (decl != nullptr && decl->getName() == name) {
165 erase(it);
166 return true;
167 }
168 }
169 return false;
170 }
171 void push_back(T *a) {
172 CHECK_NULL(a);
173 Vector<T>::push_back(a);
174 insertInMap(a);
175 }
176 void push_back(const T *a) {
177 CHECK_NULL(a);
178 Vector<T>::push_back(a);
179 insertInMap(a);
180 }
181 void pop_back() {
182 if (Vector<T>::empty()) BUG("pop_back from empty IndexedVector");
183 auto last = Vector<T>::back();
184 removeFromMap(last);
185 Vector<T>::pop_back();
186 }
187 template <class U>
188 void push_back(U &a) {
189 Vector<T>::push_back(a);
190 insertInMap(a);
191 }
192
193 IRNODE_SUBCLASS(IndexedVector)
194 IRNODE_DECLARE_APPLY_OVERLOAD(IndexedVector)
195 bool operator==(const Node &a) const override { return a == *this; }
196 bool operator==(const Vector<T> &a) const override { return a == *this; }
197 bool operator==(const IndexedVector &a) const override {
198 return Vector<T>::operator==(static_cast<const Vector<T> &>(a));
199 }
200 /* DANGER -- if you get an error on one of the above lines
201 * operator== ... marked ‘override’, but does not override
202 * that mean you're trying to create an instantiation of IR::IndexedVector
203 * that does not appear anywhere in any .def file, which won't work.
204 * To make double-dispatch comparisons work, the IR generator must know
205 * about ALL instantiations of IR class templates, which it does by scanning
206 * all the .def files for instantiations. This could in theory be fixed by
207 * having the IR generator scan all C++ header and source files for
208 * instantiations, but that is currently not done.
209 *
210 * To avoid this problem, you need to have your code ONLY use instantiations
211 * of IR::IndexedVector that appear somewhere in a .def file -- you can usually
212 * make it work by using an instantiation with an (abstract) base class rather
213 * than a concrete class, as most of those appear in .def files. */
214
215 cstring node_type_name() const override {
216 return "IndexedVector<" + T::static_type_name() + ">";
217 }
218 static cstring static_type_name() { return "IndexedVector<" + T::static_type_name() + ">"; }
219 void visit_children(Visitor &v, const char *name) override;
220 void visit_children(Visitor &v, const char *name) const override;
221
222 void toJSON(JSONGenerator &json) const override;
223 static IndexedVector<T> *fromJSON(JSONLoader &json);
224 void validate() const override {
225 if (invalid) return; // don't crash the compiler because an error happened
226 for (auto el : *this) {
227 auto decl = el->template to<IR::IDeclaration>();
228 if (!decl) continue;
229 auto it = declarations.find(decl->getName());
230 BUG_CHECK(it != declarations.end() && it->second->getNode() == el->getNode(),
231 "invalid element %1%", el);
232 }
233 }
234
235 DECLARE_TYPEINFO_WITH_DISCRIMINATOR(IndexedVector<T>, NodeDiscriminator::IndexedVectorT, T,
236 Vector<T>);
237};
238
239} // namespace P4::IR
240
241#endif /* IR_INDEXED_VECTOR_H_ */
The Declaration interface, representing objects with names.
Definition declaration.h:26
Definition node.h:94
Definition json_generator.h:39
Definition json_loader.h:40
Type-erased Enumerator interface.
Definition enumerator.h:69
Definition cstring.h:85
Definition safe_vector.h:27
Definition string_map.h:41
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58
T * to() noexcept
Definition rtti.h:226
bool is() const noexcept
Definition rtti.h:216