P4C
The P4 Compiler
Loading...
Searching...
No Matches
predication.h
1/*
2 * Copyright 2016 VMware, Inc.
3 * SPDX-FileCopyrightText: 2016 VMware, Inc.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef MIDEND_PREDICATION_H_
9#define MIDEND_PREDICATION_H_
10
11#include "frontends/p4/typeChecking/typeChecker.h"
12#include "ir/ir.h"
13
14namespace P4 {
15
32class Predication final : public Transform {
36 class EmptyStatementRemover final : public Transform {
37 public:
38 EmptyStatementRemover() {}
39 const IR::Node *postorder(IR::ForStatement *) override;
40 const IR::Node *postorder(IR::ForInStatement *) override;
41 const IR::Node *postorder(IR::EmptyStatement *statement) override;
42 const IR::Node *postorder(IR::BlockStatement *statement) override;
43 };
50 class ExpressionReplacer final : public Transform {
51 private:
52 // Original assignment that the replacer works on
53 const IR::AssignmentStatement *const statement;
54 // To keep track of the path used while traversing nested if-else statements:
55 // IF - true / ELSE - false
56 const std::vector<bool> &traversalPath;
57 // To store the condition used in every if-else statement
58 std::vector<const IR::Expression *> &conditions;
59 // Nesting level of Mux expressions
60 unsigned currentNestingLevel = 0;
61 // An indicator used to implement the logic for ArrayIndex transformation
62 bool visitingIndex = false;
63
64 public:
65 explicit ExpressionReplacer(const IR::AssignmentStatement *a, std::vector<bool> &t,
66 std::vector<const IR::Expression *> &c)
67 : statement(a), traversalPath(t), conditions(c) {
68 CHECK_NULL(a);
69 }
70 const IR::Mux *preorder(IR::Mux *mux) override;
71 void emplaceExpression(IR::Mux *mux);
72 void visitBranch(IR::Mux *mux, bool then);
73 void setVisitingIndex(bool val);
74 };
75
76 // Used to dynamically generate names for variables in parts of code
77 MinimalNameGenerator generator;
78 // Used to remove empty statements and empty block statements that appear in the code
79 EmptyStatementRemover remover;
80 bool inside_action;
81 // Used to indicate whether or not an ArrayIndex should be modified.
82 bool modifyIndex = false;
83 // Tracking the nesting level of IF-ELSE statements
84 unsigned ifNestingLevel;
85 // Tracking the nesting level of dependency assignment
86 unsigned depNestingLevel;
87 // To store dependent assignments.
88 // If current statement is equal to any member of dependentNames,
89 // isStatementdependent of the coresponding statement is set to true.
90 std::vector<cstring> dependentNames;
91 // Traverse path of nested if-else statements.
92 // Size of this vector is the current IF nesting level. IF - true / ELSE - false
93 std::vector<bool> traversalPath;
94 std::vector<cstring> dependencies;
95 // Collects assignment statements with transformed right expression.
96 // liveAssignments are pushed at the back of liveAssigns vector.
97 std::map<cstring, const IR::AssignmentStatement *> liveAssignments;
98 // Vector of assignment statements which collects assignments from
99 // liveAssignments and dependencies in adequate order. In preorder
100 // of if statements assignments from liveAssigns are pushed on rv block.
101 std::vector<const IR::AssignmentStatement *> liveAssigns;
102 // Vector of ArrayIndex declarations which is used to temporary
103 // store these declarations so they can later be pushed on the 'rv' block.
104 std::vector<const IR::Declaration *> indexDeclarations;
105 // Map that shows if the current statement is dependent.
106 // Bool value is true for dependent statements,
107 // false for statements that are not dependent.
108 std::map<cstring, bool> isStatementDependent;
109 const IR::Statement *error(const IR::Statement *statement) const {
110 if (inside_action && ifNestingLevel > 0)
111 ::P4::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET,
112 "%1%: Conditional execution in actions unsupported on this target",
113 statement);
114 return statement;
115 }
116
117 public:
118 explicit Predication() : inside_action(false), ifNestingLevel(0), depNestingLevel(0) {
119 setName("Predication");
120 }
121 Visitor::profile_t init_apply(const IR::Node *node) override {
122 auto rv = Transform::init_apply(node);
123 node->apply(generator);
124
125 return rv;
126 }
127
128 const IR::Expression *clone(const IR::Expression *expression);
129 const IR::AssignmentStatement *clone(const IR::AssignmentStatement *statement);
130 const IR::Node *preorder(IR::IfStatement *statement) override;
131 const IR::Node *preorder(IR::P4Action *action) override;
132 const IR::Node *postorder(IR::P4Action *action) override;
133 const IR::Node *preorder(IR::AssignmentStatement *statement) override;
134 const IR::Node *preorder(IR::OpAssignmentStatement *statement) override;
135 // Assignment dependecy checkers
136 const IR::Node *preorder(IR::PathExpression *pathExpr) override;
137 const IR::Node *preorder(IR::Member *member) override;
138 const IR::Node *preorder(IR::ArrayIndex *arrInd) override;
139 // The presence of other statements makes predication impossible to apply
140 const IR::Node *postorder(IR::MethodCallStatement *statement) override {
141 return error(statement);
142 }
143 const IR::Node *postorder(IR::ReturnStatement *statement) override { return error(statement); }
144 const IR::Node *postorder(IR::ExitStatement *statement) override { return error(statement); }
145};
146
147} // namespace P4
148
149#endif /* MIDEND_PREDICATION_H_ */
Definition node.h:44
Definition referenceMap.h:27
Definition visitor.h:433
Definition visitor.h:69
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