Skip to main content

luaur_analysis/methods/
data_flow_graph_builder_join_props.rs

1use crate::records::data_flow_graph_builder::DataFlowGraphBuilder;
2use crate::records::def::Def;
3use crate::records::dfg_scope::DfgScope;
4use crate::type_aliases::def_id_def::DefId;
5use alloc::collections::BTreeMap;
6use alloc::string::String;
7
8impl DataFlowGraphBuilder {
9    /// `void DataFlowGraphBuilder::joinProps(DfgScope* result, const DfgScope& a, const DfgScope& b)`.
10    /// Reference: `DataFlowGraph.cpp:246-294`.
11    pub fn join_props(&mut self, result: *mut DfgScope, a: &DfgScope, b: &DfgScope) {
12        let def_arena = self.def_arena;
13        // C++ lambda `phinodify`: merges per-key defs of `a`/`b` into `scope->props[parent]`.
14        let phinodify = |scope: *mut DfgScope,
15                         a_props: &BTreeMap<String, *const Def>,
16                         b_props: &BTreeMap<String, *const Def>,
17                         parent: DefId| unsafe {
18            let p: &mut BTreeMap<String, *const Def> = (*scope).props.get_or_insert(parent);
19            for (k, def_a) in a_props.iter() {
20                if let Some(it) = b_props.get(k) {
21                    p.insert(k.clone(), (*def_arena).phi_def_id_def_id(*it, *def_a));
22                } else if let Some(it) = p.get(k).copied() {
23                    p.insert(k.clone(), (*def_arena).phi_def_id_def_id(it, *def_a));
24                } else if let Some(def2) = (*scope).lookup_def_id_string(parent, k) {
25                    p.insert(k.clone(), (*def_arena).phi_def_id_def_id(def2, *def_a));
26                } else {
27                    p.insert(k.clone(), *def_a);
28                }
29            }
30
31            for (k, def_b) in b_props.iter() {
32                if a_props.get(k).is_some() {
33                    continue;
34                } else if let Some(it) = p.get(k).copied() {
35                    p.insert(k.clone(), (*def_arena).phi_def_id_def_id(it, *def_b));
36                } else if let Some(def2) = (*scope).lookup_def_id_string(parent, k) {
37                    p.insert(k.clone(), (*def_arena).phi_def_id_def_id(def2, *def_b));
38                } else {
39                    p.insert(k.clone(), *def_b);
40                }
41            }
42        };
43
44        unsafe {
45            for (def, a1) in a.props.iter() {
46                (*result).props.try_insert(*def, BTreeMap::new());
47                if let Some(a2) = b.props.find(def) {
48                    let a2 = a2.clone();
49                    phinodify(result, a1, &a2, *def);
50                } else if let Some(a2) = (*result).props.find(def) {
51                    let a2 = a2.clone();
52                    phinodify(result, a1, &a2, *def);
53                }
54            }
55
56            for (def, a1) in b.props.iter() {
57                (*result).props.try_insert(*def, BTreeMap::new());
58                if a.props.find(def).is_some() {
59                    continue;
60                } else if let Some(a2) = (*result).props.find(def) {
61                    let a2 = a2.clone();
62                    phinodify(result, a1, &a2, *def);
63                }
64            }
65        }
66    }
67}