cairo_lang_lowering/graph_algorithms/
feedback_set.rs

1use cairo_lang_diagnostics::Maybe;
2use cairo_lang_filesystem::db::FilesGroup;
3use cairo_lang_filesystem::flag::Flag;
4use cairo_lang_filesystem::ids::{FlagId, FlagLongId};
5use cairo_lang_utils::graph_algos::feedback_set::calc_feedback_set;
6use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
7use salsa::Database;
8
9use super::concrete_function_node::ConcreteFunctionWithBodyNode;
10use crate::db::LoweringGroup;
11use crate::ids::ConcreteFunctionWithBodyId;
12use crate::{DependencyType, LoweringStage};
13
14/// Query implementation of [crate::db::LoweringGroup::function_with_body_feedback_set].
15#[salsa::tracked(returns(ref))]
16pub fn function_with_body_feedback_set<'db>(
17    db: &'db dyn Database,
18    function: ConcreteFunctionWithBodyId<'db>,
19    stage: LoweringStage,
20) -> Maybe<OrderedHashSet<ConcreteFunctionWithBodyId<'db>>> {
21    let r = db.lowered_scc_representative(function, DependencyType::Cost, stage);
22    function_with_body_feedback_set_of_representative(db, r.0, stage)
23}
24
25/// Returns the value of the `add_withdraw_gas` flag, or `true` if the flag is not set.
26pub fn flag_add_withdraw_gas(db: &dyn Database) -> bool {
27    db.get_flag(FlagId::new(db, FlagLongId("add_withdraw_gas".into())))
28        .map(|flag| *flag == Flag::AddWithdrawGas(true))
29        .unwrap_or(true)
30}
31
32/// Query implementation of [crate::db::LoweringGroup::needs_withdraw_gas].
33#[salsa::tracked]
34pub fn needs_withdraw_gas<'db>(
35    db: &'db dyn Database,
36    function: ConcreteFunctionWithBodyId<'db>,
37) -> Maybe<bool> {
38    Ok(flag_add_withdraw_gas(db)
39        && db
40            .function_with_body_feedback_set(function, LoweringStage::Monomorphized)?
41            .contains(&function))
42}
43
44/// Returns the feedback-vertex-set of the given concrete-function SCC-representative. A
45/// feedback-vertex-set is the set of vertices whose removal leaves a graph without cycles.
46#[salsa::tracked]
47fn function_with_body_feedback_set_of_representative<'db>(
48    db: &'db dyn Database,
49    function_id: ConcreteFunctionWithBodyId<'db>,
50    stage: LoweringStage,
51) -> Maybe<OrderedHashSet<ConcreteFunctionWithBodyId<'db>>> {
52    Ok(calc_feedback_set(
53        ConcreteFunctionWithBodyNode {
54            function_id,
55            db,
56            dependency_type: DependencyType::Cost,
57            stage,
58        }
59        .into(),
60    ))
61}