Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
program_block.cpp
Go to the documentation of this file.
11
13{
14 if (resolved_address.pointer_address.has_value()) {
15 if (resolved_address.via_relative) {
16 // Indirect relative: Write the pointer in a relative manner
18 .operand(static_cast<uint16_t>(resolved_address.operand_address))
19 .relative()
21 .operand(resolved_address.absolute_address)
22 .build();
23 instructions.push_back(set_pointer_instruction);
24 } else {
25 // Indirect: Write the pointer directly
27 .operand(static_cast<uint16_t>(resolved_address.pointer_address.value()))
29 .operand(resolved_address.absolute_address)
30 .build();
31 instructions.push_back(set_pointer_instruction);
32 }
33
35 }
36}
37
40{
41 for (const auto& param : params) {
42 auto tag =
43 std::visit(overloaded{ [](const VariableRef& var) -> std::optional<MemoryTag> { return var.tag.value; },
44 [](const AddressRef&) -> std::optional<MemoryTag> { return std::nullopt; } },
45 param);
46 if (tag.has_value()) {
47 memory_manager.set_memory_address(tag.value(), result_address.absolute_address);
48 return;
49 }
50 }
51}
52
54{
55#ifdef DISABLE_ADD_8_INSTRUCTION
56 return;
57#endif
61 if (!a.has_value() || !b.has_value() || !result.has_value()) {
62 return;
63 }
64 preprocess_memory_addresses(a.value().first);
65 preprocess_memory_addresses(b.value().first);
66 preprocess_memory_addresses(result.value().first);
67
69 .operand(a.value().second)
70 .operand(b.value().second)
71 .operand(result.value().second)
72 .build();
73 instructions.push_back(add_8_instruction);
74 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
75}
76
78{
79#ifdef DISABLE_SUB_8_INSTRUCTION
80 return;
81#endif
85 if (!a.has_value() || !b.has_value() || !result.has_value()) {
86 return;
87 }
88 preprocess_memory_addresses(a.value().first);
89 preprocess_memory_addresses(b.value().first);
90 preprocess_memory_addresses(result.value().first);
92 .operand(a.value().second)
93 .operand(b.value().second)
94 .operand(result.value().second)
95 .build();
96 instructions.push_back(sub_8_instruction);
97 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
98}
99
101{
102#ifdef DISABLE_MUL_8_INSTRUCTION
103 return;
104#endif
108 if (!a.has_value() || !b.has_value() || !result.has_value()) {
109 return;
110 }
111 preprocess_memory_addresses(a.value().first);
112 preprocess_memory_addresses(b.value().first);
113 preprocess_memory_addresses(result.value().first);
115 .operand(a.value().second)
116 .operand(b.value().second)
117 .operand(result.value().second)
118 .build();
119 instructions.push_back(mul_8_instruction);
120 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
121}
122
124{
125#ifdef DISABLE_DIV_8_INSTRUCTION
126 return;
127#endif
131 if (!a.has_value() || !b.has_value() || !result.has_value()) {
132 return;
133 }
134 preprocess_memory_addresses(a.value().first);
135 preprocess_memory_addresses(b.value().first);
136 preprocess_memory_addresses(result.value().first);
138 .operand(a.value().second)
139 .operand(b.value().second)
140 .operand(result.value().second)
141 .build();
142 instructions.push_back(div_8_instruction);
143 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
144}
145
147{
148#ifdef DISABLE_EQ_8_INSTRUCTION
149 return;
150#endif
154 if (!a.has_value() || !b.has_value() || !result.has_value()) {
155 return;
156 }
157 preprocess_memory_addresses(a.value().first);
158 preprocess_memory_addresses(b.value().first);
159 preprocess_memory_addresses(result.value().first);
161 .operand(a.value().second)
162 .operand(b.value().second)
163 .operand(result.value().second)
164 .build();
165 instructions.push_back(eq_8_instruction);
166 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address);
167}
168
170{
171#ifdef DISABLE_LT_8_INSTRUCTION
172 return;
173#endif
177 if (!a.has_value() || !b.has_value() || !result.has_value()) {
178 return;
179 }
180 preprocess_memory_addresses(a.value().first);
181 preprocess_memory_addresses(b.value().first);
182 preprocess_memory_addresses(result.value().first);
184 .operand(a.value().second)
185 .operand(b.value().second)
186 .operand(result.value().second)
187 .build();
188 instructions.push_back(lt_8_instruction);
189 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address);
190}
191
193{
194#ifdef DISABLE_LTE_8_INSTRUCTION
195 return;
196#endif
200 if (!a.has_value() || !b.has_value() || !result.has_value()) {
201 return;
202 }
203 preprocess_memory_addresses(a.value().first);
204 preprocess_memory_addresses(b.value().first);
205 preprocess_memory_addresses(result.value().first);
207 .operand(a.value().second)
208 .operand(b.value().second)
209 .operand(result.value().second)
210 .build();
211 instructions.push_back(lte_8_instruction);
212 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address);
213}
214
216{
217#ifdef DISABLE_AND_8_INSTRUCTION
218 return;
219#endif
223 if (!a.has_value() || !b.has_value() || !result.has_value()) {
224 return;
225 }
226
227 preprocess_memory_addresses(a.value().first);
228 preprocess_memory_addresses(b.value().first);
229 preprocess_memory_addresses(result.value().first);
231 .operand(a.value().second)
232 .operand(b.value().second)
233 .operand(result.value().second)
234 .build();
235 instructions.push_back(and_8_instruction);
236 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
237}
238
240{
241#ifdef DISABLE_OR_8_INSTRUCTION
242 return;
243#endif
247 if (!a.has_value() || !b.has_value() || !result.has_value()) {
248 return;
249 }
250
251 preprocess_memory_addresses(a.value().first);
252 preprocess_memory_addresses(b.value().first);
253 preprocess_memory_addresses(result.value().first);
255 .operand(a.value().second)
256 .operand(b.value().second)
257 .operand(result.value().second)
258 .build();
259 instructions.push_back(or_8_instruction);
260 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
261}
262
264{
265#ifdef DISABLE_XOR_8_INSTRUCTION
266 return;
267#endif
271 if (!a.has_value() || !b.has_value() || !result.has_value()) {
272 return;
273 }
274
275 preprocess_memory_addresses(a.value().first);
276 preprocess_memory_addresses(b.value().first);
277 preprocess_memory_addresses(result.value().first);
279 .operand(a.value().second)
280 .operand(b.value().second)
281 .operand(result.value().second)
282 .build();
283 instructions.push_back(xor_8_instruction);
284 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
285}
286
288{
289#ifdef DISABLE_SHL_8_INSTRUCTION
290 return;
291#endif
295 if (!a.has_value() || !b.has_value() || !result.has_value()) {
296 return;
297 }
298
299 preprocess_memory_addresses(a.value().first);
300 preprocess_memory_addresses(b.value().first);
301 preprocess_memory_addresses(result.value().first);
303 .operand(a.value().second)
304 .operand(b.value().second)
305 .operand(result.value().second)
306 .build();
307 instructions.push_back(shl_8_instruction);
308 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
309}
310
312{
313#ifdef DISABLE_SHR_8_INSTRUCTION
314 return;
315#endif
319 if (!a.has_value() || !b.has_value() || !result.has_value()) {
320 return;
321 }
322
323 preprocess_memory_addresses(a.value().first);
324 preprocess_memory_addresses(b.value().first);
325 preprocess_memory_addresses(result.value().first);
327 .operand(a.value().second)
328 .operand(b.value().second)
329 .operand(result.value().second)
330 .build();
331 instructions.push_back(shr_8_instruction);
332 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
333}
334
336{
337#ifdef DISABLE_SET_8_INSTRUCTION
338 return;
339#endif
340 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
341 if (!effective_address_operand.has_value()) {
342 return;
343 }
344 preprocess_memory_addresses(effective_address_operand.value().first);
346 .operand(effective_address_operand.value().second)
347 .operand(instruction.value_tag.value)
348 .operand(instruction.value)
349 .build());
351 effective_address_operand.value().first.absolute_address);
352}
353
355{
356#ifdef DISABLE_SET_16_INSTRUCTION
357 return;
358#endif
359 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
360 if (!effective_address_operand.has_value()) {
361 return;
362 }
363 preprocess_memory_addresses(effective_address_operand.value().first);
365 .operand(effective_address_operand.value().second)
366 .operand(instruction.value_tag.value)
367 .operand(instruction.value)
368 .build());
370 effective_address_operand.value().first.absolute_address);
371}
372
374{
375#ifdef DISABLE_SET_32_INSTRUCTION
376 return;
377#endif
378 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
379 if (!effective_address_operand.has_value()) {
380 return;
381 }
382 preprocess_memory_addresses(effective_address_operand.value().first);
384 .operand(effective_address_operand.value().second)
385 .operand(instruction.value_tag.value)
386 .operand(instruction.value)
387 .build());
389 effective_address_operand.value().first.absolute_address);
390}
391
393{
394#ifdef DISABLE_SET_64_INSTRUCTION
395 return;
396#endif
397 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
398 if (!effective_address_operand.has_value()) {
399 return;
400 }
401 preprocess_memory_addresses(effective_address_operand.value().first);
403 .operand(effective_address_operand.value().second)
404 .operand(instruction.value_tag.value)
405 .operand(instruction.value)
406 .build());
408 effective_address_operand.value().first.absolute_address);
409}
410
412{
413#ifdef DISABLE_SET_128_INSTRUCTION
414 return;
415#endif
416 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
417 if (!effective_address_operand.has_value()) {
418 return;
419 }
421 (static_cast<uint128_t>(instruction.value_high) << 64) | static_cast<uint128_t>(instruction.value_low);
422 preprocess_memory_addresses(effective_address_operand.value().first);
424 .operand(effective_address_operand.value().second)
425 .operand(instruction.value_tag.value)
426 .operand(value)
427 .build());
429 effective_address_operand.value().first.absolute_address);
430}
431
433{
434#ifdef DISABLE_SET_FF_INSTRUCTION
435 return;
436#endif
437 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
438 if (!effective_address_operand.has_value()) {
439 return;
440 }
441 preprocess_memory_addresses(effective_address_operand.value().first);
443 .operand(effective_address_operand.value().second)
444 .operand(instruction.value_tag.value)
445 .operand(instruction.value)
446 .build());
448 effective_address_operand.value().first.absolute_address);
449}
450
452{
453#ifdef DISABLE_MOV_8_INSTRUCTION
454 return;
455#endif
456 auto src_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.src_address);
457 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
458 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
459 return;
460 }
461 preprocess_memory_addresses(src_address_operand.value().first);
462 preprocess_memory_addresses(result_address_operand.value().first);
464 .operand(src_address_operand.value().second)
465 .operand(result_address_operand.value().second)
466 .build();
467 instructions.push_back(mov_8_instruction);
468 record_result_tag_from_param_tags({ instruction.src_address }, result_address_operand.value().first);
469}
470
472{
473#ifdef DISABLE_MOV_16_INSTRUCTION
474 return;
475#endif
476 auto src_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.src_address);
477 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
478 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
479 return;
480 }
481
482 preprocess_memory_addresses(src_address_operand.value().first);
483 preprocess_memory_addresses(result_address_operand.value().first);
485 .operand(src_address_operand.value().second)
486 .operand(result_address_operand.value().second)
487 .build();
488 instructions.push_back(mov_16_instruction);
489 record_result_tag_from_param_tags({ instruction.src_address }, result_address_operand.value().first);
490}
491
493{
494#ifdef DISABLE_FDIV_8_INSTRUCTION
495 return;
496#endif
497 auto a_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.a_address);
498 auto b_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.b_address);
499 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
500 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
501 return;
502 }
503
504 preprocess_memory_addresses(a_address_operand.value().first);
505 preprocess_memory_addresses(b_address_operand.value().first);
506 preprocess_memory_addresses(result_address_operand.value().first);
508 .operand(a_address_operand.value().second)
509 .operand(b_address_operand.value().second)
510 .operand(result_address_operand.value().second)
511 .build();
512 instructions.push_back(fdiv_8_instruction);
514 result_address_operand.value().first);
515}
516
518{
519#ifdef DISABLE_NOT_8_INSTRUCTION
520 return;
521#endif
522 auto a_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.a_address);
523 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
524 if (!a_address_operand.has_value() || !result_address_operand.has_value()) {
525 return;
526 }
527
528 preprocess_memory_addresses(a_address_operand.value().first);
529 preprocess_memory_addresses(result_address_operand.value().first);
531 .operand(a_address_operand.value().second)
532 .operand(result_address_operand.value().second)
533 .build();
534 instructions.push_back(not_8_instruction);
535 record_result_tag_from_param_tags({ instruction.a_address }, result_address_operand.value().first);
536}
537
539{
540#ifdef DISABLE_ADD_16_INSTRUCTION
541 return;
542#endif
543 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
544 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
545 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
546 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
547 return;
548 }
549
550 preprocess_memory_addresses(a_address_operand.value().first);
551 preprocess_memory_addresses(b_address_operand.value().first);
552 preprocess_memory_addresses(result_address_operand.value().first);
554 .operand(a_address_operand.value().second)
555 .operand(b_address_operand.value().second)
556 .operand(result_address_operand.value().second)
557 .build();
558 instructions.push_back(add_16_instruction);
560 result_address_operand.value().first);
561}
562
564{
565#ifdef DISABLE_SUB_16_INSTRUCTION
566 return;
567#endif
568 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
569 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
570 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
571 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
572 return;
573 }
574
575 preprocess_memory_addresses(a_address_operand.value().first);
576 preprocess_memory_addresses(b_address_operand.value().first);
577 preprocess_memory_addresses(result_address_operand.value().first);
579 .operand(a_address_operand.value().second)
580 .operand(b_address_operand.value().second)
581 .operand(result_address_operand.value().second)
582 .build();
583 instructions.push_back(sub_16_instruction);
585 result_address_operand.value().first);
586}
587
589{
590#ifdef DISABLE_MUL_16_INSTRUCTION
591 return;
592#endif
593 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
594 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
595 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
596 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
597 return;
598 }
599
600 preprocess_memory_addresses(a_address_operand.value().first);
601 preprocess_memory_addresses(b_address_operand.value().first);
602 preprocess_memory_addresses(result_address_operand.value().first);
604 .operand(a_address_operand.value().second)
605 .operand(b_address_operand.value().second)
606 .operand(result_address_operand.value().second)
607 .build();
608 instructions.push_back(mul_16_instruction);
610 result_address_operand.value().first);
611}
612
614{
615#ifdef DISABLE_DIV_16_INSTRUCTION
616 return;
617#endif
618 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
619 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
620 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
621 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
622 return;
623 }
624
625 preprocess_memory_addresses(a_address_operand.value().first);
626 preprocess_memory_addresses(b_address_operand.value().first);
627 preprocess_memory_addresses(result_address_operand.value().first);
629 .operand(a_address_operand.value().second)
630 .operand(b_address_operand.value().second)
631 .operand(result_address_operand.value().second)
632 .build();
633 instructions.push_back(div_16_instruction);
635 result_address_operand.value().first);
636}
637
639{
640#ifdef DISABLE_FDIV_16_INSTRUCTION
641 return;
642#endif
643 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
644 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
645 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
646 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
647 return;
648 }
649
650 preprocess_memory_addresses(a_address_operand.value().first);
651 preprocess_memory_addresses(b_address_operand.value().first);
652 preprocess_memory_addresses(result_address_operand.value().first);
654 .operand(a_address_operand.value().second)
655 .operand(b_address_operand.value().second)
656 .operand(result_address_operand.value().second)
657 .build();
658 instructions.push_back(fdiv_16_instruction);
660 result_address_operand.value().first);
661}
662
664{
665#ifdef DISABLE_EQ_16_INSTRUCTION
666 return;
667#endif
668 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
669 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
670 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
671 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
672 return;
673 }
674
675 preprocess_memory_addresses(a_address_operand.value().first);
676 preprocess_memory_addresses(b_address_operand.value().first);
677 preprocess_memory_addresses(result_address_operand.value().first);
679 .operand(a_address_operand.value().second)
680 .operand(b_address_operand.value().second)
681 .operand(result_address_operand.value().second)
682 .build();
683 instructions.push_back(eq_16_instruction);
684 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
685}
686
688{
689#ifdef DISABLE_LT_16_INSTRUCTION
690 return;
691#endif
692 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
693 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
694 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
695 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
696 return;
697 }
698
699 preprocess_memory_addresses(a_address_operand.value().first);
700 preprocess_memory_addresses(b_address_operand.value().first);
701 preprocess_memory_addresses(result_address_operand.value().first);
703 .operand(a_address_operand.value().second)
704 .operand(b_address_operand.value().second)
705 .operand(result_address_operand.value().second)
706 .build();
707 instructions.push_back(lt_16_instruction);
708 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
709}
710
712{
713#ifdef DISABLE_LTE_16_INSTRUCTION
714 return;
715#endif
716 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
717 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
718 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
719 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
720 return;
721 }
722
723 preprocess_memory_addresses(a_address_operand.value().first);
724 preprocess_memory_addresses(b_address_operand.value().first);
725 preprocess_memory_addresses(result_address_operand.value().first);
727 .operand(a_address_operand.value().second)
728 .operand(b_address_operand.value().second)
729 .operand(result_address_operand.value().second)
730 .build();
731 instructions.push_back(lte_16_instruction);
732 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
733}
734
736{
737#ifdef DISABLE_AND_16_INSTRUCTION
738 return;
739#endif
740 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
741 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
742 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
743 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
744 return;
745 }
746
747 preprocess_memory_addresses(a_address_operand.value().first);
748 preprocess_memory_addresses(b_address_operand.value().first);
749 preprocess_memory_addresses(result_address_operand.value().first);
751 .operand(a_address_operand.value().second)
752 .operand(b_address_operand.value().second)
753 .operand(result_address_operand.value().second)
754 .build();
755 instructions.push_back(and_16_instruction);
757 result_address_operand.value().first);
758}
759
761{
762#ifdef DISABLE_OR_16_INSTRUCTION
763 return;
764#endif
765 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
766 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
767 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
768 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
769 return;
770 }
771
772 preprocess_memory_addresses(a_address_operand.value().first);
773 preprocess_memory_addresses(b_address_operand.value().first);
774 preprocess_memory_addresses(result_address_operand.value().first);
776 .operand(a_address_operand.value().second)
777 .operand(b_address_operand.value().second)
778 .operand(result_address_operand.value().second)
779 .build();
780 instructions.push_back(or_16_instruction);
782 result_address_operand.value().first);
783}
784
786{
787#ifdef DISABLE_XOR_16_INSTRUCTION
788 return;
789#endif
790 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
791 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
792 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
793 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
794 return;
795 }
796
797 preprocess_memory_addresses(a_address_operand.value().first);
798 preprocess_memory_addresses(b_address_operand.value().first);
799 preprocess_memory_addresses(result_address_operand.value().first);
801 .operand(a_address_operand.value().second)
802 .operand(b_address_operand.value().second)
803 .operand(result_address_operand.value().second)
804 .build();
805 instructions.push_back(xor_16_instruction);
807 result_address_operand.value().first);
808}
809
811{
812#ifdef DISABLE_NOT_16_INSTRUCTION
813 return;
814#endif
815 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
816 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
817 if (!a_address_operand.has_value() || !result_address_operand.has_value()) {
818 return;
819 }
820
821 preprocess_memory_addresses(a_address_operand.value().first);
822 preprocess_memory_addresses(result_address_operand.value().first);
824 .operand(a_address_operand.value().second)
825 .operand(result_address_operand.value().second)
826 .build();
827 instructions.push_back(not_16_instruction);
828 record_result_tag_from_param_tags({ instruction.a_address }, result_address_operand.value().first);
829}
830
832{
833#ifdef DISABLE_SHL_16_INSTRUCTION
834 return;
835#endif
836 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
837 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
838 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
839 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
840 return;
841 }
842 preprocess_memory_addresses(a_address_operand.value().first);
843 preprocess_memory_addresses(b_address_operand.value().first);
844 preprocess_memory_addresses(result_address_operand.value().first);
845
847 .operand(a_address_operand.value().second)
848 .operand(b_address_operand.value().second)
849 .operand(result_address_operand.value().second)
850 .build();
851 instructions.push_back(shl_16_instruction);
853 result_address_operand.value().first);
854}
855
857{
858#ifdef DISABLE_SHR_16_INSTRUCTION
859 return;
860#endif
861 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
862 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
863 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
864 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
865 return;
866 }
867
868 preprocess_memory_addresses(a_address_operand.value().first);
869 preprocess_memory_addresses(b_address_operand.value().first);
870 preprocess_memory_addresses(result_address_operand.value().first);
872 .operand(a_address_operand.value().second)
873 .operand(b_address_operand.value().second)
874 .operand(result_address_operand.value().second)
875 .build();
876 instructions.push_back(shr_16_instruction);
878 result_address_operand.value().first);
879}
880
882{
883#ifdef DISABLE_CAST_8_INSTRUCTION
884 return;
885#endif
886 auto src_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.src_address);
887 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
888 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
889 return;
890 }
891
892 preprocess_memory_addresses(src_address_operand.value().first);
893 preprocess_memory_addresses(result_address_operand.value().first);
895 .operand(src_address_operand.value().second)
896 .operand(result_address_operand.value().second)
897 .operand(instruction.target_tag.value)
898 .build();
899 instructions.push_back(cast_8_instruction);
901 result_address_operand.value().first.absolute_address);
902}
903
905{
906#ifdef DISABLE_CAST_16_INSTRUCTION
907 return;
908#endif
909 auto src_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.src_address);
910 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
911 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
912 return;
913 }
914
915 preprocess_memory_addresses(src_address_operand.value().first);
916 preprocess_memory_addresses(result_address_operand.value().first);
918 .operand(src_address_operand.value().second)
919 .operand(result_address_operand.value().second)
920 .operand(instruction.target_tag.value)
921 .build();
922 instructions.push_back(cast_16_instruction);
924 result_address_operand.value().first.absolute_address);
925}
926
928{
929#ifdef DISABLE_SSTORE_INSTRUCTION
930 return;
931#endif
932 auto src_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.src_address);
933 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
934 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
935 return;
936 }
937 preprocess_memory_addresses(src_address_operand.value().first);
938 preprocess_memory_addresses(result_address_operand.value().first);
939 auto set_slot_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
940 .result_address = instruction.result_address,
941 .value = instruction.slot };
942 this->process_set_ff_instruction(set_slot_instruction);
944 .operand(src_address_operand.value().second)
945 .operand(result_address_operand.value().second)
946 .build();
947 instructions.push_back(sstore_instruction);
949}
950
952{
953#ifdef DISABLE_SLOAD_INSTRUCTION
954 return;
955#endif
956 auto slot_addr = memory_manager.get_slot(instruction.slot_index);
957 if (!slot_addr.has_value()) {
958 return;
959 }
960
961 auto set_slot_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
962 .result_address = instruction.slot_address,
963 .value = *slot_addr };
964 this->process_set_ff_instruction(set_slot_instruction);
965 auto slot_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.slot_address);
966 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
967 if (!slot_address_operand.has_value() || !result_address_operand.has_value()) {
968 return;
969 }
970 preprocess_memory_addresses(slot_address_operand.value().first);
971 preprocess_memory_addresses(result_address_operand.value().first);
972
974 .operand(slot_address_operand.value().second)
975 .operand(result_address_operand.value().second)
976 .build();
977 instructions.push_back(sload_instruction);
978 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, result_address_operand.value().first.absolute_address);
979}
980
982{
983#ifdef DISABLE_GETENVVAR_INSTRUCTION
984 return;
985#endif
986 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
987 if (!result_address_operand.has_value()) {
988 return;
989 }
990 preprocess_memory_addresses(result_address_operand.value().first);
992 .operand(result_address_operand.value().second)
993 .operand(instruction.type)
994 .build();
995 instructions.push_back(getenvvar_instruction);
996 // special case for timestamp, it returns a 64-bit value
997 if (instruction.type == 6) {
999 result_address_operand.value().first.absolute_address);
1000 } else {
1002 result_address_operand.value().first.absolute_address);
1003 }
1004}
1005
1007{
1008#ifdef DISABLE_EMITNULLIFIER_INSTRUCTION
1009 return;
1010#endif
1011 auto nullifier_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.nullifier_address);
1012 if (!nullifier_address_operand.has_value()) {
1013 return;
1014 }
1015 preprocess_memory_addresses(nullifier_address_operand.value().first);
1017 .operand(nullifier_address_operand.value().second)
1018 .build();
1019 instructions.push_back(emitnulifier_instruction);
1020}
1021
1023{
1024#ifdef DISABLE_NULLIFIEREXISTS_INSTRUCTION
1025 return;
1026#endif
1027 auto nullifier_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.nullifier_address);
1028 auto contract_address_operand =
1030 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
1031 if (!nullifier_address_operand.has_value() || !contract_address_operand.has_value() ||
1032 !result_address_operand.has_value()) {
1033 return;
1034 }
1035
1036 preprocess_memory_addresses(nullifier_address_operand.value().first);
1037 preprocess_memory_addresses(contract_address_operand.value().first);
1038 preprocess_memory_addresses(result_address_operand.value().first);
1039 auto get_contract_address_instruction =
1040 GETENVVAR_Instruction{ .result_address = instruction.contract_address_address, .type = 0 };
1041 this->process_getenvvar_instruction(get_contract_address_instruction);
1042
1044 .operand(nullifier_address_operand.value().second)
1045 .operand(contract_address_operand.value().second)
1046 .operand(result_address_operand.value().second)
1047 .build();
1048 instructions.push_back(nullifierexists_instruction);
1049 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
1050}
1051
1053{
1054#ifdef DISABLE_EMITNOTEHASH_INSTRUCTION
1055 return;
1056#endif
1057 auto set_note_hash_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1058 .result_address = instruction.note_hash_address,
1059 .value = instruction.note_hash };
1060 this->process_set_ff_instruction(set_note_hash_instruction);
1061
1062 // EMITNOTEHASH expects UINT16 operand
1063 auto note_hash_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.note_hash_address);
1064 if (!note_hash_address_operand.has_value()) {
1065 return;
1066 }
1067 preprocess_memory_addresses(note_hash_address_operand.value().first);
1068
1070 .operand(note_hash_address_operand.value().second)
1071 .build();
1072 instructions.push_back(emitnotehash_instruction);
1073}
1074
1076{
1077#ifdef DISABLE_NOTEHASHEXISTS_INSTRUCTION
1078 return;
1079#endif
1080 auto notehash_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.notehash_address);
1081 auto leaf_index_address_operand =
1083 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
1084 if (!notehash_address_operand.has_value() || !leaf_index_address_operand.has_value() ||
1085 !result_address_operand.has_value()) {
1086 return;
1087 }
1088 preprocess_memory_addresses(notehash_address_operand.value().first);
1089 preprocess_memory_addresses(leaf_index_address_operand.value().first);
1090 preprocess_memory_addresses(result_address_operand.value().first);
1091
1093 .operand(notehash_address_operand.value().second)
1094 .operand(leaf_index_address_operand.value().second)
1095 .operand(result_address_operand.value().second)
1096 .build();
1097 instructions.push_back(notehashexists_instruction);
1098 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
1099}
1100
1102{
1103#ifdef DISABLE_CALLDATACOPY_INSTRUCTION
1104 return;
1105#endif
1106 auto copy_size_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.copy_size_address);
1107 auto cd_offset_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.cd_offset_address);
1108 auto dst_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1109 if (!copy_size_address_operand.has_value() || !cd_offset_address_operand.has_value() ||
1110 !dst_address_operand.has_value()) {
1111 return;
1112 }
1113
1114 preprocess_memory_addresses(copy_size_address_operand.value().first);
1115 preprocess_memory_addresses(cd_offset_address_operand.value().first);
1116 preprocess_memory_addresses(dst_address_operand.value().first);
1118 .operand(copy_size_address_operand.value().second)
1119 .operand(cd_offset_address_operand.value().second)
1120 .operand(dst_address_operand.value().second)
1121 .build();
1122 instructions.push_back(calldatacopy_instruction);
1123}
1124
1126{
1127#ifdef DISABLE_SENDL2TOL1MSG_INSTRUCTION
1128 return;
1129#endif
1130 auto set_recipient_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1131 .result_address = instruction.recipient_address,
1132 .value = instruction.recipient };
1133 this->process_set_ff_instruction(set_recipient_instruction);
1134 auto set_content_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1135 .result_address = instruction.content_address,
1136 .value = instruction.content };
1137 this->process_set_ff_instruction(set_content_instruction);
1138
1139 auto recipient_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.recipient_address);
1140 auto content_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.content_address);
1141 if (!recipient_address_operand.has_value() || !content_address_operand.has_value()) {
1142 return;
1143 }
1144 preprocess_memory_addresses(recipient_address_operand.value().first);
1145 preprocess_memory_addresses(content_address_operand.value().first);
1147 .operand(recipient_address_operand.value().second)
1148 .operand(content_address_operand.value().second)
1149 .build();
1150 instructions.push_back(sendl2tol1msg_instruction);
1151}
1152
1154{
1155#ifdef DISABLE_EMITUNENCRYPTEDLOG_INSTRUCTION
1156 return;
1157#endif
1158 auto log_size_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.log_size_address);
1159 auto log_values_address_operand =
1161 if (!log_size_address_operand.has_value() || !log_values_address_operand.has_value()) {
1162 return;
1163 }
1164 preprocess_memory_addresses(log_size_address_operand.value().first);
1165 preprocess_memory_addresses(log_values_address_operand.value().first);
1166 auto emitunencryptedlog_instruction =
1168 .operand(log_size_address_operand.value().second)
1169 .operand(log_values_address_operand.value().second)
1170 .build();
1171 instructions.push_back(emitunencryptedlog_instruction);
1172}
1173
1175{
1176#ifdef DISABLE_CALL_INSTRUCTION
1177 return;
1178#endif
1185 if (!l2_gas.has_value() || !da_gas.has_value() || !contract_address_address.has_value() ||
1186 !calldata_size_address.has_value() || !calldata_address.has_value()) {
1187 return;
1188 }
1189 preprocess_memory_addresses(l2_gas.value().first);
1190 preprocess_memory_addresses(da_gas.value().first);
1194
1196 .result_address = instruction.calldata_size_address,
1197 .value = static_cast<uint32_t>(instruction.calldata_size) });
1198
1199 auto call_instruction_builder = instruction.is_static_call
1202 auto call_instruction = call_instruction_builder.operand(l2_gas.value().second)
1203 .operand(da_gas.value().second)
1204 .operand(contract_address_address.value().second)
1205 .operand(calldata_size_address.value().second)
1206 .operand(calldata_address.value().second)
1207 .build();
1208 instructions.push_back(call_instruction);
1209}
1210
1212{
1213#ifdef DISABLE_RETURNDATASIZE_INSTRUCTION
1214 return;
1215#endif
1216 auto dst_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1217 if (!dst_address_operand.has_value()) {
1218 return;
1219 }
1220 preprocess_memory_addresses(dst_address_operand.value().first);
1222 .operand(dst_address_operand.value().second)
1223 .build();
1224 instructions.push_back(returndatasize_instruction);
1225 memory_manager.set_memory_address(bb::avm2::MemoryTag::U32, dst_address_operand.value().first.absolute_address);
1226}
1227
1229{
1230#ifdef DISABLE_RETURNDATACOPY_INSTRUCTION
1231 return;
1232#endif
1233 auto copy_size_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.copy_size_address);
1234 auto rd_offset_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.rd_offset_address);
1235 auto dst_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1236 if (!copy_size_address_operand.has_value() || !rd_offset_address_operand.has_value() ||
1237 !dst_address_operand.has_value()) {
1238 return;
1239 }
1240 preprocess_memory_addresses(copy_size_address_operand.value().first);
1241 preprocess_memory_addresses(rd_offset_address_operand.value().first);
1242 preprocess_memory_addresses(dst_address_operand.value().first);
1243
1245 .operand(copy_size_address_operand.value().second)
1246 .operand(rd_offset_address_operand.value().second)
1247 .operand(dst_address_operand.value().second)
1248 .build();
1249 instructions.push_back(returndatacopy_instruction);
1250}
1251
1253{
1254#ifdef DISABLE_GETCONTRACTINSTANCE_INSTRUCTION
1255 return;
1256#endif
1259
1261 if (!contract_address_address.has_value() || !dst_address.has_value()) {
1262 return;
1263 }
1266
1267 auto get_contract_instance_instruction =
1269 .operand(contract_address_address.value().second)
1270 .operand(dst_address.value().second)
1271 .operand(instruction.member_enum)
1272 .build();
1273 instructions.push_back(get_contract_instance_instruction);
1275 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, dst_address.value().first.absolute_address + 1);
1276}
1277
1279{
1280#ifdef DISABLE_SUCCESSCOPY_INSTRUCTION
1281 return;
1282#endif
1283 auto dst_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1284 if (!dst_address_operand.has_value()) {
1285 return;
1286 }
1287 preprocess_memory_addresses(dst_address_operand.value().first);
1289 .operand(dst_address_operand.value().second)
1290 .build();
1291 instructions.push_back(successcopy_instruction);
1292 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, dst_address_operand.value().first.absolute_address);
1293}
1294
1296{
1297#ifdef DISABLE_ECADD_INSTRUCTION
1298 return;
1299#endif
1307
1308 if (!p1_x.has_value() || !p1_y.has_value() || !p1_inf.has_value() || !p2_x.has_value() || !p2_y.has_value() ||
1309 !p2_inf.has_value() || !result.has_value()) {
1310 return;
1311 }
1312
1313 preprocess_memory_addresses(p1_x.value().first);
1314 preprocess_memory_addresses(p1_y.value().first);
1315 preprocess_memory_addresses(p1_inf.value().first);
1316 preprocess_memory_addresses(p2_x.value().first);
1317 preprocess_memory_addresses(p2_y.value().first);
1318 preprocess_memory_addresses(p2_inf.value().first);
1319 preprocess_memory_addresses(result.value().first);
1320
1322 .operand(p1_x.value().second)
1323 .operand(p1_y.value().second)
1324 .operand(p1_inf.value().second)
1325 .operand(p2_x.value().second)
1326 .operand(p2_y.value().second)
1327 .operand(p2_inf.value().second)
1328 .operand(result.value().second)
1329 .build();
1330 instructions.push_back(ecadd_instruction);
1331
1332 // ECADD writes 3 consecutive memory locations: result_x (FF), result_y (FF), result_is_inf (U1)
1333 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, result.value().first.absolute_address);
1334 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, result.value().first.absolute_address + 1);
1335 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address + 2);
1336}
1337
1339{
1340#ifdef DISABLE_POSEIDON2PERM_INSTRUCTION
1341 return;
1342#endif
1345
1346 if (!src.has_value() || !dst.has_value()) {
1347 return;
1348 }
1349
1350 preprocess_memory_addresses(src.value().first);
1351 preprocess_memory_addresses(dst.value().first);
1352
1354 .operand(src.value().second)
1355 .operand(dst.value().second)
1356 .build();
1357 instructions.push_back(poseidon2perm_instruction);
1358
1359 // Poseidon2 permutation writes 4 consecutive FF values to dst
1360 for (uint32_t i = 0; i < 4; i++) {
1361 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, dst.value().first.absolute_address + i);
1362 }
1363}
1364
1366{
1367#ifdef DISABLE_KECCAKF1600_INSTRUCTION
1368 return;
1369#endif
1372
1373 if (!src.has_value() || !dst.has_value()) {
1374 return;
1375 }
1376
1377 preprocess_memory_addresses(src.value().first);
1378 preprocess_memory_addresses(dst.value().first);
1379
1381 .operand(dst.value().second)
1382 .operand(src.value().second)
1383 .build();
1384 instructions.push_back(keccakf1600_instruction);
1385
1386 // Keccak-f[1600] permutation writes 25 consecutive U64 values to dst
1387 for (uint32_t i = 0; i < 25; i++) {
1388 memory_manager.set_memory_address(bb::avm2::MemoryTag::U64, dst.value().first.absolute_address + i);
1389 }
1390}
1391
1393{
1394#ifdef DISABLE_SHA256COMPRESSION_INSTRUCTION
1395 return;
1396#endif
1400
1401 if (!state.has_value() || !input.has_value() || !dst.has_value()) {
1402 return;
1403 }
1404
1405 preprocess_memory_addresses(state.value().first);
1406 preprocess_memory_addresses(input.value().first);
1407 preprocess_memory_addresses(dst.value().first);
1408
1410 .operand(dst.value().second)
1411 .operand(state.value().second)
1412 .operand(input.value().second)
1413 .build();
1414 instructions.push_back(sha256compression_instruction);
1415
1416 // SHA256 compression writes 8 consecutive U32 values to dst
1417 for (uint32_t i = 0; i < 8; i++) {
1418 memory_manager.set_memory_address(bb::avm2::MemoryTag::U32, dst.value().first.absolute_address + i);
1419 }
1420}
1421
1423{
1424 auto msg_hash_operand = memory_manager.get_resolved_address_and_operand_16(instruction.msg_hash_address);
1425 auto leaf_index_operand = memory_manager.get_resolved_address_and_operand_16(instruction.leaf_index_address);
1426 auto result_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
1427
1428 if (!msg_hash_operand.has_value() || !leaf_index_operand.has_value() || !result_operand.has_value()) {
1429 return;
1430 }
1431
1432 preprocess_memory_addresses(msg_hash_operand.value().first);
1433 preprocess_memory_addresses(leaf_index_operand.value().first);
1434 preprocess_memory_addresses(result_operand.value().first);
1435
1437 .operand(msg_hash_operand.value().second)
1438 .operand(leaf_index_operand.value().second)
1439 .operand(result_operand.value().second)
1440 .build();
1441 instructions.push_back(l1tol2msgexists_instruction);
1442 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_operand.value().first.absolute_address);
1443}
1444
1446{
1447 auto value_operand = memory_manager.get_resolved_address_and_operand_16(instruction.value_address);
1448 auto radix_operand = memory_manager.get_resolved_address_and_operand_16(instruction.radix_address);
1449 auto num_limbs_operand = memory_manager.get_resolved_address_and_operand_16(instruction.num_limbs_address);
1450 auto output_bits_operand = memory_manager.get_resolved_address_and_operand_16(instruction.output_bits_address);
1451 auto dst_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1452
1453 if (!value_operand.has_value() || !radix_operand.has_value() || !num_limbs_operand.has_value() ||
1454 !output_bits_operand.has_value() || !dst_operand.has_value()) {
1455 return;
1456 }
1457
1458 preprocess_memory_addresses(value_operand.value().first);
1459 preprocess_memory_addresses(radix_operand.value().first);
1460 preprocess_memory_addresses(num_limbs_operand.value().first);
1461 preprocess_memory_addresses(output_bits_operand.value().first);
1462 preprocess_memory_addresses(dst_operand.value().first);
1463
1465 .operand(value_operand.value().second)
1466 .operand(radix_operand.value().second)
1467 .operand(num_limbs_operand.value().second)
1468 .operand(output_bits_operand.value().second)
1469 .operand(dst_operand.value().second)
1470 .build();
1471 instructions.push_back(toradixbe_instruction);
1472
1473 // Use is_output_bits to determine the output memory tag
1474 auto output_tag = instruction.is_output_bits ? bb::avm2::MemoryTag::U1 : bb::avm2::MemoryTag::U8;
1475 memory_manager.set_memory_address(output_tag, dst_operand.value().first.absolute_address);
1476}
1477
1479{
1480 auto level_operand = memory_manager.get_resolved_address_and_operand_16(instruction.level_offset);
1481 auto message_operand = memory_manager.get_resolved_address_and_operand_16(instruction.message_offset);
1482 auto fields_operand = memory_manager.get_resolved_address_and_operand_16(instruction.fields_offset);
1483 auto fields_size_operand = memory_manager.get_resolved_address_and_operand_16(instruction.fields_size_offset);
1484 auto message_size = instruction.message_size;
1485
1486 if (!level_operand.has_value() || !message_operand.has_value() || !fields_operand.has_value() ||
1487 !fields_size_operand.has_value()) {
1488 return;
1489 }
1490
1491 preprocess_memory_addresses(level_operand.value().first);
1492 preprocess_memory_addresses(message_operand.value().first);
1493 preprocess_memory_addresses(fields_operand.value().first);
1494 preprocess_memory_addresses(fields_size_operand.value().first);
1495
1497 .operand(level_operand.value().second)
1498 .operand(message_operand.value().second)
1499 .operand(fields_operand.value().second)
1500 .operand(fields_size_operand.value().second)
1502 .build();
1503 instructions.push_back(debuglog_instruction);
1504}
1505
1509{
1511 // if the block is called by INTERNALCALL, just insert INTERNALRETURN
1512 if (caller != nullptr) {
1513 auto internalreturn_instruction =
1515 instructions.push_back(internalreturn_instruction);
1516 return;
1517 }
1518
1520 if (!return_addr.has_value()) {
1521 return_addr = std::optional<uint32_t>(0);
1522 }
1523
1524 // TODO(defkit): return_size_offset should be const and defined by fuzzer
1525
1526 uint16_t return_size_offset = 5U;
1527 // Ensure operands are created as U16 to match wire format (UINT16)
1529 .operand(return_size_offset)
1531 .operand(static_cast<uint16_t>(return_size))
1532 .build();
1533 instructions.push_back(set_size_instruction);
1534 // RETURN expects UINT16 operands, ensure we cast to uint16_t explicitly
1536 .operand(static_cast<uint16_t>(return_size_offset))
1537 .operand(return_addr.value())
1538 .build();
1539 instructions.push_back(return_instruction);
1540}
1541
1542void ProgramBlock::finalize_with_revert(uint8_t revert_size,
1543 MemoryTagWrapper revert_value_tag,
1544 uint16_t revert_value_offset_index)
1545{
1547
1548 auto revert_addr = memory_manager.get_memory_offset_16(revert_value_tag.value, revert_value_offset_index);
1549 if (!revert_addr.has_value()) {
1550 revert_addr = std::optional<uint32_t>(0);
1551 }
1552
1553 // Once we do more of the randomness in Instruction selection, revert_size_offset we shouldnt need to hardcode
1554 uint16_t revert_size_offset = 5U;
1555 // Ensure operands are created as U16 to match wire format (UINT16)
1557 .operand(revert_size_offset)
1559 .operand(static_cast<uint16_t>(revert_size))
1560 .build();
1561 instructions.push_back(set_size_instruction);
1562 // REVERT_16 expects UINT16 operands, ensure we cast to uint16_t explicitly
1564 .operand(static_cast<uint16_t>(revert_size_offset))
1565 .operand(revert_addr.value())
1566 .build();
1567 instructions.push_back(revert_instruction);
1568}
1569
1570void ProgramBlock::finalize_with_jump(ProgramBlock* target_block, bool copy_memory_manager)
1571{
1573 successors.push_back(target_block);
1574 target_block->predecessors.push_back(this);
1575 target_block->caller = this->caller;
1576 if (copy_memory_manager) {
1577 target_block->memory_manager = memory_manager;
1578 }
1579}
1580
1582 ProgramBlock* target_else_block,
1583 uint16_t condition_offset,
1584 bool copy_memory_manager)
1585{
1587 successors.push_back(target_then_block);
1588 successors.push_back(target_else_block);
1590 target_then_block->predecessors.push_back(this);
1591 target_else_block->predecessors.push_back(this);
1592 target_then_block->caller = this->caller;
1593 target_else_block->caller = this->caller;
1594 if (copy_memory_manager) {
1595 target_then_block->memory_manager = memory_manager;
1596 target_else_block->memory_manager = memory_manager;
1597 }
1598}
1599
1601{
1602 auto internalcall_instruction =
1604 instructions.push_back(internalcall_instruction);
1606 this->successors.push_back(target_block);
1607 target_block->predecessors.push_back(this);
1608 target_block->caller = this->caller;
1609}
1610
1612{
1613 for (auto [instruction_index, target_block] : internal_call_instruction_indicies_to_patch) {
1614 auto internalcall_instruction = instructions.at(instruction_index);
1615 if (target_block->offset == -1) {
1616 throw std::runtime_error("Target block offset is not set, should not happen");
1617 }
1618 auto internalcall_instruction_builder =
1620 .operand(static_cast<uint32_t>(target_block->offset));
1621 instructions.at(instruction_index) = internalcall_instruction_builder.build();
1622 }
1624}
1625
1627{
1629 if (!condition_addr.has_value()) {
1630 return std::nullopt;
1631 }
1632 return condition_addr;
1633}
1634
1643
1648
1650{
1651 memory_manager.set_base_offset(instruction_block.base_offset);
1654 .result_address = AddressRef{ .address = 0, .mode = AddressingMode::Direct },
1655 .value = instruction_block.base_offset });
1656 for (const auto& instr : instruction_block.instructions) {
1657 process_instruction(instr);
1658 }
1659}
1660
1662{
1663 std::visit(
1664 overloaded{
1665 [this](ADD_8_Instruction instruction) { return this->process_add_8_instruction(instruction); },
1666 [this](SUB_8_Instruction instruction) { return this->process_sub_8_instruction(instruction); },
1667 [this](MUL_8_Instruction instruction) { return this->process_mul_8_instruction(instruction); },
1668 [this](DIV_8_Instruction instruction) { return this->process_div_8_instruction(instruction); },
1669 [this](EQ_8_Instruction instruction) { return this->process_eq_8_instruction(instruction); },
1670 [this](LT_8_Instruction instruction) { return this->process_lt_8_instruction(instruction); },
1671 [this](LTE_8_Instruction instruction) { return this->process_lte_8_instruction(instruction); },
1672 [this](AND_8_Instruction instruction) { return this->process_and_8_instruction(instruction); },
1673 [this](OR_8_Instruction instruction) { return this->process_or_8_instruction(instruction); },
1674 [this](XOR_8_Instruction instruction) { return this->process_xor_8_instruction(instruction); },
1675 [this](SHL_8_Instruction instruction) { return this->process_shl_8_instruction(instruction); },
1676 [this](SHR_8_Instruction instruction) { return this->process_shr_8_instruction(instruction); },
1677 [this](SET_8_Instruction instruction) { return this->process_set_8_instruction(instruction); },
1678 [this](SET_16_Instruction instruction) { return this->process_set_16_instruction(instruction); },
1679 [this](SET_32_Instruction instruction) { return this->process_set_32_instruction(instruction); },
1680 [this](SET_64_Instruction instruction) { return this->process_set_64_instruction(instruction); },
1681 [this](SET_128_Instruction instruction) { return this->process_set_128_instruction(instruction); },
1682 [this](SET_FF_Instruction instruction) { return this->process_set_ff_instruction(instruction); },
1683 [this](MOV_8_Instruction instruction) { return this->process_mov_8_instruction(instruction); },
1684 [this](MOV_16_Instruction instruction) { return this->process_mov_16_instruction(instruction); },
1685 [this](FDIV_8_Instruction instruction) { return this->process_fdiv_8_instruction(instruction); },
1686 [this](NOT_8_Instruction instruction) { return this->process_not_8_instruction(instruction); },
1687 [this](ADD_16_Instruction instruction) { return this->process_add_16_instruction(instruction); },
1688 [this](SUB_16_Instruction instruction) { return this->process_sub_16_instruction(instruction); },
1689 [this](MUL_16_Instruction instruction) { return this->process_mul_16_instruction(instruction); },
1690 [this](DIV_16_Instruction instruction) { return this->process_div_16_instruction(instruction); },
1691 [this](FDIV_16_Instruction instruction) { return this->process_fdiv_16_instruction(instruction); },
1692 [this](EQ_16_Instruction instruction) { return this->process_eq_16_instruction(instruction); },
1693 [this](LT_16_Instruction instruction) { return this->process_lt_16_instruction(instruction); },
1694 [this](LTE_16_Instruction instruction) { return this->process_lte_16_instruction(instruction); },
1695 [this](AND_16_Instruction instruction) { return this->process_and_16_instruction(instruction); },
1696 [this](OR_16_Instruction instruction) { return this->process_or_16_instruction(instruction); },
1697 [this](XOR_16_Instruction instruction) { return this->process_xor_16_instruction(instruction); },
1698 [this](NOT_16_Instruction instruction) { return this->process_not_16_instruction(instruction); },
1699 [this](SHL_16_Instruction instruction) { return this->process_shl_16_instruction(instruction); },
1700 [this](SHR_16_Instruction instruction) { return this->process_shr_16_instruction(instruction); },
1701 [this](CAST_8_Instruction instruction) { return this->process_cast_8_instruction(instruction); },
1702 [this](CAST_16_Instruction instruction) { return this->process_cast_16_instruction(instruction); },
1703 [this](SSTORE_Instruction instruction) { return this->process_sstore_instruction(instruction); },
1704 [this](SLOAD_Instruction instruction) { return this->process_sload_instruction(instruction); },
1705 [this](GETENVVAR_Instruction instruction) { return this->process_getenvvar_instruction(instruction); },
1707 return this->process_emitnulifier_instruction(instruction);
1708 },
1710 return this->process_nullifierexists_instruction(instruction);
1711 },
1713 return this->process_emitnotehash_instruction(instruction);
1714 },
1716 return this->process_notehashexists_instruction(instruction);
1717 },
1719 return this->process_calldatacopy_instruction(instruction);
1720 },
1722 return this->process_sendl2tol1msg_instruction(instruction);
1723 },
1725 return this->process_emitunencryptedlog_instruction(instruction);
1726 },
1727 [this](CALL_Instruction instruction) { return this->process_call_instruction(instruction); },
1729 return this->process_returndatasize_instruction(instruction);
1730 },
1732 return this->process_returndatacopy_instruction(instruction);
1733 },
1735 return this->process_getcontractinstance_instruction(instruction);
1736 },
1737 [this](SUCCESSCOPY_Instruction instruction) { return this->process_successcopy_instruction(instruction); },
1738 [this](ECADD_Instruction instruction) { return this->process_ecadd_instruction(instruction); },
1740 return this->process_poseidon2perm_instruction(instruction);
1741 },
1742 [this](KECCAKF1600_Instruction instruction) { return this->process_keccakf1600_instruction(instruction); },
1744 return this->process_sha256compression_instruction(instruction);
1745 },
1747 return this->process_l1tol2msgexists_instruction(instruction);
1748 },
1749 [this](TORADIXBE_Instruction instruction) { return this->process_toradixbe_instruction(instruction); },
1750 [this](DEBUGLOG_Instruction instruction) { return this->process_debuglog_instruction(instruction); },
1751 [](auto) { throw std::runtime_error("Unknown instruction"); },
1752 },
1753 instruction);
1754}
1755
1756std::vector<bb::avm2::simulation::Instruction> ProgramBlock::get_instructions()
1757{
1758 return instructions;
1759}
::FuzzInstruction FuzzInstruction
std::optional< uint16_t > get_memory_offset_16(bb::avm2::MemoryTag tag, uint32_t address_index)
std::optional< std::pair< ResolvedAddress, bb::avm2::testing::OperandBuilder > > get_resolved_address_and_operand_8(ParamRef address)
std::optional< bb::avm2::FF > get_slot(uint16_t slot_offset_index)
bool is_memory_address_set(uint16_t address)
void set_memory_address(bb::avm2::MemoryTag tag, uint32_t address)
void append_slot(bb::avm2::FF slot)
void set_base_offset(uint32_t base_offset)
std::optional< std::pair< ResolvedAddress, bb::avm2::testing::OperandBuilder > > get_resolved_address_and_operand_16(ParamRef address)
void process_shr_16_instruction(SHR_16_Instruction instruction)
void process_set_8_instruction(SET_8_Instruction instruction)
void process_poseidon2perm_instruction(POSEIDON2PERM_Instruction instruction)
std::vector< ProgramBlock * > predecessors
void process_sload_instruction(SLOAD_Instruction instruction)
void finalize_with_return(uint8_t return_size, MemoryTagWrapper return_value_tag, uint16_t return_value_offset_index)
finalize the program block with a return instruction Tries to find memory address with the given retu...
std::vector< bb::avm2::simulation::Instruction > get_instructions()
void preprocess_memory_addresses(ResolvedAddress resolved_address)
preprocess the memory addresses Sets M[0] = base_offset for Relative/IndirectRelative modes Sets M[po...
void insert_internal_call(ProgramBlock *target_block)
insert INTERNALCALL instruction with 0 offset
bool is_memory_address_set(uint16_t address)
void process_emitnotehash_instruction(EMITNOTEHASH_Instruction instruction)
void process_xor_16_instruction(XOR_16_Instruction instruction)
ProgramBlock * caller
the block that called this block by INTERNALCALL This field is copied to predecessors on every CFG in...
void process_or_16_instruction(OR_16_Instruction instruction)
void patch_internal_calls()
in insert_internal_call we insert INTERNALCALL instruction with 0 offset, because we don't know the r...
void finalize_with_jump(ProgramBlock *target_block, bool copy_memory_manager=true)
finalize the block with a jump Sets the terminator type to JUMP, adds the target block to the success...
void process_debuglog_instruction(DEBUGLOG_Instruction instruction)
void process_returndatacopy_instruction(RETURNDATACOPY_Instruction instruction)
uint16_t condition_offset_index
the offset index of the condition variable (for JUMP_IF)
void process_lte_16_instruction(LTE_16_Instruction instruction)
void process_eq_8_instruction(EQ_8_Instruction instruction)
void process_keccakf1600_instruction(KECCAKF1600_Instruction instruction)
void process_fdiv_8_instruction(FDIV_8_Instruction instruction)
void process_nullifierexists_instruction(NULLIFIEREXISTS_Instruction instruction)
void process_not_8_instruction(NOT_8_Instruction instruction)
void process_add_8_instruction(ADD_8_Instruction instruction)
void finalize_with_revert(uint8_t revert_size, MemoryTagWrapper revert_value_tag, uint16_t revert_value_offset_index)
finalize the program block with a revert instruction Similar to finalize_with_return but uses REVERT ...
void process_and_16_instruction(AND_16_Instruction instruction)
MemoryManager memory_manager
void process_sub_8_instruction(SUB_8_Instruction instruction)
void process_shl_8_instruction(SHL_8_Instruction instruction)
void process_notehashexists_instruction(NOTEHASHEXISTS_Instruction instruction)
void process_div_16_instruction(DIV_16_Instruction instruction)
void process_instruction(FuzzInstruction instruction)
process the instruction
void process_toradixbe_instruction(TORADIXBE_Instruction instruction)
void process_emitnulifier_instruction(EMITNULLIFIER_Instruction instruction)
void process_fdiv_16_instruction(FDIV_16_Instruction instruction)
void process_shl_16_instruction(SHL_16_Instruction instruction)
void process_mul_16_instruction(MUL_16_Instruction instruction)
void process_set_ff_instruction(SET_FF_Instruction instruction)
void process_sstore_instruction(SSTORE_Instruction instruction)
std::map< size_t, ProgramBlock * > internal_call_instruction_indicies_to_patch
void process_ecadd_instruction(ECADD_Instruction instruction)
void record_result_tag_from_param_tags(std::initializer_list< ParamRef > params, ResolvedAddress result_address)
void process_div_8_instruction(DIV_8_Instruction instruction)
void process_and_8_instruction(AND_8_Instruction instruction)
void process_lt_16_instruction(LT_16_Instruction instruction)
std::vector< ProgramBlock * > successors
void process_write_terminating_condition_value()
void process_sub_16_instruction(SUB_16_Instruction instruction)
void process_or_8_instruction(OR_8_Instruction instruction)
void process_cast_8_instruction(CAST_8_Instruction instruction)
void process_call_instruction(CALL_Instruction instruction)
void process_cast_16_instruction(CAST_16_Instruction instruction)
void process_not_16_instruction(NOT_16_Instruction instruction)
void process_set_64_instruction(SET_64_Instruction instruction)
void process_calldatacopy_instruction(CALLDATACOPY_Instruction instruction)
void process_successcopy_instruction(SUCCESSCOPY_Instruction instruction)
void process_l1tol2msgexists_instruction(L1TOL2MSGEXISTS_Instruction instruction)
void process_sendl2tol1msg_instruction(SENDL2TOL1MSG_Instruction instruction)
void process_mov_8_instruction(MOV_8_Instruction instruction)
std::optional< uint16_t > get_terminating_condition_value()
void process_emitunencryptedlog_instruction(EMITUNENCRYPTEDLOG_Instruction instruction)
void process_returndatasize_instruction(RETURNDATASIZE_Instruction instruction)
void process_sha256compression_instruction(SHA256COMPRESSION_Instruction instruction)
void process_instruction_block(InstructionBlock &instruction_block)
process the instruction block
void process_mul_8_instruction(MUL_8_Instruction instruction)
void process_set_16_instruction(SET_16_Instruction instruction)
void process_add_16_instruction(ADD_16_Instruction instruction)
void process_xor_8_instruction(XOR_8_Instruction instruction)
void process_eq_16_instruction(EQ_16_Instruction instruction)
void process_lte_8_instruction(LTE_8_Instruction instruction)
void process_getcontractinstance_instruction(GETCONTRACTINSTANCE_Instruction instruction)
void finalize_with_jump_if(ProgramBlock *target_then_block, ProgramBlock *target_else_block, uint16_t condition_offset, bool copy_memory_manager=true)
finalize the block with a jump if Sets the terminator type to JUMP_IF, adds the target blocks to the ...
void process_set_32_instruction(SET_32_Instruction instruction)
void process_getenvvar_instruction(GETENVVAR_Instruction instruction)
TerminatorType terminator_type
void process_lt_8_instruction(LT_8_Instruction instruction)
std::vector< bb::avm2::simulation::Instruction > instructions
void process_shr_8_instruction(SHR_8_Instruction instruction)
void process_mov_16_instruction(MOV_16_Instruction instruction)
void process_set_128_instruction(SET_128_Instruction instruction)
simulation::Instruction build() const
InstructionBuilder & operand(OperandBuilder operand)
FF a
FF b
overloaded(Ts...) -> overloaded< Ts... >
uint64_t da_gas
uint64_t l2_gas
Instruction instruction
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
unsigned __int128 uint128_t
Definition serialize.hpp:44
mem[result_offset] = mem[a_address] + mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] + mem[b_address]
mem[result_offset] = mem[a_address] & mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] & mem[b_address]
uint32_t address
CAST_16: cast mem[src_offset_index] to target_tag and store at dst_offset.
CAST_8: cast mem[src_offset_index] to target_tag and store at dst_offset.
mem[result_offset] = mem[a_address] / mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] / mem[b_address]
EMITNOTEHASH: M[note_hash_offset] = note_hash; emit note hash to the note hash tree.
EMITNULIFIER: inserts new nullifier to the nullifier tree.
mem[result_offset] = mem[a_address] == mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] == mem[b_address]
GETENVVAR: M[result_offset] = getenvvar(type)
KECCAKF1600: Perform Keccak-f[1600] permutation on 25 U64 values M[dst_address:dst_address+25] = kecc...
L1TOL2MSGEXISTS: Check if a L1 to L2 message exists M[result_address] = L1TOL2MSGEXISTS(M[msg_hash_ad...
mem[result_offset] = mem[a_address] < mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] < mem[b_address]
mem[result_offset] = mem[a_address] <= mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] <= mem[b_address]
MOV_16 instruction: mem[dst_offset] = mem[src_offset].
MOV_8 instruction: mem[dst_offset] = mem[src_offset].
mem[result_offset] = mem[a_address] * mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] * mem[b_address]
Wrapper for MemoryTag to allow for msgpack packing and unpacking.
NULLIFIEREXISTS: checks if nullifier exists in the nullifier tree Gets contract's address by GETENVVA...
mem[result_offset] = mem[a_address] | mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] | mem[b_address]
POSEIDON2PERM: Perform Poseidon2 permutation on 4 FF values M[dst_address:dst_address+4] = poseidon2_...
Output of resolving an address in the memory manager In order to resolve a given absolute address wit...
uint32_t operand_address
uint32_t absolute_address
std::optional< uint32_t > pointer_address
SET_128 instruction.
SET_16 instruction.
MemoryTagWrapper value_tag
SET_32 instruction.
MemoryTagWrapper value_tag
SET_64 instruction.
SET_8 instruction.
SET_FF instruction.
MemoryTagWrapper value_tag
SHA256COMPRESSION: Perform SHA256 compression M[dst_address:dst_address+8] = sha256_compression(M[sta...
mem[result_offset] = mem[a_address] << mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] << mem[b_address]
mem[result_offset] = mem[a_address] >> mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] >> mem[b_address]
SLOAD: M[slot_offset] = slot; M[result_offset] = S[M[slotOffset]].
SSTORE: M[slot_offset_index] = slot; S[M[slotOffset]] = M[srcOffset].
mem[result_offset] = mem[a_address] - mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] - mem[b_address]
TORADIXBE: Convert a field element to a vector of limbs in big-endian radix representation M[dst_addr...
mem[result_offset] = mem[a_address] ^ mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] ^ mem[b_address]
std::vector< FuzzInstruction > instructions