Skip to content

Commit 51b7e5c

Browse files
Create Program2 type
1 parent f97267f commit 51b7e5c

File tree

1 file changed

+73
-91
lines changed

1 file changed

+73
-91
lines changed

vm/src/vm/runners/cairo_runner_2.rs

+73-91
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@
22

33
use core::any::Any;
44

5-
use cairo_lang_executable::executable::{EntryPointKind, Executable, ExecutableEntryPoint};
6-
75
use crate::{
86
hint_processor::hint_processor_definition::{HintProcessor, HintReference},
9-
serde::deserialize_program::{Attribute, HintParams, Identifier, InstructionLocation},
7+
serde::deserialize_program::HintParams,
108
stdlib::{
119
collections::{BTreeMap, HashMap, HashSet},
12-
mem,
1310
prelude::*,
1411
},
1512
types::{
1613
builtin_name::BuiltinName,
14+
errors::program_errors::ProgramError,
1715
exec_scope::ExecutionScopes,
1816
layout::CairoLayout,
1917
program::HintsCollection,
@@ -34,6 +32,52 @@ use crate::{
3432
Felt252,
3533
};
3634

35+
/// This type is originally defined in `cairo-lang-executable`.
36+
/// We redefine it here to avoid a cyclic dependencies.
37+
#[derive(Debug)]
38+
pub struct ExecutableEntryPoint {
39+
pub builtins: Vec<BuiltinName>,
40+
pub offset: usize,
41+
pub kind: EntryPointKind,
42+
}
43+
44+
/// This type is originally defined in `cairo-lang-executable`.
45+
/// We redefine it here to avoid a cyclic dependencies.
46+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47+
pub enum EntryPointKind {
48+
Bootloader,
49+
Standalone,
50+
}
51+
52+
pub struct Program2 {
53+
pub bytecode: Vec<MaybeRelocatable>,
54+
pub hints_collection: HintsCollection,
55+
pub entrypoint: ExecutableEntryPoint,
56+
57+
pub reference_manager: Vec<HintReference>,
58+
pub constants: HashMap<String, Felt252>,
59+
}
60+
61+
impl Program2 {
62+
pub fn new(
63+
bytecode: Vec<MaybeRelocatable>,
64+
hints: BTreeMap<usize, Vec<HintParams>>,
65+
entrypoint: ExecutableEntryPoint,
66+
reference_manager: Vec<HintReference>,
67+
constants: HashMap<String, Felt252>,
68+
) -> Result<Program2, ProgramError> {
69+
let hints_collection = HintsCollection::new(&hints, bytecode.len())?;
70+
71+
Ok(Self {
72+
bytecode,
73+
hints_collection,
74+
entrypoint,
75+
reference_manager,
76+
constants,
77+
})
78+
}
79+
}
80+
3781
#[allow(dead_code)]
3882
pub struct CairoRunner2 {
3983
vm: VirtualMachine,
@@ -43,74 +87,39 @@ pub struct CairoRunner2 {
4387
execution_scopes: ExecutionScopes,
4488

4589
// Configuration
46-
executable: Executable,
47-
entrypoint_kind: EntryPointKind,
90+
program: Program2,
4891
layout: CairoLayout,
49-
trace_enabled: bool,
50-
constants: HashMap<String, Felt252>,
51-
error_message_attributes: Vec<Attribute>,
52-
instruction_locations: Option<HashMap<usize, InstructionLocation>>,
53-
identifiers: HashMap<String, Identifier>,
54-
reference_manager: Vec<HintReference>,
55-
56-
// Preprocessed Data
57-
hint_collection: HintsCollection,
5892
}
5993

6094
impl CairoRunner2 {
6195
#[allow(clippy::too_many_arguments)]
6296
pub fn new(
63-
executable: Executable,
64-
entrypoint_kind: EntryPointKind,
97+
program: Program2,
6598
layout: CairoLayout,
6699
trace_enabled: bool,
67-
constants: HashMap<String, Felt252>,
68-
error_message_attributes: Vec<Attribute>,
69-
instruction_locations: Option<HashMap<usize, InstructionLocation>>,
70-
identifiers: HashMap<String, Identifier>,
71-
reference_manager: Vec<HintReference>,
72-
hints: BTreeMap<usize, Vec<HintParams>>,
73100
) -> Result<Self, RunnerError> {
74-
// =============
75-
// PREPROCESSING
76-
// =============
77-
78-
let entrypoint = find_entrypoint_of_kind(&executable.entrypoints, entrypoint_kind.clone());
79-
80-
let bytecode = executable
81-
.program
82-
.bytecode
83-
.iter()
84-
.map(Felt252::from)
85-
.map(MaybeRelocatable::from)
86-
.collect::<Vec<_>>();
87-
88-
let hint_collection =
89-
HintsCollection::new(&hints, bytecode.len()).expect("failed to build hint collection");
90-
91-
let builtins = get_entrypoint_builtins(entrypoint);
92-
93101
// ==============
94102
// INITIALIZATION
95103
// ==============
96104

97105
let mut vm = VirtualMachine::new(trace_enabled, false);
98106

99-
check_builtin_order(&builtins)?;
100-
vm.builtin_runners = initialize_builtin_runners(&layout, &builtins, true, true)?;
107+
check_builtin_order(&(&program.entrypoint).builtins)?;
108+
vm.builtin_runners =
109+
initialize_builtin_runners(&layout, &program.entrypoint.builtins, true, true)?;
101110

102111
let program_base = vm.add_memory_segment();
103112
let execution_base = vm.add_memory_segment();
104113

105114
initialize_builtin_runner_segments(&mut vm.builtin_runners, &mut vm.segments);
106115

107-
load_program(&mut vm, program_base, &bytecode)?;
116+
load_program(&mut vm, program_base, &program.bytecode)?;
108117

109118
let mut stack = Vec::new();
110119

111-
let initial_pc = (program_base + entrypoint.offset)?;
120+
let initial_pc = (program_base + (&program.entrypoint).offset)?;
112121

113-
let (initial_fp, final_pc) = match entrypoint_kind {
122+
let (initial_fp, final_pc) = match (&program.entrypoint).kind {
114123
EntryPointKind::Bootloader => {
115124
// On bootloader, we execute until control flow is returned.
116125
// The stack is arranged as if we are at the start of a function call.
@@ -125,7 +134,11 @@ impl CairoRunner2 {
125134
//
126135
// The initial fp variable points to the cell after the return pc.
127136

128-
extend_stack_with_builtins(&mut stack, &builtins, &vm.builtin_runners);
137+
extend_stack_with_builtins(
138+
&mut stack,
139+
&program.entrypoint.builtins,
140+
&vm.builtin_runners,
141+
);
129142

130143
let return_fp = vm.add_memory_segment();
131144
let return_pc = vm.add_memory_segment();
@@ -154,7 +167,11 @@ impl CairoRunner2 {
154167

155168
let stack_prefix = &[MaybeRelocatable::Int(Felt252::ZERO)];
156169
stack.extend_from_slice(stack_prefix);
157-
extend_stack_with_builtins(&mut stack, &builtins, &vm.builtin_runners);
170+
extend_stack_with_builtins(
171+
&mut stack,
172+
&program.entrypoint.builtins,
173+
&vm.builtin_runners,
174+
);
158175

159176
let final_pc = (initial_pc + 4)?;
160177
let initial_fp = (execution_base + stack_prefix.len())?;
@@ -172,21 +189,13 @@ impl CairoRunner2 {
172189
add_builtin_validation_rules(&mut vm.segments.memory, &mut vm.builtin_runners)?;
173190

174191
Ok(Self {
175-
executable,
176192
vm,
177193
program_base,
178194
execution_base,
179195
final_pc,
180196
execution_scopes: ExecutionScopes::new(),
181-
entrypoint_kind,
197+
program,
182198
layout,
183-
trace_enabled,
184-
constants,
185-
error_message_attributes,
186-
instruction_locations,
187-
identifiers,
188-
reference_manager,
189-
hint_collection,
190199
})
191200
}
192201

@@ -196,20 +205,21 @@ impl CairoRunner2 {
196205
) -> Result<(), VirtualMachineError> {
197206
#[cfg_attr(not(feature = "extensive_hints"), allow(unused_mut))]
198207
let mut hint_data = get_hint_data(
199-
&self.hint_collection,
200-
&self.reference_manager,
208+
&self.program.hints_collection,
209+
&self.program.reference_manager,
201210
hint_processor,
202211
)?;
203212

204213
#[cfg(feature = "extensive_hints")]
205-
let mut hint_ranges = self.hint_collection.hints_ranges.clone();
214+
let mut hint_ranges = self.program.hints_collection.hints_ranges.clone();
206215

207216
while self.vm.get_pc() != self.final_pc && !hint_processor.consumed() {
208217
#[cfg(feature = "extensive_hints")]
209218
let hint_data = &mut hint_data;
210219
#[cfg(not(feature = "extensive_hints"))]
211220
let hint_data = self
212-
.hint_collection
221+
.program
222+
.hints_collection
213223
.get_hint_range_for_pc(self.vm.get_pc().offset)
214224
.and_then(|range| {
215225
range.and_then(|(start, length)| hint_data.get(start..start + length.get()))
@@ -222,7 +232,7 @@ impl CairoRunner2 {
222232
hint_data,
223233
#[cfg(feature = "extensive_hints")]
224234
&mut hint_ranges,
225-
&self.constants,
235+
&self.program.constants,
226236
)?;
227237

228238
hint_processor.consume_step();
@@ -236,19 +246,6 @@ impl CairoRunner2 {
236246
}
237247
}
238248

239-
fn find_entrypoint_of_kind(
240-
entrypoints: &[ExecutableEntryPoint],
241-
entrypoint_kind: EntryPointKind,
242-
) -> &ExecutableEntryPoint {
243-
entrypoints
244-
.iter()
245-
.find(|entrypoint| {
246-
// TODO: Use `Eq` once implemented on `EntryPointKind`.
247-
mem::discriminant(&entrypoint.kind) == mem::discriminant(&entrypoint_kind)
248-
})
249-
.expect("executable had no entrypoint of required kind")
250-
}
251-
252249
pub fn check_builtin_order(builtins: &[BuiltinName]) -> Result<(), RunnerError> {
253250
let ordered_builtins = vec![
254251
BuiltinName::output,
@@ -465,18 +462,3 @@ fn get_hint_data(
465462
})
466463
.collect()
467464
}
468-
469-
/// TODO: Remove this once cyclic dependency is fixed.
470-
/// It should not be necessary, but cargo treats executable BuiltinName as a separate type
471-
/// which is why I had to create this adapter function.
472-
pub fn get_entrypoint_builtins(entrypoint: &ExecutableEntryPoint) -> Vec<BuiltinName> {
473-
let mut builtins = Vec::with_capacity(entrypoint.builtins.len());
474-
475-
for builtin in &entrypoint.builtins {
476-
let adapted_builtin = BuiltinName::from_str(builtin.to_str())
477-
.expect("should never fail under the same implementation");
478-
builtins.push(adapted_builtin);
479-
}
480-
481-
builtins
482-
}

0 commit comments

Comments
 (0)