Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing parserUnroll bug for sequential next operator usage #3193

Merged
merged 14 commits into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 15 additions & 57 deletions midend/parserUnroll.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "parserUnroll.h"
#include "interpreter.h"
#include "lib/hash.h"
#include "lib/stringify.h"
#include "ir/ir.h"

Expand All @@ -23,75 +24,32 @@ bool StackVariable::repOk(const IR::Expression* expr) {
return member->expr->is<IR::PathExpression>() || repOk(member->expr);
}

bool StackVariable::operator<(const StackVariable& other) const {
return compare(member, other.member) < 0;
}

bool StackVariable::operator==(const StackVariable& other) const {
// Delegate to IR's notion of equality.
return *member == *other.member;
}

int StackVariable::compare(const IR::Expression* e1, const IR::Expression* e2) {
if (const auto* m1 = e1->to<IR::Member>()) {
return compare(m1, e2);
}
if (const auto* p1 = e1->to<IR::PathExpression>()) {
return compare(p1, e2);
}
BUG("Not a valid StateVariable: %1%", e1);
}

int StackVariable::compare(const IR::Member* m1, const IR::Expression* e2) {
if (const auto* m2 = e2->to<IR::Member>()) {
return compare(m1, m2);
}
if (e2->is<IR::PathExpression>()) {
return 1;
}
BUG("Not a valid StateVariable: %1%", e2);
}

int StackVariable::compare(const IR::Member* m1, const IR::Member* m2) {
auto result = compare(m1->expr, m2->expr);
if (result != 0) {
return result;
}
if (m1->member.name < m2->member.name) {
return -1;
}
if (m1->member.name > m2->member.name) {
return 1;
}
return 0;
}

int StackVariable::compare(const IR::PathExpression* p1, const IR::Expression* e2) {
if (const auto* p2 = e2->to<IR::PathExpression>()) {
return compare(p1, p2);
}
if (e2->is<IR::Member>()) {
return -1;
}
BUG("Not a valid StateVariable: %1%", e2);
}

int StackVariable::compare(const IR::PathExpression* p1, const IR::PathExpression* p2) {
if (p1->path->name.name < p2->path->name.name) {
return -1;
}
if (p1->path->name.name > p2->path->name.name) {
return 1;
size_t StackVariableHash::operator()(const StackVariable& var) const {
const IR::Member* curMember = var.operator->();
std::vector<size_t> h;
while(curMember) {
VolodymyrPeschanenkoIntel marked this conversation as resolved.
Show resolved Hide resolved
h.push_back(Util::Hash::fnv1a<const cstring>(curMember->member.name));
if (auto* path = curMember->expr->to<IR::PathExpression>()) {
h.push_back(Util::Hash::fnv1a<const cstring>(path->path->name));
break;
}
BUG_CHECK(curMember->expr->is<IR::Member>(), "Not a valid StateVariable: %1%", curMember);
VolodymyrPeschanenkoIntel marked this conversation as resolved.
Show resolved Hide resolved
curMember = curMember->expr->to<IR::Member>();
}
return 0;
return Util::Hash::fnv1a(h.data(), sizeof(size_t) * h.size());
}

/// The main class for parsers' states key for visited checking.
struct VisitedKey {
cstring name; // name of a state.
std::map<StackVariable, size_t> indexes; // indexes of header stacks.
StackVariableMap indexes; // indexes of header stacks.

VisitedKey(cstring name, std::map<StackVariable, size_t>& indexes)
VisitedKey(cstring name, StackVariableMap& indexes)
: name(name), indexes(indexes) {}

explicit VisitedKey(const ParserStateInfo* stateInfo) {
Expand Down
24 changes: 11 additions & 13 deletions midend/parserUnroll.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
#ifndef _MIDEND_PARSERUNROLL_H_
#define _MIDEND_PARSERUNROLL_H_

#include <unordered_map>

#include "ir/ir.h"
#include "frontends/common/resolveReferences/referenceMap.h"
#include "frontends/p4/callGraph.h"
Expand Down Expand Up @@ -51,28 +53,24 @@ class StackVariable {
const IR::Member* operator->() const { return member; }

// Implements comparisons so that StateVariables can be used as map keys.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use unordered_map you only need equality and hash.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does p4c have some hash for IR::Expression? I used std::map. So, I turned back to operator<

bool operator<(const StackVariable& other) const;
bool operator==(const StackVariable& other) const;

private:
const IR::Member* member;

// Returns a negative value if e1 < e2, zero if e1 == e2, and a positive value otherwise.
// In these comparisons,
// * PathExpressions < Members.
// * PathExpressions are ordered on the name contained in their Paths.
// * Members are ordered first by their expressions, then by their member.
static int compare(const IR::Expression* e1, const IR::Expression* e2);
static int compare(const IR::Member* m1, const IR::Expression* e2);
static int compare(const IR::Member* m1, const IR::Member* m2);
static int compare(const IR::PathExpression* p1, const IR::Expression* e2);
static int compare(const IR::PathExpression* p1, const IR::PathExpression* p2);

public:
/// Implicitly converts IR::Expression* to a StackVariable.
StackVariable(const IR::Expression* expr); // NOLINT(runtime/explicit)
};

/// Class with hash function for @a StackVariable.
class StackVariableHash {
public:
size_t operator()(const StackVariable& var) const;
};

typedef std::unordered_map<StackVariable, size_t, StackVariableHash> StackVariableMap;

/// Information produced for a parser state by the symbolic evaluator
struct ParserStateInfo {
friend class ParserStateRewriter;
Expand All @@ -84,7 +82,7 @@ struct ParserStateInfo {
ValueMap* after;
IR::ParserState* newState; // pointer to a new state
size_t currentIndex;
std::map<StackVariable, size_t> statesIndexes; // global map in state indexes
StackVariableMap statesIndexes; // global map in state indexes
// set of parsers' states names with are in current path.
std::unordered_set<cstring> scenarioStates;
std::unordered_set<cstring> scenarioHS; // scenario header stack's operations
Expand Down