sp1_recursion_compiler/ir/
builder.rs1use std::{cell::UnsafeCell, ptr};
2
3use slop_algebra::AbstractField;
4use sp1_primitives::{types::RecursionProgramType, SP1ExtensionField, SP1Field};
5
6use super::{
7 Config, DslIr, DslIrBlock, Ext, ExtHandle, ExtOperations, Felt, FeltHandle, FeltOperations,
8 FromConstant, SymbolicExt, SymbolicFelt, SymbolicVar, Var, VarHandle, VarOperations, Variable,
9};
10
11#[derive(Debug, Clone)]
12pub(crate) struct InnerBuilder<C: Config> {
13 pub(crate) variable_count: u32,
14 pub operations: Vec<DslIr<C>>,
15}
16
17#[derive(Debug)]
21pub struct Builder<C: Config> {
22 pub(crate) inner: Box<UnsafeCell<InnerBuilder<C>>>,
23 pub(crate) nb_public_values: Option<Var<C::N>>,
24 pub(crate) witness_var_count: u32,
25 pub(crate) witness_felt_count: u32,
26 pub(crate) witness_ext_count: u32,
27 pub(crate) var_handle: Box<VarHandle<C::N>>,
28 pub(crate) felt_handle: Box<FeltHandle<SP1Field>>,
29 pub(crate) ext_handle: Box<ExtHandle<SP1Field, SP1ExtensionField>>,
30 pub(crate) p2_hash_num: Var<C::N>,
31 pub(crate) debug: bool,
32 pub(crate) is_sub_builder: bool,
33 pub poseidon2_constants: Vec<Ext<SP1Field, SP1ExtensionField>>,
34 pub program_type: RecursionProgramType,
35}
36
37impl<C: Config> Default for Builder<C> {
38 fn default() -> Self {
39 let mut builder = Self::new(RecursionProgramType::Core);
40 C::initialize(&mut builder);
41 builder
42 }
43}
44
45impl<C: Config> Builder<C> {
46 pub fn new(program_type: RecursionProgramType) -> Self {
47 let placeholder_p2_hash_num = Var::new(0, ptr::null_mut());
49
50 let mut inner = Box::new(UnsafeCell::new(InnerBuilder {
51 variable_count: 0,
52 operations: Default::default(),
53 }));
54
55 let var_handle = Box::new(VarOperations::var_handle(&mut inner));
56 let mut ext_handle = Box::new(ExtOperations::ext_handle(&mut inner));
57 let felt_handle = Box::new(FeltOperations::felt_handle(
58 &mut inner,
59 ext_handle.as_mut() as *mut _ as *mut (),
60 ));
61
62 let mut new_builder = Self {
63 inner,
64 witness_var_count: 0,
65 witness_felt_count: 0,
66 witness_ext_count: 0,
67 nb_public_values: None,
68 var_handle,
69 felt_handle,
70 ext_handle,
71 p2_hash_num: placeholder_p2_hash_num,
72 debug: false,
73 is_sub_builder: false,
74 poseidon2_constants: vec![],
75 program_type,
76 };
77
78 new_builder.p2_hash_num = new_builder.uninit();
79 new_builder
80 }
81
82 pub fn new_sub_builder(
84 variable_count: u32,
85 nb_public_values: Option<Var<C::N>>,
86 p2_hash_num: Var<C::N>,
87 debug: bool,
88 program_type: RecursionProgramType,
89 ) -> Self {
90 let mut builder = Self::new(program_type);
91 builder.inner.get_mut().variable_count = variable_count;
92 builder.nb_public_values = nb_public_values;
93 builder.p2_hash_num = p2_hash_num;
94 builder.debug = debug;
95
96 builder
97 }
98
99 pub fn sub_builder(&self) -> Self {
101 Builder::<C>::new_sub_builder(
102 self.variable_count(),
103 self.nb_public_values,
104 self.p2_hash_num,
105 self.debug,
106 self.program_type,
107 )
108 }
109
110 #[inline(always)]
112 pub fn push_op(&mut self, op: DslIr<C>) {
113 self.inner.get_mut().operations.push(op);
114 }
115
116 pub fn extend_ops(&mut self, ops: impl IntoIterator<Item = DslIr<C>>) {
117 self.inner.get_mut().operations.extend(ops);
118 }
119
120 #[inline(always)]
121 pub fn push_backtrace(&mut self) {
123 #[cfg(feature = "debug")]
124 self.push_op(DslIr::DebugBacktrace(backtrace::Backtrace::new_unresolved()));
125 }
126
127 #[inline(always)]
129 pub fn push_traced_op(&mut self, op: DslIr<C>) {
130 self.push_backtrace();
131 self.push_op(op);
132 }
133
134 pub fn variable_count(&self) -> u32 {
135 unsafe { (*self.inner.get()).variable_count }
136 }
137
138 pub fn into_operations(self) -> Vec<DslIr<C>> {
139 self.inner.into_inner().operations
140 }
141
142 pub fn into_root_block(self) -> DslIrBlock<C> {
143 let addrs_written = 0..self.variable_count();
144 DslIrBlock { ops: self.inner.into_inner().operations, addrs_written }
145 }
146
147 pub fn get_mut_operations(&mut self) -> &mut Vec<DslIr<C>> {
152 &mut self.inner.get_mut().operations
153 }
154
155 pub fn uninit<V: Variable<C>>(&mut self) -> V {
157 V::uninit(self)
158 }
159
160 pub fn eval<V: Variable<C>, E: Into<V::Expression>>(&mut self, expr: E) -> V {
162 let dst = V::uninit(self);
163 dst.assign(expr.into(), self);
164 dst
165 }
166
167 pub fn constant<V: FromConstant<C>>(&mut self, value: V::Constant) -> V {
169 V::constant(value, self)
170 }
171
172 pub fn assign<V: Variable<C>, E: Into<V::Expression>>(&mut self, dst: V, expr: E) {
174 dst.assign(expr.into(), self);
175 }
176
177 pub fn assert_eq<V: Variable<C>>(
179 &mut self,
180 lhs: impl Into<V::Expression>,
181 rhs: impl Into<V::Expression>,
182 ) {
183 V::assert_eq(lhs, rhs, self);
184 }
185
186 pub fn assert_ne<V: Variable<C>>(
188 &mut self,
189 lhs: impl Into<V::Expression>,
190 rhs: impl Into<V::Expression>,
191 ) {
192 V::assert_ne(lhs, rhs, self);
193 }
194
195 pub fn assert_var_eq<LhsExpr: Into<SymbolicVar<C::N>>, RhsExpr: Into<SymbolicVar<C::N>>>(
197 &mut self,
198 lhs: LhsExpr,
199 rhs: RhsExpr,
200 ) {
201 self.assert_eq::<Var<C::N>>(lhs, rhs);
202 }
203
204 pub fn assert_var_ne<LhsExpr: Into<SymbolicVar<C::N>>, RhsExpr: Into<SymbolicVar<C::N>>>(
206 &mut self,
207 lhs: LhsExpr,
208 rhs: RhsExpr,
209 ) {
210 self.assert_ne::<Var<C::N>>(lhs, rhs);
211 }
212
213 pub fn assert_felt_eq<
215 LhsExpr: Into<SymbolicFelt<SP1Field>>,
216 RhsExpr: Into<SymbolicFelt<SP1Field>>,
217 >(
218 &mut self,
219 lhs: LhsExpr,
220 rhs: RhsExpr,
221 ) {
222 self.assert_eq::<Felt<SP1Field>>(lhs, rhs);
223 }
224
225 pub fn assert_felt_ne<
227 LhsExpr: Into<SymbolicFelt<SP1Field>>,
228 RhsExpr: Into<SymbolicFelt<SP1Field>>,
229 >(
230 &mut self,
231 lhs: LhsExpr,
232 rhs: RhsExpr,
233 ) {
234 self.assert_ne::<Felt<SP1Field>>(lhs, rhs);
235 }
236
237 pub fn assert_ext_eq<
239 LhsExpr: Into<SymbolicExt<SP1Field, SP1ExtensionField>>,
240 RhsExpr: Into<SymbolicExt<SP1Field, SP1ExtensionField>>,
241 >(
242 &mut self,
243 lhs: LhsExpr,
244 rhs: RhsExpr,
245 ) {
246 self.assert_eq::<Ext<SP1Field, SP1ExtensionField>>(lhs, rhs);
247 }
248
249 pub fn assert_ext_ne<
251 LhsExpr: Into<SymbolicExt<SP1Field, SP1ExtensionField>>,
252 RhsExpr: Into<SymbolicExt<SP1Field, SP1ExtensionField>>,
253 >(
254 &mut self,
255 lhs: LhsExpr,
256 rhs: RhsExpr,
257 ) {
258 self.assert_ne::<Ext<SP1Field, SP1ExtensionField>>(lhs, rhs);
259 }
260
261 pub fn print_debug(&mut self, val: usize) {
262 let constant = self.eval(C::N::from_canonical_usize(val));
263 self.print_v(constant);
264 }
265
266 pub fn print_v(&mut self, dst: Var<C::N>) {
268 self.push_op(DslIr::PrintV(dst));
269 }
270
271 pub fn print_f(&mut self, dst: Felt<SP1Field>) {
273 self.push_op(DslIr::PrintF(dst));
274 }
275
276 pub fn print_e(&mut self, dst: Ext<SP1Field, SP1ExtensionField>) {
278 self.push_op(DslIr::PrintE(dst));
279 }
280
281 pub fn witness_var(&mut self) -> Var<C::N> {
282 assert!(!self.is_sub_builder, "Cannot create a witness var with a sub builder");
283 let witness = self.uninit();
284 self.push_op(DslIr::WitnessVar(witness, self.witness_var_count));
285 self.witness_var_count += 1;
286 witness
287 }
288
289 pub fn witness_felt(&mut self) -> Felt<SP1Field> {
290 assert!(!self.is_sub_builder, "Cannot create a witness felt with a sub builder");
291 let witness = self.uninit();
292 self.push_op(DslIr::WitnessFelt(witness, self.witness_felt_count));
293 self.witness_felt_count += 1;
294 witness
295 }
296
297 pub fn witness_ext(&mut self) -> Ext<SP1Field, SP1ExtensionField> {
298 assert!(!self.is_sub_builder, "Cannot create a witness ext with a sub builder");
299 let witness = self.uninit();
300 self.push_op(DslIr::WitnessExt(witness, self.witness_ext_count));
301 self.witness_ext_count += 1;
302 witness
303 }
304
305 pub fn error(&mut self) {
307 self.push_traced_op(DslIr::Error());
308 }
309
310 pub fn commit_public_value(&mut self, val: Felt<SP1Field>) {
312 assert!(!self.is_sub_builder, "Cannot commit to a public value with a sub builder");
313 if self.nb_public_values.is_none() {
314 self.nb_public_values = Some(self.eval(C::N::zero()));
315 }
316 let nb_public_values = *self.nb_public_values.as_ref().unwrap();
317
318 self.push_op(DslIr::Commit(val, nb_public_values));
319 self.assign(nb_public_values, nb_public_values + C::N::one());
320 }
321
322 pub fn commit_vkey_hash_circuit(&mut self, var: Var<C::N>) {
323 self.push_op(DslIr::CircuitCommitVkeyHash(var));
324 }
325
326 pub fn commit_committed_values_digest_circuit(&mut self, var: Var<C::N>) {
327 self.push_op(DslIr::CircuitCommitCommittedValuesDigest(var));
328 }
329
330 pub fn commit_exit_code_circuit(&mut self, var: Var<C::N>) {
331 self.push_op(DslIr::CircuitCommitExitCode(var));
332 }
333
334 pub fn commit_proof_nonce_circuit(&mut self, var: Var<C::N>) {
335 self.push_op(DslIr::CircuitCommitProofNonce(var));
336 }
337
338 pub fn commit_vk_root_circuit(&mut self, var: Var<C::N>) {
339 self.push_op(DslIr::CircuitCommitVkRoot(var));
340 }
341
342 pub fn reduce_e(&mut self, ext: Ext<SP1Field, SP1ExtensionField>) {
343 self.push_op(DslIr::ReduceE(ext));
344 }
345
346 pub fn felt2var_circuit(&mut self, felt: Felt<SP1Field>) -> Var<C::N> {
347 let var = self.uninit();
348 self.push_op(DslIr::CircuitFelt2Var(felt, var));
349 var
350 }
351}