sp1_recursion_compiler/ir/
ptr.rs

1use core::ops::{Add, Sub};
2
3use p3_field::Field;
4
5use super::{Builder, Config, DslIr, MemIndex, MemVariable, SymbolicVar, Usize, Var, Variable};
6
7/// A point to a location in memory.
8#[derive(Debug, Clone, Copy)]
9pub struct Ptr<N> {
10    pub address: Var<N>,
11}
12
13pub struct SymbolicPtr<N: Field> {
14    pub address: SymbolicVar<N>,
15}
16
17impl<C: Config> Builder<C> {
18    /// Allocates an array on the heap.
19    pub(crate) fn alloc(&mut self, len: Usize<C::N>, size: usize) -> Ptr<C::N> {
20        let ptr = Ptr::uninit(self);
21        self.push_op(DslIr::Alloc(ptr, len, size));
22        ptr
23    }
24
25    /// Loads a value from memory.
26    pub fn load<V: MemVariable<C>>(&mut self, var: V, ptr: Ptr<C::N>, index: MemIndex<C::N>) {
27        var.load(ptr, index, self);
28    }
29
30    /// Stores a value to memory.
31    pub fn store<V: MemVariable<C>>(&mut self, ptr: Ptr<C::N>, index: MemIndex<C::N>, value: V) {
32        value.store(ptr, index, self);
33    }
34}
35
36impl<C: Config> Variable<C> for Ptr<C::N> {
37    type Expression = SymbolicPtr<C::N>;
38
39    fn uninit(builder: &mut Builder<C>) -> Self {
40        Ptr { address: Var::uninit(builder) }
41    }
42
43    fn assign(&self, src: Self::Expression, builder: &mut Builder<C>) {
44        self.address.assign(src.address, builder);
45    }
46
47    fn assert_eq(
48        lhs: impl Into<Self::Expression>,
49        rhs: impl Into<Self::Expression>,
50        builder: &mut Builder<C>,
51    ) {
52        Var::assert_eq(lhs.into().address, rhs.into().address, builder);
53    }
54
55    fn assert_ne(
56        lhs: impl Into<Self::Expression>,
57        rhs: impl Into<Self::Expression>,
58        builder: &mut Builder<C>,
59    ) {
60        Var::assert_ne(lhs.into().address, rhs.into().address, builder);
61    }
62}
63
64impl<C: Config> MemVariable<C> for Ptr<C::N> {
65    fn size_of() -> usize {
66        1
67    }
68
69    fn load(&self, ptr: Ptr<C::N>, index: MemIndex<C::N>, builder: &mut Builder<C>) {
70        self.address.load(ptr, index, builder);
71    }
72
73    fn store(&self, ptr: Ptr<<C as Config>::N>, index: MemIndex<C::N>, builder: &mut Builder<C>) {
74        self.address.store(ptr, index, builder);
75    }
76}
77
78impl<N: Field> From<Ptr<N>> for SymbolicPtr<N> {
79    fn from(ptr: Ptr<N>) -> Self {
80        SymbolicPtr { address: SymbolicVar::from(ptr.address) }
81    }
82}
83
84impl<N: Field> Add for Ptr<N> {
85    type Output = SymbolicPtr<N>;
86
87    fn add(self, rhs: Self) -> Self::Output {
88        SymbolicPtr { address: self.address + rhs.address }
89    }
90}
91
92impl<N: Field> Sub for Ptr<N> {
93    type Output = SymbolicPtr<N>;
94
95    fn sub(self, rhs: Self) -> Self::Output {
96        SymbolicPtr { address: self.address - rhs.address }
97    }
98}
99
100impl<N: Field> Add for SymbolicPtr<N> {
101    type Output = Self;
102
103    fn add(self, rhs: Self) -> Self {
104        Self { address: self.address + rhs.address }
105    }
106}
107
108impl<N: Field> Sub for SymbolicPtr<N> {
109    type Output = Self;
110
111    fn sub(self, rhs: Self) -> Self {
112        Self { address: self.address - rhs.address }
113    }
114}
115
116impl<N: Field> Add<Ptr<N>> for SymbolicPtr<N> {
117    type Output = Self;
118
119    fn add(self, rhs: Ptr<N>) -> Self {
120        Self { address: self.address + rhs.address }
121    }
122}
123
124impl<N: Field> Sub<Ptr<N>> for SymbolicPtr<N> {
125    type Output = Self;
126
127    fn sub(self, rhs: Ptr<N>) -> Self {
128        Self { address: self.address - rhs.address }
129    }
130}
131
132impl<N: Field> Add<SymbolicPtr<N>> for Ptr<N> {
133    type Output = SymbolicPtr<N>;
134
135    fn add(self, rhs: SymbolicPtr<N>) -> SymbolicPtr<N> {
136        SymbolicPtr { address: self.address + rhs.address }
137    }
138}
139
140impl<N: Field> Add<SymbolicVar<N>> for Ptr<N> {
141    type Output = SymbolicPtr<N>;
142
143    fn add(self, rhs: SymbolicVar<N>) -> SymbolicPtr<N> {
144        SymbolicPtr { address: self.address + rhs }
145    }
146}
147
148impl<N: Field> Sub<SymbolicVar<N>> for Ptr<N> {
149    type Output = SymbolicPtr<N>;
150
151    fn sub(self, rhs: SymbolicVar<N>) -> SymbolicPtr<N> {
152        SymbolicPtr { address: self.address - rhs }
153    }
154}
155
156impl<N: Field> Sub<SymbolicPtr<N>> for Ptr<N> {
157    type Output = SymbolicPtr<N>;
158
159    fn sub(self, rhs: SymbolicPtr<N>) -> SymbolicPtr<N> {
160        SymbolicPtr { address: self.address - rhs.address }
161    }
162}
163
164impl<N: Field> Add<Usize<N>> for Ptr<N> {
165    type Output = SymbolicPtr<N>;
166
167    fn add(self, rhs: Usize<N>) -> SymbolicPtr<N> {
168        match rhs {
169            Usize::Const(rhs) => {
170                SymbolicPtr { address: self.address + N::from_canonical_usize(rhs) }
171            }
172            Usize::Var(rhs) => SymbolicPtr { address: self.address + rhs },
173        }
174    }
175}
176
177impl<N: Field> Add<Usize<N>> for SymbolicPtr<N> {
178    type Output = SymbolicPtr<N>;
179
180    fn add(self, rhs: Usize<N>) -> SymbolicPtr<N> {
181        match rhs {
182            Usize::Const(rhs) => {
183                SymbolicPtr { address: self.address + N::from_canonical_usize(rhs) }
184            }
185            Usize::Var(rhs) => SymbolicPtr { address: self.address + rhs },
186        }
187    }
188}
189
190impl<N: Field> Sub<Usize<N>> for Ptr<N> {
191    type Output = SymbolicPtr<N>;
192
193    fn sub(self, rhs: Usize<N>) -> SymbolicPtr<N> {
194        match rhs {
195            Usize::Const(rhs) => {
196                SymbolicPtr { address: self.address - N::from_canonical_usize(rhs) }
197            }
198            Usize::Var(rhs) => SymbolicPtr { address: self.address - rhs },
199        }
200    }
201}
202
203impl<N: Field> Sub<Usize<N>> for SymbolicPtr<N> {
204    type Output = SymbolicPtr<N>;
205
206    fn sub(self, rhs: Usize<N>) -> SymbolicPtr<N> {
207        match rhs {
208            Usize::Const(rhs) => {
209                SymbolicPtr { address: self.address - N::from_canonical_usize(rhs) }
210            }
211            Usize::Var(rhs) => SymbolicPtr { address: self.address - rhs },
212        }
213    }
214}