cairo_lang_executable/executable.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
use cairo_lang_casm::assembler::AssembledCairoProgram;
use cairo_lang_casm::casm;
use cairo_vm::types::builtin_name::BuiltinName;
use itertools::chain;
use serde::{Deserialize, Serialize};
use crate::compile::CompiledFunction;
/// Structure to hold the executable represenstation of a program.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Executable {
/// The bytecode of the program.
pub program: AssembledCairoProgram,
/// The available entrypoints for the program.
pub entrypoints: Vec<ExecutableEntryPoint>,
}
impl Executable {
/// Create a new executable program from a compiled function.
pub fn new(compiled: CompiledFunction) -> Self {
let non_returning_header = casm! {
ap += (compiled.wrapper.builtins.len());
call rel 4;
jmp rel 0;
};
Self {
program: compiled.program.assemble_ex(
chain!(&non_returning_header.instructions, &compiled.wrapper.header),
&compiled.wrapper.footer,
),
entrypoints: vec![
ExecutableEntryPoint {
builtins: compiled.wrapper.builtins.clone(),
offset: 0,
kind: EntryPointKind::NonReturning,
},
ExecutableEntryPoint {
builtins: compiled.wrapper.builtins,
offset: non_returning_header.current_code_offset,
kind: EntryPointKind::Function,
},
],
}
}
}
/// Information about a executable entrypoint.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExecutableEntryPoint {
/// The used builtins of the function.
pub builtins: Vec<BuiltinName>,
/// The offset of the entrypoint in the bytecode.
pub offset: usize,
/// The kind of the entrypoint.
pub kind: EntryPointKind,
}
/// The kind of an entrypoint.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum EntryPointKind {
/// The entrypoint is a function, ending with a `ret`, expecting the builtins as its parameters.
Function,
/// The entrypoint starts with `ap += <builtins.len()>` and expected the builtins to be injected
/// there, and ends with an infinite loop.
NonReturning,
}