1- use std:: collections:: BTreeMap ;
2- use std:: fmt:: Display ;
3- use std:: fmt:: Formatter ;
4-
5- use p3_field:: PrimeCharacteristicRing ;
6- use p3_field:: PrimeField64 ;
7- use utils:: ToUsize ;
8-
9- use crate :: { F , lang:: ConstExpression } ;
10- use lean_vm:: * ;
11-
12- #[ derive( Debug , Clone ) ]
13- pub struct IntermediateBytecode {
14- pub bytecode : BTreeMap < Label , Vec < IntermediateInstruction > > ,
15- pub match_blocks : Vec < Vec < Vec < IntermediateInstruction > > > ,
16- pub memory_size_per_function : BTreeMap < String , usize > ,
17- }
18-
19- #[ derive( Debug , Clone , PartialEq , Eq ) ]
20- pub enum IntermediateValue {
21- Constant ( ConstExpression ) ,
22- Fp ,
23- MemoryAfterFp { offset : ConstExpression } , // m[fp + offset]
24- }
25-
26- impl From < ConstExpression > for IntermediateValue {
27- fn from ( value : ConstExpression ) -> Self {
28- Self :: Constant ( value)
29- }
30- }
31- impl TryFrom < HighLevelOperation > for Operation {
32- type Error = String ;
33-
34- fn try_from ( value : HighLevelOperation ) -> Result < Self , Self :: Error > {
35- match value {
36- HighLevelOperation :: Add => Ok ( Self :: Add ) ,
37- HighLevelOperation :: Mul => Ok ( Self :: Mul ) ,
38- _ => Err ( format ! ( "Cannot convert {value:?} to +/x" ) ) ,
39- }
40- }
41- }
42-
43- #[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
44- pub enum IntermediaryMemOrFpOrConstant {
45- MemoryAfterFp { offset : ConstExpression } , // m[fp + offset]
46- Fp ,
47- Constant ( ConstExpression ) ,
48- }
49-
50- impl IntermediateValue {
51- pub const fn label ( label : Label ) -> Self {
52- Self :: Constant ( ConstExpression :: label ( label) )
53- }
54-
55- pub const fn is_constant ( & self ) -> bool {
56- matches ! ( self , Self :: Constant ( _) )
57- }
58- }
59-
60- #[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
61- pub enum HighLevelOperation {
62- Add ,
63- Mul ,
64- Sub ,
65- Div , // in the end everything compiles to either Add or Mul
66- Exp , // Exponentiation, only for const expressions
67- Mod , // Modulo, only for const expressions
68- }
69-
70- impl HighLevelOperation {
71- pub fn eval ( & self , a : F , b : F ) -> F {
72- match self {
73- Self :: Add => a + b,
74- Self :: Mul => a * b,
75- Self :: Sub => a - b,
76- Self :: Div => a / b,
77- Self :: Exp => a. exp_u64 ( b. as_canonical_u64 ( ) ) ,
78- Self :: Mod => F :: from_usize ( a. to_usize ( ) % b. to_usize ( ) ) ,
79- }
80- }
81- }
1+ use super :: operation:: HighLevelOperation ;
2+ use super :: value:: { IntermediaryMemOrFpOrConstant , IntermediateValue } ;
3+ use crate :: lang:: ConstExpression ;
4+ use lean_vm:: { Operation , SourceLineNumber } ;
5+ use std:: fmt:: { Display , Formatter } ;
826
7+ /// Core instruction type for the intermediate representation.
838#[ derive( Debug , Clone ) ]
849pub enum IntermediateInstruction {
8510 Computation {
@@ -200,64 +125,9 @@ impl IntermediateInstruction {
200125 }
201126}
202127
203- impl Display for IntermediateValue {
204- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
205- match self {
206- Self :: Constant ( value) => write ! ( f, "{value}" ) ,
207- Self :: Fp => write ! ( f, "fp" ) ,
208- Self :: MemoryAfterFp { offset } => {
209- write ! ( f, "m[fp + {offset}]" )
210- }
211- }
212- }
213- }
214-
215- impl Display for IntermediaryMemOrFpOrConstant {
216- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
217- match self {
218- Self :: MemoryAfterFp { offset } => write ! ( f, "m[fp + {offset}]" ) ,
219- Self :: Fp => write ! ( f, "fp" ) ,
220- Self :: Constant ( c) => write ! ( f, "{c}" ) ,
221- }
222- }
223- }
224-
225128impl Display for IntermediateInstruction {
226129 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
227130 match self {
228- Self :: Deref {
229- shift_0,
230- shift_1,
231- res,
232- } => write ! ( f, "{res} = m[m[fp + {shift_0}] + {shift_1}]" ) ,
233- Self :: DotProduct {
234- arg0,
235- arg1,
236- res,
237- size,
238- } => write ! ( f, "dot_product({arg0}, {arg1}, {res}, {size})" ) ,
239- Self :: MultilinearEval {
240- coeffs,
241- point,
242- res,
243- n_vars,
244- } => write ! ( f, "multilinear_eval({coeffs}, {point}, {res}, {n_vars})" ) ,
245- Self :: DecomposeBits {
246- res_offset,
247- to_decompose,
248- } => {
249- write ! ( f, "m[fp + {res_offset}..] = decompose_bits(" ) ?;
250- for ( i, expr) in to_decompose. iter ( ) . enumerate ( ) {
251- if i > 0 {
252- write ! ( f, ", " ) ?;
253- }
254- write ! ( f, "{expr}" ) ?;
255- }
256- write ! ( f, ")" )
257- }
258- Self :: CounterHint { res_offset } => {
259- write ! ( f, "m[fp + {res_offset}] = counter_hint()" )
260- }
261131 Self :: Computation {
262132 operation,
263133 arg_a,
@@ -266,6 +136,11 @@ impl Display for IntermediateInstruction {
266136 } => {
267137 write ! ( f, "{res} = {arg_a} {operation} {arg_c}" )
268138 }
139+ Self :: Deref {
140+ shift_0,
141+ shift_1,
142+ res,
143+ } => write ! ( f, "{res} = m[m[fp + {shift_0}] + {shift_1}]" ) ,
269144 Self :: Panic => write ! ( f, "panic" ) ,
270145 Self :: Jump { dest, updated_fp } => {
271146 if let Some ( fp) = updated_fp {
@@ -291,6 +166,18 @@ impl Display for IntermediateInstruction {
291166 Self :: Poseidon2_24 { arg_a, arg_b, res } => {
292167 write ! ( f, "{res} = poseidon2_24({arg_a}, {arg_b})" )
293168 }
169+ Self :: DotProduct {
170+ arg0,
171+ arg1,
172+ res,
173+ size,
174+ } => write ! ( f, "dot_product({arg0}, {arg1}, {res}, {size})" ) ,
175+ Self :: MultilinearEval {
176+ coeffs,
177+ point,
178+ res,
179+ n_vars,
180+ } => write ! ( f, "multilinear_eval({coeffs}, {point}, {res}, {n_vars})" ) ,
294181 Self :: Inverse { arg, res_offset } => {
295182 write ! ( f, "m[fp + {res_offset}] = inverse({arg})" )
296183 }
@@ -309,6 +196,22 @@ impl Display for IntermediateInstruction {
309196 write ! ( f, "m[fp + {offset}] = request_memory({size})" )
310197 }
311198 }
199+ Self :: DecomposeBits {
200+ res_offset,
201+ to_decompose,
202+ } => {
203+ write ! ( f, "m[fp + {res_offset}..] = decompose_bits(" ) ?;
204+ for ( i, expr) in to_decompose. iter ( ) . enumerate ( ) {
205+ if i > 0 {
206+ write ! ( f, ", " ) ?;
207+ }
208+ write ! ( f, "{expr}" ) ?;
209+ }
210+ write ! ( f, ")" )
211+ }
212+ Self :: CounterHint { res_offset } => {
213+ write ! ( f, "m[fp + {res_offset}] = counter_hint()" )
214+ }
312215 Self :: Print { line_info, content } => {
313216 write ! ( f, "print {line_info}: " ) ?;
314217 for ( i, c) in content. iter ( ) . enumerate ( ) {
@@ -323,41 +226,3 @@ impl Display for IntermediateInstruction {
323226 }
324227 }
325228}
326-
327- impl Display for HighLevelOperation {
328- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
329- match self {
330- Self :: Add => write ! ( f, "+" ) ,
331- Self :: Mul => write ! ( f, "*" ) ,
332- Self :: Sub => write ! ( f, "-" ) ,
333- Self :: Div => write ! ( f, "/" ) ,
334- Self :: Exp => write ! ( f, "**" ) ,
335- Self :: Mod => write ! ( f, "%" ) ,
336- }
337- }
338- }
339-
340- impl Display for IntermediateBytecode {
341- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
342- for ( label, instructions) in & self . bytecode {
343- writeln ! ( f, "\n {label}:" ) ?;
344- for instruction in instructions {
345- writeln ! ( f, " {instruction}" ) ?;
346- }
347- }
348- for ( i, match_blocks) in self . match_blocks . iter ( ) . enumerate ( ) {
349- writeln ! ( f, "\n Match {i}:" ) ?;
350- for ( j, case) in match_blocks. iter ( ) . enumerate ( ) {
351- writeln ! ( f, " Case {j}:" ) ?;
352- for instruction in case {
353- writeln ! ( f, " {instruction}" ) ?;
354- }
355- }
356- }
357- writeln ! ( f, "\n Memory size per function:" ) ?;
358- for ( function_name, size) in & self . memory_size_per_function {
359- writeln ! ( f, "{function_name}: {size}" ) ?;
360- }
361- Ok ( ( ) )
362- }
363- }
0 commit comments