naga/compact/
functions.rs
1use super::arena::HandleSet;
2use super::{FunctionMap, ModuleMap};
3
4pub struct FunctionTracer<'a> {
5 pub function: &'a crate::Function,
6 pub constants: &'a crate::Arena<crate::Constant>,
7 pub overrides: &'a crate::Arena<crate::Override>,
8
9 pub functions_pending: &'a mut HandleSet<crate::Function>,
10 pub functions_used: &'a mut HandleSet<crate::Function>,
11 pub types_used: &'a mut HandleSet<crate::Type>,
12 pub global_variables_used: &'a mut HandleSet<crate::GlobalVariable>,
13 pub constants_used: &'a mut HandleSet<crate::Constant>,
14 pub overrides_used: &'a mut HandleSet<crate::Override>,
15 pub global_expressions_used: &'a mut HandleSet<crate::Expression>,
16
17 pub expressions_used: HandleSet<crate::Expression>,
19}
20
21impl FunctionTracer<'_> {
22 pub fn trace_call(&mut self, function: crate::Handle<crate::Function>) {
23 if !self.functions_used.contains(function) {
24 self.functions_used.insert(function);
25 self.functions_pending.insert(function);
26 }
27 }
28
29 pub fn trace(&mut self) {
30 for argument in self.function.arguments.iter() {
31 self.types_used.insert(argument.ty);
32 }
33
34 if let Some(ref result) = self.function.result {
35 self.types_used.insert(result.ty);
36 }
37
38 for (_, local) in self.function.local_variables.iter() {
39 self.types_used.insert(local.ty);
40 if let Some(init) = local.init {
41 self.expressions_used.insert(init);
42 }
43 }
44
45 for (&value, _name) in &self.function.named_expressions {
48 self.expressions_used.insert(value);
49 }
50
51 self.trace_block(&self.function.body);
52
53 self.as_expression().trace_expressions();
57 }
58
59 fn as_expression(&mut self) -> super::expressions::ExpressionTracer<'_> {
60 super::expressions::ExpressionTracer {
61 constants: self.constants,
62 overrides: self.overrides,
63 expressions: &self.function.expressions,
64
65 types_used: self.types_used,
66 global_variables_used: self.global_variables_used,
67 constants_used: self.constants_used,
68 overrides_used: self.overrides_used,
69 expressions_used: &mut self.expressions_used,
70 global_expressions_used: Some(&mut self.global_expressions_used),
71 }
72 }
73}
74
75impl FunctionMap {
76 pub fn compact(
77 &self,
78 function: &mut crate::Function,
79 module_map: &ModuleMap,
80 reuse: &mut crate::NamedExpressions,
81 ) {
82 assert!(reuse.is_empty());
83
84 for argument in function.arguments.iter_mut() {
85 module_map.types.adjust(&mut argument.ty);
86 }
87
88 if let Some(ref mut result) = function.result {
89 module_map.types.adjust(&mut result.ty);
90 }
91
92 for (_, local) in function.local_variables.iter_mut() {
93 log::trace!("adjusting local variable {:?}", local.name);
94 module_map.types.adjust(&mut local.ty);
95 if let Some(ref mut init) = local.init {
96 self.expressions.adjust(init);
97 }
98 }
99
100 function.expressions.retain_mut(|handle, expr| {
102 if self.expressions.used(handle) {
103 module_map.adjust_expression(expr, &self.expressions);
104 true
105 } else {
106 false
107 }
108 });
109
110 for (mut handle, name) in function.named_expressions.drain(..) {
112 self.expressions.adjust(&mut handle);
113 reuse.insert(handle, name);
114 }
115 core::mem::swap(&mut function.named_expressions, reuse);
116 assert!(reuse.is_empty());
117
118 self.adjust_body(function, &module_map.functions);
120 }
121}