17#ifndef MIDEND_PARSERUNROLL_H_
18#define MIDEND_PARSERUNROLL_H_
20#include <unordered_map>
22#include "frontends/common/resolveReferences/referenceMap.h"
23#include "frontends/p4/callGraph.h"
24#include "frontends/p4/simplify.h"
25#include "frontends/p4/typeChecking/typeChecker.h"
26#include "frontends/p4/typeMap.h"
27#include "interpreter.h"
50 static bool repOk(
const IR::Expression *expr);
56 const IR::Expression *variable;
69typedef std::unordered_map<StackVariable, size_t, StackVariableHash> StackVariableMap;
70typedef std::unordered_map<StackVariable, const IR::Expression *, StackVariableHash>
71 StackVariableIndexMap;
75 friend class ParserStateRewriter;
77 const IR::P4Parser *parser;
78 const IR::ParserState *state;
82 IR::ParserState *newState;
84 StackVariableMap statesIndexes;
86 std::unordered_set<cstring> scenarioStates;
87 std::unordered_set<cstring> scenarioHS;
88 StackVariableIndexMap substitutedIndexes;
94 predecessor(predecessor),
103 statesIndexes = predecessor->statesIndexes;
104 scenarioHS = predecessor->scenarioHS;
105 substitutedIndexes = predecessor->substitutedIndexes;
114 std::map<cstring, std::vector<ParserStateInfo *> *> states;
117 std::vector<ParserStateInfo *> *get(
cstring origState) {
118 std::vector<ParserStateInfo *> *vec;
119 auto it = states.find(origState);
120 if (it == states.end()) {
121 vec =
new std::vector<ParserStateInfo *>;
122 states.emplace(origState, vec);
129 cstring origState = si->state->name.name;
130 auto vec = get(origState);
133 std::map<cstring, std::vector<ParserStateInfo *> *> &getStates() {
return states; }
140 friend class ParserStateRewriter;
141 friend class ParserSymbolicInterpreter;
143 std::map<cstring, const IR::ParserState *> stateMap;
146 const IR::P4Parser *parser;
147 const IR::ParserState *start;
150 std::map<cstring, std::set<cstring>> statesWithHeaderStacks;
151 std::map<cstring, size_t> callsIndexes;
152 void setParser(
const IR::P4Parser *parser) {
155 this->parser = parser;
158 void addState(
const IR::ParserState *state) { stateMap.emplace(state->name, state); }
159 const IR::ParserState *get(
cstring state)
const { return ::P4::get(stateMap, state); }
160 void calls(
const IR::ParserState *caller,
const IR::ParserState *callee) {
161 callGraph->calls(caller, callee);
172 void addStateHSUsage(
const IR::ParserState *state,
const IR::Expression *expression);
178 const IR::ParserState *currentState;
182 : refMap(refMap), current(current), currentState(
nullptr) {
185 setName(
"AnalyzeParser");
186 visitDagOnce =
false;
189 bool preorder(
const IR::P4Parser *parser)
override {
190 LOG2(
"Scanning " << parser);
191 current->setParser(parser);
194 bool preorder(
const IR::ParserState *state)
override;
195 void postorder(
const IR::ParserState *state)
override;
196 void postorder(
const IR::ArrayIndex *array)
override;
197 void postorder(
const IR::Member *member)
override;
198 void postorder(
const IR::PathExpression *expression)
override;
207 bool hasOutOfboundState;
213 setName(
"ParserRewriter");
216 [
this, refMap, typeMap, unroll](void) {
217 hasOutOfboundState = current.analyze(refMap, typeMap, unroll, wasError);
233 : refMap(refMap), typeMap(typeMap), unroll(unroll) {
236 setName(
"RewriteAllParsers");
243 rewriter->setCalledBy(
this);
244 parser->apply(*rewriter);
245 if (rewriter->wasError) {
249 BUG_CHECK(rewriter->current.result,
250 "No result was found after unrolling of the parser loop");
251 IR::P4Parser *newParser = parser->clone();
253 newParser->states.clear();
254 if (rewriter->hasOutOfboundState) {
257 arguments->push_back(
new IR::Argument(IR::BoolLiteral::get(
false)));
258 arguments->push_back(
new IR::Argument(
259 new IR::Member(
new IR::TypeNameExpression(
new IR::Type_Name(
IR::ID(
"error"))),
260 IR::ID(
"StackOutOfBounds"))));
263 parameters.push_back(
264 new IR::Parameter(
IR::ID(
"check"), IR::Direction::In, IR::Type::Boolean::get()));
265 parameters.push_back(
new IR::Parameter(
IR::ID(
"toSignal"), IR::Direction::In,
266 new IR::Type_Name(
IR::ID(
"error"))));
267 components.push_back(
new IR::MethodCallStatement(
new IR::MethodCallExpression(
268 IR::Type::Void::get(),
269 new IR::PathExpression(
270 new IR::Type_Method(IR::Type::Void::get(),
new IR::ParameterList(parameters),
272 new IR::Path(
IR::ID(
"verify"))),
274 auto *outOfBoundsState =
new IR::ParserState(
276 new IR::PathExpression(IR::Type_State::get(),
277 new IR::Path(IR::ParserState::reject,
false)));
278 newParser->states.push_back(outOfBoundsState);
280 for (
auto &i : rewriter->current.result->states) {
281 for (
auto &j : *i.second)
283 if (rewriter->hasOutOfboundState &&
284 j->newState->name.name ==
"stateOutOfBound") {
287 newParser->states.push_back(j->newState);
291 newParser->states.push_back(
new IR::ParserState(IR::ParserState::accept,
nullptr));
292 newParser->states.push_back(
new IR::ParserState(IR::ParserState::reject,
nullptr));
304 setName(
"ParsersUnroll");
Definition parserUnroll.h:175
Definition callGraph.h:41
Information produced for a parser by the symbolic evaluator.
Definition parserUnroll.h:111
Definition parserUnroll.h:202
Information about a parser in the input program.
Definition parserUnroll.h:139
bool reachableHSUsage(IR::ID id, const ParserStateInfo *state) const
check reachability for usage of header stack
Definition parserUnroll.cpp:878
void evaluateReachability()
evaluates rechable states with HS operations for each path.
void addStateHSUsage(const IR::ParserState *state, const IR::Expression *expression)
add HS name which is used in a current state.
Definition parserUnroll.cpp:898
Definition parserUnroll.h:297
Definition ir/pass_manager.h:40
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
Definition parserUnroll.h:226
const IR::Node * postorder(IR::P4Parser *parser) override
Definition parserUnroll.h:240
Class with hash function for StackVariable.
Definition parserUnroll.h:64
Definition parserUnroll.h:45
static bool repOk(const IR::Expression *expr)
Determines whether @expr can represent a StateVariable.
Definition parserUnroll.cpp:16
StackVariable(const IR::Expression *expr)
Implicitly converts IR::Expression* to a StackVariable.
Definition parserUnroll.cpp:10
Definition typeChecker.h:55
Definition interpreter.h:71
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
const char outOfBoundsStateName[]
Name of out of bound state.
Definition parserUnroll.h:33
Information produced for a parser state by the symbolic evaluator.
Definition parserUnroll.h:74