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 ::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:877
 
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:897
 
Definition parserUnroll.h:297
 
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
 
Definition pass_manager.h:38
 
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