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(std::move(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 typedef typename Vector<T>::iterator iterator;
96
97 const IDeclaration *getDeclaration(cstring name) const {
98 auto it = declarations.find(name);
99 if (it == declarations.end()) return nullptr;
100 return it->second;
101 }
102 const IDeclaration *getDeclaration(std::string_view name) const {
103 auto it = declarations.find(name);
104 if (it == declarations.end()) return nullptr;
105 return it->second;
106 }
107 template <class U>
108 const U *getDeclaration(cstring name) const {
109 auto it = declarations.find(name);
110 if (it == declarations.end()) return nullptr;
111 return it->second->template to<U>();
112 }
113 template <class U>
114 const U *getDeclaration(std::string_view name) const {
115 auto it = declarations.find(name);
116 if (it == declarations.end()) return nullptr;
117 return it->second->template to<U>();
118 }
119 Util::Enumerator<const IDeclaration *> *getDeclarations() const {
120 return Util::enumerate(Values(declarations));
121 }
122 iterator erase(iterator from, iterator to) {
123 for (auto it = from; it != to; ++it) {
124 removeFromMap(*it);
125 }
126 return Vector<T>::erase(from, to);
127 }
128 iterator erase(iterator i) {
129 removeFromMap(*i);
130 return Vector<T>::erase(i);
131 }
132 template <typename ForwardIter>
133 iterator insert(iterator i, ForwardIter b, ForwardIter e) {
134 for (auto it = b; it != e; ++it) insertInMap(*it);
135 return Vector<T>::insert(i, b, e);
136 }
137 iterator replace(iterator i, const T *v) {
138 removeFromMap(*i);
139 *i = v;
140 insertInMap(v);
141 return ++i;
142 }
143 template <typename Container>
144 iterator append(const Container &toAppend) {
145 return insert(Vector<T>::end(), toAppend.begin(), toAppend.end());
146 }
147 template <typename Container>
148 iterator prepend(const Container &toAppend) {
149 return insert(Vector<T>::begin(), toAppend.begin(), toAppend.end());
150 }
151 iterator insert(iterator i, const T *v) {
152 insertInMap(v);
153 return Vector<T>::insert(i, v);
154 }
155 template <class... Args>
156 void emplace_back(Args &&...args) {
157 auto el = new T(std::forward<Args>(args)...);
158 push_back(el);
159 }
160 bool removeByName(cstring name) {
161 for (auto it = begin(); it != end(); ++it) {
162 auto decl = (*it)->template to<IDeclaration>();
163 if (decl != nullptr && decl->getName() == name) {
164 erase(it);
165 return true;
166 }
167 }
168 return false;
169 }
170 void push_back(T *a) {
171 CHECK_NULL(a);
172 Vector<T>::push_back(a);
173 insertInMap(a);
174 }
175 void push_back(const T *a) {
176 CHECK_NULL(a);
177 Vector<T>::push_back(a);
178 insertInMap(a);
179 }
180 void pop_back() {
181 if (Vector<T>::empty()) BUG("pop_back from empty IndexedVector");
182 auto last = Vector<T>::back();
183 removeFromMap(last);
184 Vector<T>::pop_back();
185 }
186 template <class U>
187 void push_back(U &a) {
188 Vector<T>::push_back(a);
189 insertInMap(a);
190 }
191
192 IRNODE_SUBCLASS(IndexedVector)
193 IRNODE_DECLARE_APPLY_OVERLOAD(IndexedVector)
194 bool operator==(const Node &a) const override { return a == *this; }
195 bool operator==(const Vector<T> &a) const override { return a == *this; }
196 bool operator==(const IndexedVector &a) const override {
197 return Vector<T>::operator==(static_cast<const Vector<T> &>(a));
198 }
199 /* DANGER -- if you get an error on one of the above lines
200 * operator== ... marked ‘override’, but does not override
201 * that mean you're trying to create an instantiation of IR::IndexedVector
202 * that does not appear anywhere in any .def file, which won't work.
203 * To make double-dispatch comparisons work, the IR generator must know
204 * about ALL instantiations of IR class templates, which it does by scanning
205 * all the .def files for instantiations. This could in theory be fixed by
206 * having the IR generator scan all C++ header and source files for
207 * instantiations, but that is currently not done.
208 *
209 * To avoid this problem, you need to have your code ONLY use instantiations
210 * of IR::IndexedVector that appear somewhere in a .def file -- you can usually
211 * make it work by using an instantiation with an (abstract) base class rather
212 * than a concrete class, as most of those appear in .def files. */
213
214 cstring node_type_name() const override {
215 return "IndexedVector<" + T::static_type_name() + ">";
216 }
217 static cstring static_type_name() { return "IndexedVector<" + T::static_type_name() + ">"; }
218 void visit_children(Visitor &v) override;
219 void visit_children(Visitor &v) const override;
220
221 void toJSON(JSONGenerator &json) const override;
222 static IndexedVector<T> *fromJSON(JSONLoader &json);
223 void validate() const override {
224 if (invalid) return; // don't crash the compiler because an error happened
225 for (auto el : *this) {
226 auto decl = el->template to<IR::IDeclaration>();
227 if (!decl) continue;
228 auto it = declarations.find(decl->getName());
229 BUG_CHECK(it != declarations.end() && it->second->getNode() == el->getNode(),
230 "invalid element %1%", el);
231 }
232 }
233
234 DECLARE_TYPEINFO_WITH_DISCRIMINATOR(IndexedVector<T>, NodeDiscriminator::IndexedVectorT, T,
235 Vector<T>);
236};
237
238} // namespace P4::IR
239
240#endif /* IR_INDEXED_VECTOR_H_ */
The Declaration interface, representing objects with names.
Definition declaration.h:26
Definition node.h:94
Definition json_generator.h:37
Definition json_loader.h:39
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