spirt/passes/
legalize.rs

1use crate::visit::{InnerVisit, Visitor};
2use crate::{
3    AttrSet, Const, Context, DataInstForm, DeclDef, Func, FxIndexSet, GlobalVar, Module, Type, cfg,
4};
5
6/// Apply the [`cfg::Structurizer`] algorithm to all function definitions in `module`.
7pub fn structurize_func_cfgs(module: &mut Module) {
8    let cx = &module.cx();
9
10    // FIXME(eddyb) reuse this collection work in some kind of "pass manager".
11    let mut collector = ReachableUseCollector {
12        cx,
13        module,
14
15        seen_types: FxIndexSet::default(),
16        seen_consts: FxIndexSet::default(),
17        seen_data_inst_forms: FxIndexSet::default(),
18        seen_global_vars: FxIndexSet::default(),
19        seen_funcs: FxIndexSet::default(),
20    };
21    for (export_key, &exportee) in &module.exports {
22        export_key.inner_visit_with(&mut collector);
23        exportee.inner_visit_with(&mut collector);
24    }
25
26    for &func in &collector.seen_funcs {
27        if let DeclDef::Present(func_def_body) = &mut module.funcs[func].def {
28            cfg::Structurizer::new(cx, func_def_body).structurize_func();
29        }
30    }
31}
32
33struct ReachableUseCollector<'a> {
34    cx: &'a Context,
35    module: &'a Module,
36
37    // FIXME(eddyb) build some automation to avoid ever repeating these.
38    seen_types: FxIndexSet<Type>,
39    seen_consts: FxIndexSet<Const>,
40    seen_data_inst_forms: FxIndexSet<DataInstForm>,
41    seen_global_vars: FxIndexSet<GlobalVar>,
42    seen_funcs: FxIndexSet<Func>,
43}
44
45impl Visitor<'_> for ReachableUseCollector<'_> {
46    // FIXME(eddyb) build some automation to avoid ever repeating these.
47    fn visit_attr_set_use(&mut self, _attrs: AttrSet) {
48        // FIXME(eddyb) if `AttrSet`s are ignored, why not `Type`s too?
49    }
50    fn visit_type_use(&mut self, ty: Type) {
51        if self.seen_types.insert(ty) {
52            self.visit_type_def(&self.cx[ty]);
53        }
54    }
55    fn visit_const_use(&mut self, ct: Const) {
56        if self.seen_consts.insert(ct) {
57            self.visit_const_def(&self.cx[ct]);
58        }
59    }
60    fn visit_data_inst_form_use(&mut self, data_inst_form: DataInstForm) {
61        if self.seen_data_inst_forms.insert(data_inst_form) {
62            self.visit_data_inst_form_def(&self.cx[data_inst_form]);
63        }
64    }
65
66    fn visit_global_var_use(&mut self, gv: GlobalVar) {
67        if self.seen_global_vars.insert(gv) {
68            self.visit_global_var_decl(&self.module.global_vars[gv]);
69        }
70    }
71    fn visit_func_use(&mut self, func: Func) {
72        if self.seen_funcs.insert(func) {
73            self.visit_func_decl(&self.module.funcs[func]);
74        }
75    }
76}