@@ -65,7 +65,7 @@ PackContext::PackContext(CodeBlob& code, SrcLocation loc, std::vector<var_idx_t>
6565 , f_storeUint(lookup_function(" builder.storeUint" ))
6666 , ir_builder(std::move(ir_builder))
6767 , ir_builder0(this ->ir_builder[0 ])
68- , option_skipBitsNFieldsValidation (ir_options[0 ]) {
68+ , option_skipBitsNValidation (ir_options[0 ]) {
6969}
7070
7171void PackContext::storeInt (var_idx_t ir_idx, int len) const {
@@ -264,16 +264,51 @@ struct S_IntN final : ISerializer {
264264 }
265265};
266266
267- struct S_BytesN final : ISerializer {
267+ struct S_VariadicIntN final : ISerializer {
268+ const int n_bits; // only 16 and 32 available
269+ const bool is_unsigned;
270+
271+ explicit S_VariadicIntN (int n_bits, bool is_unsigned)
272+ : n_bits(n_bits), is_unsigned(is_unsigned) {}
273+
274+ void pack (const PackContext* ctx, CodeBlob& code, SrcLocation loc, std::vector<var_idx_t >&& rvect) override {
275+ FunctionPtr f_storeVarInt = lookup_function (" builder.__storeVarInt" );
276+ std::vector args = { ctx->ir_builder0 , rvect[0 ], code.create_int (loc, n_bits, " (n-bits)" ), code.create_int (loc, is_unsigned, " (is-unsigned)" ) };
277+ code.emplace_back (loc, Op::_Call, ctx->ir_builder , std::move (args), f_storeVarInt);
278+ }
279+
280+ std::vector<var_idx_t > unpack (const UnpackContext* ctx, CodeBlob& code, SrcLocation loc) override {
281+ FunctionPtr f_loadVarInt = lookup_function (" slice.__loadVarInt" );
282+ std::vector args = { ctx->ir_slice0 , code.create_int (loc, n_bits, " (n-bits)" ), code.create_int (loc, is_unsigned, " (is-unsigned)" ) };
283+ std::vector result = code.create_tmp_var (TypeDataInt::create (), loc, " (loaded-varint)" );
284+ code.emplace_back (loc, Op::_Call, std::vector{ctx->ir_slice0 , result[0 ]}, std::move (args), f_loadVarInt);
285+ return result;
286+ }
287+
288+ void skip (const UnpackContext* ctx, CodeBlob& code, SrcLocation loc) override {
289+ // no TVM instruction to skip, just load but don't use the result
290+ unpack (ctx, code, loc);
291+ }
292+
293+ PackSize estimate (const EstimateContext* ctx) override {
294+ if (n_bits == 32 ) {
295+ return PackSize (5 , 253 );
296+ } else {
297+ return PackSize (4 , 124 ); // same as `coins`
298+ }
299+ }
300+ };
301+
302+ struct S_BitsN final : ISerializer {
268303 const int n_bits;
269304
270- explicit S_BytesN (int n_width, bool is_bits)
305+ explicit S_BitsN (int n_width, bool is_bits)
271306 : n_bits(is_bits ? n_width : n_width * 8 ) {}
272307
273308 void pack (const PackContext* ctx, CodeBlob& code, SrcLocation loc, std::vector<var_idx_t >&& rvect) override {
274309 tolk_assert (rvect.size () == 1 );
275310
276- Op& if_disabled_by_user = code.emplace_back (loc, Op::_If, std::vector{ctx->option_skipBitsNFieldsValidation });
311+ Op& if_disabled_by_user = code.emplace_back (loc, Op::_If, std::vector{ctx->option_skipBitsNValidation });
277312 {
278313 code.push_set_cur (if_disabled_by_user.block0 );
279314 code.close_pop_cur (loc);
@@ -400,10 +435,8 @@ struct S_Coins final : ISerializer {
400435 }
401436
402437 void skip (const UnpackContext* ctx, CodeBlob& code, SrcLocation loc) override {
403- FunctionPtr f_loadCoins = lookup_function (" slice.loadCoins" );
404- std::vector args = ctx->ir_slice ;
405- std::vector dummy_loaded = code.create_tmp_var (TypeDataInt::create (), loc, " (loaded-coins)" );
406- code.emplace_back (loc, Op::_Call, std::vector{ctx->ir_slice0 , dummy_loaded[0 ]}, std::move (args), f_loadCoins);
438+ // no TVM instruction to skip, just load but don't use the result
439+ unpack (ctx, code, loc);
407440 }
408441
409442 PackSize estimate (const EstimateContext* ctx) override {
@@ -428,9 +461,7 @@ struct S_Address final : ISerializer {
428461 // we can't do just
429462 // ctx->skipBits(2 + 1 + 8 + 256);
430463 // because it may be addr_none or addr_extern; there is no "skip address" in TVM, so just load it
431- FunctionPtr f_loadAddress = lookup_function (" slice.loadAddress" );
432- std::vector ir_address = code.create_tmp_var (TypeDataSlice::create (), loc, " (tmp-addr)" );
433- code.emplace_back (loc, Op::_Call, std::vector{ctx->ir_slice0 , ir_address[0 ]}, ctx->ir_slice , f_loadAddress);
464+ unpack (ctx, code, loc);
434465 }
435466
436467 PackSize estimate (const EstimateContext* ctx) override {
@@ -1088,10 +1119,13 @@ std::vector<PackOpcode> auto_generate_opcodes_for_union(TypePtr union_type, std:
10881119
10891120static std::unique_ptr<ISerializer> get_serializer_for_type (TypePtr any_type) {
10901121 if (const auto * t_intN = any_type->try_as <TypeDataIntN>()) {
1122+ if (t_intN->is_variadic ) {
1123+ return std::make_unique<S_VariadicIntN>(t_intN->n_bits , t_intN->is_unsigned );
1124+ }
10911125 return std::make_unique<S_IntN>(t_intN->n_bits , t_intN->is_unsigned );
10921126 }
1093- if (const auto * t_bytesN = any_type->try_as <TypeDataBytesN >()) {
1094- return std::make_unique<S_BytesN>(t_bytesN ->n_width , t_bytesN ->is_bits );
1127+ if (const auto * t_bitsN = any_type->try_as <TypeDataBitsN >()) {
1128+ return std::make_unique<S_BitsN>(t_bitsN ->n_width , t_bitsN ->is_bits );
10951129 }
10961130 if (any_type == TypeDataCoins::create ()) {
10971131 return std::make_unique<S_Coins>();
0 commit comments