17#ifndef FRONTENDS_P4_SIDEEFFECTS_H_
18#define FRONTENDS_P4_SIDEEFFECTS_H_
22#include "frontends/common/resolveReferences/referenceMap.h"
23#include "frontends/common/resolveReferences/resolveReferences.h"
24#include "frontends/p4/methodInstance.h"
25#include "frontends/p4/typeChecking/typeChecker.h"
35 const IR::P4Table *table;
36 const IR::MethodCallExpression *call;
39 setName(
"HasTableApply");
42 void postorder(
const IR::MethodCallExpression *expression)
override {
44 if (!mi->isApply())
return;
46 if (!am->object->is<IR::P4Table>())
return;
47 BUG_CHECK(table ==
nullptr,
"%1% and %2%: multiple table applications in one expression",
49 table = am->object->to<IR::P4Table>();
51 LOG3(
"Invoked table is " << dbp(table));
74 void postorder(
const IR::MethodCallExpression *mce)
override {
75 if (refMap ==
nullptr || typeMap ==
nullptr) {
88 if (bim->name.name != IR::Type_Header::isValid) {
94 void postorder(
const IR::ConstructorCallExpression *cce)
override {
102 setName(
"SideEffects");
106 static bool check(
const IR::Expression *expression,
const Visitor *calledBy,
110 se.setCalledBy(calledBy);
111 expression->apply(se, ctxt);
122 if (em->method->getAnnotation(IR::Annotation::noSideEffectsAnnotation)) {
128 if (ef->method->getAnnotation(IR::Annotation::noSideEffectsAnnotation)) {
134 if (ef->function->getAnnotation(IR::Annotation::noSideEffectsAnnotation)) {
140 if (bim->name.name == IR::Type_Header::isValid) {
184 std::set<const IR::Expression *> *added;
190 std::set<const IR::Expression *> temporaries;
192 cstring createTemporary(
const IR::Type *type);
194 const IR::Expression *expression);
195 bool mayAlias(
const IR::Expression *left,
const IR::Expression *right,
197 bool containsHeaderType(
const IR::Type *type);
201 : typeMap(typeMap), added(added) {
203 setName(
"DoSimplifyExpressions");
206 const IR::Node *postorder(IR::Expression *expression)
override;
207 const IR::Node *preorder(IR::StructExpression *expression)
override;
208 const IR::Node *preorder(IR::ListExpression *expression)
override;
209 const IR::Node *preorder(IR::Literal *expression)
override;
210 const IR::Node *preorder(IR::ArrayIndex *expression)
override;
211 const IR::Node *preorder(IR::Member *expression)
override;
212 const IR::Node *preorder(IR::SelectExpression *expression)
override;
213 const IR::Node *preorder(IR::Operation_Unary *expression)
override;
214 const IR::Node *preorder(IR::Operation_Binary *expression)
override;
215 const IR::Node *shortCircuit(IR::Operation_Binary *expression);
216 const IR::Node *preorder(IR::Mux *expression)
override;
217 const IR::Node *preorder(IR::LAnd *expression)
override;
218 const IR::Node *preorder(IR::LOr *expression)
override;
219 const IR::Node *preorder(IR::MethodCallExpression *mce)
override;
221 const IR::Node *preorder(IR::ConstructorCallExpression *cce)
override {
225 const IR::Node *preorder(IR::Property *prop)
override {
229 const IR::Node *preorder(IR::Annotation *anno)
override {
234 const IR::Node *postorder(IR::P4Parser *parser)
override;
235 const IR::Node *postorder(IR::Function *function)
override;
236 const IR::Node *postorder(IR::P4Control *control)
override;
237 const IR::Node *postorder(IR::P4Action *action)
override;
238 const IR::Node *postorder(IR::ParserState *state)
override;
239 const IR::Node *postorder(IR::AssignmentStatement *statement)
override;
240 const IR::Node *postorder(IR::MethodCallStatement *statement)
override;
241 const IR::Node *postorder(IR::ReturnStatement *statement)
override;
242 const IR::Node *preorder(IR::SwitchStatement *statement)
override;
243 const IR::Node *preorder(IR::IfStatement *statement)
override;
244 const IR::Node *preorder(IR::ForStatement *statement)
override;
245 const IR::Node *preorder(IR::ForInStatement *statement)
override;
248 void end_apply(
const IR::Node *)
override;
253 std::vector<const IR::Declaration_Variable *> declarations;
254 std::vector<const IR::AssignmentStatement *> statements;
299 std::map<const IR::P4Table *, TableInsertions *> toInsert;
300 std::set<const IR::P4Table *> *invokedInKey;
304 : typeMap(typeMap), invokedInKey(invokedInKey) {
306 CHECK_NULL(invokedInKey);
307 setName(
"KeySideEffect");
312 virtual const IR::Node *doStatement(
const IR::Statement *statement,
313 const IR::Expression *expression,
316 const IR::Node *preorder(IR::Key *key)
override;
320 const IR::Node *postorder(IR::MethodCallStatement *statement)
override {
321 return doStatement(statement, statement->methodCall, getContext());
323 const IR::Node *postorder(IR::IfStatement *statement)
override {
324 return doStatement(statement, statement->condition, getContext());
326 const IR::Node *postorder(IR::SwitchStatement *statement)
override {
327 return doStatement(statement, statement->expression, getContext());
329 const IR::Node *postorder(IR::AssignmentStatement *statement)
override {
330 return doStatement(statement, statement->right, getContext());
332 const IR::Node *postorder(IR::KeyElement *element)
override;
333 const IR::Node *postorder(IR::P4Table *table)
override;
334 const IR::Node *preorder(IR::P4Table *table)
override;
344 std::set<const IR::P4Table *> *invokedInKey;
348 : typeMap(typeMap), invokedInKey(invokedInKey) {
349 CHECK_NULL(invokedInKey);
350 setName(
"TableInKeys");
353 invokedInKey->clear();
354 return Inspector::init_apply(node);
356 void postorder(
const IR::MethodCallExpression *mce)
override {
357 if (!findContext<IR::Key>())
return;
359 hta.setCalledBy(
this);
360 (void)mce->apply(hta, getContext());
361 if (hta.table !=
nullptr) {
362 LOG2(
"Table " << hta.table <<
" invoked in key of another table");
363 invokedInKey->emplace(hta.table);
378 void postorder(
const IR::MethodCallExpression *expression)
override {
379 if (findContext<IR::ActionList>()) {
381 hta.setCalledBy(
this);
382 (void)expression->apply(hta, getContext());
383 if (hta.table !=
nullptr) {
384 ::P4::error(ErrorType::ERR_UNSUPPORTED,
"%1%: table invocation in action argument",
396 std::set<const IR::P4Table *> invokedInKey;
398 std::set<const IR::Expression *> added;
403 if (!typeChecking) typeChecking =
new TypeChecking(
nullptr, typeMap);
404 if (!skipSideEffectOrdering) {
407 passes.push_back(typeChecking);
409 passes.push_back(
new TablesInKeys(typeMap, &invokedInKey));
412 setName(
"SideEffectOrdering");
Definition methodInstance.h:129
Definition methodInstance.h:260
Definition referenceMap.h:57
Convert expressions so that each expression contains at most one side effect.
Definition sideEffects.h:180
Definition methodInstance.h:194
Definition methodInstance.h:168
Definition methodInstance.h:232
Checks to see whether an IR node includes a table.apply() sub-expression.
Definition sideEffects.h:31
Definition sideEffects.h:295
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:27
Definition referenceMap.h:36
Definition ir/pass_manager.h:145
Visitor mixin for looking up names in enclosing scopes from the Visitor::Context.
Definition resolveReferences.h:35
Definition sideEffects.h:391
Determines whether an expression may have method or constructor invocations.
Definition sideEffects.h:62
unsigned sideEffectCount
Number of side effects in this expression.
Definition sideEffects.h:72
SideEffects(DeclarationLookup *refMap, TypeMap *typeMap)
Definition sideEffects.h:101
const IR::Node * nodeWithSideEffect
Last visited side-effecting node. Null if no node has side effects.
Definition sideEffects.h:69
static bool hasSideEffect(const IR::MethodCallExpression *mce, DeclarationLookup *refMap, TypeMap *typeMap)
Definition sideEffects.h:115
static bool check(const IR::Expression *expression, const Visitor *calledBy, DeclarationLookup *refMap, TypeMap *typeMap, const Visitor::Context *ctxt=nullptr)
Definition sideEffects.h:106
Definition sideEffects.h:373
Definition sideEffects.h:342
Definition typeChecker.h:55
Definition source_file.h:125
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:51
Definition sideEffects.h:251