Skip to content

Commit 8b2b827

Browse files
committed
Allow multiple declarators in a declaration
Signed-off-by: Chris Dodd <cdodd@nvidia.com>
1 parent 22067d0 commit 8b2b827

9 files changed

Lines changed: 398 additions & 50 deletions

File tree

frontends/parsers/p4/p4parser.ypp

Lines changed: 100 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,14 @@ inline std::ostream& operator<<(std::ostream& out, const OptionalConst& oc) {
7979
// forbidden in C++. We avoid the problem using a typedef.
8080
typedef const IR::Type ConstType;
8181

82-
struct NameTypePair {
82+
struct DeclaratorInfo {
83+
Util::SourceInfo srcInfo;
8384
IR::ID name;
8485
const IR::Type *type;
86+
const IR::Expression *init;
8587
};
8688

87-
inline std::ostream &operator<<(std::ostream &out, const NameTypePair &nt) {
89+
inline std::ostream &operator<<(std::ostream &out, const DeclaratorInfo &nt) {
8890
return out << nt.name << ":" << nt.type;
8991
}
9092

@@ -107,7 +109,7 @@ class Token {
107109

108110
Token() : Token(0, cstring::empty, nullptr) { }
109111
Token(int type, cstring text) : Token(type, text, nullptr) { }
110-
Token(int type, const char* text) : Token(type, cstring(text), nullptr) { }
112+
Token(int type, const char* text) : Token(type, cstring(text), nullptr) { }
111113
Token(int type, UnparsedConstant unparsedConstant)
112114
: Token(type, unparsedConstant.text,
113115
new UnparsedConstant(unparsedConstant)) { }
@@ -261,7 +263,8 @@ using namespace P4;
261263

262264

263265
%type<IR::ID> name dot_name nonTypeName nonTableKwName annotationName
264-
%type<NameTypePair> declarator
266+
%type<DeclaratorInfo> declarator
267+
%type<std::vector<DeclaratorInfo>> declaratorList initDeclaratorList
265268
%type<IR::Direction> direction
266269
%type<IR::Path*> prefixedNonTypeName prefixedType
267270
%type<IR::TypeParameters*> optTypeParameters typeParameters typeParameterList
@@ -296,20 +299,20 @@ using namespace P4;
296299
forStatement breakStatement continueStatement
297300
%type<IR::BlockStatement*> blockStatement parserBlockStatement controlBody
298301
optObjInitializer
299-
%type<IR::StatOrDecl*> statementOrDeclaration parserStatement
300-
declOrAssignmentOrMethodCallStatement
301-
%type<IR::IndexedVector<IR::StatOrDecl>> objDeclarations statOrDeclList parserStatements
302+
%type<IR::StatOrDecl*> declOrAssignmentOrMethodCallStatement
303+
%type<IR::IndexedVector<IR::StatOrDecl>> objDeclarations parserStatement
304+
statementOrDeclaration parserStatements statOrDeclList
302305
forInitStatements forInitStatementsNonEmpty
303306
forUpdateStatements forUpdateStatementsNonEmpty
304307
%type<IR::SwitchCase*> switchCase
305308
%type<IR::Vector<IR::SwitchCase>> switchCases
306309
%type<IR::Vector<IR::Type>> typeArgumentList realTypeArgumentList
307310
%type<IR::ParserState*> parserState
308-
%type<IR::IndexedVector<IR::ParserState>> parserStates
309-
%type<IR::Declaration*> constantDeclaration actionDeclaration
310-
variableDeclaration variableDeclarationWithoutSemicolon instantiation functionDeclaration
311-
objDeclaration tableDeclaration controlLocalDeclaration
312-
parserLocalElement valueSetDeclaration
311+
%type<IR::IndexedVector<IR::ParserState>> parserStates
312+
%type<IR::IndexedVector<IR::Declaration>> constantDeclaration variableDeclaration parserLocalElement controlLocalDeclaration
313+
%type<IR::Declaration*> actionDeclaration variableDeclarationWithoutSemicolon instantiation
314+
functionDeclaration objDeclaration tableDeclaration
315+
valueSetDeclaration
313316
%type<IR::Type_Declaration*> headerTypeDeclaration structTypeDeclaration
314317
headerUnionDeclaration derivedTypeDeclaration
315318
parserDeclaration controlDeclaration enumDeclaration
@@ -321,8 +324,7 @@ using namespace P4;
321324
%type<IR::Type_Parser*> parserTypeDeclaration
322325
%type<IR::Type_Control*> controlTypeDeclaration
323326
%type<IR::IndexedVector<IR::Declaration>> parserLocalElements controlLocalDeclarations
324-
%type<IR::StructField*> structField
325-
%type<IR::IndexedVector<IR::StructField>> structFieldList
327+
%type<IR::IndexedVector<IR::StructField>> structField structFieldList
326328
%type<IR::IndexedVector<IR::SerEnumMember>> specifiedIdentifierList
327329
%type<IR::SerEnumMember*> specifiedIdentifier
328330
%type<IR::Method*> methodPrototype functionPrototype
@@ -479,14 +481,18 @@ p4rtControllerType
479481
program : input END { YYACCEPT; };
480482

481483
input
482-
: %empty { driver.result = $$ = new IR::P4Program; }
483-
| input declaration { if ($2) $1->objects.push_back($2->getNode());
484-
$$ = $1; }
485-
| input ";" { $$ = $1; } // empty declaration
484+
: %empty { driver.result = $$ = new IR::P4Program; }
485+
| input declaration { $$ = $1;
486+
if (!$2) { /* do nothing */ }
487+
else if (auto *v = $2->to<IR::VectorBase>())
488+
$$->objects.append(*v);
489+
else
490+
$$->objects.push_back($2); }
491+
| input ";" { $$ = $1; } // empty declaration
486492
;
487493

488494
declaration
489-
: constantDeclaration { $$ = $1; }
495+
: constantDeclaration { $$ = new IR::IndexedVector<IR::Declaration>(std::move($1)); }
490496
| externDeclaration { $$ = $1; }
491497
| actionDeclaration { $$ = $1; }
492498
| parserDeclaration { $$ = $1; }
@@ -832,14 +838,14 @@ parserDeclaration
832838

833839
parserLocalElements
834840
: %empty { $$ = {}; }
835-
| parserLocalElements parserLocalElement { ($$ = std::move($1)).push_back($2); $$.srcInfo = @1 + @2; }
841+
| parserLocalElements parserLocalElement { ($$ = std::move($1)).append($2); $$.srcInfo = @1 + @2; }
836842
;
837843

838844
parserLocalElement
839-
: constantDeclaration { $$ = $1; }
840-
| instantiation { $$ = $1; }
841-
| variableDeclaration { $$ = $1; }
842-
| valueSetDeclaration { $$ = $1; }
845+
: constantDeclaration { $$ = std::move($1); }
846+
| instantiation { $$.push_back($1); }
847+
| variableDeclaration { $$ = std::move($1); }
848+
| valueSetDeclaration { $$.push_back($1); }
843849
;
844850

845851
parserTypeDeclaration
@@ -867,16 +873,16 @@ parserState
867873

868874
parserStatements
869875
: %empty { $$ = {}; }
870-
| parserStatements parserStatement { ($$ = std::move($1)).push_back($2); $$.srcInfo = @1 + @2; }
876+
| parserStatements parserStatement { ($$ = std::move($1)).append($2); $$.srcInfo = @1 + @2; }
871877
;
872878

873879
parserStatement
874-
: assignmentOrMethodCallStatement { $$ = $1; }
875-
| emptyStatement { $$ = $1; }
876-
| variableDeclaration { $$ = $1; }
877-
| constantDeclaration { $$ = $1; }
878-
| parserBlockStatement { $$ = $1; }
879-
| conditionalStatement { $$ = $1; }
880+
: assignmentOrMethodCallStatement { $$.push_back($1); }
881+
| emptyStatement { $$.push_back($1); }
882+
| variableDeclaration { for (auto *decl : $1) $$.push_back(decl); }
883+
| constantDeclaration { for (auto *decl : $1) $$.push_back(decl); }
884+
| parserBlockStatement { $$.push_back($1); }
885+
| conditionalStatement { $$.push_back($1); }
880886
;
881887

882888
parserBlockStatement
@@ -982,14 +988,16 @@ controlTypeDeclaration
982988

983989
controlLocalDeclarations
984990
: %empty { $$ = {}; }
985-
| controlLocalDeclarations controlLocalDeclaration { ($$ = std::move($1)).push_back($2); $$.srcInfo = @1 + @2; }
991+
| controlLocalDeclarations controlLocalDeclaration {
992+
($$ = std::move($1)).append($2);
993+
$$.srcInfo = @1 + @2; }
986994
;
987995

988996
controlLocalDeclaration
989997
: constantDeclaration { $$ = $1; }
990-
| actionDeclaration { $$ = $1; }
991-
| tableDeclaration { $$ = $1; }
992-
| instantiation { $$ = $1; }
998+
| actionDeclaration { $$.push_back($1); }
999+
| tableDeclaration { $$.push_back($1); }
1000+
| instantiation { $$.push_back($1); }
9931001
| variableDeclaration { $$ = $1; }
9941002
;
9951003

@@ -1203,12 +1211,22 @@ headerUnionDeclaration
12031211

12041212
structFieldList
12051213
: %empty { $$ = {}; }
1206-
| structFieldList structField { ($$ = std::move($1)).push_back($2); $$.srcInfo = @1 + @2; }
1214+
| structFieldList structField { ($$ = std::move($1)).append($2); $$.srcInfo = @1 + @2; }
12071215
;
12081216

12091217
structField
1210-
: optAnnotations typeRef declarator ";" {
1211-
$$ = new IR::StructField(@3, $3.name, std::move($1), $3.type); }
1218+
: optAnnotations typeRef declaratorList ";" {
1219+
for (auto &decl : $3)
1220+
$$.push_back(new IR::StructField(decl.srcInfo, decl.name, std::move($1), decl.type)); }
1221+
;
1222+
1223+
declaratorList
1224+
: declarator { $$.emplace_back($1); }
1225+
| declaratorList "," <ConstType*>{ $$ = $<ConstType*>0; } declarator {
1226+
if ($1.size() == 1)
1227+
warning(ErrorType::WARN_EXTENSION,
1228+
"%1%Multiple declarators is a non-standard extension", @4);
1229+
($$=$1).emplace_back($4); }
12121230
;
12131231

12141232
enumDeclaration
@@ -1352,7 +1370,7 @@ blockStatement
13521370

13531371
statOrDeclList
13541372
: %empty { $$ = {}; }
1355-
| statOrDeclList statementOrDeclaration { ($$ = std::move($1)).push_back($2);
1373+
| statOrDeclList statementOrDeclaration { ($$ = std::move($1)).append($2);
13561374
$$.srcInfo = @1 + @2; }
13571375
;
13581376

@@ -1377,14 +1395,14 @@ switchLabel
13771395
;
13781396

13791397
statementOrDeclaration
1380-
: variableDeclaration { $$ = $1; }
1381-
| constantDeclaration { $$ = $1; }
1382-
| statement { $$ = $1; }
1398+
: variableDeclaration { for (auto *decl : $1) $$.push_back(decl); }
1399+
| constantDeclaration { for (auto *decl : $1) $$.push_back(decl); }
1400+
| statement { $$.push_back($1); }
13831401
// The transition to instantiation below is not required by the
13841402
// languge spec, but it does help p4c give a more clear error
13851403
// message if one erroneously attempts to perform an
13861404
// instantiation inside of a block.
1387-
| instantiation { $$ = $1; }
1405+
| instantiation { $$.push_back($1); }
13881406
;
13891407

13901408
forStatement
@@ -1529,7 +1547,16 @@ actionDeclaration
15291547
/************************* VARIABLES *****************************/
15301548

15311549
variableDeclaration
1532-
: variableDeclarationWithoutSemicolon ";" { $$ = $1; }
1550+
: annotations typeRef initDeclaratorList ";" {
1551+
for (auto &decl : $3) {
1552+
$$.push_back(new IR::Declaration_Variable(decl.srcInfo, decl.name, std::move($1),
1553+
decl.type, decl.init));
1554+
driver.structure->declareObject(decl.name, decl.type->toString()); } }
1555+
| typeRef initDeclaratorList ";" {
1556+
for (auto &decl : $2) {
1557+
$$.push_back(new IR::Declaration_Variable(decl.srcInfo, decl.name,
1558+
decl.type, decl.init));
1559+
driver.structure->declareObject(decl.name, decl.type->toString()); } }
15331560
;
15341561

15351562
variableDeclarationWithoutSemicolon
@@ -1542,15 +1569,26 @@ variableDeclarationWithoutSemicolon
15421569
;
15431570

15441571
constantDeclaration
1545-
: optAnnotations CONST typeRef declarator "=" initializer ";" {
1546-
$$ = new IR::Declaration_Constant(@4, $4.name, std::move($1), $4.type, $6);
1547-
driver.structure->declareObject($4.name, $4.type->toString()); }
1572+
: optAnnotations CONST typeRef initDeclaratorList ";" {
1573+
for (auto &decl : $4) {
1574+
if (!decl.init)
1575+
P4::error(ErrorType::ERR_EXPECTED,
1576+
"Const %1% declaration requires an initializer", decl.name);
1577+
$$.push_back(new IR::Declaration_Constant(decl.srcInfo, decl.name, std::move($1),
1578+
decl.type, decl.init));
1579+
driver.structure->declareObject(decl.name, decl.type->toString()); } }
15481580
;
15491581

15501582
declarator
1551-
: name { $$.name = $1; $$.type = $<ConstType *>0; }
1552-
| declarator "[" expression "]"
1553-
{ $$ = $1; $$.type = new IR::Type_Array(@2+@4, $1.type, $3); }
1583+
: name { $$.srcInfo = @1;
1584+
$$.name = $1;
1585+
$$.type = $<ConstType *>0;
1586+
$$.init = nullptr; }
1587+
| declarator "[" expression "]" {
1588+
$$ = $1;
1589+
$$.srcInfo += @4;
1590+
$$.type = new IR::Type_Array(@2+@4, $1.type, $3);
1591+
$$.init = nullptr; }
15541592
;
15551593

15561594
optInitializer
@@ -1562,6 +1600,18 @@ initializer
15621600
: expression { $$ = $1; }
15631601
;
15641602

1603+
initDeclaratorList
1604+
: declarator optInitializer {
1605+
$$.emplace_back($1);
1606+
$$.back().init = $2; }
1607+
| initDeclaratorList "," <ConstType*>{ $$ = $<ConstType*>0; } declarator optInitializer {
1608+
if ($1.size() == 1)
1609+
warning(ErrorType::WARN_EXTENSION,
1610+
"%1%Multiple declarators is a non-standard extension", @4);
1611+
($$=$1).emplace_back($4);
1612+
$$.back().init = $5; }
1613+
;
1614+
15651615
/**************** Expressions ****************/
15661616

15671617
functionDeclaration

lib/error_catalog.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ std::map<int, cstring> ErrorCatalog::errorCatalog = {
6666
{ErrorType::WARN_DUPLICATE, "duplicate"_cs},
6767
{ErrorType::WARN_BRANCH_HINT, "branch"_cs},
6868
{ErrorType::WARN_TABLE_KEYS, "keys"_cs},
69+
{ErrorType::WARN_EXTENSION, "extension"_cs},
6970

7071
// Info messages
7172
{ErrorType::INFO_INFERRED, "inferred"_cs},
@@ -76,6 +77,9 @@ void ErrorCatalog::initReporter(ErrorReporter &reporter) {
7677
// by default, ignore warnings about branch hints -- user can turn them
7778
// on with --Wwarn=branch
7879
reporter.setDiagnosticAction("branch"_cs, DiagnosticAction::Ignore);
80+
// by default, ignore warnings about extensions -- user can turn them
81+
// on with --Wwarn=extension
82+
reporter.setDiagnosticAction("extension"_cs, DiagnosticAction::Ignore);
7983
}
8084

8185
} // namespace P4

lib/error_catalog.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class ErrorType {
8282
static constexpr int WARN_DUPLICATE = 1025; // duplicate objects
8383
static constexpr int WARN_BRANCH_HINT = 1026; // branch frequency/likely hints
8484
static constexpr int WARN_TABLE_KEYS = 1027; // something is wrong with a table key
85+
static constexpr int WARN_EXTENSION = 1028; // non-standard extension
8586
// Backends should extend this class with additional warnings in the range 1500-2141.
8687
static constexpr int WARN_MIN_BACKEND = 1500; // first allowed backend warning code
8788
static constexpr int WARN_MAX = 2141; // last allowed warning code
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <core.p4>
2+
3+
header ethernet_t {
4+
bit<48> dst_addr, src_addr;
5+
bit<16> eth_type;
6+
}
7+
8+
header ipv4_t {
9+
bit<4> version, ihl;
10+
bit<8> diffserv;
11+
bit<16> totalLen, identification;
12+
bit<3> flags;
13+
bit<13> fragOffset;
14+
bit<8> ttl, protocol;
15+
bit<16> hdrChecksum;
16+
bit<32> srcAddr, dstAddr;
17+
}
18+
19+
struct Headers {
20+
ethernet_t eth_hdr;
21+
ipv4_t ip_hdr;
22+
}
23+
24+
control ingress(inout Headers h) {
25+
bit<32> addr, temp;
26+
action dummy_action() { }
27+
table t1 {
28+
key = { addr : exact; }
29+
actions = {
30+
dummy_action();
31+
}
32+
}
33+
apply {
34+
if (h.ip_hdr.protocol > 5) {
35+
addr = h.ip_hdr.srcAddr;
36+
temp = h.eth_hdr.src_addr[31:0];
37+
} else {
38+
addr = h.ip_hdr.dstAddr;
39+
temp = h.eth_hdr.dst_addr[31:0];
40+
}
41+
t1.apply();
42+
}
43+
}
44+
45+
control c<H>(inout H h);
46+
package top<H>(c<H> c);
47+
top(ingress()) main;

0 commit comments

Comments
 (0)