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