P4C
The P4 Compiler
Loading...
Searching...
No Matches
frontends/p4/def_use.h
1/*
2Copyright 2016 VMware, 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 FRONTENDS_P4_DEF_USE_H_
18#define FRONTENDS_P4_DEF_USE_H_
19
20#include "absl/container/flat_hash_set.h"
21#include "absl/container/inlined_vector.h"
22#include "frontends/common/resolveReferences/referenceMap.h"
23#include "ir/ir.h"
24#include "lib/alloc_trace.h"
25#include "lib/hash.h"
26#include "lib/hvec_map.h"
27#include "lib/ordered_set.h"
28#include "typeMap.h"
29
30namespace P4 {
31
32class ComputeWriteSet;
33class StorageFactory;
34class LocationSet;
35
36// A location in the program. Includes the context from the visitor, which needs to
37// be copied out of the Visitor::Context objects, as they are allocated on the stack and
38// will become invalid as the IR traversal continues
39struct loc_t {
40 const IR::Node *node;
41 const loc_t *parent;
42 mutable std::size_t computedHash = 0;
43 bool operator==(const loc_t &a) const {
44 if (node != a.node) return false;
45 if (parent == a.parent) return true;
46 if (!parent || !a.parent) return false;
47 return *parent == *a.parent;
48 }
49 std::size_t hash() const;
50};
51
53class StorageLocation : public IHasDbPrint, public ICastable {
54 static unsigned crtid;
55
56 public:
57 virtual ~StorageLocation() {}
58 unsigned id;
59 const IR::Type *type;
60 const cstring name;
61 StorageLocation(const IR::Type *type, cstring name) : id(crtid++), type(type), name(name) {
62 CHECK_NULL(type);
63 }
64 void dbprint(std::ostream &out) const override { out << id << " " << name; }
65 cstring toString() const { return name; }
66
68 const LocationSet *getValidBits() const;
69 virtual void addValidBits(LocationSet *result) const = 0;
71 const LocationSet *removeHeaders() const;
72 virtual void removeHeaders(LocationSet *result) const = 0;
74 const LocationSet *getLastIndexField() const;
75 virtual void addLastIndexField(LocationSet *result) const = 0;
76
77 DECLARE_TYPEINFO(StorageLocation);
78};
79
82class BaseLocation : public StorageLocation {
83 public:
84 BaseLocation(const IR::Type *type, cstring name) : StorageLocation(type, name) {
85 if (auto tt = type->to<IR::Type_Tuple>())
86 BUG_CHECK(tt->getSize() == 0, "%1%: tuples with fields are not base locations", tt);
87 else if (auto ts = type->to<IR::Type_StructLike>())
88 BUG_CHECK(ts->fields.size() == 0, "%1%: structs with fields are not base locations",
89 tt);
90 else
91 BUG_CHECK(type->is<IR::Type_Bits>() || type->is<IR::Type_Enum>() ||
92 type->is<IR::Type_Boolean>() || type->is<IR::Type_Var>() ||
93 type->is<IR::Type_Error>() || type->is<IR::Type_Varbits>() ||
94 type->is<IR::Type_Newtype>() || type->is<IR::Type_SerEnum>() ||
95 type->is<IR::Type_List>(),
96 "%1%: unexpected type", type);
97 }
98 void addValidBits(LocationSet *) const override {}
99 void addLastIndexField(LocationSet *) const override {}
100 void removeHeaders(LocationSet *result) const override;
101
102 DECLARE_TYPEINFO(BaseLocation, StorageLocation);
103};
104
106class WithFieldsLocation : public StorageLocation {
107 protected:
109 friend class StorageFactory;
110 WithFieldsLocation(const IR::Type *type, cstring name) : StorageLocation(type, name) {}
111
112 public:
113 void createField(cstring name, StorageLocation *field) {
114 fieldLocations.emplace(name, field);
115 CHECK_NULL(field);
116 }
117 void replaceField(cstring field, StorageLocation *replacement) {
118 fieldLocations[field] = replacement;
119 }
121 return Values(fieldLocations);
122 }
123 void dbprint(std::ostream &out) const override {
124 for (auto f : fieldLocations) out << *f.second << " ";
125 }
126
127 DECLARE_TYPEINFO(WithFieldsLocation, StorageLocation);
128};
129
131class StructLocation : public WithFieldsLocation {
132 public:
133 StructLocation(const IR::Type *type, cstring name) : WithFieldsLocation(type, name) {
134 BUG_CHECK(type->is<IR::Type_StructLike>(), "%1%: unexpected type", type);
135 }
136 void addField(cstring field, LocationSet *addTo) const;
137 void addValidBits(LocationSet *result) const override;
138 void removeHeaders(LocationSet *result) const override;
139 void addLastIndexField(LocationSet *result) const override;
140 bool isHeader() const { return type->is<IR::Type_Header>(); }
141 bool isHeaderUnion() const { return type->is<IR::Type_HeaderUnion>(); }
142 bool isStruct() const { return type->is<IR::Type_Struct>(); }
143
144 DECLARE_TYPEINFO(StructLocation, WithFieldsLocation);
145};
146
148class IndexedLocation : public StorageLocation {
149 protected:
150 absl::InlinedVector<const StorageLocation *, 8> elements;
151 friend class StorageFactory;
152
153 void createElement(unsigned index, StorageLocation *element) {
154 elements[index] = element;
155 CHECK_NULL(element);
156 }
157
158 public:
159 IndexedLocation(const IR::Type *type, cstring name) : StorageLocation(type, name) {
160 CHECK_NULL(type);
161 auto it = type->to<IR::Type_Indexed>();
162 BUG_CHECK(it != nullptr, "%1%: unexpected type", type);
163 elements.resize(it->getSize());
164 }
165 void addElement(unsigned index, LocationSet *result) const;
166 auto begin() const { return elements.cbegin(); }
167 auto end() const { return elements.cend(); }
168
169 DECLARE_TYPEINFO(IndexedLocation, StorageLocation);
170};
171
173class TupleLocation : public IndexedLocation {
174 public:
175 TupleLocation(const IR::Type *type, cstring name) : IndexedLocation(type, name) {}
176 size_t getSize() const { return elements.size(); }
177 void addValidBits(LocationSet *) const override {}
178 void addLastIndexField(LocationSet *) const override {}
179 void removeHeaders(LocationSet *result) const override;
180
181 DECLARE_TYPEINFO(TupleLocation, IndexedLocation);
182};
183
184class ArrayLocation : public IndexedLocation {
185 const StorageLocation *lastIndexField; // accessed by lastIndex
186 public:
187 ArrayLocation(const IR::Type *type, cstring name)
188 : IndexedLocation(type, name), lastIndexField(nullptr) {}
189 void setLastIndexField(const StorageLocation *location) { lastIndexField = location; }
190 const StorageLocation *getLastIndexField() const { return lastIndexField; }
191 void dbprint(std::ostream &out) const override {
192 for (unsigned i = 0; i < elements.size(); i++) out << *elements.at(i) << " ";
193 }
194 void addValidBits(LocationSet *result) const override;
195 void removeHeaders(LocationSet *) const override {} // no results added
196 void addLastIndexField(LocationSet *result) const override;
197
198 DECLARE_TYPEINFO(ArrayLocation, IndexedLocation);
199};
200
202 public:
203 StorageLocation *create(const IR::Type *type, cstring name) const;
204
205 static const cstring validFieldName;
206 static const cstring indexFieldName;
207};
208
211class LocationSet : public IHasDbPrint {
213
214 public:
215 LocationSet() = default;
216 explicit LocationSet(const ordered_set<const StorageLocation *> &other) : locations(other) {}
217 explicit LocationSet(const StorageLocation *location) {
218 CHECK_NULL(location);
219 locations.emplace(location);
220 }
221 static const LocationSet *empty;
222
223 const LocationSet *getField(cstring field) const;
224 const LocationSet *getValidField() const;
225 const LocationSet *getIndex(unsigned index) const;
226 const LocationSet *allElements() const;
227 const LocationSet *getArrayLastIndex() const;
228
229 void add(const StorageLocation *location) {
230 CHECK_NULL(location);
231 locations.emplace(location);
232 }
233 const LocationSet *join(const LocationSet *other) const;
236 const LocationSet *canonicalize() const;
237 void addCanonical(const StorageLocation *location);
238 ordered_set<const StorageLocation *>::const_iterator begin() const {
239 return locations.cbegin();
240 }
241 ordered_set<const StorageLocation *>::const_iterator end() const { return locations.cend(); }
242 void dbprint(std::ostream &out) const override {
243 if (locations.empty()) out << "LocationSet::empty";
244 for (auto l : locations) {
245 l->dbprint(out);
246 out << " ";
247 }
248 }
249 // only defined for canonical representations
250 bool overlaps(const LocationSet *other) const;
251 bool operator==(const LocationSet &other) const;
252 bool isEmpty() const { return locations.empty(); }
253};
254
256class StorageMap : public IHasDbPrint {
259 StorageFactory factory;
260
261 public:
262 ReferenceMap *refMap;
263 TypeMap *typeMap;
264
265 StorageMap(ReferenceMap *refMap, TypeMap *typeMap) : refMap(refMap), typeMap(typeMap) {
266 CHECK_NULL(refMap);
267 CHECK_NULL(typeMap);
268 }
269 StorageLocation *add(const IR::IDeclaration *decl) {
270 CHECK_NULL(decl);
271 auto type = typeMap->getType(decl->getNode(), true);
272 auto loc = factory.create(type, decl->getName() + "/" + decl->externalName());
273 if (loc != nullptr) storage.emplace(decl, loc);
274 return loc;
275 }
276 StorageLocation *getOrAdd(const IR::IDeclaration *decl) {
277 auto s = getStorage(decl);
278 if (s != nullptr) return s;
279 return add(decl);
280 }
281 StorageLocation *getStorage(const IR::IDeclaration *decl) const {
282 CHECK_NULL(decl);
283 auto result = ::P4::get(storage, decl);
284 return result;
285 }
286 void dbprint(std::ostream &out) const override {
287 for (auto &it : storage) out << it.first << ": " << it.second << Log::endl;
288 }
289};
290
292class ProgramPoint : public IHasDbPrint {
300 absl::InlinedVector<const IR::Node *, 8> stack; // Has inline space for 8 nodes
301
302 public:
303 ProgramPoint() = default;
304 ProgramPoint(const ProgramPoint &other) : stack(other.stack) {}
305 explicit ProgramPoint(const IR::Node *node) {
306 CHECK_NULL(node);
307 assign(node);
308 }
309 ProgramPoint(const ProgramPoint &context, const IR::Node *node);
311 static ProgramPoint beforeStart;
313 ProgramPoint after() { return ProgramPoint(*this, nullptr); }
314 bool operator==(const ProgramPoint &other) const;
315 std::size_t hash() const;
316 void dbprint(std::ostream &out) const override {
317 if (isBeforeStart()) {
318 out << "<BeforeStart>";
319 } else {
320 bool first = true;
321 for (auto n : stack) {
322 if (!first) out << "//";
323 if (!n)
324 out << "After end";
325 else
326 out << dbp(n);
327 first = false;
328 }
329 auto l = stack.back();
330 if (l != nullptr &&
331 (l->is<IR::AssignmentStatement>() || l->is<IR::MethodCallStatement>()))
332 out << "[[" << l << "]]";
333 }
334 }
335 void assign(const ProgramPoint &context, const IR::Node *node);
336 void assign(const IR::Node *node) { stack.assign({node}); }
337 void clear() { stack.clear(); }
338 const IR::Node *last() const { return stack.empty() ? nullptr : stack.back(); }
339 bool isBeforeStart() const { return stack.empty(); }
340 auto begin() const { return stack.begin(); }
341 auto end() const { return stack.end(); }
342 ProgramPoint &operator=(const ProgramPoint &) = default;
343 ProgramPoint &operator=(ProgramPoint &&) = default;
344};
345} // namespace P4
346
347// inject hash into std namespace so it is picked up by std::unordered_set
348namespace std {
349template <>
350struct hash<P4::ProgramPoint> {
351 std::size_t operator()(const P4::ProgramPoint &s) const { return s.hash(); }
352};
353
354template <>
355struct hash<P4::loc_t> {
356 std::size_t operator()(const P4::loc_t &loc) const { return loc.hash(); }
357};
358
359} // namespace std
360
361namespace P4::Util {
362template <>
364 size_t operator()(const P4::ProgramPoint &p) const { return p.hash(); }
365};
366} // namespace P4::Util
367
368namespace P4 {
369class ProgramPoints : public IHasDbPrint {
370 typedef absl::flat_hash_set<ProgramPoint, Util::Hash> Points;
371 Points points;
372 explicit ProgramPoints(const Points &points) : points(points) {}
373
374 public:
375 ProgramPoints() = default;
376 explicit ProgramPoints(ProgramPoint point) { points.emplace(point); }
377 void add(ProgramPoint point) { points.emplace(point); }
378 void add(const ProgramPoints *from);
379 const ProgramPoints *merge(const ProgramPoints *with) const;
380 bool operator==(const ProgramPoints &other) const;
381 void dbprint(std::ostream &out) const override {
382 out << "{";
383 for (auto p : points) out << p << " ";
384 out << "}";
385 }
386 size_t size() const { return points.size(); }
387 bool containsBeforeStart() const {
388 return points.find(ProgramPoint::beforeStart) != points.end();
389 }
390 Points::const_iterator begin() const { return points.cbegin(); }
391 Points::const_iterator end() const { return points.cend(); }
392};
393
395class Definitions : public IHasDbPrint {
400 bool unreachable = false;
401
402 public:
403 Definitions() = default;
404 Definitions(const Definitions &other)
405 : definitions(other.definitions), unreachable(other.unreachable) {}
406 Definitions *joinDefinitions(const Definitions *other) const;
408 Definitions *writes(ProgramPoint point, const LocationSet *locations) const;
409 void setDefintion(const BaseLocation *loc, const ProgramPoints *point) {
410 CHECK_NULL(loc);
411 CHECK_NULL(point);
412 definitions[loc] = point;
413 }
414 void setDefinition(const StorageLocation *loc, const ProgramPoints *point);
415 void setDefinition(const LocationSet *loc, const ProgramPoints *point);
416 Definitions *setUnreachable() {
417 unreachable = true;
418 return this;
419 }
420 bool isUnreachable() const { return unreachable; }
421 bool hasLocation(const BaseLocation *location) const {
422 return definitions.find(location) != definitions.end();
423 }
424 const ProgramPoints *getPoints(const BaseLocation *location) const {
425 auto r = ::P4::get(definitions, location);
426 BUG_CHECK(r != nullptr, "no definitions found for %1%", location);
427 return r;
428 }
429 const ProgramPoints *getPoints(const LocationSet *locations) const;
430 bool operator==(const Definitions &other) const;
431 void dbprint(std::ostream &out) const override {
432 if (unreachable) {
433 out << " Unreachable" << Log::endl;
434 }
435 if (definitions.empty()) out << " Empty definitions";
436 bool first = true;
437 for (auto d : definitions) {
438 if (!first) out << Log::endl;
439 out << " " << *d.first << "=>" << *d.second;
440 first = false;
441 }
442 }
443 Definitions *cloneDefinitions() const { return new Definitions(*this); }
444 void removeLocation(const StorageLocation *loc);
445 bool empty() const { return definitions.empty(); }
446 size_t size() const { return definitions.size(); }
447};
448
449class AllDefinitions : public IHasDbPrint {
455
456 public:
457 StorageMap *storageMap;
458 AllDefinitions(ReferenceMap *refMap, TypeMap *typeMap)
459 : storageMap(new StorageMap(refMap, typeMap)) {}
460 Definitions *getDefinitions(ProgramPoint point, bool emptyIfNotFound = false) {
461 auto it = atPoint.find(point);
462 if (it == atPoint.end()) {
463 if (emptyIfNotFound) {
464 auto defs = new Definitions();
465 setDefinitionsAt(point, defs, false);
466 return defs;
467 }
468 BUG("Unknown point %1% for definitions", &point);
469 }
470 return it->second;
471 }
472 void setDefinitionsAt(ProgramPoint point, Definitions *defs, bool overwrite) {
473 if (!overwrite) {
474 auto it = atPoint.find(point);
475 if (it != atPoint.end()) {
476 LOG2("Overwriting definitions at " << point << ": " << it->second << " with "
477 << defs);
478 BUG_CHECK(false, "Overwriting definitions at %1%", point);
479 }
480 }
481 atPoint[point] = defs;
482 }
483 void dbprint(std::ostream &out) const override {
484 for (auto e : atPoint) out << e.first << " => " << e.second << Log::endl;
485 }
486};
487
498
499class ComputeWriteSet : public Inspector, public IHasDbPrint {
500 public:
501 explicit ComputeWriteSet(AllDefinitions *allDefinitions)
502 : allDefinitions(allDefinitions),
503 currentDefinitions(nullptr),
504 returnedDefinitions(nullptr),
506 storageMap(allDefinitions->storageMap),
507 lhs(false),
508 virtualMethod(false),
509 cached_locs(*new std::unordered_set<loc_t>) {
510 CHECK_NULL(allDefinitions);
511 visitDagOnce = false;
512 }
513
514 // expressions
515 bool preorder(const IR::Literal *expression) override;
516 bool preorder(const IR::Slice *expression) override;
517 bool preorder(const IR::TypeNameExpression *expression) override;
518 bool preorder(const IR::PathExpression *expression) override;
519 bool preorder(const IR::Member *expression) override;
520 bool preorder(const IR::ArrayIndex *expression) override;
521 bool preorder(const IR::Operation_Binary *expression) override;
522 bool preorder(const IR::Mux *expression) override;
523 bool preorder(const IR::SelectExpression *expression) override;
524 bool preorder(const IR::ListExpression *expression) override;
525 bool preorder(const IR::Operation_Unary *expression) override;
526 bool preorder(const IR::MethodCallExpression *expression) override;
527 bool preorder(const IR::DefaultExpression *expression) override;
528 bool preorder(const IR::Expression *expression) override;
529 bool preorder(const IR::InvalidHeader *expression) override;
530 bool preorder(const IR::InvalidHeaderUnion *expression) override;
531 bool preorder(const IR::P4ListExpression *expression) override;
532 bool preorder(const IR::HeaderStackExpression *expression) override;
533 bool preorder(const IR::StructExpression *expression) override;
534 // statements
535 bool preorder(const IR::P4Parser *parser) override;
536 bool preorder(const IR::P4Control *control) override;
537 bool preorder(const IR::P4Action *action) override;
538 bool preorder(const IR::P4Table *table) override;
539 bool preorder(const IR::Function *function) override;
540 bool preorder(const IR::AssignmentStatement *statement) override;
541 bool preorder(const IR::ReturnStatement *statement) override;
542 bool preorder(const IR::ExitStatement *statement) override;
543 bool preorder(const IR::BreakStatement *statement) override;
544 bool handleJump(const char *tok, Definitions *&defs);
545 bool preorder(const IR::ContinueStatement *statement) override;
546 bool preorder(const IR::IfStatement *statement) override;
547 bool preorder(const IR::ForStatement *statement) override;
548 bool preorder(const IR::ForInStatement *statement) override;
549 bool preorder(const IR::BlockStatement *statement) override;
550 bool preorder(const IR::SwitchStatement *statement) override;
551 bool preorder(const IR::EmptyStatement *statement) override;
552 bool preorder(const IR::MethodCallStatement *statement) override;
553
554 const LocationSet *writtenLocations(const IR::Expression *expression) {
555 expression->apply(*this);
556 return getWrites(expression);
557 }
558
559 protected:
560 AllDefinitions *allDefinitions;
567 const StorageMap *storageMap;
569 bool lhs;
572 bool virtualMethod;
574 alloc_trace_cb_t nested_trace;
575 static int nest_count;
576
579 ComputeWriteSet(const ComputeWriteSet *source, ProgramPoint context, Definitions *definitions,
580 std::unordered_set<loc_t> &cached_locs)
581 : allDefinitions(source->allDefinitions),
582 currentDefinitions(definitions),
583 returnedDefinitions(nullptr),
587 callingContext(context),
588 storageMap(source->storageMap),
589 lhs(false),
590 virtualMethod(false),
591 cached_locs(cached_locs) {
592 visitDagOnce = false;
593 }
595 const loc_t *getLoc(const IR::Node *n, const loc_t *parentLoc);
596 const loc_t *getLoc(const Visitor::Context *ctxt);
597 const loc_t *getLoc(const IR::Node *n, const Visitor::Context *ctxt);
598 void enterScope(const IR::ParameterList *parameters,
599 const IR::IndexedVector<IR::Declaration> *locals, ProgramPoint startPoint,
600 bool clear = true);
601 void exitScope(const IR::ParameterList *parameters,
603 Definitions *getDefinitionsAfter(const IR::ParserState *state);
604 bool setDefinitions(Definitions *defs, const IR::Node *who = nullptr, bool overwrite = false);
605 ProgramPoint getProgramPoint(const IR::Node *node = nullptr) const;
606 // Get writes of a node that is a direct child of the currently being visited node.
607 const LocationSet *getWrites(const IR::Expression *expression) {
608 const loc_t &exprLoc = *getLoc(expression, getChildContext());
609 auto result = ::P4::get(writes, exprLoc);
610 BUG_CHECK(result != nullptr, "No location set known for %1%", expression);
611 return result;
612 }
613 // Get writes of a node that is not a direct child of the currently being visited node.
614 // In this case, parentLoc is the loc of expression's direct parent node.
615 const LocationSet *getWrites(const IR::Expression *expression, const loc_t *parentLoc) {
616 const loc_t &exprLoc = *getLoc(expression, parentLoc);
617 auto result = ::P4::get(writes, exprLoc);
618 BUG_CHECK(result != nullptr, "No location set known for %1%", expression);
619 return result;
620 }
621 // Register writes of expression, which is expected to be the currently visited node.
622 void expressionWrites(const IR::Expression *expression, const LocationSet *loc) {
623 CHECK_NULL(expression);
624 CHECK_NULL(loc);
625 LOG3(expression << dbp(expression) << " writes " << loc);
626 const Context *ctx = getChildContext();
627 BUG_CHECK(ctx->node == expression, "Expected ctx->node == expression.");
628 const loc_t &exprLoc = *getLoc(ctx);
629 if (auto it = writes.find(exprLoc); it != writes.end()) {
630 BUG_CHECK(*it->second == *loc || expression->is<IR::Literal>(),
631 "Expression %1% write set already set", expression);
632 } else {
633 writes.emplace(exprLoc, loc);
634 }
635 }
636 void dbprint(std::ostream &out) const override {
637 if (writes.empty()) out << "No writes";
638 for (auto &it : writes) out << it.first.node << " writes " << it.second << Log::endl;
639 }
640 profile_t init_apply(const IR::Node *root) override {
641 auto rv = Inspector::init_apply(root);
642 LOG1("starting ComputWriteSet" << Log::indent);
643 if (nest_count++ == 0 && LOGGING(2)) {
644 memuse.clear();
645 nested_trace = memuse.start();
646 }
647 return rv;
648 }
649 void end_apply() override {
650 LOG1("finished CWS" << Log::unindent);
651 if (--nest_count == 0 && LOGGING(2)) {
652 memuse.stop(nested_trace);
653 LOG2(memuse);
654 }
655 }
656
657 private:
658 // TODO: Make absl::node_hash_set instead?
659 std::unordered_set<loc_t> &cached_locs;
660};
661
662} // namespace P4
663
664#endif /* FRONTENDS_P4_DEF_USE_H_ */
Definition frontends/p4/def_use.h:449
Definition alloc_trace.h:29
Definition frontends/p4/def_use.h:82
Definition frontends/p4/def_use.h:499
bool lhs
if true we are processing an expression on the lhs of an assignment
Definition frontends/p4/def_use.h:569
AllocTrace memuse
True if we are analyzing a virtual method.
Definition frontends/p4/def_use.h:573
Definitions * breakDefinitions
Definitions after exit statements.
Definition frontends/p4/def_use.h:564
Definitions * returnedDefinitions
Before statement currently processed.
Definition frontends/p4/def_use.h:562
void visitVirtualMethods(const IR::IndexedVector< IR::Declaration > &locals)
Statements and other control structures.
Definition frontends/p4/def_use.cpp:753
Definitions * exitDefinitions
Definitions after return statements.
Definition frontends/p4/def_use.h:563
Definitions * currentDefinitions
Result computed by this pass.
Definition frontends/p4/def_use.h:561
ComputeWriteSet(const ComputeWriteSet *source, ProgramPoint context, Definitions *definitions, std::unordered_set< loc_t > &cached_locs)
Definition frontends/p4/def_use.h:579
Definitions * continueDefinitions
Definitions at break statements.
Definition frontends/p4/def_use.h:565
ProgramPoint callingContext
Definitions at continue statements.
Definition frontends/p4/def_use.h:566
hvec_map< loc_t, const LocationSet * > writes
For each program location the location set it writes.
Definition frontends/p4/def_use.h:571
List of definers for each base storage (at a specific program point).
Definition frontends/p4/def_use.h:395
Definitions * writes(ProgramPoint point, const LocationSet *locations) const
Point writes the specified LocationSet.
Definition frontends/p4/def_use.cpp:355
Definition castable.h:36
Definition stringify.h:33
The Declaration interface, representing objects with names.
Definition declaration.h:26
virtual ID getName() const =0
Definition indexed_vector.h:40
Definition node.h:95
Definition visitor.h:400
Definition map.h:146
Definition frontends/p4/def_use.h:211
const LocationSet * canonicalize() const
Definition frontends/p4/def_use.cpp:233
Indicates a statement in the program.
Definition frontends/p4/def_use.h:292
static ProgramPoint beforeStart
A point logically before the function/control/action start.
Definition frontends/p4/def_use.h:311
ProgramPoint after()
We use a nullptr to indicate a point after the previous context.
Definition frontends/p4/def_use.h:313
Definition frontends/p4/def_use.h:369
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
Definition frontends/p4/def_use.h:201
Abstraction for something that is has a left value (variable, parameter)
Definition frontends/p4/def_use.h:53
const LocationSet * getLastIndexField() const
Definition frontends/p4/def_use.cpp:160
const LocationSet * removeHeaders() const
Definition frontends/p4/def_use.cpp:106
const LocationSet * getValidBits() const
Definition frontends/p4/def_use.cpp:154
Maps a declaration to its associated storage.
Definition frontends/p4/def_use.h:256
Definition typeMap.h:41
Definition visitor.h:78
Definition cstring.h:85
Definition hvec_map.h:31
Definition ordered_set.h:32
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
STL namespace.
Definition hash.h:123
Definition frontends/p4/def_use.h:39
Definition gc.h:27