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