Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
memory_manager.cpp
Go to the documentation of this file.
5
6using namespace bb::avm2::testing;
7
8namespace {
9
20template <std::ranges::input_range Range, typename Predicate>
21std::optional<std::ranges::range_value_t<Range>> get_nth_filtered(Range&& range, Predicate predicate, size_t index)
22{
23 auto filtered = range | std::views::filter(predicate);
24
25 auto count = std::ranges::distance(filtered);
26 if (count == 0) {
27 return std::nullopt;
28 }
29
30 return *std::ranges::next(filtered.begin(), static_cast<long>(index % static_cast<size_t>(count)));
31}
32
33uint32_t get_max_variable_address(AddressingMode mode, uint32_t literal_max_value)
34{
36 return literal_max_value;
37 }
38 // In relative addressing, and indirect addressing, we can reach any variable address.
40}
41
42uint32_t trimmed_pointer_address(uint32_t pointer_address_seed, uint32_t max_operand_address)
43{
44 return pointer_address_seed % (max_operand_address + 1);
45}
46
47uint32_t trimmed_relative_operand_address(uint32_t base_offset_seed,
48 uint32_t relative_target,
49 uint32_t max_operand_address)
50{
51 uint32_t max_operand = std::min(relative_target, max_operand_address);
52 return (base_offset_seed % (max_operand + 1));
53}
54
55uint32_t trimmed_base_pointer(uint32_t base_offset_seed, uint32_t relative_target, uint32_t max_operand_address)
56{
57 return relative_target - trimmed_relative_operand_address(base_offset_seed, relative_target, max_operand_address);
58}
59
60} // namespace
61
63{
64 if (this != &other) {
67 }
68 return *this;
69}
70
75
77{
78 // if address is already set
80 auto stored_tag = memory_address_to_tag[address];
81 // if address is already set to the same tag, do nothing
82 if (stored_tag == tag) {
83 return;
84 }
85 // if address is already set to different tag, remove address from stored_variables
86 stored_variables[stored_tag].erase(
87 std::remove(stored_variables[stored_tag].begin(), stored_variables[stored_tag].end(), address),
88 stored_variables[stored_tag].end());
89 }
91 stored_variables[tag].push_back(address);
92}
93
95 uint32_t absolute_address,
96 uint32_t max_operand_address)
97{
98 ResolvedAddress resolved_address = {
99 .absolute_address = absolute_address,
100 };
101 switch (variable.mode) {
103 uint32_t trimmed_pointer_address_value =
104 trimmed_pointer_address(variable.pointer_address_seed, max_operand_address);
105 resolved_address.pointer_address = trimmed_pointer_address_value;
106 resolved_address.operand_address = trimmed_pointer_address_value;
107 break;
108 }
110 resolved_address.base_pointer =
111 trimmed_base_pointer(variable.base_offset_seed, absolute_address, max_operand_address);
112 resolved_address.operand_address =
113 trimmed_relative_operand_address(variable.base_offset_seed, absolute_address, max_operand_address);
114 break;
116 resolved_address.pointer_address = variable.pointer_address_seed;
117 // Relative addressing target is the pointer
118 resolved_address.base_pointer =
119 trimmed_base_pointer(variable.base_offset_seed, variable.pointer_address_seed, max_operand_address);
120 resolved_address.operand_address = trimmed_relative_operand_address(
121 variable.base_offset_seed, variable.pointer_address_seed, max_operand_address);
122 break;
124 // We can't change the absolute address, or it won't find anything useful there.
125 resolved_address.operand_address = absolute_address;
126 break;
127 }
128 return resolved_address;
129}
130
132{
133
134 ResolvedAddress resolved_address = {
135 .absolute_address = address.address,
136 };
137 switch (address.mode) {
139 // Trim the pointer to 16 bits for it to be writable by SET_32
140 uint32_t trimmed_pointer_address_value =
141 trimmed_pointer_address(address.pointer_address_seed, max_operand_address);
142 resolved_address.pointer_address = trimmed_pointer_address_value;
143 resolved_address.operand_address = trimmed_pointer_address_value;
144 break;
145 }
147 resolved_address.base_pointer =
148 trimmed_base_pointer(address.base_offset_seed, resolved_address.absolute_address, max_operand_address);
149 resolved_address.operand_address = trimmed_relative_operand_address(
150 address.base_offset_seed, resolved_address.absolute_address, max_operand_address);
151 break;
153 resolved_address.pointer_address = address.pointer_address_seed;
154 // Relative addressing target is the pointer
155 resolved_address.base_pointer =
156 trimmed_base_pointer(address.base_offset_seed, address.pointer_address_seed, max_operand_address);
157 resolved_address.operand_address = trimmed_relative_operand_address(
158 address.base_offset_seed, address.pointer_address_seed, max_operand_address);
159 break;
161 // Do not delete this assert, if it fails, it means that some address was generated / mutated incorrectly in
162 // instruction.cpp. Check all the `max_operand` parameters that you're passing to generate_address_ref.
163 BB_ASSERT_LTE(address.address, max_operand_address);
164 resolved_address.operand_address = resolved_address.absolute_address;
165 break;
166 }
167 return resolved_address;
168}
169
171{
172 switch (mode) {
174 operand = operand.indirect();
175 break;
177 operand = operand.relative();
178 break;
180 operand = operand.indirect();
181 operand = operand.relative();
182 break;
184 break;
185 }
186 return operand;
187}
188
196
199{
200 auto actual_address = get_variable_address(address.tag, address.index, get_max_variable_address(address.mode, 255));
201 if (!actual_address.has_value()) {
202 return std::nullopt;
203 }
204 auto resolved_address = resolve_address(address, actual_address.value(), 255);
205
206 BB_ASSERT_LTE(resolved_address.operand_address, uint32_t{ 255 });
207
208 auto operand = OperandBuilder::from<uint8_t>(static_cast<uint8_t>(resolved_address.operand_address));
209
210 return std::make_pair(resolved_address, get_memory_address_operand(operand, address.mode));
211}
212
215{
216 auto resolved_address = resolve_address(address, 255);
217 auto operand = OperandBuilder::from<uint8_t>(static_cast<uint8_t>(resolved_address.operand_address));
218 return std::make_pair(resolved_address, get_memory_address_operand(operand, address.mode));
219}
220
228
231{
232 auto actual_address =
233 get_variable_address(address.tag, address.index, get_max_variable_address(address.mode, 65535));
234 if (!actual_address.has_value()) {
235 return std::nullopt;
236 }
237
238 auto resolved_address = resolve_address(address, actual_address.value(), 65535);
239
240 BB_ASSERT_LTE(resolved_address.operand_address, uint32_t{ 65535 });
241 auto operand = OperandBuilder::from<uint16_t>(static_cast<uint16_t>(resolved_address.operand_address));
242 return std::make_pair(resolved_address, get_memory_address_operand(operand, address.mode));
243}
244
247{
248 auto resolved_address = resolve_address(address, 65535);
249 auto operand = OperandBuilder::from<uint16_t>(static_cast<uint16_t>(resolved_address.operand_address));
250 return std::make_pair(resolved_address, get_memory_address_operand(operand, address.mode));
251}
252
254{
255 return get_nth_filtered(this->stored_variables[tag], [max_value](uint32_t val) { return val <= max_value; }, index);
256}
257
259{
260 auto value = get_variable_address(tag, index, 255);
261 if (!value.has_value()) {
262 return std::nullopt;
263 }
264 BB_ASSERT_LTE(value.value(), uint8_t{ 255 });
265 return static_cast<uint8_t>(value.value());
266}
267
269{
270 auto value = get_variable_address(tag, index, 65535);
271 if (!value.has_value()) {
272 return std::nullopt;
273 }
274 BB_ASSERT_LTE(value.value(), uint16_t{ 65535 });
275 return static_cast<uint16_t>(value.value());
276}
277
282
284{
285 if (storage_addresses.empty()) {
286 return std::nullopt;
287 }
288 return storage_addresses[slot_offset_index % storage_addresses.size()];
289}
290
295
297{
298 if (emitted_note_hashes.empty()) {
299 return std::nullopt;
300 }
301 return emitted_note_hashes[note_hash_index % emitted_note_hashes.size()];
302}
303
305{
306 if (emitted_note_hashes.empty()) {
307 return std::nullopt;
308 }
309 return note_hash_index % emitted_note_hashes.size();
310}
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:168
#define AVM_HIGHEST_MEM_ADDRESS
bb::avm2::testing::OperandBuilder get_memory_address_operand(bb::avm2::testing::OperandBuilder operand, AddressingMode mode)
std::optional< uint16_t > get_memory_offset_16(bb::avm2::MemoryTag tag, uint32_t address_index)
std::map< bb::avm2::MemoryTag, std::vector< uint32_t > > stored_variables
MemoryManager & operator=(const MemoryManager &other)
std::optional< std::pair< ResolvedAddress, bb::avm2::testing::OperandBuilder > > get_resolved_address_and_operand_8(ParamRef address)
std::vector< bb::avm2::FF > emitted_note_hashes
std::optional< bb::avm2::FF > get_emitted_note_hash(uint16_t note_hash_index)
std::map< uint32_t, bb::avm2::MemoryTag > memory_address_to_tag
ResolvedAddress resolve_address(VariableRef address, uint32_t absolute_address, uint32_t max_operand_address)
std::optional< bb::avm2::FF > get_slot(uint16_t slot_offset_index)
bool is_memory_address_set(uint16_t address)
std::optional< uint16_t > get_leaf_index(uint16_t note_hash_index)
void set_memory_address(bb::avm2::MemoryTag tag, uint32_t address)
void append_slot(bb::avm2::FF slot)
std::optional< uint32_t > get_variable_address(bb::avm2::MemoryTag tag, uint32_t index, uint32_t max_value)
std::optional< uint8_t > get_memory_offset_8(bb::avm2::MemoryTag tag, uint32_t address_index)
void append_emitted_note_hash(bb::avm2::FF note_hash)
std::vector< bb::avm2::FF > storage_addresses
std::optional< std::pair< ResolvedAddress, bb::avm2::testing::OperandBuilder > > get_resolved_address_and_operand_16(ParamRef address)
AddressingMode
std::variant< VariableRef, AddressRef > ParamRef
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Output of resolving an address in the memory manager In order to resolve a given absolute address wit...
uint32_t operand_address
std::optional< uint32_t > base_pointer
uint32_t absolute_address
std::optional< uint32_t > pointer_address
AddressingModeWrapper mode
uint32_t base_offset_seed
A seed for the generation of the base offset Used for Relative/IndirectRelative modes only Sets M[0] ...
uint16_t pointer_address_seed
A seed for the generation of the pointer address Used for Indirect/IndirectRelative modes only.