P4C
The P4 Compiler
 
Loading...
Searching...
No Matches
alias.h
1/*
2Copyright 2019 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_ALIAS_H_
18#define FRONTENDS_P4_ALIAS_H_
19
20/*
21 * A simple conservative syntactic alias analysis. Two things may
22 * alias if they refer to objects with the same name. This pass may
23 * be run early in the front end, before enough information is present
24 * (eg. def-use information) to do a precise alias analysis. Also,
25 * this pass is safe only if the expressions compared for aliasing are
26 * part of the *same statement*.
27 */
28
29#include "frontends/common/resolveReferences/referenceMap.h"
30#include "frontends/p4/methodInstance.h"
31#include "frontends/p4/typeChecking/typeChecker.h"
32#include "ir/ir.h"
33
34namespace P4 {
35
40struct LocationPath : public IHasDbPrint {
41 const IR::IDeclaration *root;
42 std::vector<cstring> path;
43
44 explicit LocationPath(const IR::IDeclaration *root) : root(root) { CHECK_NULL(root); }
45
46 const LocationPath *append(cstring suffix) const {
47 auto result = new LocationPath(root);
48 result->path = path;
49 result->path.push_back(suffix);
50 return result;
51 }
52
54 bool isPrefix(const LocationPath *other) const {
55 // Due to the structure of the P4 language, two distinct
56 // declarations can never alias.
57 if (root != other->root) return false;
58 size_t len = std::min(path.size(), other->path.size());
59 for (size_t i = 0; i < len; i++) {
60 if (path.at(i) == "*" || other->path.at(i) == "*") continue;
61 if (path.at(i) != other->path.at(i)) return false;
62 }
63 return true;
64 }
65
66 void dbprint(std::ostream &out) const override {
67 out << root->getName();
68 for (auto p : path) out << "." << p;
69 }
70};
71
75 public:
76 std::set<const LocationPath *> paths;
77
78 SetOfLocations() = default;
79 explicit SetOfLocations(const LocationPath *path) { add(path); }
80 explicit SetOfLocations(const SetOfLocations *set) : paths(set->paths) {}
81
82 void add(const LocationPath *path) { paths.emplace(path); }
83 bool overlaps(const SetOfLocations *other) const {
84 // Normally one of these sets has only one element, because
85 // one of the two is a left-value, so this should be fast.
86 for (auto s : paths) {
87 for (auto so : other->paths) {
88 if (s->isPrefix(so)) return true;
89 }
90 }
91 return false;
92 }
93
94 const SetOfLocations *join(const SetOfLocations *other) const {
95 auto result = new SetOfLocations(this);
96 for (auto p : other->paths) result->add(p);
97 return result;
98 }
99
101 const SetOfLocations *append(cstring suffix) const {
102 auto result = new SetOfLocations();
103 for (auto p : paths) {
104 auto append = p->append(suffix);
105 result->add(append);
106 }
107 return result;
108 }
109
110 void dbprint(std::ostream &out) const override {
111 for (auto p : paths) out << p << std::endl;
112 }
113};
114
116class ReadsWrites : public Inspector {
117 const ReferenceMap *refMap;
118 std::map<const IR::Expression *, const SetOfLocations *> rw;
119
120 public:
121 explicit ReadsWrites(const ReferenceMap *refMap) : refMap(refMap) { setName("ReadsWrites"); }
122
123 void postorder(const IR::Operation_Binary *expression) override {
124 auto left = ::get(rw, expression->left);
125 auto right = ::get(rw, expression->right);
126 CHECK_NULL(left);
127 CHECK_NULL(right);
128 rw.emplace(expression, left->join(right));
129 }
130
131 void postorder(const IR::PathExpression *expression) override {
132 auto decl = refMap->getDeclaration(expression->path);
133 auto path = new LocationPath(decl);
134 auto locs = new SetOfLocations(path);
135 rw.emplace(expression, locs);
136 }
137
138 void postorder(const IR::Operation_Unary *expression) override {
139 auto e = ::get(rw, expression->expr);
140 CHECK_NULL(e);
141 rw.emplace(expression, e);
142 }
143
144 void postorder(const IR::Member *expression) override {
145 auto e = ::get(rw, expression->expr);
146 CHECK_NULL(e);
147 auto result = e->append(expression->member);
148 rw.emplace(expression, result);
149 }
150
151 void postorder(const IR::ArrayIndex *expression) override {
152 auto e = ::get(rw, expression->left);
153 CHECK_NULL(e);
154 const SetOfLocations *result;
155 if (expression->right->is<IR::Constant>()) {
156 int index = expression->right->to<IR::Constant>()->asInt();
157 result = e->append(Util::toString(index));
158 } else {
159 auto index = ::get(rw, expression->right);
160 result = e->append("*")->join(index);
161 }
162 rw.emplace(expression, result);
163 }
164
165 void postorder(const IR::Literal *expression) override {
166 rw.emplace(expression, new SetOfLocations());
167 }
168
169 void postorder(const IR::InvalidHeader *expression) override {
170 rw.emplace(expression, new SetOfLocations());
171 }
172
173 void postorder(const IR::InvalidHeaderUnion *expression) override {
174 rw.emplace(expression, new SetOfLocations());
175 }
176
177 void postorder(const IR::HeaderStackExpression *expression) override {
178 rw.emplace(expression, new SetOfLocations());
179 }
180
181 void postorder(const IR::TypeNameExpression *expression) override {
182 rw.emplace(expression, new SetOfLocations());
183 }
184
185 void postorder(const IR::Operation_Ternary *expression) override {
186 auto e0 = ::get(rw, expression->e0);
187 auto e1 = ::get(rw, expression->e1);
188 auto e2 = ::get(rw, expression->e2);
189 CHECK_NULL(e0);
190 CHECK_NULL(e1);
191 CHECK_NULL(e2);
192 rw.emplace(expression, e0->join(e1)->join(e2));
193 }
194
195 void postorder(const IR::Slice *expression) override {
196 auto e = ::get(rw, expression->e0);
197 CHECK_NULL(e);
198 rw.emplace(expression, e);
199 }
200
201 void postorder(const IR::MethodCallExpression *expression) override {
202 auto e = ::get(rw, expression->method);
203 for (auto a : *expression->arguments) {
204 auto s = ::get(rw, a->expression);
205 CHECK_NULL(s);
206 e = e->join(s);
207 }
208 rw.emplace(expression, e);
209 }
210
211 void postorder(const IR::ConstructorCallExpression *expression) override {
212 const SetOfLocations *result = new SetOfLocations();
213 for (auto e : *expression->arguments) {
214 auto s = ::get(rw, e->expression);
215 CHECK_NULL(s);
216 result = result->join(s);
217 }
218 rw.emplace(expression, result);
219 }
220
221 void postorder(const IR::StructExpression *expression) override {
222 const SetOfLocations *result = new SetOfLocations();
223 for (auto e : expression->components) {
224 auto s = ::get(rw, e->expression);
225 CHECK_NULL(s);
226 result = result->join(s);
227 }
228 rw.emplace(expression, result);
229 }
230
231 void postorder(const IR::ListExpression *expression) override {
232 const SetOfLocations *result = new SetOfLocations();
233 for (auto e : expression->components) {
234 auto s = ::get(rw, e);
235 CHECK_NULL(s);
236 result = result->join(s);
237 }
238 rw.emplace(expression, result);
239 }
240
241 const SetOfLocations *get(const IR::Expression *expression) {
242 expression->apply(*this);
243 auto result = ::get(rw, expression);
244 CHECK_NULL(result);
245 LOG3("SetOfLocations(" << expression << ")=" << result);
246 return result;
247 }
248
249 bool mayAlias(const IR::Expression *left, const IR::Expression *right) {
250 auto llocs = get(left);
251 auto rlocs = get(right);
252 CHECK_NULL(llocs);
253 CHECK_NULL(rlocs);
254 LOG3("Checking overlap between " << llocs << " and " << rlocs);
255 return llocs->overlaps(rlocs);
256 }
257};
258
259} // namespace P4
260
261#endif /* FRONTENDS_P4_ALIAS_H_ */
Definition source_file.h:38
Computes the SetOfLocations read and written by an expression.
Definition alias.h:116
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
const IR::IDeclaration * getDeclaration(const IR::Path *path, bool notNull=false) const override
Definition referenceMap.cpp:78
Definition alias.h:74
const SetOfLocations * append(cstring suffix) const
Append suffix to each location in the set.
Definition alias.h:101
Definition cstring.h:72
Definition applyOptionsPragmas.cpp:24
STL namespace.
Definition alias.h:40
bool isPrefix(const LocationPath *other) const
True if this path is a prefix of other or the other way around.
Definition alias.h:54