diff --git a/frontends/parsers/p4/p4parser.ypp b/frontends/parsers/p4/p4parser.ypp index c95f82e0f9..6ce23efad4 100644 --- a/frontends/parsers/p4/p4parser.ypp +++ b/frontends/parsers/p4/p4parser.ypp @@ -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 @@ -251,6 +260,7 @@ using namespace P4; %type name dot_name nonTypeName nonTableKwName annotationName +%type declarator %type direction %type prefixedNonTypeName prefixedType %type*> typeParameterList @@ -262,6 +272,7 @@ using namespace P4; nonBraceExpression forCollectionExpr %type baseType typeOrVoid specializedType headerStackType typeRef tupleType typeArg realTypeArg namedType p4listType + derivedTypeDeclarationAsType %type typeName %type argument %type*> argumentList nonEmptyArgList @@ -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 @@ -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($1); } + ; + headerTypeDeclaration : optAnnotations HEADER name { driver.structure->pushContainerType(*$3, true); } optTypeParameters { driver.structure->markAsTemplate(*$3); @@ -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 @@ -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 *************************/ @@ -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 = $0; } + | declarator "[" expression "]" + { $$ = $1; $$.type = new IR::Type_Stack(@2+@4, $1.type, $3); } ; optInitializer diff --git a/testdata/p4_16_samples/array2.p4 b/testdata/p4_16_samples/array2.p4 new file mode 100644 index 0000000000..7d05e5e257 --- /dev/null +++ b/testdata/p4_16_samples/array2.p4 @@ -0,0 +1,71 @@ +#include +#include + +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(p(), + vc(), + ingress(), + egress(), + uc(), + deparser()) main; diff --git a/testdata/p4_16_samples_outputs/array2-first.p4 b/testdata/p4_16_samples_outputs/array2-first.p4 new file mode 100644 index 0000000000..04c776aea2 --- /dev/null +++ b/testdata/p4_16_samples_outputs/array2-first.p4 @@ -0,0 +1,61 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +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(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(hdr); + } +} + +V1Switch(p(), vc(), ingress(), egress(), uc(), deparser()) main; diff --git a/testdata/p4_16_samples_outputs/array2-frontend.p4 b/testdata/p4_16_samples_outputs/array2-frontend.p4 new file mode 100644 index 0000000000..04c776aea2 --- /dev/null +++ b/testdata/p4_16_samples_outputs/array2-frontend.p4 @@ -0,0 +1,61 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +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(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(hdr); + } +} + +V1Switch(p(), vc(), ingress(), egress(), uc(), deparser()) main; diff --git a/testdata/p4_16_samples_outputs/array2-midend.p4 b/testdata/p4_16_samples_outputs/array2-midend.p4 new file mode 100644 index 0000000000..045c490f83 --- /dev/null +++ b/testdata/p4_16_samples_outputs/array2-midend.p4 @@ -0,0 +1,70 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +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(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(hdr.data); + } +} + +V1Switch(p(), vc(), ingress(), egress(), uc(), deparser()) main; diff --git a/testdata/p4_16_samples_outputs/array2.p4 b/testdata/p4_16_samples_outputs/array2.p4 new file mode 100644 index 0000000000..e0fe8c3ead --- /dev/null +++ b/testdata/p4_16_samples_outputs/array2.p4 @@ -0,0 +1,61 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +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(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(p(), vc(), ingress(), egress(), uc(), deparser()) main; diff --git a/testdata/p4_16_samples_outputs/array2.p4-stderr b/testdata/p4_16_samples_outputs/array2.p4-stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/p4_16_samples_outputs/array2.p4.entries.txtpb b/testdata/p4_16_samples_outputs/array2.p4.entries.txtpb new file mode 100644 index 0000000000..5cb9652623 --- /dev/null +++ b/testdata/p4_16_samples_outputs/array2.p4.entries.txtpb @@ -0,0 +1,3 @@ +# proto-file: p4/v1/p4runtime.proto +# proto-message: p4.v1.WriteRequest + diff --git a/testdata/p4_16_samples_outputs/array2.p4.p4info.txtpb b/testdata/p4_16_samples_outputs/array2.p4.p4info.txtpb new file mode 100644 index 0000000000..fdf16790b9 --- /dev/null +++ b/testdata/p4_16_samples_outputs/array2.p4.p4info.txtpb @@ -0,0 +1,6 @@ +# proto-file: p4/config/v1/p4info.proto +# proto-message: p4.config.v1.P4Info + +pkg_info { + arch: "v1model" +}