Skip to content

Commit

Permalink
Add statements->functions map to SierraDebugInfo (#5325)
Browse files Browse the repository at this point in the history
  • Loading branch information
piotmag769 authored Mar 27, 2024
1 parent f362614 commit babbb5a
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 18 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/bin/cairo-run/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ fn main() -> anyhow::Result<()> {
let profiling_info_processor = ProfilingInfoProcessor::new(
Some(db),
sierra_program,
debug_info.statements_locations.get_statements_functions_map(db),
debug_info.statements_locations.get_statements_functions_map_for_tests(db),
);
match result.profiling_info {
Some(raw_profiling_info) => {
Expand Down
14 changes: 4 additions & 10 deletions crates/cairo-lang-compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod diagnostics;
pub mod project;

/// Configuration for the compiler.
#[derive(Default)]
pub struct CompilerConfig<'c> {
pub diagnostics_reporter: DiagnosticsReporter<'c>,

Expand All @@ -31,17 +32,10 @@ pub struct CompilerConfig<'c> {
/// The name of the allowed libfuncs list to use in compilation.
/// If None the default list of audited libfuncs will be used.
pub allowed_libfuncs_list_name: Option<String>,
}

/// The default compiler configuration.
impl Default for CompilerConfig<'static> {
fn default() -> Self {
CompilerConfig {
diagnostics_reporter: DiagnosticsReporter::default(),
replace_ids: false,
allowed_libfuncs_list_name: None,
}
}
/// Adds mapping used by [cairo-profiler](https://github.com/software-mansion/cairo-profiler) to
/// [cairo_lang_sierra::debug_info::Annotations] in [cairo_lang_sierra::debug_info::DebugInfo].
pub add_statements_functions: bool,
}

/// Compiles a Cairo project at the given path.
Expand Down
3 changes: 2 additions & 1 deletion crates/cairo-lang-runner/src/profiling_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ pub fn test_profiling(
let SierraProgramWithDebug { program: sierra_program, debug_info } =
Arc::unwrap_or_clone(db.get_sierra_program(vec![test_module.crate_id]).unwrap());
let sierra_program = replace_sierra_ids_in_program(&db, &sierra_program);
let statements_functions = debug_info.statements_locations.get_statements_functions_map(&db);
let statements_functions =
debug_info.statements_locations.get_statements_functions_map_for_tests(&db);
let runner = SierraCasmRunner::new(
sierra_program.clone(),
Some(Default::default()),
Expand Down
2 changes: 2 additions & 0 deletions crates/cairo-lang-sierra-generator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ itertools = { workspace = true, default-features = true }
num-traits = { workspace = true }
once_cell.workspace = true
salsa.workspace = true
serde.workspace = true
serde_json.workspace = true
smol_str.workspace = true

[dev-dependencies]
Expand Down
1 change: 1 addition & 0 deletions crates/cairo-lang-sierra-generator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod program_generator;
pub mod replace_ids;
mod resolve_labels;
mod specialization_context;
pub mod statements_functions;
pub mod statements_locations;
mod store_variables;
#[cfg(any(feature = "testing", test))]
Expand Down
24 changes: 24 additions & 0 deletions crates/cairo-lang-sierra-generator/src/statements_functions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use std::collections::HashMap;

use cairo_lang_sierra::debug_info::Annotations;
use cairo_lang_sierra::program::StatementIdx;
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use serde::{Deserialize, Serialize};

/// The mapping from sierra statement index to fully qualified Cairo path of the Cairo function
/// (if obtainable) which caused the statement to be generated. Should be created using
/// [`crate::statements_locations::StatementsLocations::extract_statements_functions`].
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct StatementsFunctions {
pub statements_to_functions_map: HashMap<StatementIdx, Option<String>>,
}

impl From<StatementsFunctions> for Annotations {
fn from(value: StatementsFunctions) -> Self {
let mapping = serde_json::to_value(value.statements_to_functions_map).unwrap();
OrderedHashMap::from([(
"github.com/software-mansion/cairo-profiler".to_string(),
serde_json::Value::from_iter([("statements_functions", mapping)]),
)])
}
}
20 changes: 17 additions & 3 deletions crates/cairo-lang-sierra-generator/src/statements_locations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use cairo_lang_syntax::node::{Terminal, TypedSyntaxNode};
use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
use itertools::Itertools;

use crate::statements_functions::StatementsFunctions;

#[cfg(test)]
#[path = "statements_locations_test.rs"]
mod test;
Expand Down Expand Up @@ -138,14 +140,26 @@ impl StatementsLocations {
Self { locations }
}
/// Builds a map between each Sierra statement index and a string representation of the Cairo
/// function that it was generated from. The function representation is composed of the function
/// name and the path (modules and impls) to the function in the file. It is used for places
/// function that it was generated from. It is used for places
/// without db access such as the profiler.
// TODO(Gil): Add a db access to the profiler and remove this function.
pub fn get_statements_functions_map(
pub fn get_statements_functions_map_for_tests(
&self,
db: &dyn DefsGroup,
) -> UnorderedHashMap<StatementIdx, String> {
self.locations.map(|s| containing_function_identifier_for_tests(db, *s))
}

/// Creates a new [StatementsFunctions] struct using [StatementsLocations] and [DefsGroup].
pub fn extract_statements_functions(&self, db: &dyn DefsGroup) -> StatementsFunctions {
StatementsFunctions {
statements_to_functions_map: self
.locations
.iter_sorted()
.map(|(statement_idx, stable_location)| {
(*statement_idx, containing_function_identifier(db, *stable_location))
})
.collect(),
}
}
}
8 changes: 7 additions & 1 deletion crates/cairo-lang-starknet-classes/src/contract_class.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use cairo_lang_sierra as sierra;
use cairo_lang_utils::bigint::{deserialize_big_uint, serialize_big_uint, BigUintAsHex};
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use num_bigint::BigUint;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use thiserror::Error;

use crate::abi::Contract;
Expand Down Expand Up @@ -36,14 +38,18 @@ impl ContractClass {
program: &sierra::program::Program,
entry_points_by_type: ContractEntryPoints,
abi: Option<Contract>,
annotations: OrderedHashMap<String, Value>,
) -> Result<Self, Felt252SerdeError> {
let mut sierra_program_debug_info = sierra::debug_info::DebugInfo::extract(program);
sierra_program_debug_info.annotations.extend(annotations);

Ok(Self {
sierra_program: sierra_to_felt252s(
current_sierra_version_id(),
current_compiler_version_id(),
program,
)?,
sierra_program_debug_info: Some(sierra::debug_info::DebugInfo::extract(program)),
sierra_program_debug_info: Some(sierra_program_debug_info),
contract_class_version: DEFAULT_CONTRACT_CLASS_VERSION.into(),
entry_points_by_type,
abi,
Expand Down
12 changes: 11 additions & 1 deletion crates/cairo-lang-starknet/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use cairo_lang_diagnostics::ToOption;
use cairo_lang_filesystem::ids::CrateId;
use cairo_lang_lowering::db::LoweringGroup;
use cairo_lang_lowering::ids::ConcreteFunctionWithBodyId;
use cairo_lang_sierra::debug_info::Annotations;
use cairo_lang_sierra_generator::canonical_id_replacer::CanonicalReplacer;
use cairo_lang_sierra_generator::db::SierraGenGroup;
use cairo_lang_sierra_generator::program_generator::SierraProgramWithDebug;
Expand Down Expand Up @@ -126,7 +127,7 @@ fn compile_contract_with_prepared_and_checked_db(
) -> Result<ContractClass> {
let SemanticEntryPoints { external, l1_handler, constructor } =
extract_semantic_entrypoints(db, contract)?;
let SierraProgramWithDebug { program: mut sierra_program, .. } = Arc::unwrap_or_clone(
let SierraProgramWithDebug { program: mut sierra_program, debug_info } = Arc::unwrap_or_clone(
db.get_sierra_program_for_functions(
chain!(&external, &l1_handler, &constructor).map(|f| f.value).collect(),
)
Expand All @@ -146,6 +147,14 @@ fn compile_contract_with_prepared_and_checked_db(
// Later generation of ABI verifies that there is up to one constructor.
constructor: get_entry_points(db, &constructor, &replacer)?,
};

let annotations = if compiler_config.add_statements_functions {
let statements_functions = debug_info.statements_locations.extract_statements_functions(db);
Annotations::from(statements_functions)
} else {
Default::default()
};

let contract_class = ContractClass::new(
&sierra_program,
entry_points_by_type,
Expand All @@ -156,6 +165,7 @@ fn compile_contract_with_prepared_and_checked_db(
.finalize()
.with_context(|| "Could not create ABI from contract submodule")?,
),
annotations,
)?;
contract_class.sanity_check();
Ok(contract_class)
Expand Down
1 change: 1 addition & 0 deletions crates/cairo-lang-starknet/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub fn get_test_contract(example_file_name: &str) -> ContractClass {
replace_ids: true,
allowed_libfuncs_list_name: Some(BUILTIN_ALL_LIBFUNCS_LIST.to_string()),
diagnostics_reporter,
add_statements_functions: false,
},
)
.expect("compile_path failed")
Expand Down
3 changes: 2 additions & 1 deletion crates/cairo-lang-test-plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ pub fn compile_test_prepared_db(
);
let replacer = DebugReplacer { db };
let sierra_program = replacer.apply(&sierra_program);
let statements_functions = debug_info.statements_locations.get_statements_functions_map(db);
let statements_functions =
debug_info.statements_locations.get_statements_functions_map_for_tests(db);

let named_tests = all_tests
.into_iter()
Expand Down

0 comments on commit babbb5a

Please sign in to comment.