spirt/passes/
qptr.rs

1//! [`QPtr`](crate::TypeKind::QPtr) transforms.
2
3use crate::visit::{InnerVisit, Visitor};
4use crate::{AttrSet, Const, Context, Func, FxIndexSet, GlobalVar, Module, Type};
5use crate::{DataInstForm, qptr};
6
7pub fn lower_from_spv_ptrs(module: &mut Module, layout_config: &qptr::LayoutConfig) {
8    let cx = &module.cx();
9
10    let (seen_global_vars, seen_funcs) = {
11        // FIXME(eddyb) reuse this collection work in some kind of "pass manager".
12        let mut collector = ReachableUseCollector {
13            cx,
14            module,
15
16            seen_types: FxIndexSet::default(),
17            seen_consts: FxIndexSet::default(),
18            seen_data_inst_forms: FxIndexSet::default(),
19            seen_global_vars: FxIndexSet::default(),
20            seen_funcs: FxIndexSet::default(),
21        };
22        for (export_key, &exportee) in &module.exports {
23            export_key.inner_visit_with(&mut collector);
24            exportee.inner_visit_with(&mut collector);
25        }
26        (collector.seen_global_vars, collector.seen_funcs)
27    };
28
29    let lowerer = qptr::lower::LowerFromSpvPtrs::new(cx.clone(), layout_config);
30    for &global_var in &seen_global_vars {
31        lowerer.lower_global_var(&mut module.global_vars[global_var]);
32    }
33    for &func in &seen_funcs {
34        lowerer.lower_func(&mut module.funcs[func]);
35    }
36}
37
38pub fn analyze_uses(module: &mut Module, layout_config: &qptr::LayoutConfig) {
39    qptr::analyze::InferUsage::new(module.cx(), layout_config).infer_usage_in_module(module);
40}
41
42pub fn lift_to_spv_ptrs(module: &mut Module, layout_config: &qptr::LayoutConfig) {
43    let cx = &module.cx();
44
45    let (seen_global_vars, seen_funcs) = {
46        // FIXME(eddyb) reuse this collection work in some kind of "pass manager".
47        let mut collector = ReachableUseCollector {
48            cx,
49            module,
50
51            seen_types: FxIndexSet::default(),
52            seen_consts: FxIndexSet::default(),
53            seen_data_inst_forms: FxIndexSet::default(),
54            seen_global_vars: FxIndexSet::default(),
55            seen_funcs: FxIndexSet::default(),
56        };
57        for (export_key, &exportee) in &module.exports {
58            export_key.inner_visit_with(&mut collector);
59            exportee.inner_visit_with(&mut collector);
60        }
61        (collector.seen_global_vars, collector.seen_funcs)
62    };
63
64    let lifter = qptr::lift::LiftToSpvPtrs::new(cx.clone(), layout_config);
65    for &global_var in &seen_global_vars {
66        lifter.lift_global_var(&mut module.global_vars[global_var]);
67    }
68    lifter.lift_all_funcs(module, seen_funcs);
69}
70
71struct ReachableUseCollector<'a> {
72    cx: &'a Context,
73    module: &'a Module,
74
75    // FIXME(eddyb) build some automation to avoid ever repeating these.
76    seen_types: FxIndexSet<Type>,
77    seen_consts: FxIndexSet<Const>,
78    seen_data_inst_forms: FxIndexSet<DataInstForm>,
79    seen_global_vars: FxIndexSet<GlobalVar>,
80    seen_funcs: FxIndexSet<Func>,
81}
82
83impl Visitor<'_> for ReachableUseCollector<'_> {
84    // FIXME(eddyb) build some automation to avoid ever repeating these.
85    fn visit_attr_set_use(&mut self, _attrs: AttrSet) {
86        // FIXME(eddyb) if `AttrSet`s are ignored, why not `Type`s too?
87    }
88    fn visit_type_use(&mut self, ty: Type) {
89        if self.seen_types.insert(ty) {
90            self.visit_type_def(&self.cx[ty]);
91        }
92    }
93    fn visit_const_use(&mut self, ct: Const) {
94        if self.seen_consts.insert(ct) {
95            self.visit_const_def(&self.cx[ct]);
96        }
97    }
98    fn visit_data_inst_form_use(&mut self, data_inst_form: DataInstForm) {
99        if self.seen_data_inst_forms.insert(data_inst_form) {
100            self.visit_data_inst_form_def(&self.cx[data_inst_form]);
101        }
102    }
103
104    fn visit_global_var_use(&mut self, gv: GlobalVar) {
105        if self.seen_global_vars.insert(gv) {
106            self.visit_global_var_decl(&self.module.global_vars[gv]);
107        }
108    }
109    fn visit_func_use(&mut self, func: Func) {
110        if self.seen_funcs.insert(func) {
111            self.visit_func_decl(&self.module.funcs[func]);
112        }
113    }
114}