From 1b84d98e4f67ab18d7800d76ba000f882f970e28 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Tue, 23 Jan 2024 14:49:38 +0100 Subject: [PATCH] Fix filters consuming too much data. We would previously assume that a filter would consume all available data. This only holds if the filter is attached to a top-level unit, but in general not if some sub-unit uses a filter. With this patch we explicitly compute how much data is consumed. Closes #1652. --- .../src/compiler/codegen/parser-builder.cc | 27 +++-- .../noopt.hlt | 33 ++++--- .../noopt.hlt | 77 +++++++++------ .../opt.hlt | 11 ++- .../noopt.hlt | 55 +++++++---- .../spicy.optimization.unused-types/noopt.hlt | 99 ++++++++++++------- .../output | 4 +- .../spicy.types.unit.canonical-ids/output | 8 +- .../spicy.types.unit.filter-size/output | 22 +++++ tests/spicy/types/unit/filter-size.spicy | 41 ++++++++ 10 files changed, 267 insertions(+), 110 deletions(-) create mode 100644 tests/Baseline/spicy.types.unit.filter-size/output create mode 100644 tests/spicy/types/unit/filter-size.spicy diff --git a/spicy/toolchain/src/compiler/codegen/parser-builder.cc b/spicy/toolchain/src/compiler/codegen/parser-builder.cc index a0fb51a10..4fc1e2383 100644 --- a/spicy/toolchain/src/compiler/codegen/parser-builder.cc +++ b/spicy/toolchain/src/compiler/codegen/parser-builder.cc @@ -327,6 +327,11 @@ struct ProductionVisitor if ( unit ) { pb->guardFeatureCode(*unit->id(), {"supports_filters"}, [&]() { // If we have a filter attached, we initialize it and change to parse from its output. + auto offset1 = + builder()->addTmp("offset1", + builder::memberCall(builder::begin(builder::deref(state().data)), + "offset", {})); + auto filtered = builder::assign(builder::id("filtered"), builder::call("spicy_rt::filter_init", {state().self, state().data, state().cur})); @@ -335,15 +340,23 @@ struct ProductionVisitor pushBuilder(have_filter); auto args2 = args; - builder()->addLocal("filtered_data", type::ValueReference(type::Stream()), - builder::id("filtered")); - args2[0] = builder::id("filtered_data"); - args2[1] = builder::begin(builder::deref(args2[0])); - args2[2] = builder::deref(args2[0]); + + auto filtered_data = + builder()->addTmp("filtered_data", type::ValueReference(type::Stream()), + builder::id("filtered")); + args2[0] = filtered_data; + args2[1] = builder::begin(builder::deref(filtered_data)); + args2[2] = builder::deref(filtered_data); + builder()->addExpression(builder::memberCall(state().self, id_stage2, args2)); - // Assume the filter consumed the full input. - pb->advanceInput(builder::size(state().cur)); + auto offset2 = + builder()->addTmp("offset2", + builder::memberCall(builder::begin(builder::deref(state().data)), + "offset", {})); + + auto advance = builder::difference(offset2, offset1); + pb->advanceInput(advance); auto result = builder::tuple({state().cur, state().lahead, state().lahead_end, state().error}); diff --git a/tests/Baseline/spicy.optimization.default-parser-functions/noopt.hlt b/tests/Baseline/spicy.optimization.default-parser-functions/noopt.hlt index 5300b7889..358c604bf 100644 --- a/tests/Baseline/spicy.optimization.default-parser-functions/noopt.hlt +++ b/tests/Baseline/spicy.optimization.default-parser-functions/noopt.hlt @@ -142,12 +142,14 @@ method method tuple, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@P0%supports_filters ) + if ( __feat%foo@@P0%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_P0_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_P0_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -155,6 +157,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@P1%supports_filters ) + if ( __feat%foo@@P1%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_P1_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_P1_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -388,6 +393,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@P2%supports_filters ) + if ( __feat%foo@@P2%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_P2_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_P2_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -623,6 +631,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@X0%supports_filters ) + if ( __feat%foo@@X0%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_X0_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_X0_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -286,6 +288,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@X1%supports_filters ) + if ( __feat%foo@@X1%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_X1_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_X1_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -523,6 +528,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@X2%supports_filters ) + if ( __feat%foo@@X2%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_X2_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_X2_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -756,6 +764,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@X3%supports_filters ) + if ( __feat%foo@@X3%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_X3_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_X3_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -989,6 +1000,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@X4%supports_filters ) + if ( __feat%foo@@X4%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_X4_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_X4_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -1230,6 +1244,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@X5%supports_filters ) + if ( __feat%foo@@X5%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_X5_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_X5_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -1475,6 +1492,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@X6%supports_filters ) + if ( __feat%foo@@X6%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_X6_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_X6_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -1708,6 +1728,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - + { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_X5_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_X5_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -260,6 +262,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@A%supports_filters ) + if ( __feat%foo@@A%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_A_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_A_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -223,6 +225,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@B%supports_filters ) + if ( __feat%foo@@B%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_B_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_B_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -456,6 +461,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@C%supports_filters ) + if ( __feat%foo@@C%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_C_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_C_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -685,6 +693,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@D%supports_filters ) + if ( __feat%foo@@D%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_D_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_D_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -918,6 +929,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@F%supports_filters ) + if ( __feat%foo@@F%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_F_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_F_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -1162,6 +1176,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@Priv1%supports_filters ) + if ( __feat%foo@@Priv1%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_Priv1_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_Priv1_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -360,6 +362,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@Pub2%supports_filters ) + if ( __feat%foo@@Pub2%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_Pub2_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_Pub2_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -593,6 +598,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@Priv2%supports_filters ) + if ( __feat%foo@@Priv2%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_Priv2_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_Priv2_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -822,6 +830,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@Priv3%supports_filters ) + if ( __feat%foo@@Priv3%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_Priv3_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_Priv3_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -1055,6 +1066,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@Priv4%supports_filters ) + if ( __feat%foo@@Priv4%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_Priv4_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_Priv4_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -1288,6 +1302,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@Priv5%supports_filters ) + if ( __feat%foo@@Priv5%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_Priv5_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_Priv5_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -1567,6 +1584,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@Priv6%supports_filters ) + if ( __feat%foo@@Priv6%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_Priv6_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_Priv6_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -1800,6 +1820,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@Pub3%supports_filters ) + if ( __feat%foo@@Pub3%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_Pub3_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_Pub3_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -2033,6 +2056,7 @@ method method tuple, int<64>, iterator, optional, int<64>, iterator, optional filtered = Null; - if ( __feat%foo@@Priv10%supports_filters ) + if ( __feat%foo@@Priv10%supports_filters ) { + local uint<64> __offset1 = begin((*__data)).offset(); if ( filtered = spicy_rt::filter_init(self, __data, __cur) ) { - local value_ref filtered_data = filtered; - (*self).__parse_foo_Priv10_stage2(filtered_data, begin((*filtered_data)), (*filtered_data), __trim, __lah, __lahe, __error); - __cur = __cur.advance(|__cur|); + local value_ref __filtered_data = filtered; + (*self).__parse_foo_Priv10_stage2(__filtered_data, begin((*__filtered_data)), (*__filtered_data), __trim, __lah, __lahe, __error); + local uint<64> __offset2 = begin((*__data)).offset(); + __cur = __cur.advance(__offset2 - __offset1); if ( __trim ) (*__data).trim(begin(__cur)); @@ -2308,6 +2334,7 @@ method method tuple, int<64>, iterator, optional= 0.63. +foo::X { + restrict_: NONE + y: foo::Y { + data: A + } + z: BC +} +foo::X { + restrict_: SIZE + y: foo::Y { + data: A + } + z: BC +} +foo::X { + restrict_: MAX_SIZE + y: foo::Y { + data: A + } + z: BC +} diff --git a/tests/spicy/types/unit/filter-size.spicy b/tests/spicy/types/unit/filter-size.spicy new file mode 100644 index 000000000..3251a526e --- /dev/null +++ b/tests/spicy/types/unit/filter-size.spicy @@ -0,0 +1,41 @@ +# @TEST-EXEC: spicyc -dj %INPUT -o foo.hlto +# @TEST-EXEC: ${SCRIPTS}/printf '\x00ABC' | spicy-dump -d foo.hlto >>output 2>&1 +# @TEST-EXEC: ${SCRIPTS}/printf '\x01ABC' | spicy-dump -d foo.hlto >>output 2>&1 +# @TEST-EXEC: ${SCRIPTS}/printf '\x02ABC' | spicy-dump -d foo.hlto >>output 2>&1 +# @TEST-EXEC: btest-diff output + +module foo; + +type RestrictFilteredUnit = enum { + NONE = 0, + SIZE = 1, + MAX_SIZE = 2, +}; + +const N: uint64 = 1; + +public type X = unit { + restrict: uint8 &convert=RestrictFilteredUnit($$); + switch (self.restrict) { + RestrictFilteredUnit::NONE -> y: Y; + RestrictFilteredUnit::SIZE -> y: Y &size=N; + RestrictFilteredUnit::MAX_SIZE -> y: Y &max-size=N; + }; + z: bytes &eod &requires=|$$| != 0; +}; + +type Y = unit { + on %init { + self.connect_filter(new F); + } + + data: bytes &size=N; +}; + +type F = unit { + %filter; + + filter_input: bytes &size=N { + self.forward($$); + } +};