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