P4C
The P4 Compiler
Loading...
Searching...
No Matches
midend/def_use.h
1/*
2Copyright 2024 Intel Corp.
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 MIDEND_DEF_USE_H_
18#define MIDEND_DEF_USE_H_
19
20#include "frontends/common/resolveReferences/resolveReferences.h"
21#include "ir/ir.h"
22#include "lib/bitrange.h"
23
24namespace P4 {
25
42class ComputeDefUse : public Inspector,
43 public ControlFlowVisitor,
44 public P4WriteContext,
46 static int uid_ctr;
47 int uid = 0;
48 ComputeDefUse *clone() const override {
49 auto *rv = new ComputeDefUse(*this);
50 rv->uid = ++uid_ctr;
51 LOG8("ComputeDefUse::clone " << rv->uid);
52 return rv;
53 }
54 void flow_merge(Visitor &) override;
55 void flow_copy(ControlFlowVisitor &) override;
56 bool operator==(const ControlFlowVisitor &) const override;
57
58 enum { SKIPPING, NORMAL, READ_ONLY, WRITE_ONLY } state = SKIPPING;
59
60 public:
61 // a location in the program. Includes the context from the visitor, which needs to
62 // be copied out of the Visitor::Context objects, as they are allocated on the stack and
63 // will become invalid as the IR traversal continues
64 struct loc_t {
65 const IR::Node *node;
66 const loc_t *parent;
67 bool operator<(const loc_t &a) const {
68 if (node != a.node) return node->id < a.node->id;
69 if (!parent || !a.parent) return parent != nullptr;
70 return *parent < *a.parent;
71 }
72 template <class T>
73 const T *find() const {
74 for (auto *p = this; p; p = p->parent) {
75 if (auto *t = p->node->to<T>()) return t;
76 }
77 return nullptr;
78 }
79 };
81
82 private:
83 std::set<loc_t> &cached_locs;
84 const loc_t *getLoc(const Visitor::Context *ctxt);
85 const loc_t *getLoc() { return getLoc(getChildContext()); }
86 const loc_t *getLoc(const IR::Node *, const Visitor::Context *);
87 const loc_t *getLoc(const IR::Node *n) { return getLoc(n, getChildContext()); }
88
89 // flow tracking info about defs live at the point we are currently visiting
90 struct def_info_t {
91 // definitions of a symbol (or part of a symbol) visible at this point in the
92 // program. `defs` will be empty if `live` is; if not those defs are visible only
93 // for those bits/elements/fields where live is set.
94 locset_t defs;
95 bitvec live;
96 // FIXME -- this parent field is never used and is not set consistently, so
97 // appears to be useless?
98 def_info_t *parent = nullptr;
99 // track valid bit access for headers separate from the rest of the header
100 locset_t valid_bit_defs;
101 // one of these maps will always be empty.
102 std::map<cstring, def_info_t> fields;
103 std::map<le_bitrange, def_info_t> slices; // also used for arrays
104 // keys in slices are always non-overlapping (checked by slices_sanity)
105 void slices_sanity();
106 std::map<le_bitrange, def_info_t>::iterator slices_overlap_begin(le_bitrange);
107 void erase_slice(le_bitrange);
108 void split_slice(le_bitrange);
109 void flow_merge(def_info_t &);
110 bool operator==(const def_info_t &) const;
111 bool operator!=(const def_info_t &a) const { return !(*this == a); }
112 def_info_t() = default;
113 def_info_t(const def_info_t &);
114 def_info_t(def_info_t &&);
115 };
117 void add_uses(const loc_t *, def_info_t &);
118 void set_live_from_type(def_info_t &di, const IR::Type *type);
119
120 // computed defuse info for all uses and defs in the program
121 struct defuse_t {
122 // defs maps from all uses to their definitions
123 // uses maps from all definitions to their uses
124 // uses/defs are lvalue expressions, or param declarations.
127 } & defuse;
128 static const locset_t empty;
129
130 profile_t init_apply(const IR::Node *root) override {
131 auto rv = Inspector::init_apply(root);
132 LOG3("## Midend ComputeDefUse");
133 uid_ctr = 0;
134 state = SKIPPING;
135 clear();
136 return rv;
137 }
138 bool preorder(const IR::P4Control *) override;
139 bool preorder(const IR::P4Table *) override;
140 bool preorder(const IR::P4Action *) override;
141 bool preorder(const IR::P4Parser *) override;
142 bool preorder(const IR::ParserState *) override;
143 void revisit(const IR::ParserState *) override;
144 void loop_revisit(const IR::ParserState *) override;
145 void postorder(const IR::ParserState *) override;
146 bool preorder(const IR::Type *) override { return false; }
147 bool preorder(const IR::Annotations *) override { return false; }
148 bool preorder(const IR::KeyElement *) override;
149 bool preorder(const IR::AssignmentStatement *) override;
150 const IR::Expression *do_read(def_info_t &, const IR::Expression *, const Context *);
151 const IR::Expression *do_write(def_info_t &, const IR::Expression *, const Context *);
152 bool preorder(const IR::PathExpression *) override;
153 void loop_revisit(const IR::PathExpression *) override;
154 bool preorder(const IR::MethodCallExpression *) override;
155 void end_apply() override;
156
157 class SetupJoinPoints;
158 void applySetupJoinPoints(const IR::Node *root) override;
159 bool filter_join_point(const IR::Node *) override;
160
161 public:
162 ComputeDefUse()
163 : ResolutionContext(true), cached_locs(*new std::set<loc_t>), defuse(*new defuse_t) {
164 joinFlows = true;
165 visitDagOnce = false;
166 }
167 void clear() {
168 cached_locs.clear();
169 def_info.clear();
170 defuse.defs.clear();
171 defuse.uses.clear();
172 }
173
174 const locset_t &getDefs(const IR::Node *n) const {
175 auto it = defuse.defs.find(n);
176 return it == defuse.defs.end() ? empty : it->second;
177 }
178 const locset_t &getUses(const IR::Node *n) const {
179 auto it = defuse.uses.find(n);
180 return it == defuse.uses.end() ? empty : it->second;
181 }
182
183 // for debugging
184 friend std::ostream &operator<<(std::ostream &, const loc_t &);
185 friend std::ostream &operator<<(std::ostream &, const defuse_t &);
186 friend std::ostream &operator<<(std::ostream &out, const ComputeDefUse &cdu) {
187 return out << cdu.defuse;
188 }
189};
190
191} // namespace P4
192
193#endif /* MIDEND_DEF_USE_H_ */
Definition visitor.h:459
Definition node.h:93
Definition visitor.h:396
Compute defuse info within P4Parser and P4Control blocks in the midend.
Definition midend/def_use.h:45
Visitor mixin for looking up names in enclosing scopes from the Visitor::Context.
Definition resolveReferences.h:32
Definition visitor.h:782
Definition visitor.h:73
Definition bitvec.h:119
Definition ordered_map.h:30
Definition ordered_set.h:30
Definition applyOptionsPragmas.cpp:24
STL namespace.
Definition bitrange.h:511
Definition midend/def_use.h:64
Definition frontends/p4/def_use.h:39
Definition visitor.h:45