sway_ir/analysis/
call_graph.rs1use crate::{Context, Function, InstOp, Instruction, ValueDatum};
5
6use indexmap::IndexSet;
7use sway_types::{FxIndexMap, FxIndexSet};
8
9pub type CallGraph = FxIndexMap<Function, FxIndexSet<Function>>;
10
11pub fn build_call_graph(ctx: &Context, functions: &[Function]) -> CallGraph {
13 let mut res = CallGraph::default();
14 for function in functions {
15 let entry = res.entry(*function);
16 let entry = entry.or_insert_with(IndexSet::default);
17 for (_, inst) in function.instruction_iter(ctx) {
18 if let ValueDatum::Instruction(Instruction {
19 op: InstOp::Call(callee, _),
20 ..
21 }) = ctx.values[inst.0].value
22 {
23 entry.insert(callee);
24 }
25 }
26 }
27 res
28}
29
30pub fn callee_first_order(cg: &CallGraph) -> Vec<Function> {
34 let mut res = Vec::new();
35
36 let mut visited = FxIndexSet::<Function>::default();
37 fn post_order_visitor(
38 cg: &CallGraph,
39 visited: &mut FxIndexSet<Function>,
40 res: &mut Vec<Function>,
41 node: Function,
42 ) {
43 if visited.contains(&node) {
44 return;
45 }
46 visited.insert(node);
47 for callee in &cg[&node] {
48 post_order_visitor(cg, visited, res, *callee);
49 }
50 res.push(node);
51 }
52 for node in cg.keys() {
53 post_order_visitor(cg, &mut visited, &mut res, *node);
54 }
55
56 res
57}