8#ifndef FRONTENDS_P4_SIDEEFFECTS_H_
9#define FRONTENDS_P4_SIDEEFFECTS_H_
13#include "frontends/common/resolveReferences/referenceMap.h"
14#include "frontends/common/resolveReferences/resolveReferences.h"
15#include "frontends/p4/methodInstance.h"
16#include "frontends/p4/typeChecking/typeChecker.h"
22class HasTableApply :
public Inspector,
public ResolutionContext {
26 const IR::P4Table *table;
27 const IR::MethodCallExpression *call;
28 explicit HasTableApply(
TypeMap *typeMap) : typeMap(typeMap), table(
nullptr), call(
nullptr) {
30 setName(
"HasTableApply");
33 void postorder(
const IR::MethodCallExpression *expression)
override {
35 if (!mi->isApply())
return;
37 if (!am->object->is<IR::P4Table>())
return;
38 BUG_CHECK(table ==
nullptr,
"%1% and %2%: multiple table applications in one expression",
40 table = am->object->to<IR::P4Table>();
42 LOG3(
"Invoked table is " << dbp(table));
64 void postorder(
const IR::MethodCallExpression *mce)
override {
71 void postorder(
const IR::ConstructorCallExpression *cce)
override {
81 static bool check(
const IR::Expression *expression,
const Visitor *calledBy,
82 TypeMap *typeMap =
nullptr,
const Visitor::Context *ctxt =
nullptr) {
84 se.setCalledBy(calledBy);
85 if (calledBy && !ctxt) ctxt = calledBy->getChildContext();
86 expression->apply(se, ctxt);
98 return !ec->method->hasAnnotation(IR::Annotation::noSideEffectsAnnotation);
100 return !ef->function->hasAnnotation(IR::Annotation::noSideEffectsAnnotation);
101 if (
const auto *bim = mi->to<
BuiltInMethod>())
return bim->name != IR::Type_Header::isValid;
142 std::set<const IR::Expression *> *added;
148 std::set<const IR::Expression *> temporaries;
152 const IR::Expression *expression,
154 bool mayAlias(
const IR::Expression *left,
const IR::Expression *right,
155 const Visitor::Context *ctxt)
const;
156 bool containsHeaderType(
const IR::Type *type);
159 DoSimplifyExpressions(
TypeMap *typeMap, std::set<const IR::Expression *> *added)
160 : typeMap(typeMap), added(added) {
162 setName(
"DoSimplifyExpressions");
165 const IR::Node *postorder(IR::Expression *expression)
override;
166 const IR::Node *preorder(IR::StructExpression *expression)
override;
167 const IR::Node *preorder(IR::ListExpression *expression)
override;
168 const IR::Node *preorder(IR::Literal *expression)
override;
169 const IR::Node *preorder(IR::ArrayIndex *expression)
override;
170 const IR::Node *preorder(IR::Member *expression)
override;
171 const IR::Node *preorder(IR::SelectExpression *expression)
override;
172 const IR::Node *preorder(IR::Operation_Unary *expression)
override;
173 const IR::Node *preorder(IR::Operation_Binary *expression)
override;
174 const IR::Node *shortCircuit(IR::Operation_Binary *expression);
175 const IR::Node *preorder(IR::Mux *expression)
override;
176 const IR::Node *preorder(IR::LAnd *expression)
override;
177 const IR::Node *preorder(IR::LOr *expression)
override;
178 const IR::Node *preorder(IR::MethodCallExpression *mce)
override;
180 const IR::Node *preorder(IR::ConstructorCallExpression *cce)
override {
184 const IR::Node *preorder(IR::Property *prop)
override {
188 const IR::Node *preorder(IR::Annotation *anno)
override {
193 const IR::Node *postorder(IR::P4Parser *parser)
override;
194 const IR::Node *postorder(IR::Function *function)
override;
195 const IR::Node *postorder(IR::P4Control *control)
override;
196 const IR::Node *postorder(IR::P4Action *action)
override;
197 const IR::Node *postorder(IR::ParserState *state)
override;
198 const IR::Node *postorder(IR::BaseAssignmentStatement *statement)
override;
199 const IR::Node *postorder(IR::MethodCallStatement *statement)
override;
200 const IR::Node *postorder(IR::ReturnStatement *statement)
override;
201 const IR::Node *preorder(IR::SwitchStatement *statement)
override;
202 const IR::Node *preorder(IR::IfStatement *statement)
override;
203 const IR::Node *preorder(IR::ForStatement *statement)
override;
204 const IR::Node *preorder(IR::ForInStatement *statement)
override;
207 void end_apply(
const IR::Node *)
override;
212 std::vector<const IR::Declaration_Variable *> declarations;
213 std::vector<const IR::BaseAssignmentStatement *> statements;
254class KeySideEffect :
public Transform,
public ResolutionContext {
258 std::map<const IR::P4Table *, TableInsertions *> toInsert;
259 std::set<const IR::P4Table *> *invokedInKey;
262 KeySideEffect(
TypeMap *typeMap, std::set<const IR::P4Table *> *invokedInKey)
263 : typeMap(typeMap), invokedInKey(invokedInKey) {
265 CHECK_NULL(invokedInKey);
266 setName(
"KeySideEffect");
271 virtual const IR::Node *doStatement(
const IR::Statement *statement,
272 const IR::Expression *expression,
273 const Visitor::Context *ctxt);
275 const IR::Node *preorder(IR::Key *key)
override;
279 const IR::Node *postorder(IR::MethodCallStatement *statement)
override {
280 return doStatement(statement, statement->methodCall, getContext());
282 const IR::Node *postorder(IR::IfStatement *statement)
override {
283 return doStatement(statement, statement->condition, getContext());
285 const IR::Node *postorder(IR::SwitchStatement *statement)
override {
286 return doStatement(statement, statement->expression, getContext());
288 const IR::Node *postorder(IR::BaseAssignmentStatement *statement)
override {
289 return doStatement(statement, statement->right, getContext());
291 const IR::Node *postorder(IR::KeyElement *element)
override;
292 const IR::Node *postorder(IR::P4Table *table)
override;
293 const IR::Node *preorder(IR::P4Table *table)
override;
303 std::set<const IR::P4Table *> *invokedInKey;
306 TablesInKeys(
TypeMap *typeMap, std::set<const IR::P4Table *> *invokedInKey)
307 : typeMap(typeMap), invokedInKey(invokedInKey) {
308 CHECK_NULL(invokedInKey);
309 setName(
"TableInKeys");
312 invokedInKey->clear();
313 return Inspector::init_apply(node);
315 void postorder(
const IR::MethodCallExpression *mce)
override {
316 if (!isInContext<IR::Key>())
return;
318 hta.setCalledBy(
this);
319 (void)mce->apply(hta, getContext());
320 if (hta.table !=
nullptr) {
321 LOG2(
"Table " << hta.table <<
" invoked in key of another table");
322 invokedInKey->emplace(hta.table);
336 explicit TablesInActions(
TypeMap *typeMap) : typeMap(typeMap) {}
337 void postorder(
const IR::MethodCallExpression *expression)
override {
338 if (isInContext<IR::ActionList>()) {
340 hta.setCalledBy(
this);
341 (void)expression->apply(hta, getContext());
342 if (hta.table !=
nullptr) {
343 ::P4::error(ErrorType::ERR_UNSUPPORTED,
"%1%: table invocation in action argument",
350class SideEffectOrdering :
public PassRepeated {
355 std::set<const IR::P4Table *> invokedInKey;
357 std::set<const IR::Expression *> added;
360 SideEffectOrdering(
TypeMap *typeMap,
bool skipSideEffectOrdering,
362 if (!typeChecking) typeChecking =
new TypeChecking(
nullptr, typeMap);
363 if (!skipSideEffectOrdering) {
367 passes.push_back(typeChecking);
369 passes.push_back(
new TablesInKeys(typeMap, &invokedInKey));
372 setName(
"SideEffectOrdering");
Definition methodInstance.h:120
Definition methodInstance.h:251
Definition typeChecker.h:23
Definition referenceMap.h:48
Convert expressions so that each expression contains at most one side effect.
Definition sideEffects.h:138
Definition methodInstance.h:140
Definition methodInstance.h:223
Checks to see whether an IR node includes a table.apply() sub-expression.
Definition sideEffects.h:22
Definition indexed_vector.h:31
Definition sideEffects.h:254
static MethodInstance * resolve(const IR::MethodCallExpression *mce, const DeclarationLookup *refMap, TypeMap *typeMap, bool useExpressionType=false, const Visitor::Context *ctxt=nullptr, bool incomplete=false)
Definition methodInstance.cpp:16
Definition referenceMap.h:27
static bool mayHaveSideEffect(const IR::MethodCallExpression *mce, DeclarationLookup *refMap, TypeMap *typeMap)
Definition sideEffects.h:90
unsigned sideEffectCount
Number of side effects in this expression.
Definition sideEffects.h:62
static bool check(const IR::Expression *expression, const Visitor *calledBy, TypeMap *typeMap=nullptr, const Visitor::Context *ctxt=nullptr)
Definition sideEffects.h:81
const IR::Node * nodeWithSideEffect
Last visited side-effecting node. Null if no node has side effects.
Definition sideEffects.h:59
SideEffects(TypeMap *typeMap)
Definition sideEffects.h:78
Definition sideEffects.h:332
Definition sideEffects.h:301
Definition typeChecker.h:46
Definition source_file.h:123
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:48
Definition sideEffects.h:210