Skip to content

Commit

Permalink
Allow C-style array declarators after the name
Browse files Browse the repository at this point in the history
- this allows declaring arrays as in C (eg, `bit<8> data[16];`) rather
  than in the java style previously required (`bit<8> [16] data;`)

Signed-off-by: Chris Dodd <[email protected]>
  • Loading branch information
ChrisDodd committed Jan 30, 2025
1 parent 8df3c2a commit 618c817
Show file tree
Hide file tree
Showing 9 changed files with 379 additions and 18 deletions.
64 changes: 46 additions & 18 deletions frontends/parsers/p4/p4parser.ypp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ inline std::ostream& operator<<(std::ostream& out, const OptionalConst& oc) {
// forbidden in C++. We avoid the problem using a typedef.
typedef const IR::Type ConstType;

struct NameTypePair {
const IR::ID *name;
const IR::Type *type;
};

inline std::ostream &operator<<(std::ostream &out, const NameTypePair &nt) {
return out << nt.name << ":" << nt.type;
}

} // namespace P4

#ifndef YYDEBUG
Expand Down Expand Up @@ -251,6 +260,7 @@ using namespace P4;


%type<IR::ID*> name dot_name nonTypeName nonTableKwName annotationName
%type<NameTypePair> declarator
%type<IR::Direction> direction
%type<IR::Path*> prefixedNonTypeName prefixedType
%type<IR::IndexedVector<IR::Type_Var>*> typeParameterList
Expand All @@ -262,6 +272,7 @@ using namespace P4;
nonBraceExpression forCollectionExpr
%type<ConstType*> baseType typeOrVoid specializedType headerStackType
typeRef tupleType typeArg realTypeArg namedType p4listType
derivedTypeDeclarationAsType
%type<IR::Type_Name*> typeName
%type<IR::Argument*> argument
%type<IR::Vector<IR::Argument>*> argumentList nonEmptyArgList
Expand Down Expand Up @@ -745,8 +756,10 @@ nonEmptyParameterList
;

parameter
: optAnnotations direction typeRef name { $$ = new IR::Parameter(@4, *$4, *$1, $2, $3, nullptr); }
| optAnnotations direction typeRef name "=" expression { $$ = new IR::Parameter(@4, *$4, *$1, $2, $3, $6); }
: optAnnotations direction typeRef declarator {
$$ = new IR::Parameter(@4, *$4.name, *$1, $2, $4.type, nullptr); }
| optAnnotations direction typeRef declarator "=" expression {
$$ = new IR::Parameter(@4, *$4.name, *$1, $2, $4.type, $6); }
;

direction
Expand Down Expand Up @@ -1168,6 +1181,12 @@ derivedTypeDeclaration
| enumDeclaration { $$ = $1; }
;

// workaround for bison's broken type variant handling that needs an explicit conversion
// to the base class
derivedTypeDeclarationAsType
: derivedTypeDeclaration { $$ = static_cast<const IR::Type *>($1); }
;

headerTypeDeclaration
: optAnnotations HEADER name { driver.structure->pushContainerType(*$3, true); } optTypeParameters {
driver.structure->markAsTemplate(*$3);
Expand Down Expand Up @@ -1198,7 +1217,7 @@ structFieldList
;

structField
: optAnnotations typeRef name ";" { $$ = new IR::StructField(@3, *$3, *$1, $2); }
: optAnnotations typeRef declarator ";" { $$ = new IR::StructField(@3, *$3.name, *$1, $3.type); }
;

enumDeclaration
Expand Down Expand Up @@ -1240,12 +1259,15 @@ identifierList
;

typedefDeclaration
: optAnnotations TYPEDEF typeRef name { driver.structure->declareType(*$4);
$$ = new IR::Type_Typedef(@4, *$4, *$1, $3); }
| optAnnotations TYPEDEF derivedTypeDeclaration name { driver.structure->declareType(*$4);
$$ = new IR::Type_Typedef(@4, *$4, *$1, $3); }
| optAnnotations TYPE typeRef name { driver.structure->declareType(*$4);
$$ = new IR::Type_Newtype(@4, *$4, *$1, $3); }
: optAnnotations TYPEDEF typeRef declarator {
driver.structure->declareType(*$4.name);
$$ = new IR::Type_Typedef(@4, *$4.name, *$1, $4.type); }
| optAnnotations TYPEDEF derivedTypeDeclarationAsType declarator {
driver.structure->declareType(*$4.name);
$$ = new IR::Type_Typedef(@4, *$4.name, *$1, $4.type); }
| optAnnotations TYPE typeRef declarator {
driver.structure->declareType(*$4.name);
$$ = new IR::Type_Newtype(@4, *$4.name, *$1, $4.type); }
;

/*************************** STATEMENTS *************************/
Expand Down Expand Up @@ -1524,18 +1546,24 @@ variableDeclaration
;

variableDeclarationWithoutSemicolon
: annotations typeRef name optInitializer
{ $$ = new IR::Declaration_Variable(@1+@4, *$3, *$1, $2, $4);
driver.structure->declareObject(*$3, $2->toString()); }
| typeRef name optInitializer
{ $$ = new IR::Declaration_Variable(@1+@3, *$2, $1, $3);
driver.structure->declareObject(*$2, $1->toString()); }
: annotations typeRef declarator optInitializer
{ $$ = new IR::Declaration_Variable(@1+@4, *$3.name, *$1, $3.type, $4);
driver.structure->declareObject(*$3.name, $3.type->toString()); }
| typeRef declarator optInitializer
{ $$ = new IR::Declaration_Variable(@1+@3, *$2.name, $2.type, $3);
driver.structure->declareObject(*$2.name, $2.type->toString()); }
;

constantDeclaration
: optAnnotations CONST typeRef name "=" initializer ";"
{ $$ = new IR::Declaration_Constant(@4, *$4, *$1, $3, $6);
driver.structure->declareObject(*$4, $3->toString()); }
: optAnnotations CONST typeRef declarator "=" initializer ";"
{ $$ = new IR::Declaration_Constant(@4, *$4.name, *$1, $4.type, $6);
driver.structure->declareObject(*$4.name, $4.type->toString()); }
;

declarator
: name { $$.name = $1; $$.type = $<ConstType *>0; }
| declarator "[" expression "]"
{ $$ = $1; $$.type = new IR::Type_Stack(@2+@4, $1.type, $3); }
;

optInitializer
Expand Down
71 changes: 71 additions & 0 deletions testdata/p4_16_samples/array2.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <core.p4>
#include <v1model.p4>

header data_t {
bit<32> f1;
bit<32> f2;
bit<16> h1;
bit<16> h2;
bit<8> arr[16];
}

struct metadata {}

struct headers {
data_t data;
}

parser p(packet_in b,
out headers hdr,
inout metadata meta,
inout standard_metadata_t stdmeta) {
state start {
b.extract(hdr.data);
transition accept;
}
}

control ingress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t stdmeta) {
apply {
hdr.data.arr[0] = hdr.data.f1[0+:8];
hdr.data.arr[1] = hdr.data.f1[8+:8];
hdr.data.arr[2] = hdr.data.f1[16+:8];
hdr.data.arr[3] = hdr.data.f1[24+:8];
hdr.data.arr[4] = hdr.data.f2[0+:8];
hdr.data.arr[5] = hdr.data.f2[8+:8];
hdr.data.arr[6] = hdr.data.f2[16+:8];
hdr.data.arr[7] = hdr.data.f2[24+:8];
}
}

control egress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t stdmeta) {
apply {}
}

control vc(inout headers hdr,
inout metadata meta) {
apply {}
}

control uc(inout headers hdr,
inout metadata meta) {
apply {}
}

control deparser(packet_out packet,
in headers hdr) {
apply {
packet.emit(hdr);
}
}

V1Switch<headers, metadata>(p(),
vc(),
ingress(),
egress(),
uc(),
deparser()) main;
61 changes: 61 additions & 0 deletions testdata/p4_16_samples_outputs/array2-first.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <core.p4>
#define V1MODEL_VERSION 20180101
#include <v1model.p4>

header data_t {
bit<32> f1;
bit<32> f2;
bit<16> h1;
bit<16> h2;
bit<8>[16] arr;
}

struct metadata {
}

struct headers {
data_t data;
}

parser p(packet_in b, out headers hdr, inout metadata meta, inout standard_metadata_t stdmeta) {
state start {
b.extract<data_t>(hdr.data);
transition accept;
}
}

control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t stdmeta) {
apply {
hdr.data.arr[0] = hdr.data.f1[7:0];
hdr.data.arr[1] = hdr.data.f1[15:8];
hdr.data.arr[2] = hdr.data.f1[23:16];
hdr.data.arr[3] = hdr.data.f1[31:24];
hdr.data.arr[4] = hdr.data.f2[7:0];
hdr.data.arr[5] = hdr.data.f2[15:8];
hdr.data.arr[6] = hdr.data.f2[23:16];
hdr.data.arr[7] = hdr.data.f2[31:24];
}
}

control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t stdmeta) {
apply {
}
}

control vc(inout headers hdr, inout metadata meta) {
apply {
}
}

control uc(inout headers hdr, inout metadata meta) {
apply {
}
}

control deparser(packet_out packet, in headers hdr) {
apply {
packet.emit<headers>(hdr);
}
}

V1Switch<headers, metadata>(p(), vc(), ingress(), egress(), uc(), deparser()) main;
61 changes: 61 additions & 0 deletions testdata/p4_16_samples_outputs/array2-frontend.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <core.p4>
#define V1MODEL_VERSION 20180101
#include <v1model.p4>

header data_t {
bit<32> f1;
bit<32> f2;
bit<16> h1;
bit<16> h2;
bit<8>[16] arr;
}

struct metadata {
}

struct headers {
data_t data;
}

parser p(packet_in b, out headers hdr, inout metadata meta, inout standard_metadata_t stdmeta) {
state start {
b.extract<data_t>(hdr.data);
transition accept;
}
}

control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t stdmeta) {
apply {
hdr.data.arr[0] = hdr.data.f1[7:0];
hdr.data.arr[1] = hdr.data.f1[15:8];
hdr.data.arr[2] = hdr.data.f1[23:16];
hdr.data.arr[3] = hdr.data.f1[31:24];
hdr.data.arr[4] = hdr.data.f2[7:0];
hdr.data.arr[5] = hdr.data.f2[15:8];
hdr.data.arr[6] = hdr.data.f2[23:16];
hdr.data.arr[7] = hdr.data.f2[31:24];
}
}

control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t stdmeta) {
apply {
}
}

control vc(inout headers hdr, inout metadata meta) {
apply {
}
}

control uc(inout headers hdr, inout metadata meta) {
apply {
}
}

control deparser(packet_out packet, in headers hdr) {
apply {
packet.emit<headers>(hdr);
}
}

V1Switch<headers, metadata>(p(), vc(), ingress(), egress(), uc(), deparser()) main;
70 changes: 70 additions & 0 deletions testdata/p4_16_samples_outputs/array2-midend.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include <core.p4>
#define V1MODEL_VERSION 20180101
#include <v1model.p4>

header data_t {
bit<32> f1;
bit<32> f2;
bit<16> h1;
bit<16> h2;
bit<8>[16] arr;
}

struct metadata {
}

struct headers {
data_t data;
}

parser p(packet_in b, out headers hdr, inout metadata meta, inout standard_metadata_t stdmeta) {
state start {
b.extract<data_t>(hdr.data);
transition accept;
}
}

control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t stdmeta) {
@hidden action array2l32() {
hdr.data.arr[0] = hdr.data.f1[7:0];
hdr.data.arr[1] = hdr.data.f1[15:8];
hdr.data.arr[2] = hdr.data.f1[23:16];
hdr.data.arr[3] = hdr.data.f1[31:24];
hdr.data.arr[4] = hdr.data.f2[7:0];
hdr.data.arr[5] = hdr.data.f2[15:8];
hdr.data.arr[6] = hdr.data.f2[23:16];
hdr.data.arr[7] = hdr.data.f2[31:24];
}
@hidden table tbl_array2l32 {
actions = {
array2l32();
}
const default_action = array2l32();
}
apply {
tbl_array2l32.apply();
}
}

control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t stdmeta) {
apply {
}
}

control vc(inout headers hdr, inout metadata meta) {
apply {
}
}

control uc(inout headers hdr, inout metadata meta) {
apply {
}
}

control deparser(packet_out packet, in headers hdr) {
apply {
packet.emit<data_t>(hdr.data);
}
}

V1Switch<headers, metadata>(p(), vc(), ingress(), egress(), uc(), deparser()) main;
Loading

0 comments on commit 618c817

Please sign in to comment.