Skip to content

Commit

Permalink
Added panic print in executable run.
Browse files Browse the repository at this point in the history
commit-id:2b23af69
  • Loading branch information
orizi committed Jan 21, 2025
1 parent 022c26c commit cb43895
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 38 deletions.
9 changes: 9 additions & 0 deletions crates/bin/cairo-execute/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use cairo_lang_compiler::diagnostics::DiagnosticsReporter;
use cairo_lang_compiler::project::check_compiler_path;
use cairo_lang_executable::compile::compile_executable;
use cairo_lang_executable::executable::{EntryPointKind, Executable};
use cairo_lang_runner::casm_run::format_for_panic;
use cairo_lang_runner::{Arg, CairoHintProcessor, build_hints_dict};
use cairo_lang_utils::bigint::BigUintAsHex;
use cairo_vm::cairo_run::{CairoRunConfig, cairo_run_program};
Expand Down Expand Up @@ -225,6 +226,7 @@ fn main() -> anyhow::Result<()> {
run_resources: Default::default(),
syscalls_used_resources: Default::default(),
no_temporary_segments: false,
markers: Default::default(),
};

let cairo_run_config = CairoRunConfig {
Expand All @@ -243,6 +245,13 @@ fn main() -> anyhow::Result<()> {
let mut output_buffer = "Program Output:\n".to_string();
runner.vm.write_output(&mut output_buffer)?;
print!("{output_buffer}");
if let [start_marker, end_marker] = &hint_processor.markers[..] {
let size = (*end_marker - *start_marker).with_context(|| {
format!("Failed calculating size between markers start={start_marker}, end={end_marker}")
})?;
let panic_data = runner.vm.get_integer_range(*start_marker, size).with_context(||"Failed reading panic data.")?;
println!("{}", format_for_panic(panic_data.into_iter().map(|v| v.as_ref().clone())));
}
}

if let Some(trace_path) = &args.run.standalone_outputs.trace_file {
Expand Down
7 changes: 7 additions & 0 deletions crates/cairo-lang-casm/src/hints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,9 @@ pub enum ExternalHint {
/// Writes a run argument of number `index` to `dst` and on.
#[cfg_attr(feature = "parity-scale-codec", codec(index = 1))]
WriteRunParam { index: ResOperand, dst: CellRef },
/// Writes a marker into the VM. Useful for debugging.
#[cfg_attr(feature = "parity-scale-codec", codec(index = 2))]
SetMarker { marker: ResOperand },
}

struct DerefOrImmediateFormatter<'a>(&'a DerefOrImmediate);
Expand Down Expand Up @@ -850,6 +853,10 @@ impl PythonicHint for ExternalHint {
let index = ResOperandAsIntegerFormatter(index);
format!(r#"raise NotImplementedError("memory{dst}.. = params[{index}])")"#)
}
Self::SetMarker { marker } => {
let marker = ResOperandAsAddressFormatter(marker);
format!(r#"raise NotImplementedError("marker = {}")"#, marker)
}
}
}
}
10 changes: 10 additions & 0 deletions crates/cairo-lang-executable/src/compile_test_data/basic
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ call rel 12;
jmp rel 5 if [ap + -3] != 0, ap++;
[ap + -1] = [ap + -2];
jmp rel 4;
%{ raise NotImplementedError("marker = memory[ap + -3]") %}
%{ raise NotImplementedError("marker = memory[ap + -2]") %}
[ap + -1] = [fp + -3] + 1;
[ap + -4] = [[fp + -3] + 0];
[ap + 0] = [ap + -1], ap++;
Expand Down Expand Up @@ -68,6 +70,8 @@ call rel 12;
jmp rel 5 if [ap + -3] != 0, ap++;
[ap + -1] = [ap + -2];
jmp rel 4;
%{ raise NotImplementedError("marker = memory[ap + -3]") %}
%{ raise NotImplementedError("marker = memory[ap + -2]") %}
[ap + -1] = [fp + -3] + 1;
[ap + -4] = [[fp + -3] + 0];
[ap + 0] = [ap + -1], ap++;
Expand Down Expand Up @@ -155,6 +159,8 @@ call rel 13;
jmp rel 5 if [ap + -3] != 0, ap++;
[ap + -1] = [ap + -2];
jmp rel 4;
%{ raise NotImplementedError("marker = memory[ap + -3]") %}
%{ raise NotImplementedError("marker = memory[ap + -2]") %}
[ap + -1] = [fp + -4] + 1;
[ap + -4] = [[fp + -4] + 0];
[ap + 0] = [ap + -1], ap++;
Expand Down Expand Up @@ -428,6 +434,8 @@ call rel 12;
jmp rel 5 if [ap + -3] != 0, ap++;
[ap + -1] = [ap + -2];
jmp rel 4;
%{ raise NotImplementedError("marker = memory[ap + -3]") %}
%{ raise NotImplementedError("marker = memory[ap + -2]") %}
[ap + -1] = [fp + -3] + 1;
[ap + -4] = [[fp + -3] + 0];
[ap + 0] = [ap + -1], ap++;
Expand Down Expand Up @@ -490,6 +498,8 @@ call rel 39;
jmp rel 5 if [ap + -3] != 0, ap++;
[ap + -1] = [ap + -2];
jmp rel 4;
%{ raise NotImplementedError("marker = memory[ap + -3]") %}
%{ raise NotImplementedError("marker = memory[ap + -2]") %}
[ap + -1] = [fp + -4] + 1;
[ap + -4] = [[fp + -4] + 0];
[fp + 0] = [ap + -7];
Expand Down
41 changes: 21 additions & 20 deletions crates/cairo-lang-runnable-utils/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,34 +419,40 @@ pub fn create_entry_code_from_params(
}
casm_build_extend! (ctx, let () = call FUNCTION;);
let mut unprocessed_return_size = return_types.iter().map(|(_, size)| size).sum::<i16>();
let mut next_unprocessed_deref = || {
let ret = CellExpression::Deref(deref!([ap - unprocessed_return_size]));
unprocessed_return_size -= 1;
ret
};
let mut return_data = vec![];
for (ret_ty, size) in return_types {
if let Some(name) = builtin_ty_to_vm_name.get(ret_ty) {
*builtin_vars.get_mut(name).unwrap() =
ctx.add_var(CellExpression::Deref(deref!([ap - unprocessed_return_size])));
unprocessed_return_size -= 1;
*builtin_vars.get_mut(name).unwrap() = ctx.add_var(next_unprocessed_deref());
} else if config.outputting_function {
if ret_ty == &GasBuiltinType::ID {
unprocessed_return_size -= 1;
next_unprocessed_deref();
continue;
}
let output_ptr_var = builtin_vars[&BuiltinName::output];
// The output builtin values.
let new_output_ptr = if *size == 3 {
let panic_indicator =
ctx.add_var(CellExpression::Deref(deref!([ap - unprocessed_return_size])));
unprocessed_return_size -= 2;
// The output ptr in the case of successful run.
let output_ptr_end =
ctx.add_var(CellExpression::Deref(deref!([ap - unprocessed_return_size])));
unprocessed_return_size -= 1;
let panic_indicator = ctx.add_var(next_unprocessed_deref());
// The start ptr of the output in the case of successful run,
// or the panic data in case of a failure.
let ptr_start = ctx.add_var(next_unprocessed_deref());
// The end ptr of the output in the case of successful run,
// or the panic data in case of a failure.
let ptr_end = ctx.add_var(next_unprocessed_deref());
casm_build_extend! {ctx,
tempvar new_output_ptr;
jump PANIC if panic_indicator != 0;
// SUCCESS:
assert new_output_ptr = output_ptr_end;
assert new_output_ptr = ptr_end;
jump AFTER_PANIC_HANDLING;
PANIC:
// Marking the panic message in case of a panic.
hint ExternalHint::SetMarker { marker: ptr_start };
hint ExternalHint::SetMarker { marker: ptr_end };
const one = 1;
// In the case of an error, we assume no values are written to the output_ptr.
assert new_output_ptr = output_ptr_var + one;
Expand All @@ -456,10 +462,8 @@ pub fn create_entry_code_from_params(
new_output_ptr
} else if *size == 2 {
// No panic possible.
unprocessed_return_size -= 1;
let output_ptr_end =
ctx.add_var(CellExpression::Deref(deref!([ap - unprocessed_return_size])));
unprocessed_return_size -= 1;
next_unprocessed_deref();
let output_ptr_end = ctx.add_var(next_unprocessed_deref());
casm_build_extend! {ctx,
const czero = 0;
tempvar zero = czero;
Expand All @@ -472,10 +476,7 @@ pub fn create_entry_code_from_params(
*builtin_vars.get_mut(&BuiltinName::output).unwrap() = new_output_ptr;
} else {
for _ in 0..*size {
return_data.push(
ctx.add_var(CellExpression::Deref(deref!([ap - unprocessed_return_size]))),
);
unprocessed_return_size -= 1;
return_data.push(ctx.add_var(next_unprocessed_deref()));
}
}
}
Expand Down
25 changes: 21 additions & 4 deletions crates/cairo-lang-runner/src/casm_run/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ pub struct CairoHintProcessor<'a> {
pub syscalls_used_resources: StarknetExecutionResources,
/// Avoid allocating memory segments so finalization of segment arena may not occur.
pub no_temporary_segments: bool,
/// A set of markers created by the run.
pub markers: Vec<Relocatable>,
}

pub fn cell_ref_to_relocatable(cell_ref: &CellRef, vm: &VirtualMachine) -> Relocatable {
Expand Down Expand Up @@ -1306,15 +1308,15 @@ impl CairoHintProcessor<'_> {

/// Executes an external hint.
fn execute_external_hint(
&self,
&mut self,
vm: &mut VirtualMachine,
core_hint: &ExternalHint,
) -> Result<(), HintError> {
match core_hint {
ExternalHint::AddRelocationRule { src, dst } => Ok(vm.add_relocation_rule(
ExternalHint::AddRelocationRule { src, dst } => vm.add_relocation_rule(
extract_relocatable(vm, src)?,
extract_relocatable(vm, dst)?,
)?),
)?,
ExternalHint::WriteRunParam { index, dst } => {
let index = get_val(vm, index)?.to_usize().expect("Got a bad index.");
let mut stack = vec![(cell_ref_to_relocatable(dst, vm), &self.user_args[index])];
Expand All @@ -1336,9 +1338,12 @@ impl CairoHintProcessor<'_> {
}
}
}
Ok(())
}
ExternalHint::SetMarker { marker } => {
self.markers.push(extract_relocatable(vm, marker)?);
},
}
Ok(())
}
}

Expand Down Expand Up @@ -2378,6 +2383,18 @@ where
Some(FormattedItem { item: format_short_string(&first_felt), is_string: false })
}

/// Formats the given felts as a panic string.
pub fn format_for_panic<T>(mut felts: T) -> String
where T : Iterator<Item = Felt252> + Clone {
let mut items = Vec::new();
while let Some(item) = format_next_item(&mut felts) {
items.push(item.quote_if_string());
}
let panic_values_string =
if let [item] = &items[..] { item.clone() } else { format!("({})", items.join(", ")) };
format!("Panicked with {panic_values_string}.")
}

/// Formats a `Felt252`, as a short string if possible.
fn format_short_string(value: &Felt252) -> String {
let hex_value = value.to_biguint();
Expand Down
2 changes: 2 additions & 0 deletions crates/cairo-lang-runner/src/casm_run/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ fn test_runner(function: CasmContext, n_returns: usize, expected: &[i128]) {
run_resources: RunResources::default(),
syscalls_used_resources: Default::default(),
no_temporary_segments: true,
markers: Default::default(),
};

let RunFunctionResult { ap, memory, .. } =
Expand Down Expand Up @@ -159,6 +160,7 @@ fn test_allocate_segment() {
run_resources: RunResources::default(),
syscalls_used_resources: Default::default(),
no_temporary_segments: true,
markers: Default::default(),
};

let RunFunctionResult { ap, memory, .. } =
Expand Down
1 change: 1 addition & 0 deletions crates/cairo-lang-runner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ impl SierraCasmRunner {
run_resources: RunResources::default(),
syscalls_used_resources: Default::default(),
no_temporary_segments: true,
markers: Default::default(),
};
let RunResult { gas_counter, memory, value, used_resources, profiling_info } = self
.run_function(
Expand Down
14 changes: 1 addition & 13 deletions crates/cairo-lang-test-runner/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use std::path::Path;
use std::sync::Mutex;
use std::vec::IntoIter;

use anyhow::{Context, Result, bail};
use cairo_lang_compiler::db::RootDatabase;
use cairo_lang_compiler::diagnostics::DiagnosticsReporter;
use cairo_lang_compiler::project::setup_project;
use cairo_lang_filesystem::cfg::{Cfg, CfgSet};
use cairo_lang_filesystem::ids::CrateId;
use cairo_lang_runner::casm_run::format_next_item;
use cairo_lang_runner::casm_run::format_for_panic;
use cairo_lang_runner::profiling::{
ProfilingInfo, ProfilingInfoProcessor, ProfilingInfoProcessorParams,
};
Expand Down Expand Up @@ -165,17 +164,6 @@ impl CompiledTestRunner {
}
}

/// Formats the given felts as a panic string.
fn format_for_panic(mut felts: IntoIter<Felt252>) -> String {
let mut items = Vec::new();
while let Some(item) = format_next_item(&mut felts) {
items.push(item.quote_if_string());
}
let panic_values_string =
if let [item] = &items[..] { item.clone() } else { format!("({})", items.join(", ")) };
format!("Panicked with {panic_values_string}.")
}

/// Whether to run the profiler, and what results to produce.
///
/// With `None`, don't run the profiler.
Expand Down
3 changes: 2 additions & 1 deletion crates/cairo-lang-test-runner/src/test.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use cairo_lang_runner::casm_run::format_for_panic;
use cairo_lang_sierra::program::{Program, ProgramArtifact};
use cairo_lang_test_plugin::test_config::TestExpectation;
use cairo_lang_test_plugin::{TestCompilationMetadata, TestConfig, TestsCompilationConfig};
use cairo_lang_utils::byte_array::BYTE_ARRAY_MAGIC;
use itertools::Itertools;
use starknet_types_core::felt::Felt as Felt252;

use crate::{TestCompilation, TestCompiler, filter_test_cases, format_for_panic};
use crate::{TestCompilation, TestCompiler, filter_test_cases};

#[test]
fn test_compiled_serialization() {
Expand Down

0 comments on commit cb43895

Please sign in to comment.