cairo_lang_executable/
executable.rs1use cairo_lang_casm::assembler::AssembledCairoProgram;
2use cairo_lang_casm::casm;
3use cairo_vm::types::builtin_name::BuiltinName;
4use itertools::chain;
5use serde::{Deserialize, Serialize};
6
7use crate::compile::CompiledFunction;
8use crate::debug_info::{Annotations, DebugInfo, ProgramInformation};
9
10pub const NOT_RETURNING_HEADER_SIZE: usize = 6;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct Executable {
15 pub program: AssembledCairoProgram,
17 pub entrypoints: Vec<ExecutableEntryPoint>,
19 #[serde(skip_serializing_if = "Option::is_none")]
21 pub debug_info: Option<DebugInfo>,
22}
23
24impl Executable {
25 pub fn new(compiled: CompiledFunction) -> Self {
27 let non_returning_header = casm! {
28 ap += (compiled.wrapper.builtins.len());
29 call rel 4;
30 jmp rel 0;
31 };
32 assert_eq!(non_returning_header.current_code_offset, NOT_RETURNING_HEADER_SIZE);
33 Self {
34 program: compiled.program.assemble_ex(
35 chain!(&non_returning_header.instructions, &compiled.wrapper.header),
36 &compiled.wrapper.footer,
37 ),
38 entrypoints: vec![
39 ExecutableEntryPoint {
40 builtins: compiled.wrapper.builtins.clone(),
41 offset: 0,
42 kind: EntryPointKind::Standalone,
43 },
44 ExecutableEntryPoint {
45 builtins: compiled.wrapper.builtins,
46 offset: NOT_RETURNING_HEADER_SIZE,
47 kind: EntryPointKind::Bootloader,
48 },
49 ],
50 debug_info: Some(DebugInfo {
51 annotations: Annotations::from(ProgramInformation {
52 program_offset: NOT_RETURNING_HEADER_SIZE
53 + compiled
54 .wrapper
55 .header
56 .iter()
57 .map(|inst| inst.body.op_size())
58 .sum::<usize>(),
59 }),
60 }),
61 }
62 }
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct ExecutableEntryPoint {
68 pub builtins: Vec<BuiltinName>,
70 pub offset: usize,
72 pub kind: EntryPointKind,
74}
75
76#[derive(Debug, Clone, Serialize, PartialEq, Deserialize)]
78pub enum EntryPointKind {
79 Bootloader,
83 Standalone,
88}