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

Which kinds of P4_16 objects should be allowed to have the same name? #1932

Closed
jafingerhut opened this issue May 9, 2019 · 13 comments
Closed
Assignees
Labels
bug This behavior is unintended and should be fixed. fixed This topic is considered to be fixed.

Comments

@jafingerhut
Copy link
Contributor

For example, latest p4test as of 2019-May-08 gives no error for this program, which gives the name foo to both an action defined at the top level, and a control declaration.

#include <core.p4>
#include <v1model.p4>
// nameconflict-actionDeclaration-controlDeclaration.p4
action foo (in bit<8> x, out bit<8> y) { y = (x >> 2); }
control foo (in bit<8> x, out bit<8> y) { apply { y = x + 7; } }

struct headers_t { }
struct metadata_t { }
parser parserImpl(packet_in packet, out headers_t hdr, inout metadata_t meta, inout standard_metadata_t stdmeta) { state start { transition accept; } }
control verifyChecksum(inout headers_t hdr, inout metadata_t meta) { apply { } }
control ingressImpl(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t stdmeta) { apply { } }
control egressImpl(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t stdmeta) { apply { } }
control updateChecksum(inout headers_t hdr, inout metadata_t meta) { apply { } }
control deparserImpl(packet_out packet, in headers_t hdr) { apply { } }
V1Switch(parserImpl(), verifyChecksum(), ingressImpl(), egressImpl(), updateChecksum(), deparserImpl()) main;

I have a simple Python program that produces 20*20=400 little test programs like this, with the same name for each of 20 different "kinds" of named things that can appear at the top level in a P4_16 program.

Most of those 400 programs cause p4test to give an error message like foo duplicates foo or error: Re-declaration of foo with different type: as I would expect, but 36 of those 400 pairs give no error at all. A handful give an error message other than the one I would expect.

This question is motivated by the design of a P4_16 module system. If a module can have multiple named "things" at the top level with the same name, and this is legal, then does that mean we should have a way to import one of those things but not the other? If so, we need something more than just a name to specify which one to import.

@jafingerhut
Copy link
Contributor Author

The 36 that give no errors are the 6*6 programs that consist of one of the list of 6 kinds of things below, followed by another one of the kinds from the same list of 6:

externFunctionDeclaration
functionDeclaration
actionDeclaration
controlDeclaration
parserDeclaration
packageTypeDeclaration

@jafingerhut
Copy link
Contributor Author

jafingerhut commented May 9, 2019

This program gives a completely different error than most of them do. I don't see why, though:

#include <core.p4>
#include <v1model.p4>
// nameconflict-controlDeclaration-externObjectDeclaration.p4
control foo (in bit<8> x, out bit<8> y) { apply { y = x + 7; } }
extern foo { bit<8> methodbar (in bit<8> x); }

struct headers_t { }
struct metadata_t { }
parser parserImpl(packet_in packet, out headers_t hdr, inout metadata_t meta, inout standard_metadata_t stdmeta) { state start { transition accept; } }
control verifyChecksum(inout headers_t hdr, inout metadata_t meta) { apply { } }
control ingressImpl(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t stdmeta) { apply { } }
control egressImpl(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t stdmeta) { apply { } }
control updateChecksum(inout headers_t hdr, inout metadata_t meta) { apply { } }
control deparserImpl(packet_out packet, in headers_t hdr) { apply { } }
V1Switch(parserImpl(), verifyChecksum(), ingressImpl(), egressImpl(), updateChecksum(), deparserImpl()) main;

Error message from p4test I see:

nameconflict-controlDeclaration-externObjectDeclaration.p4(5):syntax error, unexpected {
extern foo {
           ^
error: 1 errors encountered, aborting compilation

EDIT: I also see the same unusual error message if I eliminate the body of control foo and make it just a control type declaration instead, or if I replace the control foo with enum foo { ENUM_CASE1, ENUM_CASE2 }

@jafingerhut
Copy link
Contributor Author

If someone else would like to run these test programs and see the results, or add new test cases for top level things that can have names I neglected to include, the scripts are here: https://github.com/jafingerhut/p4-guide/tree/master/top-level-name-conflicts

@mihaibudiu
Copy link
Contributor

Like the C language, the P4 grammar does lexing and parsing simultaneously. The parser will install new type terminals into the symbol table, and the lexer will subsequently return TYPE for terminals which denote a type, and IDENTIFIER for something else. In your example the second "FOO" is actually a type name, and the grammar does not allow that. Unfortunately such errors come straight from BISON, and are quite uninformative; it's not easy to fix them.

@jafingerhut
Copy link
Contributor Author

Well, I guess the good news is that at least there is an error, rather than no error at all.

Do you have any thoughts on whether the cases that give no error, ought to give an error?

@mihaibudiu
Copy link
Contributor

Some of these should probably be errors.
We allow overloading of functions/controls/parsers, but we still do not really support a parser and a control with the same name. So our checks should also verify that the overloaded objects have the same "kind".

mihaibudiu pushed a commit to mihaibudiu/p4c-clone that referenced this issue May 9, 2019
@mihaibudiu mihaibudiu self-assigned this May 9, 2019
@mihaibudiu mihaibudiu added bug This behavior is unintended and should be fixed. fixed This topic is considered to be fixed. labels May 9, 2019
@jnfoster
Copy link
Contributor

It would be interesting to cross-check these examples with Petr4.

@jafingerhut
Copy link
Contributor Author

@jnfoster Petr4 exits with exit status 0 when run on all 441 of these test P4 programs (increased to 21*21=441 when I added match_kind to the list of top level "kinds" of named things), and the output does not contain the string "error:" in any of them.

This seems to mean that as far as Petr4 is concerned, there is no problem with any of these programs.

Is Petr4 intended to print warning messages I should be looking for? Or is there some other string besides "error:" in the output that signals a problem found?

@jafingerhut
Copy link
Contributor Author

@jnfoster I have added a note to the README at the link below on how to run Petr4 on all 441 of these test programs (as well as how to generate them all), which includes some simple categorization of the results of each run: https://github.com/jafingerhut/p4-guide/tree/master/top-level-name-conflicts

@jafingerhut
Copy link
Contributor Author

I have also run Petr4 on the 2 programs in the zip file attached to issue #1936 and it gives no errors for either of those programs. As I mention both on this issue and that one, I do not know what is considered allowed vs. disallowed same-named "things" according to the P4_16 language spec. If there is something in the spec relevant to this, I'd be happy for a reference to a section within it.

@liujed
Copy link
Member

liujed commented Jun 6, 2019

This question is motivated by the design of a P4_16 module system. If a module can have multiple named "things" at the top level with the same name, and this is legal, then does that mean we should have a way to import one of those things but not the other? If so, we need something more than just a name to specify which one to import.

Here is one possibility for disambiguating:

from m1 import control foo;
from m2 import parser bar;

@jafingerhut
Copy link
Contributor Author

This question is motivated by the design of a P4_16 module system. If a module can have multiple named "things" at the top level with the same name, and this is legal, then does that mean we should have a way to import one of those things but not the other? If so, we need something more than just a name to specify which one to import.

Here is one possibility for disambiguating:

from m1 import control foo;
from m2 import parser bar;

Agreed that would distinguish controls from parsers, and also actions, since we have an action keyword already. It would not distinguish an extern function from a P4 function, which today p4c allows to have the same names without issuing an error.

@jafingerhut
Copy link
Contributor Author

I would like to suggest that the issue of what kinds of things in P4_16 programs can have identical names, and which should not be allowed to have identical names, be brought up at a future P4 language design WG meeting.

I am fine if the answer comes out to be an explicit "these kinds of things X, Y, Z, and W can have common names, and the compiler and other tools must deal with this". For example, the answer might be that the current p4c behavior is what should be allowed. Perhaps even things that p4c currently does not allow to have common names should be allowed (although some cases like allowing a typedef and a type declaration to have a common name seems like a very bad idea to me). Whatever is decided upon, it would be nice to have a brief description of the rules there, since it seems that some people are writing programs that reuse the same names across different categories of things with existing P4 implementations.

Copied from an earlier comment, the latest p4c as of 2019-Jun-21 currently allows any pair of the following 6 kinds of things to have the same name, with no error:

externFunctionDeclaration
functionDeclaration
actionDeclaration
controlDeclaration
parserDeclaration
packageTypeDeclaration

There could be difficulties in specification and/or implementation to keep things this way, though, and I don't claim to know all of them.

For example, allowing externFunctionDeclaration, functionDeclaration, and actionDeclaration things to have the same name seems like it could make it difficult for the compiler to know which one of these things is being called at a call site.

Similarly for allowing controlDeclaration and parserDeclaration to have common names, although one might say that as long as parsers cannot call controls and controls cannot call parsers, calls could be disambiguated that way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This behavior is unintended and should be fixed. fixed This topic is considered to be fixed.
Projects
None yet
Development

No branches or pull requests

4 participants