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

Conversation

VolodymyrPeschanenkoIntel
Copy link
Contributor

These changes fix bug of parserUnroll which appears in issue561-6-bmv2.p4 example.
This example contains the following code:

state parseO1O1 {
        packet.extract(hdr.u.next.byte);
        packet.extract(hdr.u.next.byte);
        transition accept;
}

ParserUnroll generated the following state before these changes:

state parseO1O1 {
        packet.extract(hdr.u[0].byte);
        packet.extract(hdr.u[0].byte);  /* <= here should be hdr.u[1].byte, according to the semantics of a next operator. */
        transition accept;
}

@fruffy
Copy link
Collaborator

fruffy commented Apr 8, 2022

Any way to write a test for this? It will take a while until the loops unrolling pull request for p4test is in.

Copy link
Collaborator

@fruffy fruffy left a comment

Choose a reason for hiding this comment

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

Looks fine from my point of view. @mbudiu-vmw any comments?

}
if (expression->member.name == IR::Type_Stack::lastIndex) {
return new IR::Constant(IR::Type_Bits::get(32), idx);
} else {
state->statesIndexes[expression->expr->toString()] = idx;
state->statesIndexes[expression->expr->toString()] = idx + offset;
Copy link
Collaborator

Choose a reason for hiding this comment

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

expression->expr->toString() is there no better way to map this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

clone_id can't be applied here. It is possible to implement operator< for IR::Member, but IR::Member::member still contains cstring. So, for now, I think that this is the best solution.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

clone_id can't be applied here. It is possible to implement operator< for IR::Member, but IR::Member::member still contains cstring. So, for now, I think that this is the best solution.

Copy link
Contributor

Choose a reason for hiding this comment

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

node->toString() should only be used for reporting user messages.
Such usage in the compiler is unsafe, since the different expressions may generate identical toString outputs.

@mihaibudiu
Copy link
Contributor

The spec does actually not mandate this behavior. The spec says that nextIndex should only be incremented if extracting directly to next. You can argue that this is a bug in the spec, but we should first take this change to the language design committee.

@mihaibudiu
Copy link
Contributor

@mihaibudiu
Copy link
Contributor

Filed p4lang/p4-spec#1048

}
if (expression->member.name == IR::Type_Stack::lastIndex) {
return new IR::Constant(IR::Type_Bits::get(32), idx);
} else {
state->statesIndexes[expression->expr->toString()] = idx;
state->statesIndexes[expression->expr->toString()] = idx + offset;
Copy link
Contributor

Choose a reason for hiding this comment

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

node->toString() should only be used for reporting user messages.
Such usage in the compiler is unsafe, since the different expressions may generate identical toString outputs.

@VolodymyrPeschanenkoIntel
Copy link
Contributor Author

I added StackVariable class to support std::map<IR::Member, ...>

midend/parserUnroll.cpp Outdated Show resolved Hide resolved
const IR::Expression& operator*() const { return *expr; }
const IR::Expression* operator->() const { return expr; }

// 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<

midend/parserUnroll.h Outdated Show resolved Hide resolved
midend/parserUnroll.h Outdated Show resolved Hide resolved
midend/parserUnroll.h Outdated Show resolved Hide resolved
midend/parserUnroll.h Outdated Show resolved Hide resolved
break;
else
idx = i;
unsigned offset = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

can you explain what is happening here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if it is a next operator then we need to make offset = 1, otherwise it should be 0. I did some refactoring there.

@mihaibudiu
Copy link
Contributor

You do not seem to have addressed the comments made in my previous review.

@VolodymyrPeschanenkoIntel
Copy link
Contributor Author

The spec does actually not mandate this behavior. The spec says that nextIndex should only be incremented if extracting directly to next. You can argue that this is a bug in the spec, but we should first take this change to the language design committee.

It looks very strange, because in the documentation of P4C we have:
hs.next: produces a reference to the element with index hs.nextIndex in the stack. May only be used in a parser. If the stack's nextIndex counter is greater than or equal to size, then evaluating this expression results in a transition to reject and sets the error to error.StackOutOfBounds. If hs is an l-value, then hs.next is also an l-value.
As I can see there are no restrictions for operator next usage. So, I think that we need to increment index of a header stack for next operator independently of a place where we use it. Am I right?

@mihaibudiu
Copy link
Contributor

The spec does actually not mandate this behavior. The spec says that nextIndex should only be incremented if extracting directly to next. You can argue that this is a bug in the spec, but we should first take this change to the language design committee.

It looks very strange, because in the documentation of P4C we have: hs.next: produces a reference to the element with index hs.nextIndex in the stack. May only be used in a parser. If the stack's nextIndex counter is greater than or equal to size, then evaluating this expression results in a transition to reject and sets the error to error.StackOutOfBounds. If hs is an l-value, then hs.next is also an l-value. As I can see there are no restrictions for operator next usage. So, I think that we need to increment index of a header stack for next operator independently of a place where we use it. Am I right?

See https://p4.org/p4-spec/docs/P4-16-v1.2.2.html#sec-packet-extract-one, in particular the pseudo-code for extract. It says nothing about header_unions. That is arguably wrong, but it should be changed if it is wrong.

@VolodymyrPeschanenkoIntel
Copy link
Contributor Author

The spec does actually not mandate this behavior. The spec says that nextIndex should only be incremented if extracting directly to next. You can argue that this is a bug in the spec, but we should first take this change to the language design committee.

It looks very strange, because in the documentation of P4C we have: hs.next: produces a reference to the element with index hs.nextIndex in the stack. May only be used in a parser. If the stack's nextIndex counter is greater than or equal to size, then evaluating this expression results in a transition to reject and sets the error to error.StackOutOfBounds. If hs is an l-value, then hs.next is also an l-value. As I can see there are no restrictions for operator next usage. So, I think that we need to increment index of a header stack for next operator independently of a place where we use it. Am I right?

See https://p4.org/p4-spec/docs/P4-16-v1.2.2.html#sec-packet-extract-one, in particular the pseudo-code for extract. It says nothing about header_unions. That is arguably wrong, but it should be changed if it is wrong.

I see. So, you said that "we should first take this change to the language design committee". How to do that?

@jnfoster
Copy link
Contributor

For a change like this, which is sort of a bug fix, you can propose a PR on the p4-spec repository. Then we'll discuss at the next LDWG.

midend/parserUnroll.cpp Outdated Show resolved Hide resolved
midend/parserUnroll.cpp Outdated Show resolved Hide resolved
@VolodymyrPeschanenkoIntel
Copy link
Contributor Author

@fruffy, @mbudiu-vmw Can we merge it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants