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