Skip to content

Commit 6e5f40f

Browse files
Create Program2 type
1 parent f97267f commit 6e5f40f

File tree

1 file changed

+76
-98
lines changed

1 file changed

+76
-98
lines changed

vm/src/vm/runners/cairo_runner_2.rs

+76-98
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,35 @@ 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-
93-
// ==============
94-
// INITIALIZATION
95-
// ==============
96-
97101
let mut vm = VirtualMachine::new(trace_enabled, false);
98102

99-
check_builtin_order(&builtins)?;
100-
vm.builtin_runners = initialize_builtin_runners(&layout, &builtins, true, true)?;
103+
check_builtin_order(&(&program.entrypoint).builtins)?;
104+
vm.builtin_runners =
105+
initialize_builtin_runners(&layout, &program.entrypoint.builtins, true, true)?;
101106

102107
let program_base = vm.add_memory_segment();
103108
let execution_base = vm.add_memory_segment();
104109

105110
initialize_builtin_runner_segments(&mut vm.builtin_runners, &mut vm.segments);
106111

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

109114
let mut stack = Vec::new();
110115

111-
let initial_pc = (program_base + entrypoint.offset)?;
116+
let initial_pc = (program_base + program.entrypoint.offset)?;
112117

113-
let (initial_fp, final_pc) = match entrypoint_kind {
118+
let (initial_fp, final_pc) = match program.entrypoint.kind {
114119
EntryPointKind::Bootloader => {
115120
// On bootloader, we execute until control flow is returned.
116121
// The stack is arranged as if we are at the start of a function call.
@@ -125,7 +130,11 @@ impl CairoRunner2 {
125130
//
126131
// The initial fp variable points to the cell after the return pc.
127132

128-
extend_stack_with_builtins(&mut stack, &builtins, &vm.builtin_runners);
133+
extend_stack_with_builtins(
134+
&mut stack,
135+
&program.entrypoint.builtins,
136+
&vm.builtin_runners,
137+
);
129138

130139
let return_fp = vm.add_memory_segment();
131140
let return_pc = vm.add_memory_segment();
@@ -154,7 +163,11 @@ impl CairoRunner2 {
154163

155164
let stack_prefix = &[MaybeRelocatable::Int(Felt252::ZERO)];
156165
stack.extend_from_slice(stack_prefix);
157-
extend_stack_with_builtins(&mut stack, &builtins, &vm.builtin_runners);
166+
extend_stack_with_builtins(
167+
&mut stack,
168+
&program.entrypoint.builtins,
169+
&vm.builtin_runners,
170+
);
158171

159172
let final_pc = (initial_pc + 4)?;
160173
let initial_fp = (execution_base + stack_prefix.len())?;
@@ -167,26 +180,18 @@ impl CairoRunner2 {
167180
let run_context = RunContext::new(initial_pc, initial_ap.offset, initial_fp.offset);
168181
vm.set_run_context(run_context);
169182

170-
load_stack(&mut vm, execution_base, stack)?;
183+
load_stack(&mut vm, execution_base, &stack)?;
171184

172185
add_builtin_validation_rules(&mut vm.segments.memory, &mut vm.builtin_runners)?;
173186

174187
Ok(Self {
175-
executable,
176188
vm,
177189
program_base,
178190
execution_base,
179191
final_pc,
180192
execution_scopes: ExecutionScopes::new(),
181-
entrypoint_kind,
193+
program,
182194
layout,
183-
trace_enabled,
184-
constants,
185-
error_message_attributes,
186-
instruction_locations,
187-
identifiers,
188-
reference_manager,
189-
hint_collection,
190195
})
191196
}
192197

@@ -196,20 +201,21 @@ impl CairoRunner2 {
196201
) -> Result<(), VirtualMachineError> {
197202
#[cfg_attr(not(feature = "extensive_hints"), allow(unused_mut))]
198203
let mut hint_data = get_hint_data(
199-
&self.hint_collection,
200-
&self.reference_manager,
204+
&self.program.hints_collection,
205+
&self.program.reference_manager,
201206
hint_processor,
202207
)?;
203208

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

207212
while self.vm.get_pc() != self.final_pc && !hint_processor.consumed() {
208213
#[cfg(feature = "extensive_hints")]
209214
let hint_data = &mut hint_data;
210215
#[cfg(not(feature = "extensive_hints"))]
211216
let hint_data = self
212-
.hint_collection
217+
.program
218+
.hints_collection
213219
.get_hint_range_for_pc(self.vm.get_pc().offset)
214220
.and_then(|range| {
215221
range.and_then(|(start, length)| hint_data.get(start..start + length.get()))
@@ -222,7 +228,7 @@ impl CairoRunner2 {
222228
hint_data,
223229
#[cfg(feature = "extensive_hints")]
224230
&mut hint_ranges,
225-
&self.constants,
231+
&self.program.constants,
226232
)?;
227233

228234
hint_processor.consume_step();
@@ -236,19 +242,6 @@ impl CairoRunner2 {
236242
}
237243
}
238244

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-
252245
pub fn check_builtin_order(builtins: &[BuiltinName]) -> Result<(), RunnerError> {
253246
let ordered_builtins = vec![
254247
BuiltinName::output,
@@ -413,7 +406,7 @@ fn extend_stack_with_builtins(
413406
fn load_program(
414407
vm: &mut VirtualMachine,
415408
program_base: Relocatable,
416-
bytecode: &Vec<MaybeRelocatable>,
409+
bytecode: &[MaybeRelocatable],
417410
) -> Result<(), RunnerError> {
418411
vm.load_data(program_base, bytecode)
419412
.map_err(RunnerError::MemoryInitializationError)?;
@@ -426,7 +419,7 @@ fn load_program(
426419
fn load_stack(
427420
vm: &mut VirtualMachine,
428421
execution_base: Relocatable,
429-
stack: Vec<MaybeRelocatable>,
422+
stack: &[MaybeRelocatable],
430423
) -> Result<(), RunnerError> {
431424
vm.load_data(execution_base, &stack)
432425
.map_err(RunnerError::MemoryInitializationError)?;
@@ -465,18 +458,3 @@ fn get_hint_data(
465458
})
466459
.collect()
467460
}
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)