Skip to content

Commit 6a24261

Browse files
committed
Allow multiple declarators in a declaration
Signed-off-by: Chris Dodd <cdodd@nvidia.com>
1 parent 94272a6 commit 6a24261

9 files changed

Lines changed: 406 additions & 53 deletions

File tree

frontends/parsers/p4/p4parser.ypp

Lines changed: 108 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,14 @@ inline std::ostream& operator<<(std::ostream& out, const OptionalConst& oc) {
8989
// forbidden in C++. We avoid the problem using a typedef.
9090
typedef const IR::Type ConstType;
9191

92-
struct NameTypePair {
92+
struct DeclaratorInfo {
93+
Util::SourceInfo srcInfo;
9394
const IR::ID *name;
9495
const IR::Type *type;
96+
const IR::Expression *init;
9597
};
9698

97-
inline std::ostream &operator<<(std::ostream &out, const NameTypePair &nt) {
99+
inline std::ostream &operator<<(std::ostream &out, const DeclaratorInfo &nt) {
98100
return out << nt.name << ":" << nt.type;
99101
}
100102

@@ -271,7 +273,8 @@ using namespace P4;
271273

272274

273275
%type<IR::ID*> name dot_name nonTypeName nonTableKwName annotationName
274-
%type<NameTypePair> declarator
276+
%type<DeclaratorInfo> declarator
277+
%type<std::vector<DeclaratorInfo>> declaratorList initDeclaratorList
275278
%type<IR::Direction> direction
276279
%type<IR::Path*> prefixedNonTypeName prefixedType
277280
%type<IR::IndexedVector<IR::Type_Var>*> typeParameterList
@@ -308,20 +311,20 @@ using namespace P4;
308311
forStatement breakStatement continueStatement
309312
%type<IR::BlockStatement*> blockStatement parserBlockStatement controlBody
310313
optObjInitializer
311-
%type<IR::StatOrDecl*> statementOrDeclaration parserStatement
312-
declOrAssignmentOrMethodCallStatement
313-
%type<IR::IndexedVector<IR::StatOrDecl>*> objDeclarations statOrDeclList parserStatements
314+
%type<IR::StatOrDecl*> declOrAssignmentOrMethodCallStatement
315+
%type<IR::IndexedVector<IR::StatOrDecl>*> objDeclarations parserStatement
316+
statementOrDeclaration parserStatements statOrDeclList
314317
forInitStatements forInitStatementsNonEmpty
315318
forUpdateStatements forUpdateStatementsNonEmpty
316319
%type<IR::SwitchCase*> switchCase
317320
%type<IR::Vector<IR::SwitchCase>*> switchCases
318321
%type<IR::Vector<IR::Type>*> typeArgumentList realTypeArgumentList
319322
%type<IR::ParserState*> parserState
320323
%type<IR::IndexedVector<IR::ParserState>*> parserStates
321-
%type<IR::Declaration*> constantDeclaration actionDeclaration
322-
variableDeclaration variableDeclarationWithoutSemicolon instantiation functionDeclaration
323-
objDeclaration tableDeclaration controlLocalDeclaration
324-
parserLocalElement valueSetDeclaration
324+
%type<IR::IndexedVector<IR::Declaration>*> constantDeclaration variableDeclaration parserLocalElement controlLocalDeclaration
325+
%type<IR::Declaration*> actionDeclaration variableDeclarationWithoutSemicolon instantiation
326+
functionDeclaration objDeclaration tableDeclaration
327+
valueSetDeclaration
325328
%type<IR::Type_Declaration*> headerTypeDeclaration structTypeDeclaration
326329
headerUnionDeclaration derivedTypeDeclaration
327330
parserDeclaration controlDeclaration enumDeclaration
@@ -332,8 +335,7 @@ using namespace P4;
332335
%type<IR::Type_Parser*> parserTypeDeclaration
333336
%type<IR::Type_Control*> controlTypeDeclaration
334337
%type<IR::IndexedVector<IR::Declaration>*> parserLocalElements controlLocalDeclarations
335-
%type<IR::StructField*> structField
336-
%type<IR::IndexedVector<IR::StructField>*> structFieldList
338+
%type<IR::IndexedVector<IR::StructField>*> structField structFieldList
337339
%type<IR::IndexedVector<IR::SerEnumMember>*> specifiedIdentifierList
338340
%type<IR::SerEnumMember*> specifiedIdentifier
339341
%type<IR::Method*> methodPrototype functionPrototype
@@ -485,10 +487,14 @@ p4rtControllerType
485487
program : input END { YYACCEPT; };
486488

487489
input
488-
: %empty { driver.result = $$ = new IR::P4Program; }
489-
| input declaration { if ($2) $1->objects.push_back($2->getNode());
490-
$$ = $1; }
491-
| input ";" { $$ = $1; } // empty declaration
490+
: %empty { driver.result = $$ = new IR::P4Program; }
491+
| input declaration { $$ = $1;
492+
if (!$2) { /* do nothing */ }
493+
else if (auto *v = $2->to<IR::VectorBase>())
494+
$$->objects.append(*v);
495+
else
496+
$$->objects.push_back($2); }
497+
| input ";" { $$ = $1; } // empty declaration
492498
;
493499

494500
declaration
@@ -841,14 +847,14 @@ parserDeclaration
841847

842848
parserLocalElements
843849
: %empty { $$ = new IR::IndexedVector<IR::Declaration>(); }
844-
| parserLocalElements parserLocalElement { $$ = $1; $$->push_back($2); $$->srcInfo = @1 + @2; }
850+
| parserLocalElements parserLocalElement { $$ = $1; $$->append(*$2); $$->srcInfo = @1 + @2; }
845851
;
846852

847853
parserLocalElement
848854
: constantDeclaration { $$ = $1; }
849-
| instantiation { $$ = $1; }
855+
| instantiation { $$ = new IR::IndexedVector<IR::Declaration>($1); }
850856
| variableDeclaration { $$ = $1; }
851-
| valueSetDeclaration { $$ = $1; }
857+
| valueSetDeclaration { $$ = new IR::IndexedVector<IR::Declaration>($1); }
852858
;
853859

854860
parserTypeDeclaration
@@ -876,17 +882,17 @@ parserState
876882

877883
parserStatements
878884
: %empty { $$ = new IR::IndexedVector<IR::StatOrDecl>(); }
879-
| parserStatements parserStatement { $$ = $1; $1->push_back($2); $$->srcInfo = @1 + @2; }
885+
| parserStatements parserStatement { $$ = $1; $1->append(*$2); $$->srcInfo = @1 + @2; }
880886
;
881887

882888
parserStatement
883-
: assignmentOrMethodCallStatement { $$ = $1; }
884-
| directApplication { $$ = $1; }
885-
| emptyStatement { $$ = $1; }
886-
| variableDeclaration { $$ = $1; }
887-
| constantDeclaration { $$ = $1; }
888-
| parserBlockStatement { $$ = $1; }
889-
| conditionalStatement { $$ = $1; }
889+
: assignmentOrMethodCallStatement { $$ = new IR::IndexedVector<IR::StatOrDecl>($1); }
890+
| directApplication { $$ = new IR::IndexedVector<IR::StatOrDecl>($1); }
891+
| emptyStatement { $$ = new IR::IndexedVector<IR::StatOrDecl>($1); }
892+
| variableDeclaration { $$ = new IR::IndexedVector<IR::StatOrDecl>($1->begin(), $1->end()); }
893+
| constantDeclaration { $$ = new IR::IndexedVector<IR::StatOrDecl>($1->begin(), $1->end()); }
894+
| parserBlockStatement { $$ = new IR::IndexedVector<IR::StatOrDecl>($1); }
895+
| conditionalStatement { $$ = new IR::IndexedVector<IR::StatOrDecl>($1); }
890896
;
891897

892898
parserBlockStatement
@@ -992,14 +998,16 @@ controlTypeDeclaration
992998

993999
controlLocalDeclarations
9941000
: %empty { $$ = new IR::IndexedVector<IR::Declaration>(); }
995-
| controlLocalDeclarations controlLocalDeclaration { $$ = $1; $$->push_back($2); $$->srcInfo = @1 + @2; }
1001+
| controlLocalDeclarations controlLocalDeclaration {
1002+
($$ = $1)->append(*$2);
1003+
$$->srcInfo = @1 + @2; }
9961004
;
9971005

9981006
controlLocalDeclaration
9991007
: constantDeclaration { $$ = $1; }
1000-
| actionDeclaration { $$ = $1; }
1001-
| tableDeclaration { $$ = $1; }
1002-
| instantiation { $$ = $1; }
1008+
| actionDeclaration { $$ = new IR::IndexedVector<IR::Declaration>($1); }
1009+
| tableDeclaration { $$ = new IR::IndexedVector<IR::Declaration>($1); }
1010+
| instantiation { $$ = new IR::IndexedVector<IR::Declaration>($1); }
10031011
| variableDeclaration { $$ = $1; }
10041012
;
10051013

@@ -1209,11 +1217,23 @@ headerUnionDeclaration
12091217

12101218
structFieldList
12111219
: %empty { $$ = new IR::IndexedVector<IR::StructField>(); }
1212-
| structFieldList structField { $$ = $1; $1->push_back($2); $$->srcInfo = @1 + @2; }
1220+
| structFieldList structField { $$ = $1; $1->append(*$2); $$->srcInfo = @1 + @2; }
12131221
;
12141222

12151223
structField
1216-
: optAnnotations typeRef declarator ";" { $$ = new IR::StructField(@3, *$3.name, *$1, $3.type); }
1224+
: optAnnotations typeRef declaratorList ";" {
1225+
$$ = new IR::IndexedVector<IR::StructField>();
1226+
for (auto &decl : $3)
1227+
$$->push_back(new IR::StructField(decl.srcInfo, *decl.name, *$1, decl.type)); }
1228+
;
1229+
1230+
declaratorList
1231+
: declarator { $$.emplace_back($1); }
1232+
| declaratorList "," <ConstType*>{ $$ = $<ConstType*>0; } declarator {
1233+
if ($1.size() == 1)
1234+
warning(ErrorType::WARN_EXTENSION,
1235+
"%1%Multiple declarators is a non-standard extension", @4);
1236+
($$=$1).emplace_back($4); }
12171237
;
12181238

12191239
enumDeclaration
@@ -1346,15 +1366,15 @@ continueStatement
13461366
// To support direct invocation of a control or parser without instantiation
13471367
directApplication
13481368
: typeName "." APPLY "(" argumentList ")" ";" {
1349-
auto method = new IR::Member(
1350-
@1 + @3, new IR::TypeNameExpression($1), IR::ID(@3, "apply"_cs));
1351-
auto mce = new IR::MethodCallExpression(@1 + @6, method, $5);
1352-
$$ = new IR::MethodCallStatement(@1 + @6, mce); }
1369+
auto method = new IR::Member(@1 + @3, new IR::TypeNameExpression($1),
1370+
IR::ID(@3, "apply"_cs));
1371+
auto mce = new IR::MethodCallExpression(@1 + @6, method, $5);
1372+
$$ = new IR::MethodCallStatement(@1 + @6, mce); }
13531373
| specializedType "." APPLY "(" argumentList ")" ";" {
1354-
auto method = new IR::Member(
1355-
@1 + @3, new IR::TypeNameExpression($1), IR::ID(@3, "apply"_cs));
1356-
auto mce = new IR::MethodCallExpression(@1 + @6, method, $5);
1357-
$$ = new IR::MethodCallStatement(@1 + @6, mce); }
1374+
auto method = new IR::Member(@1 + @3, new IR::TypeNameExpression($1),
1375+
IR::ID(@3, "apply"_cs));
1376+
auto mce = new IR::MethodCallExpression(@1 + @6, method, $5);
1377+
$$ = new IR::MethodCallStatement(@1 + @6, mce); }
13581378
;
13591379

13601380
statement
@@ -1379,7 +1399,7 @@ blockStatement
13791399

13801400
statOrDeclList
13811401
: %empty { $$ = new IR::IndexedVector<IR::StatOrDecl>(); }
1382-
| statOrDeclList statementOrDeclaration { $$ = $1; $$->push_back($2); $$->srcInfo = @1 + @2; }
1402+
| statOrDeclList statementOrDeclaration { $$ = $1; $$->append(*$2); $$->srcInfo = @1 + @2; }
13831403
;
13841404

13851405
switchStatement
@@ -1403,14 +1423,14 @@ switchLabel
14031423
;
14041424

14051425
statementOrDeclaration
1406-
: variableDeclaration { $$ = $1; }
1407-
| constantDeclaration { $$ = $1; }
1408-
| statement { $$ = $1; }
1426+
: variableDeclaration { $$ = new IR::IndexedVector<IR::StatOrDecl>($1->begin(), $1->end()); }
1427+
| constantDeclaration { $$ = new IR::IndexedVector<IR::StatOrDecl>($1->begin(), $1->end()); }
1428+
| statement { $$ = new IR::IndexedVector<IR::StatOrDecl>($1); }
14091429
// The transition to instantiation below is not required by the
14101430
// languge spec, but it does help p4c give a more clear error
14111431
// message if one erroneously attempts to perform an
14121432
// instantiation inside of a block.
1413-
| instantiation { $$ = $1; }
1433+
| instantiation { $$ = new IR::IndexedVector<IR::StatOrDecl>($1); }
14141434
;
14151435

14161436
forStatement
@@ -1563,7 +1583,18 @@ actionDeclaration
15631583
/************************* VARIABLES *****************************/
15641584

15651585
variableDeclaration
1566-
: variableDeclarationWithoutSemicolon ";" { $$ = $1; }
1586+
: annotations typeRef initDeclaratorList ";" {
1587+
$$ = new IR::IndexedVector<IR::Declaration>();
1588+
for (auto &decl : $3) {
1589+
$$->push_back(new IR::Declaration_Variable(decl.srcInfo, *decl.name, *$1,
1590+
decl.type, decl.init));
1591+
driver.structure->declareObject(*decl.name, decl.type->toString()); } }
1592+
| typeRef initDeclaratorList ";" {
1593+
$$ = new IR::IndexedVector<IR::Declaration>();
1594+
for (auto &decl : $2) {
1595+
$$->push_back(new IR::Declaration_Variable(decl.srcInfo, *decl.name,
1596+
decl.type, decl.init));
1597+
driver.structure->declareObject(*decl.name, decl.type->toString()); } }
15671598
;
15681599

15691600
variableDeclarationWithoutSemicolon
@@ -1576,15 +1607,27 @@ variableDeclarationWithoutSemicolon
15761607
;
15771608

15781609
constantDeclaration
1579-
: optAnnotations CONST typeRef declarator "=" initializer ";"
1580-
{ $$ = new IR::Declaration_Constant(@4, *$4.name, *$1, $4.type, $6);
1581-
driver.structure->declareObject(*$4.name, $4.type->toString()); }
1610+
: optAnnotations CONST typeRef initDeclaratorList ";" {
1611+
$$ = new IR::IndexedVector<IR::Declaration>();
1612+
for (auto &decl : $4) {
1613+
if (!decl.init)
1614+
P4::error(ErrorType::ERR_EXPECTED,
1615+
"Const %1% declaration requires an initializer", decl.name);
1616+
$$->push_back(new IR::Declaration_Constant(decl.srcInfo, *decl.name, *$1,
1617+
decl.type, decl.init));
1618+
driver.structure->declareObject(*decl.name, decl.type->toString()); } }
15821619
;
15831620

15841621
declarator
1585-
: name { $$.name = $1; $$.type = $<ConstType *>0; }
1586-
| declarator "[" expression "]"
1587-
{ $$ = $1; $$.type = new IR::Type_Array(@2+@4, $1.type, $3); }
1622+
: name { $$.srcInfo = @1;
1623+
$$.name = $1;
1624+
$$.type = $<ConstType *>0;
1625+
$$.init = nullptr; }
1626+
| declarator "[" expression "]" {
1627+
$$ = $1;
1628+
$$.srcInfo += @4;
1629+
$$.type = new IR::Type_Array(@2+@4, $1.type, $3);
1630+
$$.init = nullptr; }
15881631
;
15891632

15901633
optInitializer
@@ -1596,6 +1639,18 @@ initializer
15961639
: expression { $$ = $1; }
15971640
;
15981641

1642+
initDeclaratorList
1643+
: declarator optInitializer {
1644+
$$.emplace_back($1);
1645+
$$.back().init = $2; }
1646+
| initDeclaratorList "," <ConstType*>{ $$ = $<ConstType*>0; } declarator optInitializer {
1647+
if ($1.size() == 1)
1648+
warning(ErrorType::WARN_EXTENSION,
1649+
"%1%Multiple declarators is a non-standard extension", @4);
1650+
($$=$1).emplace_back($4);
1651+
$$.back().init = $5; }
1652+
;
1653+
15991654
/**************** Expressions ****************/
16001655

16011656
functionDeclaration

lib/error_catalog.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ std::map<int, cstring> ErrorCatalog::errorCatalog = {
7777
{ErrorType::WARN_DUPLICATE, "duplicate"_cs},
7878
{ErrorType::WARN_BRANCH_HINT, "branch"_cs},
7979
{ErrorType::WARN_TABLE_KEYS, "keys"_cs},
80+
{ErrorType::WARN_EXTENSION, "extension"_cs},
8081

8182
// Info messages
8283
{ErrorType::INFO_INFERRED, "inferred"_cs},
@@ -87,6 +88,9 @@ void ErrorCatalog::initReporter(ErrorReporter &reporter) {
8788
// by default, ignore warnings about branch hints -- user can turn them
8889
// on with --Wwarn=branch
8990
reporter.setDiagnosticAction("branch"_cs, DiagnosticAction::Ignore);
91+
// by default, ignore warnings about extensions -- user can turn them
92+
// on with --Wwarn=extension
93+
reporter.setDiagnosticAction("extension"_cs, DiagnosticAction::Ignore);
9094
}
9195

9296
} // namespace P4

lib/error_catalog.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class ErrorType {
9191
static constexpr int WARN_DUPLICATE = 1025; // duplicate objects
9292
static constexpr int WARN_BRANCH_HINT = 1026; // branch frequency/likely hints
9393
static constexpr int WARN_TABLE_KEYS = 1027; // something is wrong with a table key
94+
static constexpr int WARN_EXTENSION = 1028; // non-standard extension
9495
// Backends should extend this class with additional warnings in the range 1500-2141.
9596
static constexpr int WARN_MIN_BACKEND = 1500; // first allowed backend warning code
9697
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)