1use std::{cell::UnsafeCell, ptr};
2
3use p3_field::AbstractField;
4use sp1_primitives::types::RecursionProgramType;
5
6use super::{
7 Array, Config, DslIr, DslIrBlock, Ext, ExtHandle, ExtOperations, Felt, FeltHandle,
8 FeltOperations, FromConstant, SymbolicExt, SymbolicFelt, SymbolicUsize, SymbolicVar, Usize,
9 Var, VarHandle, VarOperations, Variable,
10};
11
12#[derive(Debug, Clone)]
13pub struct InnerBuilder<C: Config> {
14 pub(crate) variable_count: u32,
15 pub operations: Vec<DslIr<C>>,
16}
17
18#[derive(Debug)]
22pub struct Builder<C: Config> {
23 pub(crate) inner: Box<UnsafeCell<InnerBuilder<C>>>,
24 pub(crate) nb_public_values: Option<Var<C::N>>,
25 pub(crate) witness_var_count: u32,
26 pub(crate) witness_felt_count: u32,
27 pub(crate) witness_ext_count: u32,
28 pub(crate) var_handle: Box<VarHandle<C::N>>,
29 pub(crate) felt_handle: Box<FeltHandle<C::F>>,
30 pub(crate) ext_handle: Box<ExtHandle<C::F, C::EF>>,
31 pub(crate) p2_hash_num: Var<C::N>,
32 pub(crate) debug: bool,
33 pub(crate) is_sub_builder: bool,
34 pub program_type: RecursionProgramType,
35}
36
37impl<C: Config> Default for Builder<C> {
38 fn default() -> Self {
39 Self::new(RecursionProgramType::Core)
40 }
41}
42
43impl<C: Config> Builder<C> {
44 pub fn new(program_type: RecursionProgramType) -> Self {
45 let placeholder_p2_hash_num = Var::new(0, ptr::null_mut());
47
48 let mut inner = Box::new(UnsafeCell::new(InnerBuilder {
49 variable_count: 0,
50 operations: Default::default(),
51 }));
52
53 let var_handle = Box::new(VarOperations::var_handle(&mut inner));
54 let mut ext_handle = Box::new(ExtOperations::ext_handle(&mut inner));
55 let felt_handle = Box::new(FeltOperations::felt_handle(
56 &mut inner,
57 ext_handle.as_mut() as *mut _ as *mut (),
58 ));
59
60 let mut new_builder = Self {
61 inner,
62 witness_var_count: 0,
63 witness_felt_count: 0,
64 witness_ext_count: 0,
65 nb_public_values: None,
66 var_handle,
67 felt_handle,
68 ext_handle,
69 p2_hash_num: placeholder_p2_hash_num,
70 debug: false,
71 is_sub_builder: false,
72 program_type,
73 };
74
75 new_builder.p2_hash_num = new_builder.uninit();
76 new_builder
77 }
78
79 pub fn new_sub_builder(
81 variable_count: u32,
82 nb_public_values: Option<Var<C::N>>,
83 p2_hash_num: Var<C::N>,
84 debug: bool,
85 program_type: RecursionProgramType,
86 ) -> Self {
87 let mut builder = Self::new(program_type);
88 builder.inner.get_mut().variable_count = variable_count;
89 builder.nb_public_values = nb_public_values;
90 builder.p2_hash_num = p2_hash_num;
91 builder.debug = debug;
92
93 builder
94 }
95
96 pub fn sub_builder(&self) -> Self {
98 Builder::<C>::new_sub_builder(
99 self.variable_count(),
100 self.nb_public_values,
101 self.p2_hash_num,
102 self.debug,
103 self.program_type,
104 )
105 }
106
107 #[inline(always)]
109 pub fn push_op(&mut self, op: DslIr<C>) {
110 self.inner.get_mut().operations.push(op);
111 }
112
113 pub fn extend_ops(&mut self, ops: impl IntoIterator<Item = DslIr<C>>) {
114 self.inner.get_mut().operations.extend(ops);
115 }
116
117 #[inline(always)]
118 pub fn push_backtrace(&mut self) {
120 #[cfg(feature = "debug")]
121 self.push_op(DslIr::DebugBacktrace(backtrace::Backtrace::new_unresolved()));
122 }
123
124 #[inline(always)]
126 pub fn push_traced_op(&mut self, op: DslIr<C>) {
127 self.push_backtrace();
128 self.push_op(op);
129 }
130
131 pub fn variable_count(&self) -> u32 {
132 unsafe { (*self.inner.get()).variable_count }
133 }
134
135 pub fn set_variable_count(&mut self, variable_count: u32) {
136 self.inner.get_mut().variable_count = variable_count;
137 }
138
139 pub fn into_operations(self) -> Vec<DslIr<C>> {
140 self.inner.into_inner().operations
141 }
142
143 pub fn into_root_block(self) -> DslIrBlock<C> {
144 let addrs_written = 0..self.variable_count();
145 DslIrBlock { ops: self.inner.into_inner().operations, addrs_written }
146 }
147
148 pub fn get_mut_operations(&mut self) -> &mut Vec<DslIr<C>> {
153 &mut self.inner.get_mut().operations
154 }
155
156 pub fn uninit<V: Variable<C>>(&mut self) -> V {
158 V::uninit(self)
159 }
160
161 pub fn eval<V: Variable<C>, E: Into<V::Expression>>(&mut self, expr: E) -> V {
163 let dst = V::uninit(self);
164 dst.assign(expr.into(), self);
165 dst
166 }
167
168 pub fn constant<V: FromConstant<C>>(&mut self, value: V::Constant) -> V {
170 V::constant(value, self)
171 }
172
173 pub fn assign<V: Variable<C>, E: Into<V::Expression>>(&mut self, dst: V, expr: E) {
175 dst.assign(expr.into(), self);
176 }
177
178 pub fn assert_eq<V: Variable<C>>(
180 &mut self,
181 lhs: impl Into<V::Expression>,
182 rhs: impl Into<V::Expression>,
183 ) {
184 V::assert_eq(lhs, rhs, self);
185 }
186
187 pub fn assert_ne<V: Variable<C>>(
189 &mut self,
190 lhs: impl Into<V::Expression>,
191 rhs: impl Into<V::Expression>,
192 ) {
193 V::assert_ne(lhs, rhs, self);
194 }
195
196 pub fn assert_var_eq<LhsExpr: Into<SymbolicVar<C::N>>, RhsExpr: Into<SymbolicVar<C::N>>>(
198 &mut self,
199 lhs: LhsExpr,
200 rhs: RhsExpr,
201 ) {
202 self.assert_eq::<Var<C::N>>(lhs, rhs);
203 }
204
205 pub fn assert_var_ne<LhsExpr: Into<SymbolicVar<C::N>>, RhsExpr: Into<SymbolicVar<C::N>>>(
207 &mut self,
208 lhs: LhsExpr,
209 rhs: RhsExpr,
210 ) {
211 self.assert_ne::<Var<C::N>>(lhs, rhs);
212 }
213
214 pub fn assert_felt_eq<LhsExpr: Into<SymbolicFelt<C::F>>, RhsExpr: Into<SymbolicFelt<C::F>>>(
216 &mut self,
217 lhs: LhsExpr,
218 rhs: RhsExpr,
219 ) {
220 self.assert_eq::<Felt<C::F>>(lhs, rhs);
221 }
222
223 pub fn assert_felt_ne<LhsExpr: Into<SymbolicFelt<C::F>>, RhsExpr: Into<SymbolicFelt<C::F>>>(
225 &mut self,
226 lhs: LhsExpr,
227 rhs: RhsExpr,
228 ) {
229 self.assert_ne::<Felt<C::F>>(lhs, rhs);
230 }
231
232 pub fn assert_usize_eq<
234 LhsExpr: Into<SymbolicUsize<C::N>>,
235 RhsExpr: Into<SymbolicUsize<C::N>>,
236 >(
237 &mut self,
238 lhs: LhsExpr,
239 rhs: RhsExpr,
240 ) {
241 self.assert_eq::<Usize<C::N>>(lhs, rhs);
242 }
243
244 pub fn assert_usize_ne(
246 &mut self,
247 lhs: impl Into<SymbolicUsize<C::N>>,
248 rhs: impl Into<SymbolicUsize<C::N>>,
249 ) {
250 self.assert_ne::<Usize<C::N>>(lhs, rhs);
251 }
252
253 pub fn assert_ext_eq<
255 LhsExpr: Into<SymbolicExt<C::F, C::EF>>,
256 RhsExpr: Into<SymbolicExt<C::F, C::EF>>,
257 >(
258 &mut self,
259 lhs: LhsExpr,
260 rhs: RhsExpr,
261 ) {
262 self.assert_eq::<Ext<C::F, C::EF>>(lhs, rhs);
263 }
264
265 pub fn assert_ext_ne<
267 LhsExpr: Into<SymbolicExt<C::F, C::EF>>,
268 RhsExpr: Into<SymbolicExt<C::F, C::EF>>,
269 >(
270 &mut self,
271 lhs: LhsExpr,
272 rhs: RhsExpr,
273 ) {
274 self.assert_ne::<Ext<C::F, C::EF>>(lhs, rhs);
275 }
276
277 pub fn lt(&mut self, lhs: Var<C::N>, rhs: Var<C::N>) -> Var<C::N> {
278 let result = self.uninit();
279 self.push_op(DslIr::LessThan(result, lhs, rhs));
280 result
281 }
282
283 pub fn if_eq<LhsExpr: Into<SymbolicVar<C::N>>, RhsExpr: Into<SymbolicVar<C::N>>>(
285 &mut self,
286 lhs: LhsExpr,
287 rhs: RhsExpr,
288 ) -> IfBuilder<C> {
289 IfBuilder { lhs: lhs.into(), rhs: rhs.into(), is_eq: true, builder: self }
290 }
291
292 pub fn if_ne<LhsExpr: Into<SymbolicVar<C::N>>, RhsExpr: Into<SymbolicVar<C::N>>>(
294 &mut self,
295 lhs: LhsExpr,
296 rhs: RhsExpr,
297 ) -> IfBuilder<C> {
298 IfBuilder { lhs: lhs.into(), rhs: rhs.into(), is_eq: false, builder: self }
299 }
300
301 pub fn range(
303 &mut self,
304 start: impl Into<Usize<C::N>>,
305 end: impl Into<Usize<C::N>>,
306 ) -> RangeBuilder<C> {
307 RangeBuilder { start: start.into(), end: end.into(), builder: self, step_size: 1 }
308 }
309
310 pub fn break_loop(&mut self) {
312 self.push_op(DslIr::Break);
313 }
314
315 pub fn print_debug(&mut self, val: usize) {
316 let constant = self.eval(C::N::from_canonical_usize(val));
317 self.print_v(constant);
318 }
319
320 pub fn print_v(&mut self, dst: Var<C::N>) {
322 self.push_op(DslIr::PrintV(dst));
323 }
324
325 pub fn print_f(&mut self, dst: Felt<C::F>) {
327 self.push_op(DslIr::PrintF(dst));
328 }
329
330 pub fn print_e(&mut self, dst: Ext<C::F, C::EF>) {
332 self.push_op(DslIr::PrintE(dst));
333 }
334
335 pub fn hint_len(&mut self) -> Var<C::N> {
337 let len = self.uninit();
338 self.push_op(DslIr::HintLen(len));
339 len
340 }
341
342 pub fn hint_var(&mut self) -> Var<C::N> {
344 let len = self.hint_len();
345 let arr = self.dyn_array(len);
346 self.push_op(DslIr::HintVars(arr.clone()));
347 self.get(&arr, 0)
348 }
349
350 pub fn hint_felt(&mut self) -> Felt<C::F> {
352 let len = self.hint_len();
353 let arr = self.dyn_array(len);
354 self.push_op(DslIr::HintFelts(arr.clone()));
355 self.get(&arr, 0)
356 }
357
358 pub fn hint_ext(&mut self) -> Ext<C::F, C::EF> {
360 let len = self.hint_len();
361 let arr = self.dyn_array(len);
362 self.push_op(DslIr::HintExts(arr.clone()));
363 self.get(&arr, 0)
364 }
365
366 pub fn hint_vars(&mut self) -> Array<C, Var<C::N>> {
368 let len = self.hint_len();
369 let arr = self.dyn_array(len);
370 self.push_op(DslIr::HintVars(arr.clone()));
371 arr
372 }
373
374 pub fn hint_felts(&mut self) -> Array<C, Felt<C::F>> {
376 let len = self.hint_len();
377 let arr = self.dyn_array(len);
378 self.push_op(DslIr::HintFelts(arr.clone()));
379 arr
380 }
381
382 pub fn hint_exts(&mut self) -> Array<C, Ext<C::F, C::EF>> {
384 let len = self.hint_len();
385 let arr = self.dyn_array(len);
386 self.push_op(DslIr::HintExts(arr.clone()));
387 arr
388 }
389
390 pub fn witness_var(&mut self) -> Var<C::N> {
391 assert!(!self.is_sub_builder, "Cannot create a witness var with a sub builder");
392 let witness = self.uninit();
393 self.push_op(DslIr::WitnessVar(witness, self.witness_var_count));
394 self.witness_var_count += 1;
395 witness
396 }
397
398 pub fn witness_felt(&mut self) -> Felt<C::F> {
399 assert!(!self.is_sub_builder, "Cannot create a witness felt with a sub builder");
400 let witness = self.uninit();
401 self.push_op(DslIr::WitnessFelt(witness, self.witness_felt_count));
402 self.witness_felt_count += 1;
403 witness
404 }
405
406 pub fn witness_ext(&mut self) -> Ext<C::F, C::EF> {
407 assert!(!self.is_sub_builder, "Cannot create a witness ext with a sub builder");
408 let witness = self.uninit();
409 self.push_op(DslIr::WitnessExt(witness, self.witness_ext_count));
410 self.witness_ext_count += 1;
411 witness
412 }
413
414 pub fn error(&mut self) {
416 self.push_traced_op(DslIr::Error());
417 }
418
419 pub fn materialize(&mut self, num: Usize<C::N>) -> Var<C::N> {
421 match num {
422 Usize::Const(num) => self.eval(C::N::from_canonical_usize(num)),
423 Usize::Var(num) => num,
424 }
425 }
426
427 pub fn register_public_value(&mut self, val: Felt<C::F>) {
429 self.push_op(DslIr::RegisterPublicValue(val));
430 }
431
432 pub fn commit_public_value(&mut self, val: Felt<C::F>) {
434 assert!(!self.is_sub_builder, "Cannot commit to a public value with a sub builder");
435 if self.nb_public_values.is_none() {
436 self.nb_public_values = Some(self.eval(C::N::zero()));
437 }
438 let nb_public_values = *self.nb_public_values.as_ref().unwrap();
439
440 self.push_op(DslIr::Commit(val, nb_public_values));
441 self.assign(nb_public_values, nb_public_values + C::N::one());
442 }
443
444 pub fn commit_public_values(&mut self, vals: &Array<C, Felt<C::F>>) {
446 assert!(!self.is_sub_builder, "Cannot commit to public values with a sub builder");
447 let len = vals.len();
448 self.range(0, len).for_each(|i, builder| {
449 let val = builder.get(vals, i);
450 builder.commit_public_value(val);
451 });
452 }
453
454 pub fn commit_vkey_hash_circuit(&mut self, var: Var<C::N>) {
455 self.push_op(DslIr::CircuitCommitVkeyHash(var));
456 }
457
458 pub fn commit_committed_values_digest_circuit(&mut self, var: Var<C::N>) {
459 self.push_op(DslIr::CircuitCommitCommittedValuesDigest(var));
460 }
461
462 pub fn reduce_e(&mut self, ext: Ext<C::F, C::EF>) {
463 self.push_op(DslIr::ReduceE(ext));
464 }
465
466 pub fn felt2var_circuit(&mut self, felt: Felt<C::F>) -> Var<C::N> {
467 let var = self.uninit();
468 self.push_op(DslIr::CircuitFelt2Var(felt, var));
469 var
470 }
471
472 pub fn cycle_tracker(&mut self, name: &str) {
473 self.push_op(DslIr::CycleTracker(name.to_string()));
474 }
475
476 pub fn halt(&mut self) {
477 self.push_op(DslIr::Halt);
478 }
479}
480
481#[allow(dead_code)]
483pub struct IfBuilder<'a, C: Config> {
484 lhs: SymbolicVar<C::N>,
485 rhs: SymbolicVar<C::N>,
486 is_eq: bool,
487 pub(crate) builder: &'a mut Builder<C>,
488}
489
490#[allow(dead_code)]
492enum IfCondition<N> {
493 EqConst(N, N),
494 NeConst(N, N),
495 Eq(Var<N>, Var<N>),
496 EqI(Var<N>, N),
497 Ne(Var<N>, Var<N>),
498 NeI(Var<N>, N),
499}
500
501impl<C: Config> IfBuilder<'_, C> {
502 pub fn then(mut self, mut f: impl FnMut(&mut Builder<C>)) {
503 let condition = self.condition();
505
506 let mut f_builder = Builder::<C>::new_sub_builder(
508 self.builder.variable_count(),
509 self.builder.nb_public_values,
510 self.builder.p2_hash_num,
511 self.builder.debug,
512 self.builder.program_type,
513 );
514 f(&mut f_builder);
515 self.builder.p2_hash_num = f_builder.p2_hash_num;
516
517 let then_instructions = f_builder.into_operations();
518
519 match condition {
521 IfCondition::EqConst(lhs, rhs) => {
522 if lhs == rhs {
523 self.builder.extend_ops(then_instructions);
524 }
525 }
526 IfCondition::NeConst(lhs, rhs) => {
527 if lhs != rhs {
528 self.builder.extend_ops(then_instructions);
529 }
530 }
531 IfCondition::Eq(lhs, rhs) => {
532 let op = DslIr::IfEq(Box::new((lhs, rhs, then_instructions, Default::default())));
533 self.builder.push_op(op);
534 }
535 IfCondition::EqI(lhs, rhs) => {
536 let op = DslIr::IfEqI(Box::new((lhs, rhs, then_instructions, Default::default())));
537 self.builder.push_op(op);
538 }
539 IfCondition::Ne(lhs, rhs) => {
540 let op = DslIr::IfNe(Box::new((lhs, rhs, then_instructions, Default::default())));
541 self.builder.push_op(op);
542 }
543 IfCondition::NeI(lhs, rhs) => {
544 let op = DslIr::IfNeI(Box::new((lhs, rhs, then_instructions, Default::default())));
545 self.builder.push_op(op);
546 }
547 }
548 }
549
550 pub fn then_or_else(
551 mut self,
552 mut then_f: impl FnMut(&mut Builder<C>),
553 mut else_f: impl FnMut(&mut Builder<C>),
554 ) {
555 let condition = self.condition();
557 let mut then_builder = Builder::<C>::new_sub_builder(
558 self.builder.variable_count(),
559 self.builder.nb_public_values,
560 self.builder.p2_hash_num,
561 self.builder.debug,
562 self.builder.program_type,
563 );
564
565 then_f(&mut then_builder);
567 self.builder.p2_hash_num = then_builder.p2_hash_num;
568
569 let then_instructions = then_builder.into_operations();
570
571 let mut else_builder = Builder::<C>::new_sub_builder(
572 self.builder.variable_count(),
573 self.builder.nb_public_values,
574 self.builder.p2_hash_num,
575 self.builder.debug,
576 self.builder.program_type,
577 );
578 else_f(&mut else_builder);
579 self.builder.p2_hash_num = else_builder.p2_hash_num;
580
581 let else_instructions = else_builder.into_operations();
582
583 match condition {
585 IfCondition::EqConst(lhs, rhs) => {
586 if lhs == rhs {
587 self.builder.extend_ops(then_instructions);
588 } else {
589 self.builder.extend_ops(else_instructions);
590 }
591 }
592 IfCondition::NeConst(lhs, rhs) => {
593 if lhs != rhs {
594 self.builder.extend_ops(then_instructions);
595 } else {
596 self.builder.extend_ops(else_instructions);
597 }
598 }
599 IfCondition::Eq(lhs, rhs) => {
600 let op = DslIr::IfEq(Box::new((lhs, rhs, then_instructions, else_instructions)));
601 self.builder.push_op(op);
602 }
603 IfCondition::EqI(lhs, rhs) => {
604 let op = DslIr::IfEqI(Box::new((lhs, rhs, then_instructions, else_instructions)));
605 self.builder.push_op(op);
606 }
607 IfCondition::Ne(lhs, rhs) => {
608 let op = DslIr::IfNe(Box::new((lhs, rhs, then_instructions, else_instructions)));
609 self.builder.push_op(op);
610 }
611 IfCondition::NeI(lhs, rhs) => {
612 let op = DslIr::IfNeI(Box::new((lhs, rhs, then_instructions, else_instructions)));
613 self.builder.push_op(op);
614 }
615 }
616 }
617
618 fn condition(&mut self) -> IfCondition<C::N> {
619 unimplemented!("Deprecated")
620 }
689}
690
691pub struct RangeBuilder<'a, C: Config> {
693 start: Usize<C::N>,
694 end: Usize<C::N>,
695 step_size: usize,
696 builder: &'a mut Builder<C>,
697}
698
699impl<C: Config> RangeBuilder<'_, C> {
700 pub const fn step_by(mut self, step_size: usize) -> Self {
701 self.step_size = step_size;
702 self
703 }
704
705 pub fn for_each(self, mut f: impl FnMut(Var<C::N>, &mut Builder<C>)) {
706 let step_size = C::N::from_canonical_usize(self.step_size);
707 let loop_variable: Var<C::N> = self.builder.uninit();
708 let mut loop_body_builder = Builder::<C>::new_sub_builder(
709 self.builder.variable_count(),
710 self.builder.nb_public_values,
711 self.builder.p2_hash_num,
712 self.builder.debug,
713 self.builder.program_type,
714 );
715
716 f(loop_variable, &mut loop_body_builder);
717 self.builder.p2_hash_num = loop_body_builder.p2_hash_num;
718
719 let loop_instructions = loop_body_builder.into_operations();
720
721 let op = DslIr::For(Box::new((
722 self.start,
723 self.end,
724 step_size,
725 loop_variable,
726 loop_instructions,
727 )));
728 self.builder.push_op(op);
729 }
730}