From d8dce05cb4d168de2aaab9aefd5a9b2904494af4 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Fri, 8 Apr 2022 12:38:53 +0300 Subject: [PATCH 01/12] fixing bug for sequential next usage --- midend/parserUnroll.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/midend/parserUnroll.cpp b/midend/parserUnroll.cpp index 45def24bace..9137acb2bef 100644 --- a/midend/parserUnroll.cpp +++ b/midend/parserUnroll.cpp @@ -147,19 +147,17 @@ class ParserStateRewriter : public Transform { BUG_CHECK(l->is(), "%1%: expected an array", l); auto array = l->to(); unsigned idx = 0; - for (size_t i = 0; i < array->size; i++) { - auto* v = array->get(expression, i); - if (v->hasUninitializedParts()) - break; - else - idx = i; + unsigned offset = 0; + if (state->statesIndexes.count(expression->expr->toString())) { + idx = state->statesIndexes.at(expression->expr->toString()); + offset = 1; } if (expression->member.name == IR::Type_Stack::lastIndex) { return new IR::Constant(IR::Type_Bits::get(32), idx); } else { - state->statesIndexes[expression->expr->toString()] = idx; + state->statesIndexes[expression->expr->toString()] = idx + offset; return new IR::ArrayIndex(expression->expr->clone(), - new IR::Constant(IR::Type_Bits::get(32), idx)); + new IR::Constant(IR::Type_Bits::get(32), idx + offset)); } } return expression; From d487c87e005ce21b74046a17750ead26b1085b05 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Fri, 8 Apr 2022 15:03:27 +0300 Subject: [PATCH 02/12] update for detection index of last --- midend/parserUnroll.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/midend/parserUnroll.cpp b/midend/parserUnroll.cpp index 9137acb2bef..9d39128cb86 100644 --- a/midend/parserUnroll.cpp +++ b/midend/parserUnroll.cpp @@ -150,7 +150,9 @@ class ParserStateRewriter : public Transform { unsigned offset = 0; if (state->statesIndexes.count(expression->expr->toString())) { idx = state->statesIndexes.at(expression->expr->toString()); - offset = 1; + if (idx + 1 < array->size && expression->member.name != IR::Type_Stack::last) { + offset = 1; + } } if (expression->member.name == IR::Type_Stack::lastIndex) { return new IR::Constant(IR::Type_Bits::get(32), idx); From 6f0bc2881b5091fc6fae59f15d972f1b09147640 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Fri, 8 Apr 2022 17:50:30 +0300 Subject: [PATCH 03/12] add test --- testdata/p4_16_samples/parser-unroll-test7.p4 | 69 +++++++++++++++++++ .../parser-unroll-test7-first.p4 | 65 +++++++++++++++++ .../parser-unroll-test7-frontend.p4 | 65 +++++++++++++++++ .../parser-unroll-test7-midend.p4 | 68 ++++++++++++++++++ .../parser-unroll-test7.p4 | 65 +++++++++++++++++ .../parser-unroll-test7.p4-stderr | 0 .../parser-unroll-test7.p4.entries.txt | 0 .../parser-unroll-test7.p4.p4info.txt | 3 + .../parser-unroll-test7-first.p4 | 65 +++++++++++++++++ .../parser-unroll-test7-frontend.p4 | 65 +++++++++++++++++ .../parser-unroll-test7-midend.p4 | 68 ++++++++++++++++++ .../parser-unroll/parser-unroll-test7.p4 | 65 +++++++++++++++++ .../parser-unroll-test7.p4-stderr | 6 ++ 13 files changed, 604 insertions(+) create mode 100644 testdata/p4_16_samples/parser-unroll-test7.p4 create mode 100644 testdata/p4_16_samples_outputs/parser-unroll-test7-first.p4 create mode 100644 testdata/p4_16_samples_outputs/parser-unroll-test7-frontend.p4 create mode 100644 testdata/p4_16_samples_outputs/parser-unroll-test7-midend.p4 create mode 100644 testdata/p4_16_samples_outputs/parser-unroll-test7.p4 create mode 100644 testdata/p4_16_samples_outputs/parser-unroll-test7.p4-stderr create mode 100644 testdata/p4_16_samples_outputs/parser-unroll-test7.p4.entries.txt create mode 100644 testdata/p4_16_samples_outputs/parser-unroll-test7.p4.p4info.txt create mode 100644 testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-first.p4 create mode 100644 testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-frontend.p4 create mode 100644 testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-midend.p4 create mode 100644 testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4 create mode 100644 testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4-stderr diff --git a/testdata/p4_16_samples/parser-unroll-test7.p4 b/testdata/p4_16_samples/parser-unroll-test7.p4 new file mode 100644 index 00000000000..fdfaf180d6f --- /dev/null +++ b/testdata/p4_16_samples/parser-unroll-test7.p4 @@ -0,0 +1,69 @@ +#include +#include + +header S { + bit<8> t; +} + +header O1 { + bit<8> data; +} +header O2 { + bit<16> data; +} + +header_union U { + O1 byte; + O2 short; +} + +struct headers { + S base; + U[2] u; +} + +struct metadata {} + +parser ParserImpl(packet_in packet, + out headers hdr, + inout metadata meta, + inout standard_metadata_t standard_metadata) +{ + state start { + packet.extract(hdr.u.next.byte); + packet.extract(hdr.u.next.short); + transition accept; + } +} + +control ingress(inout headers hdr, + inout metadata meta, + inout standard_metadata_t standard_metadata) { + apply {} +} + +control egress(inout headers hdr, + inout metadata meta, + inout standard_metadata_t standard_metadata) +{ apply {} } + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.u); + } +} + +control verifyChecksum(inout headers hdr, inout metadata meta) { + apply { } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { } +} + +V1Switch(ParserImpl(), + verifyChecksum(), + ingress(), + egress(), + computeChecksum(), + DeparserImpl()) main; diff --git a/testdata/p4_16_samples_outputs/parser-unroll-test7-first.p4 b/testdata/p4_16_samples_outputs/parser-unroll-test7-first.p4 new file mode 100644 index 00000000000..8fb4d353639 --- /dev/null +++ b/testdata/p4_16_samples_outputs/parser-unroll-test7-first.p4 @@ -0,0 +1,65 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +header S { + bit<8> t; +} + +header O1 { + bit<8> data; +} + +header O2 { + bit<16> data; +} + +header_union U { + O1 byte; + O2 short; +} + +struct headers { + S base; + U[2] u; +} + +struct metadata { +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + state start { + packet.extract(hdr.u.next.byte); + packet.extract(hdr.u.next.short); + transition accept; + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.u); + } +} + +control verifyChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; + diff --git a/testdata/p4_16_samples_outputs/parser-unroll-test7-frontend.p4 b/testdata/p4_16_samples_outputs/parser-unroll-test7-frontend.p4 new file mode 100644 index 00000000000..8fb4d353639 --- /dev/null +++ b/testdata/p4_16_samples_outputs/parser-unroll-test7-frontend.p4 @@ -0,0 +1,65 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +header S { + bit<8> t; +} + +header O1 { + bit<8> data; +} + +header O2 { + bit<16> data; +} + +header_union U { + O1 byte; + O2 short; +} + +struct headers { + S base; + U[2] u; +} + +struct metadata { +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + state start { + packet.extract(hdr.u.next.byte); + packet.extract(hdr.u.next.short); + transition accept; + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.u); + } +} + +control verifyChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; + diff --git a/testdata/p4_16_samples_outputs/parser-unroll-test7-midend.p4 b/testdata/p4_16_samples_outputs/parser-unroll-test7-midend.p4 new file mode 100644 index 00000000000..300e762737b --- /dev/null +++ b/testdata/p4_16_samples_outputs/parser-unroll-test7-midend.p4 @@ -0,0 +1,68 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +header S { + bit<8> t; +} + +header O1 { + bit<8> data; +} + +header O2 { + bit<16> data; +} + +header_union U { + O1 byte; + O2 short; +} + +struct headers { + S base; + U[2] u; +} + +struct metadata { +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + state start { + packet.extract(hdr.u.next.byte); + packet.extract(hdr.u.next.short); + transition accept; + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.u[0].byte); + packet.emit(hdr.u[0].short); + packet.emit(hdr.u[1].byte); + packet.emit(hdr.u[1].short); + } +} + +control verifyChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; + diff --git a/testdata/p4_16_samples_outputs/parser-unroll-test7.p4 b/testdata/p4_16_samples_outputs/parser-unroll-test7.p4 new file mode 100644 index 00000000000..11d544ae23a --- /dev/null +++ b/testdata/p4_16_samples_outputs/parser-unroll-test7.p4 @@ -0,0 +1,65 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +header S { + bit<8> t; +} + +header O1 { + bit<8> data; +} + +header O2 { + bit<16> data; +} + +header_union U { + O1 byte; + O2 short; +} + +struct headers { + S base; + U[2] u; +} + +struct metadata { +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + state start { + packet.extract(hdr.u.next.byte); + packet.extract(hdr.u.next.short); + transition accept; + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.u); + } +} + +control verifyChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; + diff --git a/testdata/p4_16_samples_outputs/parser-unroll-test7.p4-stderr b/testdata/p4_16_samples_outputs/parser-unroll-test7.p4-stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/testdata/p4_16_samples_outputs/parser-unroll-test7.p4.entries.txt b/testdata/p4_16_samples_outputs/parser-unroll-test7.p4.entries.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/testdata/p4_16_samples_outputs/parser-unroll-test7.p4.p4info.txt b/testdata/p4_16_samples_outputs/parser-unroll-test7.p4.p4info.txt new file mode 100644 index 00000000000..9ec92493e4c --- /dev/null +++ b/testdata/p4_16_samples_outputs/parser-unroll-test7.p4.p4info.txt @@ -0,0 +1,3 @@ +pkg_info { + arch: "v1model" +} diff --git a/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-first.p4 b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-first.p4 new file mode 100644 index 00000000000..8fb4d353639 --- /dev/null +++ b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-first.p4 @@ -0,0 +1,65 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +header S { + bit<8> t; +} + +header O1 { + bit<8> data; +} + +header O2 { + bit<16> data; +} + +header_union U { + O1 byte; + O2 short; +} + +struct headers { + S base; + U[2] u; +} + +struct metadata { +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + state start { + packet.extract(hdr.u.next.byte); + packet.extract(hdr.u.next.short); + transition accept; + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.u); + } +} + +control verifyChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; + diff --git a/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-frontend.p4 b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-frontend.p4 new file mode 100644 index 00000000000..8fb4d353639 --- /dev/null +++ b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-frontend.p4 @@ -0,0 +1,65 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +header S { + bit<8> t; +} + +header O1 { + bit<8> data; +} + +header O2 { + bit<16> data; +} + +header_union U { + O1 byte; + O2 short; +} + +struct headers { + S base; + U[2] u; +} + +struct metadata { +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + state start { + packet.extract(hdr.u.next.byte); + packet.extract(hdr.u.next.short); + transition accept; + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.u); + } +} + +control verifyChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; + diff --git a/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-midend.p4 b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-midend.p4 new file mode 100644 index 00000000000..fcb852c229c --- /dev/null +++ b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7-midend.p4 @@ -0,0 +1,68 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +header S { + bit<8> t; +} + +header O1 { + bit<8> data; +} + +header O2 { + bit<16> data; +} + +header_union U { + O1 byte; + O2 short; +} + +struct headers { + S base; + U[2] u; +} + +struct metadata { +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + state start { + packet.extract(hdr.u[32w0].byte); + packet.extract(hdr.u[32w1].short); + transition accept; + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.u[0].byte); + packet.emit(hdr.u[0].short); + packet.emit(hdr.u[1].byte); + packet.emit(hdr.u[1].short); + } +} + +control verifyChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; + diff --git a/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4 b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4 new file mode 100644 index 00000000000..11d544ae23a --- /dev/null +++ b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4 @@ -0,0 +1,65 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +header S { + bit<8> t; +} + +header O1 { + bit<8> data; +} + +header O2 { + bit<16> data; +} + +header_union U { + O1 byte; + O2 short; +} + +struct headers { + S base; + U[2] u; +} + +struct metadata { +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + state start { + packet.extract(hdr.u.next.byte); + packet.extract(hdr.u.next.short); + transition accept; + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.u); + } +} + +control verifyChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; + diff --git a/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4-stderr b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4-stderr new file mode 100644 index 00000000000..88a87166203 --- /dev/null +++ b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4-stderr @@ -0,0 +1,6 @@ +parser-unroll-test7.p4(33): [--Wwarn=ignore-prop] warning: Result of packet.extract is not defined: Error: Reading field from invalid header union + packet.extract(hdr.u.next.byte); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +parser-unroll-test7.p4(34): [--Wwarn=ignore-prop] warning: Result of packet.extract is not defined: Error: Reading field from invalid header union + packet.extract(hdr.u.next.short); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From d012e3f766205291f38a6888c82259259b94d0a5 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Tue, 19 Apr 2022 15:05:16 +0300 Subject: [PATCH 04/12] add StackVariable class --- midend/parserUnroll.cpp | 96 +++++++++++++++++++++++++++++++++++++---- midend/parserUnroll.h | 51 +++++++++++++++++++++- 2 files changed, 137 insertions(+), 10 deletions(-) diff --git a/midend/parserUnroll.cpp b/midend/parserUnroll.cpp index 9d39128cb86..ced2270da38 100644 --- a/midend/parserUnroll.cpp +++ b/midend/parserUnroll.cpp @@ -5,12 +5,90 @@ namespace P4 { +StackVariable::StackVariable(const IR::Expression* expr) + : expr(checkedTo(expr)) {} + +bool StackVariable::repOk(const IR::Expression* expr) { + // Only members can be stack variables. + const auto* member = expr->to(); + if (member == nullptr) { + return false; + } + + // A member is a stack variable if it is qualified by a PathExpression or if its qualifier is a + // stack variable. + return member->expr->is() || repOk(member->expr); +} + +bool StackVariable::operator<(const StackVariable& other) const { + return compare(expr, other.expr) < 0; +} + +bool StackVariable::operator==(const StackVariable& other) const { + // Delegate to IR's notion of equality. + return *expr == *other.expr; +} + +int StackVariable::compare(const IR::Expression* e1, const IR::Expression* e2) { + if (const auto* m1 = e1->to()) { + return compare(m1, e2); + } + if (const auto* p1 = e1->to()) { + return compare(p1, e2); + } + BUG("Not a valid StateVariable: %1%", e1); +} + +int StackVariable::compare(const IR::Member* m1, const IR::Expression* e2) { + if (const auto* m2 = e2->to()) { + return compare(m1, m2); + } + if (e2->is()) { + return 1; + } + BUG("Not a valid StateVariable: %1%", e2); +} + +int StackVariable::compare(const IR::Member* m1, const IR::Member* m2) { + auto result = compare(m1->expr, m2->expr); + if (result != 0) { + return result; + } + if (m1->member.name < m2->member.name) { + return -1; + } + if (m1->member.name > m2->member.name) { + return 1; + } + return 0; +} + +int StackVariable::compare(const IR::PathExpression* p1, const IR::Expression* e2) { + if (const auto* p2 = e2->to()) { + return compare(p1, p2); + } + if (e2->is()) { + return -1; + } + BUG("Not a valid StateVariable: %1%", e2); +} + +int StackVariable::compare(const IR::PathExpression* p1, const IR::PathExpression* p2) { + if (p1->path->name.name < p2->path->name.name) { + return -1; + } + if (p1->path->name.name > p2->path->name.name) { + return 1; + } + return 0; +} + /// The main class for parsers' states key for visited checking. struct VisitedKey { cstring name; // name of a state. - std::map indexes; // indexes of header stacks. + std::map indexes; // indexes of header stacks. - VisitedKey(cstring name, std::map& indexes) : name(name), indexes(indexes) { + VisitedKey(cstring name, std::map& indexes) : name(name), indexes(indexes) { } explicit VisitedKey(const ParserStateInfo* stateInfo) { @@ -32,7 +110,7 @@ struct VisitedKey { return true; if (name > e.name) return false; - std::map > mp; + std::map > mp; for (auto& i1 : indexes) mp.emplace(i1.first, std::make_pair(i1.second, -1)); for (auto& i2 : e.indexes) { @@ -133,7 +211,7 @@ class ParserStateRewriter : public Transform { auto* res = value->to()->constant->clone(); newExpression->right = res; BUG_CHECK(res->fitsInt64(), "To big integer for a header stack index %1%", res); - state->statesIndexes[expression->left->toString()] = (size_t)res->asInt64(); + state->statesIndexes[expression->left] = (size_t)res->asInt64(); return newExpression; } @@ -148,8 +226,8 @@ class ParserStateRewriter : public Transform { auto array = l->to(); unsigned idx = 0; unsigned offset = 0; - if (state->statesIndexes.count(expression->expr->toString())) { - idx = state->statesIndexes.at(expression->expr->toString()); + if (state->statesIndexes.count(expression->expr)) { + idx = state->statesIndexes.at(expression->expr); if (idx + 1 < array->size && expression->member.name != IR::Type_Stack::last) { offset = 1; } @@ -157,7 +235,7 @@ class ParserStateRewriter : public Transform { if (expression->member.name == IR::Type_Stack::lastIndex) { return new IR::Constant(IR::Type_Bits::get(32), idx); } else { - state->statesIndexes[expression->expr->toString()] = idx + offset; + state->statesIndexes[expression->expr] = idx + offset; return new IR::ArrayIndex(expression->expr->clone(), new IR::Constant(IR::Type_Bits::get(32), idx + offset)); } @@ -448,9 +526,9 @@ class ParserSymbolicInterpreter { visitedStates); const IR::Node* node = se->select->apply(rewriter); const IR::ListExpression* newListSelect = node->to(); - std::map etalonStateIndexes = state->statesIndexes; + auto etalonStateIndexes = state->statesIndexes; for (auto c : se->selectCases) { - std::map currentStateIndexes = etalonStateIndexes; + auto currentStateIndexes = etalonStateIndexes; auto path = c->state->path; auto next = refMap->getDeclaration(path); BUG_CHECK(next->is(), "%1%: expected a state", path); diff --git a/midend/parserUnroll.h b/midend/parserUnroll.h index 01a4a87b745..9b798d19410 100644 --- a/midend/parserUnroll.h +++ b/midend/parserUnroll.h @@ -33,6 +33,54 @@ const char outOfBoundsStateName[] = "stateOutOfBound"; ////////////////////////////////////////////// // The following are for a single parser +/// Represents a variable instance in a parser. +/// +/// This is a thin wrapper around a 'const IR::Member*' to (1) enforce invariants on which forms of +/// Members can represent state variables and (2) enable the use of StackVariable as map keys. +/// +/// A Member can represent a StackVariable exactly when its qualifying expression +/// (IR::Member::expr) either is a PathExpression or can represent a StackVariable. +class StackVariable { + public: + /// Determines whether @expr can represent a StateVariable. + static bool repOk(const IR::Expression* expr); + + // Implicit conversions to allow implementations to be treated like a Node*. + operator const IR::Expression*() const { return expr; } + const IR::Expression& operator*() const { return *expr; } + const IR::Expression* operator->() const { return expr; } + + // Implements comparisons so that StateVariables can be used as map keys. + bool operator<(const StackVariable& other) const; + bool operator==(const StackVariable& other) const; + + private: + const IR::Expression* expr; + + template + static const T* checkedTo(const IR::Expression* e) { + const T* result = e->to(); + BUG_CHECK(result, "Cast failed: %1% is not a %2%. It is a %3% instead.", e, + T::static_type_name(), e->node_type_name()); + return result; + } + + // Returns a negative value if e1 < e2, zero if e1 == e2, and a positive value otherwise. + // In these comparisons, + // * PathExpressions < Members. + // * PathExpressions are ordered on the name contained in their Paths. + // * Members are ordered first by their expressions, then by their member. + static int compare(const IR::Expression* e1, const IR::Expression* e2); + static int compare(const IR::Member* m1, const IR::Expression* e2); + static int compare(const IR::Member* m1, const IR::Member* m2); + static int compare(const IR::PathExpression* p1, const IR::Expression* e2); + static int compare(const IR::PathExpression* p1, const IR::PathExpression* p2); + + public: + /// Implicitly converts IR::Expression* to a StackVariable. + StackVariable(const IR::Expression* expr); // NOLINT(runtime/explicit) +}; + /// Information produced for a parser state by the symbolic evaluator struct ParserStateInfo { friend class ParserStateRewriter; @@ -44,7 +92,7 @@ struct ParserStateInfo { ValueMap* after; IR::ParserState* newState; // pointer to a new state size_t currentIndex; - std::map statesIndexes; // global map in state indexes + std::map statesIndexes; // global map in state indexes // set of parsers' states names with are in current path. std::unordered_set scenarioStates; std::unordered_set scenarioHS; // scenario header stack's operations @@ -234,6 +282,7 @@ class RewriteAllParsers : public Transform { // adding accept/reject newParser->states.push_back(new IR::ParserState(IR::ParserState::accept, nullptr)); newParser->states.push_back(new IR::ParserState(IR::ParserState::reject, nullptr)); + std::cout << newParser << std::endl; return newParser; } }; From 49ef04bf056e5fbe02163e2ce0bd2839cc514239 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Tue, 19 Apr 2022 16:35:21 +0300 Subject: [PATCH 05/12] fixing bug --- midend/parserUnroll.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/midend/parserUnroll.cpp b/midend/parserUnroll.cpp index ced2270da38..a4360e8eb51 100644 --- a/midend/parserUnroll.cpp +++ b/midend/parserUnroll.cpp @@ -88,8 +88,8 @@ struct VisitedKey { cstring name; // name of a state. std::map indexes; // indexes of header stacks. - VisitedKey(cstring name, std::map& indexes) : name(name), indexes(indexes) { - } + VisitedKey(cstring name, std::map& indexes) + : name(name), indexes(indexes) {} explicit VisitedKey(const ParserStateInfo* stateInfo) { CHECK_NULL(stateInfo); From 22e2fd1319ad8b9919ce0fb5a97c1431912430c2 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Wed, 20 Apr 2022 16:58:05 +0300 Subject: [PATCH 06/12] fix failed test --- .../parser-unroll/parser-unroll-test7.p4-stderr | 6 ------ 1 file changed, 6 deletions(-) diff --git a/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4-stderr b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4-stderr index 88a87166203..e69de29bb2d 100644 --- a/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4-stderr +++ b/testdata/p4_16_samples_outputs/parser-unroll/parser-unroll-test7.p4-stderr @@ -1,6 +0,0 @@ -parser-unroll-test7.p4(33): [--Wwarn=ignore-prop] warning: Result of packet.extract is not defined: Error: Reading field from invalid header union - packet.extract(hdr.u.next.byte); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -parser-unroll-test7.p4(34): [--Wwarn=ignore-prop] warning: Result of packet.extract is not defined: Error: Reading field from invalid header union - packet.extract(hdr.u.next.short); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 0f9362a1ca448cc39d0868bab8f21d09ebb18a20 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Thu, 21 Apr 2022 14:17:47 +0300 Subject: [PATCH 07/12] changes according review --- midend/parserUnroll.cpp | 71 ++++------------------------------------- midend/parserUnroll.h | 35 ++++---------------- 2 files changed, 14 insertions(+), 92 deletions(-) diff --git a/midend/parserUnroll.cpp b/midend/parserUnroll.cpp index a4360e8eb51..8312dd6fd4a 100644 --- a/midend/parserUnroll.cpp +++ b/midend/parserUnroll.cpp @@ -5,8 +5,10 @@ namespace P4 { -StackVariable::StackVariable(const IR::Expression* expr) - : expr(checkedTo(expr)) {} +StackVariable::StackVariable(const IR::Expression* expr) : expr(expr) { + CHECK_NULL(expr); + expr->checkedTo(); +} bool StackVariable::repOk(const IR::Expression* expr) { // Only members can be stack variables. @@ -20,69 +22,11 @@ bool StackVariable::repOk(const IR::Expression* expr) { return member->expr->is() || repOk(member->expr); } -bool StackVariable::operator<(const StackVariable& other) const { - return compare(expr, other.expr) < 0; -} - bool StackVariable::operator==(const StackVariable& other) const { // Delegate to IR's notion of equality. return *expr == *other.expr; } -int StackVariable::compare(const IR::Expression* e1, const IR::Expression* e2) { - if (const auto* m1 = e1->to()) { - return compare(m1, e2); - } - if (const auto* p1 = e1->to()) { - return compare(p1, e2); - } - BUG("Not a valid StateVariable: %1%", e1); -} - -int StackVariable::compare(const IR::Member* m1, const IR::Expression* e2) { - if (const auto* m2 = e2->to()) { - return compare(m1, m2); - } - if (e2->is()) { - return 1; - } - BUG("Not a valid StateVariable: %1%", e2); -} - -int StackVariable::compare(const IR::Member* m1, const IR::Member* m2) { - auto result = compare(m1->expr, m2->expr); - if (result != 0) { - return result; - } - if (m1->member.name < m2->member.name) { - return -1; - } - if (m1->member.name > m2->member.name) { - return 1; - } - return 0; -} - -int StackVariable::compare(const IR::PathExpression* p1, const IR::Expression* e2) { - if (const auto* p2 = e2->to()) { - return compare(p1, p2); - } - if (e2->is()) { - return -1; - } - BUG("Not a valid StateVariable: %1%", e2); -} - -int StackVariable::compare(const IR::PathExpression* p1, const IR::PathExpression* p2) { - if (p1->path->name.name < p2->path->name.name) { - return -1; - } - if (p1->path->name.name > p2->path->name.name) { - return 1; - } - return 0; -} - /// The main class for parsers' states key for visited checking. struct VisitedKey { cstring name; // name of a state. @@ -225,16 +169,15 @@ class ParserStateRewriter : public Transform { BUG_CHECK(l->is(), "%1%: expected an array", l); auto array = l->to(); unsigned idx = 0; - unsigned offset = 0; if (state->statesIndexes.count(expression->expr)) { idx = state->statesIndexes.at(expression->expr); - if (idx + 1 < array->size && expression->member.name != IR::Type_Stack::last) { - offset = 1; - } } if (expression->member.name == IR::Type_Stack::lastIndex) { return new IR::Constant(IR::Type_Bits::get(32), idx); } else { + int offset = + (idx + 1 < array->size && expression->member.name == IR::Type_Stack::next) ? 1 + : 0; state->statesIndexes[expression->expr] = idx + offset; return new IR::ArrayIndex(expression->expr->clone(), new IR::Constant(IR::Type_Bits::get(32), idx + offset)); diff --git a/midend/parserUnroll.h b/midend/parserUnroll.h index 9b798d19410..f905e3b4b8e 100644 --- a/midend/parserUnroll.h +++ b/midend/parserUnroll.h @@ -33,13 +33,13 @@ const char outOfBoundsStateName[] = "stateOutOfBound"; ////////////////////////////////////////////// // The following are for a single parser -/// Represents a variable instance in a parser. -/// -/// This is a thin wrapper around a 'const IR::Member*' to (1) enforce invariants on which forms of -/// Members can represent state variables and (2) enable the use of StackVariable as map keys. -/// -/// A Member can represent a StackVariable exactly when its qualifying expression -/// (IR::Member::expr) either is a PathExpression or can represent a StackVariable. +// Represents a variable for storing indexes values for a header stack. +// +// This is a thin wrapper around a 'const IR::Member*' to (1) enforce invariants on which forms of +// Members can represent state variables and (2) enable the use of StackVariable as map keys. +// +// A Member can represent a StackVariable exactly when its qualifying variable +// (IR::Member::expr) either is a PathExpression or can represent a StackVariable. class StackVariable { public: /// Determines whether @expr can represent a StateVariable. @@ -51,31 +51,11 @@ class StackVariable { const IR::Expression* operator->() const { return expr; } // Implements comparisons so that StateVariables can be used as map keys. - bool operator<(const StackVariable& other) const; bool operator==(const StackVariable& other) const; private: const IR::Expression* expr; - template - static const T* checkedTo(const IR::Expression* e) { - const T* result = e->to(); - BUG_CHECK(result, "Cast failed: %1% is not a %2%. It is a %3% instead.", e, - T::static_type_name(), e->node_type_name()); - return result; - } - - // Returns a negative value if e1 < e2, zero if e1 == e2, and a positive value otherwise. - // In these comparisons, - // * PathExpressions < Members. - // * PathExpressions are ordered on the name contained in their Paths. - // * Members are ordered first by their expressions, then by their member. - static int compare(const IR::Expression* e1, const IR::Expression* e2); - static int compare(const IR::Member* m1, const IR::Expression* e2); - static int compare(const IR::Member* m1, const IR::Member* m2); - static int compare(const IR::PathExpression* p1, const IR::Expression* e2); - static int compare(const IR::PathExpression* p1, const IR::PathExpression* p2); - public: /// Implicitly converts IR::Expression* to a StackVariable. StackVariable(const IR::Expression* expr); // NOLINT(runtime/explicit) @@ -282,7 +262,6 @@ class RewriteAllParsers : public Transform { // adding accept/reject newParser->states.push_back(new IR::ParserState(IR::ParserState::accept, nullptr)); newParser->states.push_back(new IR::ParserState(IR::ParserState::reject, nullptr)); - std::cout << newParser << std::endl; return newParser; } }; From 5fa6561c2299dbfabf3a336b4662011b95403542 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Thu, 21 Apr 2022 17:34:54 +0300 Subject: [PATCH 08/12] add operator< --- midend/parserUnroll.cpp | 76 ++++++++++++++++++++++++++++++++++++----- midend/parserUnroll.h | 20 ++++++++--- 2 files changed, 84 insertions(+), 12 deletions(-) diff --git a/midend/parserUnroll.cpp b/midend/parserUnroll.cpp index 8312dd6fd4a..4c03ea24490 100644 --- a/midend/parserUnroll.cpp +++ b/midend/parserUnroll.cpp @@ -5,9 +5,10 @@ namespace P4 { -StackVariable::StackVariable(const IR::Expression* expr) : expr(expr) { +StackVariable::StackVariable(const IR::Expression* expr) : member(nullptr) { CHECK_NULL(expr); - expr->checkedTo(); + BUG_CHECK(repOk(expr), "Invalid stack variable %1%", expr); + member = expr->checkedTo(); } bool StackVariable::repOk(const IR::Expression* expr) { @@ -22,15 +23,73 @@ bool StackVariable::repOk(const IR::Expression* expr) { return member->expr->is() || repOk(member->expr); } +bool StackVariable::operator<(const StackVariable& other) const { + return compare(member, other.member) < 0; +} + bool StackVariable::operator==(const StackVariable& other) const { // Delegate to IR's notion of equality. - return *expr == *other.expr; + return *member == *other.member; +} + +int StackVariable::compare(const IR::Expression* e1, const IR::Expression* e2) { + if (const auto* m1 = e1->to()) { + return compare(m1, e2); + } + if (const auto* p1 = e1->to()) { + return compare(p1, e2); + } + BUG("Not a valid StateVariable: %1%", e1); +} + +int StackVariable::compare(const IR::Member* m1, const IR::Expression* e2) { + if (const auto* m2 = e2->to()) { + return compare(m1, m2); + } + if (e2->is()) { + return 1; + } + BUG("Not a valid StateVariable: %1%", e2); +} + +int StackVariable::compare(const IR::Member* m1, const IR::Member* m2) { + auto result = compare(m1->expr, m2->expr); + if (result != 0) { + return result; + } + if (m1->member.name < m2->member.name) { + return -1; + } + if (m1->member.name > m2->member.name) { + return 1; + } + return 0; +} + +int StackVariable::compare(const IR::PathExpression* p1, const IR::Expression* e2) { + if (const auto* p2 = e2->to()) { + return compare(p1, p2); + } + if (e2->is()) { + return -1; + } + BUG("Not a valid StateVariable: %1%", e2); +} + +int StackVariable::compare(const IR::PathExpression* p1, const IR::PathExpression* p2) { + if (p1->path->name.name < p2->path->name.name) { + return -1; + } + if (p1->path->name.name > p2->path->name.name) { + return 1; + } + return 0; } /// The main class for parsers' states key for visited checking. struct VisitedKey { - cstring name; // name of a state. - std::map indexes; // indexes of header stacks. + cstring name; // name of a state. + std::map indexes; // indexes of header stacks. VisitedKey(cstring name, std::map& indexes) : name(name), indexes(indexes) {} @@ -169,15 +228,16 @@ class ParserStateRewriter : public Transform { BUG_CHECK(l->is(), "%1%: expected an array", l); auto array = l->to(); unsigned idx = 0; + unsigned offset = 0; if (state->statesIndexes.count(expression->expr)) { idx = state->statesIndexes.at(expression->expr); + if (idx + 1 < array->size && expression->member.name != IR::Type_Stack::last) { + offset = 1; + } } if (expression->member.name == IR::Type_Stack::lastIndex) { return new IR::Constant(IR::Type_Bits::get(32), idx); } else { - int offset = - (idx + 1 < array->size && expression->member.name == IR::Type_Stack::next) ? 1 - : 0; state->statesIndexes[expression->expr] = idx + offset; return new IR::ArrayIndex(expression->expr->clone(), new IR::Constant(IR::Type_Bits::get(32), idx + offset)); diff --git a/midend/parserUnroll.h b/midend/parserUnroll.h index f905e3b4b8e..2f064257d18 100644 --- a/midend/parserUnroll.h +++ b/midend/parserUnroll.h @@ -46,15 +46,27 @@ class StackVariable { static bool repOk(const IR::Expression* expr); // Implicit conversions to allow implementations to be treated like a Node*. - operator const IR::Expression*() const { return expr; } - const IR::Expression& operator*() const { return *expr; } - const IR::Expression* operator->() const { return expr; } + operator const IR::Member*() const { return member; } + const IR::Member& operator*() const { return *member; } + const IR::Member* operator->() const { return member; } // Implements comparisons so that StateVariables can be used as map keys. + bool operator<(const StackVariable& other) const; bool operator==(const StackVariable& other) const; private: - const IR::Expression* expr; + const IR::Member* member; + + // Returns a negative value if e1 < e2, zero if e1 == e2, and a positive value otherwise. + // In these comparisons, + // * PathExpressions < Members. + // * PathExpressions are ordered on the name contained in their Paths. + // * Members are ordered first by their expressions, then by their member. + static int compare(const IR::Expression* e1, const IR::Expression* e2); + static int compare(const IR::Member* m1, const IR::Expression* e2); + static int compare(const IR::Member* m1, const IR::Member* m2); + static int compare(const IR::PathExpression* p1, const IR::Expression* e2); + static int compare(const IR::PathExpression* p1, const IR::PathExpression* p2); public: /// Implicitly converts IR::Expression* to a StackVariable. From 147017facf07bf80992d2546ec532f36c2fb76b0 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Thu, 9 Jun 2022 15:47:11 +0300 Subject: [PATCH 09/12] update according review --- midend/parserUnroll.cpp | 72 +++++++++-------------------------------- midend/parserUnroll.h | 24 +++++++------- 2 files changed, 26 insertions(+), 70 deletions(-) diff --git a/midend/parserUnroll.cpp b/midend/parserUnroll.cpp index 166cdc5bf31..0af0a56de7f 100644 --- a/midend/parserUnroll.cpp +++ b/midend/parserUnroll.cpp @@ -1,5 +1,6 @@ #include "parserUnroll.h" #include "interpreter.h" +#include "lib/hash.h" #include "lib/stringify.h" #include "ir/ir.h" @@ -23,75 +24,32 @@ bool StackVariable::repOk(const IR::Expression* expr) { return member->expr->is() || repOk(member->expr); } -bool StackVariable::operator<(const StackVariable& other) const { - return compare(member, other.member) < 0; -} - bool StackVariable::operator==(const StackVariable& other) const { // Delegate to IR's notion of equality. return *member == *other.member; } -int StackVariable::compare(const IR::Expression* e1, const IR::Expression* e2) { - if (const auto* m1 = e1->to()) { - return compare(m1, e2); - } - if (const auto* p1 = e1->to()) { - return compare(p1, e2); - } - BUG("Not a valid StateVariable: %1%", e1); -} - -int StackVariable::compare(const IR::Member* m1, const IR::Expression* e2) { - if (const auto* m2 = e2->to()) { - return compare(m1, m2); - } - if (e2->is()) { - return 1; - } - BUG("Not a valid StateVariable: %1%", e2); -} - -int StackVariable::compare(const IR::Member* m1, const IR::Member* m2) { - auto result = compare(m1->expr, m2->expr); - if (result != 0) { - return result; - } - if (m1->member.name < m2->member.name) { - return -1; - } - if (m1->member.name > m2->member.name) { - return 1; - } - return 0; -} - -int StackVariable::compare(const IR::PathExpression* p1, const IR::Expression* e2) { - if (const auto* p2 = e2->to()) { - return compare(p1, p2); - } - if (e2->is()) { - return -1; - } - BUG("Not a valid StateVariable: %1%", e2); -} - -int StackVariable::compare(const IR::PathExpression* p1, const IR::PathExpression* p2) { - if (p1->path->name.name < p2->path->name.name) { - return -1; - } - if (p1->path->name.name > p2->path->name.name) { - return 1; +size_t StackVariableHash::operator()(const StackVariable& var) const { + const IR::Member* curMember = var.operator->(); + std::vector h; + while(curMember) { + h.push_back(Util::Hash::fnv1a(curMember->member.name)); + if (auto* path = curMember->expr->to()) { + h.push_back(Util::Hash::fnv1a(path->path->name)); + break; + } + BUG_CHECK(curMember->expr->is(), "Not a valid StateVariable: %1%", curMember); + curMember = curMember->expr->to(); } - return 0; + return Util::Hash::fnv1a(h.data(), sizeof(size_t) * h.size()); } /// The main class for parsers' states key for visited checking. struct VisitedKey { cstring name; // name of a state. - std::map indexes; // indexes of header stacks. + StackVariableMap indexes; // indexes of header stacks. - VisitedKey(cstring name, std::map& indexes) + VisitedKey(cstring name, StackVariableMap& indexes) : name(name), indexes(indexes) {} explicit VisitedKey(const ParserStateInfo* stateInfo) { diff --git a/midend/parserUnroll.h b/midend/parserUnroll.h index 2f064257d18..d7a90b83c58 100644 --- a/midend/parserUnroll.h +++ b/midend/parserUnroll.h @@ -17,6 +17,8 @@ limitations under the License. #ifndef _MIDEND_PARSERUNROLL_H_ #define _MIDEND_PARSERUNROLL_H_ +#include + #include "ir/ir.h" #include "frontends/common/resolveReferences/referenceMap.h" #include "frontends/p4/callGraph.h" @@ -51,28 +53,24 @@ class StackVariable { const IR::Member* operator->() const { return member; } // Implements comparisons so that StateVariables can be used as map keys. - bool operator<(const StackVariable& other) const; bool operator==(const StackVariable& other) const; private: const IR::Member* member; - // Returns a negative value if e1 < e2, zero if e1 == e2, and a positive value otherwise. - // In these comparisons, - // * PathExpressions < Members. - // * PathExpressions are ordered on the name contained in their Paths. - // * Members are ordered first by their expressions, then by their member. - static int compare(const IR::Expression* e1, const IR::Expression* e2); - static int compare(const IR::Member* m1, const IR::Expression* e2); - static int compare(const IR::Member* m1, const IR::Member* m2); - static int compare(const IR::PathExpression* p1, const IR::Expression* e2); - static int compare(const IR::PathExpression* p1, const IR::PathExpression* p2); - public: /// Implicitly converts IR::Expression* to a StackVariable. StackVariable(const IR::Expression* expr); // NOLINT(runtime/explicit) }; +/// Class with hash function for @a StackVariable. +class StackVariableHash { + public: + size_t operator()(const StackVariable& var) const; +}; + +typedef std::unordered_map StackVariableMap; + /// Information produced for a parser state by the symbolic evaluator struct ParserStateInfo { friend class ParserStateRewriter; @@ -84,7 +82,7 @@ struct ParserStateInfo { ValueMap* after; IR::ParserState* newState; // pointer to a new state size_t currentIndex; - std::map statesIndexes; // global map in state indexes + StackVariableMap statesIndexes; // global map in state indexes // set of parsers' states names with are in current path. std::unordered_set scenarioStates; std::unordered_set scenarioHS; // scenario header stack's operations From a9797f75b4de7a213dffd649d581b9881580b5d5 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Fri, 10 Jun 2022 18:17:09 +0300 Subject: [PATCH 10/12] fixing bug for stack variable storage --- midend/parserUnroll.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/midend/parserUnroll.cpp b/midend/parserUnroll.cpp index 0af0a56de7f..cd569ab940b 100644 --- a/midend/parserUnroll.cpp +++ b/midend/parserUnroll.cpp @@ -26,7 +26,7 @@ bool StackVariable::repOk(const IR::Expression* expr) { bool StackVariable::operator==(const StackVariable& other) const { // Delegate to IR's notion of equality. - return *member == *other.member; + return member->equiv(*other.member); } size_t StackVariableHash::operator()(const StackVariable& var) const { @@ -197,6 +197,7 @@ class ParserStateRewriter : public Transform { return new IR::Constant(IR::Type_Bits::get(32), idx); } else { state->statesIndexes[expression->expr] = idx + offset; + std::cout << state->statesIndexes.size() << std::endl; return new IR::ArrayIndex(expression->expr->clone(), new IR::Constant(IR::Type_Bits::get(32), idx + offset)); } From 4814a028f5072fc11141ef311bad3b8df9e34f94 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Fri, 10 Jun 2022 21:16:41 +0300 Subject: [PATCH 11/12] fixing bug --- midend/parserUnroll.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/midend/parserUnroll.cpp b/midend/parserUnroll.cpp index cd569ab940b..85daea2db2d 100644 --- a/midend/parserUnroll.cpp +++ b/midend/parserUnroll.cpp @@ -32,7 +32,7 @@ bool StackVariable::operator==(const StackVariable& other) const { size_t StackVariableHash::operator()(const StackVariable& var) const { const IR::Member* curMember = var.operator->(); std::vector h; - while(curMember) { + while (curMember) { h.push_back(Util::Hash::fnv1a(curMember->member.name)); if (auto* path = curMember->expr->to()) { h.push_back(Util::Hash::fnv1a(path->path->name)); From 4569335b98ce5b5fde0a7b58b2c8f77396a5d3ee Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Tue, 14 Jun 2022 11:07:57 +0300 Subject: [PATCH 12/12] changes according review --- midend/parserUnroll.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/midend/parserUnroll.cpp b/midend/parserUnroll.cpp index 85daea2db2d..07d78c4d0cf 100644 --- a/midend/parserUnroll.cpp +++ b/midend/parserUnroll.cpp @@ -38,8 +38,7 @@ size_t StackVariableHash::operator()(const StackVariable& var) const { h.push_back(Util::Hash::fnv1a(path->path->name)); break; } - BUG_CHECK(curMember->expr->is(), "Not a valid StateVariable: %1%", curMember); - curMember = curMember->expr->to(); + curMember = curMember->expr->checkedTo(); } return Util::Hash::fnv1a(h.data(), sizeof(size_t) * h.size()); }