@@ -55,39 +55,49 @@ static void append_bitwise_and_shard_mask(CodeBlob& code, SrcLocation loc, var_i
5555
5656// struct AutoDeployAddress { workchain: int8; stateInit: ContractState | cell; toShard: AddressShardingOptions?; }
5757struct IR_AutoDeployAddress {
58- std::vector<var_idx_t > is_ContractState, // stateInit is ContractState
59- is_AddressSharding; // toShard is not null
58+ std::vector<var_idx_t > ir_stateInitField,
59+ ir_toShardField;
60+ const TypeDataUnion* t_stateInit;
61+ const TypeDataUnion* t_toShard;
6062 var_idx_t workchain, // workchain
6163 stateInitCode, stateInitData, stateInitCell, // stateInit
6264 ir_shardDepth, ir_closeTo; // toShard
6365
6466 IR_AutoDeployAddress (CodeBlob& code, SrcLocation loc, const std::vector<var_idx_t >& ir_vars) {
6567 StructPtr s_AutoDeployAddress = lookup_global_symbol (" AutoDeployAddress" )->try_as <StructPtr>();
66- const TypeDataUnion* t_stateInit = s_AutoDeployAddress->find_field (" stateInit" )->declared_type ->try_as <TypeDataUnion>();
67- const TypeDataUnion* t_toShard = s_AutoDeployAddress->find_field (" toShard" )->declared_type ->try_as <TypeDataUnion>();
68+ t_stateInit = s_AutoDeployAddress->find_field (" stateInit" )->declared_type ->try_as <TypeDataUnion>();
69+ t_toShard = s_AutoDeployAddress->find_field (" toShard" )->declared_type ->try_as <TypeDataUnion>();
6870 tolk_assert (ir_vars.size () == 1 + 3 + 3 );
6971 tolk_assert (t_stateInit && t_stateInit->get_width_on_stack () == (2 +1 ) && t_stateInit->size () == 2 );
7072 tolk_assert (t_toShard && t_toShard->get_width_on_stack () == (2 +1 ) && t_toShard->or_null );
7173
7274 workchain = ir_vars[0 ];
7375
74- std::vector ir_stateInitUnion (ir_vars.begin () + 1 , ir_vars.begin () + 1 + 3 );
75- is_ContractState = pre_compile_is_type (code, t_stateInit, t_stateInit->variants [0 ], ir_stateInitUnion, loc, " (is-ContractState)" );
76- std::vector ir_ContractState = transition_to_target_type (std::vector (ir_stateInitUnion), code, t_stateInit, t_stateInit->variants [0 ], loc);
76+ ir_stateInitField = std::vector (ir_vars.begin () + 1 , ir_vars.begin () + 1 + 3 );
77+ std::vector ir_ContractState = transition_to_target_type (std::vector (ir_stateInitField), code, t_stateInit, t_stateInit->variants [0 ], loc);
7778 stateInitCode = ir_ContractState[0 ];
7879 stateInitData = ir_ContractState[1 ];
79- stateInitCell = transition_to_target_type (std::vector (ir_stateInitUnion ), code, t_stateInit, t_stateInit->variants [1 ], loc)[0 ];
80+ stateInitCell = transition_to_target_type (std::vector (ir_stateInitField ), code, t_stateInit, t_stateInit->variants [1 ], loc)[0 ];
8081
81- std::vector ir_toShardOrNull (ir_vars.begin () + 1 + 3 , ir_vars.begin () + 1 + 3 + 3 );
82- is_AddressSharding = pre_compile_is_type (code, t_toShard, t_toShard->or_null , ir_toShardOrNull, loc, " (is-AddressSharding)" );
83- std::vector ir_AddressSharding = transition_to_target_type (std::vector (ir_toShardOrNull), code, t_toShard, t_toShard->or_null , loc);
82+ ir_toShardField = std::vector (ir_vars.begin () + 1 + 3 , ir_vars.begin () + 1 + 3 + 3 );
83+ std::vector ir_AddressSharding = transition_to_target_type (std::vector (ir_toShardField), code, t_toShard, t_toShard->or_null , loc);
8484 ir_shardDepth = ir_AddressSharding[0 ];
8585 ir_closeTo = ir_AddressSharding[1 ];
8686 }
87+
88+ // generate IR vars "stateInit is ContractState"
89+ std::vector<var_idx_t > is_ContractState (CodeBlob& code, SrcLocation loc) const {
90+ return pre_compile_is_type (code, t_stateInit, t_stateInit->variants [0 ], ir_stateInitField, loc, " (is-ContractState)" );
91+ }
92+
93+ // generate IR vars "toShard is not null"
94+ std::vector<var_idx_t > is_AddressSharding (CodeBlob& code, SrcLocation loc) const {
95+ return pre_compile_is_type (code, t_toShard, t_toShard->or_null , ir_toShardField, loc, " (is-AddressSharding)" );
96+ }
8797};
8898
8999// fun createMessage<TBody>(options: CreateMessageOptions<TBody>): OutMessage
90- std::vector<var_idx_t > generate_createMessage (FunctionPtr called_f, CodeBlob& code, SrcLocation loc, const std::vector<std::vector<var_idx_t >>& args ) {
100+ std::vector<var_idx_t > generate_createMessage (FunctionPtr called_f, CodeBlob& code, SrcLocation loc, const std::vector<std::vector<var_idx_t >>& ir_options ) {
91101 TypePtr bodyT = called_f->substitutedTs ->typeT_at (0 );
92102 StructPtr s_Options = lookup_global_symbol (" CreateMessageOptions" )->try_as <StructPtr>();
93103 StructPtr s_AutoDeployAddress = lookup_global_symbol (" AutoDeployAddress" )->try_as <StructPtr>();
@@ -100,7 +110,7 @@ std::vector<var_idx_t> generate_createMessage(FunctionPtr called_f, CodeBlob& co
100110 tolk_assert (t_value && t_value->get_width_on_stack () == (2 +1 ) && t_value->size () == 2 );
101111
102112 int offset = 0 ;
103- std::vector rvect = args [0 ];
113+ std::vector rvect = ir_options [0 ];
104114 auto next_slice = [&rvect, &offset](int width) -> std::vector<var_idx_t > {
105115 int start = offset;
106116 offset += width;
@@ -118,14 +128,11 @@ std::vector<var_idx_t> generate_createMessage(FunctionPtr called_f, CodeBlob& co
118128 // struct ContractState { code: cell; data: cell; }
119129 // struct AddressShardingOptions { fixedPrefixLength: uint5; closeTo: address; }
120130 std::vector ir_dest_is_address = pre_compile_is_type (code, t_dest, TypeDataAddress::create (), ir_dest, loc, " (is-address)" );
121- std::vector ir_dest_is_AutoDeploy = pre_compile_is_type (code, t_dest, TypeDataStruct::create (s_AutoDeployAddress), ir_dest, loc, " (is-address )" );
131+ std::vector ir_dest_is_AutoDeploy = pre_compile_is_type (code, t_dest, TypeDataStruct::create (s_AutoDeployAddress), ir_dest, loc, " (is-auto )" );
122132 std::vector ir_dest_is_builder = pre_compile_is_type (code, t_dest, TypeDataBuilder::create (), ir_dest, loc, " (is-builder)" );
123133 std::vector ir_dest_AutoDeployAddress = transition_to_target_type (std::vector (ir_dest), code, t_dest, TypeDataStruct::create (s_AutoDeployAddress), loc);
124134 IR_AutoDeployAddress ir_dest_ad (code, loc, ir_dest_AutoDeployAddress);
125135
126- // currently, there is no way to pass PackOptions, defaults are used
127- std::vector ir_options = create_default_PackOptions (code, loc);
128-
129136 FunctionPtr f_beginCell = lookup_function (" beginCell" );
130137 FunctionPtr f_endCell = lookup_function (" builder.endCell" );
131138
@@ -146,7 +153,7 @@ std::vector<var_idx_t> generate_createMessage(FunctionPtr called_f, CodeBlob& co
146153 if (body_store_as_ref && !body_already_ref) {
147154 std::vector ir_ref_builder = code.create_var (TypeDataBuilder::create (), loc, " refb" );
148155 code.emplace_back (loc, Op::_Call, ir_ref_builder, std::vector<var_idx_t >{}, f_beginCell);
149- PackContext ref_ctx (code, loc, ir_ref_builder, ir_options );
156+ PackContext ref_ctx (code, loc, ir_ref_builder, create_default_PackOptions (code, loc) );
150157 ref_ctx.generate_pack_any (bodyT, std::move (ir_body));
151158 std::vector ir_ref_cell = code.create_tmp_var (TypeDataCell::create (), loc, " (ref-cell)" );
152159 code.emplace_back (loc, Op::_Call, ir_ref_cell, std::move (ir_ref_builder), f_endCell);
@@ -155,7 +162,7 @@ std::vector<var_idx_t> generate_createMessage(FunctionPtr called_f, CodeBlob& co
155162
156163 std::vector ir_builder = code.create_var (TypeDataSlice::create (), loc, " b" );
157164 code.emplace_back (loc, Op::_Call, ir_builder, std::vector<var_idx_t >{}, f_beginCell);
158- PackContext ctx (code, loc, ir_builder, ir_options );
165+ PackContext ctx (code, loc, ir_builder, create_default_PackOptions (code, loc) );
159166 var_idx_t ir_zero = code.create_int (loc, 0 , " (zero)" );
160167 var_idx_t ir_one = code.create_int (loc, 1 , " (one)" );
161168
@@ -188,11 +195,11 @@ std::vector<var_idx_t> generate_createMessage(FunctionPtr called_f, CodeBlob& co
188195 ctx.storeUint (code.create_int (loc, 0b100 , " (addr-prefix)" ), 3 ); // addr_std$10 + 0 anycast
189196 ctx.storeInt (ir_dest_ad.workchain , 8 );
190197 std::vector ir_hash = code.create_tmp_var (TypeDataInt::create (), loc, " (addr-hash)" );
191- Op& if_ContractState = code.emplace_back (loc, Op::_If, ir_dest_ad.is_ContractState );
198+ Op& if_ContractState = code.emplace_back (loc, Op::_If, ir_dest_ad.is_ContractState (code, loc) );
192199 {
193200 // input is `dest: { ... stateInit: { code, data } }`
194201 code.push_set_cur (if_ContractState.block0 );
195- Op& if_sharded = code.emplace_back (loc, Op::_If, ir_dest_ad.is_AddressSharding );
202+ Op& if_sharded = code.emplace_back (loc, Op::_If, ir_dest_ad.is_AddressSharding (code, loc) );
196203 {
197204 // input is `dest: { ... stateInit: { code, data }, toShard: { fixedPrefixLength, closeTo } };
198205 // then stateInitHash = (hash of StateInit = 0b1(depth)0110 (prefix + code + data))
@@ -218,7 +225,7 @@ std::vector<var_idx_t> generate_createMessage(FunctionPtr called_f, CodeBlob& co
218225 code.emplace_back (loc, Op::_Call, ir_hash, std::move (args), lookup_function (" cell.hash" ));
219226 code.close_pop_cur (loc);
220227 }
221- Op& if_sharded = code.emplace_back (loc, Op::_If, ir_dest_ad.is_AddressSharding );
228+ Op& if_sharded = code.emplace_back (loc, Op::_If, ir_dest_ad.is_AddressSharding (code, loc) );
222229 {
223230 // input is `dest: { ... toShard: { fixedPrefixLength, closeTo } }`
224231 // we already calculated stateInitHash (ir_hash): either cell.hash() or based on prefix+code+data;
@@ -306,12 +313,12 @@ std::vector<var_idx_t> generate_createMessage(FunctionPtr called_f, CodeBlob& co
306313 }
307314 {
308315 code.push_set_cur (if_no_init.block0 );
309- Op& if_ContractState = code.emplace_back (loc, Op::_If, ir_dest_ad.is_ContractState );
316+ Op& if_ContractState = code.emplace_back (loc, Op::_If, ir_dest_ad.is_ContractState (code, loc) );
310317 {
311318 // input is `dest: { ... stateInit: { code, data } }` and need to compose TL/B StateInit;
312319 // it's either just code+data OR (if `toShard: { ... }` is set) fixedPrefixLength+code+data
313320 code.push_set_cur (if_ContractState.block0 );
314- Op& if_sharded = code.emplace_back (loc, Op::_If, ir_dest_ad.is_AddressSharding );
321+ Op& if_sharded = code.emplace_back (loc, Op::_If, ir_dest_ad.is_AddressSharding (code, loc) );
315322 {
316323 // 1 (maybe true) + 0 (either left) + 1 (maybe true of StateInit) + fixedPrefixLength + 0110 + body ref or not
317324 code.push_set_cur (if_sharded.block0 );
@@ -530,20 +537,20 @@ std::vector<var_idx_t> generate_address_buildInAnotherShard(FunctionPtr called_f
530537}
531538
532539// fun AutoDeployAddress.buildAddress(self): builder
533- std::vector<var_idx_t > generate_AutoDeployAddress_buildAddress (FunctionPtr called_f, CodeBlob& code, SrcLocation loc, const std::vector<std::vector<var_idx_t >>& args ) {
534- IR_AutoDeployAddress ir_self (code, loc, args [0 ]);
540+ std::vector<var_idx_t > generate_AutoDeployAddress_buildAddress (FunctionPtr called_f, CodeBlob& code, SrcLocation loc, const std::vector<std::vector<var_idx_t >>& ir_options ) {
541+ IR_AutoDeployAddress ir_self (code, loc, ir_options [0 ]);
535542
536543 std::vector ir_builder = code.create_tmp_var (TypeDataSlice::create (), loc, " (addr-b)" );
537544 // important! unlike `createMessage()`, we calculate hash and shard prefix BEFORE creating a cell
538545 // (for fewer stack manipulations)
539546
540547 // calculate stateInitHash = (hash of StateInit cell would be, but without constructing a cell)
541548 std::vector ir_hash = code.create_tmp_var (TypeDataInt::create (), loc, " (addr-hash)" );
542- Op& if_ContractState = code.emplace_back (loc, Op::_If, ir_self.is_ContractState );
549+ Op& if_ContractState = code.emplace_back (loc, Op::_If, ir_self.is_ContractState (code, loc) );
543550 {
544551 // called `{ ... stateInit: { code, data } }`
545552 code.push_set_cur (if_ContractState.block0 );
546- Op& if_sharded = code.emplace_back (loc, Op::_If, ir_self.is_AddressSharding );
553+ Op& if_sharded = code.emplace_back (loc, Op::_If, ir_self.is_AddressSharding (code, loc) );
547554 {
548555 // called `{ ... stateInit: { code, data }, toShard: { fixedPrefixLength, closeTo } }
549556 code.push_set_cur (if_sharded.block0 );
@@ -569,7 +576,7 @@ std::vector<var_idx_t> generate_AutoDeployAddress_buildAddress(FunctionPtr calle
569576 }
570577
571578 // now, if toShard, perform bitwise calculations with hashes (order on a stack matters)
572- Op& if_sharded = code.emplace_back (loc, Op::_If, ir_self.is_AddressSharding );
579+ Op& if_sharded = code.emplace_back (loc, Op::_If, ir_self.is_AddressSharding (code, loc) );
573580 {
574581 // called `{ ... toShard: { fixedPrefixLength, closeTo } }`
575582 // we already calculated stateInitHash (ir_hash): either cell.hash() or based on prefix+code+data;
@@ -609,16 +616,16 @@ std::vector<var_idx_t> generate_AutoDeployAddress_buildAddress(FunctionPtr calle
609616}
610617
611618// fun AutoDeployAddress.addressMatches(self, addr: address): bool
612- std::vector<var_idx_t > generate_AutoDeployAddress_addressMatches (FunctionPtr called_f, CodeBlob& code, SrcLocation loc, const std::vector<std::vector<var_idx_t >>& args ) {
613- IR_AutoDeployAddress ir_self (code, loc, args [0 ]);
619+ std::vector<var_idx_t > generate_AutoDeployAddress_addressMatches (FunctionPtr called_f, CodeBlob& code, SrcLocation loc, const std::vector<std::vector<var_idx_t >>& ir_self_and_addr ) {
620+ IR_AutoDeployAddress ir_self (code, loc, ir_self_and_addr [0 ]);
614621
615622 // at first, calculate stateInitHash = (hash of StateInit cell would be, but without constructing a cell)
616623 std::vector ir_hash = code.create_tmp_var (TypeDataInt::create (), loc, " (addr-hash)" );
617- Op& if_ContractState = code.emplace_back (loc, Op::_If, ir_self.is_ContractState );
624+ Op& if_ContractState = code.emplace_back (loc, Op::_If, ir_self.is_ContractState (code, loc) );
618625 {
619626 // called `{ ... stateInit: { code, data } }`
620627 code.push_set_cur (if_ContractState.block0 );
621- Op& if_sharded = code.emplace_back (loc, Op::_If, ir_self.is_AddressSharding );
628+ Op& if_sharded = code.emplace_back (loc, Op::_If, ir_self.is_AddressSharding (code, loc) );
622629 {
623630 // called `{ ... stateInit: { code, data }, toShard: { fixedPrefixLength, closeTo } }
624631 code.push_set_cur (if_sharded.block0 );
@@ -644,7 +651,7 @@ std::vector<var_idx_t> generate_AutoDeployAddress_addressMatches(FunctionPtr cal
644651 }
645652
646653 // now calculate `stateInitHash &= mask` where mask = `(1 << (256 - SHARD_DEPTH)) - 1`
647- Op& if_sharded1 = code.emplace_back (loc, Op::_If, ir_self.is_AddressSharding );
654+ Op& if_sharded1 = code.emplace_back (loc, Op::_If, ir_self.is_AddressSharding (code, loc) );
648655 {
649656 code.push_set_cur (if_sharded1.block0 );
650657 append_bitwise_and_shard_mask (code, loc, ir_hash[0 ], ir_self.ir_shardDepth );
@@ -657,10 +664,10 @@ std::vector<var_idx_t> generate_AutoDeployAddress_addressMatches(FunctionPtr cal
657664
658665 // now do `(wc, hash) = addr.getWorkchainAndHash()`
659666 std::vector ir_addr_wc_hash = code.create_tmp_var (TypeDataTensor::create ({TypeDataInt::create (), TypeDataInt::create ()}), loc, " (self-wc-hash)" );
660- code.emplace_back (loc, Op::_Call, ir_addr_wc_hash, args [1 ], lookup_function (" address.getWorkchainAndHash" ));
667+ code.emplace_back (loc, Op::_Call, ir_addr_wc_hash, ir_self_and_addr [1 ], lookup_function (" address.getWorkchainAndHash" ));
661668
662669 // now calculate `hash &= mask` (the same as we did earlier for stateInitHash)
663- Op& if_sharded2 = code.emplace_back (loc, Op::_If, ir_self.is_AddressSharding );
670+ Op& if_sharded2 = code.emplace_back (loc, Op::_If, ir_self.is_AddressSharding (code, loc) );
664671 {
665672 code.push_set_cur (if_sharded2.block0 );
666673 append_bitwise_and_shard_mask (code, loc, ir_addr_wc_hash[1 ], ir_self.ir_shardDepth );
0 commit comments